关于 Opengist
Opengist 是用于管理自托管 Opengist 实例中 gist 的 MCP 服务,支持读取、搜索和写入,并提供可配置的工具集及有界结构化结果。
主要功能
- 01读取和搜索 gist
- 02创建、更新、删除和派生 gist
- 03查看文件、修订版和提交记录
- 04配置工具白名单和只读模式
- 05带内容限制的结构化结果
适用场景
- 01按标题、主题或所有者查找 gist
- 02查看指定修订版中的文件
- 03通过 MCP 客户端创建或编辑 gist
MCP 相关
将 Opengist REST API 操作作为 MCP 工具提供,供客户端列出、搜索、读取和修改 gist,并查看账户信息、派生内容及点赞状态。工具可按需注册,也可限制为只读。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y opengist-mcpOPENGIST_URLBase URL of the Opengist instance, e.g. https://gist.example.comOPENGIST_TOKEN密钥Opengist Personal Access Token (starts with og_), created under Settings -> Access TokensOPENGIST_READ_ONLYSet to true to not register any write tools (create, update, delete, fork, like)OPENGIST_INSECURE_TLSSet to true to accept self-signed TLS certificates (scoped to the Opengist connection)OPENGIST_ALLOW_TOOLSComma-separated tool names or list_* prefixes to register; 'essential' selects a curated preset (default: all tools)OPENGIST_DENY_TOOLSComma-separated tool names or list_* prefixes to remove from whatever OPENGIST_ALLOW_TOOLS left本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
14收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | integer | 否 | 要返回的页码,从 1 开始(参见结果中的分页信息) |
| scope | enum | 否 | mine = 令牌所有者(或 `username`)的 gist;public = 实例上的所有公开 gist;liked/forked = 令牌所有者(或 `username`)点赞或派生的 gistmine | public | liked | forked |
| since | string | 否 | 仅返回在此 RFC 3339 时间戳当时或之后更新的 gist |
| perPage | integer | 否 | 每页项目数(1-100,默认值为 30) |
| username | string | 否 | 列出此用户的 gist,而不是你自己的。不能与 scope="public" 一起使用。 |
详细介绍
opengist-mcp
这是一个面向 Opengist 的 Model Context Protocol(MCP)服务。Opengist 是一个由 Git 驱动、可自托管的代码片段服务。
它让 Claude Code、Claude Desktop 或 Codex 等 MCP 客户端能够在你自己的 Opengist 实例上读取、搜索、创建、更新和删除 gist:文件内容与修订版本、提交历史、分叉和点赞,以及你的用户账户。
十四个工具是上限,而不是下限:设置 OPENGIST_ALLOW_TOOLS=essential
即可改为注册精选的七个工具。模型从七个工具中挑选合适工具的可靠性远高于从十四个中挑选——请参阅
选择要加载的工具。

Note: 此服务通过
/api与 Opengist REST API 通信,该 API 在较新的 Opengist 版本中提供,并默认启用(api.enabled)。运行中的实例会通过GET /api/openapi.yaml提供自身的 OpenAPI 规范——如果工具行为异常,请将其与你所用的版本进行比较。
特点
基于一个 API 提供十四个工具,源自 Opengist REST API,并经过实时实例验证:读取、搜索、编写、分叉和点赞 gist,包括修订版本、提交历史和原始文件访问。
从设计上限制数据量。 文件内容会按单个文件和总预算进行限制;二进制文件绝不会作为文本输出;每次截断都会注明用于获取剩余内容的调用。
要求
-
Node.js 22 或更高版本
-
已启用 REST API 的 Opengist 实例
-
Opengist Personal Access Token(Settings → Access Tokens)。所需权限范围:
gist:read— 读取 gist,包括你自己的私有和未列出的 gistgist:write— 创建、更新、删除和分叉 gistuser:read— 读取你自己的账户user:write— 仅set_gist_like需要
不含
gist:read的令牌仍然可用,但此时 API 会静默地只返回公开 gist,而不会报错。
配置
| 变量 | 必填 | 说明 |
|---|---|---|
OPENGIST_URL | 是 | 实例的基础 URL,例如 https://gist.example.com。接受末尾带 /api 的 URL,并会将其移除。 |
OPENGIST_TOKEN | 是 | 个人访问令牌,以 og_ 开头 |
OPENGIST_READ_ONLY | 否 | true、1 或 yes 仅注册读取工具;该会话中完全不会提供写入工具 |
OPENGIST_INSECURE_TLS | 否 | true 接受自签名证书,仅对 Opengist 连接生效(绝不会影响整个进程) |
OPENGIST_ALLOW_TOOLS | 否 | 以逗号分隔的工具名称、list_* 前缀,或用于精选预设的 essential |
OPENGIST_DENY_TOOLS | 否 | 语法相同;会从 OPENGIST_ALLOW_TOOLS 留下的工具中移除对应项 |
ELICITATION | 否 | false 会将审批对话框替换为双调用令牌。不带前缀 |
令牌只会在启动时读取一次,随后便会从
process.env中移除,因此对子进程不可见。除回环地址外,请使用https://——使用普通 http 时,令牌和每个 gist 都会以明文传输。如果实例未配置
external-url,Opengist 报告的 URL(以及此服务透传的 URL)会指向localhost。请在实例上设置external-url/OG_EXTERNAL_URL,以确保链接可用。
选择要加载的工具
OPENGIST_ALLOW_TOOLS 和 OPENGIST_DENY_TOOLS 接受以逗号分隔的工具名称;
末尾的 * 可匹配整个工具系列。essential 是包含以下七个工具的精选预设:
list_gists、search_gists、get_gist、get_gist_file、create_gist、update_gist、delete_gist。
OPENGIST_ALLOW_TOOLS=essential
OPENGIST_ALLOW_TOOLS=list_gists,get_gist_file,create_gist
OPENGIST_DENY_TOOLS=delete_*
如果某个条目未匹配到任何工具,启动就会中止并指出该条目,因此拼写错误不会
悄悄隐藏工具——没人会把缺少的工具追溯到环境变量。
经过筛选的工具不会被注册,因此它不会出现在
tools/list 中,也不会被 tools/call 识别,这与
OPENGIST_READ_ONLY 下的写入工具完全相同。
如果你同时运行多个此类服务,mcp-hub
是另一种解决方案——它的 /hub 端点会用六个元工具替换每个服务的所有工具。
安装
Claude Code
claude mcp add opengist -s user \
-e OPENGIST_URL=https://gist.example.com \
-e OPENGIST_TOKEN=og_your_token \
-- npx -y opengist-mcp
Claude Desktop
claude_desktop_config.json:
{
"mcpServers": {
"opengist": {
"command": "npx",
"args": ["-y", "opengist-mcp"],
"env": {
"OPENGIST_URL": "https://gist.example.com",
"OPENGIST_TOKEN": "og_your_token"
}
}
}
}
Codex
~/.codex/config.toml:
[mcp_servers.opengist]
command = "npx"
args = ["-y", "opengist-mcp"]
env = { OPENGIST_URL = "https://gist.example.com", OPENGIST_TOKEN = "og_your_token" }
Docker
docker run --rm -i \
-e OPENGIST_URL=https://gist.example.com \
-e OPENGIST_TOKEN=og_your_token \
ghcr.io/ni-c/opengist-mcp:latest
必须使用 -i——传输方式是 stdio。不要添加 -t;TTY 会破坏协议流。
从源代码安装
git clone https://github.com/ni-c/opengist-mcp.git
cd opengist-mcp
npm install
npm run build
通过 mcp-hub
无法启动本地进程的客户端——ChatGPT connectors、Claude 网页版、
Cursor、LibreChat——可通过 mcp-hub 连接 opengist-mcp:一个
容器即可通过 Streamable HTTP 服务多个 stdio MCP 服务,并通过单个密码提供 OAuth 2.1 登录,
还可为不支持 OAuth 的客户端提供长期令牌。它的
/hub 端点会用六个元工具将所有服务整合在一起,因此一个连接器即可访问所有服务,
无需在模型上下文中包含 N×工具模式;它还同时支持两个协议版本——此服务提出的问题
会经由它传递给另一端的用户。
它的 /config/mcp.json 使用 Claude Code 的格式,因此配置项就是你已有的那个:
{
"mcpServers": {
"opengist": {
"command": "npx",
"args": ["-y", "opengist-mcp"],
"env": { "OPENGIST_ALLOW_TOOLS": "essential" },
"denyTools": ["delete_*"]
}
}
}
其中的 allowTools 和 denyTools 是 hub 自身针对各服务的筛选器,与 env 中的 *_ALLOW_TOOLS 并不相同——
两者的区别,以及由此引发的误用,详见客户端指南。
工具
阅读
| 工具 | 描述 |
|---|---|
list_gists | 列出代码片段:自己的、其他用户的、所有公开的,或已点赞/已复刻的(scope + 可选的 username) |
search_gists | 按标题、描述、主题或所有者查找代码片段——进行有界的客户端扫描(Opengist 没有搜索 API) |
get_gist | 获取一个代码片段及其文件内容,可指定版本;也可按需获取提交记录和复刻记录 |
get_gist_file | 获取单个文件的原始内容,可指定版本和偏移量——适用于大型或被截断的文件 |
list_gist_commits | 代码片段的提交历史,按时间从新到旧排列 |
list_gist_forks | 代码片段的复刻记录 |
get_user | 获取自己的账户,或通过 username 或 userId 获取其他用户的账户 |
check_gist_like | 检查你是否给某个代码片段点过赞;区分“未点赞”和“你无法查看” |
写入
| 工具 | 描述 |
|---|---|
create_gist 👤 | 从文件列表创建代码片段。必须指定 visibility;公开/不公开列出时需要人员确认 |
update_gist | 更改标题/描述/可见性,以及写入或重命名文件。无法删除文件 |
delete_gist_files 👤 | 从代码片段中删除文件——审批内容会精确绑定到这些文件名 |
delete_gist 👤 | 永久删除代码片段 |
fork_gist | 复刻代码片段;报告是否创建了新复刻,或已存在复刻 |
set_gist_like | 幂等地点赞或取消点赞代码片段(先读取当前状态,因此重复调用不会切换状态) |
结构化输出
每个工具都声明了 outputSchema,并在文本块旁返回 structuredContent,
因此客户端无需解析散文即可使用结果:
{
"untrusted": true,
"source": "opengist",
"scope": "self",
"pagination": { "page": 1, "perPage": 20, "total": 42, "nextPage": 2 },
"gists": [{ "id": "abc123", "title": "…", "visibility": "private" }],
"notes": ["…"],
}
每个会报告代码片段内容的工具都会将 untrusted: true 和
source: "opengist" 作为字段携带。此服务一直在 notes 中这样说明——
以列表中的散文形式呈现,客户端可以读取但无法验证;而这个字段则可以验证。三个工具不包含这些字段,因为它们的回答完全是
此服务自己的内容:check_gist_like、set_gist_like 和 delete_gist
会报告传入的 ID 和一个布尔值。
结果超出预算时,仍会优先丢弃文件内容。如果这样仍不够,
现在会返回错误:过去会返回达到上限时截断的 JSON,文本块可以容忍这种情况,但 structuredContent 不行。
安全
- 不可逆操作需要征求用户同意。
delete_gist、delete_gist_files和扩大 gist 的可见范围,都会在客户端支持时通过 MCP elicitation 弹出真实对话框——模型无法代替用户作答。模型可以自行设置普通的confirm: true标志,也可能被 gist 中的文本诱导着设置该标志。如果客户端无法显示对话框,服务会拒绝首次调用,并返回一个随机的一次性令牌,该令牌会在五分钟后过期;它只能证明调用使用相同参数执行了两次,仅此而已,说明文本也会明确这一点。无论哪种情况,delete_gist_files的批准都绑定到确切的文件名集合,因此针对单个文件的批准无法被重放来删除其他文件。ELICITATION=false会有意采用回退方案,但绝不会移除这道防护。请参阅征求用户同意。 - 发布内容也会以同样的方式征求同意。 创建
public或unlistedgist,以及向已有的此类 gist 写入文件,都会造成信息披露:模型上下文中的任何内容都会变得可供他人读取,而且无法从已看过这些内容的人那里撤回。两种操作都会在执行前征求同意。批准会绑定到确切的内容,因此针对单个文件的批准无法在附带另一个文件时重放。在同一次操作中将 gist 设为私有,不属于信息披露,因此不会征求同意。 - 确认会在验证后检查。 如果某次调用无论如何都无法成功,系统会将其报告为输入错误,而不是先让用户多走一遍确认流程。
- 确认提示绝不会引用 gist 文本。 标题、描述、主题和文件名由用户提供,可能包含旨在诱导生成确认提示的指令,因此拒绝时只显示服务端元数据(可见性、文件数量、日期)。
update_gist无法删除文件。 Opengist API 会在文件条目为null_或_既没有content也没有filename时删除文件——而粗心构造的对象恰好就可能是这种形式。因此,该服务绝不公开原始文件映射;它只接受明确的write/rename操作,并在发送前断言没有任何条目会被解读为删除操作。未提及的文件会保持不变。- 拼写错误不会悄悄导致文件重复。 如果要写入的文件名不存在,除非传入
allowCreate: true,否则会拒绝操作;拒绝信息会指出不区分大小写的近似匹配项(readme.md与README.md)。 - Gist 内容是不可信输入。 每条包含文件内容的响应都会附上相应提示。应将 gist 文本视为数据,绝不要将其当作指令。
- 结果有长度限制。 每个文件内容都有上限,且所有文件内容总量也有预算限制;默认不返回提交记录和分支副本,不会将二进制文件作为文本输出,并且每次截断都会连同获取剩余内容的调用一并报告。
search_gists会说明扫描了多少内容,并明确标记不完整的结果。 - 实例数据会被读取,但不会被信任。 每条响应都经过统一的边界处理:类型错误的字段会被视为缺失,而不会导致致命错误;计数值始终有限;提交 ID 在使用前会先验证其格式;显示字符串会被截断。所有输出字符串都会移除控制字符,并修复孤立代理项;如果这影响到文件正文,结果会按文件说明移除了多少个字符。
- 请求经过加固。 系统会拒绝重定向,防止持有者令牌被重放到其他主机;每个请求都会设置超时时间;路径参数会拒绝
./..并进行 URL 编码;上游错误正文会被截断,HTML 错误页面则会被完全丢弃。 - 剩余风险:
OPENGIST_READ_ONLY和批准流程都是客户端防护。真正的安全边界是访问令牌的权限范围和 MCP 主机的权限提示。仅限gist:read/user:read权限的令牌无法写入,无论模型尝试做什么。
有意不提供的功能
不是 Git 客户端。 它与 REST API 通信。克隆、推送和分支是 Git 的工作——它会返回 clone_url 和 ssh_url,供你传给 Git。
不是管理工具。 它不提供用户、设置或实例管理相关功能,而且 get_user 返回的是允许列表中的字段,而不是 API 恰好包含的所有内容。
不是搜索索引。 Opengist 没有搜索端点,因此 search_gists 只使用 API 提供的功能,不会假装提供更多功能。
安全
- Opengist 返回的所有内容都由某个人编写,而且很可能不是你——文件内容、标题、描述、主题和 Git 作者名称都标记为不可信数据,应当报告,而不是照做。
- 结果都有上限:每个文件的内容和总体预算均有限制,不会以文本形式输出二进制文件,且每次截断都会指出用于获取其余内容的调用。
- 删除 gist 或其文件,以及扩大 gist 的可见范围,都需要先通过 MCP elicitation 征求用户同意。如果客户端无法显示对话框,就会拒绝该调用,并附带一个随机的一次性令牌。该令牌 5 分钟后过期,且只会出现在之前的工具结果中。
- 有两种方法可以阻止它写入,但两者并不等同:
OPENGIST_READ_ONLY=true不会注册写入工具,且此服务会强制执行这一点;限定为gist:read和user:read的令牌则无法写入,无论是此服务还是模型都不行。需要确保无法写入时,请使用第二种方法。 - 公开 gist 是一种发布渠道——在大多数实例上,任何人都能查看,而且内容会被索引。创建公开 gist 是一项决定,因此它会先征求同意。
文档
完整指南、工具参考和安全说明请见
opengist-mcp.ni-c.de(源文件位于 docs/)。
开发
npm install
npm run build
npm test
npm run lint
发布
更新 package.json 和 server.json 中的版本号,将 CHANGELOG.md 中的 ## [Unreleased] 部分移至新版本下,提交,然后推送一个标签:
git tag -a v0.1.0 -m "v0.1.0"
git push origin main v0.1.0
发布工作流会验证标签与软件包版本一致,通过 npm 的 OIDC 可信发布机制发布(无需长期令牌),等待容器镜像出现在 GHCR 上,在 MCP 注册表中登记此次发布,并根据变更日志部分创建 GitHub 发布。
如果注册表步骤失败,请在 main 上修复,然后触发 mcp-registry.yml——切勿重新运行带标签的任务,因为它会检出不可变标签。
发布
发布由标签驱动。更新 package.json,将 CHANGELOG.md 中的 [Unreleased] 说明移至新版本下,提交,然后:
git tag -s vX.Y.Z -m "vX.Y.Z"
git push origin main vX.Y.Z
发布工作流会通过 Trusted Publishing(使用 OIDC 并提供来源证明)发布到 npm,将多架构容器镜像推送到 GHCR,根据 CHANGELOG 部分创建 GitHub 发布,并更新官方 MCP 注册表中的条目。
参与贡献
欢迎提交问题、参与讨论和发起拉取请求——请参阅 CONTRIBUTING.md。报告漏洞时,请使用私下报告渠道,而非公开问题;相关政策见 SECURITY.md。
许可证
MIT © Willi Thiel
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。