# Debriefing developer docs

Read one Debriefing workspace from your own tools: competitors, signals with their evidence, digests, and battlecards. The read API takes an API key. The MCP server takes the same key, or an OAuth sign-in from Claude, ChatGPT, and other OAuth clients. Both only read. A paid plan is required.

- OpenAPI description (YAML): https://debriefing.io/developers/openapi.yaml
- OpenAPI description (JSON): https://debriefing.io/openapi.json
- MCP endpoint: https://debriefing.io/mcp
- MCP server card: https://debriefing.io/.well-known/mcp/server-card.json
- OAuth protected resource metadata: https://debriefing.io/.well-known/oauth-protected-resource
- OAuth authorization server metadata: https://debriefing.io/.well-known/oauth-authorization-server

## Get an API key

1. Sign in to your workspace.
2. Open Organization settings, then Integrations.
3. Under API keys and MCP, name a key and click Create key.
4. Copy the token. It starts with `dbk_` and Debriefing shows it one time only.
5. Send it as `Authorization: Bearer dbk_…` or as `X-API-Key`.

A missing or revoked key returns 401. A workspace with no paid plan returns 402. Blank fields are left out of every response.

## Read API

Base URL: https://debriefing.io

### GET /api/v1/competitors

List tracked competitors. Every competitor this workspace actively monitors. Paused, removed, and pending links are left out. Not paginated.

Request:

```http
GET /api/v1/competitors
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": [
    {
      "id": 42,
      "name": "Acme Analytics",
      "website_url": "https://acme.example",
      "category": "Analytics",
      "watch": "core",
      "tracked_since": "2026-01-12T09:00:00Z",
      "url": "https://debriefing.io/competitors/42"
    },
    {
      "id": 57,
      "name": "Northwind AI",
      "website_url": "https://northwind.example",
      "category": "AI",
      "watch": "horizon",
      "tracked_since": "2026-03-02T14:30:00Z",
      "url": "https://debriefing.io/competitors/57"
    }
  ]
}
```

### GET /api/v1/competitors/:id

Get a competitor dossier. Company record and current reads for one tracked competitor. Signals and the battlecard stay on their own routes.

Parameters:

- `id` (path, required): Competitor id from the watchlist.

Request:

```http
GET /api/v1/competitors/42
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": {
    "id": 42,
    "name": "Acme Analytics",
    "description": "Product analytics for B2B SaaS teams.",
    "website_url": "https://acme.example",
    "category": "Analytics",
    "industry": "Software",
    "company_type": "private",
    "business_model": "subscription",
    "company_size": 120,
    "founding_year": 2018,
    "headquarters": {
      "city": "San Francisco",
      "country": "US"
    },
    "target_customer": "B2B SaaS product teams",
    "ownership": {
      "type": "private",
      "public": false
    },
    "urls": {
      "pricing": "https://acme.example/pricing",
      "docs": "https://docs.acme.example",
      "linkedin": "https://www.linkedin.com/company/acme"
    },
    "watch": "core",
    "priority": 1,
    "tracked_since": "2026-01-12T09:00:00Z",
    "workspace": {
      "relative_risk": "medium",
      "relative_opportunity": "high",
      "icp_overlap": {
        "score": "high",
        "notes": "Same ICP in mid-market SaaS."
      }
    },
    "reads": {
      "positioning": "Product analytics for growth and product teams.",
      "pricing": {
        "plans": [
          {
            "name": "Pro",
            "price": "$99/mo"
          }
        ],
        "recent_changes": []
      },
      "funding": {
        "total_raised_text": "$45M",
        "last_round": "Series B",
        "estimated_revenue_text": "$8M–$12M ARR"
      },
      "traffic": {
        "monthly_visits": 180000,
        "trend": "up"
      },
      "fortnight": {
        "written_at": "2026-09-20T08:00:00Z",
        "sentences": [
          {
            "text": "Acme raised pricing on the Pro plan.",
            "kind": "pricing"
          }
        ]
      }
    },
    "freshness": {
      "state_updated_at": "2026-09-22T11:00:00Z",
      "last_signal_at": "2026-09-21T16:40:00Z",
      "last_snapshot_at": "2026-09-22T10:55:00Z"
    },
    "links": {
      "signals": "/api/v1/signals?competitor_id=42",
      "battlecard_id": 9,
      "url": "https://debriefing.io/competitors/42"
    }
  }
}
```

### GET /api/v1/signals

List open signals. Open signals for tracked competitors, newest first. Each signal includes its evidence. Default page size is 50. Maximum is 50.

Parameters:

- `competitor_id` (query): Limit to one tracked competitor.
- `severity` (query): low, medium, or high.
- `since` (query): ISO 8601 time. First seen on or after this time.
- `q` (query): Case-insensitive match on title or summary.
- `page` (query): Page number. Default 1.
- `per_page` (query): Page size. Default 50. Maximum 50.

Request:

```http
GET /api/v1/signals?severity=high&per_page=2
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": [
    {
      "id": 881,
      "competitor_id": 42,
      "competitor_name": "Acme Analytics",
      "title": "Acme raised Pro plan pricing",
      "summary": "The Pro plan moved from $79 to $99 per month on the public pricing page.",
      "category": "pricing",
      "type": "price_change",
      "severity": "high",
      "status": "open",
      "first_seen_at": "2026-09-21T16:40:00Z",
      "last_seen_at": "2026-09-21T16:40:00Z",
      "confidence": 0.92,
      "topics": [
        "pricing",
        "packaging"
      ],
      "evidence": [
        {
          "text": "Pro · $99 / month",
          "source_title": "Acme Pricing",
          "source_url": "https://acme.example/pricing",
          "observed_at": "2026-09-21T16:40:00Z"
        }
      ],
      "url": "https://debriefing.io/dashboard/signals/881"
    }
  ],
  "page": 1,
  "per_page": 2
}
```

### GET /api/v1/signals/:id

Get one signal. One signal for a tracked competitor. Unlike the list, this route can return a closed signal when you know the id.

Parameters:

- `id` (path, required): Signal id.

Request:

```http
GET /api/v1/signals/881
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": {
    "id": 881,
    "competitor_id": 42,
    "competitor_name": "Acme Analytics",
    "title": "Acme raised Pro plan pricing",
    "summary": "The Pro plan moved from $79 to $99 per month on the public pricing page.",
    "category": "pricing",
    "type": "price_change",
    "severity": "high",
    "status": "open",
    "first_seen_at": "2026-09-21T16:40:00Z",
    "last_seen_at": "2026-09-21T16:40:00Z",
    "confidence": 0.92,
    "topics": [
      "pricing",
      "packaging"
    ],
    "evidence": [
      {
        "text": "Pro · $99 / month",
        "source_title": "Acme Pricing",
        "source_url": "https://acme.example/pricing",
        "observed_at": "2026-09-21T16:40:00Z"
      }
    ],
    "url": "https://debriefing.io/dashboard/signals/881"
  }
}
```

### GET /api/v1/digests

List generated digests. Digests with status generated, newest coverage period first. Default page size is 50. Maximum is 50.

Parameters:

- `type` (query): Debrief type, for example daily_digest or weekly_tldr.
- `page` (query): Page number. Default 1.
- `per_page` (query): Page size. Default 50. Maximum 50.

Request:

```http
GET /api/v1/digests?type=daily_digest
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": [
    {
      "id": 310,
      "slug": "daily-2026-09-22",
      "type": "daily_digest",
      "status": "generated",
      "title": "Daily digest · 22 Sep 2026",
      "headline": "Acme raised Pro pricing. Northwind opened a EU careers page.",
      "tldr": "Two moves matter today: Acme pricing and Northwind hiring in Europe.",
      "what_to_watch": "Watch whether Acme changes packaging next.",
      "coverage_period_start": "2026-09-21T00:00:00Z",
      "coverage_period_end": "2026-09-22T00:00:00Z",
      "generated_at": "2026-09-22T07:15:00Z",
      "signal_ids": [
        881,
        902
      ],
      "url": "https://debriefing.io/dashboard/digests/daily-2026-09-22"
    }
  ],
  "page": 1,
  "per_page": 50
}
```

### GET /api/v1/digests/:id

Get one digest. Looks up a generated digest by slug first, then by id.

Parameters:

- `id` (path, required): Digest slug or numeric id.

Request:

```http
GET /api/v1/digests/daily-2026-09-22
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": {
    "id": 310,
    "slug": "daily-2026-09-22",
    "type": "daily_digest",
    "status": "generated",
    "title": "Daily digest · 22 Sep 2026",
    "headline": "Acme raised Pro pricing. Northwind opened a EU careers page.",
    "tldr": "Two moves matter today: Acme pricing and Northwind hiring in Europe.",
    "what_to_watch": "Watch whether Acme changes packaging next.",
    "coverage_period_start": "2026-09-21T00:00:00Z",
    "coverage_period_end": "2026-09-22T00:00:00Z",
    "generated_at": "2026-09-22T07:15:00Z",
    "signal_ids": [
      881,
      902
    ],
    "url": "https://debriefing.io/dashboard/digests/daily-2026-09-22"
  }
}
```

### GET /api/v1/battlecards

List generated battlecards. Generated battlecards for this workspace, ordered by competitor id. Not paginated.

Request:

```http
GET /api/v1/battlecards
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": [
    {
      "id": 9,
      "competitor_id": 42,
      "competitor_name": "Acme Analytics",
      "status": "generated",
      "generated_at": "2026-09-20T12:00:00Z",
      "sections": {
        "overview": "Acme sells product analytics to mid-market SaaS.",
        "strengths": [
          "Strong product analytics brand",
          "Clear Pro packaging"
        ],
        "weaknesses": [
          "Price rose without a feature add"
        ],
        "talk_tracks": [
          "Ask what they get for the new Pro price."
        ]
      },
      "url": "https://debriefing.io/dashboard/battlecards/9"
    }
  ]
}
```

### GET /api/v1/battlecards/:id

Get one battlecard. Looks up a generated battlecard by battlecard id first, then by competitor id.

Parameters:

- `id` (path, required): Battlecard id or competitor id.

Request:

```http
GET /api/v1/battlecards/9
Authorization: Bearer dbk_…
```

Response:

```json
{
  "data": {
    "id": 9,
    "competitor_id": 42,
    "competitor_name": "Acme Analytics",
    "status": "generated",
    "generated_at": "2026-09-20T12:00:00Z",
    "sections": {
      "overview": "Acme sells product analytics to mid-market SaaS.",
      "strengths": [
        "Strong product analytics brand",
        "Clear Pro packaging"
      ],
      "weaknesses": [
        "Price rose without a feature add"
      ],
      "talk_tracks": [
        "Ask what they get for the new Pro price."
      ]
    },
    "url": "https://debriefing.io/dashboard/battlecards/9"
  }
}
```

## Errors

Every error is RFC 9457 problem details, sent as `application/problem+json`. Branch on `code`. The `hint` tells you what to do next. The `error` field holds the same text as `detail`, for older clients. The `type` URL points at the code on https://debriefing.io/developers#errors.

A JSON request for a missing page anywhere on the site gets the same shape, with the code `not_found`. The OAuth endpoints send RFC 6749 errors. The MCP endpoint sends JSON-RPC errors.

Codes:

- `invalid_request` (400, Invalid request): Correct the parameter that the detail names. Then send the request again.
- `invalid_api_key` (401, API key missing or not valid): Send a valid key as Authorization: Bearer dbk_… or as X-API-Key. A workspace admin creates keys in Organization settings, under Integrations.
- `paid_plan_required` (402, Paid plan required): Choose a paid plan for this workspace on /pricing. The free week does not include the API.
- `forbidden` (403, Forbidden): Use a key from the workspace that owns this record. The read API does not send this code now.
- `not_found` (404, Not found): Check the path and the id. The list routes, such as /api/v1/competitors, give the ids that this key can read.
- `unprocessable_content` (422, Unprocessable content): Correct the value that the detail names. Then send the request again. The read API does not send this code now.
- `rate_limited` (429, Too many requests): Wait for the number of seconds in the Retry-After header. Then send the request again.
- `internal_error` (500, Internal error): Send the request again later. If the error continues, email team@debriefing.io with the request_id.

Example:

```json
{
  "type": "https://debriefing.io/developers#errors-not_found",
  "title": "Not found",
  "status": 404,
  "detail": "No such competitor.",
  "code": "not_found",
  "hint": "Check the path and the id. The list routes, such as /api/v1/competitors, give the ids that this key can read.",
  "instance": "/api/v1/competitors/999",
  "request_id": "5f1c2b7e-9a41-4c1e-8d0e-2b1f3a6c7d80",
  "error": "No such competitor."
}
```

## MCP server

Endpoint: https://debriefing.io/mcp. Streamable HTTP: JSON-RPC 2.0 in a POST, one JSON answer back. The server does not push over SSE.

Authentication, one of two:

- OAuth 2.1: authorization code with PKCE (S256), dynamic client registration at https://debriefing.io/oauth/register, refresh tokens, and revocation at https://debriefing.io/oauth/revoke. A request with no credential gets 401 and a `WWW-Authenticate` header that points at the protected resource metadata. A signed-in member of a paid workspace approves the app. The token reads that workspace only.
- API key: the same key in the same headers as the read API.

Public tools: `search_public_briefs`, `get_public_brief`, `search_guides`, and `get_free_brief_link` need no credential. They read only the briefs and guides Debriefing publishes on debriefing.io, never a workspace. Every other `tools/call` without a credential gets the 401.

## MCP tools

- `get_workspace`: Gets the Debriefing workspace this connection works on: its name and website, who you are in it and your role, the scopes this connection holds, and the plan. Call it first when you are not sure what you may do. Example arguments: `{}`
- `get_plan_and_limits`: Gets the workspace plan and every limit an agent runs into: competitor slots, the weekly research allowance, the daily caps on battlecards, ICP refreshes and positioning drafts, share link lifetimes, monitoring cadences, and which features need a paid plan. Includes the pricing link. Example arguments: `{}`
- `list_competitors`: Lists the competitors this Debriefing workspace tracks, with the id, name, website, and category of each. Call it first to get the competitor_id that other tools take. Example arguments: `{}`
- `get_competitor`: Gets the dossier for one tracked competitor: company facts, the risk and opportunity it poses to this workspace, and the stored reads on positioning, product, pricing, funding, traffic, and more. Use it when the user asks about one competitor in depth. Example arguments: `{"competitor_id":42}`
- `search_signals`: Searches open signals, newest first. A signal is a competitor move that Debriefing found, such as a price change or a launch, with the source evidence. Filter by competitor_id, severity (low, medium, high), a text query, or a since time. Use it when the user asks what a competitor changed. Example arguments: `{"competitor_id":42,"severity":"high","limit":5}`
- `list_digests`: Lists the digests Debriefing wrote for this workspace, newest first. A digest is a brief that sums up competitor moves over a period. Filter by type, such as daily_digest. Example arguments: `{"type":"daily_digest","limit":5}`
- `get_digest`: Gets one digest by id or slug, or the newest digest when no id is given. Pass type daily_digest for the newest daily digest. Use it when the user asks for the latest brief. Example arguments: `{"id":"daily-2026-09-22"}`
- `list_battlecards`: Lists the battlecards Debriefing wrote for this workspace, one for each competitor that has one. A battlecard holds talk tracks for sales calls against that competitor. Example arguments: `{}`
- `get_battlecard`: Gets one battlecard by competitor_id or battlecard_id. Use it when the user prepares a sales call against a competitor. Example arguments: `{"competitor_id":42}`
- `get_evidence`: Gets the evidence behind one signal: each source excerpt with its URL and date. Use it when the user asks where a claim comes from. Example arguments: `{"signal_id":881}`
- `add_competitor`: Adds a competitor to the workspace's core watchlist from its website. Debriefing then monitors it. Admin only. The plan sets how many core competitors fit; get_plan_and_limits shows the free slots. Example arguments: `{"website_url":"https://northwind.example"}`
- `rename_competitor`: Changes the display name of one tracked competitor. Admin only. Example arguments: `{"competitor_id":42,"name":"Acme"}`
- `remove_competitor`: Takes one core competitor off the watchlist. Debriefing stops monitoring it and keeps its history. Admin only, on a paid plan. Example arguments: `{"competitor_id":42}`
- `add_monitored_page`: Asks Debriefing to watch one more page of a core competitor, such as its pricing page. Changes on it then show up as signals. Up to 10 pages per competitor. Admin only, on a paid plan. Example arguments: `{"competitor_id":42,"url":"https://acme.example/pricing"}`
- `remove_monitored_page`: Stops watching a page that someone added on a core competitor. Name it by page_id or url. Admin only, on a paid plan. Example arguments: `{"competitor_id":42,"page_id":77}`
- `research_competitor`: Starts the first research on one core competitor that has none yet: Debriefing reads its site and outside sources. It uses one update from the weekly research allowance. Admin only. Example arguments: `{"competitor_id":43,"idempotency_key":"7f3c2a9e-research-43"}`
- `refresh_watchlist`: Refreshes the research on the core watchlist now, instead of at the next cycle. It uses one update from the weekly research allowance. Admin only. Example arguments: `{"idempotency_key":"b81d40c2-refresh"}`
- `pin_signal`: Pins a signal for the whole team, or removes the pin with pinned false. Example arguments: `{"signal_id":881,"pinned":true}`
- `save_signal`: Saves a signal to your own saved list, or removes it with saved false. Only you see your saved signals. Example arguments: `{"signal_id":881,"saved":true}`
- `add_signal_note`: Adds a talking point to a signal. The team sees it in the workspace. It never appears on a public link unless the link includes notes. Example arguments: `{"signal_id":881,"body":"Lead with our flat price when Acme comes up."}`
- `rate_signal`: Tells Debriefing whether a signal was useful to you. For not useful, add reasons and a comment. A new rating replaces your old one. Example arguments: `{"signal_id":881,"useful":true}`
- `pin_digest`: Pins a digest for the whole team, or removes the pin with pinned false. Example arguments: `{"digest_id":"daily-2026-09-22","pinned":true}`
- `add_digest_note`: Adds a talking point to a digest. The team sees it in the workspace. Example arguments: `{"digest_id":"daily-2026-09-22","body":"Share the pricing move with sales."}`
- `rate_digest`: Scores a digest from 1 to 5, says what is missing from it, or both. A new rating replaces your old one. Example arguments: `{"digest_id":"daily-2026-09-22","score":5}`
- `generate_battlecard`: Writes or rewrites the battlecard for one core competitor now, instead of at the next cycle. It takes about a minute; read it afterwards with get_battlecard. The competitor needs finished research. Needs a paid plan or the free first week, and counts toward a daily cap per workspace. Example arguments: `{"competitor_id":42,"idempotency_key":"c19a2f7e-card-42"}`
- `add_battlecard_note`: Adds what the team knows about a core competitor that no page says. The next rewrite of its battlecard reads the note as framing, never as a verified fact. Example arguments: `{"competitor_id":42,"body":"Their onboarding takes two weeks; ours takes a day."}`
- `get_company_profile`: Gets the workspace's own company profile: description, category, target customer, positioning lists, and the ideal customer profile. Debriefing reads every competitor move against it. Example arguments: `{}`
- `update_company_profile`: Changes fields of the workspace's company profile. Only the fields you send change. The lists replace the old lists. Admin only. Locked while the first brief runs. Example arguments: `{"target_customer":"Product teams at B2B SaaS companies","differentiators":["Evidence on every signal"]}`
- `update_icp`: Sets the ideal customer profile, then re-reads how much each tracked competitor overlaps it. Only the dimensions you send change; an empty list clears one. Admin only. Counts toward a daily cap per workspace. Locked while the first brief runs. Example arguments: `{"industries":["B2B SaaS"],"buyer_roles":["Head of Product"],"idempotency_key":"4d2e8b10-icp"}`
- `draft_positioning`: Reads the company's own website and drafts the empty positioning fields: value propositions, differentiators, and exclusions. Filled fields stay as they are. Read the result later with get_company_profile. Admin only. Counts toward a daily cap per workspace. Example arguments: `{"idempotency_key":"9a7c5e33-positioning"}`
- `get_delivery_settings`: Gets how often Debriefing runs a monitoring cycle for the workspace, the cadences the plan allows, and whether a finished cycle goes out by email and to Slack. Admin only. Example arguments: `{}`
- `set_monitoring_cadence`: Sets how often Debriefing runs a monitoring cycle. The plan decides which cadences are allowed; get_delivery_settings lists them. Admin only, on a paid plan. Example arguments: `{"cadence":"weekly"}`
- `set_delivery_channels`: Turns delivery of a finished cycle by email and to Slack on or off. Only the channels you send change. Slack needs a paid plan and a Slack connection made in the app. Admin only. Example arguments: `{"email":true,"slack":false}`
- `create_share_link`: Makes a public link to one signal that anyone with the address can open. A new link replaces the old one, which stops working. The plan sets how long a link can live; the free plan and Starter allow 24 hours. Example arguments: `{"signal_id":881,"expiry":"7d","idempotency_key":"e2b6c8d4-share-881"}`
- `list_members`: Lists the people in the workspace with their roles. An admin also sees pending invitations. Example arguments: `{}`
- `invite_member`: Sends an email invitation to join the workspace as a member. The invitation lasts 7 days. Inviting the same address again sends a fresh email. Admin only, on a paid plan. Example arguments: `{"email":"sam@yourco.example","idempotency_key":"0c4f1a9b-invite-sam"}`
- `what_changed`: Lists everything new in the workspace since a time: signals Debriefing found, digests it wrote, and battlecards it wrote or rewrote. Use it to catch up, such as since the user's last visit. Example arguments: `{"since":"2026-09-28T00:00:00Z","limit":10}`
- `search_public_briefs`: Searches the competitive briefs Debriefing publishes on debriefing.io about named companies, newest first. Each brief is dated and every finding cites a public source. Filter by words in the brief and by company name, slug, or domain. With no arguments, lists the newest briefs. Needs no Debriefing account. Returns the page URL of each brief. Example arguments: `{"query":"pricing","company":"Crayon","limit":5}`
- `get_public_brief`: Gets one competitive brief that Debriefing published on debriefing.io: the summary, each finding with its category and date, and the numbered public sources with their URLs. Name the brief by its URL, or by company_slug and slug from search_public_briefs. With company_slug only, gets the newest brief about that company. Needs no Debriefing account. Example arguments: `{"company_slug":"crayon","slug":"2026-09-28"}`
- `search_guides`: Searches the public competitive intelligence library on debriefing.io: how-to guides, glossary terms, tool comparisons, alternatives pages, company profiles, and market intel posts. Returns the title, a short excerpt, and the page URL of each match, best match first. Needs no Debriefing account. Example arguments: `{"query":"battlecard","limit":3}`
- `get_free_brief_link`: Gets the debriefing.io links where a person requests a free competitive brief about their own company and competitors, signs up for a workspace, or compares plans. It only returns links. It sends nothing and creates nothing. Example arguments: `{}`

## Connect a client

### Add to Claude

Claude on the web, on the desktop, and on mobile connects with OAuth. You sign in to Debriefing and approve the connection. You do not need an API key.

1. In Claude, open Customize, then Connectors. Select Add custom connector.
2. Enter the name Debriefing and the URL https://debriefing.io/mcp. Select Add.
3. Select Connect. Sign in to Debriefing and select Approve.
4. In a chat, open the + menu, then Connectors, and turn on Debriefing. Ask: Which competitors do we track?
5. On a Team or Enterprise plan, an owner adds the connector in Organization settings, then Connectors. Each member then selects Connect.

### Add to ChatGPT

ChatGPT connects with OAuth. You sign in to Debriefing and approve the connection. To add an app by URL, ChatGPT needs developer mode. Plus, Pro, Business, Enterprise, and Edu plans have it on the web.

1. In ChatGPT on the web, open Settings and turn on Developer mode.
2. Create an app. Name: Debriefing. MCP server URL: https://debriefing.io/mcp. Authentication: OAuth.
3. Select Create. Sign in to Debriefing and select Approve.
4. In a chat, open the + menu and choose Debriefing. Ask: What did our competitors change this week?

### Claude Code

Claude Code connects with OAuth, like Claude. It can also send an API key as a header.

1. Run: claude mcp add --transport http debriefing https://debriefing.io/mcp
2. Inside Claude Code, run /mcp, select debriefing, and select Authenticate. Sign in to Debriefing in the browser and select Approve.
3. To use an API key instead, add --header "Authorization: Bearer dbk_…" to the first command.

### Cursor

Add a remote server in ~/.cursor/mcp.json or in the project .cursor/mcp.json. Put the key in an environment variable so it stays out of the file. To sign in with OAuth instead, leave out headers.

1. Create an API key in Settings, then Integrations. Copy it once.
2. Export DEBRIEFING_API_KEY=dbk_… in your shell profile.
3. Paste the config below. Restart Cursor.
4. Open Customize, confirm the debriefing server is on, then ask for your tracked competitors.

~/.cursor/mcp.json:

```json
{
  "mcpServers": {
    "debriefing": {
      "url": "https://debriefing.io/mcp",
      "headers": {
        "Authorization": "Bearer ${env:DEBRIEFING_API_KEY}"
      }
    }
  }
}
```

### Other MCP clients

Any client that can reach a Streamable HTTP MCP server can use the same endpoint. Clients that only speak stdio should use mcp-remote.

1. Endpoint: https://debriefing.io/mcp
2. Auth: OAuth 2.1 with PKCE, dynamic client registration, and client ID metadata documents. Scopes: read, write, and spend. Discovery starts at the 401 from a tools/call. Or send Authorization: Bearer dbk_… or X-API-Key: dbk_…
3. Transport: Streamable HTTP. Each POST gets one JSON answer. This server does not push over SSE.

stdio via mcp-remote:

```json
{
  "mcpServers": {
    "debriefing": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://debriefing.io/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer dbk_…"
      }
    }
  }
}
```

## Example prompts

- Brief me on one competitor: "Use get_competitor for Acme, then search_signals for that competitor from the last 14 days. Cite the evidence URLs."
- What moved this week?: "List digests of type daily_digest, open the newest one, and summarize what matters for our sales team."
- Prep a call: "Get the battlecard for competitor_id 42. Pull the three highest-severity open signals. Give me talk tracks grounded in the evidence."
- Trace a claim: "Search signals for pricing changes. For the top result, call get_evidence and show me each source excerpt with its URL."
- Catch up and act: "Call what_changed since Monday. Pin the most important signal for the team and add a talking point on what sales should say about it."
- No account yet: "Search Debriefing's public briefs for Crayon and summarize the newest one with its sources. Then find the Debriefing guide on battlecards."
- Add a competitor: "Check get_plan_and_limits for a free competitor slot. If there is one, add northwind.example to the watchlist and start its research."
