mcp polishing

frdel committed Jun 4, 2025 at 14:23 UTC f2813b8a794a64e535b96b5688126b306578bf52
4 files changed +43 -26
agent.py
+19 -2
@@ -79,6 +79,10 @@ class AgentContext:
79 if not AgentContext._contexts:
80 return None
81 return list(AgentContext._contexts.values())[0]
82 +
83 + @staticmethod
84 + def all():
85 + return list(AgentContext._contexts.values())
86
87 @staticmethod
88 def remove(id: str):
@@ -107,8 +111,21 @@ class AgentContext:
111 "type": self.type.value,
112 }
113
110 - def get_created_at(self):
111 - return self.created_at
114 + @staticmethod
115 + def log_to_all(
116 + type: Log.Type,
117 + heading: str | None = None,
118 + content: str | None = None,
119 + kvps: dict | None = None,
120 + temp: bool | None = None,
121 + update_progress: Log.ProgressUpdate | None = None,
122 + id: str | None = None, # Add id parameter
123 + **kwargs,
124 + ) -> list[Log.LogItem]:
125 + items: list[Log.LogItem] = []
126 + for context in AgentContext.all():
127 + items.append(context.log.log(type, heading, content, kvps, temp, update_progress, id, **kwargs))
128 + return items
129
130 def kill_process(self):
131 if self.task:
python/api/mcp_servers_apply.py
+1
@@ -12,6 +12,7 @@ class McpServersApply(ApiHandler):
12 mcp_servers = input["mcp_servers"]
13 try:
14 # MCPConfig.update(mcp_servers) # done in settings automatically
15 + set_settings_delta({"mcp_servers": "[]"}) # to force reinitialization
16 set_settings_delta({"mcp_servers": mcp_servers})
17
18 except Exception as e:
python/helpers/mcp_handler.py
+12 -9
@@ -260,6 +260,7 @@ class MCPServerRemote(BaseModel):
260 "name",
261 "description",
262 "url",
263 + "serverUrl",
264 "headers",
265 "init_timeout",
266 "tool_timeout",
@@ -267,6 +268,9 @@ class MCPServerRemote(BaseModel):
268 ]:
269 if key == "name":
270 value = normalize_name(value)
271 + if key == "serverUrl":
272 + key = "url" # remap serverUrl to url
273 +
274 setattr(self, key, value)
275 # We already run in an event loop, dont believe Pylance
276 return asyncio.run(self.__on_update())
@@ -579,7 +583,7 @@ class MCPConfig(BaseModel):
583
584 try:
585 # not generic MCPServer because: "Annotated can not be instatioated"
582 - if server_item.get("url", None):
586 + if server_item.get("url", None) or server_item.get("serverUrl", None):
587 self.servers.append(MCPServerRemote(server_item))
588 else:
589 self.servers.append(MCPServerLocal(server_item))
@@ -690,12 +694,13 @@ class MCPConfig(BaseModel):
694 tool_args += f' "{key}": "...",\n'
695 examples = ""
696 description = ""
697 + param_type = value.get("type", "any")
698 if "examples" in value:
699 examples = f"(examples: {value['examples']})"
700 if "description" in value:
701 description = f": {value['description']}"
702 prompt += (
698 - f" * {key} ({value['type']}){description} {examples}\n"
703 + f" * {key} ({param_type}){description} {examples}\n"
704 )
705 prompt += "\n"
706
@@ -789,9 +794,6 @@ class MCPClientBase(ABC):
794 try:
795 async with AsyncExitStack() as temp_stack:
796 try:
792 - async def log_callback(params):
793 - msg = getattr(params, "message", str(params))
794 - self.log.append(f"[{self.server.name}] [session]: {msg}")
797
798 stdio, write = await self._create_stdio_transport(temp_stack)
799 # PrintStyle(font_color="cyan").print(f"MCPClientBase ({self.server.name} - {operation_name}): Transport created. Initializing session...")
@@ -800,19 +802,20 @@ class MCPClientBase(ABC):
802 stdio, # type: ignore
803 write, # type: ignore
804 read_timeout_seconds=timedelta(seconds=read_timeout_seconds),
803 - # logging_callback=log_callback,
805 )
806 )
807 await session.initialize()
807 - # PrintStyle(font_color="green").print(f"MCPClientBase ({self.server.name} - {operation_name}): Session initialized.")
808
809 result = await coro_func(session)
810
811 - # PrintStyle(font_color="green").print(f"MCPClientBase ({self.server.name} - {operation_name}): Operation successful.")
811 return result
812 except Exception as e:
813 # Store the original exception and raise a dummy exception
815 - original_exception = e
814 + excs = getattr(e, "exceptions", None) # Python 3.11+ ExceptionGroup
815 + if excs:
816 + original_exception = excs[0]
817 + else:
818 + original_exception = e
819 # Create a dummy exception to break out of the async block
820 raise RuntimeError("Dummy exception to break out of async block")
821 except Exception as e:
python/helpers/settings.py
+11 -15
@@ -981,22 +981,19 @@ def _apply_settings(previous: Settings | None):
981 PrintStyle(
982 background_color="black", font_color="white", padding=True
983 ).print("Updating MCP config...")
984 - first_context = AgentContext.first()
985 - if first_context:
986 - first_context.log.log(
987 - type="info", content="Updating MCP settings...", temp=True
988 - )
984 + AgentContext.log_to_all(
985 + type="info", content="Updating MCP settings...", temp=True
986 + )
987
988 mcp_config = MCPConfig.get_instance()
989 try:
990 MCPConfig.update(mcp_servers)
991 except Exception as e:
994 - if first_context:
995 - first_context.log.log(
996 - type="warning",
997 - content=f"Failed to update MCP settings: {e}",
998 - temp=False,
999 - )
992 + AgentContext.log_to_all(
993 + type="error",
994 + content=f"Failed to update MCP settings: {e}",
995 + temp=False,
996 + )
997 (
998 PrintStyle(
999 background_color="red", font_color="black", padding=True
@@ -1016,10 +1013,9 @@ def _apply_settings(previous: Settings | None):
1013 background_color="#334455", font_color="white", padding=False
1014 ).print(mcp_config.model_dump_json())
1015 )
1019 - if first_context:
1020 - first_context.log.log(
1021 - type="info", content="Finished updating MCP settings :)", temp=True
1022 - )
1016 + AgentContext.log_to_all(
1017 + type="info", content="Finished updating MCP settings.", temp=True
1018 + )
1019
1020 task2 = defer.DeferredTask().start_task(
1021 update_mcp_settings, config.mcp_servers