88import httpx
99import os
1010import re
11+ import tempfile
1112
1213
1314def sanitize_name (name : str ) -> str :
@@ -25,23 +26,62 @@ def sanitize_name(name: str) -> str:
2526
2627
2728async def get_mcp_servers () -> list [StdioServerParameters ]:
28- async with httpx .AsyncClient () as client :
29- """Get MCP servers from the API."""
30- headers = {"Authorization" : f"Bearer { os .environ ['METATOOL_API_KEY' ]} " }
31- response = await client .get (
32- f"{ METATOOL_API_BASE_URL } /api/mcp-servers" , headers = headers
33- )
34- response .raise_for_status ()
35- data = response .json ()
36- server_params = []
37- for params in data :
38- # Convert empty lists and dicts to None
39- if "args" in params and not params ["args" ]:
40- params ["args" ] = None
41- if "env" in params and not params ["env" ]:
42- params ["env" ] = None
43- server_params .append (StdioServerParameters (** params ))
44- return server_params
29+ try :
30+ async with httpx .AsyncClient () as client :
31+ """Get MCP servers from the API."""
32+ headers = {"Authorization" : f"Bearer { os .environ ['METATOOL_API_KEY' ]} " }
33+ response = await client .get (
34+ f"{ METATOOL_API_BASE_URL } /api/mcp-servers" , headers = headers
35+ )
36+ response .raise_for_status ()
37+ data = response .json ()
38+ server_params = []
39+ for params in data :
40+ # Convert empty lists and dicts to None
41+ if "args" in params and not params ["args" ]:
42+ params ["args" ] = None
43+ if "env" in params and not params ["env" ]:
44+ params ["env" ] = None
45+ server_params .append (StdioServerParameters (** params ))
46+ return server_params
47+ except Exception :
48+ return []
49+
50+
51+ async def get_custom_mcp_servers () -> list [StdioServerParameters ]:
52+ try :
53+ async with httpx .AsyncClient () as client :
54+ headers = {"Authorization" : f"Bearer { os .environ ['METATOOL_API_KEY' ]} " }
55+ response = await client .get (
56+ f"{ METATOOL_API_BASE_URL } /api/custom-mcp-servers" , headers = headers
57+ )
58+ response .raise_for_status ()
59+ data = response .json ()
60+ server_params = []
61+ for params in data :
62+ if "code" not in params or "code_uuid" not in params :
63+ continue
64+ code_uuid = params ["code_uuid" ]
65+ with tempfile .NamedTemporaryFile (
66+ mode = "w" , suffix = f"_{ code_uuid } .py" , delete = False
67+ ) as temp_file :
68+ temp_file .write (params ["code" ])
69+ params ["command" ] = "uv"
70+ params ["args" ] = ["run" , temp_file .name ] + params .get (
71+ "additionalArgs" , []
72+ )
73+ if "env" in params and not params ["env" ]:
74+ params ["env" ] = None
75+ server_params .append (StdioServerParameters (** params ))
76+ return server_params
77+ except Exception :
78+ return []
79+
80+
81+ async def get_all_mcp_servers () -> list [StdioServerParameters ]:
82+ server_params = await get_mcp_servers ()
83+ custom_server_params = await get_custom_mcp_servers ()
84+ return server_params + custom_server_params
4585
4686
4787async def initialize_session (session : ClientSession ) -> dict :
@@ -57,7 +97,7 @@ async def initialize_session(session: ClientSession) -> dict:
5797@server .list_tools ()
5898async def handle_list_tools () -> list [types .Tool ]:
5999 # Reload MCP servers
60- remote_server_params = await get_mcp_servers ()
100+ remote_server_params = await get_all_mcp_servers ()
61101
62102 # Combine with default servers
63103 all_server_params = remote_server_params
@@ -94,7 +134,7 @@ async def handle_call_tool(
94134 )
95135
96136 # Get all server parameters
97- remote_server_params = await get_mcp_servers ()
137+ remote_server_params = await get_all_mcp_servers ()
98138
99139 # Find the matching server parameters
100140 for params in remote_server_params :
0 commit comments