Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

forgejo-projects-mcp

An MCP server that lets an AI agent manage Forgejo Projects / Kanban boards, which Forgejo does not expose over its REST API.

It works by driving the same internal web routes the browser uses, authenticated with a session cookie. HTTP is done through Playwright's APIRequestContext, so no browser binary is downloaded — only the playwright Python package is needed. See forgejo-projects-automation-reference.md for the reverse-engineered endpoints this is built on.

⚠️ This is a janky backend — do not rely on it for production

Forgejo exposes no API for Projects/Kanban, so this tool resorts to browser-style automation: it logs in with a username and password, keeps a session cookie, and calls Forgejo's undocumented, unversioned internal web routes — scraping HTML to recover ids and board state. That is a fragile approach by nature:

  • These routes are not a public contract. A Forgejo upgrade (even a minor one) can change markup or routes and silently break tools here.
  • State is recovered by HTML scraping and regex, not a structured API, so parsing can drift.
  • It authenticates as a real user with a password, not a scoped API token, and performs writes with no transactional guarantees.
  • It was verified against one instance (v15.0.7) only.

Treat it as a best-effort convenience / stop-gap for personal or experimental use. Do not put it on a critical path, run it against data you can't afford to lose, or depend on it for production workflows. If/when Forgejo ships a real Projects API, migrate to it. Use at your own risk; test against a throwaway repo first.

Prerequisites

Installation

All methods install a forgejo-projects-mcp executable onto your PATH (in uv's tool bin directory). If uv warns that the directory isn't on your PATH, run uv tool update-shell once and restart your shell. Verify with forgejo-projects-mcp --help (or uv tool list).

No playwright install step is needed — the tool uses Playwright's HTTP layer, not a real browser.

Latest release (PyPI)

uv tool install forgejo-projects-mcp
uv tool upgrade forgejo-projects-mcp     # update later

Beta testing (latest from source)

Installs the current main branch straight from GitHub — newer than the last release, and not guaranteed stable:

uv tool install git+https://github.com/UnwantedForeignCloudProvider/ForgejoProjectsMCP
uv tool upgrade forgejo-projects-mcp     # re-pull the latest main

Local build (from a clone)

For development, or to install a specific checkout:

git clone https://github.com/UnwantedForeignCloudProvider/ForgejoProjectsMCP
cd ForgejoProjectsMCP
uv tool install .

To pick up local code changes automatically, install with uv tool install --editable .; to update after pulling changes, uv tool install . --force. To remove any of the above: uv tool uninstall forgejo-projects-mcp.

Configuration

Credentials come from environment variables:

Variable When required Example
FORGEJO_URL Always, so the cached session can be checked https://forge.example.com
FORGEJO_USERNAME When a fresh login is needed your-username
FORGEJO_PASSWORD When a fresh login is needed your-password

A .env file in the working directory is loaded automatically (via python-dotenv) — copy .env.example to .env and fill it in; no source/ export needed. Real environment variables already set (and an MCP client's own env block) take precedence. See .env.example for the full list, including the optional FORGEJO_MCP_MAX_CONCURRENCY, FORGEJO_MCP_RPS, and FORGEJO_MCP_LOG_LEVEL.

The authenticated session is cached at <config>/forgejo_projects_mcp/storage_state.json and refreshed automatically when it expires. <config> is $XDG_CONFIG_HOME if set, otherwise ~/.config — resolved in an OS-agnostic way (Linux, macOS, Windows) via Path.home(). A valid cached session can be reused with only FORGEJO_URL; username and password are requested again only when Forgejo requires a fresh login.

Run

export FORGEJO_URL=... FORGEJO_USERNAME=... FORGEJO_PASSWORD=...
uv run forgejo-projects-mcp            # stdio MCP server

Register with an MCP client

Once installed, reference the command directly:

{
  "mcpServers": {
    "forgejo-projects-mcp": {
      "command": "forgejo-projects-mcp",
      "env": {
        "FORGEJO_URL": "https://forge.example.com",
        "FORGEJO_USERNAME": "your-username",
        "FORGEJO_PASSWORD": "your-password"
      }
    }
  }
}

If your MCP client doesn't inherit your shell PATH, use the absolute path to the executable instead (find it with which forgejo-projects-mcp, or where forgejo-projects-mcp on Windows).

Agent installation

After uv tool install ., the forgejo-projects-mcp stdio command is on your PATH. Register it with your agent below (replace the credential values). If the command isn't found, use its absolute path (which forgejo-projects-mcp).

Claude Code
claude mcp add forgejo-projects-mcp \
  -e FORGEJO_URL=https://forge.example.com \
  -e FORGEJO_USERNAME=your-username \
  -e FORGEJO_PASSWORD=your-password \
  -- forgejo-projects-mcp
Codex
codex mcp add forgejo-projects-mcp \
  --env FORGEJO_URL=https://forge.example.com \
  --env FORGEJO_USERNAME=your-username \
  --env FORGEJO_PASSWORD=your-password \
  -- forgejo-projects-mcp
Qwen Code
qwen mcp add forgejo-projects-mcp \
  -e FORGEJO_URL=https://forge.example.com \
  -e FORGEJO_USERNAME=your-username \
  -e FORGEJO_PASSWORD=your-password \
  forgejo-projects-mcp
OpenClaw
openclaw mcp add forgejo-projects-mcp \
  --command forgejo-projects-mcp \
  --env FORGEJO_URL=https://forge.example.com \
  --env FORGEJO_USERNAME=your-username \
  --env FORGEJO_PASSWORD=your-password
opencode

opencode's opencode mcp add is an interactive wizard (no inline env flags), so add it to opencode.json instead:

{
  "mcp": {
    "forgejo-projects-mcp": {
      "type": "local",
      "command": ["forgejo-projects-mcp"],
      "environment": {
        "FORGEJO_URL": "https://forge.example.com",
        "FORGEJO_USERNAME": "your-username",
        "FORGEJO_PASSWORD": "your-password"
      }
    }
  }
}
Hermes

Hermes is config-file based — add to ~/.hermes/config.yaml:

mcp_servers:
  forgejo-projects-mcp:
    command: forgejo-projects-mcp
    env:
      FORGEJO_URL: https://forge.example.com
      FORGEJO_USERNAME: your-username
      FORGEJO_PASSWORD: your-password

Tools

Session & discovery

  • forgejo_status — check authentication
  • authenticate(force=False) — log in / refresh session
  • list_repositories(query, limit, page) — repos the user can access (pick one to work in)

Projects

  • list_projects(owner, repo, state)
  • create_project(owner, repo, title, description, card_type)
  • get_project(owner, repo, project_id) — board with columns + cards
  • update_project(...), close_project(...), reopen_project(...), delete_project(...)

Columns

  • create_column, edit_column, delete_column, set_default_column

Cards / issues

  • create_issue(... project_id=) — create an issue, optionally straight onto a board
  • add_issues_to_project, remove_issues_from_project
  • move_card(owner, repo, project_id, column_id, issue_numbers)
  • bulk_move_cards(owner, repo, project_id, moves) — move many cards, each to its own column, in one call (moves = list of {issue_number, column_id})
  • delete_issue

Bulk reads (run concurrently, rate-limited)

  • bulk_read_issues(owner, repo, issue_numbers, state="all") — lightweight summaries (number, title, state, milestone)
  • read_card(owner, repo, number) — one card's full content (body + comments) ⚠️
  • read_column(owner, repo, project_id, column_id, state="all", milestone=None) ⚠️
  • read_milestone(owner, repo, milestone_id, state="all", project=None) ⚠️
  • read_project(owner, repo, project_id, state="all", milestone=None) ⚠️

Optional filters on the readers use direct values (no name lookup): state (open/closed/all), and a milestone/project id (each tool omits the filter that is already its own subject).

The full readers take limit/offset to cap and page results, and return total / returned / truncated / error_count so cost and completeness are explicit. bulk_read_issues returns count (successful only) plus a separate errors list.

⚠️ = network- and token-expensive; use only when needed. Concurrency and request rate are tunable via FORGEJO_MCP_MAX_CONCURRENCY (default 8) and FORGEJO_MCP_RPS (default 5).

Error signaling. Tool failures are returned as MCP errors (isError: true) with a [CODE] message (e.g. [NOT_FOUND], [INVALID_STATE], [MILESTONE_NOT_FOUND], [NETWORK_ERROR]) — agents can detect failure without parsing content. Invalid state values and missing projects/columns/milestones/ issues are hard errors, not silent empty results. Individual issues that fail to read inside a bulk call are reported inline instead (partial success).

Milestones

  • list_milestones, create_milestone, edit_milestone, close_milestone, reopen_milestone, delete_milestone

Issue arguments use the repo issue number (what you see as #N); the server resolves the internal id automatically.

CLI (no MCP client needed)

For harnesses that can't speak MCP, forgejo-projects-cli exposes every tool as a subcommand, generated from the same tool definitions and dispatched in-process — so it stays in sync automatically. It reads the same FORGEJO_URL / FORGEJO_USERNAME / FORGEJO_PASSWORD env vars, prints the JSON result to stdout, logs to stderr, and exits non-zero on an error result.

When stdin and stderr are attached to a terminal, missing or rejected credentials are requested interactively. Password input is hidden, and login is retried up to three times. Prompted credentials stay in memory; only the normal Playwright session state is saved. Piped/automated CLI invocations and the forgejo-projects-mcp stdio server never prompt.

forgejo-projects-cli --help                      # lists every tool
forgejo-projects-cli <tool> --help               # options for one tool

forgejo-projects-cli list_repositories --query kanban
forgejo-projects-cli create_project --owner o --repo r --title "Q3"
forgejo-projects-cli read_project --owner o --repo r --project_id 3 --state open
forgejo-projects-cli bulk_move_cards --owner o --repo r --project_id 3 \
    --moves '[{"issue_number": 5, "column_id": 12}]'

Options mirror each tool's parameters (--owner, --repo, …); list/object parameters (--issue_numbers, --moves) take a JSON string.

Notes

  • Tested against Forgejo v15.0.7. The web routes are internal and unversioned, so a major Forgejo upgrade may require adjusting client.py.
  • The Forgejo session cookie does not authorize /api/v1, so everything runs through the web routes.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

forgejo_projects_mcp-0.1.0rc2.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

forgejo_projects_mcp-0.1.0rc2-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file forgejo_projects_mcp-0.1.0rc2.tar.gz.

File metadata

  • Download URL: forgejo_projects_mcp-0.1.0rc2.tar.gz
  • Upload date:
  • Size: 24.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for forgejo_projects_mcp-0.1.0rc2.tar.gz
Algorithm Hash digest
SHA256 cb4ce858c3c3920d822d9568d4881dd6a7a085e718275a7d24c3c1ae793787f8
MD5 9c42fda7ed4330ff8f77e8498b237d91
BLAKE2b-256 0bca1736dc04b42c1b8b47af4bb024835545e685ad9c15755ddb5d39f7903921

See more details on using hashes here.

Provenance

The following attestation bundles were made for forgejo_projects_mcp-0.1.0rc2.tar.gz:

Publisher: publish.yml on UnwantedForeignCloudProvider/ForgejoProjectsMCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file forgejo_projects_mcp-0.1.0rc2-py3-none-any.whl.

File metadata

File hashes

Hashes for forgejo_projects_mcp-0.1.0rc2-py3-none-any.whl
Algorithm Hash digest
SHA256 080aacbdf5c56c348f12223cafc7cde76d59bdeedb9af3313b3fcfaa6728b201
MD5 c2e1ba5a6bd23325b6681ee7d3241d93
BLAKE2b-256 44bedaacb7ffe99bc782e1db443b99ac02524a8e4fa2df86e7597294dbb68b01

See more details on using hashes here.

Provenance

The following attestation bundles were made for forgejo_projects_mcp-0.1.0rc2-py3-none-any.whl:

Publisher: publish.yml on UnwantedForeignCloudProvider/ForgejoProjectsMCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0rc2 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page