Git on Nostr via gittr.space: repos, push, issues, PRs, stars, bounties. Nostr identity (NIP-34).
Let your AI agent (or app) use gittr.space like a developer would — create repos, push code, open and merge pull requests, manage issues, and work with Lightning bounties — using your Nostr identity, not a GitHub login.
Works with Cursor, Claude Desktop, VS Code / Copilot MCP, Windsurf, OpenClaw, or any host that speaks the Model Context Protocol over stdio.
Docs hub: gittr-docu — product map and how this MCP sits next to the website.
This repo’s Page: root index.html. After Push Manifest, save site name gittr-mcp.
| Without gittr-mcp | With gittr-mcp |
|---|---|
| You copy-paste between chat and the gittr website | The agent calls tools: push files, publish repo metadata, open issues/PRs |
| Custom scripts for NIP-98 bridge auth and NIP-34 signing | Signing, challenge handling, and relay checks are built in |
| Unclear whether a push “really” landed on Nostr | Tools return pass/fail plus verification / nextSteps for automation |
End result: one MCP server connects your agent to decentralized git on Nostr — same account as on gittr.space (nsec / keys file), no separate vendor account for the agent.
Hosting note: The website Create/Import flow stays browser-local until announce/Push. MCP createRepo / mirrorRepo / pushToBridge do write the bridge when you want hosted git — put https://git.gittr.space/… in clone[]. Soft-delete POSTs the tombstone to the bridge so disk is wiped.
gittr-mcp is the agent door into the same platform humans use in the browser. You are here = gittr-mcp (this repo, teal). Cyan-outlined host boxes = public hostnames (git. / pages. / relay.gittr.space) (teal = this repo; cyan outline = host URLs).
flowchart TB
Agent["AI host<br/>Cursor / Claude / …"]
MCP["★ YOU ARE HERE · gittr-mcp<br/>this repo · agent tools"]
UI["gittr Client<br/>gittr.space"]
Bridge["gitnostr Bridge<br/>git.gittr.space<br/>SSH / HTTPS git"]
RelayGittr["gittr Pyramid relay<br/>relay.gittr.space<br/>wss · open forge + GRASP"]
Relays["Other Nostr relays"]
Pages["Pages / nsite<br/>pages.gittr.space"]
Remote["git remote nostr<br/>optional"]
Agent -->|MCP tools| MCP
MCP -->|HTTPS + Nostr auth| Bridge
MCP -->|sign NIP-34 events| RelayGittr
MCP -->|sign NIP-34 events| Relays
UI --> RelayGittr
UI --> Relays
UI --> Bridge
Pages --> Relays
Remote -.-> Relays
classDef youAreHere fill:#0f766e,stroke:#5eead4,stroke-width:3px,color:#ecfdf5
classDef hostUrl fill:#164e63,stroke:#22d3ee,stroke-width:2px,color:#ecfeff
class MCP youAreHere
class Bridge,Pages,RelayGittr hostUrl
| Piece | Host / link | How MCP uses it |
|---|---|---|
| gittr Client | gittr on gittr.space · gittr.space | Same product; MCP mirrors forge actions (repos, issues, PRs, bounties) |
| gitnostr Bridge | gitnostr on gittr.space · git.gittr.space | pushToBridge, file list, merge clones over HTTPS |
| Pages / nsite | nsite-gateway · pages.gittr.space | Out of band for most MCP git tools |
| gittr Pyramid relay | pyramid · relay.gittr.space | Prefer in relay lists when publishing NIP-34 |
| ★ gittr-mcp (this README) | gittr-mcp on gittr.space | You are here |
| git remote nostr | ngit-cli | Not required for MCP; agents usually use bridge HTTPS + events |
Addressing for agents: resolveRepoByNostrId(npub|hex, repo) → cloneUrl + relays. Prefer announced npub-path HTTPS on git.gittr.space (NIP-34); hex path is a disk fallback if a symlink is missing. Include wss://relay.gittr.space when publishing.
These are the processes people actually run; each maps to MCP tools the agent can call.
createRepo — push initial files to the bridge and publish Nostr kinds 30617 + 30618 in one step (best default for agents).publicRead: false to create a private repo (code/clone/API/SSH readable only by you and listed maintainers). The announcement name/description still appear on relays — only file access is gated.pushToBridge → publishRepoAnnouncement → publishRepoState.publicRead: false on createRepo, publishRepoAnnouncement, forkRepo, or mirrorRepo.addCollaborator or Settings → Contributors on gittr.space).pushToBridge — update files on a branch (NIP-98 auth to gittr bridge); optional deletedPaths / allowTreeShrink for file or folder deletes (parity with Code-tab trash).getFile, bridgeListFiles, bridgeGetFileContent, getBranches, getCommitHistory — read without cloning. getFile is the bridge, then a short GRASP list — not the Code tab. On the website: latest live 30617; forge source is the tree when present (stale bridge listing is replaced); otherwise first non-empty clone[] listing. See MCP-GITTR-PARITY.md and gittr FILE_FETCHING_INSIGHTS.md.resolveRepoByNostrId — find clone URLs and relays from npub + repo name.listIssues, createIssue, getIssueByIdlistIssueComments, createIssueComment — NIP-22 kind 1111 (same tags as gittr issue threads). Does not touch bounties.closeIssue, reopenIssue — publish NIP-34 status events (1632 / 1630) for a 64-char Nostr event id. GitHub/Gitea imported issue-12 / pr-12 (and a bare 12) are refused — close those on the origin.| Step | Tool | Notes |
|---|---|---|
| List / open PR | listPRs, createPR | Signed Nostr events (kind 1618). |
| Comment on PR | listPRComments, createPRComment | NIP-22 kind 1111. |
| Full PR with git branches | createPRViaGittrCLI | Recommended when the agent has git on PATH. |
| Update PR tip | updatePullRequest | New commit + clone URLs on the PR event. |
Merge into main | mergePullRequest | Real git merge of a Nostr PR (kind 1618 event id): clone/fetch, merge, push bridge, publish 30618 + merged status 1631. Forge pr-N is refused. Repo owner or listed maintainer; git required. |
| Mark merged (Nostr only) | markPullRequestMerged | Status only — no git merge. |
Honest limits on PRs: Creating and listing PRs via MCP is supported. Merging needs git installed and permission on the repo. Some relays are strict about clone URL + relay matching in repo announcements — if PR publish fails, fix metadata (see Limitations) or use createPRViaGittrCLI. Details: docs/DEVELOPER.md#limitations.
forkRepo — fork an existing gittr repo under your key.mirrorRepo — copy from GitHub/GitLab URL to gittr.importRemoteToBridge — server-side import/refetch into bridge storage.listRepos, searchRepos, myRepos, exploreRepos, getTrendingRepos (trending = recent repos, not engagement rank)starRepo, unstarRepo, listStars — NIP-25 on the repo’s 30617 event (same as gittr Star button).watchRepo, unwatchRepo, listWatchedRepos — NIP-51 kind 10018 followed-repo list (same as gittr Watch).getRepoContributorsParity details: docs/MCP-GITTR-PARITY.md — what matches gittr.space vs caveats.
listReleases — git tags from bridge (refs/tags/*), not the web UI Releases tab and not Zapstore.listForgeReleases — forge Releases tab listing (all assets; no NIP-82 MIME gate).createRelease — returns guidance only (UI release notes until next 30617 push).fetchForgeReleases — one forge Release + announceable binaries. Omit tag for latest; hash:true for sha256 (required before announce).announceSoftwareFromForgeRelease — Zapstore/NIP-82 (kinds 32267 / 30063 / 3063) from a tagged forge Release. APK preferred; AppImage/DMG/linux tar.gz/MSI/EXE/IPA also. Extra binaries on the same tag are sibling assets. Copies images: from the forge zapstore.yaml. Optional pinToBlossom (public Blossom; blossom.gittr.space only for official space.gittr.app). Same as gittr Nostr Apps (latest) or Releases Announce on Nostr (tag=). Never a tagless app.deleteSoftwareAnnounce — NIP-09 kind 5 for those app/release/asset event ids.publishNostrPages — NIP-5A kind 35128 + Blossom upload through gittr (index.html required).auditRepoDependencies — parse lockfiles on the bridge and query OSV via gittr /api/security/audit.listBounties, createBountyInvoice, publishBountyToNostr, submitBounty, listBountiesForIssue, release/withdraw tools.getPushPaywallStatus, createPushPaywallIntent, syncRepoPushPolicy.GITTR_LNBITS_URL and GITTR_LNBITS_ADMIN_KEY in MCP env (see .env.example).describeAgentAuth — run once: confirms keys load (never returns nsec); if unconfigured it tells the agent to ask you about a test keypair.setupTestKeypair — after your explicit OK, writes a disposable test identity to .nostr-keys.json (replace with your real nsec anytime).loadCredentials, getPublicKey — debugging helpers. MCP loadCredentials masks nsec (prefix only), secretKey, and private_key.Full tool list: 50+ tools in server.js (search for name:). Library API: docs/DEVELOPER.md.
nsec or hex) — same identity you use on gittr.spaceClone (developers / Cursor):
git clone https://github.com/arbadacarbaYK/gittr-mcp.git
cd gittr-mcp
npm install
Claude Desktop one-click (.mcpb): this package is not on npm. Download the latest bundle from GitHub Releases (gittr-mcp-x.y.z.mcpb) and install that. New releases are built automatically when we push a v* tag — see docs/RELEASE.md.
cp .nostr-keys.json.example .nostr-keys.json
Edit .nostr-keys.json and set your nsec (or hex secretKey). The file is gitignored.
Lookup order: ./.nostr-keys.json → ~/.nostr-identity.json → ~/.config/gittr/keys.json.
No key yet? Test keypair flow. If no credentials are found, describeAgentAuth and all key-missing errors tell the agent to ask you whether a disposable test keypair should be created. If you agree, the agent calls setupTestKeypair({ confirm: true }) — it writes a fresh identity into .nostr-keys.json (flagged "generated": true, file mode 600, never committed) and everything auto-loads it from then on. Replace the nsec in that file with your real key whenever you're ready; describeAgentAuth keeps reminding the agent that a test key is active. It never runs without confirm: true and never overwrites existing credentials unless you explicitly ask for force: true — anything published under a keypair stays under that identity forever, so this is always your call, not the agent's.
Important: Add a new server entry — do not replace your entire MCP config.
Edit ~/.cursor/mcp.json (or project MCP settings). Use an absolute path:
{
"mcpServers": {
"gittr": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/gittr-mcp/server.js"],
"env": {
"BRIDGE_URL": "https://gittr.space"
}
}
}
}
Reload MCP or restart Cursor.
Quit Claude, edit claude_desktop_config.json (path depends on OS — see Anthropic docs), same mcpServers block as above, restart.
Same stdio contract: command: node, args: ["/path/to/server.js"], optional env.
OpenClaw / mcporter: docs/MCP-HOSTS.md.
const gittr = require('gittr-mcp');
await gittr.pushToBridge({ /* ... */ });
Entry point: index.js. MCP process: server.js (npm bin gittr-mcp).
In chat, ask the agent to call describeAgentAuth, or from the repo:
npm test # full package (includes clone-set + forge-match regressions)
npm run test:regressions # fast: grasp clone URLs + findReposBySource matchers
npm run test:mcp-stdio # optional live stdio CallTool matrix
UI / file-fetch tip fidelity regressions live in the gittr monorepo: cd ../gittr/ui && npm run test:regressions (see gittr docs/FILE_FETCHING_INSIGHTS.md).
Examples that map to the workflows above:
my-demo with a README and publish it on gittr.”my-demo on main.”<id> if I’m the owner.”https://github.com/user/repo to gittr as repo-name.”Agents should read tool results as JSON; many responses include agentSummary and nextSteps.
Short version — full detail in docs/DEVELOPER.md:
createRepo. Pushing alone does not make the repo visible everywhere.git clone only “works” for others if your published clone URL serves git HTTP. This MCP defaults toward https://git.gittr.space/<hex-pubkey>/<repo>.git. A failed clone means fix the URL in 30617, not “ignore and continue.” Host-only values like https://git.gittr.space are rejected/expanded on publish.mergePullRequest needs git on the machine running MCP and maintainer/owner rights.Mostly yes, without updating MCP. Browser/filter/uploadpack/CORS fixes live on git.gittr.space. Anyone (including agents via MCP) cloning that host benefits as soon as the server is fixed.
MCP package updates are separate. Cursor/Claude do not auto-pull new MCP code. To get new tools or clone-tag logic:
cd gittr-mcp && git pull && npm install, then reload MCP / restart the host.mcpb: download the latest from Releases and reinstall the bundlenpm ci
npm test
# Live tests (real relays; optional LNbits) — see .env.example
GITTR_TEST_NSEC=nsec1... npm run test:live:matrix
| Doc | Contents |
|---|---|
| docs/MCP-HOSTS.md | Per-host MCP config |
| docs/AGENT-WORKFLOW.md | Step-by-step push + publish |
| docs/AGENT-QUICKSTART.md | Copy-paste agent prompts |
| docs/DEVELOPER.md | API, verification contract, GRASP |
| docs/SIGNING-GUIDE.md | Keys and NIP-98 |
| docs/NIP34-SCHEMAS.md | Event kinds |
| docs/MCP-GITTR-PARITY.md | MCP vs gittr.space feature map |
.nostr-keys.json, .env, or real nsec values..nostr-keys.json.example belongs in git.fast-uri / hono / qs in package.json overrides so that list stays clean. Details: docs/SECURITY-ADVISORIES.md.See LICENSE (MIT).
This listing does not have a supported local package template. Use the maintainer’s documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.