Toolkit MCP Server
by cyanheads
Verified
- src
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { systemTools } from './tools/system.js';
import { networkTools } from './tools/network.js';
import { geoTools } from './tools/geo.js';
import { generatorTools } from './tools/generator.js';
import { dateTimeTools } from './tools/datetime.js';
import { securityTools } from './tools/security.js';
import { McpToolError, handleToolError } from './utils/errors.js';
import { RateLimiter, systemRateLimiter, networkRateLimiter, geoRateLimiter } from './utils/rate-limiter.js';
import { withProgress, ProgressReporter } from './utils/progress.js';
// Combine all tools
import { ToolKit, Tool } from './types.js';
// Update Tool interface to support progress reporting
declare module './types.js' {
interface Tool {
handler: (args: any, progress?: ProgressReporter) => Promise<{
content: Array<{ type: string; text: string }>;
isError?: boolean;
}>;
}
}
const allTools: ToolKit = {
...systemTools,
...networkTools,
...geoTools,
...generatorTools,
...dateTimeTools,
...securityTools
};
class ToolkitServer {
private server: Server;
private isShuttingDown: boolean = false;
constructor() {
this.server = new Server(
{
name: 'toolkit-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
progress: {}
}
}
);
this.setupHandlers();
this.setupErrorHandling();
this.setupCleanup();
}
private setupErrorHandling(): void {
this.server.onerror = (error) => {
console.error('[MCP Error]', error);
if (!this.isShuttingDown) {
// Attempt to notify clients of the error
this.server.notification({
method: 'notifications/server/error',
params: {
error: error instanceof Error ? error.message : 'Unknown error occurred'
}
}).catch(console.error);
}
};
}
private setupCleanup(): void {
const cleanup = async () => {
this.isShuttingDown = true;
console.log('Shutting down toolkit-mcp-server...');
try {
// Notify clients of shutdown
await this.server.notification({
method: 'notifications/server/shutdown',
params: {
reason: 'Server is shutting down'
}
});
// Close server connection
await this.server.close();
console.log('Server shutdown complete');
process.exit(0);
} catch (error) {
console.error('Error during shutdown:', error);
process.exit(1);
}
};
// Handle termination signals
process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);
process.on('uncaughtException', (error) => {
console.error('Uncaught exception:', error);
cleanup().catch(console.error);
});
}
private setupHandlers(): void {
// Handle tool listing
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
try {
return {
tools: Object.entries(allTools).map(([name, tool]) => ({
name,
description: tool.description,
inputSchema: tool.inputSchema
}))
};
} catch (error) {
throw new McpToolError(
ErrorCode.InternalError,
'Failed to list tools',
error instanceof Error ? error.message : undefined
);
}
});
// Handle tool execution
this.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
try {
const tool = allTools[request.params.name as keyof typeof allTools];
if (!tool) {
throw new McpToolError(
ErrorCode.MethodNotFound,
`Tool not found: ${request.params.name}`
);
}
// Get appropriate rate limiter based on tool category
let rateLimiter: RateLimiter;
if (request.params.name.startsWith('get_system')) {
rateLimiter = systemRateLimiter;
} else if (request.params.name.startsWith('get_network') ||
request.params.name === 'ping_host' ||
request.params.name === 'traceroute') {
rateLimiter = networkRateLimiter;
} else if (request.params.name === 'geolocate') {
rateLimiter = geoRateLimiter;
} else {
rateLimiter = systemRateLimiter; // default to system rate limiter
}
// Execute tool with rate limiting and progress reporting
const result = await rateLimiter.withRateLimit(request.params.name, async () => {
return await withProgress(
this.server,
{
title: `Executing ${request.params.name}`,
unit: 'operations'
},
async (progress) => {
const toolResult = await tool.handler(request.params.arguments, progress);
await progress.complete();
return toolResult;
}
);
});
// Convert ToolResponse to ServerResult format
return {
content: result.content,
_meta: result.isError ? { isError: true } : undefined
};
} catch (error) {
if (error instanceof McpToolError) {
throw error;
}
const errorResult = handleToolError(error);
return {
content: errorResult.content,
_meta: { isError: true }
};
}
});
}
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('Toolkit MCP server running on stdio');
// Handle process termination
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
await this.server.close();
process.exit(0);
});
}
}
// Start the server
const server = new ToolkitServer();
server.run().catch((error) => {
console.error('Failed to start server:', error);
process.exit(1);
});