MCP server for Forgejo: connects LLM clients to issues, pull requests, repos, and more via the Model Context Protocol. Works standalone as an MCP server, as an OpenCode plugin, or directly as a CLI for the terminal. One tool, three ways to access the same Forgejo API.
  • TypeScript 99.6%
  • Shell 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Sebastian Schulz 7bc0309935
All checks were successful
ci / test (pull_request) Successful in 1m28s
fix(release): make bun pm pack build before packing
2026-09-10 11:50:48 +00:00
.forgejo/workflows ci(forgejo): gate on bun run knip 2026-09-09 13:12:37 +00:00
docs fix(release): make bun pm pack build before packing 2026-09-10 11:50:48 +00:00
scripts fix(release): make bun pm pack build before packing 2026-09-10 11:50:48 +00:00
src fix(opencode): drop unused watchActionRun import 2026-09-09 13:33:48 +00:00
.envrc docs: rename forgejo-mcp references to forgejoctl across all docs 2026-09-01 09:38:59 +00:00
.gitignore feat(core): add swagger-derived api types to source tree 2026-08-25 21:49:00 +00:00
AGENTS.md docs(agents): add knip to the lint gate list 2026-09-09 13:13:57 +00:00
biome.json fix(lint): delete unused run_id, exclude generated api-schema.ts from biome, apply biome formatting 2026-09-01 15:22:39 +00:00
bun.lock chore(deps): add knip devDependency and run script 2026-09-09 13:07:32 +00:00
knip.jsonc chore(knip): triage default-config report to zero 2026-09-09 13:12:09 +00:00
LICENSE Initial commit 2026-08-25 08:56:38 +00:00
mise.toml fix(release): make bun pm pack build before packing 2026-09-10 11:50:48 +00:00
opencode.jsonc fix(lint): resolve pre-existing biome errors blocking CI 2026-09-04 21:03:14 +00:00
package.json fix(ci): switch knip to the Bun runtime binary 2026-09-09 13:23:38 +00:00
README.md docs(copy): polish releases & tags user-facing copy 2026-09-04 13:45:33 +00:00
tsconfig.json feat: scaffold hello-world across all three adapters 2026-08-25 12:27:46 +00:00

forgejoctl

Talk to your Forgejo from your terminal, editor, or LLM client. One tool, three ways in.

What you can do

Pull requests

  • list_pull_requests
  • get_pull_request
  • create_pull_request
  • update_pull_request

Issues

  • list_issues
  • get_issue
  • create_issue
  • update_issue
  • list_issue_comments
  • create_issue_comment

Actions

  • list_action_runs
  • get_action_run
  • list_action_run_jobs
  • get_action_run_job_log
  • get_action_run_logs
  • watch_action_run
  • dispatch_workflow
  • cancel_action_run

Releases & tags

Manage repository releases and git tags.

  • list_releases
  • get_release
  • create_release
  • update_release
  • delete_release
  • list_tags
  • get_tag
  • create_tag
  • delete_tag
  • list_release_assets
  • delete_release_asset
  • release_asset_upload (CLI only)

Release and tag addressing is tag-only in v1 — pass tag="latest" to get_release to resolve the latest non-prerelease, non-draft release. Assets are addressed by (tag, asset_name). Binary asset upload is intentionally CLI-only: the MCP stdio transport has no binary content blocks for outbound responses, and the CLI is the natural CI consumer with the file path on disk.

A get_version tool is also available for smoke testing.

Three ways to use it

CLI

Install once. Run subcommands from any checkout with an origin remote pointing to your Forgejo host.

bunx @sebatec-eu/forgejoctl version

Or, if you cloned the source:

bun run build
FORGEJO_URL=https://forge.example.org ./dist/forgejoctl version

Note

The package is published to the Forgejo package registry at https://forge.sebatec.eu/api/packages/sebatec-eu/npm/, not npmjs.org. bunx defaults to npmjs.org and will not find it there. Add a .npmrc so npm / Bun resolve @sebatec-eu/* from the Forgejo registry. Downloads are public — no token required.

MCP server

Wire it into any MCP-compatible client (Claude Desktop, VS Code, Cursor, OpenCode, etc.) as a local stdio server. The host comes from FORGEJO_URL; owner and repo are passed per call.

{
  "mcpServers": {
    "forgejo": {
      "command": "bunx",
      "args": ["@sebatec-eu/forgejoctl"],
      "env": { "FORGEJO_URL": "https://forge.example.org" }
    }
  }
}

OpenCode plugin

Drop it into opencode.jsonc. Call the tools from any OpenCode session in a checkout with an origin remote pointing to your Forgejo host.

{
  "plugin": ["@sebatec-eu/forgejoctl"]
}

Configuration

Variable MCP server CLI / OpenCode plugin Notes
FORGEJO_URL required optional Default Forgejo host. Scheme included (https://...).
FORGEJO_TOKEN optional optional API token, sent as Authorization: token <token>. Fallback when FORGEJO_TOKEN_FILE is unset.
FORGEJO_TOKEN_FILE optional optional Path to a file containing the API token. Defaults to /run/secrets/forgejo-token. Takes precedence over FORGEJO_TOKEN.

The CLI and OpenCode plugin infer host, owner, and repo from the origin git remote. FORGEJO_URL is a fallback they consult only when the cwd has no checkout or no origin. The MCP server has no working directory to inspect, so FORGEJO_URL is the only way it learns the host.

Commands

A quick tour:

# Hello world
forgejoctl version

# Pull requests
forgejoctl pr list
forgejoctl pr view 7
forgejoctl pr create -t "Add feature" -H feature -B main

# Actions
forgejoctl run list
forgejoctl run view 13
forgejoctl run watch 13
forgejoctl run dispatch ci.yml --ref main --input env=prod
forgejoctl run logs 13 --tail 200

# Releases & tags
forgejoctl release list
forgejoctl release view latest
forgejoctl release view v1.2.3
forgejoctl release create --tag v1.2.3 --name "v1.2.3" --body "release notes"
forgejoctl release update v1.2.3 --name "v1.2.3"
forgejoctl release delete v1.2.3 --delete-tag true
forgejoctl release asset list v1.2.3
forgejoctl release asset upload v1.2.3 dist/foo.tar.gz
forgejoctl tag list
forgejoctl tag view v1.2.3
forgejoctl tag create --tag v1.2.3 --message "annotated tag"
forgejoctl tag delete v1.2.3

Run forgejoctl <subcommand> --help for the full grammar of any subcommand.

Where to go next