Spaces:
Sleeping
Sleeping
| 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'); | |
| } | |