@smithery/sdk 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +3 -187
- package/dist/index.js +3 -85
- package/dist/integrations/error-adapter.d.ts +5 -0
- package/dist/integrations/error-adapter.js +25 -0
- package/dist/multi-client.d.ts +187 -0
- package/dist/multi-client.js +84 -0
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Smithery is a Typescript framework with utilities to make it easier to connect l
|
|
|
7
7
|
**Key Features**
|
|
8
8
|
|
|
9
9
|
- Connect to multiple MCPs with a single client
|
|
10
|
-
- Adapters to transform MCP
|
|
10
|
+
- Adapters to transform MCP responses for OpenAI and Anthropic clients
|
|
11
11
|
- Supports chaining tool calls until LLM completes
|
|
12
12
|
|
|
13
13
|
To find our registry of MCPs, visit [https://smithery.ai/](https://smithery.ai/).
|
|
@@ -120,4 +120,4 @@ Patch the global EventSource object:
|
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
122
|
import EventSource from "eventsource"
|
|
123
|
-
global.EventSource = EventSource as any
|
|
123
|
+
global.EventSource = EventSource as any
|
package/dist/index.d.ts
CHANGED
|
@@ -1,188 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
-
import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
|
-
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
5
|
-
import { type CallToolRequest, CallToolResultSchema, type CompatibilityCallToolResultSchema, type ListToolsRequest, type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
export { OpenAIChatAdapter } from "./integrations/llm/openai.js";
|
|
1
|
+
export { wrapErrorAdapter } from "./integrations/error-adapter.js";
|
|
7
2
|
export { AnthropicChatAdapter } from "./integrations/llm/anthropic.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
version: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* A client that connects to multiple MCPs and provides a unified interface for
|
|
14
|
-
* accessing their tools, treating them as a single MCP.
|
|
15
|
-
*/
|
|
16
|
-
export declare class MultiClient implements Pick<Client, "callTool" | "listTools" | "close"> {
|
|
17
|
-
private client_capabilities;
|
|
18
|
-
clients: Record<string, Client>;
|
|
19
|
-
client_info: ClientInfo;
|
|
20
|
-
constructor(client_info?: ClientInfo, client_capabilities?: {
|
|
21
|
-
capabilities: Record<string, unknown>;
|
|
22
|
-
});
|
|
23
|
-
/**
|
|
24
|
-
* Connects to a collection of transport or servers.
|
|
25
|
-
*/
|
|
26
|
-
connectAll(transports: Record<string, Transport | Server>): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Maps a tool name to a namespace-specific name to avoid conflicts.
|
|
29
|
-
*/
|
|
30
|
-
toolNameMapper: (namespace: string, tool: Tool) => string;
|
|
31
|
-
toolNameUnmapper: (fullToolName: string) => {
|
|
32
|
-
namespace: string;
|
|
33
|
-
toolName: string;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* List all tools available from all MCPs, ensuring each tool is namespaced.
|
|
37
|
-
* @param params - Optional parameters for the request.
|
|
38
|
-
* @param options - Optional options for the request.
|
|
39
|
-
* @returns A promise that resolves to an array of tools.
|
|
40
|
-
*/
|
|
41
|
-
listTools(params?: ListToolsRequest["params"], options?: RequestOptions): Promise<{
|
|
42
|
-
tools: import("zod").objectOutputType<{
|
|
43
|
-
name: import("zod").ZodString;
|
|
44
|
-
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
45
|
-
inputSchema: import("zod").ZodObject<{
|
|
46
|
-
type: import("zod").ZodLiteral<"object">;
|
|
47
|
-
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
48
|
-
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
49
|
-
type: import("zod").ZodLiteral<"object">;
|
|
50
|
-
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
51
|
-
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
52
|
-
type: import("zod").ZodLiteral<"object">;
|
|
53
|
-
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
54
|
-
}, import("zod").ZodTypeAny, "passthrough">>;
|
|
55
|
-
}, import("zod").ZodTypeAny, "passthrough">[];
|
|
56
|
-
}>;
|
|
57
|
-
callTool(params: CallToolRequest["params"], resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
58
|
-
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
59
|
-
}, {
|
|
60
|
-
content: import("zod").ZodArray<import("zod").ZodUnion<[import("zod").ZodObject<{
|
|
61
|
-
type: import("zod").ZodLiteral<"text">;
|
|
62
|
-
text: import("zod").ZodString;
|
|
63
|
-
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
64
|
-
type: import("zod").ZodLiteral<"text">;
|
|
65
|
-
text: import("zod").ZodString;
|
|
66
|
-
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
67
|
-
type: import("zod").ZodLiteral<"text">;
|
|
68
|
-
text: import("zod").ZodString;
|
|
69
|
-
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
|
|
70
|
-
type: import("zod").ZodLiteral<"image">;
|
|
71
|
-
data: import("zod").ZodString;
|
|
72
|
-
mimeType: import("zod").ZodString;
|
|
73
|
-
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
74
|
-
type: import("zod").ZodLiteral<"image">;
|
|
75
|
-
data: import("zod").ZodString;
|
|
76
|
-
mimeType: import("zod").ZodString;
|
|
77
|
-
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
78
|
-
type: import("zod").ZodLiteral<"image">;
|
|
79
|
-
data: import("zod").ZodString;
|
|
80
|
-
mimeType: import("zod").ZodString;
|
|
81
|
-
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
|
|
82
|
-
type: import("zod").ZodLiteral<"resource">;
|
|
83
|
-
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
84
|
-
uri: import("zod").ZodString;
|
|
85
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
86
|
-
}, {
|
|
87
|
-
text: import("zod").ZodString;
|
|
88
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
89
|
-
uri: import("zod").ZodString;
|
|
90
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
91
|
-
}, {
|
|
92
|
-
text: import("zod").ZodString;
|
|
93
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
94
|
-
uri: import("zod").ZodString;
|
|
95
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
96
|
-
}, {
|
|
97
|
-
text: import("zod").ZodString;
|
|
98
|
-
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
99
|
-
uri: import("zod").ZodString;
|
|
100
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
101
|
-
}, {
|
|
102
|
-
blob: import("zod").ZodString;
|
|
103
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
104
|
-
uri: import("zod").ZodString;
|
|
105
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
106
|
-
}, {
|
|
107
|
-
blob: import("zod").ZodString;
|
|
108
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
109
|
-
uri: import("zod").ZodString;
|
|
110
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
111
|
-
}, {
|
|
112
|
-
blob: import("zod").ZodString;
|
|
113
|
-
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
114
|
-
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
115
|
-
type: import("zod").ZodLiteral<"resource">;
|
|
116
|
-
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
117
|
-
uri: import("zod").ZodString;
|
|
118
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
119
|
-
}, {
|
|
120
|
-
text: import("zod").ZodString;
|
|
121
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
122
|
-
uri: import("zod").ZodString;
|
|
123
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
124
|
-
}, {
|
|
125
|
-
text: import("zod").ZodString;
|
|
126
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
127
|
-
uri: import("zod").ZodString;
|
|
128
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
129
|
-
}, {
|
|
130
|
-
text: import("zod").ZodString;
|
|
131
|
-
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
132
|
-
uri: import("zod").ZodString;
|
|
133
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
134
|
-
}, {
|
|
135
|
-
blob: import("zod").ZodString;
|
|
136
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
137
|
-
uri: import("zod").ZodString;
|
|
138
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
139
|
-
}, {
|
|
140
|
-
blob: import("zod").ZodString;
|
|
141
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
142
|
-
uri: import("zod").ZodString;
|
|
143
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
144
|
-
}, {
|
|
145
|
-
blob: import("zod").ZodString;
|
|
146
|
-
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
147
|
-
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
148
|
-
type: import("zod").ZodLiteral<"resource">;
|
|
149
|
-
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
150
|
-
uri: import("zod").ZodString;
|
|
151
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
152
|
-
}, {
|
|
153
|
-
text: import("zod").ZodString;
|
|
154
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
155
|
-
uri: import("zod").ZodString;
|
|
156
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
157
|
-
}, {
|
|
158
|
-
text: import("zod").ZodString;
|
|
159
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
160
|
-
uri: import("zod").ZodString;
|
|
161
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
162
|
-
}, {
|
|
163
|
-
text: import("zod").ZodString;
|
|
164
|
-
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
165
|
-
uri: import("zod").ZodString;
|
|
166
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
167
|
-
}, {
|
|
168
|
-
blob: import("zod").ZodString;
|
|
169
|
-
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
170
|
-
uri: import("zod").ZodString;
|
|
171
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
172
|
-
}, {
|
|
173
|
-
blob: import("zod").ZodString;
|
|
174
|
-
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
175
|
-
uri: import("zod").ZodString;
|
|
176
|
-
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
177
|
-
}, {
|
|
178
|
-
blob: import("zod").ZodString;
|
|
179
|
-
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
180
|
-
}, import("zod").ZodTypeAny, "passthrough">>]>, "many">;
|
|
181
|
-
isError: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodBoolean>>;
|
|
182
|
-
}>, import("zod").ZodTypeAny, "passthrough"> | import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
183
|
-
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
184
|
-
}, {
|
|
185
|
-
toolResult: import("zod").ZodUnknown;
|
|
186
|
-
}>, import("zod").ZodTypeAny, "passthrough">>;
|
|
187
|
-
close(): Promise<void>;
|
|
188
|
-
}
|
|
3
|
+
export { OpenAIChatAdapter } from "./integrations/llm/openai.js";
|
|
4
|
+
export { MultiClient } from "./multi-client.js";
|
package/dist/index.js
CHANGED
|
@@ -1,86 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
3
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
-
import { CallToolResultSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
export { OpenAIChatAdapter } from "./integrations/llm/openai.js";
|
|
1
|
+
export { wrapErrorAdapter } from "./integrations/error-adapter.js";
|
|
6
2
|
export { AnthropicChatAdapter } from "./integrations/llm/anthropic.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* accessing their tools, treating them as a single MCP.
|
|
10
|
-
*/
|
|
11
|
-
export class MultiClient {
|
|
12
|
-
constructor(client_info, client_capabilities = {
|
|
13
|
-
capabilities: {},
|
|
14
|
-
}) {
|
|
15
|
-
this.client_capabilities = client_capabilities;
|
|
16
|
-
this.clients = {};
|
|
17
|
-
/**
|
|
18
|
-
* Maps a tool name to a namespace-specific name to avoid conflicts.
|
|
19
|
-
*/
|
|
20
|
-
this.toolNameMapper = (namespace, tool) => {
|
|
21
|
-
return `${namespace}_${tool.name}`;
|
|
22
|
-
};
|
|
23
|
-
this.toolNameUnmapper = (fullToolName) => {
|
|
24
|
-
const namespace = fullToolName.split("_")[0];
|
|
25
|
-
const toolName = fullToolName.split("_").slice(1).join("_");
|
|
26
|
-
return { namespace, toolName };
|
|
27
|
-
};
|
|
28
|
-
this.client_info = client_info || {
|
|
29
|
-
name: "MultiClient",
|
|
30
|
-
version: "1.0.0",
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Connects to a collection of transport or servers.
|
|
35
|
-
*/
|
|
36
|
-
async connectAll(transports) {
|
|
37
|
-
await Promise.all(Object.entries(transports).map(async ([namespace, transport]) => {
|
|
38
|
-
const client = new Client({
|
|
39
|
-
name: this.client_info.name,
|
|
40
|
-
version: "1.0.0",
|
|
41
|
-
}, this.client_capabilities);
|
|
42
|
-
if (transport instanceof Server) {
|
|
43
|
-
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
44
|
-
await transport.connect(serverTransport);
|
|
45
|
-
await client.connect(clientTransport);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
await client.connect(transport);
|
|
49
|
-
}
|
|
50
|
-
this.clients[namespace] = client;
|
|
51
|
-
}));
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* List all tools available from all MCPs, ensuring each tool is namespaced.
|
|
55
|
-
* @param params - Optional parameters for the request.
|
|
56
|
-
* @param options - Optional options for the request.
|
|
57
|
-
* @returns A promise that resolves to an array of tools.
|
|
58
|
-
*/
|
|
59
|
-
async listTools(params, options) {
|
|
60
|
-
const tools = (await Promise.all(Object.entries(this.clients).map(async ([namespace, mcp]) => {
|
|
61
|
-
const capabilities = mcp.getServerCapabilities();
|
|
62
|
-
if (!capabilities?.tools)
|
|
63
|
-
return [];
|
|
64
|
-
const response = await mcp.listTools(params, options);
|
|
65
|
-
return response.tools.map((tool) => ({
|
|
66
|
-
...tool,
|
|
67
|
-
name: this.toolNameMapper(namespace, tool),
|
|
68
|
-
}));
|
|
69
|
-
}))).flat();
|
|
70
|
-
return { tools };
|
|
71
|
-
}
|
|
72
|
-
async callTool(params, resultSchema = CallToolResultSchema, options) {
|
|
73
|
-
const { namespace, toolName } = this.toolNameUnmapper(params.name);
|
|
74
|
-
const mcp = this.clients[namespace];
|
|
75
|
-
if (!mcp) {
|
|
76
|
-
throw new Error(`MCP tool ${namespace} not found`);
|
|
77
|
-
}
|
|
78
|
-
return mcp.callTool({
|
|
79
|
-
name: toolName,
|
|
80
|
-
arguments: params.arguments,
|
|
81
|
-
}, resultSchema, options);
|
|
82
|
-
}
|
|
83
|
-
async close() {
|
|
84
|
-
await Promise.all(Object.values(this.clients).map((mcp) => mcp.close()));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
3
|
+
export { OpenAIChatAdapter } from "./integrations/llm/openai.js";
|
|
4
|
+
export { MultiClient } from "./multi-client.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CallToolResultSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Wraps each tool call so any errors get sent back to the LLM instead of throwing
|
|
4
|
+
*/
|
|
5
|
+
export function wrapErrorAdapter(client) {
|
|
6
|
+
const callTool = client.callTool.bind(client);
|
|
7
|
+
client.callTool = async (params, resultSchema = CallToolResultSchema, options) => {
|
|
8
|
+
try {
|
|
9
|
+
return await callTool(params, resultSchema, options);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
console.error("Tool calling error:", err);
|
|
13
|
+
return {
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: "text",
|
|
17
|
+
text: JSON.stringify(err, Object.getOwnPropertyNames(err)),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
isError: true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return client;
|
|
25
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
4
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
5
|
+
import { type CallToolRequest, CallToolResultSchema, type CompatibilityCallToolResultSchema, type ListToolsRequest, type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
interface ClientInfo {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A client that connects to multiple MCPs and provides a unified interface for
|
|
12
|
+
* accessing their tools, treating them as a single MCP.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MultiClient implements Pick<Client, "callTool" | "listTools" | "close"> {
|
|
15
|
+
private client_capabilities;
|
|
16
|
+
clients: Record<string, Client>;
|
|
17
|
+
client_info: ClientInfo;
|
|
18
|
+
constructor(client_info?: ClientInfo, client_capabilities?: {
|
|
19
|
+
capabilities: Record<string, unknown>;
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Connects to a collection of transport or servers.
|
|
23
|
+
*/
|
|
24
|
+
connectAll(transports: Record<string, Transport | Server>): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Maps a tool name to a namespace-specific name to avoid conflicts.
|
|
27
|
+
*/
|
|
28
|
+
toolNameMapper: (namespace: string, tool: Tool) => string;
|
|
29
|
+
toolNameUnmapper: (fullToolName: string) => {
|
|
30
|
+
namespace: string;
|
|
31
|
+
toolName: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* List all tools available from all MCPs, ensuring each tool is namespaced.
|
|
35
|
+
* @param params - Optional parameters for the request.
|
|
36
|
+
* @param options - Optional options for the request.
|
|
37
|
+
* @returns A promise that resolves to an array of tools.
|
|
38
|
+
*/
|
|
39
|
+
listTools(params?: ListToolsRequest["params"], options?: RequestOptions): Promise<{
|
|
40
|
+
tools: import("zod").objectOutputType<{
|
|
41
|
+
name: import("zod").ZodString;
|
|
42
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
43
|
+
inputSchema: import("zod").ZodObject<{
|
|
44
|
+
type: import("zod").ZodLiteral<"object">;
|
|
45
|
+
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
46
|
+
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
47
|
+
type: import("zod").ZodLiteral<"object">;
|
|
48
|
+
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
49
|
+
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
50
|
+
type: import("zod").ZodLiteral<"object">;
|
|
51
|
+
properties: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
52
|
+
}, import("zod").ZodTypeAny, "passthrough">>;
|
|
53
|
+
}, import("zod").ZodTypeAny, "passthrough">[];
|
|
54
|
+
}>;
|
|
55
|
+
callTool(params: CallToolRequest["params"], resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options?: RequestOptions): Promise<import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
56
|
+
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
57
|
+
}, {
|
|
58
|
+
content: import("zod").ZodArray<import("zod").ZodUnion<[import("zod").ZodObject<{
|
|
59
|
+
type: import("zod").ZodLiteral<"text">;
|
|
60
|
+
text: import("zod").ZodString;
|
|
61
|
+
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
62
|
+
type: import("zod").ZodLiteral<"text">;
|
|
63
|
+
text: import("zod").ZodString;
|
|
64
|
+
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
65
|
+
type: import("zod").ZodLiteral<"text">;
|
|
66
|
+
text: import("zod").ZodString;
|
|
67
|
+
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
|
|
68
|
+
type: import("zod").ZodLiteral<"image">;
|
|
69
|
+
data: import("zod").ZodString;
|
|
70
|
+
mimeType: import("zod").ZodString;
|
|
71
|
+
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
72
|
+
type: import("zod").ZodLiteral<"image">;
|
|
73
|
+
data: import("zod").ZodString;
|
|
74
|
+
mimeType: import("zod").ZodString;
|
|
75
|
+
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
76
|
+
type: import("zod").ZodLiteral<"image">;
|
|
77
|
+
data: import("zod").ZodString;
|
|
78
|
+
mimeType: import("zod").ZodString;
|
|
79
|
+
}, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<{
|
|
80
|
+
type: import("zod").ZodLiteral<"resource">;
|
|
81
|
+
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
82
|
+
uri: import("zod").ZodString;
|
|
83
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
84
|
+
}, {
|
|
85
|
+
text: import("zod").ZodString;
|
|
86
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
87
|
+
uri: import("zod").ZodString;
|
|
88
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
89
|
+
}, {
|
|
90
|
+
text: import("zod").ZodString;
|
|
91
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
92
|
+
uri: import("zod").ZodString;
|
|
93
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
94
|
+
}, {
|
|
95
|
+
text: import("zod").ZodString;
|
|
96
|
+
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
97
|
+
uri: import("zod").ZodString;
|
|
98
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
99
|
+
}, {
|
|
100
|
+
blob: import("zod").ZodString;
|
|
101
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
102
|
+
uri: import("zod").ZodString;
|
|
103
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
104
|
+
}, {
|
|
105
|
+
blob: import("zod").ZodString;
|
|
106
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
107
|
+
uri: import("zod").ZodString;
|
|
108
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
109
|
+
}, {
|
|
110
|
+
blob: import("zod").ZodString;
|
|
111
|
+
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
112
|
+
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
|
113
|
+
type: import("zod").ZodLiteral<"resource">;
|
|
114
|
+
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
115
|
+
uri: import("zod").ZodString;
|
|
116
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
117
|
+
}, {
|
|
118
|
+
text: import("zod").ZodString;
|
|
119
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
120
|
+
uri: import("zod").ZodString;
|
|
121
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
122
|
+
}, {
|
|
123
|
+
text: import("zod").ZodString;
|
|
124
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
125
|
+
uri: import("zod").ZodString;
|
|
126
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
127
|
+
}, {
|
|
128
|
+
text: import("zod").ZodString;
|
|
129
|
+
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
130
|
+
uri: import("zod").ZodString;
|
|
131
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
132
|
+
}, {
|
|
133
|
+
blob: import("zod").ZodString;
|
|
134
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
135
|
+
uri: import("zod").ZodString;
|
|
136
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
137
|
+
}, {
|
|
138
|
+
blob: import("zod").ZodString;
|
|
139
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
140
|
+
uri: import("zod").ZodString;
|
|
141
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
142
|
+
}, {
|
|
143
|
+
blob: import("zod").ZodString;
|
|
144
|
+
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
145
|
+
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
|
146
|
+
type: import("zod").ZodLiteral<"resource">;
|
|
147
|
+
resource: import("zod").ZodUnion<[import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
148
|
+
uri: import("zod").ZodString;
|
|
149
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
150
|
+
}, {
|
|
151
|
+
text: import("zod").ZodString;
|
|
152
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
153
|
+
uri: import("zod").ZodString;
|
|
154
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
155
|
+
}, {
|
|
156
|
+
text: import("zod").ZodString;
|
|
157
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
158
|
+
uri: import("zod").ZodString;
|
|
159
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
160
|
+
}, {
|
|
161
|
+
text: import("zod").ZodString;
|
|
162
|
+
}>, import("zod").ZodTypeAny, "passthrough">>, import("zod").ZodObject<import("zod").objectUtil.extendShape<{
|
|
163
|
+
uri: import("zod").ZodString;
|
|
164
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
165
|
+
}, {
|
|
166
|
+
blob: import("zod").ZodString;
|
|
167
|
+
}>, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
168
|
+
uri: import("zod").ZodString;
|
|
169
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
170
|
+
}, {
|
|
171
|
+
blob: import("zod").ZodString;
|
|
172
|
+
}>, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<import("zod").objectUtil.extendShape<{
|
|
173
|
+
uri: import("zod").ZodString;
|
|
174
|
+
mimeType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
175
|
+
}, {
|
|
176
|
+
blob: import("zod").ZodString;
|
|
177
|
+
}>, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
178
|
+
}, import("zod").ZodTypeAny, "passthrough">>]>, "many">;
|
|
179
|
+
isError: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodBoolean>>;
|
|
180
|
+
}>, import("zod").ZodTypeAny, "passthrough"> | import("zod").objectOutputType<import("zod").objectUtil.extendShape<{
|
|
181
|
+
_meta: import("zod").ZodOptional<import("zod").ZodObject<{}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{}, import("zod").ZodTypeAny, "passthrough">>>;
|
|
182
|
+
}, {
|
|
183
|
+
toolResult: import("zod").ZodUnknown;
|
|
184
|
+
}>, import("zod").ZodTypeAny, "passthrough">>;
|
|
185
|
+
close(): Promise<void>;
|
|
186
|
+
}
|
|
187
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { CallToolResultSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* A client that connects to multiple MCPs and provides a unified interface for
|
|
7
|
+
* accessing their tools, treating them as a single MCP.
|
|
8
|
+
*/
|
|
9
|
+
export class MultiClient {
|
|
10
|
+
constructor(client_info, client_capabilities = {
|
|
11
|
+
capabilities: {},
|
|
12
|
+
}) {
|
|
13
|
+
this.client_capabilities = client_capabilities;
|
|
14
|
+
this.clients = {};
|
|
15
|
+
/**
|
|
16
|
+
* Maps a tool name to a namespace-specific name to avoid conflicts.
|
|
17
|
+
*/
|
|
18
|
+
this.toolNameMapper = (namespace, tool) => {
|
|
19
|
+
return `${namespace}_${tool.name}`;
|
|
20
|
+
};
|
|
21
|
+
this.toolNameUnmapper = (fullToolName) => {
|
|
22
|
+
const namespace = fullToolName.split("_")[0];
|
|
23
|
+
const toolName = fullToolName.split("_").slice(1).join("_");
|
|
24
|
+
return { namespace, toolName };
|
|
25
|
+
};
|
|
26
|
+
this.client_info = client_info || {
|
|
27
|
+
name: "MultiClient",
|
|
28
|
+
version: "1.0.0",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Connects to a collection of transport or servers.
|
|
33
|
+
*/
|
|
34
|
+
async connectAll(transports) {
|
|
35
|
+
await Promise.all(Object.entries(transports).map(async ([namespace, transport]) => {
|
|
36
|
+
const client = new Client({
|
|
37
|
+
name: this.client_info.name,
|
|
38
|
+
version: "1.0.0",
|
|
39
|
+
}, this.client_capabilities);
|
|
40
|
+
if (transport instanceof Server) {
|
|
41
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
42
|
+
await transport.connect(serverTransport);
|
|
43
|
+
await client.connect(clientTransport);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
await client.connect(transport);
|
|
47
|
+
}
|
|
48
|
+
this.clients[namespace] = client;
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* List all tools available from all MCPs, ensuring each tool is namespaced.
|
|
53
|
+
* @param params - Optional parameters for the request.
|
|
54
|
+
* @param options - Optional options for the request.
|
|
55
|
+
* @returns A promise that resolves to an array of tools.
|
|
56
|
+
*/
|
|
57
|
+
async listTools(params, options) {
|
|
58
|
+
const tools = (await Promise.all(Object.entries(this.clients).map(async ([namespace, mcp]) => {
|
|
59
|
+
const capabilities = mcp.getServerCapabilities();
|
|
60
|
+
if (!capabilities?.tools)
|
|
61
|
+
return [];
|
|
62
|
+
const response = await mcp.listTools(params, options);
|
|
63
|
+
return response.tools.map((tool) => ({
|
|
64
|
+
...tool,
|
|
65
|
+
name: this.toolNameMapper(namespace, tool),
|
|
66
|
+
}));
|
|
67
|
+
}))).flat();
|
|
68
|
+
return { tools };
|
|
69
|
+
}
|
|
70
|
+
async callTool(params, resultSchema = CallToolResultSchema, options) {
|
|
71
|
+
const { namespace, toolName } = this.toolNameUnmapper(params.name);
|
|
72
|
+
const mcp = this.clients[namespace];
|
|
73
|
+
if (!mcp) {
|
|
74
|
+
throw new Error(`MCP tool ${namespace} not found`);
|
|
75
|
+
}
|
|
76
|
+
return mcp.callTool({
|
|
77
|
+
name: toolName,
|
|
78
|
+
arguments: params.arguments,
|
|
79
|
+
}, resultSchema, options);
|
|
80
|
+
}
|
|
81
|
+
async close() {
|
|
82
|
+
await Promise.all(Object.values(this.clients).map((mcp) => mcp.close()));
|
|
83
|
+
}
|
|
84
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithery/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Connect language models to Model Context Protocols",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
"link": "npm link -ws --include-workspace-root"
|
|
21
21
|
},
|
|
22
22
|
"license": "GPL-3.0-only",
|
|
23
|
-
"workspaces": [
|
|
24
|
-
"mcps/*"
|
|
25
|
-
],
|
|
26
23
|
"dependencies": {
|
|
27
24
|
"@anthropic-ai/sdk": "^0.32.1",
|
|
28
25
|
"@icons-pack/react-simple-icons": "^10.2.0",
|