MisakaNet MCP Server¶
MisakaNet exposes its lesson knowledge base via the Model Context Protocol, enabling AI assistants to search and retrieve engineering lessons in real time.
Quick Start¶
1. Prerequisites¶
cd MisakaNet
# Homebrew/Debian/Fedora Python refuse a system-wide install (PEP 668), so this
# creates a virtualenv first. Harmless everywhere else.
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
2. Test the server¶
3. Connect from Claude Code¶
Add to ~/.claude.json (user/local scope) or .mcp.json at the project root (project scope, committable):
{
"mcpServers": {
"misakanet": {
"command": "python3",
"args": ["/path/to/MisakaNet/scripts/mcp_server.py"]
}
}
}
不是
settings.json。 Claude Code 从~/.claude.json(local/user scope)和项目根的.mcp.json(project scope)读 MCP servers;~/.claude/settings.json放的是 hooks、permissions、env。这一页此前写错成settings.json(安装器npx @misaka-net/misakanet-setup写的是~/.claude.json,两边对不上);把mcpServers放错文件的症状是/mcp里什么都看不到。 官方 scope 表:https://docs.claude.com/en/docs/claude-code/mcp更省事的路径:整仓都不用 clone ——
claude mcp add --transport http misakanet https://misakanet.org/mcp直接接远端端点(托管工具集,读不限次数免注册)。
4. Connect from Cursor¶
Create .cursor/mcp.json in your project root:
{
"mcpServers": {
"misakanet": {
"command": "python3",
"args": ["/path/to/MisakaNet/scripts/mcp_server.py"],
"env": {}
}
}
}
5. Connect from Claude Desktop¶
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"misakanet": {
"command": "python3",
"args": ["/path/to/MisakaNet/scripts/mcp_server.py"]
}
}
}
Which surface?¶
This page documents the local stdio server, because that is what the install steps above configure.
It is not the same surface as the hosted endpoint that most agents are pointed at by the README and
AGENTS.md, and the difference is the thing a reader gets wrong:
| surface | how you reach it | tools | resources | prompts |
|---|---|---|---|---|
| local stdio — what this page installs | python3 scripts/mcp_server.py |
11: misakanet_search, misakanet_get_lesson, misakanet_submit_usage, misakanet_submit_intake, misakanet_write_lesson, misakanet_preflight, misakanet_usage_status, misakanet_register, misakanet_memory_context, misakanet_me_events, misakanet_me_inbox |
5 (below) | 3 (below) |
| local HTTP (optional) | python3 scripts/mcp_http_server.py |
6: misakanet_search, misakanet_get_lesson, misakanet_submit_intake, misakanet_submit_usage, misakanet_usage_status, misakanet_register |
3 | 2 |
| hosted — what agents usually call | https://misakanet.org/mcp |
8: the stdio set minus the three local-only tools misakanet_submit_usage, misakanet_usage_status, misakanet_memory_context |
none | none |
The hosted endpoint exposes tools only. It handles tools/list and tools/call and nothing else
(measured 2026-09-25), so an MCP client that calls resources/list or prompts/list against
misakanet.org/mcp gets an error rather than the tables below. misaka://… URIs and prompts are a
local-only feature; the hosted surface's tool set is the eight names above.
Since 2026-09-30 (owner decision D4=A, issue #2000) the hosted set is a subset of the local one:
the local stdio server registers misakanet_me_events too, as a proxy of the hosted tool (the evidence it
returns is aggregated server-side), and the only difference left is the three tools that read the local
checkout — misakanet_submit_usage, misakanet_usage_status, misakanet_memory_context. Before that,
misakanet_me_events was hosted-only, so the skill's reuse-evidence step answered "Unknown tool" on a
local install. .codex-plugin/plugin.json declares both sets, and tests/test_mcp_capability_parity.py
checks them against this server and the worker.
misakanet_me_inbox is a proxy too, and for the same reason: intake status lives in the worker's
D1/KV stores. The local server answers an intake that is still in this checkout's contribution
queue from the queue, and forwards everything else to the hosted tool — so the same id gets the
same answer on both surfaces. Before 2026-11-03 it called a /api/inbox route that does not
exist and answered not_found for every hosted lookup (#3577).
The three sets are pinned against their sources by tests/test_mcp_doc_surface.py, so a tool added
without a line here fails the suite rather than leaving a reader with a wrong map.
Available Tools¶
The three below are the ones with parameters people ask about; the full set is in the table above (which also says which surface has which).
| Tool | Description | Parameters |
|---|---|---|
misakanet_search |
Search lessons by query | query (required), domain?, top? (default 5) |
misakanet_get_lesson |
Get a specific lesson | path or id (required) |
misakanet_submit_usage |
Report lesson usage — outcome feeds live reuse signals (solved → helpful vote; partial/not-helpful → feedback) | lesson_id (required), tool?, outcome? |
Reading and searching need no node. The write tool (misakanet_write_lesson) needs a node and a
token — one registration gets both. misakanet_preflight is read-only and open, so an anonymous
connector can call it (rate-limited): https://misakanet.org/register/
The registration response's identity fields¶
misakanet_register answers with {node_id, token, registered_at, agent_type, reused} and reused
is always present — it is the one field that says whether the client_id you sent was recognised:
reused |
Meaning | What to do |
|---|---|---|
true |
an existing node was found for this client_id, and its token was renewed |
keep using it; this is the renewal path |
false |
this call minted a new node | the client_id you sent was not recognised, so this token is not attached to whatever history you thought you were reusing |
The false case used to be indistinguishable from a server that never implemented the field, because
it was simply omitted (#4072). The server cannot tell you which id was the right one — that mapping
lives on your side — so a client that stores its client_id somewhere durable (not in a hint header,
which the endpoint treats as a hint and never as identity) is the only way to keep one node across
token expiries.
The name is not the key (2026-10-31). A renewal now expects the token it was given, sent the normal way:
# renewal: the same client_id AND the token you already hold
curl -sS https://misakanet.org/mcp -H "Authorization: Bearer $MISAKANET_TOKEN" ... -d '… "misakanet_register", "arguments": {"client_id": "8f14e45f-…"} …'
| what you send | what happens |
|---|---|
client_id + a valid token for that node |
renewed, reused: true — the supported path |
client_id alone, during the grace window |
renewed, reused: true, plus deprecated telling you to add the token |
client_id alone, strict mode |
{error, code: "client_id_proof_required"} and no token |
a fresh client_id |
a new node, as before |
The reason is one sentence: an agent's client_id appears in configs, transcripts and tutorials, so a
value that appears in prose cannot be the only thing standing between a stranger and a 30-day write
token.
Reading errors¶
misakanet_get_lesson answers {error, code} when it cannot return a lesson, and the code is what says
what to do next:
| Code | Meaning |
|---|---|
lesson_not_found |
No such lesson (id or path, on main or data). Search instead of retrying. |
invalid_lesson_path |
The argument is not a lesson reference. path must be a file under lessons/ ending in .md — other repository files are not readable through this tool. |
internal_error |
A service fault. Retrying is reasonable. |
Added 2026-09-25 (B35), because those last two were one code: a missing lesson answered internal_error
— the message for a transient fault — so a caller that obeyed it retried a 404 forever, and a caller that
quoted it reported MisakaNet as down for its own typo. In the same call path went into the GitHub
contents URL unvalidated, so path=docs/CI.md returned that file.
When a call fails: fetch failed is not the same as "the service is down"¶
A client-side transport error (fetch failed, UND_ERR_HEADERS_TIMEOUT, a JSON-RPC timeout) is the
client giving up. Measured on 2026-10-29 (#4052): one agent's whole session reported "the endpoint
does not work" while initialize answered in ~2 s, submit_intake succeeded, and misakanet_search
swung from 1.3 s to 62 s on the same query. Every one of those calls reached the server; the
client stopped waiting.
What to do with that knowledge:
- retry the call once, a few seconds later.
misakanet_search,misakanet_get_lessonandmisakanet_me_inboxare idempotent reads — a retry cannot double-apply anything. A singlefetch failedis not evidence about the service; two in a row after a wait is worth reporting. - do not conclude the endpoint is down, and do not degrade to "I could not find anything" — that is a different claim from "the search did not answer in time".
- the server-side numbers are in
GET /api/search-signals/stats(latencyhistogram, buckets<1s / 1–3s / 3–10s / 10–30s / 30–60s / ≥60s), andpython3 scripts/bench_search_latency.py --remotereproduces the client's own view in one command.
Resources¶
Local stdio surface only — the hosted endpoint exposes no resources (see Which surface?).
| URI | Description |
|---|---|
misaka://lessons/index |
Browse all published lessons (core + contrib) |
misaka://protocol/overview |
failure-memory protocol config (trust tiers, rings, scoring) |
misaka://docs/readme |
Project overview and quickstart |
misaka://docs/faq |
Troubleshooting FAQ |
misaka://docs/changelog |
Latest release notes |
Prompts¶
Local stdio surface only — the hosted endpoint exposes no prompts (see Which surface?).
| Name | Description | Arguments |
|---|---|---|
search_lesson |
Guided lesson search | query (required), domain? |
triage_failure |
Structured failure triage | error (required), context? |
release_audit |
Release readiness check | version (required) |
Search Scopes¶
By default, the server searches core and contrib lessons only. Drafts are excluded to avoid surfacing unverified content.
Search Sources¶
The server uses two search backends (auto-detected):
- SAG-Lite (SQLite) — fast, pre-built index at
data/sag.db - BM25 (fallback) — real-time search via
misakanet.search.engine
If neither is available, the server returns an error suggesting index rebuild:
Smoke Test¶
Run the built-in smoke test to verify your setup:
This tests:
- search returns results with path and status at every detail level, plus freshness
(fresh / recent / aging / stale) at compact and summary. There is no badge
field — an earlier version of this line promised one, and the surface never sent it; the
freshness tier is a plain label. (The offline CLI's search_knowledge.py --json does emit a
badge, inside a freshness object — but that is a score, not this age bucket, so the two
freshness fields are not comparable: see docs/cli-reference.md.)
- get_lesson returns lesson content
- Default scope excludes drafts
Security & Boundaries¶
- Not a skill marketplace. MisakaNet is a failure memory network — lessons come from real debugging sessions, not curated skill packs.
- Read-only by default. Tools like
misakanet_searchandmisakanet_get_lessonare read-only.misakanet_submit_usagereports the lesson outcome to the public worker endpoint (/api/helpfulfor solved,/api/feedbackfor partial/not-helpful) — offline-safe: it falls back to local logging when the worker is unreachable. - No raw sensitive content uploaded. Search queries stay local. Lesson content is public (open-source repo). Usage reports contain only lesson ID + outcome, not source code or error logs.
- Write operations require explicit confirmation.
misakanet_write_lessonandmisakanet_submit_intakecreate GitHub issues only when called — nothing is sent without an explicit tool call.
Glama¶
MisakaNet is listed on Glama.ai for MCP server discovery.