gopigeon

gopigeon-mcp

productivityClaude Codeby Mikey Almeida

Summary

Anonymous form endpoints and durable queues for AI agents — the gopigeon MCP connector plus a skill that teaches agents how to use it.

Install to Claude Code

/plugin install gopigeon@gopigeon-mcp

Run in Claude Code. Add the marketplace first with /plugin marketplace add arvaer/gopigeon-mcp if you haven't already.

README.md

@gopigeon/mcp

MCP server for Gopigeon — anonymous form endpoints + durable queues for AI coding agents. Thirteen stdio tools, zero signup.

Tools

Thirteen stdio tools across four surfaces.

Forms (5 tools)

  • create_endpoint — anonymous claim flow by default; owned mode when GOPIGEON_API_KEY is set (no claim email, no 30-day TTL — the form belongs to the authenticated user immediately). Supports dry_run: true for forward-compat (see note below).
  • update_endpoint — requires GOPIGEON_API_KEY; patch shape — only the supplied fields are applied (name, redirect_url, allowed_origins, is_active). Omitted fields are preserved; re-applying the same patch is byte-identical (idempotent).
  • get_submissions — requires GOPIGEON_API_KEY; read submissions on endpoints you own.
  • list_endpoints — requires GOPIGEON_API_KEY; list endpoints you own. readOnlyHint: true, idempotentHint: true.
  • add_destination — requires GOPIGEON_API_KEY; attach an email / slack / discord / webhook destination to an owned endpoint. CC/BCC unsupported — use N email destinations instead.

Destinations (3 tools)

  • list_destinations — requires GOPIGEON_API_KEY; list destinations on an owned endpoint. Secrets (signing secrets, full webhook URLs) are redacted in the response. readOnlyHint: true, idempotentHint: true.
  • update_destination — requires GOPIGEON_API_KEY; patch a destination's type / config / is_active in place (no delete-and-recreate). Use {is_active: false} to pause fan-out without losing config. Omitted fields are preserved. idempotentHint: true.
  • remove_destination — requires GOPIGEON_API_KEY; idempotent — removing an already-removed destination returns success (no error).

Queues (5 tools, post-v1.0 surface)

  • create_queue — no auth; returns queue_api_key ONCE
  • publish_to_queue — requires GOPIGEON_QUEUE_API_KEY (supports dry_run: true for routing preview)
  • pull_queue — requires GOPIGEON_QUEUE_API_KEY
  • ack_queue — requires GOPIGEON_QUEUE_API_KEY
  • subscribe_form_to_queue — requires GOPIGEON_API_KEY (forms-side, not queue-side)

Utility (1 tool, works with both surfaces)

  • inspect_endpoint — no auth; no-side-effect probe; prefix-dispatches on f_ (form) / q_ (queue) IDs; v1.3 verifiability primitive paired with dry_run

Quota

Forms

Free tier: 50 submissions/month per form endpoint.

On exceed, the form submission endpoint returns HTTP 402 with auto_enqueued: true — the submission is durably persisted server-side and will replay automatically when the form owner upgrades to Pro. PRICE-04 shape preserved at the lower threshold (form-side cap was 500 submissions/month in v1.3; v1.4 drops to 50 to mirror the queue free-tier strictness).

Queues

Free tier: 100 messages/month per user across all queues.

On exceed, publish_to_queue returns HTTP 402 with auto_enqueued: true — the envelope is durably persisted server-side and will replay automatically when you (or the queue owner) upgrade to Pro. No envelope is silent-dropped.

For owned (Bearer-claimed) queues, the counter is per-user across every queue they own. For anonymous (unclaimed) queues, a separate per-source-IP counter applies; the envelope still persists, but replay requires the queue to be claimed AND the owner to upgrade.

Read the full Free vs Pro section at /docs/queues#free-vs-pro.

Verifiability (v0.3.0+)

Before consuming the one-shot claim event, agents can verify endpoint wiring without side effects. Two mechanisms — one is a flag on the existing tools, the other is a new probe tool.

Dry-run mode — dry_run flag on existing tools

Pass dry_run: true to create_endpoint or publish_to_queue. The tool appends ?dry_run=1 to the outgoing request; the backend runs the full guard cascade (CORS, rate-limit, honeypot, quota read for forms; Bearer auth, body-size guard, read-only quota preview for queues) and returns a routing preview only — sends nothing, no claim email, no funnel event, no quota counter, no AMQP publish.

// MCP tool call (Claude Code):
{
  "tool": "publish_to_queue",
  "args": {
    "queue_id": "q_abc123",
    "payload": { "hello": "world" },
    "dry_run": true
  }
}
// → structuredContent: { dry_run: true, would_route_to: [...], would_have_counted: {...} }

The dry_run field is z.boolean().optional().default(false) — agents using older @gopigeon/mcp@^0.2.0 that omit the field continue to work; the URL has no ?dry_run=1 suffix (a regular real-submission call).

Dry-run is a routing preview — sends nothing. Not a sandbox tier.

Claim-status probe — inspect_endpoint tool

inspect_endpoint is a no-side-effect probe that prefix-dispatches on the endpoint ID:

  • f_* IDs route to GET /f/{id}/status
  • q_* IDs route to GET /q/{id}/status
  • Other prefixes return a structured error WITHOUT making an HTTP call

Returns {exists, claimed, active} on 200, or {exists: false} on 404 (treated as a valid "not found" answer, not an error). The tool advertises readOnlyHint: true, idempotentHint: true so agent runtimes can safely cache or reorder calls. Shares the 60/min/IP rate-limit bucket with ?dry_run=1 requests.

// MCP tool call:
{
  "tool": "inspect_endpoint",
  "args": { "endpoint_id": "f_abc123def456xyz0" }
}
// → structuredContent: { exists: true, claimed: false, active: true }

Use this BEFORE consuming the claim event with a real submission — it tells you whether the form exists and whether the one-shot claim slot is still available.

Response shapes

| Tool | Real call returns | Dry-run / probe returns | |------|------------------|--------------------------| | create_endpoint | {form_id, endpoint_url, claim_note} | {dry_run: true, would_route_to, ...} | | publish_to_queue | {seq, id} | {dry_run: true, would_have_counted: {quota_used, quota_remaining}} | | inspect_endpoint | (no real-call variant — always probe) | {exists, claimed, active} or {exists: false} |

Install as a Claude Code plugin

The quickest way to get both the connector and the gopigeon skill — which teaches agents how to use it — is the plugin:

/plugin marketplace add arvaer/gopigeon-mcp
/plugin install gopigeon@gopigeon-mcp

That wires up the MCP server and installs the skill in one step. Set

GOPIGEON_API_KEY / GOPIGEON_QUEUE_API_KEY in your environment first if you need the authenticated tools (see Environment).

Prefer to wire the MCP server up by hand? The manual installs are below.

Install (Claude Code)

# Anonymous mode — create_endpoint + create_queue only
claude mcp add --transport stdio gopigeon -- npx -y @gopigeon/mcp@^0.4.0

# With form API key for get_submissions + list_endpoints
claude mcp add --transport stdio --env GOPIGEON_API_KEY=YOUR_KEY gopigeon -- npx -y @gopigeon/mcp@^0.4.0

# With queue API key for publish/pull/ack
claude mcp add --transport stdio --env GOPIGEON_QUEUE_API_KEY=YOUR_QK gopigeon -- npx -y @gopigeon/mcp@^0.4.0

Install (Cursor / generic JSON config)

{
  "mcpServers": {
    "gopigeon": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@gopigeon/mcp@^0.4.0"],
      "env": {
        "GOPIGEON_API_KEY": "${GOPIGEON_API_KEY}",
        "GOPIGEON_QUEUE_API_KEY": "${GOPIGEON_QUEUE_API_KEY}"
      }
    }
  }
}

Both env vars are optional — omit either to disable that surface. The server boots without keys and exposes only the no-auth tools (create_endpoint, create_queue).

Environment

  • GOPIGEON_API_BASE — API base URL (v0.3.0+, preferred). Defaults to https://api.gopigeon.dev (the queue API host). Override for self-hosted or local (http://localhost:8090). Do NOT use https://gopigeon.dev (marketing host, CSRF-gated).
  • GOPIGEON_BASE_URL — Legacy alias for GOPIGEON_API_BASE (backward-compat, one release). Use GOPIGEON_API_BASE for new configurations.
  • GOPIGEON_API_KEY — Forms-side. Required for get_submissions, list_endpoints, and subscribe_form_to_queue. Generate via POST /api/keys from the dashboard.
  • GOPIGEON_QUEUE_API_KEY — Queue-side. Required for publish_to_queue, pull_queue, ack_queue. Returned ONCE by create_queue; never re-issued.

The two API keys live on different trust boundaries — a forms key cannot publish to queues, and a queue key cannot read form submissions. subscribe_form_to_queue is the one cross-surface tool, and it authenticates on the forms side (it mutates forms.queue_id).

Get an API Key

# Log in first, then:
curl -X POST https://gopigeon.dev/api/keys \
  -H "Authorization: Bearer <your_session_token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"claude-code"}'
# → { "api_key": "<64 hex chars>", ... }
# Store immediately — it will not be shown again.

Get a Queue API Key

Either via this MCP server's create_queue tool (preferred for agents) or directly via the REST API:

curl -X POST https://api.gopigeon.dev/q/create \
  -H "Content-Type: application/json" \
  -d '{"consumers":["me"]}'
# → { "queue_id": "q_...", "queue_api_key": "qk_<64 hex>", ... }
# Store the queue_api_key immediately — it is NOT shown again.

See /docs/queues for the full publish/pull/ack worked example.

Develop

git clone https://github.com/arvaer/gopigeon-mcp.git
cd gopigeon-mcp
npm install
npm run build     # compiles src/ → dist/
npm test          # vitest suite
npm run dev       # tsx src/index.ts — runs against live server

This repository is also a Claude Code plugin marketplace — the plugin lives in plugins/gopigeon/ and the catalog is .claude-plugin/marketplace.json. Pull requests welcome.

License

MIT

Related plugins

Browse all →