update dvmcp - fully working now

This commit is contained in:
dbth
2025-02-14 19:24:48 +01:00
parent 792e7ae5d1
commit 3ae8d018d2
6 changed files with 70 additions and 47 deletions

View File

@ -5,6 +5,7 @@ from config import load_config
from messages.send_initialize_message import send_initialize from messages.send_initialize_message import send_initialize
from messages.send_ping import send_ping from messages.send_ping import send_ping
from messages.send_tools_list import send_tools_list from messages.send_tools_list import send_tools_list
from messages.send_call_tool import send_call_tool
from transport.stdio.stdio_client import stdio_client from transport.stdio.stdio_client import stdio_client
# Configure logging # Configure logging
@ -18,7 +19,7 @@ async def main():
"""Stripped-down script to initialize the server and send a ping.""" """Stripped-down script to initialize the server and send a ping."""
# Configuration values # Configuration values
config_path = "server_config.json" config_path = "server_config.json"
server_name = "Echo" server_name = "nostrdvmmcp"
# Load server configuration # Load server configuration
server_params = await load_config(config_path, server_name) server_params = await load_config(config_path, server_name)
@ -44,6 +45,10 @@ async def main():
result = await send_tools_list(read_stream, write_stream) result = await send_tools_list(read_stream, write_stream)
print(result) print(result)
result = await send_call_tool("get-crypto-price", {"symbol":"BTC"}, read_stream, write_stream)
print(result)
# Run the script # Run the script
if __name__ == "__main__": if __name__ == "__main__":
anyio.run(main) anyio.run(main)

View File

@ -1,19 +1,8 @@
{ {
"mcpServers": { "mcpServers": {
"sqlite": { "nostrdvmmcp": {
"command": "uvx", "command": "node",
"args": ["mcp-server-sqlite", "--db-path", "test.db"] "args": ["../../../tests/mcp/nostr_dvmcp_server.js"]
},
"Echo": {
"command": "uv",
"args": [
"run",
"--with",
"mcp[cli]",
"mcp",
"run",
"~/Documents/GitHub/nostrdvm/tests/mcp_server.py"
]
} }
} }
} }

View File

@ -77,8 +77,7 @@ class MCPBridge(DVMTaskInterface):
print(c) print(c)
content = event.content() content = event.content()
print(c)
print(content)
options = { options = {
"command" : c, "command" : c,
@ -112,9 +111,8 @@ class MCPBridge(DVMTaskInterface):
return json.dumps(final_tools) return json.dumps(final_tools)
else: elif options["command"] == "execute-tool":
print(options["payload"])
ob = json.loads(options["payload"]) ob = json.loads(options["payload"])
tool_name = ob["name"] tool_name = ob["name"]
@ -162,7 +160,6 @@ class MCPBridge(DVMTaskInterface):
except BaseException as e: except BaseException as e:
pass pass
print("Ignore the error. We're good.")
return alltools return alltools

View File

@ -9,17 +9,6 @@
"args": [ "args": [
"../../mcp-crypto-price/build/index.js" "../../mcp-crypto-price/build/index.js"
] ]
},
"Echo": {
"command": "uv",
"args": [
"run",
"--with",
"mcp[cli]",
"mcp",
"run",
"tests/mcp/mcp_server.py"
]
} }
} }
} }

View File

@ -35,7 +35,7 @@ def playground(announce=False):
# MCP CONFIG # MCP CONFIG
config_path = str(Path.absolute(Path(__file__).parent / "mcp_server_config.json")) config_path = str(Path.absolute(Path(__file__).parent / "mcp_server_config.json"))
server_names = ["Echo", "mcp-crypto-price"] server_names = ["mcp-crypto-price"]
tools = asyncio.run(get_tools(config_path, server_names)) tools = asyncio.run(get_tools(config_path, server_names))
@ -74,7 +74,8 @@ def playground(announce=False):
capabilities_tag = Tag.parse(["capabilities", "mcp-1.0"]) capabilities_tag = Tag.parse(["capabilities", "mcp-1.0"])
t1_tag = Tag.parse(["t","mcp"]) t1_tag = Tag.parse(["t","mcp"])
t2_tag = Tag.parse(["t", "bitcoin price"]) t2_tag = Tag.parse(["t", "bitcoin price"])
nip89config.EXTRA_TAGS =[capabilities_tag, t1_tag, t2_tag] t3_tag = Tag.parse(["t", "bitcoin analysis"])
nip89config.EXTRA_TAGS =[capabilities_tag, t1_tag, t2_tag, t3_tag]
options = { options = {

View File

@ -62,6 +62,39 @@ const server = new McpServer(config);
await getnip89s() await getnip89s()
function convertSchemaDefinitionToZod(schemaDefinition) {
const zodSchema = {};
for (const key in schemaDefinition) {
const property = schemaDefinition[key];
let zodProperty;
switch (property.type) {
case 'string':
zodProperty = z.string();
break;
case 'number':
zodProperty = z.number();
if (property.min !== undefined) zodProperty = zodProperty.min(property.min);
if (property.max !== undefined) zodProperty = zodProperty.max(property.max);
break;
case 'boolean':
zodProperty = z.boolean();
break;
default:
zodProperty = z.any(); // Fallback for unknown types
}
if (property.description) {
zodProperty = zodProperty.describe(property.description);
}
zodSchema[key] = zodProperty;
}
return z.object(zodSchema);
}
//define getNip89s. Fetch from Nostr and add as tools to server. //define getNip89s. Fetch from Nostr and add as tools to server.
async function getnip89s() { async function getnip89s() {
await loadWasmAsync(); await loadWasmAsync();
@ -90,11 +123,8 @@ async function getnip89s() {
if (tool.inputSchema === undefined || tool.inputSchema.properties === undefined) { if (tool.inputSchema === undefined || tool.inputSchema.properties === undefined) {
continue continue
} }
const zodSchema = convertSchemaDefinitionToZod(tool.inputSchema.properties);
//TODO convert inputSchema.properties? to zod schema or to any other way so it works. server.tool(tool.name, tool.description, zodSchema.shape,
let inputSchema = {symbol: z.string()}
server.tool(tool.name, tool.description, inputSchema,
async (args) => { async (args) => {
return await handle_dvm_request(args, tool.name, pubkey) return await handle_dvm_request(args, tool.name, pubkey)
}); });
@ -123,7 +153,9 @@ async function handle_dvm_request(args, name, pubkey) {
await client.addRelay(relay); await client.addRelay(relay);
} }
await client.connect(); await client.connect();
var relays_list = merge(["relays"], relays)
const relays_list = ["relays"].concat(relays)
let tags = [ let tags = [
Tag.parse(["c", "execute-tool"]), Tag.parse(["c", "execute-tool"]),
@ -145,15 +177,25 @@ async function handle_dvm_request(args, name, pubkey) {
var result = "" var result = ""
const handle = { const handle = {
handleEvent: async (relayUrl, subscriptionId, event) => { handleEvent: async (relayUrl, subscriptionId, event) =>
//TODO More logic / safety checks {
if(event.kind.asU16() === 6910){
try {
result = JSON.parse(event.content).content[0].text result = JSON.parse(event.content).content[0].text
}
catch {
console.log("Error parsing JSON in event")
}
abortable.abort() abortable.abort()
return true return true
}
}, },
handleMsg: async (relayUrl, message) => { handleMsg: async (relayUrl, message) =>
//console.log("Received message from", relayUrl, message.asJson()); {
console.log("Received message from", relayUrl, message.asJson());
} }
}; };