gittr mcp
gittr.space的模型上下文协议 -使AI代理能够与Nostr上的Git存储库进行交互。
状态(2026-02-14)
| 功能 | 状态 |
|---|---|
| 创建/管理仓库 | ✅ 作品 |
| 问题(1621)✅ 作品 | |
| 将文件推送到网桥 | ✅ 作品 |
| 通过Git.gittr.space克隆Git | ⚠️ 桥接同步中断 |
| PR(1618)❌ 需要修复桥梁 | |
| 桥梁→ git服务器同步 | ❌ 不工作 |
什么是固定的(MCP侧):
- 克隆URL现在使用
git.gittr.space(实际工作的服务器) - 为状态事件发布添加了重试逻辑
已知的Gittr基础架构问题:
- 桥接推送不会将文件同步到git服务器(clone返回404)
- 具有外部URL的repos的中继传播不完整
- PR被拒绝,因为中继无法验证提交
看 已知问题 了解详情。
安装
git clone https://github.com/arbadacarbaYK/gittr-mcp.git
cd gittr-mcp
npm install快速开始
const gittr = require('gittr-mcp');
// Push files to gittr (Nostr auth required — privkey signs challenge)
const pushResult = await gittr.pushToBridge({
ownerPubkey: 'your-64-char-hex-pubkey',
repo: 'my-repo',
branch: 'main',
files: [
{ path: 'README.md', content: '# Hello World' },
{ path: 'src/index.js', content: 'console.log("Hello!");' }
],
privkey: 'your-hex-privkey'
});
// Publish to Nostr (REQUIRES signing with private key)
await gittr.publishRepoAnnouncement({
repoId: 'my-repo',
name: 'my-repo',
description: 'My awesome project',
web: ['https://gittr.space/npub.../my-repo'],
clone: ['https://relay.ngit.dev/pubkey.../my-repo.git'],
privkey: 'your-private-key-hex',
relays: ['wss://relay.ngit.dev']
});
await gittr.publishRepoState({
repoId: 'my-repo',
refs: pushResult.refs,
privkey: 'your-private-key-hex',
relays: ['wss://relay.ngit.dev']
});两步工作流程
注: 对于大多数用例,使用 createRepo() 它自动处理这两个步骤。
createRepo()--推荐
const result = await gittr.createRepo({
name: 'my-repo',
description: 'My project',
files: [
{ path: 'README.md', content: '# Hello' },
{ path: 'src/index.js', content: 'console.log("Hi");' }
],
privkey: 'your-hex-privkey'
});
// Returns: { success, repoId, cloneUrl, webUrl, announced, statePublished }此功能:
- 将文件推送到网桥
- 发布NIP-34公告(30617类)
- 发布NIP-34状态(种类30618)
总是使用 createRepo() 以避免桥上散落的文件。
手动步骤(高级)
如果你需要细粒度的控制:
步骤1:推送文件(需要授权)
网桥需要NIP-98身份验证(使用您的Nostr密钥签名挑战)。MCP会短暂缓存已签名的挑战,以避免冲击挑战端点。
const result = await gittr.pushToBridge({
ownerPubkey: '',
repo: 'repo-name',
branch: 'main',
files: [
{ path: 'file.txt', content: 'content' }
],
privkey: '' // required for NIP-98 bridge auth
});
console.log('Commit:', result.refs[0].commit);发生了什么:
- MCP从网桥收到挑战,用您的密钥(NIP-98)签名,并发送推送
- 签名挑战被缓存约45秒,因此多个推送重复使用一个挑战
- 在429(速率限制)上,MCP等待
retry_after秒,重试一次 - 文件被推送到桥上(https://gittr.space);返回Nostr状态的提交SHA
步骤2:发布到Nostr(需要签名)
要在gittr.space上显示文件,您必须发布Nostr事件:
// Announce repository (kind 30617)
const announceResult = await gittr.publishRepoAnnouncement({
repoId: 'repo-name',
name: 'My Repo',
description: 'Description',
web: ['https://gittr.space/npub.../repo-name'],
clone: ['https://relay.ngit.dev/
/repo-name.git'],
privkey: '',
relays: ['wss://relay.ngit.dev'] // MUST match clone URL domain
});
// Publish state (kind 30618)
const stateResult = await gittr.publishRepoState({
repoId: 'repo-name',
refs: result.refs, // From step 1
privkey: '',
relays: ['wss://relay.ngit.dev']
});发生了什么:
- 创建用您的私钥签名的Nostr事件
- 向Nostr中继宣布存储库元数据
- 发布当前引用/提交
⚠️ 安全: 永远不要提交你的私钥。使用环境变量。
API 参考
存储库操作
pushToBridge(options)
将文件推送到gittr桥。 需要 privkey 对于NIP-98身份验证(质询是自动获取和签名的;结果会被短暂缓存)。
参数:
ownerPubkey(字符串)-64个字符十六进制公钥repo(string)-存储库名称branch(string)-分支名称(默认值:'main')files(array)-数组{ path, content }物体privkey(字符串)- 必修的。 用于签署网桥挑战的十六进制私钥(NIP-98)
- path (string)-文件路径(例如“src/index.js”) - content (string)-文件内容(UTF-8) - isBinary (boolean,可选)-如果为true,则内容为base64
退货:
{
success: true,
pushedFiles: 2,
refs: [
{ ref: 'refs/heads/main', commit: 'abc123...' }
]
}publishRepoAnnouncement(options)
将存储库发布到Nostr(类型30617)。 需要签名。
参数:
repoId(string)-存储库标识符name(string)-人类可读名称description(string)-存储库描述web(数组)-Web URL(例如gittr.space链接)clone(数组)-Git克隆URL(必须与中继域匹配)privkey(string)-64个字符的十六进制私钥relays(数组)-中继URL(必须包含克隆URL中的GRASP服务器)
退货:
{
success: true,
event: { id: '...', sig: '...', ... }
}⚠️ 关键: 克隆URL域必须位于中继数组中:
// ✅ CORRECT
clone: ['https://relay.ngit.dev/
/repo.git']
relays: ['wss://relay.ngit.dev']
// ❌ WRONG - domains don't match
clone: ['https://git.gittr.space/
/repo.git']
relays: ['wss://relay.noderunners.network']publishRepoState(options)
将存储库状态发布到Nostr(类型30618)。 需要签名。
参数:
repoId(string)-存储库标识符refs(array)-数组{ name, commit }物体
- name (string)-引用名称(例如,“refs/heads/main”) - commit (string)-提交SHA
privkey(string)-64个字符的十六进制私钥relays(数组)-中继URL
退货:
{
success: true,
event: { id: '...', sig: '...', ... }
}listRepos(options)
从Nostr中继中发现存储库。
参数:
pubkey(字符串,可选)-按所有者pubkey筛选search(字符串,可选)-搜索词limit(数字,可选)-最大结果(默认值:100)relays(阵列,可选)-自定义继电器列表
退货:
[
{
id: 'repo-name',
name: 'My Repo',
description: 'Description',
owner: 'pubkey...',
web: ['https://...'],
clone: ['https://...'],
graspServers: ['relay.ngit.dev'],
relays: ['wss://relay.ngit.dev'],
event: { ... }
}
]resolveRepoByNostrId(ownerNpubOrHex, repoId, options?)
通过Nostr标识(npub或十六进制)和仓库名称解析仓库。退货 cloneUrl (更喜欢git.gittr.space), cloneUrls,以及 relays 因此代理可以是位置无关的。
参数:
ownerNpubOrHex(string)-所有者为npub(NIP-19)或64字符十六进制repoId(string)-存储库名称/idoptions.relays(阵列,可选)-用于发现的中继列表
退货: 同 getRepo 加 cloneUrl (单个首选URL)和 cloneUrls (事件中的所有克隆URL)。
问题操作
listIssues(options)
列出存储库的问题。
参数:
ownerPubkey(string)-存储库所有者pubkeyrepoId(string)-存储库标识符labels(数组,可选)-按标签筛选relays(阵列,可选)-自定义继电器列表
createIssue(options)
制造一个问题。 需要签名。
参数:
ownerPubkey(string)-存储库所有者pubkeyrepoId(string)-存储库标识符subject(string)-发行标题content(string)-问题描述(markdown)labels(数组,可选)-发布标签privkey(string)-64个字符的十六进制私钥relays(数组,可选)-中继URL
拉取请求操作
listPRs(options)
列出存储库的拉取请求。
参数:
ownerPubkey(string)-存储库所有者pubkeyrepoId(string)-存储库标识符relays(阵列,可选)-自定义继电器列表
createPR(options)
创建一个pull请求。 需要签名。
参数:
ownerPubkey(string)-存储库所有者pubkeyrepoId(string)-存储库标识符subject(字符串)-PR标题content(string)-PR描述(markdown)commitId(string)-提示提交SHAcloneUrls(数组)-PR分支的Git克隆URLbranchName(string)-PR分支机构名称labels(数组,可选)-PR标签privkey(string)-64个字符的十六进制私钥relays(数组,可选)-中继URL
赏金行动
⚠️ 注: 赏金系统存在于gittr代码中,但平台上还没有活动的赏金。
createBounty(ownerPubkey, repoId, issueId, amount, description)
为一个问题创建闪电赏金。
参数:
ownerPubkey(string)-存储库所有者pubkeyrepoId(string)-存储库标识符issueId(string)-问题事件IDamount(数字)-赏金金额(单位:沙特里亚尔)description(string)-赏金描述
已知GRASP服务器
GRASP服务器既是Nostr中继(wss://)又是git服务器(https://):
relay.ngit.dev(推荐-接受所有repos)git.shakespeare.diyngit-relay.nostrver.segit-01.uid.ovhgit-02.uid.ovhngit.danconwaydev.comgit.gittr.space(gittr的服务器)
用途:
const graspDomain = 'relay.ngit.dev';
const announceResult = await gittr.publishRepoAnnouncement({
// ...
clone: [`https://${graspDomain}/
/repo.git`],
relays: [`wss://${graspDomain}`] // MUST match clone domain
});常见问题
“公告必须在克隆和中继标签中列出服务”
原因: 克隆URL域与任何中继都不匹配。
解决方案: 从克隆URL中提取域并添加为 wss:// 继电器。
Repo在gittr.space上显示“0个文件”
原因: 仅推送文件(步骤1),未发布到Nostr(步骤2)。
解决方案: 两者都跑 publishRepoAnnouncement() 和 publishRepoState().
“重复url”错误
原因: 多次发布到同一中继。
解决方案: 非致命-事件已成功发布。去重继电器阵列。
速率限制(gittr.space桥)
该桥适用于: 推 每个IP为10/min,每个Nostr身份为5/min; 推动挑战 每IP每分钟30次。开 429,JSON正文包括 retry_after (秒)。MCP缓存已签名的质询约45秒,然后等待429秒 retry_after 然后重试一次。避免紧环(例如许多 createRepo 无延迟地连续呼叫)。
安全
- 从不提交私钥 -使用环境变量
- 桥牌推送需要NIP-98(用私钥签名挑战);Nostr发布(公告、问题、PR)也需要签名
- 安全地存储密钥(例如。,
~/.nostr-identity.json具有0600权限)
完整示例
看 docs/AGENT-WORKFLOW.md 查看完整的端到端示例。
支持
如果你用这个MCP获得了sats,可以考虑淘汰建设者!
⚡ 闪电: arbadacarba@btip.nl
公平交易:
- 成功使用? → 1,000-5000个卫星
- 打造赏金特工? → 10,000+个卫星
- 赚大? → 1-5% 你的看法
顶级支持者(10k+sats)获得:
- 在SUPPORTERS.md中列出
- 优先功能请求
- 直接支持访问
链接
- github: https://github.com/arbadacarbaYK/gittr-mcp
- gittr.space: https://gittr.space
- NIP-34规范: https://github.com/nostr-protocol/nips/blob/master/34.md
- 建设者: @arbadacarba(电报),@arbadacarbYK(推特)
许可证
麻省理工学院
局限性
getFile()--需要Nostr同步
getFile() 通过GRASP服务器获取文件内容。这行得通 只有在...之后 回购已发布给Nostr。
无法通过此功能读取桥上存在但尚未发布的文件(NIP-34事件)。
解决方法: 总是使用 createRepo() 或者在尝试读取文件之前,确保您的更改已发布到Nostr。
createPR()--需要桥接Git可访问性
状态: 通过MCP创建PR在基于gittr桥的存储库中存在局限性。
问题:
- NIP-34要求在中继接受PR事件之前,可以通过git clone访问PR提交
- gittr桥存储文件,但不允许通过git访问它们(克隆URL返回“未找到存储库”)
- 中继在接受PR事件之前验证提交是否存在于git仓库中
- 这会导致PR事件被拒绝:“PR事件必须引用已接受的存储库或已接受的事件”
什么有效:
- ✅ 问题(1621类)-不需要git验证
- ✅ 存储库-公告和状态事件工作
- ✅ 桥接推送-文件存储正确
- ❌ PR(1618类)-由于电桥限制被继电器拒绝
根本原因:
# Bridge push succeeds:
curl -X POST bridge.ngit.dev/api/nostr/repo/push → success
# But git clone fails:
git clone https://relay.ngit.dev/.../repo.git → "repository not found"
# Relays reject PR because they can't verify the commit exists解决方法:
- 使用gittr命令行界面 -它处理整个流程(内部使用nost://protocol)
- 使用外部克隆URL -使用GitHub/GitLab URL创建仓库,其中git始终可访问
- 使用补丁(1617类) 而不是PR——补丁不需要git验证
- 安装git远程鼻孔 -使用nost://URL和git的助手(需要从源代码构建)
关键见解:
- GRASP服务器=同时充当中继的git服务器(相同的URL同时服务于git和Nostr)
- 这
nostr://协议抽象出确切的服务器-通过Nostr自动找到它 - 桥接URL(relay.ngit.dev)不起作用,因为git没有同步到那里
- nost://URL是真正有效的-gittr CLI在内部使用它
测试结果(2026-02-14):
- 桥推:✅ 作品
- 回购公告(30617):✅ 作品
- 回购州(30618):⚠️ 出版但去了“炼狱”
- 提交事件(30620):⚠️ 出版但去了“炼狱”
- 公关活动(1618):❌ 拒绝-git不可访问
已测试的克隆URL(均返回404):
https://relay.ngit.dev/.../repo.git→ “未找到存储库”https://gittr.space/.../repo.git→ “找不到页面”nostr://协议→ 需要git远程鼻孔助手
MCP代码正确 -这是gittr桥的限制,而不是MCP错误。
