@onedose/lumen-mcp
v0.8.0
Published
MCP server + local-mirror CLI for managing and syncing Lumen docs from Claude Code via the /api/v1 HTTP API.
Readme
lumen-mcp
An MCP server that lets Claude Code manage Lumen — create/edit/publish/search/
organize docs and run the agent — by calling Lumen's token-authenticated
/api/v1 HTTP API. It holds no business logic; every tool is a thin wrapper over
an endpoint, so the Lumen service layer stays the single source of truth for
storage coordination and the visibility security pivot.
0. Non-technical install (sales / field users)
Goal: the person pastes one line into Claude Code's terminal and restarts — no repo, no Node build, no editing shell profiles. Each person gets their own token so their activity is attributable and individually revocable.
Per person, an admin runs the generator (prints a register-this pair + a ready-to-send message):
cd mcp
npm run mint:token -- "Jane Doe"Then:
- Register the token it prints — append the
jane-doe:<token>pair to the app'sLUMEN_API_CLIENTSenv var and redeploy (see §1). - Send the person the generated message. They paste its one command:
…restart Claude Code, done. Revoke later by removing just their pair and redeploying.claude mcp add --scope user lumen \ --env LUMEN_API_URL=https://lumen.myonedose.com \ --env LUMEN_API_TOKEN=<their-token> \ -- npx -y @onedose/lumen-mcp
Prerequisite (one-time): the one-liner runs the server via
npx @onedose/lumen-mcp, so the package must be published to npm first (npm publishfrommcp/—publishConfig.accessis alreadypublic). Until then, use the from-repo install in §3.
Claude Desktop (one line, no JSON editing)
claude mcp add configures Claude Code, not the Claude Desktop app —
Desktop reads claude_desktop_config.json. Instead of hand-editing that file,
run the built-in installer, which merges a lumen entry into it (preserving any
other servers) and backs up the previous file:
npx -y @onedose/lumen-mcp install --token <their-token>Then fully quit and reopen Claude Desktop. Options: --url <url> (default
https://lumen.myonedose.com, or $LUMEN_API_URL), --token falls back to
$LUMEN_API_TOKEN, --name to use a key other than lumen. The installer
finds the right config path per-OS (macOS ~/Library/Application Support/Claude,
Windows %APPDATA%\Claude, Linux ~/.config/Claude).
1. Configure the API (server side)
The /api/v1 routes are disabled until a token is set. In the Lumen app's env
(.env for local dev, Lambda env in prod):
LUMEN_API_TOKEN=<a long random secret>
# optional — id stamped as ownerSub on docs created via the API
LUMEN_API_OWNER_SUB=api-service-accountRotate by changing the value. Unset ⇒ all /api/v1 requests return 401.
2. Build the MCP server
cd mcp
npm install
npm run build # tsc → dist/index.js3. Register with Claude Code
One-liner (recommended). From mcp/, with the secret in your shell env — this
installs deps, builds, and registers the server at user scope (every project):
LUMEN_API_TOKEN=<same secret as the server> npm run install:claudeOverride the target with LUMEN_API_URL=http://localhost:3000 LUMEN_API_TOKEN=… npm run install:claude
to manage a local dev instance (defaults to https://lumen.myonedose.com). The
script resolves the absolute dist/index.js path for you.
claude mcp add --scope user lumen \
--env LUMEN_API_URL=https://lumen.myonedose.com \
--env LUMEN_API_TOKEN=<same secret as the server> \
-- node /absolute/path/to/Lumen/mcp/dist/index.js(The base URL is the origin only — no /internal or /api/v1 suffix.)
Project scope (committed to the Lumen repo, no secrets). Create .mcp.json
at the repo root — Claude Code will prompt to approve it, and read the secret
from your shell env so nothing sensitive is committed:
{
"mcpServers": {
"lumen": {
"command": "node",
"args": ["mcp/dist/index.js"],
"env": {
"LUMEN_API_URL": "${LUMEN_API_URL:-https://lumen.myonedose.com}",
"LUMEN_API_TOKEN": "${LUMEN_API_TOKEN}"
}
}
}
}LUMEN_API_URL defaults to the deployed CloudFront origin
(https://lumen.myonedose.com) to manage the live knowledge base;
set it to http://localhost:3000 for local dev (SQLite + filesystem).
Note:
claude mcp addand.mcp.jsonare Claude-Code startup config. They take effect on the next session, and the CLI may ask you to confirm the new server.
3b. Ingraining Claude to use Lumen (assisted behavior)
Two pieces make Claude reach for Lumen, not just have the tools:
- Skill —
.claude/skills/lumen-docs/SKILL.md(committed in this repo). Active automatically when working in the Lumen repo. To make it global (every project), copy it into your user skills dir:cp -R .claude/skills/lumen-docs ~/.claude/skills/lumen-docs - Standing rule —
~/.claude/rules/lumen-docs.md(a global rule, loaded into every project) tells Claude to search Lumen first, store internal docs there as drafts, and confirm before publishing. Already installed.
The skill enforces: search-first → store-as-draft → confirm before publish.
4. Inspect / smoke test
LUMEN_API_URL=http://localhost:3000 LUMEN_API_TOKEN=<secret> \
npx @modelcontextprotocol/inspector node dist/index.jsTools
| Tool | Endpoint |
|---|---|
| lumen_list_docs | GET /api/v1/docs (space= to scope to one department) |
| lumen_get_doc | GET /api/v1/docs/:id (format=text for clean prose) |
| lumen_create_doc | POST /api/v1/docs |
| lumen_update_doc | PATCH /api/v1/docs/:id |
| lumen_set_visibility | POST /api/v1/docs/:id/visibility |
| lumen_delete_doc | DELETE /api/v1/docs/:id |
| lumen_move_doc | POST /api/v1/docs/:id/move |
| lumen_duplicate_doc | POST /api/v1/docs/:id/duplicate |
| lumen_search | GET /api/v1/search (mode=keyword\|semantic\|hybrid, default hybrid; space= to scope to one department) |
| lumen_ask | POST /api/v1/ask (RAG answer with citations; space= to scope sources) |
| lumen_list_spaces | GET /api/v1/spaces (departments — discover slugs for the space= filter) |
| lumen_context | GET /api/v1/context (KB orientation map) |
| lumen_reindex | POST /api/v1/reindex (rebuild semantic index) |
| lumen_sync_catalog | POST /api/v1/catalog/sync (mirror plugin-marketplace repo) |
| lumen_get_doc_by_slug | GET /api/v1/docs/by-slug/:slug |
| lumen_related_docs | GET /api/v1/docs/:id/related (more like this) |
| lumen_doc_links | GET /api/v1/docs/:id/links (graph: in/outbound) |
| lumen_doc_section | GET /api/v1/docs/:id/section?q= (relevant span only) |
| lumen_get_docs | POST /api/v1/docs/batch (multi-fetch) |
| lumen_share_doc | POST /api/v1/docs/:id/share (mint share link) |
| lumen_changes | GET /api/v1/changes?since= (change feed) |
| lumen_gaps | GET /api/v1/gaps (what the KB can't answer) |
| lumen_list_folders | GET /api/v1/folders |
| lumen_create_folder | POST /api/v1/folders |
| lumen_rename_folder | PATCH /api/v1/folders/:id |
| lumen_delete_folder | DELETE /api/v1/folders/:id |
| lumen_upload_asset | POST /api/v1/assets |
| lumen_ingest_file / lumen_ingest_files / lumen_ingest_status | POST (one / many) / GET /api/v1/ingest |
| lumen_list_skills / lumen_get_skill | GET /api/v1/skills[/:slug] |
| lumen_save_skill / lumen_delete_skill | POST / DELETE /api/v1/skills |
| lumen_get_memory / lumen_write_memory_index | GET / PUT /api/v1/memory |
| lumen_get_memory_note / lumen_write_memory_note / lumen_delete_memory_note | /api/v1/memory/notes[/:slug] |
| lumen_run_agent | POST /api/v1/agent |
| lumen_agent_status | GET /api/v1/agent?run= |
Auth model
Static bearer token — the "private app token" pattern, right for a single operator. A multi-user hosted deployment would add OAuth 2.1 as a second auth mode on the API; the tools above would not change.
