support for multiple mcp servers per dvm

This commit is contained in:
dbth 2025-02-10 10:43:25 +01:00
parent 3a622ea7af
commit cf2c701670
6 changed files with 76 additions and 36 deletions

View File

@ -18,7 +18,7 @@ async def main():
"""Stripped-down script to initialize the server and send a ping."""
# Configuration values
config_path = "server_config.json"
server_name = "sqlite"
server_name = "Echo"
# Load server configuration
server_params = await load_config(config_path, server_name)

View File

@ -3,6 +3,17 @@
"sqlite": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "test.db"]
},
"Echo": {
"command": "uv",
"args": [
"run",
"--with",
"mcp[cli]",
"mcp",
"run",
"~/Documents/GitHub/nostrdvm/tests/mcp_server.py"
]
}
}
}

View File

@ -96,9 +96,18 @@ class MCPBridge(DVMTaskInterface):
if options["command"] == "list-tools":
tools = await self.list_tools(config_path, server_names)
# Just return the first for now.
if len(tools) == 0:
print("Couldnt load tools, shutting down.")
exit()
final_tools = []
for tool in tools:
print(tool[1])
return json.dumps(tool[1])
j = json.loads(json.dumps(tool[1]))["tools"]
for tool in j:
final_tools.append(tool)
print(final_tools)
return json.dumps(final_tools)
elif options["command"] == "execute-tool":
@ -134,6 +143,12 @@ class MCPBridge(DVMTaskInterface):
try:
async with stdio_client(server_params) as (read_stream, write_stream):
# Initialize the server
init_result = await send_initialize(read_stream, write_stream)
# check we got a result
if not init_result:
print("Server initialization failed")
return
tools = await send_tools_list(read_stream, write_stream)
if tools is not None:
@ -161,6 +176,11 @@ class MCPBridge(DVMTaskInterface):
async with stdio_client(server_params) as (read_stream, write_stream):
#Check if our current config has a tool.
init_result = await send_initialize(read_stream, write_stream)
# check we got a result
if not init_result:
print("Server initialization failed")
return
tools = await send_tools_list(read_stream, write_stream)
stuff = json.dumps(tools)
@ -173,44 +193,23 @@ class MCPBridge(DVMTaskInterface):
print(f"Found tool {tool_name}.")
server_has_tool = True
if server_has_tool is False:
continue
tool_response = await send_call_tool(
tool_name, tool_args, read_stream, write_stream)
raise Exception("I'm gonna leave you.") # Until we find a better way to leave the async with
print("no tool in server")
raise Exception()
else:
tool_response = await send_call_tool(
tool_name, tool_args, read_stream, write_stream)
raise Exception() # Until we find a better way to leave the async with
except:
pass
return tool_response
raise Exception("I'm gonna leave you.")
raise Exception()
except:
pass
return "not_found"
return tool_response
alltools = []
for server_name in server_names:
server_params = await config.load_config(config_path, server_name)
try:
async with stdio_client(server_params) as (read_stream, write_stream):
# Initialize the server
tools = await send_tools_list(read_stream, write_stream)
if tools is not None:
alltools.append((server_name, tools))
raise Exception("I'm gonna leave you.")
else:
print("nada")
except:
pass
print("All clear. We made it out of thread hell. never mind the error.")
return alltools
# We build an example here that we can call by either calling this file directly from the main directory,

View File

@ -90,7 +90,9 @@ async def nostr_client():
await client.subscribe(mcp_filter, None)
#await nostr_client_test_mcp_get_tools()
await nostr_client_test_mcp_execute_tool(tool_name="get-crypto-price", tool_parameters={"symbol": "BTC"})
#await nostr_client_test_mcp_execute_tool(tool_name="get-crypto-price", tool_parameters={"symbol": "BTC"})
await nostr_client_test_mcp_execute_tool(tool_name="echo_tool", tool_parameters={"message": "Hello"})
class NotificationHandler(HandleNotification):
async def handle(self, relay_url, subscription_id, event: Event):

18
tests/mcp_server.py Normal file
View File

@ -0,0 +1,18 @@
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Echo")
@mcp.resource("echo://{message}")
def echo_resource(message: str) -> str:
"""Echo a message as a resource"""
return f"Resource echo: {message}"
@mcp.tool()
def echo_tool(message: str) -> str:
"""Echo a message as a tool"""
return f"Tool echo: {message}"
@mcp.prompt()
def echo_prompt(message: str) -> str:
"""Create an echo prompt"""
return f"Please process this message: {message}"

View File

@ -32,13 +32,23 @@ def playground(announce=False):
# MCP CONFIG
config_path = str(Path.absolute(Path(__file__).parent / "mcp_server_config.json"))
server_names = ["mcp-crypto-price"]
server_names = ["Echo", "mcp-crypto-price"]
tools = asyncio.run(get_tools(config_path, server_names))
# for now get the first connected server only
#print(tools)
j = json.loads(json.dumps(tools[0][1]))
if len (tools) == 0:
print("Couldnt load tools, shutting down.")
exit()
final_tools =[]
for tool in tools:
j = json.loads(json.dumps(tool[1]))["tools"]
for tool in j:
final_tools.append(tool)
print(final_tools)
# Add NIP89
@ -50,7 +60,7 @@ def playground(announce=False):
"acceptsNutZaps": dvm_config.ENABLE_NUTZAP,
"nip90Params": {
},
"tools": j["tools"]
"tools": final_tools
}