MCP server for AI agents
Drive your full PinAppAI iteration loop from Claude Code, Cursor, or any MCP-aware agent — install, fix CRs, apply decisions, regen /changes/, remove the integration — without leaving your editor.
The PinAppAI MCP server is the AI-native interface to your project. Instead of pasting decision dumps into Claude Code, your agent runs /pinappai:apply-decisions (or any other slash command) and walks the full iteration loop end-to-end — read live state, propose code edits, write a marker so the next regeneration knows where the boundary is, and ASK before committing anything.
The MCP server is published as @pinappai/mcp on npm and runs as a stdio server next to the agent.
Install
Two commands — works for any AI client (Claude Code, Cursor, Claude Desktop, Codex CLI, Continue):
npx @pinappai/mcp install # registers the MCP entry in every detected AI client config
npx @pinappai/mcp login # opens browser for sign-in, mints a per-machine key, saves it locally
install writes the MCP server entry into every AI client config it finds on your machine (~/.claude.json, ~/.cursor/mcp.json, ~/.codex/config.toml, ~/.continue/config.yaml, ~/Library/Application Support/Claude/claude_desktop_config.json). No credential is written at this step.
login runs a browser sign-in flow: prints a URL + a short approval code, opens your browser, lets you pick a workspace if you have multiple, and saves the freshly minted API key locally on your machine. The MCP server picks it up automatically on next launch.
The ppk_… API key is separate from the widget’s pk_* key — it grants your AI agent access scoped to the role of the user who approved the login.
The four CLI subcommands:
| Command | Purpose |
|---|---|
npx @pinappai/mcp install | Register MCP entry in every detected AI client config |
npx @pinappai/mcp login | Browser sign-in; mint + save a per-machine key |
npx @pinappai/mcp logout | Delete the stored credentials file |
npx @pinappai/mcp uninstall | Remove MCP entry from AI client configs |
Verify after login + AI client restart by running any slash command in the agent (/pinappai: should auto-complete the menu).
CI / headless installs
The browser-based login doesn’t fit non-interactive contexts. Set PINAPPAI_API_KEY=ppk_… in the environment that spawns the MCP — the MCP server reads env first, then the credentials file. Mint the key from app.pinappai.com/api-keys; name it after the machine / pipeline so you can revoke cleanly later.
Manual install
If you’d rather wire up a single client by hand — or you need to pin a specific version — these are the per-client config snippets the new install writes for you:
Claude Code
claude mcp add-json pinappai '{"type":"stdio","command":"npx","args":["-y","@pinappai/mcp"],"env":{"PINAPPAI_API_KEY":"ppk_..."}}'
Cursor — ~/.cursor/mcp.json
{ "mcpServers": { "pinappai": { "command": "npx", "args": ["-y", "@pinappai/mcp"], "env": { "PINAPPAI_API_KEY": "ppk_..." } } } }
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json
{ "mcpServers": { "pinappai": { "command": "npx", "args": ["-y", "@pinappai/mcp"], "env": { "PINAPPAI_API_KEY": "ppk_..." } } } }
Codex CLI — ~/.codex/config.toml
[mcp_servers.pinappai]
command = "npx"
args = ["-y", "@pinappai/mcp"]
[mcp_servers.pinappai.env]
PINAPPAI_API_KEY = "ppk_..."
Continue — ~/.continue/config.yaml
mcpServers:
- name: pinappai
command: npx
args: ["-y", "@pinappai/mcp"]
env:
PINAPPAI_API_KEY: ppk_...
PINAPPAI_API_BASE is optional and defaults to https://api.pinappai.com.
The 10 slash commands
Slash commands ship inside the MCP server — no extra setup. Type /pinappai: in your AI client and the host shows the menu. The full set:
| Command | Purpose |
|---|---|
/pinappai:setup-project | Walk through workspace + project + widget snippet + reviewers from scratch. Bootstraps the iteration boundary marker. |
/pinappai:fix-changes | Triage queued change requests, propose code edits, write the marker, ASK before committing. |
/pinappai:apply-decisions | Apply queued reviewer decisions (rollbacks + change-requests) to source — one batch, marker-aware. |
/pinappai:generate-changes-page | Regenerate /changes/ since the last applied batch (scoped by the marker — only what’s drifted since the last apply). |
/pinappai:remove | Strip widget + /changes/ + helpers when you’re shipping the rewrite. Preserves .pinappai/ for re-install. |
/pinappai:analyze | Read-only triage report on the current CR pile — no edits made. |
/pinappai:summarize | Generate a PR description, changelog, or release note from a CR batch. |
/pinappai:audit-review | Review the audit log for a project (Business tier; owner role). |
/pinappai:triage-and-resolve | Helpers for moving CRs through the open → processing → done lifecycle without leaving the editor. |
/pinappai:auth-help | Diagnose API key / role / scope issues if a tool returns 401 or 403. |
The five featured on /mcp/ — setup-project, fix-changes, apply-decisions, generate-changes-page, remove — map to the iteration-loop arc. The other five are utilities you’ll reach for less often.
The iteration loop
You want open-ended feedback You want explicit sign-off
on a live site on a batch of changes
│ │
▼ ▼
Set up your project & Make the changes
embed the feedback widget in your source code
│ │
▼ │
Reviewers leave pinned │
feedback on the live site │
(comments, text rewrites, │
screenshots, voice notes) │
│ │
│ ┌────── (later rounds: reviewers also act on the review │
│ │ page — Approve / Reject / Request tweaks │
│ │ per item — and may leave new pins on the test │
│ │ site) ◄─────────────────────────────────────────┐ │
│ │ │ │
▼ ▼ │ │
You triage in the dashboard: │ │
what's actionable, what's not, │ │
what's already resolved │ │
│ │ │
▼ │ │
┌───────┴────────┐ │ │
▼ ▼ │ │
AI applies the AI applies the │ │
actionable per-item decisions │ │
feedback (rollbacks for rejects, │ │
refinements for tweaks) │ │
│ │ │ │
└───────┬────────┘ │ │
▼ │ │
AI generates / regenerates the review page ◄─────────────────────┼───┘
(one self-contained page, every change │
with before / after, plus per-item │
Approve / Reject / Request tweaks buttons — │
this lands in the same working tree as │
the source edits) │
│ │
▼ │
AI shows you the full diff & │
asks where to commit │
(new branch / current branch / stage only / │
skip — never auto-commits, never force-pushes) │
│ │
▼ │
Iteration boundary saved │
(the next review page only shows what's │
drifted since this round) │
│ │
▼ │
You commit & deploy to a test URL │
(one commit: source changes + the new │
review page go to test together; │
share the link with reviewers) ───────────────────────────────────┤
│ │
┌───────────┴───────────────────────┐ │
│ │ │
Everything resolved? More feedback? │
(no open or in-progress └──────────────────────────┤
items left) │
│ │
└──────────────────────────┐ │
┌──────────┴───────────┐ │
│ Ongoing project? │ │
│ Keep the widget; │ ─────────────────────┘
│ loop next round when │
│ new feedback comes in│
└──────────────────────┘
│
Shipping the rewrite?
│
▼
Strip the widget + review page
(your project config is kept,
in case you reinstall later)
│
▼
Ship to production 🚀
Three things to notice:
- Every round ends on a test URL with a refreshed review page. Reviewers always look at the current state of edits, never a stale snapshot — and they can keep refining their feedback, round after round, until everyone signs off.
- The review page only shows what’s new this round. It’s not a re-litigation of every change you’ve ever shipped — only what’s drifted since the last round of edits, so reviewers focus their attention on what actually changed.
- Two ways to leave the loop. Most projects keep the widget in place and iterate indefinitely as new feedback comes in. One-off rewrite passes can strip the widget + review page when shipping — your project config is kept either way, so reinstalling later picks up where you left off.
The .pinappai/ directory
A small folder at the root of your repo. It’s load-bearing for the iteration loop — commit it, don’t gitignore it.
| File | Purpose |
|---|---|
.pinappai/last-applied.json | The iteration boundary marker. ISO timestamp written at end of every apply run. The next /changes/ regen scopes to “git log —since= |
.pinappai/context.json | Project shape cache: detected stack (Astro / Next / Hugo / etc.), build / lint commands, source dir, route convention, localization shape, and text_lives_in (pages-inline / component-props / i18n-files / content-files / mixed). Saved once, then every prompt reads it instead of re-detecting. |
Both files are tiny (a few hundred bytes each). Committing them means a teammate’s first MCP run already knows your project’s shape — no second round of “what stack are you on?” questions per machine.
If .pinappai/ is gitignored or the working tree is read-only, the prompts fall back to in-memory detection — the loop still works, just less efficiently.
Landing-chooser — the AI never auto-commits
Every applies-to-source slash command (setup-project, fix-changes, apply-decisions, remove) ends with this verbatim block:
✅ <one-line summary>
Affected files: <list including .pinappai/last-applied.json>
How do you want to land this? Pick one:
(a) New feature branch — suggested name: pinappai/<batch>-YYYY-MM-DD-HHMM
I'll create the branch from your current HEAD, commit ALL the
affected files, and either push or stay local — your call.
(b) Commit on the current branch — same commit, no branch switch.
(c) Stage only — leave it uncommitted so you can review the diff first.
(d) Skip — don't touch git, you'll handle it manually.
Suggested commit message: <prefix>(<scope>): <summary>
Tell me which option (a / b / c / d), whether to push, and any
commit-message tweaks. I'll wait.
The agent stops there until you pick. That’s the contract — no git add, no git commit, no git push until you say which option. Branch protection is respected; --no-verify is never used. If you say “your call, just do it,” the default is (b) commit on current branch + don’t push.
Pre-flight is also covered: every applies-to-source prompt runs git status + git branch --show-current before editing. Dirty working tree → it surfaces the diff and asks instead of silently stashing.
Tools the server exposes
37 tools across read + write surfaces. Here are the 6 read tools you’ll touch most often:
| Tool | What it returns |
|---|---|
list_projects | All projects the API key can see |
list_change_requests | Recent feedback rows — pins, comments, decisions — with filtering by status / kind / page / cursor pagination |
get_change_request | Full detail for one feedback row by id: page URL, selector, before/after text, reviewer, decision, screenshot URL |
get_review_summary | Aggregate counts — pending vs decided, approved/rejected/change-requested split, per-page breakdown |
get_screenshot | The PNG bytes for an attached screenshot, base64-encoded for the agent |
analyze_patterns | Across decisions, what wording patterns are reviewers consistently rejecting? Returns clusters with examples |
The 5 newest tools (added in @pinappai/[email protected]) drive the iteration-loop primitives end to end:
| Tool | What it does |
|---|---|
pinappai_open_iteration | Atomic — snapshots the manifest of CRs to address this round (either explicit cr_ids or include_all_scheduled: true), freezes the reviewer roster, returns the iteration row |
pinappai_mark_iteration_applied | After your AI agent lands the changes, this transitions every CR in the manifest from scheduled → applied |
pinappai_acknowledge_change_request | Per-CR accept (closes — terminal) or reopen (returns to scheduled, bumps iterations_traversed); optionally cite the reviewer whose feedback drove the decision |
pinappai_get_iteration_coverage | Items decided / manifest size + per-reviewer counts + disagreement count — great for “how complete is this round?” summaries |
pinappai_list_iterations | Paginated history of past iterations + their bundle summaries — useful for showing the full review timeline at a glance |
The remaining 26 cover lifecycle (project create/update/archive, workspace create/rename/delete, member invite/role/remove, reviewer invite/revoke, API-key list/revoke/restore, audit log read, profile rename, GDPR Art. 15 export). Every write is gated by the API-key role — editor can update CRs but not invite members; admin can do everything except permanent-delete (which stays admin-UI-only by design).
Auth model
API keys are scoped per project, with a role attached at mint time (viewer / editor / admin / owner). The role determines which tools the agent can call: a viewer key sees reads only; an admin key drives the full lifecycle.
To plug an agent into a different project, mint a new key from that project’s admin page and run claude mcp add-json with a new server name (e.g. pinappai-staging). Multiple servers can coexist; the agent picks based on natural-language context.
Keys can be revoked from admin at any time — the next MCP call from that key returns 401. The agent should treat that as “I lost access, please surface a new key.”
Source
The server source and changelog live at @pinappai/mcp on npm. Bug reports and issues go to the project’s GitHub repo.