{
  "markdown": "# gittr-mcp\n\n<!-- mcp-name: io.github.arbadacarbaYK/gittr-mcp -->\n\n**Let your AI agent (or app) use [gittr.space](https://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.\n\nWorks with **Cursor**, **Claude Desktop**, **VS Code / Copilot MCP**, **Windsurf**, **OpenClaw**, or any host that speaks the [Model Context Protocol](https://modelcontextprotocol.io/) over stdio.\n\n---\n\n## Why use this?\n\n| Without gittr-mcp | With gittr-mcp |\n|-------------------|----------------|\n| You copy-paste between chat and the gittr website | The agent calls tools: push files, publish repo metadata, open issues/PRs |\n| Custom scripts for NIP-98 bridge auth and NIP-34 signing | Signing, challenge handling, and relay checks are built in |\n| Unclear whether a push “really” landed on Nostr | Tools return pass/fail plus `verification` / `nextSteps` for automation |\n\n**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.\n\n**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.\n\n## Where this sits (platform map)\n\ngittr-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).\n\n```mermaid\nflowchart TB\n  Agent[\"AI host<br/>Cursor / Claude / …\"]\n  MCP[\"★ YOU ARE HERE · gittr-mcp<br/>this repo · agent tools\"]\n  UI[\"gittr Client<br/>gittr.space\"]\n  Bridge[\"gitnostr Bridge<br/>git.gittr.space<br/>SSH / HTTPS git\"]\n  RelayGittr[\"gittr Pyramid relay<br/>relay.gittr.space<br/>wss · open forge + GRASP\"]\n  Relays[\"Other Nostr relays\"]\n  Pages[\"Pages / nsite<br/>pages.gittr.space\"]\n  Remote[\"git remote nostr<br/>optional\"]\n\n  Agent -->|MCP tools| MCP\n  MCP -->|HTTPS + Nostr auth| Bridge\n  MCP -->|sign NIP-34 events| RelayGittr\n  MCP -->|sign NIP-34 events| Relays\n  UI --> RelayGittr\n  UI --> Relays\n  UI --> Bridge\n  Pages --> Relays\n  Remote -.-> Relays\n\n  classDef youAreHere fill:#0f766e,stroke:#5eead4,stroke-width:3px,color:#ecfdf5\n  classDef hostUrl fill:#164e63,stroke:#22d3ee,stroke-width:2px,color:#ecfeff\n  class MCP youAreHere\n  class Bridge,Pages,RelayGittr hostUrl\n```\n\n| Piece | Host / link | How MCP uses it |\n| --- | --- | --- |\n| **gittr Client** | [gittr on gittr.space](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/gittr?branch=main) · `gittr.space` | Same product; MCP mirrors forge actions (repos, issues, PRs, bounties) |\n| **gitnostr Bridge** | [gitnostr on gittr.space](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/gitnostr?branch=main) · **`git.gittr.space`** | `pushToBridge`, file list, merge clones over HTTPS |\n| **Pages / nsite** | [nsite-gateway](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/nsite-gateway) · **`pages.gittr.space`** | Out of band for most MCP git tools |\n| **gittr Pyramid relay** | [pyramid](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/pyramid) · **`relay.gittr.space`** | Prefer in relay lists when publishing NIP-34 |\n| **★ gittr-mcp (this README)** | [gittr-mcp on gittr.space](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/gittr-mcp) | **You are here** |\n| **git remote nostr** | [ngit-cli](https://github.com/DanConwayDev/ngit-cli) | Not required for MCP; agents usually use bridge HTTPS + events |\n\n**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.\n\n---\n\n## What you can do (workflows)\n\nThese are the **processes** people actually run; each maps to MCP tools the agent can call.\n\n### Ship a new project\n1. **`createRepo`** — push initial files to the bridge **and** publish Nostr kinds **30617** + **30618** in one step (best default for agents).  \n   Pass **`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.  \n2. Or step-by-step: **`pushToBridge`** → **`publishRepoAnnouncement`** → **`publishRepoState`**.\n\n### Private repositories\n- Set **`publicRead: false`** on **`createRepo`**, **`publishRepoAnnouncement`**, **`forkRepo`**, or **`mirrorRepo`**.\n- Private repos are **hidden from Explore/home/profile listings** for strangers.\n- **Direct URL** still shows the repo name with a **Private** badge; unauthorized viewers see a lock screen (no code).\n- **SSH / CLI / API reads** use the same ACL as the web UI: your **npub** must be owner or maintainer (`addCollaborator` or Settings → Contributors on gittr.space).\n- **SSH key registration** is unchanged — keys identify *you*; private repos only check whether *your pubkey* has read permission.\n\n### Day-to-day development\n- **`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).  \n- **`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](docs/MCP-GITTR-PARITY.md) and gittr [FILE_FETCHING_INSIGHTS.md](https://gittr.space/npub1n2ph08n4pqz4d3jk6n2p35p2f4ldhc5g5tu7dhftfpueajf4rpxqfjhzmc/gittr?file=docs/FILE_FETCHING_INSIGHTS.md&branch=main).\n- **`resolveRepoByNostrId`** — find clone URLs and relays from npub + repo name.\n\n### Issues (bug reports, tasks)\n- **`listIssues`**, **`createIssue`**, **`getIssueById`**  \n- **`listIssueComments`**, **`createIssueComment`** — NIP-22 kind **1111** (same tags as gittr issue threads). Does **not** touch bounties.\n- **`closeIssue`**, **`reopenIssue`** — publish NIP-34 status events (1632 / 1630).\n\n### Pull requests (code review flow)\n| Step | Tool | Notes |\n|------|------|--------|\n| List / open PR | **`listPRs`**, **`createPR`** | Signed Nostr events (kind **1618**). |\n| Comment on PR | **`listPRComments`**, **`createPRComment`** | NIP-22 kind **1111**. |\n| Full PR with git branches | **`createPRViaGittrCLI`** | Recommended when the agent has **`git`** on PATH. |\n| Update PR tip | **`updatePullRequest`** | New commit + clone URLs on the PR event. |\n| Merge into `main` | **`mergePullRequest`** | **Real git merge**: clone/fetch, merge, push bridge, publish **30618** + merged status **1631**. Repo owner or listed maintainer; **`git` required**. |\n| Mark merged (Nostr only) | **`markPullRequestMerged`** | Status only — no git merge. |\n\n**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](#limitations-prs--clone-urls)) or use **`createPRViaGittrCLI`**. Details: [docs/DEVELOPER.md#limitations](docs/DEVELOPER.md#limitations).\n\n### Fork, mirror, import\n- **`forkRepo`** — fork an existing gittr repo under your key.  \n- **`mirrorRepo`** — copy from GitHub/GitLab URL to gittr.  \n- **`importRemoteToBridge`** — server-side import/refetch into bridge storage.\n\n### Discover & social\n- **`listRepos`**, **`searchRepos`**, **`myRepos`**, **`exploreRepos`**, **`getTrendingRepos`** (trending = recent repos, not engagement rank)  \n- **`starRepo`**, **`unstarRepo`**, **`listStars`** — NIP-25 on the repo’s **30617** event (same as gittr Star button).  \n- **`watchRepo`**, **`unwatchRepo`**, **`listWatchedRepos`** — NIP-51 kind **10018** followed-repo list (same as gittr Watch).  \n- **`getRepoContributors`**\n\n**Parity details:** [docs/MCP-GITTR-PARITY.md](docs/MCP-GITTR-PARITY.md) — what matches gittr.space vs caveats.\n\n### Releases & tags\n- **`listReleases`** — git **tags** from bridge (`refs/tags/*`), not the web UI Releases tab and not Zapstore.  \n- **`listForgeReleases`** — forge Releases tab listing (all assets; no NIP-82 MIME gate).  \n- **`createRelease`** — returns guidance only (UI release notes until next **30617** push).  \n- **`fetchForgeReleases`** — one forge Release + announceable binaries. Omit `tag` for latest; `hash:true` for sha256 (required before announce).  \n- **`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. Optional `pinToBlossom` (public Blossom only — never `blossom.gittr.space`). Same as gittr **Nostr Apps** (latest) or Releases **Announce on Nostr** (`tag=`). Never a tagless app.  \n- **`deleteSoftwareAnnounce`** — NIP-09 kind **5** for those app/release/asset event ids.\n\n### Pages & security\n- **`publishNostrPages`** — NIP-5A kind **35128** + Blossom upload through gittr (`index.html` required).  \n- **`auditRepoDependencies`** — parse lockfiles on the bridge and query OSV via gittr `/api/security/audit`.\n\n### Lightning bounties & pay-to-push\n- Bounties: **`listBounties`**, **`createBountyInvoice`**, **`publishBountyToNostr`**, **`submitBounty`**, **`listBountiesForIssue`**, release/withdraw tools.  \n- Paywall: **`getPushPaywallStatus`**, **`createPushPaywallIntent`**, **`syncRepoPushPolicy`**.  \n- Optional LNbits: set **`GITTR_LNBITS_URL`** and **`GITTR_LNBITS_ADMIN_KEY`** in MCP env (see `.env.example`).\n\n### Session / keys\n- **`describeAgentAuth`** — run once: confirms keys load (never returns `nsec`); if unconfigured it tells the agent to ask you about a test keypair.  \n- **`setupTestKeypair`** — after your explicit OK, writes a disposable test identity to `.nostr-keys.json` (replace with your real `nsec` anytime).  \n- **`loadCredentials`**, **`getPublicKey`** — debugging helpers. MCP `loadCredentials` masks `nsec` (prefix only), `secretKey`, and `private_key`.\n\n**Full tool list:** 50+ tools in `server.js` (search for `name:`). Library API: [docs/DEVELOPER.md](docs/DEVELOPER.md).\n\n---\n\n## Install (5 minutes)\n\n### Requirements\n- **Node.js 18+**\n- A **Nostr private key** (`nsec` or hex) — same identity you use on gittr.space\n\n### 1. Get the server\n\n**Clone (developers / Cursor):**\n\n```bash\ngit clone https://github.com/arbadacarbaYK/gittr-mcp.git\ncd gittr-mcp\nnpm install\n```\n\n**Claude Desktop one-click (`.mcpb`):** download the latest bundle from [GitHub Releases](https://github.com/arbadacarbaYK/gittr-mcp/releases) (`gittr-mcp-x.y.z.mcpb`). New releases are built automatically when we push a `v*` tag — see [docs/RELEASE.md](docs/RELEASE.md).\n\n### 2. Add your key (local only, never commit)\n\n```bash\ncp .nostr-keys.json.example .nostr-keys.json\n```\n\nEdit `.nostr-keys.json` and set your **`nsec`** (or hex `secretKey`). The file is gitignored.\n\nLookup order: `./.nostr-keys.json` → `~/.nostr-identity.json` → `~/.config/gittr/keys.json`.\n\n**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.\n\n### 3. Wire up your MCP host\n\n**Important:** **Add** a new server entry — do **not** replace your entire MCP config.\n\n#### Cursor\n\nEdit `~/.cursor/mcp.json` (or project MCP settings). Use an **absolute** path:\n\n```json\n{\n  \"mcpServers\": {\n    \"gittr\": {\n      \"command\": \"node\",\n      \"args\": [\"/ABSOLUTE/PATH/TO/gittr-mcp/server.js\"],\n      \"env\": {\n        \"BRIDGE_URL\": \"https://gittr.space\"\n      }\n    }\n  }\n}\n```\n\nReload MCP or restart Cursor.\n\n#### Claude Desktop\n\nQuit Claude, edit `claude_desktop_config.json` (path depends on OS — see Anthropic docs), same `mcpServers` block as above, restart.\n\n#### VS Code / Copilot, Windsurf, OpenClaw, custom apps\n\nSame stdio contract: `command`: `node`, `args`: `[\"/path/to/server.js\"]`, optional `env`.  \nOpenClaw / mcporter: [docs/MCP-HOSTS.md](docs/MCP-HOSTS.md).\n\n#### Embed as a library (no MCP)\n\n```javascript\nconst gittr = require('gittr-mcp');\nawait gittr.pushToBridge({ /* ... */ });\n```\n\nEntry point: `index.js`. MCP process: `server.js` (npm bin **`gittr-mcp`**).\n\n### 4. Verify\n\nIn chat, ask the agent to call **`describeAgentAuth`**, or from the repo:\n\n```bash\nnpm test                 # full package (includes clone-set + forge-match regressions)\nnpm run test:regressions # fast: grasp clone URLs + findReposBySource matchers\nnpm run test:mcp-stdio   # optional live stdio CallTool matrix\n```\n\nUI / file-fetch tip fidelity regressions live in the gittr monorepo: `cd ../gittr/ui && npm run test:regressions` (see gittr `docs/FILE_FETCHING_INSIGHTS.md`).\n\n---\n\n## What to ask your agent\n\nExamples that map to the workflows above:\n\n- “Create a repo `my-demo` with a README and publish it on gittr.”  \n- “Push these file changes to `my-demo` on `main`.”  \n- “Open an issue: login button broken.”  \n- “List open PRs on npub…/my-demo and merge PR `<id>` if I’m the owner.”  \n- “Mirror `https://github.com/user/repo` to gittr as `repo-name`.”\n\nAgents should read tool results as JSON; many responses include **`agentSummary`** and **`nextSteps`**.\n\n---\n\n## Limitations (PRs & clone URLs)\n\nShort version — full detail in [docs/DEVELOPER.md](docs/DEVELOPER.md):\n\n1. **Bridge push** and **Nostr publish** are separate steps unless you use **`createRepo`**. Pushing alone does not make the repo visible everywhere.  \n2. **`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.  \n3. **`mergePullRequest`** needs **`git`** on the machine running MCP and maintainer/owner rights.  \n4. Relays can rate-limit or lag; failed verification is a **failed** publish, not “maybe OK.”\n\n### Do MCP users get gittr’s filter / CORS server fixes?\n\n**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.\n\n**MCP package updates are separate.** Cursor/Claude do **not** auto-pull new MCP code. To get new tools or clone-tag logic:\n\n- **git clone install:** `cd gittr-mcp && git pull && npm install`, then reload MCP / restart the host  \n- **Claude `.mcpb`:** download the latest from [Releases](https://github.com/arbadacarbaYK/gittr-mcp/releases) and reinstall the bundle\n\n---\n\n## For developers\n\n```bash\nnpm ci\nnpm test\n# Live tests (real relays; optional LNbits) — see .env.example\nGITTR_TEST_NSEC=nsec1... npm run test:live:matrix\n```\n\n| Doc | Contents |\n|-----|----------|\n| [docs/MCP-HOSTS.md](docs/MCP-HOSTS.md) | Per-host MCP config |\n| [docs/AGENT-WORKFLOW.md](docs/AGENT-WORKFLOW.md) | Step-by-step push + publish |\n| [docs/AGENT-QUICKSTART.md](docs/AGENT-QUICKSTART.md) | Copy-paste agent prompts |\n| [docs/DEVELOPER.md](docs/DEVELOPER.md) | API, verification contract, GRASP |\n| [docs/SIGNING-GUIDE.md](docs/SIGNING-GUIDE.md) | Keys and NIP-98 |\n| [docs/NIP34-SCHEMAS.md](docs/NIP34-SCHEMAS.md) | Event kinds |\n| [docs/MCP-GITTR-PARITY.md](docs/MCP-GITTR-PARITY.md) | MCP vs gittr.space feature map |\n\n---\n\n## Security\n\n- Do **not** commit `.nostr-keys.json`, `.env`, or real `nsec` values.  \n- Bridge auth uses **NIP-98**; treat agent transcripts as sensitive.  \n- Only **`.nostr-keys.json.example`** belongs in git.\n\n---\n\n## Links\n\n- **This repo:** https://github.com/arbadacarbaYK/gittr-mcp  \n- **gittr.space:** https://gittr.space  \n- **Glama:** https://glama.ai/mcp/servers/arbadacarbaYK/gittr-mcp  \n- **Awesome MCP Servers:** https://github.com/punkpeye/awesome-mcp-servers (Version Control)  \n- **NIP-34 (git on Nostr):** https://github.com/nostr-protocol/nips/blob/master/34.md  \n\nSee [LICENSE](LICENSE) (MIT).\n",
  "bytes": 17332,
  "sha": "31cefdcd19caef3372980f0fba7d6dc7d449ff96bd82a226daf88854fd396e23",
  "repo_slug": "arbadacarbayk/gittr-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_arbadacarbayk_gittr_mcp_d8d20036/readme"
}