
Pincushion
- 1 repo stars
- Updated June 27, 2026
- jcooley8/pincushion-plugin
Pincushion MCP is a MCP server that lets your agent read stakeholder feedback pinned on your live app so it can implement fixes from real UI context.
About
Pincushion MCP links in-app stakeholder feedback to your AI coding agent: reviewers pin notes on the live product, and the agent pulls that structured input through MCP to implement fixes. For developers shipping client work or small-team SaaS, it reduces the slack-and-screenshot churn between demo URLs and Cursor or Claude Code sessions. You install the pincushion-mcp npm server over stdio and connect it alongside your usual repo tools. It is a collaboration MCP integration, not a code generator skill—value shows up when you already deploy previews or production URLs stakeholders can annotate.
- Stakeholders pin feedback directly on the live application UI
- MCP bridge lets the coding agent read pinned issues in context
- Closes the loop from review comment to code change in one toolchain
- npm stdio package pincushion-mcp (v1.3.1)
- Designed for agent-first fix workflows, not static ticket exports
Pincushion by the numbers
- Data as of Jul 9, 2026 (Skillselion catalog sync)
claude mcp add pincushion-mcp -- npx -y pincushion-mcpAdd your badge
Show developers this MCP server is listed on Skillselion. Paste this into your README.
| repo stars | ★ 1 |
|---|---|
| Package | pincushion-mcp |
| Transport | STDIO |
| Auth | None |
| Last updated | June 27, 2026 |
| Repository | jcooley8/pincushion-plugin ↗ |
What it does
Wire live-app stakeholder pins into your coding agent so feedback becomes actionable fixes without copy-pasting screenshots.
Who is it for?
Best when you're running preview or production URLs where non-technical stakeholders mark up the app while you code in an MCP agent.
Skip if: Pure local-only CLI projects with no deployed UI or teams that want a full issue tracker replacement without the Pincushion product workflow.
What you get
Pinned comments flow into MCP tools so the agent can fetch feedback and ship fixes without manual re-description of every UI bug.
- Agent-readable pinned feedback from the live application
- Structured input for implementing UI and copy fixes
- Reduced manual transfer of review notes into the IDE
By the numbers
- Server version 1.3.1
- npm package identifier pincushion-mcp
- stdio MCP transport
README.md
Pincushion MCP Server
The implementation-context layer for AI-native development. Stakeholders drop visual pins on any page of your live app; your AI coding agent reads each pin through MCP and ships the fix — in Claude Code, Cursor, VS Code, Windsurf, or any MCP client.
What makes a Pincushion pin different
A pin isn't a feedback item — it's an agent work packet. Each one carries everything an agent needs to implement the change without a back-and-forth:
- URL + element selector — exactly what, exactly where
- Screenshot + viewport + DOM snippet — the visual and structural context
- Thread + project context — the conversation and the codebase it lives in
- Likely files + acceptance criteria — where to look, and how to know it's done
The loop closes itself: a stakeholder pins it → your agent reads it via MCP and fixes it in your IDE → the resolve records the commit, branch, and PR → an optional post-deploy critique verifies the fix actually landed.
This server is also how Pincushion AI runs design/copy/a11y critiques on a live page and writes the pins straight back onto it.
Installation
# npm
npm install -g pincushion-mcp
# pnpm
pnpm add -g pincushion-mcp
# yarn
yarn global add pincushion-mcp
Or run directly without installing:
# npm
npx pincushion-mcp --project-dir .
# pnpm
pnpm dlx pincushion-mcp --project-dir .
# yarn
yarn dlx pincushion-mcp --project-dir .
Quick Start
1. Install the Browser Extension
Download the Pincushion Chrome extension from pincushion.io/install/chrome.
2. Configure Your Agent
Pick your AI agent below and follow the configuration for your setup.
3. Start Using
Once configured, your agent can:
- See all feedback:
get_feedback_summary - Find specific pins:
search_annotations - Fix and mark as done:
fix_and_resolve
Agent Configuration Guides
Cursor
File: .cursor/mcp.json
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "."]
}
}
}
pnpm / yarn users: replace
"command": "npx"with"command": "pnpm"and add"dlx"as the first arg, or use"command": "yarn"with"dlx"likewise.
With Supabase sync:
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": [
"pincushion-mcp",
"--project-dir", ".",
"--sync-url", "https://your-supabase.com/api",
"--api-key", "YOUR_API_KEY"
]
}
}
}
Claude Desktop
File: ~/.config/Claude/claude_desktop_config.json (Linux/Windows)
or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "/path/to/your/project"]
}
}
}
pnpm users:
{
"mcpServers": {
"pincushion": {
"command": "pnpm",
"args": ["dlx", "pincushion-mcp", "--project-dir", "/path/to/your/project"]
}
}
}
yarn users:
{
"mcpServers": {
"pincushion": {
"command": "yarn",
"args": ["dlx", "pincushion-mcp", "--project-dir", "/path/to/your/project"]
}
}
}
With Supabase sync:
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": [
"pincushion-mcp",
"--project-dir", "/path/to/your/project",
"--sync-url", "https://your-supabase.com/api",
"--api-key", "YOUR_API_KEY"
]
}
}
}
Claude Code (CLI)
Run this command to add Pincushion to Claude Code:
claude mcp add pincushion -- npx pincushion-mcp --project-dir .
Or with Supabase sync:
claude mcp add pincushion -- npx pincushion-mcp --project-dir . --sync-url https://your-supabase.com/api --api-key YOUR_API_KEY
VS Code (Copilot / Continue)
File: .vscode/settings.json
{
"mcp.servers": {
"pincushion": {
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "${workspaceFolder}"]
}
}
}
Windsurf / Codeium Windsurf
File: ~/.windsurf/mcp.json or ~/.config/windsurf/mcp.json
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "."]
}
}
}
Antigravity
File: ~/.antigravity/mcp.json
{
"mcpServers": {
"pincushion": {
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "."]
}
}
}
OpenAI Codex / REST API Clients
For tools that don't support MCP directly, use the REST API wrapper:
npx pincushion-mcp --rest --port 3456
This starts an HTTP server on localhost:3456. Endpoints:
GET /health— Check server statusPOST /call-tool— Invoke a tool- Body:
{ "toolName": "get_feedback_summary", "args": {} }
- Body:
Example using curl:
curl -X POST http://localhost:3456/call-tool \
-H "Content-Type: application/json" \
-d '{"toolName": "get_feedback_summary", "args": {}}'
CLI Flags
npx pincushion-mcp [flags]
| Flag | Description | Default |
|---|---|---|
--project-dir PATH |
Root directory containing .feedback/ |
Current working directory |
--sync-url URL |
Supabase API endpoint for remote sync | None (local only) |
--api-key KEY |
API key for Supabase authentication | None |
--license-key KEY |
Pro license key (optional) | None |
--rest |
Enable REST API mode | Disabled (uses MCP/stdio) |
--port PORT |
Port for REST API server | 3456 |
Examples
Local project:
npx pincushion-mcp --project-dir /path/to/project
With Supabase sync:
npx pincushion-mcp \
--project-dir /path/to/project \
--sync-url https://abcd1234.supabase.co/api \
--api-key sb_project_key_abc123...
REST API server:
npx pincushion-mcp --rest --port 8080
Tools
get_annotations
Retrieve annotations from .feedback/. Filter by page, component, or status.
Parameters:
pageUrl(string, optional) — Filter by page URL (partial match)componentName(string, optional) — Filter by LWC component namestatus(string, optional) — Filter byopen,in-progress, orresolved
Example:
await mcp.callTool('get_annotations', {
componentName: 'wmlHomePage',
status: 'open'
});
search_annotations
Full-text search across all annotations, comments, selectors, and tags.
Parameters:
query(string, required) — Search term
Example:
await mcp.callTool('search_annotations', {
query: 'button label'
});
get_feedback_summary
High-level rollup of all feedback: counts by status, priority, page, and component.
Example:
await mcp.callTool('get_feedback_summary', {});
get_component_feedback
Get all feedback for a specific LWC component with a plain-language summary.
Parameters:
componentName(string, required) — LWC component name
Example:
await mcp.callTool('get_component_feedback', {
componentName: 'wmlHomePage'
});
resolve_annotation
Mark an annotation as resolved after fixing the issue.
Parameters:
annotationId(string, required) — Annotation IDcomment(string, optional) — Resolution messageresolvedBy(string, optional) — Name to attribute resolution (default: "AI Agent")
Example:
await mcp.callTool('resolve_annotation', {
annotationId: 'ann_abc123',
comment: 'Updated button label in line 42 of wmlHomePage.js'
});
add_agent_reply
Add a reply to an annotation thread (e.g., ask clarifying questions).
Parameters:
annotationId(string, required) — Annotation IDbody(string, required) — Reply messageauthor(string, optional) — Author name (default: "AI Agent")
Example:
await mcp.callTool('add_agent_reply', {
annotationId: 'ann_abc123',
body: 'Is this button in the main navigation or sidebar?'
});
fix_and_resolve
Combine fixing code and marking an annotation as resolved in one call. Optionally records commit / branch / PR metadata so the dashboard can backlink to what shipped.
Parameters:
annotationId(string, required) — Annotation IDfixDescription(string, required) — Description of the fixfilePath(string, optional) — File where fix was appliedlineNumber(number, optional) — Line number of the fixcommitSha(string, optional) — Commit SHA that landed the changebranchName(string, optional) — Branch the commit was made onprUrl(string, optional) — Pull request URL (GitHub/GitLab/Bitbucket; shape-validated)
Example:
await mcp.callTool('fix_and_resolve', {
annotationId: 'ann_abc123',
fixDescription: 'Updated button label to match design spec',
filePath: 'src/components/wmlHomePage.js',
lineNumber: 42,
commitSha: 'abc123def456',
branchName: 'pincushion/checkout-fix',
prUrl: 'https://github.com/acme/app/pull/142'
});
get_implementation_packet
Fetch a single implementation packet for one page URL — selector list, full pin payloads, suggested branch name, and traceability config. Use when an agent wants to batch-fix one page in a single branch.
await mcp.callTool('get_implementation_packet', { pageUrl: '/checkout' });
assign_pin_to_agent
Dispatch a pin straight to your local coding agent. Promotes the pin to ready if not already, marks pending_implementation, and writes a .feedback/.agent-queue/<id>.json trigger file that agent-loop.mjs picks up and shells out to Cursor / Claude Code / Codex.
await mcp.callTool('assign_pin_to_agent', { annotationId: 'ann_abc123' });
link_pin_deploy
Attach a deploy URL to a resolved pin. Typically called by the deploy-hook edge function once production includes the fix, but available manually too.
await mcp.callTool('link_pin_deploy', {
annotationId: 'ann_abc123',
deployUrl: 'https://acme-app.vercel.app'
});
record_pin_verification
Write Pincushion AI's post-deploy verdict back to the pin. Called by the critic agent after /critique-latest-deploy runs against a fresh deploy.
await mcp.callTool('record_pin_verification', {
annotationId: 'ann_abc123',
status: 'verified', // or 'regressed' or 'inconclusive'
notes: 'Button matches the primary token. No regression on adjacent CTAs.'
});
get_time_to_fix_metrics
Pro/Team feature — Free callers get sample size + upgrade hint. Median + p25/p75 of pin-to-resolve duration, with a 5-pin minimum so the metric is never noise.
await mcp.callTool('get_time_to_fix_metrics', { scope: 'project', projectId: 'pc_proj_abc' });
// → { sampleSize, thresholdMet, median, p25, p75, medianHuman, ... }
get_setup_instructions (NEW)
Get setup and configuration instructions for all supported agents.
Example:
await mcp.callTool('get_setup_instructions', {});
Slack and Microsoft Teams integrations
Pincushion can notify Slack or Microsoft Teams through project-scoped incoming webhooks. The defaults are intentionally quiet and Figma-inspired: notify when a pin is ready for implementation, when someone is @mentioned, and when a collaborator adds follow-up on work already being handled. Every newly dropped pin and every resolution are opt-in events.
Recommended use cases:
- Developer channel:
pin_readyandfollow_up - Design or PM channel:
mentionand optionallyresolved - Launch or QA channel:
pageUrlPatternspluspin_ready,follow_up, andresolved - Temporary incident channel: enable a focused subscription, then pause it after the ship window
Example:
await mcp.callTool('configure_collaboration_integration', {
projectId: 'my-project',
provider: 'slack',
webhookUrl: 'https://hooks.slack.com/services/...',
targetLabel: '#product-feedback',
events: ['pin_ready', 'mention', 'follow_up'],
pageUrlPatterns: ['staging.example.com/checkout'],
sendTest: true
});
For Slack, use create_slack_install_link when the hosted Slack app secrets are configured. It returns an Add-to-Slack URL; after approval, Slack returns the incoming webhook and Pincushion stores it automatically.
Use list_collaboration_integrations to audit configured destinations, remove_collaboration_integration to disconnect one, and preview_collaboration_notification to see the payload shape before adding a real webhook. Webhook URLs are stored server-side and returned only as masked values.
Auto-Agent Loop (Optional)
For agents that don't watch the file system (Claude Code, Cursor, generic),
agent-loop.mjs polls .feedback/.agent-queue/ and dispatches new pins
to the configured agent automatically.
# from inside the pincushion-mcp directory
npm run agent-loop -- --project-dir /path/to/your/project
# or directly
node agent-loop.mjs --project-dir /path/to/your/project [--agent claude-code|cursor|generic] [--interval 3000]
The bridge (server.js) writes one trigger file per approved pin into
.feedback/.agent-queue/. The loop reads them, builds a prompt with
the pin's thread + element selector, and shells out to the chosen agent.
The agent uses MCP tools (claim_pin → fix → fix_and_resolve) and
the queue file is removed when the pin closes.
detectAgent() auto-detects claude or cursor on the PATH; falls
back to generic (writes the prompt to .feedback/.agent-prompt and
stdout). Run with --interval 3000 to control poll cadence.
Local File Structure
The server reads annotations from .feedback/ in your project:
.feedback/
├── annotations/
│ ├── example-com-login.json
│ ├── example-com-dashboard.json
│ └── ...
└── index.json
Each annotation file contains:
{
"pageUrl": "https://example.com/login",
"pageTitle": "Login",
"annotations": [
{
"id": "ann_abc123",
"status": "open",
"priority": "high",
"tags": ["design", "accessibility"],
"createdAt": "2026-03-19T10:30:00Z",
"element": {
"lwcComponent": "wmlLoginForm",
"selector": ".login-button",
"textContent": "Sign In"
},
"thread": [
{
"author": "Design Team",
"timestamp": "2026-03-19T10:30:00Z",
"body": "Button label should say 'Sign In' not 'Login'",
"type": "comment"
}
]
}
]
}
Supabase Sync
To sync annotations with a remote Supabase database:
- Set up a Supabase project at supabase.com
- Create an
annotationstable with columns matching the annotation schema - Generate an API key from your project settings
- Configure the server with
--sync-urland--api-key
Example:
npx pincushion-mcp \
--project-dir . \
--sync-url https://your-project.supabase.co/rest/v1 \
--api-key sb_project_key_abc123...
The server merges local .feedback/ files with remote data, with remote taking precedence on newer updates.
Pro License
Pincushion Pro includes additional features. Activate with --license-key:
npx pincushion-mcp --project-dir . --license-key YOUR_PRO_KEY
Troubleshooting
"Module not found" error
Make sure you have Node.js 18+ installed:
node --version
Install dependencies:
npm install @modelcontextprotocol/sdk
Annotations not appearing
Check that .feedback/ exists in your project directory:
ls -la .feedback/
If it doesn't exist, create it and add some test annotations, or the extension will create it when you pin your first feedback.
Supabase sync not working
Verify your credentials:
curl -H "x-api-key: YOUR_API_KEY" \
https://your-project.supabase.co/rest/v1/annotations
Agent can't find the server
In your agent config, use the full path to pincushion-mcp:
which pincushion-mcp
# Use the output path in your config
Or use npx to let it find the package:
{
"command": "npx",
"args": ["pincushion-mcp", "--project-dir", "."]
}
Development
Clone the repository and install dependencies:
git clone https://github.com/jcooley8/pincushion-plugin.git
cd pincushion-plugin
npm install
Run the server:
npm start
Or with test data:
npm start -- --project-dir ./test-feedback
License
MIT License. See LICENSE file for details.
Support
- Issues: GitHub Issues
- Docs: Pincushion Documentation
Changelog
v1.0.0 (March 2026)
- Initial release
- Support for Cursor, Claude Desktop, Claude Code, VS Code, Windsurf, Antigravity
- Local
.feedback/file support - Supabase remote sync
- REST API wrapper for non-MCP clients
- New tools:
fix_and_resolve,get_setup_instructions
Recommended MCP Servers
How it compares
Live-app feedback MCP bridge, not a generic GitHub issue or code-review skill.
FAQ
Who is Pincushion MCP for?
Developers who ship web apps and want clients or teammates to pin UI feedback that Claude Code, Cursor, or similar agents can read and act on.
When should I use Pincushion MCP?
Use it during active build and iteration when you have a deployed app and need stakeholder comments to drive agent-led fixes.
How do I add Pincushion MCP to my agent?
Add the pincushion-mcp npm package as a stdio MCP server in your agent config and complete setup with the Pincushion plugin workflow on your live app.