X Tutup
Skip to content

Latest commit

 

History

History
292 lines (224 loc) · 12.8 KB

File metadata and controls

292 lines (224 loc) · 12.8 KB

GitHub MCP Server - Copilot Instructions

Project Overview

This is the GitHub MCP Server, a Model Context Protocol (MCP) server that connects AI tools to GitHub's platform. It enables AI agents to manage repositories, issues, pull requests, workflows, and more through natural language.

Key Details:

  • Language: Go 1.24+ (~38k lines of code)
  • Type: MCP server application with CLI interface
  • Primary Package: github-mcp-server (stdio MCP server - this is the main focus)
  • Secondary Package: mcpcurl (testing utility - don't break it, but not the priority)
  • Framework: Uses modelcontextprotocol/go-sdk for MCP protocol, google/go-github for GitHub API
  • Size: ~60MB repository, 70 Go files
  • Library Usage: This repository is also used as a library by the remote server. Functions that could be called by other repositories should be exported (capitalized), even if not required internally. Preserve existing export patterns.

Code Quality Standards:

  • Popular Open Source Repository - High bar for code quality and clarity
  • Comprehension First - Code must be clear to a wide audience
  • Clean Commits - Atomic, focused changes with clear messages
  • Structure - Always maintain or improve, never degrade
  • Code over Comments - Prefer self-documenting code; comment only when necessary

Critical Build & Validation Steps

Required Commands (Run Before Committing)

ALWAYS run these commands in this exact order before using report_progress or finishing work:

  1. Format Code: script/lint (runs gofmt -s -w . then golangci-lint)
  2. Run Tests: script/test (runs go test -race ./...)
  3. Update Documentation: script/generate-docs (if you modified MCP tools/toolsets)

These commands are FAST: Lint ~1s, Tests ~1s (cached), Build ~1s

When Modifying MCP Tools/Endpoints

If you change any MCP tool definitions or schemas:

  1. Run tests with UPDATE_TOOLSNAPS=true go test ./... to update toolsnaps
  2. Commit the updated .snap files in pkg/github/__toolsnaps__/
  3. Run script/generate-docs to update README.md
  4. Toolsnaps document API surface and ensure changes are intentional

Common Build Commands

# Download dependencies (rarely needed - usually cached)
go mod download

# Build the server binary
go build -v ./cmd/github-mcp-server

# Run the server
./github-mcp-server stdio

# Run specific package tests
go test ./pkg/github -v

# Run specific test
go test ./pkg/github -run TestGetMe

Project Structure

Directory Layout

.
├── cmd/
│   ├── github-mcp-server/    # Main MCP server entry point (PRIMARY FOCUS)
│   └── mcpcurl/              # MCP testing utility (secondary - don't break it)
├── pkg/                      # Public API packages
│   ├── github/               # GitHub API MCP tools implementation
│   │   └── __toolsnaps__/    # Tool schema snapshots (*.snap files)
│   ├── toolsets/             # Toolset configuration & management
│   ├── errors/               # Error handling utilities
│   ├── sanitize/             # HTML/content sanitization
│   ├── log/                  # Logging utilities
│   ├── raw/                  # Raw data handling
│   ├── buffer/               # Buffer utilities
│   └── translations/         # i18n translation support
├── internal/                 # Internal implementation packages
│   ├── ghmcp/                # GitHub MCP server core logic
│   ├── githubv4mock/         # GraphQL API mocking for tests
│   ├── toolsnaps/            # Toolsnap validation system
│   └── profiler/             # Performance profiling
├── e2e/                      # End-to-end tests (require GitHub PAT)
├── script/                   # Build and maintenance scripts
├── docs/                     # Documentation
├── .github/workflows/        # CI/CD workflows
└── [config files]            # See below

Key Configuration Files

  • go.mod / go.sum: Go module dependencies (Go 1.24.0+)
  • .golangci.yml: Linter configuration (v2 format, ~15 linters enabled)
  • Dockerfile: Multi-stage build (golang:1.25.3-alpine → distroless)
  • server.json: MCP server metadata for registry
  • .goreleaser.yaml: Release automation config
  • .gitignore: Excludes bin/, dist/, vendor/, *.DS_Store, github-mcp-server binary

Important Scripts (script/ directory)

  • script/lint - Runs gofmt + golangci-lint. MUST RUN before committing
  • script/test - Runs go test -race ./... (full test suite)
  • script/generate-docs - Updates README.md tool documentation. Run after tool changes
  • script/licenses - Updates third-party license files when dependencies change
  • script/licenses-check - Validates license compliance (runs in CI)
  • script/get-me - Quick test script for get_me tool
  • script/get-discussions - Quick test for discussions
  • script/tag-release - NEVER USE THIS - releases are managed separately

GitHub Workflows (CI/CD)

All workflows run on push/PR unless noted. Located in .github/workflows/:

  1. go.yml - Build and test on ubuntu/windows/macos. Runs script/test and builds binary
  2. lint.yml - Runs golangci-lint-action v2.5 (GitHub Action) with actions/setup-go stable
  3. docs-check.yml - Verifies README.md is up-to-date by running generate-docs and checking git diff
  4. code-scanning.yml - CodeQL security analysis for Go and GitHub Actions
  5. license-check.yml - Runs script/licenses-check to validate compliance
  6. docker-publish.yml - Publishes container image to ghcr.io
  7. goreleaser.yml - Creates releases (main branch only)
  8. registry-releaser.yml - Updates MCP registry

All of these must pass for PR merge. If docs-check fails, run script/generate-docs and commit changes.

Testing Guidelines

Unit Tests

  • Use testify for assertions (require for critical checks, assert for non-blocking)
  • Tests are in *_test.go files alongside implementation (internal tests, not _test package)
  • Mock GitHub API with go-github-mock (REST) or githubv4mock (GraphQL)
  • Test structure for tools:
    1. Test tool snapshot
    2. Verify critical schema properties (e.g., ReadOnly annotation)
    3. Table-driven behavioral tests

Toolsnaps (Tool Schema Snapshots)

  • Every MCP tool has a JSON schema snapshot in pkg/github/__toolsnaps__/*.snap
  • Tests fail if current schema differs from snapshot (shows diff)
  • To update after intentional changes: UPDATE_TOOLSNAPS=true go test ./...
  • MUST commit updated .snap files - they document API changes
  • Missing snapshots cause CI failure

End-to-End Tests

  • Located in e2e/ directory with e2e_test.go
  • Require GitHub PAT token - you usually cannot run these yourself
  • Run with: GITHUB_MCP_SERVER_E2E_TOKEN=<token> go test -v --tags e2e ./e2e
  • Tests interact with live GitHub API via Docker container
  • Keep e2e tests updated when changing MCP tools
  • Use only the e2e test style when modifying tests in this directory
  • For debugging: GITHUB_MCP_SERVER_E2E_DEBUG=true runs in-process (no Docker)

Code Style & Linting

Go Code Requirements

  • gofmt with simplify flag (-s) - Automatically run by script/lint
  • golangci-lint with these linters enabled:
    • bodyclose, gocritic, gosec, makezero, misspell, nakedret, revive
    • errcheck, staticcheck, govet, ineffassign, unused
  • Exclusions for: third_party/, builtin/, examples/, generated code

Go Naming Conventions

  • Acronyms in identifiers: Use ID not Id, API not Api, URL not Url, HTTP not Http
  • Examples: userID, getAPI, parseURL, HTTPClient
  • This applies to variable names, function names, struct fields, etc.

Code Patterns

  • Keep changes minimal and focused on the specific issue being addressed
  • Prefer clarity over cleverness - code must be understandable by a wide audience
  • Atomic commits - each commit should be a complete, logical change
  • Maintain or improve structure - never degrade code organization
  • Use table-driven tests for behavioral testing
  • Comment sparingly - code should be self-documenting
  • Follow standard Go conventions (Effective Go, Go proverbs)
  • Test changes thoroughly before committing
  • Export functions (capitalize) if they could be used by other repos as a library

Common Development Workflows

Adding a New MCP Tool

  1. Add tool implementation in pkg/github/ (e.g., foo_tools.go)
  2. Register tool in appropriate toolset in pkg/github/ or pkg/toolsets/
  3. Write unit tests following the tool test pattern
  4. Run UPDATE_TOOLSNAPS=true go test ./... to create snapshot
  5. Run script/generate-docs to update README
  6. Run script/lint and script/test before committing
  7. If e2e tests are relevant, update e2e/e2e_test.go using existing test style
  8. Commit code + snapshots + README changes together

Fixing a Bug

  1. Write a failing test that reproduces the bug
  2. Fix the bug with minimal changes
  3. Verify test passes and existing tests still pass
  4. Run script/lint and script/test
  5. If tool schema changed, update toolsnaps (see above)

Updating Dependencies

  1. Update go.mod (e.g., go get -u ./... or manually)
  2. Run go mod tidy
  3. Run script/licenses to update license files
  4. Run script/test to verify nothing broke
  5. Commit go.mod, go.sum, and third-party-licenses* files

Common Errors & Solutions

"Documentation is out of date" in CI

Fix: Run script/generate-docs and commit README.md changes

Toolsnap mismatch failures

Fix: Run UPDATE_TOOLSNAPS=true go test ./... and commit updated .snap files

Lint failures

Fix: Run script/lint locally - it will auto-format and show issues. Fix manually reported issues.

License check failures

Fix: Run script/licenses to regenerate license files after dependency changes

Test failures after changing a tool

Likely causes:

  1. Forgot to update toolsnaps - run with UPDATE_TOOLSNAPS=true
  2. Changed behavior broke existing tests - verify intent and fix tests
  3. Schema change not reflected in test - update test expectations

Environment Variables

  • GITHUB_PERSONAL_ACCESS_TOKEN - Required for server operation and e2e tests
  • GITHUB_HOST - For GitHub Enterprise Server (prefix with https://)
  • GITHUB_TOOLSETS - Comma-separated toolset list (overrides --toolsets flag)
  • GITHUB_READ_ONLY - Set to "1" for read-only mode
  • GITHUB_DYNAMIC_TOOLSETS - Set to "1" for dynamic toolset discovery
  • UPDATE_TOOLSNAPS - Set to "true" when running tests to update snapshots
  • GITHUB_MCP_SERVER_E2E_TOKEN - Token for e2e tests
  • GITHUB_MCP_SERVER_E2E_DEBUG - Set to "true" for in-process e2e debugging

Key Files Reference

Root Directory Files

.dockerignore        - Docker build exclusions
.gitignore          - Git exclusions (includes bin/, dist/, vendor/, binaries)
.golangci.yml       - Linter configuration
.goreleaser.yaml    - Release automation
CODE_OF_CONDUCT.md  - Community guidelines
CONTRIBUTING.md     - Contribution guide (fork, clone, test, lint workflow)
Dockerfile          - Multi-stage Go build
LICENSE             - MIT license
README.md           - Main documentation (auto-generated sections)
SECURITY.md         - Security policy
SUPPORT.md          - Support resources
gemini-extension.json - Gemini CLI configuration
go.mod / go.sum     - Go dependencies
server.json         - MCP server registry metadata

Main Entry Point

cmd/github-mcp-server/main.go - Uses cobra for CLI, viper for config, supports:

  • stdio command (default) - MCP stdio transport
  • generate-docs command - Documentation generation
  • Flags: --toolsets, --read-only, --dynamic-toolsets, --gh-host, --log-file

Important Reminders

  1. PRIMARY FOCUS: The local stdio MCP server (github-mcp-server) - this is what you should work on and test with
  2. REMOTE SERVER: Ignore remote server instructions when making code changes (unless specifically asked). This repo is used as a library by the remote server, so keep functions exported (capitalized) if they could be called by other repos, even if not needed internally.
  3. ALWAYS trust these instructions first - only search if information is incomplete or incorrect
  4. NEVER use script/tag-release or push tags
  5. NEVER skip script/lint before committing Go code changes
  6. ALWAYS update toolsnaps when changing MCP tool schemas
  7. ALWAYS run script/generate-docs after modifying tools
  8. For specific test files, use go test ./path -run TestName not full suite
  9. E2E tests require PAT token - you likely cannot run them
  10. Toolsnaps are API documentation - treat changes seriously
  11. Build/test/lint are very fast (~1s each) - run frequently
  12. CI failures for docs-check or license-check have simple fixes (run the script)
  13. mcpcurl is secondary - don't break it, but it's not the priority
X Tutup