github-project-mcp

jaqarx/github-project-mcp

3.3

If you are the rightful owner of github-project-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

A Model Context Protocol (MCP) server for managing GitHub projects and issues using GitHub's GraphQL API.

Tools
7
Resources
0
Prompts
0

GitHub Project MCP Server

A Model Context Protocol (MCP) server for managing GitHub projects and issues using GitHub's GraphQL API.

Features

  • 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 gps command

Installation

From PyPI (Recommended)

pip install github-project-mcp

From Source

git clone <your-repo-url>
cd github-project-mcp
pip install .

For Development

pip install -e .

From Wheel

# 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

Quick Start

  1. Configure your GitHub token:
gps config --token YOUR_GITHUB_TOKEN
  1. Test the connection:
gps test
  1. Start the server:
gps start

CLI Commands

The gps command provides a comprehensive interface for managing the MCP server:

Server Management

# 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

Configuration

# Configure GitHub token
gps config --token YOUR_TOKEN

# Show current configuration
gps config --show

# Clear configuration
gps config --clear

Utilities

# Test GitHub API connection
gps test

# List available MCP tools
gps tools

Integration with AI Coding Assistants

Setup

The 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

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.ai

Cursor doesn't natively support MCP yet, but you can use the server as a local API:

  1. Start the server as a daemon:
gps start --daemon
  1. 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)
  1. Reference this in your Cursor rules or documentation for the AI to use.

Windsurf (Codeium)

Windsurf supports custom tools through its API integration:

  1. Install the package globally:
pip install github-project-mcp
  1. Add to Windsurf's ~/.windsurf/config.json:
{
  "mcpServers": {
    "github-project-server": {
      "command": "$PACKAGE_BIN_PATH/gps",
      "args": ["start", "--token", "YOUR_GITHUB_TOKEN"]
    }
  }
}
  1. In Windsurf chat, you can now reference GitHub operations:
@github list issues in owner/repo
@github create issue "Bug: Application crashes"

Visual Studio Code

For VS Code, you can integrate the MCP server through extensions or terminal commands:

Option 1: VS Code Tasks

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"
    }
  ]
}
Option 2: VS Code Extension (Continue.dev)

If using Continue.dev extension for AI assistance:

  1. Install Continue.dev extension
  2. Add to ~/.continue/config.json:
{
  "tools": [
    {
      "name": "github",
      "command": "gps",
      "args": ["start"],
      "description": "GitHub project management"
    }
  ]
}
Option 3: GitHub Copilot Chat

While GitHub Copilot doesn't directly support MCP, you can create command shortcuts:

  1. Create a .github/copilot-instructions.md file 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"`
  1. Copilot will recognize these commands and can help you use them.

General Integration Pattern

For any IDE or assistant that doesn't natively support MCP, you can:

  1. Install the package:
pip install github-project-mcp
  1. Start as a daemon:
gps start --daemon
  1. 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
  1. 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")

Available Tools

Issue Management

  • list_issues: List issues in a repository

    • Parameters: owner, repo, state (OPEN/CLOSED)
  • create_issue: Create a new issue

    • Parameters: owner, repo, title, body, labels, assignees
  • 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/url and alt text
  • update_issue: Update an existing issue

    • Parameters: issue_id, title, body, state, labels, assignees
  • delete_issue: Close an issue (GitHub doesn't support deletion)

    • Parameters: issue_id
  • add_labels_to_issue: Add labels to an issue

    • Parameters: issue_id, label_ids (array)
  • remove_labels_from_issue: Remove labels from an issue

    • Parameters: issue_id, label_ids (array)
  • add_assignees_to_issue: Add assignees to an issue

    • Parameters: issue_id, assignee_ids (array)
  • remove_assignees_from_issue: Remove assignees from an issue

    • Parameters: issue_id, assignee_ids (array)

Project Management

  • list_projects: List projects in a repository

    • Parameters: owner, repo
  • get_project_items: Get items in a project

    • Parameters: project_id
  • add_issue_to_project: Add an issue to a project

    • Parameters: project_id, issue_id
  • remove_issue_from_project: Remove an issue from a project

    • Parameters: project_id, item_id
  • 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)
  • 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)
  • get_project_fields: Get available fields in a project (including status options)

    • Parameters: project_id

Utilities

  • get_repo_id: Get repository ID for GraphQL mutations

    • Parameters: owner, repo
  • get_repository_labels: Get all labels in a repository with their IDs

    • Parameters: owner, repo
  • get_user_id: Get a GitHub user's ID by username

    • Parameters: username

Example Usage

List Open Issues

{
  "tool": "list_issues",
  "arguments": {
    "owner": "octocat",
    "repo": "hello-world",
    "state": "OPEN"
  }
}

Create New Issue

{
  "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"
  }
}

Update Issue

{
  "tool": "update_issue",
  "arguments": {
    "issue_id": "I_kwDOBFQLEs5XB1234",
    "state": "CLOSED",
    "body": "Fixed in PR #123"
  }
}

Add Labels to Issue

{
  "tool": "add_labels_to_issue",
  "arguments": {
    "issue_id": "I_kwDOBFQLEs5XB1234",
    "label_ids": ["LA_kwDOBFQLEs7XB5678", "LA_kwDOBFQLEs7XB9012"]
  }
}

Add Issue to Project

{
  "tool": "add_issue_to_project",
  "arguments": {
    "project_id": "PVT_kwDOBFQLEs4XB1234",
    "issue_id": "I_kwDOBFQLEs5XB1234"
  }
}

Update Issue Status in Project Board

{
  "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)

Advanced: Update Project Field Directly

{
  "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

Create Issue with Images

{
  "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

GraphQL API Benefits

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)

Requirements

  • Python 3.10+
  • GitHub Personal Access Token with appropriate permissions
  • Dependencies listed in requirements.txt

License

MIT

Publishing to PyPI

Prerequisites

  1. Install build tools:
pip install build twine
  1. Create PyPI account:

Publishing Steps

  1. Update version in setup.py or pyproject.toml

  2. Build the package:

python -m build
  1. Upload to TestPyPI (optional, for testing):
twine upload --repository testpypi dist/*
  • Username: __token__
  • Password: Your TestPyPI API token
  1. Upload to PyPI:
twine upload dist/*
  • Username: __token__
  • Password: Your PyPI API token
  1. Verify installation:
pip install github-project-mcp

Notes

  • 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

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.