forgejo-mcp-gateway
Provides tools for interacting with a Forgejo instance through its API, enabling repository browsing, file and branch management, issue and pull request workflows, code reviews, merges, releases, and action run listing, with permissions limited by the user's Forgejo access token.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
forgejo-mcp-gateway
An MCP server for Forgejo that many people can share, and that hosted assistants such as ChatGPT can connect to.
Every request acts as one Forgejo user, with that user's own access token, so an assistant can do exactly what the token allows and nothing more. The gateway accepts two kinds of connection:
OAuth, for hosted assistants. ChatGPT connects through the gateway's built-in OAuth server. On the consent page, the person pastes a Forgejo access token. The gateway checks it with Forgejo, stores it encrypted and acts with it from then on.
Tokens, for everything else. Claude Code, scripts and other MCP clients send a Forgejo access token as the bearer token, and the gateway passes it through.
The gateway is the only thing you expose. Forgejo itself can stay on your private network: the gateway talks to it over the LAN, and the internet only ever reaches the gateway's MCP and OAuth paths.
ChatGPT ──HTTPS──▶ /mcp, /oauth/*, /.well-known/* ┐
Claude Code ─────▶ /mcp (Forgejo token) ├─ forgejo-mcp-gateway ──LAN──▶ Forgejo /api/v1
┘ (SQLite: grants, encrypted tokens)Tools
Read | Write |
|
|
|
|
|
|
|
There are no admin, delete or settings tools. Writes are guarded against races:
write_fileneeds the file's currentshato replace it, so it never overwrites a file blind.merge_pull_requestaccepts the head commit the reviewer saw, and refuses the merge if anything was pushed since.
List tools page through results and say when more pages exist. File contents, issue bodies and diffs always come back whole.
Related MCP server: Forgejo MCP
Quick start
cp .env.example .env # set FORGEJO_URL, and PUBLIC_URL + SECRET_KEY for OAuth
openssl rand -hex 32 # a SECRET_KEY
docker compose -f docker-compose.example.yml up -d
curl http://localhost:8080/healthzThe container runs as a non-root user on a read-only filesystem. It keeps its state in one SQLite file on the /data volume: pending authorization requests, connections, hashed OAuth tokens and encrypted Forgejo tokens.
Configuration
Variable | Default | |
| required | How the gateway reaches Forgejo, e.g. |
|
| The Forgejo address people open in a browser. Used for links on the consent page. |
| unset | This gateway's public HTTPS address, which is also the OAuth issuer. Set it together with |
| unset | At least 32 random bytes, hex or base64. It keys every stored hash and encrypts stored Forgejo tokens. Changing it disconnects every OAuth connection. |
|
| Accept a Forgejo access token directly as the bearer token. |
| ChatGPT | JSON list of |
| unset | The header your proxy sets to the caller's address, e.g. |
|
| |
|
| Limits |
|
| Limits the OAuth pages and the token endpoint per caller address. |
|
| Reads are retried with backoff on timeouts, 429 and 5xx. Writes are never retried. |
|
| How long a verified Forgejo token is trusted before Forgejo is asked again. |
|
| Logs are JSON, one line per event. Each tool call logs the user, tool, outcome and latency. |
Exposing it
Hosted assistants call the gateway from their own servers, so it needs a public HTTPS address. Route only these paths to it, and keep everything else (including Forgejo itself) private:
^/(mcp$|\.well-known/oauth-(authorization-server|protected-resource)|oauth/)With Cloudflare Tunnel, that is an ingress rule with this path, and the service pointing at the gateway, never at Forgejo. With Caddy:
forgejo-mcp.example.com {
@gateway path_regexp ^/(mcp$|\.well-known/oauth-(authorization-server|protected-resource)|oauth/)
handle @gateway {
reverse_proxy gateway:8080
}
handle {
respond 404
}
}/healthz is meant for your own monitoring, so leave it off the public route.
Connecting
ChatGPT. Add a connector with the MCP server URL https://<PUBLIC_URL>/mcp and OAuth authentication. ChatGPT finds the authorization server on its own. When the consent page opens, create a Forgejo access token under Settings → Applications and paste it. The token needs at least read:user, plus the repository and issue scopes you want ChatGPT to have. To disconnect, remove the connector in ChatGPT. Deleting the token in Forgejo cuts the connection off at once, and the gateway then revokes it.
Claude Code and other clients that can send a header:
claude mcp add --transport http forgejo https://<PUBLIC_URL>/mcp \
--header "Authorization: Bearer <forgejo-access-token>"Security model
Permissions. A connection can do what its Forgejo token can do, and no more.
OAuth. The OAuth server is a fixed subset of OAuth 2.1:
authorization code with PKCE S256 only;
exact client and redirect matching (no dynamic registration, no outbound fetches);
resource indicators (RFC 8707) and
isson responses (RFC 9207).
Consent page. The consent request is bound to the browser that started it. The page refuses cross-origin posts and can't be framed.
Token lifetimes. Access tokens are opaque and last one hour. They're checked on every call, so a revoked connection stops working at once.
Replay protection. Refresh tokens rotate, and each works once. Reusing a refresh token or an authorization code revokes the whole connection.
Storage. Nothing secret is stored in the clear. OAuth tokens, codes and browser secrets are stored as keyed hashes. Forgejo tokens are encrypted with AES-256-GCM, and each ciphertext is bound to its row.
Refused tokens. If Forgejo stops accepting a connection's token, the gateway revokes that connection, and the assistant has to reconnect.
Development
uv sync
uv run pytest # offline: OAuth refusal paths, settings, crypto
uv run ruff check && uv run mypyThe live suite runs every tool and the full ChatGPT connection flow against a running gateway and a real Forgejo. Give it a scratch repository owned by the token's user; the suite opens branches, files, issues and pull requests there, and merges them.
GATEWAY_URL=http://localhost:8080 FORGEJO_TEST_TOKEN=... FORGEJO_TEST_REPO=user/sandbox \
uv run pytest -m liveThe gateway keeps its state in SQLite, so run a single replica. Rate limits are also kept in that process's memory.
License
Apache-2.0
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
One OAuth connector for your team's remote MCP servers, with Tool Packs, guardrails and logs.
Hosted MCP for Google Workspace, Atlassian and Notion: one OAuth, per-user accounts, write access.
AI-native git hosting — repos, PRs, issues, CI gates, and AI code review over MCP (60 tools).
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with a Forgejo instance as an authenticated user, supporting issues, pull requests, repositories, and notifications.70 npmMIT
- AlicenseNot gradedqualityBmaintenanceA self-hosted MCP server and dashboard that provides governed, auditable AI access to a Forgejo instance, with tools for managing repositories, issues, pull requests, and more.3Apache 2.0
- FlicenseAqualityCmaintenanceEnables assistants to read Forgejo repositories and manage issues and pull requests directly from the working session, using the caller's own token against any Forgejo instance.13-
- AlicenseNot gradedqualityCmaintenanceThis MCP server enables users to interact with Forgejo instances through a finite, audited catalog of 33 tools covering users, repositories, issues, pull requests, and more, with explicit write controls and verified result envelopes.181 npmMIT