Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 3,235 Bytes
52c6f5c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import type { MCPServerConfig, McpToolSchema, OpenAIFunctionSchema } from "./types.js";
import { debugError, debugLog } from "./utils.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
export const mcpToolToOpenAIFunction = (tool: McpToolSchema): OpenAIFunctionSchema => {
return {
type: "function",
function: {
name: tool.name,
description: tool.name,
parameters: tool.inputSchema,
strict: true,
},
};
};
export type MCPServerConnection = { client: Client; tools: OpenAIFunctionSchema[] };
export const connectToMCPServers = async (servers: MCPServerConfig[]): Promise<MCPServerConnection[]> => {
const connections: MCPServerConnection[] = [];
await Promise.allSettled(
servers.map(async server => {
try {
const conn: MCPServerConnection = {
client: new Client({
name: "playground-client" + crypto.randomUUID(),
version: "0.0.1",
}),
tools: [],
};
debugLog(`Connecting to MCP server: ${server.name} (${server.url})`);
let transport;
const url = new URL(server.url);
if (server.protocol === "sse") {
transport = new SSEClientTransport(url);
} else {
transport = new StreamableHTTPClientTransport(url);
}
await conn.client.connect(transport);
const { tools: mcpTools } = await conn.client.listTools();
const serverTools = mcpTools.map(mcpToolToOpenAIFunction);
conn.tools.push(...serverTools);
debugLog(`Connected to ${server.name} with ${mcpTools.length} tools`);
connections.push(conn);
} catch (error) {
debugError(`Failed to connect to MCP server ${server.name}:`, error);
}
}),
);
return connections;
};
export const executeMcpTool = async (
connections: MCPServerConnection[],
toolCall: { id: string; function: { name: string; arguments: string } },
) => {
try {
debugLog(`Executing tool: ${toolCall.function.name}`);
debugLog(`Tool arguments:`, JSON.parse(toolCall.function.arguments));
// Try to find the tool in any of the connected clients
let result = null;
for (const conn of connections) {
try {
const toolExists = conn.tools.some(tool => tool.function?.name === toolCall.function.name);
if (!toolExists) continue;
debugLog(`Found tool ${toolCall.function.name}`);
result = await conn.client.callTool({
name: toolCall.function.name,
arguments: JSON.parse(toolCall.function.arguments),
});
} catch (clientError) {
debugError(`Failed to execute tool on client:`, clientError);
continue;
}
}
if (!result) {
throw new Error(`Tool ${toolCall.function.name} not found in any connected MCP server`);
}
// mcpLog(`Tool result:`, result.content);
return {
tool_call_id: toolCall.id,
role: "tool" as const,
content: JSON.stringify(result.content),
};
} catch (error) {
debugError(`Tool execution failed:`, error);
return {
tool_call_id: toolCall.id,
role: "tool" as const,
content: JSON.stringify({ error: error instanceof Error ? error.message : "Tool execution failed" }),
};
}
};
|