#!/usr/bin/env node /** * CTP MCP Server * * Model Context Protocol server for generating ConveniencePro Tool Protocol tools. * Provides AI-powered tool scaffolding and code generation. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { createTool } from './tools/create-tool.js'; import { validateTool } from './tools/validate-tool.js'; import { generateImplementation } from './tools/generate-implementation.js'; import { generateTests } from './tools/generate-tests.js'; import { searchDuplicates } from './tools/search-duplicates.js'; // MCP Server instance const server = new Server( { name: '@conveniencepro/ctp-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'ctp_create_tool', description: 'Generate a complete CTP tool from a natural language description. Creates tool definition, implementation, and tests.', inputSchema: { type: 'object', properties: { description: { type: 'string', description: 'Natural language description of what the tool should do', }, name: { type: 'string', description: 'Tool name (optional - will be auto-generated if not provided)', }, category: { type: 'string', description: 'Tool category (e.g., "converters", "calculators", "generators")', }, executionMode: { type: 'string', enum: ['client', 'server', 'both'], description: 'Where the tool should execute (default: client)', }, }, required: ['description'], }, }, { name: 'ctp_validate_tool', description: 'Validate a tool definition against the CTP specification', inputSchema: { type: 'object', properties: { definition: { type: 'object', description: 'The tool definition to validate', }, }, required: ['definition'], }, }, { name: 'ctp_generate_implementation', description: 'Generate implementation code from a tool definition', inputSchema: { type: 'object', properties: { definition: { type: 'object', description: 'The tool definition', }, executionMode: { type: 'string', enum: ['client', 'server', 'both'], description: 'Execution mode (default: client)', }, }, required: ['definition'], }, }, { name: 'ctp_generate_tests', description: 'Generate test suite for a CTP tool', inputSchema: { type: 'object', properties: { definition: { type: 'object', description: 'The tool definition', }, implementation: { type: 'string', description: 'The tool implementation code', }, }, required: ['definition'], }, }, { name: 'ctp_search_duplicates', description: 'Search for existing tools with similar functionality', inputSchema: { type: 'object', properties: { description: { type: 'string', description: 'Description of the tool to search for', }, category: { type: 'string', description: 'Optional category to narrow search', }, }, required: ['description'], }, }, ], }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { if (!args) { throw new Error('Missing arguments'); } switch (name) { case 'ctp_create_tool': return await createTool(args as never); case 'ctp_validate_tool': return await validateTool(args as never); case 'ctp_generate_implementation': return await generateImplementation(args as never); case 'ctp_generate_tests': return await generateTests(args as never); case 'ctp_search_duplicates': return await searchDuplicates(args as never); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; return { content: [ { type: 'text', text: JSON.stringify({ success: false, error: message, }, null, 2), }, ], }; } }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('CTP MCP Server running on stdio'); } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });