generated from personal-projects/leo-claude-mktplace
- 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>
240 lines
7.1 KiB
Markdown
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
|