Skip to content

Commit 6093a1c

Browse files
chore: update README to reflect recent changes (#53)
1 parent 09f511a commit 6093a1c

File tree

1 file changed

+218
-21
lines changed

1 file changed

+218
-21
lines changed

README.md

+218-21
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This library provides a lightweight wrapper that makes [Anthropic Model Context
2323

2424
- Compatible with LangChain.js and LangGraph.js
2525
- Optimized for OpenAI, Anthropic, and Google models
26+
- Supports rich content responses including text, images, and embedded resources
2627

2728
- 🛠️ **Development Features**
2829
- Uses `debug` package for debug logging
@@ -87,8 +88,15 @@ try {
8788
// Connect to the transport
8889
await client.connect(transport);
8990

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+
});
92100

93101
// Create and run the agent
94102
const agent = createReactAgent({ llm: model, tools });
@@ -117,19 +125,50 @@ import { createReactAgent } from "@langchain/langgraph/prebuilt";
117125

118126
// Create client and connect to server
119127
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+
},
133172
},
134173
});
135174

@@ -148,18 +187,176 @@ const agent = createReactAgent({
148187
});
149188

150189
// 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+
}
157202

158203
await client.close();
159204
```
160205

161206
For more detailed examples, see the [examples](./examples) directory.
162207

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+
163360
## Browser Environments
164361

165362
When using in browsers:

0 commit comments

Comments
 (0)