valiot/mcp-deployable
If you are the rightful owner of mcp-deployable and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
A Model Context Protocol (MCP) server for GitHub operations, enabling LLMs to interact with GitHub repositories through a standardized interface.
GitHub MCP Server
A Model Context Protocol (MCP) server for GitHub operations, enabling LLMs to interact with GitHub repositories through a standardized interface. Deployable to Cloudflare Workers for production use.
Features
- 🔌 MCP Protocol Compliant: Works with any MCP-compatible LLM (OpenAI, Claude, Cursor, etc.)
- 🚀 9 GitHub Operations: Comprehensive PR management capabilities
- ✅ Type-Safe: Full TypeScript with runtime validation using Zod
- ☁️ Cloudflare Workers Ready: Deploy to the edge with zero configuration
- 🧪 Tested: Golden tests for schema and behavior validation
- 🔐 Secure: GitHub Personal Access Token authentication
Available Tools
- list_prs - List pull requests with filters (state, base, head)
- get_pr - Get detailed PR information
- create_pr - Create new pull request
- update_pr - Update PR title, description, state, or base branch
- add_pr_comment - Add comment to a PR
- merge_pr - Merge PR with specified method (merge/squash/rebase)
- request_pr_reviewers - Request PR reviewers (users or teams)
- add_pr_labels - Add labels to PR
- remove_pr_labels - Remove labels from PR
Architecture
┌─────────────┐
│ LLM │ (OpenAI, Claude, Cursor, etc.)
│ (Client) │
└──────┬──────┘
│ MCP Protocol
│ (stdio or HTTP)
▼
┌─────────────────┐
│ MCP Server │
│ (This repo) │
├─────────────────┤
│ • Tool Registry │
│ • Validation │
│ • Error Handler │
└──────┬──────────┘
│
│ Octokit REST API
▼
┌─────────────────┐
│ GitHub API │
└─────────────────┘
Setup
Prerequisites
- Node.js 18+
- GitHub Personal Access Token with appropriate permissions
Installation
# Clone or create project
npm install
# Set GitHub token
export GITHUB_TOKEN="ghp_your_token_here"
# Build project
npm run build
Creating a GitHub Token
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token with these scopes:
repo(Full control of private repositories)read:org(if working with organization repos)
- Copy the token and set as
GITHUB_TOKENenvironment variable
Usage
Local Development (stdio)
Run the MCP server locally using stdio transport:
export GITHUB_TOKEN="your_token"
npm run dev
The server will run on stdio and can be connected to by MCP clients.
Test Client
Run the example test client to see the server in action:
export GITHUB_TOKEN="your_token"
npm run client
This will:
- Start the MCP server
- Connect via stdio transport
- List available tools
- Execute example operations (list PRs, get PR details)
- Display results
Integration with Cursor
To use with Cursor, add to your MCP configuration:
{
"mcpServers": {
"github": {
"command": "node",
"args": ["path/to/mcp-deployable/dist/server/index.js"],
"env": {
"GITHUB_TOKEN": "your_token_here"
}
}
}
}
Integration with OpenAI
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { spawn } from 'child_process';
import OpenAI from 'openai';
// Start MCP server
const serverProcess = spawn('node', ['dist/server/index.js'], {
env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
});
// Connect MCP client
const client = new Client({
name: 'openai-github-client',
version: '1.0.0',
}, { capabilities: {} });
const transport = new StdioClientTransport({ command: serverProcess });
await client.connect(transport);
// Get available tools
const tools = await client.listTools();
// Use with OpenAI
const openai = new OpenAI();
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'user', content: 'List open PRs in owner/repo' }
],
tools: tools.tools.map(tool => ({
type: 'function',
function: {
name: tool.name,
description: tool.description,
parameters: tool.inputSchema,
},
})),
});
// Execute tool if requested
if (response.choices[0].message.tool_calls) {
const toolCall = response.choices[0].message.tool_calls[0];
const result = await client.callTool({
name: toolCall.function.name,
arguments: JSON.parse(toolCall.function.arguments),
});
console.log(result);
}
Cloudflare Workers Deployment
Prerequisites
- Cloudflare account
- Wrangler CLI installed (
npm install -g wrangler)
Deploy
# Build worker bundle
npm run build:worker
# Set GitHub token as secret
wrangler secret put GITHUB_TOKEN
# Deploy to Cloudflare Workers
npm run deploy
HTTP API
Once deployed, the worker exposes these endpoints:
Health Check
curl https://your-worker.workers.dev/health
List Tools
curl https://your-worker.workers.dev/tools
Invoke Tool
curl -X POST https://your-worker.workers.dev/invoke \
-H "Content-Type: application/json" \
-d '{
"tool": "list_prs",
"arguments": {
"owner": "octocat",
"repo": "hello-world",
"state": "open"
}
}'
Development
Project Structure
mcp-deployable/
├── src/
│ ├── server/
│ │ ├── index.ts # MCP server (stdio)
│ │ ├── tools/
│ │ │ └── github-tools.ts # GitHub API operations
│ │ └── schemas/
│ │ └── tools.ts # Zod schemas
│ ├── client/
│ │ └── test-client.ts # Example client
│ ├── types/
│ │ └── github.ts # TypeScript types
│ └── worker.ts # Cloudflare Workers entry
├── tests/
│ └── golden/
│ ├── github-tools.test.ts # Golden tests
│ └── fixtures/ # Mock responses
├── wrangler.toml # Workers config
├── package.json
└── tsconfig.json
Running Tests
# Run all tests
npm test
# Run golden tests only
npm run test:golden
# Run tests in watch mode
npm test -- --watch
Scripts
npm run build- Build TypeScript and worker bundlenpm run dev- Run MCP server locally (stdio)npm run client- Run test clientnpm test- Run test suitenpm run deploy- Deploy to Cloudflare Workers
Tool Examples
List Pull Requests
{
"tool": "list_prs",
"arguments": {
"owner": "modelcontextprotocol",
"repo": "typescript-sdk",
"state": "open",
"per_page": 10
}
}
Get Pull Request Details
{
"tool": "get_pr",
"arguments": {
"owner": "modelcontextprotocol",
"repo": "typescript-sdk",
"pull_number": 42
}
}
Create Pull Request
{
"tool": "create_pr",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"title": "Add new feature",
"body": "This PR adds feature X",
"head": "feature-branch",
"base": "main",
"draft": false
}
}
Update Pull Request
{
"tool": "update_pr",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"pull_number": 42,
"title": "Updated title",
"body": "Updated description"
}
}
Add Comment
{
"tool": "add_pr_comment",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"pull_number": 42,
"body": "Great work! LGTM 👍"
}
}
Merge Pull Request
{
"tool": "merge_pr",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"pull_number": 42,
"merge_method": "squash",
"commit_title": "feat: add new feature"
}
}
Request Reviewers
{
"tool": "request_pr_reviewers",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"pull_number": 42,
"reviewers": ["user1", "user2"],
"team_reviewers": ["team-alpha"]
}
}
Manage Labels
{
"tool": "add_pr_labels",
"arguments": {
"owner": "myorg",
"repo": "myrepo",
"pull_number": 42,
"labels": ["bug", "high-priority"]
}
}
Error Handling
All tools include comprehensive error handling:
- Validation Errors: Input parameters are validated using Zod schemas
- GitHub API Errors: HTTP errors from GitHub API are caught and formatted
- Rate Limiting: GitHub API rate limit errors are properly surfaced
- Authentication Errors: Missing or invalid tokens return clear error messages
Example error response:
{
"error": "GitHub API error (404): Not Found",
"code": "INTERNAL_ERROR"
}
Security
- Authentication: Uses GitHub Personal Access Token (PAT)
- Least Privilege: Configure tokens with only necessary scopes
- Environment Variables: Secrets stored in env vars, never committed
- Input Validation: All inputs validated before GitHub API calls
License
MIT
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Support
For issues or questions:
- Open an issue on GitHub
- Check existing issues for solutions
- Review MCP protocol documentation: https://modelcontextprotocol.io