A Model Context Protocol (MCP) server for managing GitHub projects and issues using GitHub's GraphQL API.
- List, create, update, and delete (close) GitHub issues
- Create issues with embedded images (upload local files or use URLs)
- Add/remove labels and assignees from issues
- List GitHub projects (ProjectsV2)
- Add/remove issues from projects
- Update project item fields (move between columns/status)
- Get project items and fields
- Get repository labels and user IDs
- Full GraphQL API integration for efficient data fetching
- Easy-to-use CLI with
gpscommand
pip install github-project-mcpgit clone <your-repo-url>
cd github-project-mcp
pip install .pip install -e .# Install Python `build`
pip install build
# Build the wheel
python -m build
# Install the wheel
pip install dist/github_project_mcp-0.1.0-py3-none-any.whl- Configure your GitHub token:
gps config --token YOUR_GITHUB_TOKEN- Test the connection:
gps test- Start the server:
gps startThe gps command provides a comprehensive interface for managing the MCP server:
# Start the server
gps start
# Start with specific token
gps start --token YOUR_TOKEN
# Start as daemon (background process)
gps start --daemon
# Stop the server
Press Ctrl + C
# Check server status
gps status# Configure GitHub token
gps config --token YOUR_TOKEN
# Show current configuration
gps config --show
# Clear configuration
gps config --clear# Test GitHub API connection
gps test
# List available MCP tools
gps toolsThe gps cli needs to be accessible from the system PATH, which typically means it should be installed globally or
in the active environment.
Option 1: Install globally with Python >=3.10
pip3 install github-project-mcp
Option 2: Use absolute path to virtual environment (venv or miniconda)
{
"mcpServers": {
"github-project-server": {
"command": "/path/to/your/gps",
"args": ["start"],
}
}
}
Claude Desktop supports MCP servers natively. Configure it by editing the Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
Add the following configuration:
{
"mcpServers": {
"github-project": {
"command": "gps",
"args": ["start", "--token", "your_github_token_here"]
}
}
}Or if you've configured the token with gps config:
{
"mcpServers": {
"github-project": {
"command": "gps",
"args": ["start"]
}
}
}After adding the configuration, restart Claude Desktop. You'll see the GitHub tools available in the tools menu.
Cursor doesn't natively support MCP yet, but you can use the server as a local API:
- Start the server as a daemon:
gps start --daemon- Create a wrapper script
cursor-github-helper.py:
import subprocess
import json
def query_github(command, params):
# Use the MCP server via subprocess
result = subprocess.run(
["gps", "query", "--json", json.dumps({"tool": command, "params": params})],
capture_output=True,
text=True
)
return json.loads(result.stdout)- Reference this in your Cursor rules or documentation for the AI to use.
Windsurf supports custom tools through its API integration:
- Install the package globally:
pip install github-project-mcp- Add to Windsurf's
~/.windsurf/config.json:
{
"mcpServers": {
"github-project-server": {
"command": "$PACKAGE_BIN_PATH/gps",
"args": ["start", "--token", "YOUR_GITHUB_TOKEN"]
}
}
}- In Windsurf chat, you can now reference GitHub operations:
@github list issues in owner/repo
@github create issue "Bug: Application crashes"
For VS Code, you can integrate the MCP server through extensions or terminal commands:
Add to .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Start GitHub MCP Server",
"type": "shell",
"command": "gps start --daemon",
"problemMatcher": [],
"group": "build"
},
{
"label": "List GitHub Issues",
"type": "shell",
"command": "gps",
"args": ["query", "list_issues", "${input:owner}", "${input:repo}"],
"problemMatcher": []
}
],
"inputs": [
{
"id": "owner",
"type": "promptString",
"description": "Repository owner"
},
{
"id": "repo",
"type": "promptString",
"description": "Repository name"
}
]
}If using Continue.dev extension for AI assistance:
- Install Continue.dev extension
- Add to
~/.continue/config.json:
{
"tools": [
{
"name": "github",
"command": "gps",
"args": ["start"],
"description": "GitHub project management"
}
]
}While GitHub Copilot doesn't directly support MCP, you can create command shortcuts:
- Create a
.github/copilot-instructions.mdfile in your project:
You have access to a GitHub MCP server. To use it:
- Start server: Run `gps start` in terminal
- List issues: Run `gps query list_issues OWNER REPO`
- Create issue: Run `gps query create_issue OWNER REPO "TITLE" "BODY"`- Copilot will recognize these commands and can help you use them.
For any IDE or assistant that doesn't natively support MCP, you can:
- Install the package:
pip install github-project-mcp- Start as a daemon:
gps start --daemon- Use the CLI programmatically:
# List issues
gps query list_issues octocat hello-world
# Create an issue
gps query create_issue octocat hello-world "Bug Report" "Description here"
# Update an issue
gps query update_issue ISSUE_ID --state CLOSED- Or use it in Python scripts:
from github_project_mcp import GitHubGraphQLClient
import os
client = GitHubGraphQLClient(os.getenv("GITHUB_TOKEN"))
issues = await client.list_issues("octocat", "hello-world")-
list_issues: List issues in a repository
- Parameters:
owner,repo,state(OPEN/CLOSED)
- Parameters:
-
create_issue: Create a new issue
- Parameters:
owner,repo,title,body,labels,assignees
- Parameters:
-
create_issue_with_images: Create an issue with embedded images
- Parameters:
owner,repo,title,body,images(array),labels,assignees - Images can be: local file paths, URLs, or objects with
path/urlandalttext
- Parameters:
-
update_issue: Update an existing issue
- Parameters:
issue_id,title,body,state,labels,assignees
- Parameters:
-
delete_issue: Close an issue (GitHub doesn't support deletion)
- Parameters:
issue_id
- Parameters:
-
add_labels_to_issue: Add labels to an issue
- Parameters:
issue_id,label_ids(array)
- Parameters:
-
remove_labels_from_issue: Remove labels from an issue
- Parameters:
issue_id,label_ids(array)
- Parameters:
-
add_assignees_to_issue: Add assignees to an issue
- Parameters:
issue_id,assignee_ids(array)
- Parameters:
-
remove_assignees_from_issue: Remove assignees from an issue
- Parameters:
issue_id,assignee_ids(array)
- Parameters:
-
list_projects: List projects in a repository
- Parameters:
owner,repo
- Parameters:
-
get_project_items: Get items in a project
- Parameters:
project_id
- Parameters:
-
add_issue_to_project: Add an issue to a project
- Parameters:
project_id,issue_id
- Parameters:
-
remove_issue_from_project: Remove an issue from a project
- Parameters:
project_id,item_id
- Parameters:
-
update_project_item_field: Update a project item's field (advanced)
- Parameters:
project_id,item_id,field_id,value(option ID for single-select fields)
- Parameters:
-
update_project_item_status: Update a project item's status (Todo, In Progress, Done, etc.)
- Parameters:
project_id,item_id,status(status name as text)
- Parameters:
-
get_project_fields: Get available fields in a project (including status options)
- Parameters:
project_id
- Parameters:
-
get_repo_id: Get repository ID for GraphQL mutations
- Parameters:
owner,repo
- Parameters:
-
get_repository_labels: Get all labels in a repository with their IDs
- Parameters:
owner,repo
- Parameters:
-
get_user_id: Get a GitHub user's ID by username
- Parameters:
username
- Parameters:
{
"tool": "list_issues",
"arguments": {
"owner": "octocat",
"repo": "hello-world",
"state": "OPEN"
}
}{
"tool": "create_issue",
"arguments": {
"owner": "octocat",
"repo": "hello-world",
"title": "Bug: Application crashes on startup",
"body": "The application crashes when trying to start with the --debug flag"
}
}{
"tool": "update_issue",
"arguments": {
"issue_id": "I_kwDOBFQLEs5XB1234",
"state": "CLOSED",
"body": "Fixed in PR #123"
}
}{
"tool": "add_labels_to_issue",
"arguments": {
"issue_id": "I_kwDOBFQLEs5XB1234",
"label_ids": ["LA_kwDOBFQLEs7XB5678", "LA_kwDOBFQLEs7XB9012"]
}
}{
"tool": "add_issue_to_project",
"arguments": {
"project_id": "PVT_kwDOBFQLEs4XB1234",
"issue_id": "I_kwDOBFQLEs5XB1234"
}
}{
"tool": "update_project_item_status",
"arguments": {
"project_id": "PVT_kwDOBFQLEs4XB1234",
"item_id": "PVTI_lADOBFQLEs5XB1234",
"status": "In Progress"
}
}Common status values: "Todo", "In Progress", "Done" (varies by project configuration)
{
"tool": "update_project_item_field",
"arguments": {
"project_id": "PVT_kwDOBFQLEs4XB1234",
"item_id": "PVTI_lADOBFQLEs5XB1234",
"field_id": "PVTF_lADOBFQLEs5XB5678",
"value": "PVTSSF_lADOBFQLEs5XB9999"
}
}Note: For status fields, use update_project_item_status instead for easier usage
{
"tool": "create_issue_with_images",
"arguments": {
"owner": "octocat",
"repo": "hello-world",
"title": "Bug: Visual regression in dashboard",
"body": "The dashboard layout is broken on mobile devices",
"images": [
"/path/to/screenshot1.png",
"https://example.com/image.jpg",
{
"path": "/path/to/screenshot2.png",
"alt": "Mobile view screenshot"
}
]
}
}Images are automatically uploaded to the repository and embedded in the issue body using Markdown
This server uses GitHub's GraphQL API v4 instead of REST API v3, providing:
- Efficient data fetching: Request only the fields you need
- Fewer API calls: Get related data in a single request
- Better performance: Reduced network overhead
- Type safety: Strongly typed schema
- Real-time capabilities: Support for subscriptions (future enhancement)
- Python 3.10+
- GitHub Personal Access Token with appropriate permissions
- Dependencies listed in
requirements.txt
MIT
- Install build tools:
pip install build twine- Create PyPI account:
- Register at https://pypi.org
- Generate API token in account settings
- Optionally, create TestPyPI account at https://test.pypi.org
-
Update version in
setup.pyorpyproject.toml -
Build the package:
python -m build- Upload to TestPyPI (optional, for testing):
twine upload --repository testpypi dist/*- Username:
__token__ - Password: Your TestPyPI API token
- Upload to PyPI:
twine upload dist/*- Username:
__token__ - Password: Your PyPI API token
- Verify installation:
pip install github-project-mcp- Clean the
dist/directory between builds:rm -rf dist/ - Use semantic versioning (e.g., 0.1.0, 0.1.1, 1.0.0)
- Ensure all tests pass before publishing
- Consider using GitHub Actions for automated publishing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.