@smithery/sdk 0.0.15 → 0.0.16

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 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 resposnes for OpenAI and Anthropic clients
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
- 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
- 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
- interface ClientInfo {
9
- name: string;
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
- 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
- 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
- * A client that connects to multiple MCPs and provides a unified interface for
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,5 @@
1
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ /**
3
+ * Wraps each tool call so any errors get sent back to the LLM instead of throwing
4
+ */
5
+ export declare function wrapErrorAdapter<C extends Pick<Client, "callTool">>(client: C): C;
@@ -0,0 +1,24 @@
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;
7
+ client.callTool = async (params, resultSchema = CallToolResultSchema, options) => {
8
+ try {
9
+ return await callTool(params, resultSchema, options);
10
+ }
11
+ catch (e) {
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(e),
17
+ },
18
+ ],
19
+ isError: true,
20
+ };
21
+ }
22
+ };
23
+ return client;
24
+ }
@@ -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.15",
3
+ "version": "0.0.16",
4
4
  "description": "Connect language models to Model Context Protocols",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",