← Back to Course Summary
WEEK 3 - 协议集成

GitHub MCP Server
GitHub MCP服务器完整教程

Build a Model Context Protocol server that enables AI assistants to interact with GitHub.

构建模型上下文协议服务器,使AI助手能够与GitHub交互。

What is MCP? / 什么是MCP?

┌─────────────┐ MCP Protocol ┌─────────────┐
│ AI Client │ ◄──────────────────► │ MCP Server │
│ (Claude) │ │ │
└─────────────┘ └──────┬──────┘


┌─────────────┐
│ GitHub API │
└─────────────┘

MCP (Model Context Protocol) is an open protocol that allows AI applications to communicate bidirectionally with external data sources and tools.

  • 📡 Unified Protocol - Standard interface for AI-tool integration
  • 🔧 Tools - Functions AI can call / AI可以调用的函数
  • 📚 Resources - Static data providers / 静态数据提供者
  • 💬 Prompts - Pre-defined prompt templates / 预定义的提示模板

Architecture / 架构

Project Structure / 项目结构
week3/
├── server/
│ ├── __init__.py # Package initialization
│ ├── main.py # MCP server entry point
│ ├── config.py # Configuration management
│ ├── api_client.py # GitHub API client
│ └── exceptions.py # Custom exceptions
├── README.md # Documentation
├── test_server.py # Test script
└── .env.example # Environment template
Layered Architecture / 分层架构

1. MCP Protocol Layer (main.py)

Tool definitions and routing / 工具定义和路由

2. Business Logic Layer (api_client.py)

GitHub API integration / GitHub API集成

3. Infrastructure Layer (config.py, exceptions.py)

Configuration and error handling / 配置和错误处理

Step-by-Step Implementation / 分步实现

Step 1: Initialize Server / 初始化服务器
# server/main.py
from mcp.server import Server
from server.config import settings

# Initialize server
server = Server(settings.server_name)

@server.list_tools()
async def list_tools() -> list[Tool]:
    """List available tools."""
    return [
        Tool(
            name="get_github_issue",
            description="Get details of a GitHub issue",
            inputSchema={
                "type": "object",
                "properties": {
                    "owner": {"type": "string"},
                    "repo": {"type": "string"},
                    "issue_number": {"type": "integer"}
                },
                "required": ["owner", "repo", "issue_number"]
            }
        ),
        # ... more tools
    ]
Step 2: Implement Tool Handler / 实现工具处理器
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    """Handle tool calls."""
    try:
        if name == "get_github_issue":
            result = await client.get_issue(
                owner=arguments["owner"],
                repo=arguments["repo"],
                issue_number=arguments["issue_number"]
            )
            return [TextContent(type="text", text=format_issue(result))]
        # ... handle other tools
    except Exception as e:
        return [TextContent(type="text", text=f"Error: {str(e)}")]
Step 3: GitHub API Client / GitHub API客户端
# server/api_client.py
import httpx
from server.config import settings

class GitHubClient:
    async def get_issue(self, owner: str, repo: str, issue_number: int):
        """Get issue details."""
        # Validate input
        if not owner or not repo:
            raise ValidationError("owner/repo", "Cannot be empty")

        # Make request
        endpoint = f"/repos/{owner}/{repo}/issues/{issue_number}"
        return await self._request("GET", endpoint)
Step 4: Run Server / 运行服务器
# Run with STDIO transport
import asyncio
from mcp.server.stdio import stdio_server

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            server.create_initialization_options()
        )

if __name__ == "__main__":
    asyncio.run(main())

Implemented Tools / 实现的工具

1. get_github_issue
Get detailed information about a specific GitHub issue
Parameters:
• owner (string) - Repository owner / 仓库所有者
• repo (string) - Repository name / 仓库名称
• issue_number (integer) - Issue number / Issue编号
2. list_github_issues
List issues in a repository with optional filtering
Parameters:
• owner (string) - Repository owner
• repo (string) - Repository name
• state (string) - "open" or "closed"
• limit (integer) - Max results (default: 10)
3. get_repository
Get repository information and statistics
Parameters:
• owner (string) - Repository owner
• repo (string) - Repository name
4. search_issues
Search for issues across repositories
Parameters:
• query (string) - Search query
• sort (string) - Sort field
• order (string) - "asc" or "desc"
• limit (integer) - Max results

Configuration / 配置

Environment Variables / 环境变量
# .env
GITHUB_TOKEN=ghp_xxxxxxxxxxxx  # Optional, increases rate limit

Rate Limits:

  • ❌ No token: 60 requests/hour
  • ✅ With token: 5,000 requests/hour
Claude Desktop Config / Claude Desktop配置
# Claude Desktop config file location:
# Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
# Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "github": {
      "command": "python",
      "args": ["-m", "server.main"],
      "cwd": "C:/repos/.../week3",
      "env": {
        "GITHUB_TOKEN": "your_token_here"
      }
    }
  }
}

Key Features / 关键特性

✨ Async Operations
Non-blocking HTTP requests using httpx
🛡️ Rate Limiting
Respects GitHub API limits with tracking
🔒 Authentication
Optional token-based auth support
⚠️ Error Handling
Typed exceptions for all failure modes