Fork note (ModuleAddon): This fork extends upstream
ervwalter/mcp-kankawith additional Kanka modules and workflow tooling for campaign operations.What’s added in this fork
- Expanded module/tool coverage beyond upstream core entity/post CRUD (for example: map marker workflows, map/timeline/calendar-related operations, and migration-oriented helpers).
- Safer map-marker update behavior for Kanka validation edge cases (including
entity_id: nullflows that require markernamehandling).- A whitelisted ordered migration runner (
run_migration_plan) for repeatable bulk conversions (marker repoints, entity updates, tag removals, deletes).- Campaign-specific operational docs/scripts used for worldbuilding conversion workflows.
Why this differs from upstream
- Upstream stays focused on a smaller, general MCP surface.
- This fork optimizes for high-volume campaign migrations and region/location conversion workflows with stricter sequencing and guardrails.
This branch builds on MCP-Kanka main and adds extra module-focused capabilities for this campaign workflow.
MCP (Model Context Protocol) server for Kanka API integration. This server provides AI assistants with tools to interact with Kanka campaigns, enabling CRUD operations on various entity types like characters, locations, organizations, and more.
This package is designed specifically to serve the needs of Teghrim but may be useful to others working with Kanka and MCP.
- Entity Management: Create, read, update, and delete Kanka entities
- Search & Filter: Search entities by name with partial matching, filter by type/tags/date
- Batch Operations: Process multiple entities in a single request
- Posts Management: Create, update, and delete posts (notes) on entities
- Markdown Support: Automatic conversion between Markdown and HTML with entity mention preservation
- Type Safety: Full type hints and validation
- Client-side Filtering: Enhanced filtering beyond API limitations
- Sync Support: Efficient synchronization with timestamp tracking and Kanka's native lastSync feature
- Timestamp Tracking: All entities include created_at and updated_at timestamps
- Python 3.10 or higher (3.13.5 recommended)
- Kanka API token and campaign ID
pip install mcp-kankagit clone https://github.com/ervwalter/mcp-kanka.git
cd mcp-kanka
uv sync --all-groups
uv pip install -e .git clone https://github.com/ervwalter/mcp-kanka.git
cd mcp-kanka
pip install -e .-
Set up your environment variables:
KANKA_TOKEN: Your Kanka API tokenKANKA_CAMPAIGN_ID: Your campaign ID
-
Add to Claude Desktop config:
{
"mcpServers": {
"kanka": {
"command": "python",
"args": ["-m", "mcp_kanka"],
"env": {
"KANKA_TOKEN": "your-token",
"KANKA_CAMPAIGN_ID": "your-campaign-id"
}
}
}
}claude mcp add kanka \
-e KANKA_TOKEN="your-token" \
-e KANKA_CAMPAIGN_ID="your-campaign-id" \
-- python -m mcp_kankaOpenWebUI does not use the native MCP stdio transport. If you bridge this server with mcpo (MCP → HTTP/OpenAPI), tool responses must be valid JSON in the tool result text, not Python’s repr of a dict (single quotes, True/False). From v1.1.1 onward, all tool payloads are serialized with json.dumps, so OpenWebUI and similar HTTP clients can parse results reliably.
- Character - Player characters (PCs), non-player characters (NPCs)
- Creature - Monster types, animals, non-unique creatures
- Location - Places, regions, buildings, landmarks
- Organization - Guilds, governments, cults, companies
- Race - Species, ancestries
- Note - Internal content, session digests, GM notes (private by default)
- Journal - Session summaries, narratives, chronicles
- Quest - Missions, objectives, story arcs
- Ability - Special actions and abilities
- Conversation - In-game dialog content
- Dice Roll - Dice roll definitions
- Bookmark - Bookmarks for sharing links
- Attribute - Entity properties/stat blocks
Search and filter entities with comprehensive options and sync metadata.
Parameters:
entity_type(optional): Type to filter by - character, creature, location, organization, race, note, journal, questquery(optional): Search term for full-text search across names and contentname(optional): Filter by name (partial match by default, e.g., "Test" matches "Test Character")name_exact(optional): Use exact name matching instead of partial (default: false)name_fuzzy(optional): Enable fuzzy matching for typo tolerance (default: false)type(optional): Filter by user-defined Type field (e.g., 'NPC', 'City')tags(optional): Array of tags - returns entities having ALL specified tagsdate_range(optional): For journals only - filter by date range withstartandenddateslimit(optional): Results per page (default: 25, max: 100, use 0 for all)page(optional): Page number for pagination (default: 1)include_full(optional): Include full entity details (default: true)last_synced(optional): ISO 8601 timestamp to get only entities modified after this time
Returns:
{
"entities": [...],
"sync_info": {
"request_timestamp": "2024-01-01T12:00:00Z",
"newest_updated_at": "2024-01-01T11:30:00Z",
"total_count": 150,
"last_page": 6,
"returned_count": 25
}
}Create one or more entities with markdown content.
Parameters:
entities: Array of entities to create, each with:entity_type(required): Type of entity to createname(required): Entity nameentry(optional): Description (Markdown accepted; auto-converted to HTML for API)type(optional): User-defined Type field (e.g., 'NPC', 'Player Character')tags(optional): Array of tag namesis_hidden(optional): If true, hidden from players (admin-only)
Returns: Array of created entities with their IDs and timestamps
Update one or more existing entities.
Parameters:
updates: Array of updates, each with:entity_id(required): ID of entity to updatename(optional): Entity name (optional for PATCH; if omitted and API requires it, MCP will retry with current name)entry(optional): Updated content (Markdown accepted; auto-converted to HTML for API)type(optional): Updated Type fieldtags(optional): Updated array of tagsis_hidden(optional): If true, hidden from players (admin-only)
Returns: Array of results with success/error status for each update
Retrieve specific entities by ID with optional posts.
Parameters:
entity_ids(required): Array of entity IDs to retrieveinclude_posts(optional): Include posts for each entity (default: false)
Returns: Array of full entity details with timestamps and optional posts
Delete one or more entities.
Parameters:
entity_ids(required): Array of entity IDs to delete
Returns: Array of results with success/error status for each deletion
This MCP server provides doc-verified manage_* tools and supporting read-only tools:
manage_map_markers: map marker CRUDmanage_relations: relation CRUDmanage_timeline_elements: timeline element CRUD (includesposition)manage_attributes: entity property/attribute CRUDmanage_entity_tags: entity tag add/removemanage_inventory: entity inventory CRUDmanage_permissions: per-entity permissions (list/update)search_entities: global search across all entity typesget_archives: retrieve archived entitiesmanage_entity_image: entity image list/upload/removemanage_calendar_weather: calendar weather CRUDcalendar_advance_date: advance calendar by one daycalendar_retreat_date: retreat calendar by one day
Efficiently check which entities have been modified since last sync.
Parameters:
entity_ids(required): Array of entity IDs to checklast_synced(required): ISO 8601 timestamp to check updates since
Returns:
{
"modified_entity_ids": [101, 103],
"deleted_entity_ids": [102],
"check_timestamp": "2024-01-01T12:00:00Z"
}Add posts (notes) to entities.
Parameters:
posts: Array of posts to create, each with:entity_id(required): Entity to attach post toname(required): Post titleentry(optional): Post content (Markdown accepted; auto-converted to HTML for API)is_hidden(optional): If true, hidden from players (admin-only)
Returns: Array of created posts with their IDs
Modify existing posts.
Parameters:
updates: Array of updates, each with:entity_id(required): The entity IDpost_id(required): The post ID to updatename(optional): Post title (optional for PATCH; if omitted and API requires it, MCP will retry with current title)entry(optional): Updated content (Markdown accepted; auto-converted to HTML for API)is_hidden(optional): If true, hidden from players (admin-only)
Returns: Array of results with success/error status for each update
Remove posts from entities.
Parameters:
deletions: Array of deletions, each with:entity_id(required): The entity IDpost_id(required): The post ID to delete
Returns: Array of results with success/error status for each deletion
The MCP server provides enhanced search capabilities:
- Content search: Full-text search across entity names and content (client-side)
- Name filter: Exact or fuzzy name matching
- Type filter: Filter by user-defined type field (e.g., 'NPC', 'City')
- Tag filter: Filter by tags (AND logic - entity must have all specified tags)
- Date range: Filter journals by date
- Fuzzy matching: Optional fuzzy name matching for more flexible searches
- Last sync filter: Use Kanka's native lastSync parameter to get only modified entities
Note: Content search fetches all entities and searches client-side, which may be slower for large campaigns but provides comprehensive search functionality.
All entities include created_at and updated_at timestamps in ISO 8601 format, enabling:
- Tracking when entities were created or last modified
- Implementing conflict resolution strategies
- Building audit trails
The find_entities tool returns sync metadata including:
request_timestamp: When the request was madenewest_updated_at: Latest updated_at from returned entitiestotal_count: Total matching entitieslast_page: Last pagination page numberreturned_count: Number returned in this response
Use the last_synced parameter to fetch only entities modified after a specific time:
# Example: Get entities modified in the last 24 hours
result = await find_entities(
entity_type="character",
last_synced="2024-01-01T00:00:00Z"
)The check_entity_updates tool efficiently checks which entities have been modified:
# Check which of these entities have changed
result = await check_entity_updates(
entity_ids=[101, 102, 103],
last_synced="2024-01-01T00:00:00Z"
)
# Returns: modified_entity_ids, deleted_entity_ids, check_timestamp# Clone the repository
git clone https://github.com/ervwalter/mcp-kanka.git
cd mcp-kanka
# Install development dependencies
make install# Run all tests
make test
# Run with coverage
make coverage
# Run all checks (lint + typecheck + test)
make check# Format code
make format
# Run linting
make lint
# Run type checking
make typecheckIn addition to being an MCP server, this package provides an operations layer that can be used directly in Python scripts:
from mcp_kanka.operations import create_operations
# Create operations instance
ops = create_operations()
# Find entities
result = await ops.find_entities(
entity_type="character",
name="Moradin"
)
# Create an entity
results = await ops.create_entities([{
"entity_type": "character",
"name": "New Character",
"type": "NPC",
"entry": "A mysterious figure"
}])This makes it easy to build sync scripts, bulk operations, or other tools that interact with Kanka.
The MCP server requires:
KANKA_TOKEN: Your Kanka API tokenKANKA_CAMPAIGN_ID: The ID of your Kanka campaign
The server provides a kanka://context resource that explains Kanka's structure and capabilities.
- Initial release
- Full CRUD operations for Kanka entities
- Batch operations support
- Markdown/HTML conversion with entity mention preservation
- Sync support with timestamp tracking
- Comprehensive search and filtering capabilities
MIT