Skip to content

Commit c915fee

Browse files
committed
refactor: Use official @modelcontextprotocol/sdk package
1 parent 8ec9619 commit c915fee

File tree

6 files changed

+154
-45
lines changed

6 files changed

+154
-45
lines changed

packages/agent/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"license": "MIT",
4646
"dependencies": {
4747
"@anthropic-ai/sdk": "^0.37",
48+
"@modelcontextprotocol/sdk": "^1.7.0",
4849
"@mozilla/readability": "^0.5.0",
4950
"@playwright/test": "^1.50.1",
5051
"@vitest/browser": "^3.0.5",

packages/agent/src/core/executeToolCall.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,12 @@ export const executeToolCall = async (
110110
}
111111
}
112112

113-
const toolOutput =
114-
typeof output === 'string' ? output : JSON.stringify(output, null, 2);
115-
return toolOutput.length > OUTPUT_LIMIT
116-
? `${toolOutput.slice(0, OUTPUT_LIMIT)}...(truncated)`
117-
: toolOutput;
113+
const outputIsString = typeof output === 'string';
114+
if (outputIsString) {
115+
return output.length > OUTPUT_LIMIT
116+
? `${output.slice(0, OUTPUT_LIMIT)}...(truncated)`
117+
: output;
118+
} else {
119+
return JSON.stringify(output, null, 2);
120+
}
118121
};
Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
/**
22
* Model Context Protocol (MCP) Integration
3-
*
3+
*
44
* This module provides integration with the Model Context Protocol (MCP),
55
* allowing MyCoder to use context from MCP-compatible servers.
6+
*
7+
* Uses the official MCP SDK: https://www.npmjs.com/package/@modelcontextprotocol/sdk
68
*/
79

8-
export * from './client';
9-
export * from './types';
10+
import * as MCP from '@modelcontextprotocol/sdk';
11+
12+
export { MCP };
13+
14+
/**
15+
* Configuration for MCP in mycoder.config.js
16+
*/
17+
export interface McpConfig {
18+
/** Array of MCP server configurations */
19+
servers?: McpServerConfig[];
20+
/** Default resources to load automatically */
21+
defaultResources?: string[];
22+
}
23+
24+
/**
25+
* Configuration for an MCP server
26+
*/
27+
export interface McpServerConfig {
28+
/** Unique name for this MCP server */
29+
name: string;
30+
/** URL of the MCP server */
31+
url: string;
32+
/** Optional authentication configuration */
33+
auth?: {
34+
/** Authentication type (currently only 'bearer' is supported) */
35+
type: 'bearer';
36+
/** Authentication token */
37+
token: string;
38+
};
39+
}

packages/agent/src/core/toolAgent/toolExecutor.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ import { Tool, ToolCall, ToolContext } from '../types.js';
66
import { addToolResultToMessages } from './messageUtils.js';
77
import { ToolCallResult } from './types.js';
88

9-
const safeParse = (value: string) => {
9+
const safeParse = (value: string, context: Record<string, string>) => {
1010
try {
1111
return JSON.parse(value);
1212
} catch (error) {
13-
console.error('Error parsing JSON:', error, 'original value:', value);
13+
console.error(
14+
'Error parsing JSON:',
15+
error,
16+
'original value:',
17+
value,
18+
'context',
19+
JSON.stringify(context),
20+
);
1421
return { error: value };
1522
}
1623
};
@@ -77,7 +84,7 @@ export async function executeTools(
7784
}
7885
}
7986

80-
const parsedResult = safeParse(toolResult);
87+
const parsedResult = safeParse(toolResult, { tool: call.name });
8188

8289
// Add the tool result to messages
8390
addToolResultToMessages(messages, call.id, parsedResult, isError);

packages/agent/src/tools/mcp.ts

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
*
44
* This tool allows the agent to interact with Model Context Protocol (MCP) servers
55
* to retrieve resources and use tools provided by those servers.
6+
*
7+
* Uses the official MCP SDK: https://www.npmjs.com/package/@modelcontextprotocol/sdk
68
*/
79

8-
import { McpClient } from '../core/mcp/client';
9-
import { McpConfig, McpResource } from '../core/mcp/types';
10+
import { MCP, McpConfig, McpServerConfig } from '../core/mcp';
1011
import { Tool } from './tool';
1112
import { ToolContext } from './types';
1213

@@ -30,7 +31,7 @@ interface GetResourceParams {
3031
* MCP Tool for interacting with MCP servers
3132
*/
3233
export class McpTool extends Tool {
33-
private client: McpClient;
34+
private clients: Map<string, MCP.Client> = new Map();
3435

3536
/**
3637
* Create a new MCP tool
@@ -64,28 +65,72 @@ export class McpTool extends Tool {
6465
},
6566
});
6667

67-
// Initialize the MCP client with configured servers
68-
this.client = new McpClient(config.servers || []);
68+
// Initialize MCP clients for each configured server
69+
this.initializeClients();
70+
}
71+
72+
/**
73+
* Initialize MCP clients for each configured server
74+
*/
75+
private initializeClients(): void {
76+
if (!this.config.servers || this.config.servers.length === 0) {
77+
return;
78+
}
79+
80+
for (const server of this.config.servers) {
81+
try {
82+
const clientOptions: MCP.ClientOptions = {
83+
baseURL: server.url,
84+
};
85+
86+
// Add authentication if configured
87+
if (server.auth && server.auth.type === 'bearer') {
88+
clientOptions.headers = {
89+
Authorization: `Bearer ${server.auth.token}`,
90+
};
91+
}
92+
93+
const client = new MCP.Client(clientOptions);
94+
this.clients.set(server.name, client);
95+
} catch (error) {
96+
console.error(`Failed to initialize MCP client for server ${server.name}:`, error);
97+
}
98+
}
6999
}
70100

71101
/**
72102
* List available resources from MCP servers
73103
* @param params Optional parameters
74-
* @param context Tool context
104+
* @param _context Tool context
75105
* @returns List of available resources
76106
*/
77107
async listResources(
78108
params: ListResourcesParams = {},
79109
_context: ToolContext,
80-
): Promise<McpResource[]> {
81-
const resources = await this.client.getAvailableResources();
110+
): Promise<MCP.Resource[]> {
111+
const resources: MCP.Resource[] = [];
82112

83-
// Filter by server if specified
113+
// If a specific server is requested, only check that server
84114
if (params.server) {
85-
return resources.filter(resource => {
86-
// Simple implementation - in a real implementation, this would be more sophisticated
87-
return resource.uri.startsWith(`${params.server}://`);
88-
});
115+
const client = this.clients.get(params.server);
116+
if (client) {
117+
try {
118+
const serverResources = await client.resources();
119+
resources.push(...serverResources);
120+
} catch (error) {
121+
console.error(`Failed to fetch resources from server ${params.server}:`, error);
122+
}
123+
}
124+
} else {
125+
// Otherwise, check all servers
126+
for (const [serverName, client] of this.clients.entries()) {
127+
try {
128+
const serverResources = await client.resources();
129+
resources.push(...serverResources);
130+
} catch (error) {
131+
console.error(`Failed to fetch resources from server ${serverName}:`, error);
132+
}
133+
}
89134
}
90135

91136
return resources;
@@ -94,13 +139,38 @@ export class McpTool extends Tool {
94139
/**
95140
* Fetch a resource from an MCP server
96141
* @param params Parameters
97-
* @param context Tool context
142+
* @param _context Tool context
98143
* @returns The resource content
99144
*/
100145
async getResource(
101146
params: GetResourceParams,
102147
_context: ToolContext,
103148
): Promise<string> {
104-
return await this.client.fetchResource(params.uri);
149+
// Parse the URI to determine which server to use
150+
const serverName = this.getServerNameFromUri(params.uri);
151+
if (!serverName) {
152+
throw new Error(`Could not determine server from URI: ${params.uri}`);
153+
}
154+
155+
const client = this.clients.get(serverName);
156+
if (!client) {
157+
throw new Error(`Server not found: ${serverName}`);
158+
}
159+
160+
// Use the MCP SDK to fetch the resource
161+
const resource = await client.resource(params.uri);
162+
return resource.content;
163+
}
164+
165+
/**
166+
* Extract the server name from a resource URI
167+
* @param uri Resource URI in the format 'scheme://path'
168+
* @returns The server name or undefined if not found
169+
* @private
170+
*/
171+
private getServerNameFromUri(uri: string): string | undefined {
172+
// For simplicity, we'll use the first part of the URI as the server name
173+
const match = uri.match(/^([^:]+):\/\//);
174+
return match ? match[1] : undefined;
105175
}
106176
}

packages/cli/README.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export default {
119119
customPrompt: '',
120120
profile: false,
121121
tokenCache: true,
122-
122+
123123
// MCP configuration
124124
mcp: {
125125
servers: [
@@ -128,14 +128,12 @@ export default {
128128
url: 'https://mcp.example.com',
129129
auth: {
130130
type: 'bearer',
131-
token: 'your-token-here'
132-
}
133-
}
131+
token: 'your-token-here',
132+
},
133+
},
134134
],
135-
defaultResources: [
136-
'example://docs/api'
137-
]
138-
}
135+
defaultResources: ['example://docs/api'],
136+
},
139137
};
140138
```
141139

@@ -180,13 +178,15 @@ export default {
180178

181179
### Model Context Protocol (MCP) Configuration
182180

183-
MyCoder supports the Model Context Protocol (MCP), which allows the agent to access external context sources and tools. To configure MCP support, add an `mcp` section to your `mycoder.config.js` file:
181+
MyCoder supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io), which allows the agent to access external context sources and tools. MyCoder uses the official [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk) package for MCP integration.
182+
183+
To configure MCP support, add an `mcp` section to your `mycoder.config.js` file:
184184

185185
```javascript
186186
// mycoder.config.js
187187
export default {
188188
// Other configuration...
189-
189+
190190
// MCP configuration
191191
mcp: {
192192
// MCP Servers to connect to
@@ -197,17 +197,15 @@ export default {
197197
// Optional authentication
198198
auth: {
199199
type: 'bearer',
200-
token: process.env.MCP_SERVER_TOKEN
201-
}
202-
}
200+
token: process.env.MCP_SERVER_TOKEN,
201+
},
202+
},
203203
],
204-
204+
205205
// Optional: Default context resources to load
206-
defaultResources: [
207-
'company-docs://api/reference'
208-
]
209-
}
210-
}
206+
defaultResources: ['company-docs://api/reference'],
207+
},
208+
};
211209
```
212210

213211
When MCP is configured, the agent will have access to a new `mcp` tool that allows it to:

0 commit comments

Comments
 (0)