Files
gitea-mcp-remote/CLAUDE.md
lmiranda 2dbb66deae docs: Create CLAUDE.md and update deployment documentation (#27)
- Create CLAUDE.md with comprehensive project guidance for Claude Code
- Update README.md with correct architecture (direct import, not subprocess)
- Update project structure to reflect tests/ at repo root and docker/ directory
- Update default port from 8000 to 8080
- Update repository links to Gitea
- Update DEPLOYMENT.md with two-service Docker architecture (app + Caddy)
- Fix Claude Desktop config example to use /mcp endpoint

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 21:32:39 -05:00

240 lines
7.1 KiB
Markdown

# 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