Notes MCP Server

#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import { Octokit } from '@octokit/rest'; import * as dotenv from 'dotenv'; import { resolve } from 'path'; // Load environment variables from .env file dotenv.config({ path: resolve(__dirname, '../.env') }); const GITHUB_TOKEN = process.env.GITHUB_TOKEN; if (!GITHUB_TOKEN) { throw new Error('GITHUB_TOKEN environment variable is required'); } interface CreateIssueArgs { owner: string; repo: string; title: string; body?: string; labels?: string[]; assignees?: string[]; } const isValidCreateIssueArgs = (args: any): args is CreateIssueArgs => typeof args === 'object' && args !== null && typeof args.owner === 'string' && typeof args.repo === 'string' && typeof args.title === 'string' && (args.body === undefined || typeof args.body === 'string') && (args.labels === undefined || Array.isArray(args.labels)) && (args.assignees === undefined || Array.isArray(args.assignees)); class GitHubServer { private server: Server; private octokit: Octokit; constructor() { this.server = new Server( { name: 'github-server', version: '0.1.0', }, { capabilities: { tools: {}, }, } ); this.octokit = new Octokit({ auth: GITHUB_TOKEN, }); this.setupToolHandlers(); this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } private setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'create_issue', description: 'Create a new GitHub issue', inputSchema: { type: 'object', properties: { owner: { type: 'string', description: 'Repository owner (user or organization)', }, repo: { type: 'string', description: 'Repository name', }, title: { type: 'string', description: 'Issue title', }, body: { type: 'string', description: 'Issue body/description', }, labels: { type: 'array', items: { type: 'string', }, description: 'Labels to apply to the issue', }, assignees: { type: 'array', items: { type: 'string', }, description: 'GitHub usernames to assign to the issue', }, }, required: ['owner', 'repo', 'title'], }, }, ], })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'create_issue') { throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } if (!isValidCreateIssueArgs(request.params.arguments)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid issue creation arguments' ); } try { const response = await this.octokit.issues.create({ owner: request.params.arguments.owner, repo: request.params.arguments.repo, title: request.params.arguments.title, body: request.params.arguments.body, labels: request.params.arguments.labels, assignees: request.params.arguments.assignees, }); return { content: [ { type: 'text', text: JSON.stringify({ issueNumber: response.data.number, issueUrl: response.data.html_url, }, null, 2), }, ], }; } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; return { content: [ { type: 'text', text: `GitHub API error: ${message}`, }, ], isError: true, }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('GitHub MCP server running on stdio'); } } const server = new GitHubServer(); server.run().catch(console.error);