#!/usr/bin/env node /** * A2P AutoPilot MCP Server * Provides rich UI tools for A2P registration management via Claude Desktop */ 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 { allTools } from './src/tools.js'; import { handleRegistrationWizard, handleDashboard, handleViewSubmission, handlePreviewLanding, handleSubmitRegistration, handleRetrySubmission, handleCancelSubmission, handleCheckStatus, handleGetStats } from './src/handlers.js'; import { appResources, loadResourceContent, getResourceList } from './src/resources.js'; // ============================================================ // SERVER SETUP // ============================================================ const server = new Server( { name: 'a2p-autopilot-mcp', version: '1.0.0' }, { capabilities: { resources: {}, tools: {} } } ); // ============================================================ // TOOL HANDLERS // ============================================================ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: allTools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, ...(tool._meta && { _meta: tool._meta }) })) }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { // Model + App visible tools (show UI) case 'a2p_registration_wizard': return await handleRegistrationWizard(args as any); case 'a2p_dashboard': return await handleDashboard(args as any); case 'a2p_view_submission': return await handleViewSubmission(args as any); case 'a2p_preview_landing': return await handlePreviewLanding(args as any); // App-only tools (backend operations) case 'a2p_submit_registration': return await handleSubmitRegistration(args as any); case 'a2p_retry_submission': return await handleRetrySubmission(args as any); case 'a2p_cancel_submission': return await handleCancelSubmission(args as any); case 'a2p_check_status': return await handleCheckStatus(args as any); case 'a2p_get_stats': return await handleGetStats(); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { content: [ { type: 'text', text: `Error: ${errorMessage}` } ], isError: true }; } }); // ============================================================ // RESOURCE HANDLERS // ============================================================ server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: getResourceList() }; }); server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; const resource = appResources.find(r => r.uri === uri); if (!resource) { throw new Error(`Resource not found: ${uri}`); } const content = loadResourceContent(resource); return { contents: [ { uri, mimeType: resource.mimeType, text: content } ] }; }); // ============================================================ // SERVER START // ============================================================ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('A2P AutoPilot MCP Server running on stdio'); console.error('Tools registered:', allTools.length); console.error('Resources registered:', appResources.length); } main().catch((error) => { console.error('Server error:', error); process.exit(1); });