Skip to content

Commit c1b0988

Browse files
committed
mcp(fix[hierarchy]): Remove broad try/except, let FastMCP handle errors
why: Broad except Exception blocks caught all errors and returned them as content strings, hiding real errors from the MCP client. FastMCP natively converts unhandled exceptions to ResourceError. what: - Remove all 6 try/except Exception blocks from resource functions - Raise ValueError for not-found sessions/windows/panes - Remove unused logger import
1 parent 9313108 commit c1b0988

File tree

1 file changed

+47
-62
lines changed

1 file changed

+47
-62
lines changed

src/libtmux/mcp/resources/hierarchy.py

Lines changed: 47 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from __future__ import annotations
44

55
import json
6-
import logging
76
import typing as t
87

98
from libtmux.mcp._utils import (
@@ -16,8 +15,6 @@
1615
if t.TYPE_CHECKING:
1716
from fastmcp import FastMCP
1817

19-
logger = logging.getLogger(__name__)
20-
2118

2219
def register(mcp: FastMCP) -> None:
2320
"""Register hierarchy resources with the FastMCP instance."""
@@ -31,12 +28,9 @@ def get_sessions() -> str:
3128
str
3229
JSON array of session objects.
3330
"""
34-
try:
35-
server = _get_server()
36-
sessions = [_serialize_session(s) for s in server.sessions]
37-
return json.dumps(sessions, indent=2)
38-
except Exception as e:
39-
return json.dumps({"error": str(e)})
31+
server = _get_server()
32+
sessions = [_serialize_session(s) for s in server.sessions]
33+
return json.dumps(sessions, indent=2)
4034

4135
@mcp.resource("tmux://sessions/{session_name}")
4236
def get_session(session_name: str) -> str:
@@ -52,17 +46,15 @@ def get_session(session_name: str) -> str:
5246
str
5347
JSON object with session info and its windows.
5448
"""
55-
try:
56-
server = _get_server()
57-
session = server.sessions.get(session_name=session_name, default=None)
58-
if session is None:
59-
return json.dumps({"error": f"Session not found: {session_name}"})
60-
61-
result = _serialize_session(session)
62-
result["windows"] = [_serialize_window(w) for w in session.windows]
63-
return json.dumps(result, indent=2)
64-
except Exception as e:
65-
return json.dumps({"error": str(e)})
49+
server = _get_server()
50+
session = server.sessions.get(session_name=session_name, default=None)
51+
if session is None:
52+
msg = f"Session not found: {session_name}"
53+
raise ValueError(msg)
54+
55+
result = _serialize_session(session)
56+
result["windows"] = [_serialize_window(w) for w in session.windows]
57+
return json.dumps(result, indent=2)
6658

6759
@mcp.resource("tmux://sessions/{session_name}/windows")
6860
def get_session_windows(session_name: str) -> str:
@@ -78,16 +70,14 @@ def get_session_windows(session_name: str) -> str:
7870
str
7971
JSON array of window objects.
8072
"""
81-
try:
82-
server = _get_server()
83-
session = server.sessions.get(session_name=session_name, default=None)
84-
if session is None:
85-
return json.dumps({"error": f"Session not found: {session_name}"})
73+
server = _get_server()
74+
session = server.sessions.get(session_name=session_name, default=None)
75+
if session is None:
76+
msg = f"Session not found: {session_name}"
77+
raise ValueError(msg)
8678

87-
windows = [_serialize_window(w) for w in session.windows]
88-
return json.dumps(windows, indent=2)
89-
except Exception as e:
90-
return json.dumps({"error": str(e)})
79+
windows = [_serialize_window(w) for w in session.windows]
80+
return json.dumps(windows, indent=2)
9181

9282
@mcp.resource("tmux://sessions/{session_name}/windows/{window_index}")
9383
def get_window(session_name: str, window_index: str) -> str:
@@ -105,21 +95,20 @@ def get_window(session_name: str, window_index: str) -> str:
10595
str
10696
JSON object with window info and its panes.
10797
"""
108-
try:
109-
server = _get_server()
110-
session = server.sessions.get(session_name=session_name, default=None)
111-
if session is None:
112-
return json.dumps({"error": f"Session not found: {session_name}"})
113-
114-
window = session.windows.get(window_index=window_index, default=None)
115-
if window is None:
116-
return json.dumps({"error": f"Window not found: index {window_index}"})
117-
118-
result = _serialize_window(window)
119-
result["panes"] = [_serialize_pane(p) for p in window.panes]
120-
return json.dumps(result, indent=2)
121-
except Exception as e:
122-
return json.dumps({"error": str(e)})
98+
server = _get_server()
99+
session = server.sessions.get(session_name=session_name, default=None)
100+
if session is None:
101+
msg = f"Session not found: {session_name}"
102+
raise ValueError(msg)
103+
104+
window = session.windows.get(window_index=window_index, default=None)
105+
if window is None:
106+
msg = f"Window not found: index {window_index}"
107+
raise ValueError(msg)
108+
109+
result = _serialize_window(window)
110+
result["panes"] = [_serialize_pane(p) for p in window.panes]
111+
return json.dumps(result, indent=2)
123112

124113
@mcp.resource("tmux://panes/{pane_id}")
125114
def get_pane(pane_id: str) -> str:
@@ -135,15 +124,13 @@ def get_pane(pane_id: str) -> str:
135124
str
136125
JSON object of pane details.
137126
"""
138-
try:
139-
server = _get_server()
140-
pane = server.panes.get(pane_id=pane_id, default=None)
141-
if pane is None:
142-
return json.dumps({"error": f"Pane not found: {pane_id}"})
127+
server = _get_server()
128+
pane = server.panes.get(pane_id=pane_id, default=None)
129+
if pane is None:
130+
msg = f"Pane not found: {pane_id}"
131+
raise ValueError(msg)
143132

144-
return json.dumps(_serialize_pane(pane), indent=2)
145-
except Exception as e:
146-
return json.dumps({"error": str(e)})
133+
return json.dumps(_serialize_pane(pane), indent=2)
147134

148135
@mcp.resource("tmux://panes/{pane_id}/content")
149136
def get_pane_content(pane_id: str) -> str:
@@ -159,13 +146,11 @@ def get_pane_content(pane_id: str) -> str:
159146
str
160147
Plain text captured pane content.
161148
"""
162-
try:
163-
server = _get_server()
164-
pane = server.panes.get(pane_id=pane_id, default=None)
165-
if pane is None:
166-
return f"Error: Pane not found: {pane_id}"
167-
168-
lines = pane.capture_pane()
169-
return "\n".join(lines)
170-
except Exception as e:
171-
return f"Error: {e}"
149+
server = _get_server()
150+
pane = server.panes.get(pane_id=pane_id, default=None)
151+
if pane is None:
152+
msg = f"Pane not found: {pane_id}"
153+
raise ValueError(msg)
154+
155+
lines = pane.capture_pane()
156+
return "\n".join(lines)

0 commit comments

Comments
 (0)