index.js•6.11 kB
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
// 導入工具模組
import { fileTools } from './tools/fileTools.js';
import { calculatorTools } from './tools/calculatorTools.js';
import { systemTools } from './tools/systemTools.js';
class MCPServer {
server;
constructor() {
this.server = new Server({
name: 'nodejs-mcp-server',
version: '1.0.0',
description: 'A comprehensive MCP server built with Node.js and TypeScript',
}, {
capabilities: {
tools: {},
resources: {},
},
});
this.setupToolHandlers();
this.setupResourceHandlers();
}
setupToolHandlers() {
// 註冊工具列表處理器
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
...fileTools.getToolDefinitions(),
...calculatorTools.getToolDefinitions(),
...systemTools.getToolDefinitions(),
],
};
});
// 註冊工具調用處理器
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
// 根據工具名稱路由到相應的處理器
let result;
if (fileTools.hasToolName(name)) {
result = await fileTools.handleToolCall(name, args || {});
}
else if (calculatorTools.hasToolName(name)) {
result = await calculatorTools.handleToolCall(name, args || {});
}
else if (systemTools.hasToolName(name)) {
result = await systemTools.handleToolCall(name, args || {});
}
else {
throw new Error(`Unknown tool: ${name}`);
}
return {
content: result.content,
isError: result.isError || false,
};
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
});
}
setupResourceHandlers() {
// 註冊資源列表處理器
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: 'mcp://server-info',
mimeType: 'application/json',
name: 'Server Information',
description: 'Information about this MCP server',
},
{
uri: 'mcp://available-tools',
mimeType: 'application/json',
name: 'Available Tools',
description: 'List of all available tools and their descriptions',
},
],
};
});
// 註冊資源讀取處理器
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
switch (uri) {
case 'mcp://server-info':
return {
contents: [
{
uri,
mimeType: 'application/json',
text: JSON.stringify({
name: 'nodejs-mcp-server',
version: '1.0.0',
description: 'A comprehensive MCP server built with Node.js and TypeScript',
capabilities: ['tools', 'resources'],
toolCategories: ['file-operations', 'calculations', 'system-info'],
}, null, 2),
},
],
};
case 'mcp://available-tools':
const allTools = [
...fileTools.getToolDefinitions(),
...calculatorTools.getToolDefinitions(),
...systemTools.getToolDefinitions(),
];
return {
contents: [
{
uri,
mimeType: 'application/json',
text: JSON.stringify({ tools: allTools }, null, 2),
},
],
};
default:
throw new Error(`Unknown resource: ${uri}`);
}
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('MCP Server running on stdio');
}
}
// 啟動服務器
async function main() {
const server = new MCPServer();
await server.run();
}
// 處理未捕獲的錯誤
process.on('SIGINT', async () => {
console.error('Received SIGINT, shutting down gracefully...');
process.exit(0);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
main().catch((error) => {
console.error('Failed to start server:', error);
process.exit(1);
});