关于 LegendKeeper
legendkeeper-mcp 通过 LegendKeeper v3 REST API 将世界设定连接到 AI 助手。它面向希望读取和编辑页面、地图、时间线、事实等内容的世界构建者,支持按章节编辑 Markdown 页面及管理多个世界。
主要功能
- 01以 Markdown 读取和编辑页面
- 02管理资源、事实、地图和时间线
- 03批量创建关联资源
- 04连接多个世界
- 05只读模式及 stdio 或 HTTP 传输
适用场景
- 01起草或修改世界设定 Wiki 页面
- 02为设定添加事实和地图标记
- 03创建时间线事件及关联资源
- 04浏览多个 LegendKeeper 世界
MCP 相关
该服务将 LegendKeeper 内容操作作为 MCP 工具提供,并提供 Markdown 和样式指南两项 MCP 资源。它支持桌面客户端使用 stdio,也支持带 Bearer 令牌验证的 Streamable HTTP。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx legendkeeper-mcpLEGENDKEEPER_API_KEY密钥LegendKeeper project API key (Project Settings → Developers → API Keys). The project owner needs a paid plan.LEGENDKEEPER_READ_ONLYSet to true to expose only reading tools.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
31收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
legendkeeper-mcp

一个 MCP 服务,可让 AI 助手(Claude、Copilot、Cursor、……)通过 LegendKeeper 官方 v3 REST API,读取并构建你的 LegendKeeper 世界:维基页面、信息框事实、地图标记、时间线、 标签、模板和图片。
非官方项目。 本项目并非由 LegendKeeper 制作、认可或支持。它使用你自己的 API 密钥,在你的本地计算机上运行。
You: Create a tavern called The Drunken Dragon in Waterdeep, give it an infobox with its owner and
a pin on the city map, and mention it on Volo's page.
Claude: (search → create_resource → set_facts → create_map_feature → write_page) Done! ...
目录
功能
- 31 个精选工具,专为大模型设计。资源既可使用名称,也可使用 ID;错误信息会说明如何修复。
api_request可作为备用入口,访问所有其他 v3 端点。 - 页面以 Markdown 格式双向处理。
[[Wiki Links]]会转换为真正的 LegendKeeper 提及。支持提示框、仅 GM 可见的秘密内容、可折叠部分、任务列表、表格和图片。Markdown 无法表达的内容块(信息框、嵌入内容、集合……)在重写时会原样保留。请参阅 页面编辑方式。 - 按章节编辑:可追加、前置、替换或扩展某个标题下的章节,而不影响页面其余内容。每次写入都会进行版本检查(
If-Match),因此不会静默覆盖应用中的并发编辑。 - 结构化世界构建:信息框和侧边栏事实、地图标记/区域/路径(经纬度或图片像素坐标)、时间线事件和轨道(如
"3 March 1204"这样的自然日期)、模板、批量创建最多 100 个互相关联的资源,以及从磁盘或 URL 上传图片。 - 一个服务支持多个世界(每个世界使用一个 API 密钥),并支持只读模式。
- 两种传输方式:供桌面客户端使用的 stdio,或通过持有者令牌提供可流式传输 HTTP 的长时间运行 Docker 容器。
- 健壮的客户端:支持退避重试、遵循
Retry-After、每个 POST 请求都使用幂等键以避免重试导致重复创建,并跟踪速率限制。 - 经过契约测试:测试套件针对模拟 API 运行,该 API 会根据 LegendKeeper 发布的 OpenAPI 规范验证每个请求和响应。每周运行的 CI 任务会根据最新规范重新检查。
要求
- 项目所有者使用付费计划的 LegendKeeper 项目。 LegendKeeper 只接受这类项目的 API 密钥(试用计划不算),否则会返回
402 PAID_PLAN_REQUIRED。 - API 密钥:在 LegendKeeper 中打开项目,前往 Project Settings → Developers → API Keys,为密钥命名、选择角色并创建密钥。复制
lk_…密钥;它只会显示一次。- Member 密钥可以读取和写入内容。
- Admin 密钥还可以查看和创建隐藏资源及 GM 秘密、读取标签(对于 Member 密钥,
list_tags会改为自行统计标签)、查看成员电子邮件地址并保存模板。 - 密钥的权限不会超过其创建者的权限,并且只能在创建它的项目中使用。
- 以下三者任选其一:uv(推荐)、Docker,或带 pip 的 Python ≥ 3.11。
快速开始
任选一种。它们都会从 LEGENDKEEPER_API_KEY 读取密钥。
uvx(无需安装):
LEGENDKEEPER_API_KEY=lk_... uvx legendkeeper-mcp check # verify the key
Docker:
docker run -i --rm -e LEGENDKEEPER_API_KEY=lk_... ghcr.io/chase-roohms/legendkeeper-mcp:latest check
pip:
pip install legendkeeper-mcp
legendkeeper-mcp check
check 会打印每个已配置密钥所打开的世界,然后退出。不加 check 时,命令会通过标准输入输出启动 MCP 服务,桌面客户端会为你启动该服务(见下文)。
在首次发布到 PyPI 之前,请使用
uvx --from git+https://github.com/chase-roohms/legendkeeper-mcp legendkeeper-mcp,或自行使用docker build -t legendkeeper-mcp .构建镜像。
长时间运行的 HTTP 服务(Docker Compose):
cp .env.example .env # set LEGENDKEEPER_API_KEY and MCP_AUTH_TOKEN (openssl rand -hex 32)
docker compose up -d # serves http://localhost:8000/mcp, bound to 127.0.0.1 only
curl http://localhost:8000/healthz
让支持 HTTP 的客户端连接到 http://localhost:8000/mcp,并设置请求头 Authorization: Bearer <MCP_AUTH_TOKEN>。放在 ./uploads 中的图像可以通过 upload_image 上传(source: /uploads/<file>)。
客户端配置
可直接使用的文件位于 examples/。
Claude Desktop:添加到 claude_desktop_config.json(macOS:~/Library/Application Support/Claude/,Windows:%APPDATA%\Claude\),然后重启 Claude:
{
"mcpServers": {
"legendkeeper": {
"command": "uvx",
"args": ["legendkeeper-mcp"],
"env": { "LEGENDKEEPER_API_KEY": "lk_your_key_here" }
}
}
}
VS Code(.vscode/mcp.json,系统会提示输入密钥并安全保存):
{
"inputs": [{ "type": "promptString", "id": "lk-key", "description": "LegendKeeper API key", "password": true }],
"servers": {
"legendkeeper": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "LEGENDKEEPER_API_KEY", "ghcr.io/chase-roohms/legendkeeper-mcp:latest"],
"env": { "LEGENDKEEPER_API_KEY": "${input:lk-key}" }
}
}
}
Claude Code:
claude mcp add legendkeeper --env LEGENDKEEPER_API_KEY=lk_... -- uvx legendkeeper-mcp
**Cursor、Windsurf 等:**在客户端的 MCP 配置文件中使用与 Claude Desktop 相同的 command/args/env。
配置
所有内容均通过环境变量配置。CLI 标志(--transport、--host、--port、--read-only)会覆盖这些变量。
| 变量 | 默认值 | 描述 |
|---|---|---|
LEGENDKEEPER_API_KEY | — | 名为 default 的项目的 API 密钥。 |
LEGENDKEEPER_API_KEY_<NAME> | — | 其他世界。LEGENDKEEPER_API_KEY_HOMEBREW 会成为项目 homebrew。 |
LEGENDKEEPER_API_KEY_FILE、LEGENDKEEPER_API_KEY_<NAME>_FILE | — | 从文件读取密钥(Docker secrets)。 |
LEGENDKEEPER_DEFAULT_PROJECT | default,否则为第一个名称 | 未提供 project 时工具使用的世界。 |
LEGENDKEEPER_PROJECT_ID、LEGENDKEEPER_PROJECT_ID_<NAME> | 自动发现 | 跳过对密钥对应项目 ID 的查询。 |
LEGENDKEEPER_READ_ONLY | false | 仅注册读取工具;api_request 仅允许 GET。 |
LEGENDKEEPER_BASE_URL | https://www.legendkeeper.com | API 来源(用于代理和模拟服务)。 |
LEGENDKEEPER_TIMEOUT | 30 | 请求超时时间,单位为秒。 |
LEGENDKEEPER_MAX_RETRIES | 3 | 对 429/5xx/网络错误进行重试的次数。 |
LEGENDKEEPER_UPLOAD_ROOT | 不限(Docker 中为 /uploads) | upload_image 只能读取此目录下的文件。 |
LEGENDKEEPER_MAX_UPLOAD_MB | 25 | 图片大小上限。 |
LEGENDKEEPER_ALLOW_URL_UPLOADS | true | 允许 upload_image 从 http(s) URL 下载内容。 |
LEGENDKEEPER_LOG_LEVEL | INFO | 日志级别(日志写入 stderr;绝不会记录密钥)。 |
MCP_TRANSPORT | stdio | stdio 或 http(可流式传输的 HTTP)。 |
MCP_HOST | 127.0.0.1(Docker 中为 0.0.0.0) | HTTP 绑定地址。 |
MCP_PORT | 8000 | HTTP 端口。 |
MCP_PATH | /mcp | HTTP 端点路径。 |
MCP_AUTH_TOKEN、MCP_AUTH_TOKEN_FILE | — | 每个 HTTP 请求都必须提供 Bearer 令牌(/healthz 除外)。 |
MCP_ALLOW_UNAUTHENTICATED | false | 允许在非环回地址上无令牌使用 HTTP(不推荐)。 |
MCP_ALLOWED_HOSTS | — | 以逗号分隔的 host:port 值;启用 DNS 重绑定防护(例如 localhost:8000)。 |
多个世界
LEGENDKEEPER_API_KEY_HOMEBREW=lk_aaa
LEGENDKEEPER_API_KEY_STRAHD=lk_bbb
LEGENDKEEPER_DEFAULT_PROJECT=homebrew
每个工具都接受可选的 project 参数("strahd"),list_projects 会显示已配置的项目。
工具
| 区域 | 工具 |
|---|---|
| 发现 | list_projects、browse_tree、search、get_resource、list_tags、list_templates、list_calendars、list_members、list_assets |
| 读取 | read_document:将页面作为 Markdown、地图作为带坐标的要素、时间线作为泳道/事件、看板作为文本返回。format: "json" 会返回原始 API 数据。 |
| 页面 | write_page(模式:append、prepend、replace、replace_section、append_to_section) |
| 资源 | create_resource、create_resources(批量创建,最多 100 个;通过 key/parent_key 创建嵌套资源)、update_resource(名称、添加/移除标签、别名、图标、横幅、隐藏、锁定)、move_resource、delete_resource、restore_resource、create_from_template |
| 文档 | create_document(页面/地图/时间线/看板)、update_document、delete_document |
| 事实 | set_facts:在页面的信息框(若不存在则创建)或侧边栏中设置键值对形式的事实;null 会移除事实 |
| 地图 | create_map_feature(图钉/标签/区域/路径/文件夹,可使用经纬度或像素坐标,并链接到页面)、update_map_feature、delete_map_feature |
| 时间线 | create_timeline_event(根据时间线日历解析人类可读日期,按名称指定泳道;必要时自动创建泳道)、update_timeline_event、delete_timeline_event、create_timeline_lane |
| 资源文件 | upload_image(本地文件或 URL → 可在页面、横幅和地图图片中使用的资源 URL) |
| 其他 | api_request:可调用项目的任意 v3 端点(看板、日历、块级编辑、邀请、恢复等) |
该服务还会公开两个助手可读取的 MCP 资源:
legendkeeper://guides/markdown(Markdown 方言)和 legendkeeper://guides/style(根据 LegendKeeper 风格指南调整的标签、图标、信息框、图钉和事件规范)。写入工具都带有注释,客户端可据此请求确认;破坏性工具还要求设置 confirm: true。
如何编辑页面(Markdown)
LegendKeeper 将页面存储为由不同类型块组成的树,而非 Markdown。此服务支持双向转换:
| Markdown | LegendKeeper |
|---|---|
# … ######、段落、- 列表、1. 列表、> 引用、``` 代码块、---、GFM 表格 | 对应的块 |
- [ ] 任务 / - [x] 已完成 | 任务列表 |
> [!info]、[!note]、[!success]/[!tip]、[!warning]、[!error]/[!caution] | 提示框 |
> [!secret] | 秘密块(仅限 GM 查看,对玩家和公开页面隐藏) |
> [!expand] 标题 | 可折叠部分 |
**粗体**、*斜体*、~~删除线~~、`代码`、<u>、<sub>、<sup>、<span style="color:#…; background-color:#…"> | 文本标记和颜色 |
[[名称]]、[[名称|标签]]、[标签](lk://resources/<id>) | 提及(链接到其他页面) |
 | 图片(请先使用 upload_image 上传) |
```lk-block + JSON | 任意原始块(信息框、嵌入内容、计量条、集合等) |
读取页面时,Markdown 无法表达的块会以易读区域的形式显示:
**Infobox**
*Facts*
- **Ruler:** [Princess Bubblegum](lk://resources/pb…)
将这些标记行原样写回即可保留原始块。在该区域内的编辑会被忽略,并显示警告;请使用 set_facts,或通过 opaque_blocks: "json" 读取原始 JSON 后进行编辑。在 replace 模式下,内容未发生变化的段落和其他块会与原始内容匹配。它们的 ID 以及 Markdown 无法显示的样式(颜色、对齐方式、提示框图标)都会保留。
转换器使用 Hypothesis 进行模糊测试,确保往返转换完全一致,包括棘手的标点、嵌套标记和转义。
安全性
- 只读模式(
LEGENDKEEPER_READ_ONLY=true或--read-only)完全不会注册写入工具。 - 确认:
delete_*工具和api_requestDELETE 操作在没有confirm: true时会拒绝执行。删除的 资源会移至 LegendKeeper 的回收站,并可通过restore_resource恢复。 - 避免更新丢失:页面写入会发送所依据的版本(
If-Match),发生冲突时会基于最新读取结果重试一次。 - 重试时避免重复:每个 POST 请求都会携带幂等键。
- HTTP 模式:如果未设置
MCP_AUTH_TOKEN,则拒绝在非本地回环地址上监听;compose 仅绑定到127.0.0.1,使用只读文件系统、移除所有权限,并以非 root 用户运行。 - 上传:仅接受经内容检查的真实 JPEG/PNG/GIF/WebP 文件,且不得超过大小限制;还可使用
LEGENDKEEPER_UPLOAD_ROOT限制上传范围。 - 机密信息:密钥绝不会被记录到日志中(只会掩码显示为
lk_ab…wxyz),且只会发送给 LegendKeeper。 签名上传 URL 接收的是图片字节,而不是密钥。
故障排查
| 症状 | 解决方法 |
|---|---|
402 PAID_PLAN_REQUIRED | 项目所有者需要订阅 LegendKeeper 付费方案(试用不算)。 |
401 UNAUTHENTICATED | 密钥缺失、拼写错误、已撤销或过期。运行 legendkeeper-mcp check。 |
403 FORBIDDEN | 密钥(或其创建者)的角色权限过低,例如使用 Member 密钥访问隐藏资源或标签。 |
403 WRONG_PROJECT | 密钥只能用于其所属的世界;每个世界需配置一个密钥。 |
429 RATE_LIMITED | LegendKeeper 对每个密钥的限制为每分钟 120 次写入和 300 次请求。等待一分钟;使用 create_resources 批量处理。 |
图片因 VALIDATION_ERROR 被拒绝 | 图片 URL 必须是 LegendKeeper 资源 URL;请先使用 upload_image。 |
| 客户端未显示工具 | 检查客户端的 MCP 日志。手动运行已配置的命令;配置错误会输出到 stderr,退出码为 2。 |
开发
uv sync # create .venv with dev dependencies
uv run pytest # full test suite (downloads the OpenAPI spec once into tests/.cache)
uv run ruff check . && uv run ruff format --check . && uv run mypy
uv run legendkeeper-mcp # run from source
npx @modelcontextprotocol/inspector uv run legendkeeper-mcp # poke at it interactively
测试层:
-
tests/test_markdown*.py:转换器单元测试和 Hypothesis 属性测试(往返转换必须完全一致)。 -
tests/test_tools.py:通过真实 MCP 客户端会话,针对tests/fake_lk.py中的内存版 LegendKeeper,对每个工具进行端到端测试。如果 OpenAPI 规范可用,每个请求都必须命中真实路由,且请求体必须符合架构;每个模拟响应也必须符合文档规定的响应架构。CI 要求提供该规范(LK_REQUIRE_SPEC=1)。 -
tests/test_live.py:针对真实 API 的可选冒烟测试。写入测试会在一个[mcp-test] …沙盒资源下创建所有内容,并在之后将其删除:LEGENDKEEPER_LIVE_TESTS=1 LEGENDKEEPER_LIVE_WRITE=1 LEGENDKEEPER_API_KEY=lk_... uv run pytest tests/test_live.py -v
项目结构:
src/legendkeeper_mcp/
client.py async HTTP client (auth, retries, idempotency, pagination, errors)
config.py environment configuration
service.py per-project sessions, project-id discovery, cached resource index
documents.py reading/writing documents (page Markdown, maps, timelines, boards)
markdown/ Markdown <-> block conversion (parse, render, merge)
tools/ MCP tool definitions
server.py server assembly; http_app.py streamable HTTP + bearer auth; cli.py entry point
发布
CI 会在每次推送和 PR 时运行:包括 lint、mypy、测试(覆盖 Linux/macOS/Windows,Python 3.11-3.13)、构建 wheel,以及运行 stdio/HTTP 冒烟测试的 Docker 构建。
要发布,请在 pyproject.toml、src/legendkeeper_mcp/__init__.py 和 server.json 中更新 version(服务和软件包版本以及镜像标签),更新 CHANGELOG.md,提交,然后运行 git tag v0.2.0 && git push --tags。发布工作流 随后会:
- 验证标签与软件包版本一致,并重新运行 CI,
- 使用可信发布发布到 PyPI,
- 将带有 SBOM 和来源证明的多架构(amd64/arm64)镜像推送到
ghcr.io/<owner>/legendkeeper-mcp, - 使用构建好的发行包创建 GitHub 发布版本,
- 将
server.json以io.github.chase-roohms/legendkeeper-mcp的名称发布到官方 MCP Registry(使用 GitHub OIDC 登录,无需密钥)。注册表通过本 README 顶部的mcp-name注释验证所有权;PyPI 会将该注释显示为软件包描述,而 Docker 镜像则通过io.modelcontextprotocol.server.name标签进行验证。
一次性设置:在 PyPI 上为项目 legendkeeper-mcp 添加一个待处理的可信发布者,并指定此仓库、工作流 release.yml 和环境 pypi;然后在仓库设置中创建一个 pypi 环境。GHCR 无需设置。首次推送后,在 GitHub 软件包设置中将该软件包设为公开。
许可证
MIT。LegendKeeper 是其各自所有者的商标;本项目仅使用其公共 API。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。