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 { executeGitHubAgentAction, GitHubAgentAction } from './runtime.js'; const server = new Server( { name: 'sin-github-issues', version: '2026.03.22' }, { capabilities: { tools: {} } }, ); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'sin_github_health', description: 'Check 2026 Elite GitHub Operations Architect readiness.', inputSchema: { type: 'object', properties: {} }, }, { name: 'sin_github_app_routing_status', description: 'Inspect per-agent GitHub App routing config without exposing secrets.', inputSchema: { type: 'object', properties: {} }, }, { name: 'sin_github_webhook_route', description: 'Resolve a GitHub webhook payload to the correct specialized SIN coder app using installation.app_id and routing config.', inputSchema: { type: 'object', properties: { payload: {}, rawBody: { type: 'string' }, routePath: { type: 'string' }, signature256: { type: 'string' }, eventName: { type: 'string' }, deliveryId: { type: 'string' }, }, }, }, { name: 'sin_github_issue_comment_as_app', description: 'Post an issue or PR comment as the correct GitHub App identity using a JWT + installation token flow.', inputSchema: { type: 'object', properties: { repo: { type: 'string' }, issueNumber: { type: 'number' }, body: { type: 'string' }, agentSlug: { type: 'string' }, appId: { type: 'number' }, installationId: { type: 'number' }, }, required: ['repo', 'issueNumber', 'body', 'installationId'], }, }, { name: 'sin_github_project_orchestrate', description: 'Create and manage GitHub Projects V2 boards.', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, contextDir: { type: 'string' }, }, required: ['prompt'], }, }, { name: 'sin_github_issue_manage', description: 'Create, update, or close issues (Epics, Sub-tasks).', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, issueNumber: { type: 'number' }, }, required: ['prompt'], }, }, { name: 'sin_github_wiki_sync', description: 'Update the repository Wiki with project documentation.', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, contextDir: { type: 'string' }, }, required: ['prompt'], }, }, { name: 'sin_github_discussion_start', description: 'Start an architectural debate in Discussions.', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, category: { type: 'string' }, }, required: ['prompt'], }, }, { name: 'sin_github_gist_publish', description: 'Upload a large log or code snippet to a Gist.', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, isPublic: { type: 'boolean' }, }, required: ['prompt'], }, }, { name: 'sin_github_security_audit', description: 'Audit security alerts and configure Dependabot/CodeQL.', inputSchema: { type: 'object', properties: { prompt: { type: 'string' }, contextDir: { type: 'string' }, }, required: ['prompt'], }, }, { name: 'sin_github_pr_review', description: 'Review and approve/merge Pull Requests.', inputSchema: { type: 'object', properties: { prNumber: { type: 'number' }, contextDir: { type: 'string' }, }, required: ['prNumber'], }, }, { name: 'sin_github_issue_pool_enqueue', description: 'Insert an issue into the Hermes issue pool for Team-Coding dispatch.', inputSchema: { type: 'object', properties: { repoName: { type: 'string' }, issueNumber: { type: 'number' }, title: { type: 'string' }, body: { type: 'string' }, labels: { type: 'array', items: { type: 'string' } }, issueUrl: { type: 'string' }, assignedTeam: { type: 'string' }, assignedAgent: { type: 'string' }, status: { type: 'string' }, state: { type: 'string' }, routingStrategy: { type: 'string' }, fanoutPlan: { type: 'array', items: {} }, }, required: ['repoName', 'issueNumber', 'title'], }, }, { name: 'sin_github_ledger_log', description: 'Publish an agent activity log or achievement to the public OpenSIN-Ledger showcase repository.', inputSchema: { type: 'object', properties: { agentName: { type: 'string', description: 'Name of the agent logging the activity' }, activityTitle: { type: 'string', description: 'Short title of the achievement or task' }, details: { type: 'string', description: 'Detailed markdown describing what was accomplished' }, }, required: ['agentName', 'activityTitle', 'details'], }, }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { try { let action: GitHubAgentAction; const args = request.params.arguments as any; switch (request.params.name) { case 'sin_github_health': action = { action: 'sin.github.health' }; break; case 'sin_github_app_routing_status': action = { action: 'sin.github.app.routing.status' }; break; case 'sin_github_webhook_route': action = { action: 'sin.github.webhook.route', payload: args.payload, rawBody: args.rawBody, routePath: args.routePath, signature256: args.signature256, eventName: args.eventName, deliveryId: args.deliveryId, }; break; case 'sin_github_issue_comment_as_app': action = { action: 'sin.github.issue.comment.as_app', repo: args.repo, issueNumber: args.issueNumber, body: args.body, agentSlug: args.agentSlug, appId: args.appId, installationId: args.installationId, }; break; case 'sin_github_project_orchestrate': action = { action: 'sin.github.project.orchestrate', prompt: args.prompt, contextDir: args.contextDir }; break; case 'sin_github_issue_manage': action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber }; break; case 'sin_github_wiki_sync': action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir }; break; case 'sin_github_discussion_start': action = { action: 'sin.github.discussion.start', prompt: args.prompt, category: args.category }; break; case 'sin_github_gist_publish': action = { action: 'sin.github.gist.publish', prompt: args.prompt, isPublic: args.isPublic }; break; case 'sin_github_security_audit': action = { action: 'sin.github.security.audit', prompt: args.prompt, contextDir: args.contextDir }; break; case 'sin_github_pr_review': action = { action: 'sin.github.pr.review', prNumber: args.prNumber, contextDir: args.contextDir }; break; case 'sin_github_issue_pool_enqueue': action = { action: 'sin.github.issue.pool.enqueue', repoName: args.repoName, issueNumber: args.issueNumber, title: args.title, body: args.body, labels: args.labels, issueUrl: args.issueUrl, assignedTeam: args.assignedTeam, assignedAgent: args.assignedAgent, status: args.status, state: args.state, routingStrategy: args.routingStrategy, fanoutPlan: args.fanoutPlan, }; break; case 'sin_github_ledger_log': action = { action: 'sin.github.ledger.log', agentName: args.agentName, activityTitle: args.activityTitle, details: args.details }; break; default: throw new Error(`Unknown tool: ${request.params.name}`); } const result = await executeGitHubAgentAction(action); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } catch (error: any) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true, }; } }); export async function runMcpServer() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('A2A-SIN-GitHub-Issues MCP Server running on stdio'); }