166 lines
4.1 KiB
JavaScript

#!/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);
});