Files
shockbot/mcp/server.ts
T
2025-10-08 14:07:28 -04:00

102 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
// Minimal GitHub Issue Comment MCP Server
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { Octokit } from "@octokit/rest";
import { type } from "arktype";
// Get repository information from environment variables
const REPO_OWNER = process.env.REPO_OWNER;
const REPO_NAME = process.env.REPO_NAME;
if (!REPO_OWNER || !REPO_NAME) {
console.error("Error: REPO_OWNER and REPO_NAME environment variables are required");
process.exit(1);
}
const server = new McpServer({
name: "Minimal GitHub Issue Comment Server",
version: "0.0.1",
});
// Define the schema for creating issue comments
const Comment = type({
issueNumber: type.number.describe("the issue number to comment on"),
body: type.string.describe("the comment body content"),
});
function annotations(t: type<Record<string, unknown>>): Record<string, unknown> {
return Object.fromEntries(t.props.map((prop) => [prop.key, prop.value.toJsonSchema()]));
}
server.tool(
"create_issue_comment",
"Create a comment on a GitHub issue",
annotations(Comment),
async ({ issueNumber, body }) => {
try {
// Validate input using arktype
const validation = Comment({ issueNumber, body });
if (validation instanceof type.errors) {
throw new Error(`Invalid input: ${validation.summary}`);
}
const githubToken = process.env.GITHUB_TOKEN;
if (!githubToken) {
throw new Error("GITHUB_TOKEN environment variable is required");
}
const octokit = new Octokit({
auth: githubToken,
});
const result = await octokit.rest.issues.createComment({
owner: REPO_OWNER,
repo: REPO_NAME,
issue_number: issueNumber,
body: body,
});
return {
content: [
{
type: "text",
text: JSON.stringify(
{
success: true,
commentId: result.data.id,
url: result.data.html_url,
body: result.data.body,
},
null,
2
),
},
],
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [
{
type: "text",
text: `Error creating comment: ${errorMessage}`,
},
],
error: errorMessage,
isError: true,
};
}
}
);
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
process.on("exit", () => {
server.close();
});
}
runServer().catch(console.error);