delqhi/sin-github-issues
0
1import { Server } from '@modelcontextprotocol/sdk/server/index.js';2import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';3import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';4import { executeGitHubAgentAction, GitHubAgentAction } from './runtime.js';5 6const server = new Server(7 { name: 'sin-github-issues', version: '2026.03.22' },8 { capabilities: { tools: {} } },9);10 11server.setRequestHandler(ListToolsRequestSchema, async () => {12 return {13 tools: [14 {15 name: 'sin_github_health',16 description: 'Check 2026 Elite GitHub Operations Architect readiness.',17 inputSchema: { type: 'object', properties: {} },18 },19 {20 name: 'sin_github_app_routing_status',21 description: 'Inspect per-agent GitHub App routing config without exposing secrets.',22 inputSchema: { type: 'object', properties: {} },23 },24 {25 name: 'sin_github_webhook_route',26 description: 'Resolve a GitHub webhook payload to the correct specialized SIN coder app using installation.app_id and routing config.',27 inputSchema: {28 type: 'object',29 properties: {30 payload: {},31 rawBody: { type: 'string' },32 routePath: { type: 'string' },33 signature256: { type: 'string' },34 eventName: { type: 'string' },35 deliveryId: { type: 'string' },36 },37 },38 },39 {40 name: 'sin_github_issue_comment_as_app',41 description: 'Post an issue or PR comment as the correct GitHub App identity using a JWT + installation token flow.',42 inputSchema: {43 type: 'object',44 properties: {45 repo: { type: 'string' },46 issueNumber: { type: 'number' },47 body: { type: 'string' },48 agentSlug: { type: 'string' },49 appId: { type: 'number' },50 installationId: { type: 'number' },51 },52 required: ['repo', 'issueNumber', 'body', 'installationId'],53 },54 },55 {56 name: 'sin_github_project_orchestrate',57 description: 'Create and manage GitHub Projects V2 boards.',58 inputSchema: {59 type: 'object',60 properties: {61 prompt: { type: 'string' },62 contextDir: { type: 'string' },63 },64 required: ['prompt'],65 },66 },67 {68 name: 'sin_github_issue_manage',69 description: 'Create, update, or close issues (Epics, Sub-tasks).',70 inputSchema: {71 type: 'object',72 properties: {73 prompt: { type: 'string' },74 issueNumber: { type: 'number' },75 },76 required: ['prompt'],77 },78 },79 {80 name: 'sin_github_wiki_sync',81 description: 'Update the repository Wiki with project documentation.',82 inputSchema: {83 type: 'object',84 properties: {85 prompt: { type: 'string' },86 contextDir: { type: 'string' },87 },88 required: ['prompt'],89 },90 },91 {92 name: 'sin_github_discussion_start',93 description: 'Start an architectural debate in Discussions.',94 inputSchema: {95 type: 'object',96 properties: {97 prompt: { type: 'string' },98 category: { type: 'string' },99 },100 required: ['prompt'],101 },102 },103 {104 name: 'sin_github_gist_publish',105 description: 'Upload a large log or code snippet to a Gist.',106 inputSchema: {107 type: 'object',108 properties: {109 prompt: { type: 'string' },110 isPublic: { type: 'boolean' },111 },112 required: ['prompt'],113 },114 },115 {116 name: 'sin_github_security_audit',117 description: 'Audit security alerts and configure Dependabot/CodeQL.',118 inputSchema: {119 type: 'object',120 properties: {121 prompt: { type: 'string' },122 contextDir: { type: 'string' },123 },124 required: ['prompt'],125 },126 },127 {128 name: 'sin_github_pr_review',129 description: 'Review and approve/merge Pull Requests.',130 inputSchema: {131 type: 'object',132 properties: {133 prNumber: { type: 'number' },134 contextDir: { type: 'string' },135 },136 required: ['prNumber'],137 },138 },139 {140 name: 'sin_github_issue_pool_enqueue',141 description: 'Insert an issue into the Hermes issue pool for Team-Coding dispatch.',142 inputSchema: {143 type: 'object',144 properties: {145 repoName: { type: 'string' },146 issueNumber: { type: 'number' },147 title: { type: 'string' },148 body: { type: 'string' },149 labels: { type: 'array', items: { type: 'string' } },150 issueUrl: { type: 'string' },151 assignedTeam: { type: 'string' },152 assignedAgent: { type: 'string' },153 status: { type: 'string' },154 state: { type: 'string' },155 routingStrategy: { type: 'string' },156 fanoutPlan: { type: 'array', items: {} },157 },158 required: ['repoName', 'issueNumber', 'title'],159 },160 },161 {162 name: 'sin_github_ledger_log',163 description: 'Publish an agent activity log or achievement to the public OpenSIN-Ledger showcase repository.',164 inputSchema: {165 type: 'object',166 properties: {167 agentName: { type: 'string', description: 'Name of the agent logging the activity' },168 activityTitle: { type: 'string', description: 'Short title of the achievement or task' },169 details: { type: 'string', description: 'Detailed markdown describing what was accomplished' },170 },171 required: ['agentName', 'activityTitle', 'details'],172 },173 },174 ],175 };176});177 178server.setRequestHandler(CallToolRequestSchema, async (request) => {179 try {180 let action: GitHubAgentAction;181 const args = request.params.arguments as any;182 183 switch (request.params.name) {184 case 'sin_github_health':185 action = { action: 'sin.github.health' };186 break;187 case 'sin_github_app_routing_status':188 action = { action: 'sin.github.app.routing.status' };189 break;190 case 'sin_github_webhook_route':191 action = {192 action: 'sin.github.webhook.route',193 payload: args.payload,194 rawBody: args.rawBody,195 routePath: args.routePath,196 signature256: args.signature256,197 eventName: args.eventName,198 deliveryId: args.deliveryId,199 };200 break;201 case 'sin_github_issue_comment_as_app':202 action = {203 action: 'sin.github.issue.comment.as_app',204 repo: args.repo,205 issueNumber: args.issueNumber,206 body: args.body,207 agentSlug: args.agentSlug,208 appId: args.appId,209 installationId: args.installationId,210 };211 break;212 case 'sin_github_project_orchestrate':213 action = { action: 'sin.github.project.orchestrate', prompt: args.prompt, contextDir: args.contextDir };214 break;215 case 'sin_github_issue_manage':216 action = { action: 'sin.github.issue.manage', prompt: args.prompt, issueNumber: args.issueNumber };217 break;218 case 'sin_github_wiki_sync':219 action = { action: 'sin.github.wiki.sync', prompt: args.prompt, contextDir: args.contextDir };220 break;221 case 'sin_github_discussion_start':222 action = { action: 'sin.github.discussion.start', prompt: args.prompt, category: args.category };223 break;224 case 'sin_github_gist_publish':225 action = { action: 'sin.github.gist.publish', prompt: args.prompt, isPublic: args.isPublic };226 break;227 case 'sin_github_security_audit':228 action = { action: 'sin.github.security.audit', prompt: args.prompt, contextDir: args.contextDir };229 break;230 case 'sin_github_pr_review':231 action = { action: 'sin.github.pr.review', prNumber: args.prNumber, contextDir: args.contextDir };232 break;233 case 'sin_github_issue_pool_enqueue':234 action = {235 action: 'sin.github.issue.pool.enqueue',236 repoName: args.repoName,237 issueNumber: args.issueNumber,238 title: args.title,239 body: args.body,240 labels: args.labels,241 issueUrl: args.issueUrl,242 assignedTeam: args.assignedTeam,243 assignedAgent: args.assignedAgent,244 status: args.status,245 state: args.state,246 routingStrategy: args.routingStrategy,247 fanoutPlan: args.fanoutPlan,248 };249 break;250 case 'sin_github_ledger_log':251 action = { action: 'sin.github.ledger.log', agentName: args.agentName, activityTitle: args.activityTitle, details: args.details };252 break;253 default:254 throw new Error(`Unknown tool: ${request.params.name}`);255 }256 257 const result = await executeGitHubAgentAction(action);258 return {259 content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],260 };261 } catch (error: any) {262 return {263 content: [{ type: 'text', text: `Error: ${error.message}` }],264 isError: true,265 };266 }267});268 269export async function runMcpServer() {270 const transport = new StdioServerTransport();271 await server.connect(transport);272 console.error('A2A-SIN-GitHub-Issues MCP Server running on stdio');273}274 