{
  "markdown": "# Archivist AI MCP Server\n\n[![MIT License](https://img.shields.io/github/license/Astrotomic/mcp.myarchivist.ai.svg?label=License&color=blue&style=for-the-badge)](https://github.com/Astrotomic/mcp.myarchivist.ai/blob/master/LICENSE)\n[![Treeware](https://img.shields.io/badge/Treeware-%F0%9F%8C%B3-green?style=for-the-badge)](https://plant.treeware.earth/Astrotomic/mcp.myarchivist.ai)\n[![Larabelles](https://img.shields.io/badge/Larabelles-%F0%9F%A6%84-lightpink?style=for-the-badge)](https://www.larabelles.com/)\n\n[![GitHub PHPunit Status](https://img.shields.io/github/actions/workflow/status/Astrotomic/mcp.myarchivist.ai/phpunit.yml?style=flat-square&logoColor=white&logo=github&label=PHPunit)](https://github.com/Astrotomic/mcp.myarchivist.ai/actions/workflows/phpunit.yml)\n[![GitHub PHPStan Status](https://img.shields.io/github/actions/workflow/status/Astrotomic/mcp.myarchivist.ai/phpstan.yml?style=flat-square&logoColor=white&logo=github&label=PHPStan)](https://github.com/Astrotomic/mcp.myarchivist.ai/actions/workflows/phpstan.yml)\n[![GitHub Pint Status](https://img.shields.io/github/actions/workflow/status/Astrotomic/mcp.myarchivist.ai/pint.yml?style=flat-square&logoColor=white&logo=github&label=Pint)](https://github.com/Astrotomic/mcp.myarchivist.ai/actions/workflows/pint.yml)\n[![GitHub PHPMND Status](https://img.shields.io/github/actions/workflow/status/Astrotomic/mcp.myarchivist.ai/phpmnd.yml?style=flat-square&logoColor=white&logo=github&label=PHPMND)](https://github.com/Astrotomic/mcp.myarchivist.ai/actions/workflows/phpmnd.yml)\n\n[![Discord](https://img.shields.io/badge/Discord-MyArchivist-5865F2?style=flat-square&logoColor=white&logo=discord)](https://discord.gg/t3yk6AWyg7)\n[![Smithery](https://img.shields.io/badge/Smithery-MyArchivist-ff5601?style=flat-square)](https://smithery.ai/servers/me-26lt/archivist-ai)\n[![Glama](https://img.shields.io/badge/Glama-MyArchivist-00d992?style=flat-square)](https://glama.ai/mcp/connectors/ai.myarchivist.mcp/mcp-archivist-ai)\n[![mcp.so](https://img.shields.io/badge/mcp.so-MyArchivist-c96442?style=flat-square)](https://mcp.so/server/archivist-ai/Archivist%20AI)\n\nThe official [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for [Archivist AI](https://www.myarchivist.ai) -- a TTRPG campaign memory platform for game masters and players.\n\nRegistry metadata lives in [`server.json`](./server.json). Publishing to the [official MCP Registry](https://modelcontextprotocol.io/registry) is automated on version tags via [`.github/workflows/publish-mcp.yml`](./.github/workflows/publish-mcp.yml) (`git tag v1.0.0 && git push origin v1.0.0`).\n\nConnect AI assistants like Claude, ChatGPT, Cursor, Notion, and Windsurf directly to your campaign data: characters, sessions, locations, factions, items, quests, journals, key moments, hero awards, quotes, spotlights, and more.\n\n## Quick Start\n\n**MCP Server URL:** `https://mcp.myarchivist.ai/mcp`\n\nDiscord tools live on a sibling host: `https://discord.myarchivist.ai/mcp`. That is a separate MCP resource (OAuth + your recording bot) and does not replace campaign tools here.\n\n<details>\n<summary>Claude Desktop</summary>\n\nClaude Desktop requires the [`mcp-remote`](https://github.com/geelen/mcp-remote) proxy (Node.js must be installed).\n\nAdd to your `claude_desktop_config.json` (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\\Claude\\claude_desktop_config.json` on Windows):\n```json\n{\n  \"mcpServers\": {\n    \"archivist-ai\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"mcp-remote\",\n        \"https://mcp.myarchivist.ai/mcp\",\n        \"--header\",\n        \"Authorization:${AUTH_HEADER}\"\n      ],\n      \"env\": {\n        \"AUTH_HEADER\": \"Bearer YOUR_API_KEY\"\n      }\n    }\n  }\n}\n```\n\nReplace `YOUR_API_KEY` with your Archivist AI API key from [app.myarchivist.ai](https://app.myarchivist.ai). Restart Claude Desktop after saving.\n</details>\n\n<details>\n<summary>Cursor</summary>\n\nAdd to `.cursor/mcp.json` in your project:\n```json\n{\n  \"mcpServers\": {\n    \"archivist-ai\": {\n      \"url\": \"https://mcp.myarchivist.ai/mcp\"\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary>Windsurf</summary>\n\nAdd to your MCP configuration:\n```json\n{\n  \"mcpServers\": {\n    \"archivist-ai\": {\n      \"serverUrl\": \"https://mcp.myarchivist.ai/mcp\"\n    }\n  }\n}\n```\n</details>\n\n<details>\n<summary>ChatGPT</summary>\n\nArchivist AI is available as a ChatGPT plugin. Search for \"Archivist AI\" in the ChatGPT plugin store.\n</details>\n\n## Available Tools\n\nRead tools are non-destructive and idempotent. Write tools follow standard REST semantics — deletes are destructive and idempotent; PATCH is non-idempotent; PUT is idempotent. Every read tool that returns text-carrying descriptions (Character, Faction, Location, Item, Moment, Beat, Session, Journal) accepts an optional `with_links` parameter — see [Wikilinks](#wikilinks) below for why you almost always want to pass `with_links: true` before editing.\n\nCampaign delete, session delete, product-view-only endpoints (beat reorder/batch-edit, campaign settings, cast/member management), multipart recording uploads, and AI image generation are intentionally not exposed.\n\n### OAuth scopes and write access\n\nOAuth clients that connect via `https://app.myarchivist.ai` request scopes at authorization time. Every write tool (create/update/delete + image upload) additionally requires the `agent_write` scope on the caller's token.\n\nThe MCP mirrors the API's enforcement in `tools/list`: agent clients without `agent_write` see only the read tools, and receive a \"tool not found\" JSON-RPC error if they attempt to call a write tool anyway. API-key credentials and non-agent OAuth clients bypass this filter — the API is the authoritative gate for them and all tools remain visible.\n\nExisting OAuth clients that connected before `agent_write` was advertised need to re-authorize to receive a token with the new scope.\n\n### Campaigns\n\n| Tool | Description |\n|------|-------------|\n| `list_campaigns` | List your campaigns. Returns a paginated list. |\n| `get_campaign` | Get a specific campaign by ID. |\n| `get_campaign_stats` | Get statistics for a campaign: character count, session count, and more. |\n| `create_campaign` | Create a new campaign. Subject to the account's subscription-tier campaign limit. |\n| `update_campaign` | Partially update campaign metadata (title, description, tones, public/mature flags). |\n\n### Sessions\n\n| Tool | Description |\n|------|-------------|\n| `list_sessions` | List game sessions. Filter by session type or public-only. |\n| `get_session` | Get a session by ID. Optionally include related beats and moments. |\n| `get_session_cast_analysis` | Get cast analysis: talk-share breakdown and core session metrics. |\n| `get_session_transcript` | Get the cleaned transcript for a game session, including utterances, full text, and aggregate stats. |\n| `get_session_handout` | Get the generated session handout for a game session, including summary, outlines, spotlights, and notable moments. |\n| `patch_session` | Partial update (title, session_date, summary, image). Explicit-link contract for wikilinks. |\n| `update_session` | Full update (PUT). Explicit-link contract for wikilinks. |\n\n### Story Structure\n\n| Tool | Description |\n|------|-------------|\n| `list_beats` | List beats ordered by index. Beats represent story moments (major, minor, step). |\n| `get_beat` | Get a specific beat by ID. |\n| `create_beat` | Create a beat. Explicit-link contract for wikilinks. |\n| `update_beat` | Partially update a beat. |\n| `delete_beat` | Delete a beat (child beats have parent_id cleared). |\n| `list_moments` | List Key Moments (Moments) in a campaign or session. Filter by label, categories (typically `key-moment`), or kind. Includes image and presentation metadata. |\n| `get_moment` | Get a Key Moment by ID, including image URL, categories, kind, and metadata. |\n| `create_moment` | Create a Key Moment attached to a session. Set `categories=[\"key-moment\"]` for a Key Moment card. Explicit-link contract for wikilinks. |\n| `update_moment` | Partially update a Key Moment, including image and merged presentation metadata. |\n| `delete_moment` | Delete a Key Moment. |\n\n### Highlights\n\n| Tool | Description |\n|------|-------------|\n| `list_hero_awards` | List hero awards in a campaign or session. |\n| `get_hero_award` | Get a hero award by ID. |\n| `create_hero_award` | Create a hero award attached to a session. |\n| `update_hero_award` | Partially update a hero award. |\n| `delete_hero_award` | Delete a hero award. |\n| `list_quotes` | List memorable session quotes in a campaign or session. |\n| `get_quote` | Get a quote by ID. |\n| `create_quote` | Create a quote attached to a session (creates a recap pipeline if needed). |\n| `update_quote` | Partially update a quote. |\n| `delete_quote` | Delete a quote. |\n| `list_spotlights` | List recap spotlights (GEMS cards, not session-handout spotlights). |\n| `get_spotlight` | Get a recap spotlight by ID. |\n| `create_spotlight` | Create a recap spotlight attached to a session. |\n| `update_spotlight` | Partially update a recap spotlight. |\n| `delete_spotlight` | Delete a recap spotlight. |\n\n### World Building\n\n| Tool | Description |\n|------|-------------|\n| `list_characters` | List characters in a campaign. Filter by name, type (PC/NPC), or approval status. |\n| `get_character` | Get a character by ID including aliases, backstory, and speaker linkage. |\n| `create_character` | Create a character. Description/backstory wikilinks auto-resolve. |\n| `update_character` | Partially update a character. Read with `with_links: true` before editing description/backstory. |\n| `delete_character` | Delete a character. API unbrackets all inbound `[[alias]]` references automatically. |\n| `list_factions` | List factions. Factions represent guilds, organisations, or other groups. |\n| `get_faction` | Get a specific faction by ID. |\n| `create_faction` | Create a faction. Description wikilinks auto-resolve. |\n| `update_faction` | Partially update a faction. Read with `with_links: true` before editing. |\n| `delete_faction` | Delete a faction. |\n| `list_locations` | List locations. Locations can be nested (cities, taverns, dungeons, etc.). |\n| `get_location` | Get a specific location by ID. |\n| `create_location` | Create a location. Description wikilinks auto-resolve. |\n| `update_location` | Partially update a location. Read with `with_links: true` before editing. |\n| `delete_location` | Delete a location (child locations have parent_id cleared). |\n| `list_items` | List items. Items include weapons, armour, artefacts, and other notable objects. |\n| `get_item` | Get a specific item by ID. |\n| `create_item` | Create an item. Description wikilinks auto-resolve. |\n| `update_item` | Partially update an item. Read with `with_links: true` before editing. |\n| `delete_item` | Delete an item. |\n\n### Quests\n\n| Tool | Description |\n|------|-------------|\n| `list_quests` | List quests with pagination. Filter by status or category. |\n| `get_quest` | Get a fully expanded quest: objectives, progress log, related entities, session provenance. |\n| `create_quest` | Create a quest entry. Quests do not participate in the wikilinks system. |\n| `update_quest` | Partially update a quest. Lists you send replace their corresponding lists on the record. |\n| `delete_quest` | Delete a quest and its objectives / progress entries / related refs. |\n\n### Journals\n\n| Tool | Description |\n|------|-------------|\n| `list_journals` | List journal entries. Content omitted from list; use get_journal for full content. |\n| `get_journal` | Get a journal entry by ID including full content and permission level. |\n| `create_journal` | Create a journal entry. Returns `{success, id}`. |\n| `update_journal` | Update a journal entry (PUT). Returns `{success, id}`. |\n| `delete_journal` | Delete a journal entry (embeddings are best-effort deleted). |\n| `list_journal_folders` | List journal folders ordered by path and position for tree rendering. |\n| `get_journal_folder` | Get a specific journal folder by ID. |\n| `create_journal_folder` | Create a journal folder (owners/admins only; path must be unique per campaign). |\n| `update_journal_folder` | Update a journal folder (PUT). |\n| `delete_journal_folder` | Delete a folder; entries move to the campaign root. |\n\n### Relationships\n\n| Tool | Description |\n|------|-------------|\n| `list_links` | List links between entities. Filter by source/target entity and relationship alias. |\n| `create_link` | Create a Link row between two entities (upserts if `(from_type, from_id, alias)` collides). |\n| `update_link` | Update an existing link's alias. |\n| `delete_link` | Delete a single Link row (does not rewrite the source's text). |\n| `bulk_link_maintenance` | Trigger campaign-wide link maintenance (add/remove/update) via webhook — requires an active subscription tier. |\n\n### Images\n\n| Tool | Description |\n|------|-------------|\n| `get_image_usage` | Return the calling account's image quota for a campaign: `used`/`limit`, `tier`, `can_access`, and cycle window. |\n| `init_image_upload` | Step 1 of direct upload: reserve an `object_key` and receive a presigned S3 PUT URL. The client then PUTs the raw image bytes to `upload_url` with the same `Content-Type`. Expires after `expires_in_seconds`. |\n| `complete_image_upload` | Step 2 of direct upload: validate the uploaded object, run NSFW moderation, and (when `attach: true`) set the entity's `image` field to the moderated URL. |\n| `delete_entity_image` | Remove an image. Provide `entity_type` + `entity_id` (detaches AND deletes the object) or `image_url` (deletes just the object). |\n\n## Wikilinks\n\nDescriptions, summaries, moment content, and journal bodies in Archivist AI can contain `[[Target Name|Optional Alias]]` markup that resolves to real records. Every write tool that touches a text field carrying wikilinks has to follow a small protocol to avoid destroying existing links.\n\n### The one rule you must follow\n\n**Always read with `with_links: true` before writing.** Every Get/List tool for Character, Faction, Location, Item, Moment, Beat, Session, and Journal accepts this parameter. The API defaults to stripping wikilinks so that read consumers get clean prose, which means a naive read/modify/write cycle will erase every `[[…]]` on the source record. Passing `with_links: true` returns the text with brackets intact so you can preserve them on write.\n\n### Per-record contract\n\n| Record type | Contract |\n|-------------|----------|\n| Character, Faction, Location, Item, Character.backstory | **Auto-resolve.** On write, the API extracts `[[…]]` from your new text, matches each against records in the same campaign, and syncs the Link table (inserts new, updates changed, deletes removed). New `[[Alias]]` markup for a matchable target creates a Link automatically. |\n| GameSession, Beat, Moment | **Explicit-link only.** The API strips `[[Alias]]` markup that does NOT already have a matching Link row for that source. To add a wikilink, first call `create_link` with the correct `from_type`/`from_id`, then include `[[Alias]]` in the text on your write. |\n| Journal | **Rendering-only.** Stored `[[…]]` markup renders as links on read with `with_links: true` but writes do not auto-populate the Link table. Use `create_link` (`from_type=Journal`) if you want persistent link tracking. |\n| Quest | **No wikilinks.** Quest text fields are stored verbatim. Relationships are modelled via the `related_*` list fields, not wikilinks. |\n| Delete (any record) | The API automatically unbrackets all `[[alias]]` references to a deleted record across every referring text field. No manual cleanup is required. |\n\n### Renaming and repointing\n\n- **Rename an alias**: edit inside the brackets. `[[Alice|Al]]` → `[[Alice|Ali]]`.\n- **Repoint at a different target**: change the visible target name. `[[Alice]]` → `[[Alicia]]`.\n- **Remove a link**: unbracket the alias in the text (auto-resolve) or call `delete_link` (explicit).\n- **Campaign-wide rename or repoint** for a compendium target: use `bulk_link_maintenance` with `operation: \"update\"`, `new_alias`, and/or `new_target_id`. The API rewrites every referring text field in a background webhook and returns a `task_id`.\n\n## Images\n\nEntity images can be added to Characters, Factions, Locations, Items, Moments, Sessions, and the Campaign itself via direct upload. The MCP server does not expose an AI image generation tool — image generation remains a product feature in the Archivist AI app and a REST endpoint on the API.\n\n### Direct upload (two-step)\n\nFor images the user already has on disk or in memory, use the presigned-URL flow:\n\n1. Call `init_image_upload` with `campaign_id`, `entity_type`, `entity_id`, `file_name`, and `content_type` (must be `image/*`). You receive `object_key`, `upload_url`, `public_url`, and `expires_in_seconds`.\n2. Your client (or a human collaborator) issues an HTTP `PUT` to `upload_url` with the raw image bytes and the same `Content-Type` header before the URL expires. This step happens outside the MCP transport.\n3. Call `complete_image_upload` with `object_key`, `entity_type`, `entity_id`, and `attach` (defaults to `true`). The API validates the upload, runs NSFW moderation, and — when `attach` is true — sets the entity's `image` field to the moderated `public_url`.\n\nAgents that cannot make arbitrary HTTP PUTs should hand the PUT step off to a human between step 1 and step 3.\n\n### Removal\n\n`delete_entity_image` removes an image within a campaign in one of two modes:\n- **By entity**: pass `entity_type` + `entity_id`. The API detaches the image from the record AND deletes the underlying object.\n- **By URL**: pass a managed `image_url` (e.g. from a previous `init_image_upload` response). Deletes just the object.\n",
  "bytes": 17796,
  "sha": "f3c7df31426b3d4f3bfa58fe64dd9d1b248e31ccdd28eeb89f9a095e2375cd34",
  "repo_slug": "astrotomic/mcp.myarchivist.ai",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_astrotomic_archivist_ai_5fc0265e/readme"
}