Skip to content
RECAP RAVEN
The Recap Raven MCP server is available now on paid plans.

For power users & automators

Bring your own AI to your campaign.

Want to ask questions of your campaign from ChatGPT, Claude, Gemini or your own agent? Recap Raven’s MCP server exposes your campaign memory and AI answers as tools any MCP client can call — so the recap engine is reachable from wherever your agent lives.

Get started

Connect your MCP client to mcp.recapraven.com/mcp using a personal API key from your Recap Raven account area. Choose your client to see the setup steps:

ChatGPT Desktop setup

  1. In your Recap Raven account area, open API Keys → Create key. You need a paid plan, and the key is shown once.
  2. Open ChatGPT Desktop → Settings → Connectors → Add a new connector.
  3. Set the URL to https://mcp.recapraven.com/mcp
  4. Set the Authorization header to: Bearer raven_sk_… (the key from step 1).
  5. Save, then start a chat — Recap Raven’s tools become available to ChatGPT.

Available on all paid plans

MCP is unavailable on the Free tier. The included tool calls below run on every paid plan (Premium, Studio, Pro) at no extra cost; credit-charged tools spend your existing Ask credits.

MCP availability by plan
Free tierUnavailable
Paid plansAll included tools at no extra cost; credit-charged tools spend your existing Ask credits.
API keyCreate one personal API key in your account area. Revoke any time; keys are disabled if the account returns to the Free tier.

Fair use & rate limits

The MCP server is a shared, metered surface. To keep it sustainable (and stop a runaway agent loop from burning a whole licence in minutes), every API key is rate-limited in addition to your credit balance.

MCP rate limits
Server fair-usePer-API-key request ceiling on the MCP server itself (all tool calls combined) — prevents a single key from flooding the endpoint. Responses over the limit return 429 with Retry-After.
Premium30 requests/minute and 300 requests/hour.
Studio60 requests/minute and 900 requests/hour.
Pro120 requests/minute and 2400 requests/hour.
Included toolsRate-limited per API key. Keyword search (search_transcript) and read endpoints cost you no credits.
Credit-charged toolsBounded by both your Ask credit balance and a per-key rate limit. The credit gate stops spend when the balance is empty; the rate limit stops a burst from draining it instantly. No separate MCP quota — your agent spends the same per-licence Ask credits it uses in the app.

Included tool calls

Read-only data tools, included on every paid plan at no extra cost. They return stored campaign data and keyword-search transcript matches — no AI answer, no credit charged. Expand any tool for example input, example output and field reference.

list_campaignsIncluded

Discovery tool: list the campaigns available to your MCP key so other tools can use the right campaign_id.

Example input

{}

Example output

{
  "campaigns": [
    {
      "campaign_id": "a1b2c3d4-…",
      "name": "The White Moose",
      "module": "Dolmenwood"
    }
  ]
}
Field descriptions
FieldTypeDescription
campaignsarrayCampaigns owned by your account.
campaigns[].campaign_idstring (uuid)Use this id with campaign-scoped MCP tools.
campaigns[].namestringCampaign name.
campaigns[].modulestring | nullOptional module/system label.
list_recapsIncluded

Discovery tool: list ready recaps/sessions so get_recap and transcript windows can use the right recap_id.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid) | omittedOptional campaign filter.

Example output

{
  "recaps": [
    {
      "recap_id": "r1e2c3a4-…",
      "campaign_id": "a1b2c3d4-…",
      "title": "Session 12: The Choosing",
      "status": "ready"
    }
  ]
}
Field descriptions
FieldTypeDescription
recapsarrayReady recaps visible to your account.
recaps[].recap_idstring (uuid)Use this id with get_recap and get_transcript_window.
recaps[].campaign_idstring (uuid) | nullCampaign that owns the recap.
recaps[].titlestring | nullSession/recap title.
recaps[].statusstringOnly ready recaps are listed.
get_engagement_trendIncluded

Per-speaker participation %, turn count, talk time and word count across every ready session.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read. Must be owned by your account.

Example output

{
  "sessions": [
    {
      "recap_id": "…",
      "session_ref": "S01AB",
      "session_at": "2026-06-20T19:00:00Z"
    }
  ],
  "players": [
    {
      "speaker": "Mira",
      "points": [
        {
          "session_ref": "S01AB",
          "participation_pct": 28.4,
          "turn_count": 42,
          "talk_time_seconds": 612,
          "word_count": 1840
        }
      ]
    }
  ]
}
Field descriptions
FieldTypeDescription
sessionsarrayOne entry per ready session in the campaign.
sessions[].recap_idstring (uuid)The recap/session id.
sessions[].session_refstringShort human reference, e.g. S01AB.
sessions[].session_atstring (ISO 8601)When the session started (UTC).
playersarrayOne entry per recognised speaker.
players[].speakerstringSpeaker display name.
players[].pointsarrayPer-session metrics for this speaker.
players[].points[].participation_pctnumberShare of conversation, 0–100.
players[].points[].turn_countintegerNumber of speaking turns taken.
players[].points[].talk_time_secondsintegerTotal seconds speaking.
players[].points[].word_countintegerTotal words spoken.
get_campaign_synthesisIncluded

The cached cross-session AI narrative — campaign summary and key-events timeline. The synthesis already cost credits at refresh time.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "synthesis": {
    "campaign_summary": "…",
    "key_events": [
      {
        "session_ref": "S01AB",
        "title": "The white moose hunt",
        "detail": "…"
      }
    ],
    "synthesised_at": "2026-06-21T08:00:00Z",
    "source_session_count": 4
  }
}
Field descriptions
FieldTypeDescription
synthesisobject | nullnull until at least two sessions are synthesised.
synthesis.campaign_summarystringAI-generated cross-session narrative.
synthesis.key_eventsarrayTimeline of notable events.
synthesis.key_events[].titlestringShort event label.
synthesis.key_events[].detailstringEvent description.
synthesis.synthesised_atstring (ISO 8601)When the synthesis was last built.
synthesis.source_session_countintegerSessions included in the synthesis.
get_credit_balanceIncluded

Your available credits, total granted, and per-lane (GM / player) usage %. Lets an agent self-throttle before calling a paid tool.

Example input

{}

Example output

{
  "available_credits": 142,
  "total_credits": 200,
  "gm_chat": {
    "used_pct": 29
  },
  "player_chat": {
    "used_pct": 6
  }
}
Field descriptions
FieldTypeDescription
available_creditsnumberCredits remaining across both lanes.
total_creditsnumberCredits granted this billing period.
gm_chat.used_pctnumberGM lane usage, 0–100.
player_chat.used_pctnumberPlayer lane usage, 0–100.
get_recent_activityIncluded

A capped feed (≤300 rows) of session-recorded, recap-ready and credit-ledger events.

Example input

{}

Example output

{
  "activity": [
    {
      "type": "recap_ready",
      "label": "Session S01AB recap is ready",
      "date": "2026-06-21T08:02:00Z",
      "recap_id": "…"
    },
    {
      "type": "credit",
      "label": "Asked your campaign",
      "date": "2026-06-21T08:05:00Z"
    }
  ]
}
Field descriptions
FieldTypeDescription
activityarrayNewest-first feed, capped at 300 rows.
activity[].typestringEvent kind.values: recap_ready | session_recorded | credit
activity[].labelstringHuman-readable summary.
activity[].datestring (ISO 8601)When the event occurred.
activity[].recap_idstring (uuid) | omittedPresent for recap/session-related events.
get_memory_overviewIncluded

Richest GM situational-awareness blob: distribution, engagement trend + overall score, per-session participation, pillars of play.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "distribution": [
    {
      "label": "Roleplay",
      "pct": 58
    }
  ],
  "engagement": {
    "overall": {
      "score": 74,
      "label": "Playful / tense"
    }
  },
  "pillars": [
    "The green-eyed stranger",
    "The old inn",
    "The white moose hunt"
  ]
}
Field descriptions
FieldTypeDescription
distributionarrayShare of play by category.
distribution[].labelstringCategory name.
distribution[].pctnumberShare, 0–100.
engagement.overall.scorenumber | nullComposite engagement score, 0–100.
engagement.overall.labelstring | nullQualitative label, e.g. "Playful / tense".
pillarsstring[] | nullRecurring themes / pillars of play.
get_open_hooksIncluded

Unresolved narrative hooks — what to prep next session.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "hooks": [
    {
      "text": "Nobody bypasses the Choosing.",
      "session_ref": "S01AB",
      "session_date": "2026-06-20"
    }
  ]
}
Field descriptions
FieldTypeDescription
hooksarrayCurrently open narrative hooks.
hooks[].textstringThe hook description.
hooks[].session_refstringSession where the hook was introduced.
hooks[].session_datestring (YYYY-MM-DD)Date of that session.
get_previously_onIncluded

Previously-on context for the campaign, built from owner-scoped memory.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "sections": [
    {
      "title": "Last time",
      "bullets": [
        "The party followed the white moose into the mist."
      ]
    }
  ]
}
Field descriptions
FieldTypeDescription
sectionsarrayCampaign memory sections for recap/context.
sections[].titlestringSection heading.
sections[].bulletsstring[]Concise memory bullets.
get_chronicleIncluded

Scenes-per-session map — the structured campaign chronicle.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "sessions": [
    {
      "recap_id": "…",
      "session_ref": "S01AB",
      "scenes": [
        "The market",
        "The hunt",
        "The banshee fight"
      ]
    }
  ]
}
Field descriptions
FieldTypeDescription
sessionsarrayOne entry per session.
sessions[].recap_idstring (uuid)The recap/session id.
sessions[].scenesstring[]Ordered scene labels for that session.
get_entitiesIncluded

Named entities (NPCs, places, items) extracted across the campaign.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "entities": [
    {
      "name": "The green-eyed stranger",
      "description": "…",
      "session_ref": "S01AB",
      "session_date": "2026-06-20"
    }
  ]
}
Field descriptions
FieldTypeDescription
entitiesarrayNamed entities across the campaign.
entities[].namestringEntity display name.
entities[].descriptionstringShort description.
get_lore_documentsIncluded

The list of lore documents for the campaign.

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "documents": [
    {
      "id": "…",
      "title": "The Choosing",
      "updated_at": "2026-06-20"
    }
  ]
}
Field descriptions
FieldTypeDescription
documentsarrayLore documents.
documents[].idstring (uuid)Document identifier.
documents[].titlestringDocument title.
get_lore_documentIncluded

A single lore document with its full body.

Example input

{
  "campaign_id": "a1b2c3d4-…",
  "doc_id": "…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.
doc_idstring (uuid)The lore document to fetch.

Example output

{
  "document": {
    "id": "…",
    "title": "The Choosing",
    "body": "…"
  }
}
Field descriptions
FieldTypeDescription
document.idstring (uuid)Document identifier.
document.titlestringDocument title.
document.bodystringFull document body (markdown).
get_lexiconIncluded

Lexicon entries (canonical names, aliases, type, confidence).

Example input

{
  "campaign_id": "a1b2c3d4-…"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to read.

Example output

{
  "entries": [
    {
      "id": "…",
      "canonical": "Sol’Thun",
      "type": "npc",
      "aliases": [
        "the archmage"
      ],
      "confidence": 0.92,
      "enabled": true
    }
  ]
}
Field descriptions
FieldTypeDescription
entriesarrayLexicon entries.
entries[].canonicalstringCanonical name.
entries[].typestringEntity kind.values: npc | place | item | creature | other
entries[].aliasesstring[]Alternate names / aliases.
entries[].confidencenumberExtraction confidence, 0–1.
entries[].enabledbooleanWhether this entry is active.
get_transcript_windowIncluded

A positional slice of a session’s stored turns (no content search — just from/to turn indices).

Example input

{
  "recap_id": "…",
  "from": 0,
  "to": 20
}
Field descriptions
FieldTypeDescription
recap_idstring (uuid)The recap/session to read. Use list_recaps to discover ids.
fromintegerStart turn index (inclusive, default 0).
tointegerEnd turn index. Omit for a 50-turn window from the start index.

Example output

{
  "recap_id": "…",
  "total_turns": 184,
  "from": 0,
  "to": 20,
  "turns": [
    {
      "index": 0,
      "t": "~00:01",
      "speaker": "GM",
      "text": "…"
    }
  ]
}
Field descriptions
FieldTypeDescription
total_turnsintegerTotal turns in the session.
fromintegerStart index returned.
tointegerEnd index returned.
turnsarrayTurns in the requested window.
turns[].indexintegerPositional index in the session.
turns[].tstringRelative timestamp, e.g. ~00:01.
turns[].speakerstringSpeaker display name.
turns[].textstringThe spoken text.
get_recapIncluded

The player-safe recap HTML for a ready recap. The artifact type is server-owned; there is no type input.

Example input

{
  "recap_id": "…"
}
Field descriptions
FieldTypeDescription
recap_idstring (uuid)The recap/session whose player-safe recap should be fetched.

Example output

{
  "recap": {
    "recap_id": "…",
    "content_type": "player_recap_html",
    "html": "<!doctype html>…",
    "truncated": false
  }
}
Field descriptions
FieldTypeDescription
recap.recap_idstring (uuid)The recap/session id.
recap.content_typestringAlways player_recap_html.values: player_recap_html
recap.htmlstringThe player-safe recap HTML.
recap.truncatedbooleanTrue when the MCP response cap trimmed the HTML.
search_transcriptIncluded

Exact keyword (full-text) search over your campaign transcript turns. Returns turns containing the exact phrase, with their session, speaker and timestamp — no LLM, no embedding, no credits.

Example input

{
  "campaign_id": "a1b2c3d4-…",
  "query": "white moose"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to search.
querystringExact phrase to match (full-text search against transcript text).

Example output

{
  "query": "white moose",
  "matches": [
    {
      "recap_id": "…",
      "speaker": "GM",
      "t": "~01:04",
      "text": "All you know is that it’s a white moose."
    }
  ]
}
Field descriptions
FieldTypeDescription
querystringEcho of the submitted query.
matchesarrayTranscript turns containing the exact phrase, best match first.
matches[].recap_idstring (uuid)Recap/session the match came from.
matches[].speakerstringSpeaker of the matched turn.
matches[].tstringRelative timestamp, e.g. ~01:04.
matches[].textstringThe matched transcript text.

Ask-credit tool calls

These tools spend your existing Ask credits — the same ledger as in-app chat. Semantic RAG search (search_corpus) uses an embedding call and costs 0.25 credits; the agent answer (ask_gm) costs 1 credit for a simple answer, 2 credits for the deep / planning lanes. Rate-limited per API key in addition to your balance.

search_corpus0.25 credits

Hybrid RAG search over your campaign transcripts + memory using semantic embeddings. Returns retrieved chunks (not an LLM answer) — bring your own model to reason over them. Uses an embedding call (LLM-adjacent), so costs 0.25 credits. Rate-limited per API key in addition to your credit balance.

Example input

{
  "campaign_id": "a1b2c3d4-…",
  "query": "where did the hunter see the moose?"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to search.
querystringNatural-language search query (semantic matching).

Example output

{
  "query": "where did the hunter see the moose?",
  "chunks": [
    {
      "kind": "transcript",
      "recap_id": "…",
      "speaker": "Skoll",
      "text": "…",
      "score": 0.81
    },
    {
      "kind": "memory",
      "text": "The hunter saw the white moose near the old inn.",
      "score": 0.76
    }
  ],
  "credits_spent": 0.25
}
Field descriptions
FieldTypeDescription
querystringEcho of the submitted query.
chunksarrayRetrieved chunks, best match first.
chunks[].kindstringSource of the chunk.values: transcript | memory
chunks[].textstringThe matched text.
chunks[].scorenumberRelevance score, 0–1.
chunks[].recap_idstring (uuid) | nullRecap/session id when the chunk is anchored to a session.
chunks[].speakerstring (transcript only)Speaker of a transcript chunk.
credits_spentnumberCredits debited (0.25).
ask_gm1–2 credits

Ask your campaign a question and get the AI answer — the same agent/planning engine as in-app chat, with transcript receipts. Cost mirrors the in-app chat agent (deep/planning lanes = 2 credits). Rate-limited per API key in addition to your credit balance.

Example input

{
  "campaign_id": "a1b2c3d4-…",
  "question": "Where did the hunter see the moose?"
}
Field descriptions
FieldTypeDescription
campaign_idstring (uuid)The campaign to ask.
questionstringYour question.
clarificationobject | omittedOptional: answer a clarifying question the agent asked.
clarification.questionstringThe clarifying question from the agent.
clarification.answerstringYour answer to that question.
supersedesstring | omittedMessage id of a prior answer to replace.

Example output

{
  "answer": "The hunter reported seeing the white moose near the old inn to the north of town.",
  "receipts": [
    {
      "session_ref": "S01AB",
      "speaker": "Skoll",
      "text": "…"
    }
  ],
  "credits_spent": 2
}
Field descriptions
FieldTypeDescription
answerstringThe AI answer.
receiptsarrayTranscript evidence backing the answer.
receipts[].session_refstringSession the receipt came from.
receipts[].speakerstringSpeaker of the quoted turn.
receipts[].textstringThe quoted transcript text.
credits_spentintegerCredits debited (1 or 2 depending on lane).

Questions or feedback? See how Recap Raven works or invite the bot below.

Invite the Discord bot

Free to start — record your first session on us. No card required.

Questions or feedback? Join our Discord community