Skip to content

Commit 2e68793

Browse files
committed
feat: update mcp server status
1 parent 08df052 commit 2e68793

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

agent-chat-cli.config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mcp_servers:
2424
description: "Browser automation and debugging capabilities for AI agents"
2525
command: "npx"
2626
args:
27-
- "chrome-devtools-mcp@latest"
27+
- "chrome-devtools-mcpp@latest"
2828
disallowed_tools: []
2929
enabled: true
3030

src/agent_chat_cli/components/header.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from agent_chat_cli.components.spacer import Spacer
66
from agent_chat_cli.utils.config import load_config
7+
from agent_chat_cli.utils.mcp_server_status import MCPServerStatus
78

89

910
class Header(Widget):
@@ -18,7 +19,8 @@ def compose(self) -> ComposeResult:
1819
)
1920

2021
yield Label(
21-
f"[dim]Available MCP Servers:[/dim] {mcp_servers}",
22+
f"[dim]Available MCP Servers: {mcp_servers}[/dim]",
23+
id="header-mcp-servers",
2224
)
2325

2426
if agents:
@@ -35,3 +37,29 @@ def compose(self) -> ComposeResult:
3537
id="header-instructions",
3638
classes="header-instructions",
3739
)
40+
41+
def on_mount(self) -> None:
42+
MCPServerStatus.subscribe(self._handle_mcp_server_status)
43+
44+
def on_unmount(self) -> None:
45+
MCPServerStatus.unsubscribe(self._handle_mcp_server_status)
46+
47+
def _handle_mcp_server_status(self) -> None:
48+
config = load_config()
49+
server_names = list(config.mcp_servers.keys())
50+
51+
server_parts = []
52+
for name in server_names:
53+
is_connected = MCPServerStatus.is_connected(name)
54+
55+
if is_connected:
56+
server_parts.append(f"{name}")
57+
else:
58+
# Error connecting to MCP
59+
server_parts.append(f"[#ffa2dc][strike]{name}[/strike][/]")
60+
61+
mcp_servers = ", ".join(server_parts)
62+
markup = f"[dim]Available MCP Servers:[/dim] {mcp_servers}"
63+
64+
label = self.query_one("#header-mcp-servers", Label)
65+
label.update(markup)

src/agent_chat_cli/core/agent_loop.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from agent_chat_cli.utils.enums import AgentMessageType, ContentType, ControlCommand
2626
from agent_chat_cli.core.mcp_inference import infer_mcp_servers
2727
from agent_chat_cli.utils.logger import log_json
28+
from agent_chat_cli.utils.mcp_server_status import MCPServerStatus
2829

2930
if TYPE_CHECKING:
3031
from agent_chat_cli.app import AgentChatCLIApp
@@ -164,6 +165,9 @@ async def _handle_message(self, message: Any) -> None:
164165
# When initializing the chat, we store the session_id for later
165166
self.session_id = message.data["session_id"]
166167

168+
# Report status back to UI
169+
MCPServerStatus.update(message.data["mcp_servers"])
170+
167171
# Handle streaming messages
168172
if hasattr(message, "event"):
169173
event = message.event # type: ignore[attr-defined]
@@ -215,7 +219,7 @@ async def _can_use_tool(
215219
self,
216220
tool_name: str,
217221
tool_input: dict[str, Any],
218-
context: ToolPermissionContext,
222+
_context: ToolPermissionContext,
219223
) -> PermissionResult:
220224
"""Agent SDK handler for tool use permissions"""
221225

src/agent_chat_cli/core/styles.tcss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ MarkdownH6 {
1010
}
1111

1212
Screen {
13-
background: transparent;
13+
background: #222;
1414
}
1515

1616
Spacer {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from typing import Any, Callable
2+
3+
4+
class MCPServerStatus:
5+
# After the first query is sent, claude agent sdk sends back an init payload which
6+
# with various statuses. In it, we can see mcp connection success or failure.
7+
_mcp_servers: list[dict[str, Any]] = []
8+
9+
# Register component callbacks that need access to the status
10+
_callbacks: list[Callable[[], None]] = []
11+
12+
@classmethod
13+
def update(cls, mcp_servers: list[dict[str, Any]]) -> None:
14+
cls._mcp_servers = mcp_servers
15+
16+
for callback in cls._callbacks:
17+
callback()
18+
19+
@classmethod
20+
def is_connected(cls, server_name: str) -> bool:
21+
for server in cls._mcp_servers:
22+
if server.get("name") == server_name:
23+
return server.get("status") == "connected"
24+
25+
return False
26+
27+
@classmethod
28+
def subscribe(cls, callback: Callable[[], None]) -> None:
29+
cls._callbacks.append(callback)
30+
31+
@classmethod
32+
def unsubscribe(cls, callback: Callable[[], None]) -> None:
33+
if callback in cls._callbacks:
34+
cls._callbacks.remove(callback)

0 commit comments

Comments
 (0)