Kanka MCP Server
This server exposes 77 MCP tools for reading and writing Kanka worldbuilding campaign data via the Kanka API.
List your campaigns (
list_campaigns) to find campaign IDs.Search entities within a campaign (
search, requirescampaignIdand queryq).Manage 15 entity types — Characters, Locations, Families, Organizations, Items, Notes, Events, Calendars, Timelines, Creatures, Races, Quests, Maps, Journals, and Abilities.
For each entity type, five CRUD tools:
list_<entities>— list records in a campaign (paginated viapage).get_<entity>— fetch full details of one record byid.create_<entity>— create a new record from adataobject.update_<entity>— modify an existing record byidwithdata.delete_<entity>— remove a record byid.
Everything is scoped to a campaign — every tool except
list_campaignsrequires acampaignId.
Note: the README documents extra list_* options (per_page, entries, entry_filter) and mentions list tools for Organizations, but the live schema only exposes page and campaignId, and names the list tool list_organisations while its CRUD siblings use organization.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Kanka MCP Server List my campaigns"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Kanka MCP Tool
Local MCP tool for the Kanka worldbuilding API. Runs on your machine via stdio — no remote server needed.
Prerequisites
Node.js 20+.
A Kanka API token (get one at kanka.io/en/settings/api).
Related MCP server: kanka-mcp
Install
npm installUsage
MCP client configuration (Claude Desktop, Cursor, etc.)
Add this to your MCP client config:
{
"mcpServers": {
"kanka": {
"command": "node",
"args": ["<ABSOLUTE_PATH_TO_REPO>/index.js"],
"env": {
"KANKA_API_TOKEN": "<YOUR_KANKA_TOKEN>"
}
}
}
}Notes:
Replace
<ABSOLUTE_PATH_TO_REPO>with the full path to this repository.On Windows, prefer forward slashes (
C:/Users/...) or escaped backslashes (C:\\Users\\...).Restart the MCP client after editing the config.
Run directly
KANKA_API_TOKEN=your_token npm startInstall globally
npm install -g .
KANKA_API_TOKEN=your_token kanka-mcpAvailable tools
The tool exposes 77 MCP tools for interacting with Kanka:
list_campaigns — List all campaigns
search — Search entities within a campaign
For each entity type (Character, Location, Family, Organization, Item, Note, Event, Calendar, Timeline, Creature, Race, Quest, Map, Journal, Ability):
list_<entities>— List allget_<entity>— Get detailscreate_<entity>— Create newupdate_<entity>— Update existingdelete_<entity>— Delete existing
Listing options
Big campaigns return list pages that are too large for some MCP clients to show
in full, which hides the records in the middle of the response. Every
list_<entities> tool takes these options to keep a page small and complete:
Option | Values | Description |
| number | Page number, default |
| 1–100 | Records per page. Enforced by this server, so it holds even when the Kanka API answers with a different page size. Omit it to return the API's own page untouched. |
| boolean | Default |
|
| Default |
When per_page or entry_filter is used, the response carries this server's own
meta instead of the API's:
{
"data": [{ "id": 42, "name": "Thalion", "has_entry": false }],
"meta": {
"page": 1,
"per_page": 100,
"count": 1,
"has_more": false,
"entry_filter": "empty",
"entries_included": false,
"total_unfiltered": 168,
"api_pages_fetched": 12
}
}Notes:
per_pagedefaults to 25 with entries, 100 without, and pages are stitched from as many API requests as needed.total_unfilteredis the size of the whole collection as reported by Kanka — it is not the number of records left afterentry_filter. Walk pages untilhas_moreisfalse.scan_incomplete: truemeans the budget of 50 API requests per call ran out before the window was filled, so records past that point were not scanned.
Example — find every character with no entry yet, in as few calls as possible:
{ "campaignId": 235025, "per_page": 100, "entries": false, "entry_filter": "empty" }Contributing
Community contributions are welcome.
Read CONTRIBUTING.md for workflow, coding standards, and PR checklist.
Review CODE_OF_CONDUCT.md before participating.
Local quality checks
npm run lint
npm run format:check
npm testClaude Desktop bundle (.mcpb)
The .mcpb bundle is built by the MCP bundle (.mcpb) GitHub Actions workflow, not by hand. On every pull request it validates manifest.json, packs the bundle with the official mcpb CLI and starts it to check that it answers an MCP initialize request. Pushes to main keep the bundle as a workflow artifact, and v* tags attach it to the matching GitHub release.
To cut a release, bump the version in both package.json and manifest.json (CI fails if they differ), merge, then push the tag v<version>. The workflow creates the GitHub release for that tag if it does not exist yet and attaches the .mcpb to it; write the release notes by editing that release afterwards. Files that must stay out of the bundle are listed in .mcpbignore.
To build one locally:
npm ci --omit=dev
npx @anthropic-ai/mcpb@2.1.2 pack . kanka-mcp.mcpb
npm ci # restore the dev dependencies (eslint, prettier) removed aboveAvailable Tools
77 toolscreate_abilityC
Create a new ability
Inputs: data (required), campaignId (required).
create_calendarC
Create a new calendar
Inputs: data (required), campaignId (required).
create_characterC
Create a new character
Inputs: data (required), campaignId (required).
create_creatureC
Create a new creature
Inputs: data (required), campaignId (required).
create_eventD
Create a new event
Inputs: data (required), campaignId (required).
create_familyC
Create a new family
Inputs: data (required), campaignId (required).
create_itemC
Create a new item
Inputs: data (required), campaignId (required).
create_journalC
Create a new journal
Inputs: data (required), campaignId (required).
create_locationD
Create a new location
Inputs: data (required), campaignId (required).
create_mapC
Create a new map
Inputs: data (required), campaignId (required).
create_noteC
Create a new note
Inputs: data (required), campaignId (required).
create_organizationC
Create a new organization
Inputs: data (required), campaignId (required).
create_questC
Create a new quest
Inputs: data (required), campaignId (required).
create_raceD
Create a new race
Inputs: data (required), campaignId (required).
create_timelineD
Create a new timeline
Inputs: data (required), campaignId (required).
delete_abilityD
Delete an existing ability
Inputs: id (required), campaignId (required).
delete_calendarC
Delete an existing calendar
Inputs: id (required), campaignId (required).
delete_characterC
Delete an existing character
Inputs: id (required), campaignId (required).
delete_creatureC
Delete an existing creature
Inputs: id (required), campaignId (required).
delete_eventC
Delete an existing event
Inputs: id (required), campaignId (required).
delete_familyC
Delete an existing family
Inputs: id (required), campaignId (required).
delete_itemC
Delete an existing item
Inputs: id (required), campaignId (required).
delete_journalB
Delete an existing journal
Inputs: id (required), campaignId (required).
delete_locationC
Delete an existing location
Inputs: id (required), campaignId (required).
delete_mapC
Delete an existing map
Inputs: id (required), campaignId (required).
delete_noteB
Delete an existing note
Inputs: id (required), campaignId (required).
delete_organizationC
Delete an existing organization
Inputs: id (required), campaignId (required).
delete_questC
Delete an existing quest
Inputs: id (required), campaignId (required).
delete_raceC
Delete an existing race
Inputs: id (required), campaignId (required).
delete_timelineC
Delete an existing timeline
Inputs: id (required), campaignId (required).
get_abilityC
Get details of a ability
Inputs: id (required), campaignId (required).
get_calendarC
Get details of a calendar
Inputs: id (required), campaignId (required).
get_characterB
Get details of a character
Inputs: id (required), campaignId (required).
get_creatureC
Get details of a creature
Inputs: id (required), campaignId (required).
get_eventC
Get details of a event
Inputs: id (required), campaignId (required).
get_familyC
Get details of a family
Inputs: id (required), campaignId (required).
get_itemC
Get details of a item
Inputs: id (required), campaignId (required).
get_journalC
Get details of a journal
Inputs: id (required), campaignId (required).
get_locationC
Get details of a location
Inputs: id (required), campaignId (required).
get_mapC
Get details of a map
Inputs: id (required), campaignId (required).
get_noteB
Get details of a note
Inputs: id (required), campaignId (required).
get_organizationC
Get details of a organization
Inputs: id (required), campaignId (required).
get_questB
Get details of a quest
Inputs: id (required), campaignId (required).
get_raceC
Get details of a race
Inputs: id (required), campaignId (required).
get_timelineC
Get details of a timeline
Inputs: id (required), campaignId (required).
list_abilitiesB
List abilities. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_calendarsB
List calendars. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_campaignsA
List all campaigns
Inputs: no named parameters.
list_charactersA
List characters. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_creaturesB
List creatures. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_eventsA
List events. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_familiesB
List families. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_itemsA
List items. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_journalsB
List journals. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_locationsB
List locations. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_mapsA
List maps. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_notesB
List notes. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_organisationsA
List organisations. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_questsB
List quests. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_racesA
List races. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
list_timelinesA
List timelines. Use per_page to keep responses small enough to be returned whole, and entry_filter to return only records whose entry is empty or filled.
Inputs: campaignId (required), page, entries, per_page, +1 more.
searchC
Search entities
Inputs: q (required), campaignId (required).
update_abilityC
Update an existing ability
Inputs: id (required), data (required), campaignId (required).
update_calendarC
Update an existing calendar
Inputs: id (required), data (required), campaignId (required).
update_characterC
Update an existing character
Inputs: id (required), data (required), campaignId (required).
update_creatureC
Update an existing creature
Inputs: id (required), data (required), campaignId (required).
update_eventC
Update an existing event
Inputs: id (required), data (required), campaignId (required).
update_familyC
Update an existing family
Inputs: id (required), data (required), campaignId (required).
update_itemC
Update an existing item
Inputs: id (required), data (required), campaignId (required).
update_journalC
Update an existing journal
Inputs: id (required), data (required), campaignId (required).
update_locationC
Update an existing location
Inputs: id (required), data (required), campaignId (required).
update_mapC
Update an existing map
Inputs: id (required), data (required), campaignId (required).
update_noteC
Update an existing note
Inputs: id (required), data (required), campaignId (required).
update_organizationC
Update an existing organization
Inputs: id (required), data (required), campaignId (required).
update_questC
Update an existing quest
Inputs: id (required), data (required), campaignId (required).
update_raceC
Update an existing race
Inputs: id (required), data (required), campaignId (required).
update_timelineC
Update an existing timeline
Inputs: id (required), data (required), campaignId (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 77 tools
Each entity type has a clear list/get/create/update/delete split, so tool selection is mostly determined by the entity being managed. The generic `search` tool and the broad `list_*`/`get_*` surface add slight overlap, but no two tools appear to do the same job.
Nearly all tools follow a snake_case verb_noun pattern, such as `create_event` and `delete_calendar`. Minor deviations exist: `search` is a bare verb, and the spelling inconsistency between `list_organisations` and the CRUD tools using `organization` breaks the otherwise predictable naming.
77 tools for CRUD across 16 entity types is extremely heavy and well past the 50+ threshold for an oversized surface. The same coverage could be exposed with fewer generic or grouped tools, and this count is likely to overwhelm tool selection.
Core lifecycle coverage is strong: every major entity type has list/get/create/update/delete operations, avoiding obvious CRUD dead ends. However, campaign-level operations, relations, tags, posts, members, and other Kanka features are absent, so non-CRUD workflows may hit gaps.
Maintenance
Related MCP Connectors
Access your Kazkar TTRPG world — campaigns, chronicles, transcripts, lore — in any MCP client.
Manage your tabletop RPG campaign from any MCP client: worlds, sessions, quests, lore, recaps.
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
Rick and Morty MCP — wraps the Rick and Morty API (free, no auth)
Related MCP Servers
- AlicenseBqualityBmaintenanceEnables AI assistants to interact with Kanka campaigns through CRUD operations on entities like characters, locations, organizations, and quests, with support for markdown content, batch operations, and efficient synchronization.94MIT
- AlicenseAqualityDmaintenanceEnables MCP-compatible agents to authenticate to a Kanka account and interact with campaigns, entities (CRUD on all 18 entity types, posts, relations), and full-text search.152MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Kanka worldbuilding campaigns, characters, locations, posts, notes, and journals through the Kanka API.MIT

SagaSmith D&D MCPofficial
AlicenseNot gradedqualityFmaintenanceA local MCP server for Dungeons & Dragons campaign management, combining core runtime with skill and module-generation packs. It enables campaign creation, module generation and import, rule and skill searching via tools, resources, and prompts.Apache 2.0