MCP quickstart
PMM Tools tracks a set of competitor URLs, keeps a snapshot of each one fresh, and serves the source files — clean markdown plus a screenshot per URL — to an AI client over the Model Context Protocol (MCP). This page documents the actual server: the endpoint, how authentication works, every tool an agent can call, and what each plan is allowed to do with it. Pick your client below for the exact connection steps.
Connect your client
Server
Endpoint: https://www.pmmtools.com/api/mcp
Transport: Streamable HTTP JSON-RPC (MCP's standard HTTP transport). Each request is self-contained — there is no session state and no server-sent-events stream to keep open.
Method: POST only. GET and DELETE return 405.
Authentication
Sign in to PMM Tools and generate a key at /private/mcp. Keys look like pmm_live_YOUR_KEY and are sent as a bearer token:
Authorization: Bearer pmm_live_YOUR_KEYThe key authenticates as your account with a service-role database client on the server side — every query is scoped to your own data, but the key itself is as sensitive as a password. Treat it like one, and revoke it from /private/mcp if it leaks. You can hold multiple active keys (one per client is a reasonable default) and revoke them independently.
The server also advertises OAuth 2.1 discovery metadata (RFC 9728) at /.well-known/oauth-protected-resource/api/mcp, and every 401 carries a matching WWW-Authenticate challenge. That part of the protocol is live. Token verification is not: this project still signs its session tokens with a legacy symmetric secret, so the JSON Web Key Set an OAuth client needs to verify a token is currently empty, and every OAuth token fails closed. This is why the ChatGPT connector — the one client here that requires OAuth — is not connectable yet. See the ChatGPT page for what that means in practice.
Plan limits
MCP is available on every plan, including free — there is no paid gate on the connection itself. What differs by plan is the request budget and how much the account can track and run.
| Plan | MCP requests / hour | Competitors tracked | URLs / competitor | Monthly snapshot credits | Runs / day | Scheduled runs |
|---|---|---|---|---|---|---|
| Free | 15 | 1 | 25 | 100 | 2 | No |
| Pro | 60 | 10 | 50 | 3,000 | 50 | Yes |
| Max | 120 | 25 | 60 | 12,000 | 200 | Yes |
Going over the hourly MCP request budget returns HTTP 429 with a Retry-After header. Snapshot credits and per-day run caps are separate budgets spent by tools that start a capture (pmm_competitor_run_now, pmm_submit_batch) — reading existing data does not draw them down.
Tools (25)
Every tool the server registers, grouped the way the product groups them. An agent can also call pmm_list_skills at any time to fetch this same catalog live, in case this page is ever behind the running server.
Competitors
| Tool | What it returns |
|---|---|
| pmm_competitor_list | List the competitors in your Library with discovered/captured/excluded URL counts, how many URLs are eligible by curation status (an upper bound on a run, not a prediction), and the newest capture time. Start here when you don't have a competitor id — every other pmm_competitor_* tool needs one. |
| pmm_competitor_create | Create (or get-or-create) a Competitor for a primary domain. Idempotent: same primary_domain twice returns the same id. |
| pmm_competitor_update | Update a Competitor's scope context: tracked_for, feature_scope, size_class. Every field is optional and independently omit-to-leave-unchanged / null-to-clear. Feeds the pre-capture judge's in_scope decision. |
| pmm_competitor_add_urls | Add URLs to a Competitor (single domain). Idempotent — existing URLs report as outcome=existed. Default status=included (sticky), source=mcp. |
| pmm_competitor_get_urls | List URLs in a Competitor. Filter by status. Paginated. |
| pmm_competitor_remove_urls | Soft-remove URLs from a Competitor by setting status='excluded'. Sticky: future automation will not re-add them. |
| pmm_competitor_capture | Persist Chrome-MCP capture artifacts on a competitor URL. Inserts a snapshots row on outcome='captured' and rotates latest_good_snapshot_id; on failure outcomes records only attempt telemetry. |
| pmm_competitor_validate | Record the orchestrator's L2 validation verdict on a captured competitor URL. is_useful=false → status='excluded' with reason; is_useful=true → status='included' and reason cleared. |
| pmm_competitor_discovery_run | Record a Chrome-MCP discovery run with Step 0 scope (feature_scope, competitor_size_class) and the nav/footer screenshots + link sets. Drift detection compares runs over time. Requires an active paid subscription. |
| pmm_competitor_discovery_runs_list | List Chrome-MCP discovery runs for a competitor in DESC order. Drift-detection consumer reads here. |
| pmm_competitor_canonical_snapshots | Return the canonical (latest good) snapshot per URL for a competitor, with signed screenshot URLs and authenticity metadata for agent citations. Tenant-scoped via the api-key auth. HTTP MCP transport only (signed URLs need service-role). By default only returns capture-worthy buckets (pricing, features, homepage, and similar product-surface pages — derived from the #788 taxonomy, LEGACY_SLUG_TO_BUCKET + captureWorthyByDefault) with status included/auto, excluding human-excluded URLs. Pass buckets:["slug",...] to override the bucket set, all_buckets:true for every bucket (no filter), or include_excluded:true to also include status=excluded URLs. |
| pmm_competitor_canonical_bundle | Build (or reuse a cached) per-competitor canonical-snapshot bundle and return a signed URL to a zip whose layout is manifest.json + urls/<id>/{screenshot.<jpg|png>,markdown.md,meta.json} — the screenshot extension and content_type in manifest.json/meta.json follow the stored artifact. Tenant-scoped via api-key auth. HTTP MCP transport only. By default only includes capture-worthy buckets (pricing, features, homepage, and similar product-surface pages — derived from the #788 taxonomy, LEGACY_SLUG_TO_BUCKET + captureWorthyByDefault) with status included/auto, excluding human-excluded URLs. Pass buckets:["slug",...] to override the bucket set, all_buckets:true for every bucket (no filter), or include_excluded:true to also include status=excluded URLs. |
| pmm_competitor_schedule_get | Get a Competitor's recurring-run schedule: cadence, enabled/paused state (with reason), next_run_at, failure count, and last run status. |
| pmm_competitor_schedule_set | Create, update, or turn off ('off') a Competitor's recurring-run schedule. daily|weekly need anchor {hour_local, timezone (IANA), weekday for weekly}. Enabling requires an active paid subscription. |
| pmm_competitor_schedule_list | List all recurring-run schedules for the caller, soonest next_run_at first — what am I tracking and when does each refresh? |
| pmm_competitor_run_now | Start a run for a Competitor immediately — by default a snapshot refresh of the tracked URL set (preset 'snapshots_only'); 'full_rerun' or per-phase selections re-run the analysis pipeline. Same plan/quota gates as the web Run button. HTTP MCP transport only. |
| pmm_run_cancel | Cancel a competitor run by batch id. Idempotent — an already-finished run returns already_terminal=true. The batch flips to 'cancelled' and queued snapshot work is dropped. |
| pmm_run_status | Per-run progress for watching a run to completion: batch status + audit workflow/phase statuses, per-status and per-provider snapshot counts, and the block/escalation rollup. HTTP MCP transport only. |
Content audits
| Tool | What it returns |
|---|---|
| pmm_list_audits | List available content audits. Optionally filter by domain. |
| pmm_sync | Sync competitive analysis and snapshots from a content audit. In stdio mode, writes files locally. In HTTP mode, returns a JSON manifest with signed URLs. |
Browser capture
| Tool | What it returns |
|---|---|
| pmm_list_collected_urls | List URLs collected via the Chrome extension. Filter by status, domain, or collection. |
| pmm_list_recent_captures | List recent page captures (snapshots) with their status and metadata. |
| pmm_submit_batch | Submit a list of URLs (max 50) for batch snapshot processing. Creates a batch job that queues each URL for crawling and content extraction. |
System
| Tool | What it returns |
|---|---|
| pmm_auth_status | Check if authenticated and show current auth state. |
| pmm_list_skills | List all available PMM tools with their descriptions and categories. |
Resources
Alongside the tools, the server exposes three MCP resource templates an agent can read directly by URI instead of calling a tool:
| URI template | Content |
|---|---|
| pmm://competitor/{competitorId}/canonical-snapshots | Canonical-snapshots manifest (mirrors the pmm_competitor_canonical_snapshots tool output). (application/json) |
| pmm://competitor/{competitorId}/url/{competitorUrlId}/markdown | The URL's canonical markdown. (text/markdown) |
| pmm://competitor/{competitorId}/url/{competitorUrlId}/screenshot | The URL's canonical screenshot (content type follows the stored artifact). (image/*) |