npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yumiku/mcp-forgejo

v0.2.3

Published

Model Context Protocol (MCP) server for self-hosted Forgejo. Exposes 32 tools for repos, branches, files, issues, PRs, releases, tags, and wikis via the Forgejo REST API.

Readme

@yumiku/mcp-forgejo

Model Context Protocol (MCP) server for self-hosted Forgejo (and Gitea-compatible) instances. Exposes 32 tools covering repositories, branches, files, issues, pull requests, releases, tags, and wikis.

工具清单(33)

| 类别 | 工具 | 备注 | |---|---|---| | 身份 (1) | get_current_user | 返 {login, source: "env"\|"probe", is_admin} | | 仓库 (5) | list_repos, get_repo, create_repo, edit_repo, delete_repo | delete_repo 需 destructive=true;list_repos 省略 owner 时 fallback 到 identity | | 分支 (4) | list_branches, get_branch, create_branch, delete_branch | delete_branch 需 destructive=true | | 文件 (3) | list_files, read_file, write_file | write_file 不支持删除(用 git CLI) | | Issue (5) | list_issues, get_issue, create_issue, edit_issue, comment_issue | Forgejo 把 PR 当 issue;comment_issue 同时给 PR 评论 | | PR (7) | list_pull_requests, get_pull_request, create_pull_request, merge_pull_request, set_issue_state, set_pull_request_state, review_pull_request | set_*_state 拆为 issue / PR 两条;review_pull_request 支持 APPROVE / REQUEST_CHANGES / COMMENT / PENDING | | Release (3) | list_releases, get_release, create_release | | | Tag (2) | list_tags, delete_tag | delete_tag 需 destructive=true | | Wiki (3) | list_wiki_pages, get_wiki_page, edit_wiki_page | create/update 分流:POST /wiki/new + PATCH /wiki/page/{sub_url} |

v0.1.1 新行为(list 工具)

所有 list_* 工具现在返回统一信封:

{
  "ok": true,
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 30,
    "total": 237,
    "has_more": true,
    "next_page": 2
  },
  "view": "summary"
}

view 字段(可选,默认 "summary"):

  • "summary":去除 email、压缩 user/author 对象为 {login, id},减小 LLM 上下文
  • "full":返回 Forgejo 原始字段(含 email、avatar_url、bio 等)

list_issues 额外支持 type 字段(可选,默认 all):

  • "issue":只返回真 issue
  • "pull_request":只返回 PR(Forgejo 把 PR 存为 issue,所以也走这个端点)
  • "all":默认行为

错误信封:

  • 默认:上游 body 不暴露(避免内网 IP / 邮箱 / token 等敏感信息泄露到 LLM 上下文)
  • 设置 FORGEJO_DEBUG=1 后:debug.upstream_body 字段出现,便于排错

v0.1.0 → v0.1.1 升级说明

list_* 工具的响应从 {ok, data} 变为 {ok, data, pagination, view}。如果你之前直接读 result.data,仍然兼容(数组还是数组),但 data 里的对象默认字段少了——需要全字段请显式传 view: "full"。

v0.1.1 → v0.2.0 升级说明

  • 新增 get_current_user 工具:返 {login, source: "env"|"probe", is_admin}。identity 在 startup 解析一次(不每次实时探测)。
  • 新增 FORGEJO_USER 配置:可选。不设 = 现状(启动 GET /user 探测)。设了 = 显式身份 + 探测仅作 drift 检测。
  • 新增 identity 概念:ToolCtx 上挂 identity: {login, source} 和 isAdmin: boolean。list_repos 省略 owner 时 fallback 链变成 args.owner → ctx.identity.login → ctx.defaultOwner → /api/v1/user/repos。
  • 行为变更:env 设了 FORGEJO_USER 后,启动时 probe 失败 不再 exit 1,改为 stderr 警告 + 用 env 值继续。这是 v0.2.0 的 breaking change——若需保留旧行为,去掉 FORGEJO_USER。
  • 新增 error code:identity_unknown(get_current_user 在 identity 缺失时抛)。

v0.2.0 → v0.2.1 升级说明

补丁版,无新工具、无 API 变更、无字段重命名(v0.2.0 用户的 .env 零变动)。只做:

  • 代码去敏化:v0.2.0 几个 test 文件误用了真实账号 yumiko 作为 fixture,已替换为通用假名 alice。
  • ToolCtx 重构:8 个工具文件 + listWrapper.ts 各有本地 interface ToolCtx 重复定义(v0.1.1 → v0.2.0 累积 9 处)。v0.2.1 抽到 src/tools/_ctx.ts 共享。未来加 ToolCtx 字段只需改 1 处。
  • 文档澄清:README 加"USER vs DEFAULT_OWNER"专题 + 4 场景例子,避免两个字段的命名歧义(identity vs guard 兜底)。

v0.2.1 → v0.2.2 升级说明

安全补丁版,无新工具、无 API 变更、零字段重命名。修复 4 项安全漏洞 + 1 项 minimatch hardening:

  • F-001 Path traversal 防御——get_repo(owner="..", repo="admin/users") 之前能被规整成 /api/v1/admin/users。v0.2.2 加 validateSegment + validatePathSegments 拒 ./../控制字符。8 个工具文件 72 处 user-input path segment 调它。
  • F-002 create_repo allow-list 绕过——之前 create_repo 不走 assertRepoAllowed。v0.2.2 加 FORGEJO_ALLOW_CREATE_REPO=1 flag(默认 false——拒绝任何 create_repo 调用)。需要创建仓的用户需显式加这一行 env。
  • F-004 错误 message 通用化——之前 ForgejoError.message 默认含上游 body 文本(HTML/JSON 含内网 IP/邮箱/诊断)。v0.2.2 改为 HTTP <status> <code-name> 通用格式。body 仍存 upstream.body(需 FORGEJO_DEBUG=1 暴露)。
  • F-006 summary 实际剥 email——stripEmail 之前写了但 applyView 没调。v0.2.2 修——view=summary 现在递归剥 email。
  • F-013 minimatch nonegate——之前 minimatch 默认支持 !pat 当 deny-list(!alice/private 实际允许其他)。v0.2.2 加 nonegate: true。

.env 影响:唯一新变量是 FORGEJO_ALLOW_CREATE_REPO(可选)。其他变量 0 变动。

v0.2.2 → v0.2.3 升级说明

卫生+剩余安全补丁。1 个 breaking change(F-015):

  • F-008 Identity verified 字段 — get_current_user 工具返的 envelope 多一个 is_verified: boolean 字段。LLM 看到 is_verified: false 知道 env 与 probe 不一致或 probe 失败,identity 不可全信。
  • F-009 日志 sanitize — stderr 日志里的 env 值 / probe 消息控制字符(含 \n)被 strip,防止日志伪造。
  • F-005 debug cap + redact — FORGEJO_DEBUG=1 模式下 debug.upstream_body 64KB 截断、敏感 key(email/token/password 等)替 [redacted]、控制字符替 ?。
  • F-007 DoS size cap — buildPath 拒 path > 2KB、query > 100;上游 body 64KB 截断。
  • F-010 lockfile 根 name 修 — package-lock.json 根从 @local/mcp-forgejo 改 @yumiku/mcp-forgejo。
  • F-011 prepublishOnly 加 dry-run — npm run typecheck && npm test && npm run build && npm pack --dry-run 强制 tarball 校验。
  • F-015 destructive 范围扩展(breaking) — merge_pull_request / write_file / review_pull_request 3 个工具必须传 destructive: true 才能调用。HIGH_RISK_TOOLS 3 → 6。v0.2.x 用户在 ZCode/Cursor 调这 3 工具会突然失败——请通知并升级 client 调用方式。

.env 影响:0(FORGEJO_DEBUG 已存在;F-007/008/009/010 全部代码层)。

安装(ZCode / Cursor / Claude Desktop 一致)

通过 npm(推荐):

npm install -g @yumiku/mcp-forgejo

或本地开发:

git clone <this-repo-url>
cd forgejo-mcp
npm install
npm run build

配置

需要 4–5 个环境变量。占位符约定:<your-forgejo-host> 替换为你的实例主机名或 IP(如 forgejo.example.com),<port> 替换为实际端口(默认 3000),<owner> / <username> 替换为你的 Forgejo 用户名,<your-token> 替换为你的 Personal Access Token。

| 变量 | 必填 | 默认 | 说明 | |---|---|---|---| | FORGEJO_BASE_URL | ✅ | — | 例:http://<your-forgejo-host>:<port> | | FORGEJO_TOKEN | ✅ | — | Forgejo Personal Access Token | | FORGEJO_ALLOWED_REPOS | ❌ | '' | 逗号分隔 minimatch 模式,例:<owner>/* | | FORGEJO_DEFAULT_OWNER | ❌ | — | list_repos 省略 owner 时的次级 fallback(identity 优先) | | FORGEJO_USER | ❌ | — | 当前用户显式身份(不设则启动时 GET /user 探测)。设了之后:get_current_user 返它;list_repos 省略 owner 时用它。若与 token 实际归属不符,stderr 输出 drift 警告 | | FORGEJO_DEBUG | ❌ | '' | 1 启用调试;错误信封含 debug.upstream_body | | FORGEJO_HTTP_TIMEOUT_MS | ❌ | 15000 | HTTP 超时(毫秒) |

FORGEJO_USER vs FORGEJO_DEFAULT_OWNER

两个字段都涉及"用户名",但用途不同——把它们指向同一逻辑用户才能避免怪行为。

| 字段 | 答的问题 | 影响范围 | |---|---|---| | FORGEJO_USER | 我是谁(identity) | get_current_user 工具 + list_repos owner fallback(优先) | | FORGEJO_DEFAULT_OWNER | 白名单为空时默认放行谁(guard 兜底) | 写工具的白名单匹配(patterns 空时隐式放行 <owner>/*) |

4 个典型配置:

  1. 最小配置(最常见)——只配白名单:

    FORGEJO_ALLOWED_REPOS=<owner>/*
    # FORGEJO_USER 不设 → 启动时 GET /user 探测
    # FORGEJO_DEFAULT_OWNER 不设 → guard 无兜底
  2. 显式身份——避免启动时探测:

    FORGEJO_USER=<owner>
    FORGEJO_ALLOWED_REPOS=<owner>/*

    get_current_user 返 source: "env";token 实际归属不同时会 stderr drift 警告。

  3. 懒得写白名单——用 defaultOwner 兜底:

    FORGEJO_USER=<owner>
    FORGEJO_ALLOWED_REPOS=          # 留空
    FORGEJO_DEFAULT_OWNER=<owner>     # guard 隐式放行 <owner>/*
  4. 不一致示例(应当避免)——USER 和 DEFAULT_OWNER 指向不同用户名:

    FORGEJO_USER=alice               # 显式身份 alice
    FORGEJO_ALLOWED_REPOS=yumiko/*   # 但白名单只要 yumiko
    FORGEJO_DEFAULT_OWNER=yumiko     # guard 也只允 yumiko

    alice token 配上面 → alice 自己的仓被 guard 拒。不推荐——USER 和 DEFAULT_OWNER 应指向同一逻辑用户。

白名单匹配(使用 minimatch):

  • 字符比较前强制 lowercase
  • <owner>/<repo> — 字面
  • <owner>/* — 同 owner 下任意仓库(不跨 owner)
  • * — 全放行
  • 多个 pattern 用逗号分隔,任一命中即放行
  • FORGEJO_ALLOWED_REPOS 留空时:若设了 DEFAULT_OWNER,放行 <owner>/*;否则拒绝所有写

ZCode 集成

~/.zcode/cli/config.json(ZCode):

{
  "mcp": {
    "servers": {
      "forgejo": {
        "command": "npx",
        "args": ["-y", "@yumiku/mcp-forgejo"],
        "env": {
          "FORGEJO_BASE_URL": "http://<your-forgejo-host>:<port>",
          "FORGEJO_TOKEN": "<your-token>",
          "FORGEJO_ALLOWED_REPOS": "<owner>/*",
          "FORGEJO_DEFAULT_OWNER": "<owner>"
        }
      }
    }
  }
}

或 Cursor(~/.cursor/mcp.json):

{
  "mcpServers": {
    "forgejo": {
      "command": "npx",
      "args": ["-y", "@yumiku/mcp-forgejo"],
      "env": {
        "FORGEJO_BASE_URL": "http://<your-forgejo-host>:<port>",
        "FORGEJO_TOKEN": "<your-token>",
        "FORGEJO_ALLOWED_REPOS": "<owner>/*",
        "FORGEJO_DEFAULT_OWNER": "<owner>"
      }
    }
  }
}

CI 用法(SDK 子路径)

SDK 模块独立暴露,可绕过 MCP 层直接用:

import { Forgejo, ForgejoError, toEnvelope } from "@yumiku/mcp-forgejo/sdk";

const fg = Forgejo.fromEnv();   // 读 process.env
// 或:
const fg = new Forgejo({
  baseUrl: "http://<your-forgejo-host>:<port>",
  token: process.env.FORGEJO_TOKEN!,
  allowedPatterns: ["<owner>/*"],
});

const issues = await fg.http.get("/api/v1/repos/<owner>/<repo>/issues", { state: "open" });

SDK 也导出守卫 + 错误:

import { assertRepoAllowed, requireDestructive, HIGH_RISK_TOOLS } from "@yumiku/mcp-forgejo/sdk";

测试

npm test

132 个 vitest 用例覆盖:

  • errors.test.ts (7) — 13 个 ErrorCode 归一化 + 错误信封脱敏(debug on/off)
  • guard.test.ts (11) — 白名单(大小写、多 pattern、通配符、defaultOwner 回退)+ destructive gate
  • http.test.ts (18) — URL 构造、状态码 → ErrorCode 映射、getWithHeaders、parsePagination(X-Total-Count / Link)
  • transforms.test.ts (15) — 8 种资源类型 summary 投影 + email 递归剥离
  • list_envelope.test.ts (5) — withListEnvelope HOF 集成(pagination + view)
  • tools_write_happy_path.test.ts (17) — 每个写工具一个 mock fetch 验证
  • issues_type.test.ts (3) — list_issues type 字段透传
  • config.test.ts (6) — loadConfig 读 7 个 env vars(baseUrl, token, allowedPatterns, defaultOwner, httpTimeoutMs, debug, user)
  • identity.test.ts (5) — resolveIdentity 5 个场景(env wins / drift / env+probe fail / probe only / probe fail exit)
  • get_current_user.test.ts (4) — get_current_user 工具(identity=env/probe/missing/缺 isAdmin)
  • list_repos_fallback.test.ts (5) — list_repos owner fallback 链(owner/identity/defaultOwner/都没有/owner 优先)

安全

  • 高危工具(delete_repo / delete_branch / delete_tag)必须显式传 destructive=true。
  • 写操作受 FORGEJO_ALLOWED_REPOS 白名单约束。
  • PAT 通过环境变量注入,绝不入 git 仓库。
  • 启动时 GET /api/v1/user 验证 token;401/403 立即退出码 1。

License

MIT