Skip to content

Commit 668a7ab

Browse files
authored
Merge pull request #107 from QuantGeekDev/feature/readme
Feature/readme
2 parents 5b3208f + 484e3db commit 668a7ab

File tree

4 files changed

+191
-183
lines changed

4 files changed

+191
-183
lines changed

README.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,26 @@ mcp add resource market-data
156156
3. **Define your tool schemas with automatic validation:**
157157
```typescript
158158
// tools/DataFetcher.ts
159-
import { MCPTool, McpInput } from "mcp-framework";
160-
import { z } from "zod";
161-
162-
const DataFetcherSchema = z.object({
163-
// all fields should have .describe()
164-
url: z.string().url().describe("URL to fetch data from"),
165-
timeout: z.number().positive().default(5000).describe("Request timeout in milliseconds").optional()
166-
});
167-
168-
class DataFetcher extends MCPTool {
169-
name = "data_fetcher";
170-
description = "Fetch data from external APIs";
171-
schema = DataFetcherSchema;
172-
173-
async execute(input: McpInput<this>) {
174-
// Fully typed input with autocomplete support
175-
const { url, timeout = 5000 } = input;
176-
// ... implementation
177-
}
178-
}
159+
import { MCPTool, MCPInput as AddToolInput } from "mcp-framework";
160+
import { z } from "zod";
161+
162+
const AddToolSchema = z.object({
163+
a: z.number().describe("First number to add"),
164+
b: z.number().describe("Second number to add"),
165+
});
166+
167+
class AddTool extends MCPTool {
168+
name = "add";
169+
description = "Add tool description";
170+
schema = AddToolSchema;
171+
172+
async execute(input: AddToolInput<this>) {
173+
const result = input.a + input.b;
174+
return `Result: ${result}`;
175+
}
176+
}
177+
export default AddTool;
178+
179179
```
180180
181181
4. **Build with automatic validation:**

src/core/MCPServer.ts

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ export interface MCPServerConfig {
4747

4848
export type ServerCapabilities = {
4949
tools?: {
50-
listChanged?: true; // Optional: Indicates support for list change notifications
50+
listChanged?: true;
5151
};
5252
prompts?: {
53-
listChanged?: true; // Optional: Indicates support for list change notifications
53+
listChanged?: true;
5454
};
5555
resources?: {
56-
listChanged?: true; // Optional: Indicates support for list change notifications
57-
subscribe?: true; // Optional: Indicates support for resource subscriptions
56+
listChanged?: true;
57+
subscribe?: true;
5858
};
5959
};
6060

@@ -137,6 +137,54 @@ export class MCPServer {
137137
};
138138
logger.debug(`Creating HttpStreamTransport. response mode: ${httpConfig.responseMode}`);
139139
transport = new HttpStreamTransport(httpConfig);
140+
141+
const serverConfig = {
142+
name: this.serverName,
143+
version: this.serverVersion,
144+
};
145+
146+
const setupCallback = async (server: any) => {
147+
for (const [name, tool] of this.toolsMap.entries()) {
148+
let zodSchema: any;
149+
if ((tool as any).schema && typeof (tool as any).schema === 'object') {
150+
zodSchema = (tool as any).schema;
151+
} else {
152+
zodSchema = {};
153+
}
154+
155+
server.tool(name, zodSchema, async (input: any) => {
156+
try {
157+
logger.debug(`Executing tool ${name} with input: ${JSON.stringify(input)}`);
158+
const result = await (tool as any).execute(input);
159+
160+
if (result && typeof result === 'object' && 'content' in result) {
161+
return result;
162+
} else {
163+
return {
164+
content: [
165+
{
166+
type: 'text',
167+
text: typeof result === 'string' ? result : JSON.stringify(result),
168+
},
169+
],
170+
};
171+
}
172+
} catch (error) {
173+
logger.error(`Tool execution failed for ${name}: ${error}`);
174+
return {
175+
content: [
176+
{
177+
type: 'text',
178+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
179+
},
180+
],
181+
};
182+
}
183+
});
184+
}
185+
};
186+
187+
(transport as HttpStreamTransport).setServerConfig(serverConfig, setupCallback);
140188
break;
141189
}
142190
case 'stdio':
@@ -214,7 +262,6 @@ export class MCPServer {
214262
private setupHandlers(server?: Server) {
215263
const targetServer = server || this.server;
216264

217-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
218265
targetServer.setRequestHandler(ListToolsRequestSchema, async (request: any) => {
219266
logger.debug(`Received ListTools request: ${JSON.stringify(request)}`);
220267

@@ -232,7 +279,6 @@ export class MCPServer {
232279
return response;
233280
});
234281

235-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
236282
targetServer.setRequestHandler(CallToolRequestSchema, async (request: any) => {
237283
logger.debug(`Tool call request received for: ${request.params.name}`);
238284
logger.debug(`Tool call arguments: ${JSON.stringify(request.params.arguments)}`);
@@ -269,7 +315,6 @@ export class MCPServer {
269315
};
270316
});
271317

272-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
273318
targetServer.setRequestHandler(GetPromptRequestSchema, async (request: any) => {
274319
const prompt = this.promptsMap.get(request.params.name);
275320
if (!prompt) {
@@ -295,7 +340,6 @@ export class MCPServer {
295340
};
296341
});
297342

298-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
299343
targetServer.setRequestHandler(ReadResourceRequestSchema, async (request: any) => {
300344
const resource = this.resourcesMap.get(request.params.uri);
301345
if (!resource) {
@@ -321,7 +365,6 @@ export class MCPServer {
321365
return response;
322366
});
323367

324-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
325368
targetServer.setRequestHandler(SubscribeRequestSchema, async (request: any) => {
326369
const resource = this.resourcesMap.get(request.params.uri);
327370
if (!resource) {
@@ -336,7 +379,6 @@ export class MCPServer {
336379
return {};
337380
});
338381

339-
// TODO: Replace 'any' with the specific inferred request type from the SDK schema if available
340382
targetServer.setRequestHandler(UnsubscribeRequestSchema, async (request: any) => {
341383
const resource = this.resourcesMap.get(request.params.uri);
342384
if (!resource) {
@@ -410,11 +452,9 @@ export class MCPServer {
410452
const sdkVersion = this.getSdkVersion();
411453
logger.info(`Starting MCP server: (Framework: ${frameworkVersion}, SDK: ${sdkVersion})...`);
412454

413-
// Load all tools, prompts, and resources first
414455
const tools = await this.toolLoader.loadTools();
415456
this.toolsMap = new Map(tools.map((tool: ToolProtocol) => [tool.name, tool]));
416457

417-
// Validate all tools
418458
for (const tool of tools) {
419459
if ('validate' in tool && typeof tool.validate === 'function') {
420460
try {

0 commit comments

Comments
 (0)