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>
This commit is contained in:
2026-02-03 21:32:39 -05:00
parent 88c16c840b
commit 2dbb66deae
3 changed files with 354 additions and 81 deletions

239
CLAUDE.md Normal file
View File

@@ -0,0 +1,239 @@
# 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

View File

@@ -1,6 +1,6 @@
# Deployment Guide
This guide covers production deployment of the Gitea HTTP MCP Wrapper in various environments.
This guide covers production deployment of Gitea MCP Remote in various environments.
## Table of Contents
@@ -36,15 +36,15 @@ This guide covers production deployment of the Gitea HTTP MCP Wrapper in various
1. **Clone the repository:**
```bash
git clone https://github.com/lmiranda/gitea-mcp-remote.git
git clone https://gitea.hotserv.cloud/personal-projects/gitea-mcp-remote.git
cd gitea-mcp-remote
```
2. **Create configuration:**
```bash
cp .env.docker.example .env
nano .env # Edit with your values
cp docker/.env.example docker/.env
nano docker/.env # Edit with your values
```
Required configuration:
@@ -52,49 +52,49 @@ Required configuration:
GITEA_URL=https://gitea.example.com
GITEA_TOKEN=your_gitea_api_token
GITEA_OWNER=your_username_or_org
GITEA_REPO=your_default_repo
GITEA_REPO=your_default_repo # Optional
AUTH_TOKEN=your_bearer_token # Recommended
```
3. **Start the service:**
3. **Start the services (app + Caddy):**
```bash
docker-compose up -d
docker-compose -f docker/docker-compose.yml up -d
```
4. **Verify deployment:**
```bash
curl http://localhost:8000/health
curl http://localhost/health # Via Caddy
curl http://localhost:8080/health # Direct to app
```
### Production Configuration
For production, use a more robust `docker-compose.yml`:
The default `docker/docker-compose.yml` includes both app and Caddy reverse proxy services. For customization:
```yaml
version: '3.8'
services:
gitea-mcp-wrapper:
# Python MCP Server
app:
build:
context: .
dockerfile: Dockerfile
image: gitea-mcp-wrapper:latest
container_name: gitea-mcp-wrapper
context: ..
dockerfile: docker/Dockerfile
image: gitea-mcp-remote:latest
container_name: gitea-mcp-remote-app
restart: always
ports:
- "127.0.0.1:8000:8000" # Bind to localhost only
expose:
- "8080"
environment:
- GITEA_URL=${GITEA_URL}
- GITEA_TOKEN=${GITEA_TOKEN}
- GITEA_OWNER=${GITEA_OWNER}
- GITEA_REPO=${GITEA_REPO}
- GITEA_REPO=${GITEA_REPO:-}
- HTTP_HOST=0.0.0.0
- HTTP_PORT=8000
- AUTH_TOKEN=${AUTH_TOKEN}
- HTTP_PORT=8080
- AUTH_TOKEN=${AUTH_TOKEN:-}
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health').read()"]
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
retries: 3
@@ -107,9 +107,31 @@ services:
networks:
- gitea-mcp-network
# Caddy Reverse Proxy (HTTPS termination)
caddy:
image: caddy:2-alpine
container_name: gitea-mcp-remote-caddy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
app:
condition: service_healthy
networks:
- gitea-mcp-network
networks:
gitea-mcp-network:
driver: bridge
volumes:
caddy_data:
caddy_config:
```
### Docker Build Options
@@ -117,20 +139,20 @@ networks:
**Build the image:**
```bash
docker build -t gitea-mcp-wrapper:latest .
docker build -f docker/Dockerfile -t gitea-mcp-remote:latest .
```
**Build with specific Python version:**
```bash
docker build --build-arg PYTHON_VERSION=3.11 -t gitea-mcp-wrapper:latest .
docker build -f docker/Dockerfile --build-arg PYTHON_VERSION=3.11 -t gitea-mcp-remote:latest .
```
**Tag for registry:**
```bash
docker tag gitea-mcp-wrapper:latest registry.example.com/gitea-mcp-wrapper:latest
docker push registry.example.com/gitea-mcp-wrapper:latest
docker tag gitea-mcp-remote:latest registry.example.com/gitea-mcp-remote:latest
docker push registry.example.com/gitea-mcp-remote:latest
```
## Security Best Practices
@@ -218,7 +240,7 @@ Docker automatically monitors the health check and can restart if unhealthy:
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
retries: 3

110
README.md
View File

@@ -1,18 +1,22 @@
# Gitea HTTP MCP Wrapper
# Gitea MCP Remote
An HTTP transport wrapper around the official Gitea MCP server that enables AI assistants like Claude Desktop to interact with Gitea repositories via HTTP. This wrapper provides authentication, tool filtering, and HTTP transport while delegating Gitea operations to the official `gitea-mcp-server`.
An HTTP transport server that exposes Gitea operations via the MCP Streamable HTTP protocol for AI assistants like Claude Desktop. This server imports tools from the marketplace `gitea-mcp-server` package and serves them over HTTP with authentication and tool filtering.
## Architecture
This is NOT a standalone MCP server. It's an HTTP wrapper that:
1. Wraps the official `gitea-mcp-server` (stdio transport)
2. Provides HTTP transport for Claude Desktop compatibility
3. Adds Bearer token authentication
4. Filters tools for Claude Desktop compatibility
5. Proxies requests between HTTP and stdio transport
This is NOT a standalone MCP server. It imports tool definitions from the marketplace package and serves them:
1. Imports tools from `gitea-mcp-server` marketplace package
2. Serves via MCP Streamable HTTP protocol (`/mcp` endpoint)
3. Adds Bearer token authentication (optional)
4. Provides tool filtering (whitelist/blacklist)
5. Health check endpoints for monitoring
```
Claude Desktop (HTTP) → HTTP Wrapper → Gitea MCP Server (stdio) → Gitea API
Claude Desktop (HTTP) ──▶ gitea-mcp-remote ──imports──▶ gitea-mcp-server ──API──▶ Gitea
├── Authentication (Bearer token)
├── Tool Filtering
└── MCP Streamable HTTP protocol
```
## Features
@@ -33,27 +37,27 @@ Claude Desktop (HTTP) → HTTP Wrapper → Gitea MCP Server (stdio) → Gitea AP
## Quick Start with Docker
The easiest way to deploy is using Docker Compose:
The easiest way to deploy is using Docker Compose with Caddy reverse proxy:
```bash
# 1. Clone the repository
git clone https://github.com/lmiranda/gitea-mcp-remote.git
git clone https://gitea.hotserv.cloud/personal-projects/gitea-mcp-remote.git
cd gitea-mcp-remote
# 2. Create .env file from template
cp .env.docker.example .env
cp docker/.env.example docker/.env
# 3. Edit .env with your Gitea credentials
nano .env
nano docker/.env
# 4. Start the server
docker-compose up -d
# 4. Start the services (app + Caddy)
docker-compose -f docker/docker-compose.yml up -d
# 5. Check health
curl http://localhost:8000/health
curl http://localhost/health
```
The server will be available at `http://localhost:8000`.
The server will be available at `http://localhost` (Caddy) or `http://localhost:8080` (direct).
See [DEPLOYMENT.md](DEPLOYMENT.md) for detailed deployment instructions.
@@ -96,11 +100,13 @@ The wrapper uses environment variables or a `.env` file for configuration.
GITEA_URL=https://gitea.example.com
GITEA_TOKEN=your_gitea_api_token_here
GITEA_OWNER=your_username_or_org
GITEA_REPO=your_repo_name
# HTTP Server
HTTP_HOST=127.0.0.1 # Use 0.0.0.0 in Docker
HTTP_PORT=8000
# Optional
GITEA_REPO=your_repo_name # Can be omitted, specified per-request
# HTTP Server (defaults)
HTTP_HOST=0.0.0.0
HTTP_PORT=8080
```
### Optional Configuration
@@ -131,6 +137,7 @@ DISABLED_TOOLS=delete_issue,close_milestone # Blacklist mode
#### With Docker
```bash
cd docker
docker-compose up -d
```
@@ -144,19 +151,19 @@ nano .env
# Run the server
gitea-mcp-remote
# Or use the startup script
./scripts/start.sh
```
The server will start on the configured host/port (default: `http://127.0.0.1:8000`).
The server will start on the configured host/port (default: `http://0.0.0.0:8080`).
### HTTP Endpoints
#### Health Check
```bash
GET /health
GET /healthz
GET /ping
Response: {"status": "healthy"}
Response: {"status": "ok"}
```
#### MCP Protocol Endpoint
@@ -227,7 +234,7 @@ Configure Claude Desktop to use the HTTP wrapper:
{
"mcpServers": {
"gitea": {
"url": "http://localhost:8000",
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
@@ -259,44 +266,49 @@ pip install -e ".[dev]"
```bash
# Run all tests
pytest
pytest tests/ -v
# Run with coverage
pytest --cov=gitea_mcp_remote
pytest tests/ --cov=gitea_mcp_remote
# Run specific test file
pytest src/gitea_mcp_remote/tests/test_config.py
pytest tests/test_mcp_endpoints.py -v
```
### Project Structure
```
gitea-mcp-remote/
├── src/
│ └── gitea_mcp_remote/
├── src/gitea_mcp_remote/ # Main package
│ ├── __init__.py
├── server.py # Main HTTP server
├── config/
│ ├── server_http.py # MCP HTTP server
│ ├── config/ # Configuration module
│ │ ├── __init__.py
│ └── settings.py # Configuration loader
├── middleware/
│ │ └── settings.py
│ ├── middleware/ # HTTP middleware
│ │ ├── __init__.py
│ └── auth.py # HTTP authentication
├── filtering/
├── __init__.py
└── filter.py # Tool filtering
│ └── tests/ # Test suite
│ │ └── auth.py
└── filtering/ # Tool filtering
│ ├── __init__.py
│ └── filter.py
── tests/ # Test suite (at repo root)
│ ├── conftest.py
│ ├── test_config.py
│ ├── test_filtering.py
── test_middleware.py
├── Dockerfile # Docker image
├── docker-compose.yml # Docker orchestration
── test_middleware.py
│ └── test_mcp_endpoints.py
├── docker/ # Docker infrastructure
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── Caddyfile
│ └── .env.example
├── scripts/ # Utility scripts
│ ├── start.sh
│ └── healthcheck.sh
├── pyproject.toml # Project config
├── requirements.txt # Dependencies
├── .env.example # Config template
├── .env.docker.example # Docker config template
├── README.md # This file
├── CLAUDE.md # Claude Code guidance
└── DEPLOYMENT.md # Deployment guide
```
@@ -376,7 +388,7 @@ MIT License - see LICENSE file for details
## Version
Current version: 0.1.0
Current version: 0.2.0
## Author
@@ -384,7 +396,7 @@ Leo Miranda
## Links
- Repository: https://github.com/lmiranda/gitea-mcp-remote
- Issues: https://github.com/lmiranda/gitea-mcp-remote/issues
- Official Gitea MCP Server: https://github.com/modelcontextprotocol/servers/tree/main/src/gitea
- Repository: https://gitea.hotserv.cloud/personal-projects/gitea-mcp-remote
- Issues: https://gitea.hotserv.cloud/personal-projects/gitea-mcp-remote/issues
- Marketplace Package: https://gitea.hotserv.cloud/personal-projects/leo-claude-mktplace/src/branch/main/mcp-servers/gitea
- MCP Documentation: https://modelcontextprotocol.io