# CLAUDE.md - Gitea MCP Remote This file provides guidance to Claude Code when working with this repository. ## Project Overview **Name:** gitea-mcp-remote **Type:** HTTP transport server for MCP (Model Context Protocol) **Purpose:** Expose Gitea operations via MCP Streamable HTTP protocol for AI assistants This is NOT a standalone MCP server. It imports tools from the `gitea-mcp-server` marketplace package and serves them over HTTP with authentication and tool filtering. ## Architecture ``` Client (Claude Desktop) ──HTTP──▶ gitea-mcp-remote ──imports──▶ gitea-mcp-server ──API──▶ Gitea │ ├── Authentication (Bearer token) ├── Tool Filtering (enable/disable) └── MCP Streamable HTTP protocol ``` **Key Design Decision:** This server uses direct imports from the marketplace `gitea-mcp-server` package, NOT subprocess spawning. Tool definitions and dispatchers are imported and used directly. ## Project Structure ``` gitea-mcp-remote/ ├── src/gitea_mcp_remote/ # Main package │ ├── __init__.py │ ├── server_http.py # MCP HTTP server (main module) │ ├── config/ # Configuration module │ │ ├── __init__.py │ │ └── settings.py # Pydantic settings loader │ ├── middleware/ # HTTP middleware │ │ ├── __init__.py │ │ └── auth.py # Bearer auth + health check bypass │ └── filtering/ # Tool filtering │ ├── __init__.py │ └── filter.py # Whitelist/blacklist filtering ├── tests/ # Test suite (at repo root) │ ├── conftest.py │ ├── test_config.py │ ├── test_middleware.py │ ├── test_filtering.py │ └── test_mcp_endpoints.py ├── docker/ # Docker infrastructure │ ├── Dockerfile # Multi-stage build │ ├── docker-compose.yml # App + Caddy services │ ├── Caddyfile # Reverse proxy config │ └── .env.example # Environment template ├── scripts/ # Utility scripts │ ├── start.sh # Production startup │ └── healthcheck.sh # Docker health check ├── docs/ # Documentation │ └── sprint-proposals/ # Sprint planning docs ├── pyproject.toml # Project configuration ├── requirements.txt # Dependencies ├── README.md # User documentation ├── DEPLOYMENT.md # Deployment guide └── CLAUDE.md # This file ``` ## Development Workflows ### Setup Development Environment ```bash # Create virtual environment python -m venv .venv source .venv/bin/activate # Install with development dependencies pip install -e ".[dev]" ``` ### Running Tests ```bash # All tests pytest tests/ -v # With coverage pytest tests/ --cov=gitea_mcp_remote # Specific test file pytest tests/test_mcp_endpoints.py -v ``` ### Running the Server Locally ```bash # Set required environment variables export GITEA_URL=https://gitea.example.com export GITEA_TOKEN=your_token export GITEA_OWNER=your_org # Run server gitea-mcp-remote ``` ### Docker Development ```bash # Build and run docker-compose -f docker/docker-compose.yml up --build # Validate configuration docker-compose -f docker/docker-compose.yml config # Check logs docker-compose -f docker/docker-compose.yml logs -f ``` ## Key Files ### server_http.py The main MCP server implementation: - Imports tools from `mcp_server` (marketplace package) - Creates `Server` instance with tool handlers - Uses `StreamableHTTPServerTransport` for MCP protocol - Health endpoint at `/health` (bypasses auth) - MCP endpoint at `/mcp` (POST for requests, HEAD for protocol version) ### config/settings.py Pydantic settings with: - `gitea_url`, `gitea_token`, `gitea_owner` (required) - `gitea_repo` (optional) - `http_host` (default: 0.0.0.0), `http_port` (default: 8080) - `auth_token` (optional Bearer token) - `mcp_auth_mode` (optional/required/none) - `enabled_tools`, `disabled_tools` (comma-separated) ### middleware/auth.py Two middleware classes: - `BearerAuthMiddleware`: Validates Authorization header - `HealthCheckBypassMiddleware`: Sets `skip_auth` flag for health endpoints **Important:** Middleware order matters. HealthCheckBypass must wrap BearerAuth (outermost) so it runs first. ## MCP Protocol Notes This server implements the MCP Streamable HTTP protocol: 1. **HEAD /mcp** - Returns protocol version header (`x-mcp-protocol-version: 2024-11-05`) 2. **POST /mcp** - Accepts JSON-RPC 2.0 requests, returns SSE responses Supported methods: - `initialize` - Protocol handshake - `tools/list` - List available tools - `tools/call` - Execute a tool ### Request Format ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_issues", "arguments": {"owner": "org", "repo": "repo", "state": "open"} } } ``` ### Response Format (SSE) ``` event: message data: {"jsonrpc":"2.0","id":1,"result":[...]} ``` ## Configuration Reference | Variable | Required | Default | Description | |----------|----------|---------|-------------| | GITEA_URL | Yes | - | Gitea instance URL | | GITEA_TOKEN | Yes | - | Gitea API token | | GITEA_OWNER | Yes | - | Default owner/org | | GITEA_REPO | No | None | Default repository | | HTTP_HOST | No | 0.0.0.0 | Server bind address | | HTTP_PORT | No | 8080 | Server port | | AUTH_TOKEN | No | None | Bearer token for auth | | MCP_AUTH_MODE | No | optional | Auth mode | | ENABLED_TOOLS | No | None | Whitelist (comma-sep) | | DISABLED_TOOLS | No | None | Blacklist (comma-sep) | ## Troubleshooting ### Import Errors from mcp_server If `from mcp_server import ...` fails: 1. Verify `gitea-mcp-server` is installed: `pip list | grep gitea` 2. The package is installed from Git via pyproject.toml dependency 3. Reinstall: `pip install -e .` ### Health Endpoint Returns 401 Middleware order is wrong. HealthCheckBypassMiddleware must be outermost: ```python if settings.auth_token: app = BearerAuthMiddleware(app, auth_token=settings.auth_token) app = HealthCheckBypassMiddleware(app) # Must be last (outermost) ``` ### Tests Not Found Ensure pyproject.toml has correct testpaths: ```toml [tool.pytest.ini_options] testpaths = ["tests"] ``` ### MCP Requests Fail with 406 Missing Accept header. Requests must include: ``` Accept: application/json, text/event-stream ``` ## Dependencies **Runtime:** - `gitea-mcp-server` - Marketplace package (Git dependency) - `mcp` - MCP SDK - `uvicorn` - ASGI server - `starlette` - Web framework - `pydantic-settings` - Configuration **Development:** - `pytest` - Testing - `pytest-asyncio` - Async test support - `pytest-cov` - Coverage - `httpx` - HTTP client for tests