@@ -23,6 +23,7 @@ This library provides a lightweight wrapper that makes [Anthropic Model Context
23
23
24
24
- Compatible with LangChain.js and LangGraph.js
25
25
- Optimized for OpenAI, Anthropic, and Google models
26
+ - Supports rich content responses including text, images, and embedded resources
26
27
27
28
- 🛠️ ** Development Features**
28
29
- Uses ` debug ` package for debug logging
87
88
// Connect to the transport
88
89
await client .connect (transport );
89
90
90
- // Get tools
91
- const tools = await loadMcpTools (" math" , client );
91
+ // Get tools with custom configuration
92
+ const tools = await loadMcpTools (" math" , client , {
93
+ // Whether to throw errors if a tool fails to load (optional, default: true)
94
+ throwOnLoadError: true ,
95
+ // Whether to prefix tool names with the server name (optional, default: false)
96
+ prefixToolNameWithServerName: false ,
97
+ // Optional additional prefix for tool names (optional, default: "")
98
+ additionalToolNamePrefix: " " ,
99
+ });
92
100
93
101
// Create and run the agent
94
102
const agent = createReactAgent ({ llm: model , tools });
@@ -117,19 +125,50 @@ import { createReactAgent } from "@langchain/langgraph/prebuilt";
117
125
118
126
// Create client and connect to server
119
127
const client = new MultiServerMCPClient ({
120
- // adds a STDIO connection to a server named "math"
121
- math: {
122
- transport: " stdio" ,
123
- command: " npx" ,
124
- args: [" -y" , " @modelcontextprotocol/server-math" ],
125
- },
126
-
127
- // add additional servers by adding more keys to the config
128
- // here's a filesystem server
129
- filesystem: {
130
- transport: " stdio" ,
131
- command: " npx" ,
132
- args: [" -y" , " @modelcontextprotocol/server-filesystem" ],
128
+ // Global tool configuration options
129
+ // Whether to throw on errors if a tool fails to load (optional, default: true)
130
+ throwOnLoadError: true ,
131
+ // Whether to prefix tool names with the server name (optional, default: true)
132
+ prefixToolNameWithServerName: true ,
133
+ // Optional additional prefix for tool names (optional, default: "mcp")
134
+ additionalToolNamePrefix: " mcp" ,
135
+
136
+ // Server configuration
137
+ mcpServers: {
138
+ // adds a STDIO connection to a server named "math"
139
+ math: {
140
+ transport: " stdio" ,
141
+ command: " npx" ,
142
+ args: [" -y" , " @modelcontextprotocol/server-math" ],
143
+ // Restart configuration for stdio transport
144
+ restart: {
145
+ enabled: true ,
146
+ maxAttempts: 3 ,
147
+ delayMs: 1000 ,
148
+ },
149
+ },
150
+
151
+ // here's a filesystem server
152
+ filesystem: {
153
+ transport: " stdio" ,
154
+ command: " npx" ,
155
+ args: [" -y" , " @modelcontextprotocol/server-filesystem" ],
156
+ },
157
+
158
+ // SSE transport example with reconnection configuration
159
+ weather: {
160
+ transport: " sse" ,
161
+ url: " https://example.com/mcp-weather" ,
162
+ headers: {
163
+ Authorization: " Bearer token123" ,
164
+ },
165
+ useNodeEventSource: true ,
166
+ reconnect: {
167
+ enabled: true ,
168
+ maxAttempts: 5 ,
169
+ delayMs: 2000 ,
170
+ },
171
+ },
133
172
},
134
173
});
135
174
@@ -148,18 +187,176 @@ const agent = createReactAgent({
148
187
});
149
188
150
189
// Run the agent
151
- const mathResponse = await agent .invoke ({
152
- messages: [{ role: " user" , content: " what's (3 + 5) x 12?" }],
153
- });
154
- const weatherResponse = await agent .invoke ({
155
- messages: [{ role: " user" , content: " what is the weather in nyc?" }],
156
- });
190
+ try {
191
+ const mathResponse = await agent .invoke ({
192
+ messages: [{ role: " user" , content: " what's (3 + 5) x 12?" }],
193
+ });
194
+ console .log (mathResponse );
195
+ } catch (error ) {
196
+ console .error (" Error during agent execution:" , error );
197
+ // Tools throw ToolException for tool-specific errors
198
+ if (error .name === " ToolException" ) {
199
+ console .error (" Tool execution failed:" , error .message );
200
+ }
201
+ }
157
202
158
203
await client .close ();
159
204
```
160
205
161
206
For more detailed examples, see the [ examples] ( ./examples ) directory.
162
207
208
+ ## Tool Configuration Options
209
+
210
+ When loading MCP tools either directly through ` loadMcpTools ` or via ` MultiServerMCPClient ` , you can configure the following options:
211
+
212
+ | Option | Type | Default | Description |
213
+ | ------------------------------ | ------- | ------- | ------------------------------------------------------------------------------------ |
214
+ | ` throwOnLoadError ` | boolean | ` true ` | Whether to throw an error if a tool fails to load |
215
+ | ` prefixToolNameWithServerName ` | boolean | ` false ` | If true, prefixes all tool names with the server name (e.g., ` serverName__toolName ` ) |
216
+ | ` additionalToolNamePrefix ` | string | ` "" ` | Additional prefix to add to tool names (e.g., ` prefix__serverName__toolName ` ) |
217
+
218
+ ## Response Handling
219
+
220
+ MCP tools return results in the ` content_and_artifact ` format which can include:
221
+
222
+ - ** Text content** : Plain text responses
223
+ - ** Image content** : Base64-encoded images with MIME type
224
+ - ** Embedded resources** : Files, structured data, or other resources
225
+
226
+ Example for handling different content types:
227
+
228
+ ``` ts
229
+ const tool = tools .find ((t ) => t .name === " mcp__math__calculate" );
230
+ const result = await tool .invoke ({ expression: " (3 + 5) * 12" });
231
+
232
+ // Result format: [content, artifacts]
233
+ // - content: string | MessageContentComplex[]
234
+ // - artifacts: EmbeddedResource[]
235
+
236
+ const [textContent, artifacts] = result ;
237
+
238
+ // Handle text content
239
+ if (typeof textContent === " string" ) {
240
+ console .log (" Result:" , textContent );
241
+ } else {
242
+ // Handle complex content (text + images)
243
+ textContent .forEach ((item ) => {
244
+ if (item .type === " text" ) {
245
+ console .log (" Text:" , item .text );
246
+ } else if (item .type === " image_url" ) {
247
+ console .log (" Image URL:" , item .image_url .url );
248
+ }
249
+ });
250
+ }
251
+
252
+ // Handle artifacts if needed
253
+ if (artifacts .length > 0 ) {
254
+ console .log (" Received artifacts:" , artifacts );
255
+ }
256
+ ```
257
+
258
+ ## Reconnection Strategies
259
+
260
+ Both transport types support automatic reconnection:
261
+
262
+ ### Stdio Transport Restart
263
+
264
+ ``` ts
265
+ {
266
+ transport : " stdio" ,
267
+ command : " npx" ,
268
+ args : [" -y" , " @modelcontextprotocol/server-math" ],
269
+ restart : {
270
+ enabled : true , // Enable automatic restart
271
+ maxAttempts : 3 , // Maximum restart attempts
272
+ delayMs : 1000 // Delay between attempts in ms
273
+ }
274
+ }
275
+ ```
276
+
277
+ ### SSE Transport Reconnect
278
+
279
+ ``` ts
280
+ {
281
+ transport : " sse" ,
282
+ url : " https://example.com/mcp-server" ,
283
+ headers : { " Authorization" : " Bearer token123" },
284
+ useNodeEventSource : true ,
285
+ reconnect : {
286
+ enabled : true , // Enable automatic reconnection
287
+ maxAttempts : 5 , // Maximum reconnection attempts
288
+ delayMs : 2000 // Delay between attempts in ms
289
+ }
290
+ }
291
+ ```
292
+
293
+ ## Error Handling
294
+
295
+ The library provides different error types to help with debugging:
296
+
297
+ - ** MCPClientError** : For client connection and initialization issues
298
+ - ** ToolException** : For errors during tool execution
299
+ - ** ZodError** : For configuration validation errors (invalid connection settings, etc.)
300
+
301
+ Example error handling:
302
+
303
+ ``` ts
304
+ try {
305
+ const client = new MultiServerMCPClient ({
306
+ math: {
307
+ transport: " stdio" ,
308
+ command: " npx" ,
309
+ args: [" -y" , " @modelcontextprotocol/server-math" ],
310
+ },
311
+ });
312
+
313
+ const tools = await client .getTools ();
314
+ const result = await tools [0 ].invoke ({ expression: " 1 + 2" });
315
+ } catch (error ) {
316
+ if (error .name === " MCPClientError" ) {
317
+ // Handle connection issues
318
+ console .error (` Connection error (${error .serverName }): ` , error .message );
319
+ } else if (error .name === " ToolException" ) {
320
+ // Handle tool execution errors
321
+ console .error (" Tool execution failed:" , error .message );
322
+ } else if (error .name === " ZodError" ) {
323
+ // Handle configuration validation errors
324
+ console .error (" Configuration error:" , error .issues );
325
+ // Zod errors contain detailed information about what went wrong
326
+ error .issues .forEach ((issue ) => {
327
+ console .error (` - Path: ${issue .path .join (" ." )}, Error: ${issue .message } ` );
328
+ });
329
+ } else {
330
+ // Handle other errors
331
+ console .error (" Unexpected error:" , error );
332
+ }
333
+ }
334
+ ```
335
+
336
+ ### Common Zod Validation Errors
337
+
338
+ The library uses Zod for validating configuration. Here are some common validation errors:
339
+
340
+ - ** Missing required parameters** : For example, omitting ` command ` for stdio transport or ` url ` for SSE transport
341
+ - ** Invalid parameter types** : For example, providing a number where a string is expected
342
+ - ** Invalid connection configuration** : For example, using an invalid URL format for SSE transport
343
+
344
+ Example Zod error for an invalid SSE URL:
345
+
346
+ ``` json
347
+ {
348
+ "issues" : [
349
+ {
350
+ "code" : " invalid_string" ,
351
+ "validation" : " url" ,
352
+ "path" : [" mcpServers" , " weather" , " url" ],
353
+ "message" : " Invalid url"
354
+ }
355
+ ],
356
+ "name" : " ZodError"
357
+ }
358
+ ```
359
+
163
360
## Browser Environments
164
361
165
362
When using in browsers:
0 commit comments