MCP server exposing Forgejo as LLM-callable tools
  • Python 97.4%
  • Dockerfile 2.6%
Find a file
2026-05-26 12:09:46 -06:00
.env.example Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
.gitignore Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
Dockerfile Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
forgejo_client.py Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
LICENSE Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
README.md Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
requirements.txt Initial commit: forgejo-mcp v0.1 2026-05-26 11:45:19 -06:00
server.py Allow public hostname through DNS rebinding protection 2026-05-26 12:09:46 -06:00

forgejo-mcp

A Model Context Protocol (MCP) server that exposes a Forgejo instance as LLM-callable tools. Reads repositories, files, commits, and issues; can create issues and post comments. Runs as a Streamable HTTP server with bearer-token auth, deployable behind any reverse proxy.

Built as a working portfolio piece for Skip's Forgejo at https://git.opensourcesecurity.net. The deployed instance lets evaluators hand a token to Claude (or any MCP-compatible client) and explore the codebase by natural language: "list the repos", "read the README from glassbox", "what's Skip been working on in safenet lately?"

Tools

Tool Type What it does
forgejo_whoami read Health check: returns the authenticated user.
forgejo_list_repos read All repos in an organization, slimmed to LLM-friendly fields.
forgejo_get_repo read Detailed metadata for one repo.
forgejo_get_file_contents read Read a file from a repo. Handles base64 decode, binary detection, size caps.
forgejo_list_commits read Recent commit history of a repo.
forgejo_list_issues read Open issues, optionally filtered by repo or state.
forgejo_search_repos read Search repos by name/description.
forgejo_create_issue write Open a new issue. Authored by the token's owner.
forgejo_comment_issue write Comment on an existing issue.

Tool annotations (readOnlyHint, destructiveHint, etc.) are set per the MCP spec so clients can make informed decisions about confirmation prompts.

Public endpoint

https://mcp.opensourcesecurity.net/mcp

Bearer token required. Contact Skip for an evaluator token if you're reviewing portfolio work.

Architecture

LLM client (Claude Desktop, Inspector, etc.)
        |
        | JSON-RPC over Streamable HTTP + Bearer auth
        v
+---------------------+      +-------------------+
|    server.py        | ---> | forgejo_client.py |
|    (FastMCP)        |      | (httpx wrapper)   |
+---------------------+      +-------------------+
                                       |
                                       v
                              https://git.opensourcesecurity.net
                                  (Forgejo HTTP API)

Two-file design:

  • server.py knows MCP; declares tools, handles auth, runs uvicorn.
  • forgejo_client.py knows Forgejo; wraps httpx, shapes API responses.

Neither knows about the other's concerns. Either could be replaced independently (different MCP framework, different git forge).

Running locally

git clone https://git.opensourcesecurity.net/opensourcesecurity/forgejo-mcp.git
cd forgejo-mcp
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env with your Forgejo token and a fresh bearer token
python server.py

Then in another terminal, point the MCP Inspector (npx @modelcontextprotocol/inspector) at http://127.0.0.1:8765/mcp with your bearer token in the Authorization header.

Running in Docker

docker build -t forgejo-mcp:latest .
docker run -d \
  --name forgejo-mcp \
  --env-file .env \
  -e MCP_BIND_HOST=0.0.0.0 \
  -p 8765:8765 \
  forgejo-mcp:latest

The MCP_BIND_HOST=0.0.0.0 override is required for the container's port publish to work (the .env default of 127.0.0.1 is for laptop dev).

Security model

  • Server requires Authorization: Bearer <token> on every request.
  • Token comes from MCP_BEARER_TOKEN env var; the server refuses to start if it's not set.
  • Token comparison is a plain string compare; for higher-security deployments, switch to secrets.compare_digest() (one-line change).
  • The Forgejo token (FORGEJO_TOKEN) is what limits what the MCP server can DO. The bearer token is what limits WHO can use the MCP server. Treat both as secrets.

Built with

License

BSD 2-Clause. See LICENSE.