pincushion-mcp

pincushion-mcp

Visual feedback as agent work packets: stakeholders pin on your live app and your AI coding agent reads each pin (selector, screenshot, DOM, thread, acceptance criteria) via MCP and ships the fix.

Category
访问服务器

README

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 status
  • POST /call-tool — Invoke a tool
    • Body: { "toolName": "get_feedback_summary", "args": {} }

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 name
  • status (string, optional) — Filter by open, in-progress, or resolved

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 ID
  • comment (string, optional) — Resolution message
  • resolvedBy (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 ID
  • body (string, required) — Reply message
  • author (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 ID
  • fixDescription (string, required) — Description of the fix
  • filePath (string, optional) — File where fix was applied
  • lineNumber (number, optional) — Line number of the fix
  • commitSha (string, optional) — Commit SHA that landed the change
  • branchName (string, optional) — Branch the commit was made on
  • prUrl (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_ready and follow_up
  • Design or PM channel: mention and optionally resolved
  • Launch or QA channel: pageUrlPatterns plus pin_ready, follow_up, and resolved
  • 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:

  1. Set up a Supabase project at supabase.com
  2. Create an annotations table with columns matching the annotation schema
  3. Generate an API key from your project settings
  4. Configure the server with --sync-url and --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


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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选