Skip to main content

khwan-mcp

Durable memory that survives the session. An MCP server that plugs Khwan — a pure AI-memory layer — into Claude Code, Claude Desktop, or any MCP client.

Khwan never runs a model. The client is the model. Its job is to persist and distil what matters into a brain you can recall in a later session or seed a subagent with — a compact, bounded set of facts instead of a replayed transcript. One account can hold many isolated cores (brains), and — on paid plans — an isolated sub-brain per end-user.

How it saves tokens (and where it doesn't)

Be honest about the mechanism — an MCP adds to a host's context, it cannot replace the transcript the host already sends. So:

  • Within one hot session, it does not save tokens. Claude Code caches its growing history (cache reads ≈ 0.1×), so re-injecting memory every turn only adds. Don't do that here.
  • Across sessions and subagents, it does. A cache dies in minutes; a session ends. Khwan persists distilled facts so the next run recalls them cheaply — no cold-replay of an old transcript, and facts that already scrolled out of context are retrievable again.

The token-smart pattern: seed once, remember durable facts (below), rather than running the full loop on every turn of a caching host. The full prepare → record loop still shines in a custom agent on a non-caching host, where replacing history with distilled memory bounds per-turn cost directly.

Install

pip install khwan-mcp          # or: uvx khwan-mcp

Connect to Claude Code

claude mcp add khwan --scope project \
  -e KHWAN_CORE=default \
  -- khwan-mcp

--scope project writes .mcp.json into the repo, so the setting travels with the project. Note what is not in that command: the key.

Keeping the key out of the repo

claude mcp add -e KHWAN_API_KEY=… writes the literal value into .mcp.json — a file whose whole point is being committed. Two ways to avoid that, and the second is the one that works everywhere:

Shell environment. Leave KHWAN_API_KEY out of the config entirely and export it in the shell that launches claude. The server inherits it.

export KHWAN_API_KEY=kwk_live_xxx

A launcher (works in the desktop app too). A desktop app is started from a dock or menu, not a login shell, so it inherits none of your shell exports and the approach above silently yields no key. Read it from a file instead:

mkdir -p ~/.khwan && chmod 700 ~/.khwan
printf 'KHWAN_API_KEY=kwk_live_xxx\n' > ~/.khwan/env && chmod 600 ~/.khwan/env

cat > ~/.khwan/khwan-mcp <<'SH'
#!/bin/sh
set -a
[ -f "$HOME/.khwan/env" ] && . "$HOME/.khwan/env"
set +a
exec khwan-mcp "$@"
SH
chmod 700 ~/.khwan/khwan-mcp

Then point the config at the launcher and keep only non-secret settings inline:

claude mcp add khwan --scope project \
  -e KHWAN_CORE=acme -e KHWAN_USER=Web \
  -- ~/.khwan/khwan-mcp

.mcp.json is now safe to commit, and every new repo costs two lines instead of a pasted key. Anyone else on the team writes their own ~/.khwan/env.

One brain per project

Memory is only useful if the right project's memory comes back. Two axes, and both give complete isolation:

selected by costs
core KHWAN_CORE one of your plan's cores
sub-brain KHWAN_USER (with a core) nothing — unlimited on paid plans

A sub-brain is a full separate brain, not a filter: account::acme::@Web shares nothing with account::acme::@Api. So a client with several repositories can be one core with a sub-brain each, rather than a core each:

# in ~/code/acme-web
claude mcp add khwan --scope project -e KHWAN_CORE=acme -e KHWAN_USER=Web -- ~/.khwan/khwan-mcp
# in ~/code/acme-api
claude mcp add khwan --scope project -e KHWAN_CORE=acme -e KHWAN_USER=Api -- ~/.khwan/khwan-mcp

Cores must exist before you point at one — an unknown core answers 404. Create them in the dashboard. Sub-brains are created on first write.

Recommended pattern (token-smart)

On a caching host like Claude Code, prefer seed + remember over the per-turn loop:

  1. Seed at the start of a session or subagent:

    "Call khwan_recall(query="<the task>") and use the returned seed_text as context."

  2. Remember durable facts as they emerge:

    "That's a standing decision — call khwan_remember(fact="…")."

Reinforce it in your project's CLAUDE.md, e.g.:

- At the start of a task, call `khwan_recall` to seed relevant memory.
- When a durable decision/preference/fact emerges, call `khwan_remember`.
- Don't call prepare/record every turn — it adds tokens without saving them here.

Seeding a subagent is where the win is clearest — hand it a bounded brief instead of the whole transcript:

"Recall deploy memory with khwan_recall(query="deploy runbook"), then spawn a subagent whose brief is that seed_text plus the task."

Connect to Claude Desktop

Claude Desktop and Claude Code keep separate MCP configuration — a server added to one is invisible to the other, and claude mcp add does not touch this file. Add to claude_desktop_config.json:

{
  "mcpServers": {
    "khwan": {
      "command": "/Users/you/.khwan/khwan-mcp",
      "env": {
        "KHWAN_CORE": "acme",
        "KHWAN_USER": "Web"
      }
    }
  }
}

Use an absolute path: a desktop app does not get your shell's PATH either, so a bare khwan-mcp may not resolve. One core is selected for the whole app — there is no per-project switch here, so choose a broad one.

Configuration (environment)

Var Required Purpose
KHWAN_API_KEY yes Your key from the Khwan dashboard (kwk_live_…).
KHWAN_CORE no Select an isolated core/brain (default: the account's default core).
KHWAN_USER no Isolated sub-brain per end-user (paid); sets X-Khwan-User.
KHWAN_BASE_URL no Override the API base — e.g. http://127.0.0.1:8010 for a local engine.

Tools

Tool When
khwan_recall(query, limit=3) seed a session/subagent — synthesised lessons + up to 3 relevant facts, as seed_text.
khwan_remember(fact) persist a durable fact/preference for future sessions.
khwan_prepare(input) full loop, before answering — memory context + a turn_token.
khwan_record(turn_token, answer) full loop, after answering — persists the turn so Khwan learns.
khwan_memory(limit=20) inspect what the brain currently remembers.
khwan_cores() list the isolated cores on the account.

khwan_recall / khwan_remember are the token-smart pair for a caching host; khwan_prepare / khwan_record are the full loop for custom agents (pass the exact turn_token from prepare back into record).

What comes back, and what an empty answer means

khwan_recall returns at most three facts — that ceiling is the server's, so limit can lower it but not raise it — plus any lessons synthesis has distilled from many past turns. Lessons lead the seed_text: a rule earned over months outranks a single turn that happens to sit nearby in the index.

Retrieval applies a relevance floor, so an empty facts is an answer: the brain has nothing close to this question. Read it as "not known here" rather than as a failure, and do not fill the gap by leaning on whichever fact was nearest.

The floor is deliberately loose, because a memory wrongly dropped is invisible while a memory wrongly kept is not. Expect a returned fact to be plausibly related, not certainly relevant — read it before relying on it.

Seeding a brain from work you have already done

A new brain knows nothing, so its first weeks of recall are thin — while the answers are often already sitting in the host's own transcripts, unread. examples/backfill/ replays Claude Code transcripts into a brain: deterministic, no model calls, dry-run by default.

python3 examples/backfill/backfill_claude_code.py --map cores.json

Always-on memory (Claude Code hooks)

The tools above are called when Claude decides to. For deterministic memory — no reliance on the model — use the hook preset in examples/claude-code-hooks/: a UserPromptSubmit hook injects memory on every prompt and a Stop hook records every answer.

⚠️ On a caching host this is the thorough option, not the cheap one — it adds per-turn tokens. Prefer it when recall reliability matters more than token cost (or on a non-caching client); otherwise use khwan_recall at session start.

Source

github.com/khwanlabs/khwan-mcp — this server runs on your machine, with your key, reading what you type. Read it before you install it.

License

MIT — © Khwan Labs. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

khwan_mcp-0.3.2.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

khwan_mcp-0.3.2-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file khwan_mcp-0.3.2.tar.gz.

File metadata

  • Download URL: khwan_mcp-0.3.2.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for khwan_mcp-0.3.2.tar.gz
Algorithm Hash digest
SHA256 7419d8721f97841b8297389726d0adcc400d805a6ff851cf2f58d92fe2d0582c
MD5 f2e775b6b85483b12db9f3a62348d6f8
BLAKE2b-256 26d3999f9234cc0eb2a815189cdb301476d41c1297d5fc14a6e1ea7549203a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for khwan_mcp-0.3.2.tar.gz:

Publisher: publish.yml on khwanlabs/khwan-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file khwan_mcp-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: khwan_mcp-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for khwan_mcp-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0237e0c93001e462bea03038a84cdafc0bedb34f8931917533665f521550d3f4
MD5 7d62c8a9a3cdba09ab1e6a78efad74f7
BLAKE2b-256 51a645b155e64f4487402f17794147fce024b96824ef18c1a9429880ab42b894

See more details on using hashes here.

Provenance

The following attestation bundles were made for khwan_mcp-0.3.2-py3-none-any.whl:

Publisher: publish.yml on khwanlabs/khwan-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

This release

0.3.2 This release

2 files

0.3.1

2 files

0.3.0

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page