bantamkit — memory MCP server for Claude Code, Cursor, VS Code Copilot and Claude Desktop (Python)
bantamkit is a Python MCP server on PyPI that gives coding agents a per-person
memory store, JSON Schema validation, shift-work accounting, a token ledger and a
skill-catalogue auditor. It works with Claude Code, Claude Desktop, Cursor, GitHub
Copilot in VS Code and any stdio MCP client. Install it with pip install "bantamkit[mcp]";
after one install it starts offline.
The same server in pure Node is on npm as
bantamkit-mcp. The two share a memory store on
disk and a conformance suite holds them to the same answers, so install whichever your host makes
easy.
Contents
| Topic | What you'll find |
|---|---|
| Install the MCP server | Try it with pipx run; the [mcp] extra |
| Install once, run offline | A venv you keep, and a wheelhouse for machines with no network |
| Run with pipx at every launch | The online form, and when it fails offline |
| Connect it to a host | The same five steps for every host |
| Connect to Claude Code | --install claude, claude mcp remove |
| Connect to Claude Desktop | claude_desktop_config.json per OS |
| Connect to Cursor | ~/.cursor/mcp.json |
| Connect to VS Code (GitHub Copilot) | mcp.json with the servers key |
| Connect other MCP clients | Any stdio host |
| Configuration | Every flag and environment variable, with its default |
| Update | --update, pipx and uv, then restart |
| Troubleshooting | Timeouts, refusals, the wrong store |
| What it serves | The 12 tools, one prompt, two resource templates |
| Requirements | Python and dependencies |
| The asset pack | --assets-root and BANTAMKIT_ASSETS |
The operator CLI: python -m bantamkit.memory |
status, lint, compact, archived, archive, restore |
| Share a store with the Node server | One on-disk format, two servers |
| Where the Python and Node servers differ | pdf/.doc/.rtf, the CLI name, build_id |
| Development | Clone, test, lint, conformance |
| Documentation | Links to the full docs on GitHub |
Install the MCP server
To try it:
pipx run --spec "bantamkit[mcp]" bantamkit-mcp --assets-root
The [mcp] extra pulls the MCP SDK. Without it you still get the library, but the server exits
with bantamkit-mcp needs the MCP extra: pip install "bantamkit[mcp]". The uv equivalent,
uvx --from "bantamkit[mcp]" bantamkit-mcp, is documented but was not measured here.
A host launches the server every session, so what matters is whether each launch needs the network. For a host, use install once.
Install once, run offline
Recommended.
python -m venv <env>
<env>/bin/pip install "bantamkit[mcp]"
<env>/bin/bantamkit-mcp --install cursor # or claude, claude-desktop, copilot
--install records the venv's console script by absolute path with "args": [], so no launch
needs the network or your shell's PATH. Measured on macOS arm64: that command served 12 tools
under a GUI app's PATH, /usr/bin:/bin:/usr/sbin:/sbin. The Windows layout (<env>\Scripts\)
was not measured.
No network on the target machine? Carry a wheelhouse. Download on a connected machine with
the same OS, CPU architecture and Python minor version (some wheels, such as
pydantic_core, are built for one platform only), copy wheels/ across, then install from it:
python -m pip download "bantamkit[mcp]==0.34.0" -d wheels
python -m venv <env>
<env>/bin/pip install --no-index --find-links wheels "bantamkit[mcp]==0.34.0"
<env>/bin/bantamkit-mcp --install cursor
To move to a newer version, repeat both steps with the new version number. Measurements: docs/install.md → Python package: measured detail.
Run with pipx at every launch
{"mcpServers": {"bantamkit": {"command": "pipx", "args": ["run", "--spec", "bantamkit[mcp]", "bantamkit-mcp"]}}}
One config line and no venv to keep, but it works offline only while pipx's cache lasts.
Measured with the network cut: on a pipx home that had never run it, it exited 1 in 1.33 s; after
one online run, it exited 0 in 0.47 s. It needs the package index on a new machine, after the
cache is cleared, and whenever pipx decides its cached environment is stale (pipx's policy, not
measured). For Claude Code:
claude mcp add bantamkit -s user -- pipx run --spec "bantamkit[mcp]" bantamkit-mcp.
Connect it to a host
bantamkit-mcp --install <host> (claude, claude-desktop, copilot, cursor) writes the
entry, pointing at the console script you ran. It never prompts, so it behaves the same in a
terminal, in CI and inside another agent. For the three JSON hosts it backs the file up first as
<name>.backup-<date>, keeps the file's permissions, refuses a file that does not parse, and
refuses an entry that differs unless you pass --force.
Each host below has the same steps: 1 command, 2 file, 3 entry, 4 confirm,
5 undo or re-run. The entry's command and args depend on the install route:
| Route | command |
args |
|---|---|---|
| Python venv, install once | /absolute/path/to/env/bin/bantamkit-mcp |
[] |
| pipx at every launch | pipx |
["run", "--spec", "bantamkit[mcp]", "bantamkit-mcp"] |
| npm, install once | see the npm package |
To check a recorded command, run it in a terminal: with nothing on stdin it prints
usage: bantamkit-mcp ….
Connect to Claude Code
-
Command:
<env>/bin/bantamkit-mcp --install claude -
File: none edited directly. It runs
claude mcp add bantamkit -s user -- <command>(user scope, every project), because~/.claude.jsonis the host's file and holds state that is not MCP configuration. -
Entry: printed as
ran : claude mcp add bantamkit -s user -- <env>/bin/bantamkit-mcp. -
Confirm:
claude mcp listlistsbantamkit. In a session, ask the agent to callbantamkit_status. -
Undo / re-run:
--forcedoes not reach Claude Code, and a second add fails withMCP server bantamkit already exists in user config. Remove first:claude mcp remove bantamkit -s user <env>/bin/bantamkit-mcp --install claude
Connect to Claude Desktop
-
Command:
<env>/bin/bantamkit-mcp --install claude-desktop -
File: macOS
~/Library/Application Support/Claude/claude_desktop_config.json· Windows%APPDATA%\Claude\claude_desktop_config.json· Linux~/.config/Claude/claude_desktop_config.json -
Entry (key
mcpServers; each entry takescommand,argsand an optionalenv):{"mcpServers": {"bantamkit": {"command": "/absolute/path/to/env/bin/bantamkit-mcp", "args": []}}}
-
Confirm: it prints
installed bantamkit into claude-desktopwith file, key and command. Fully quit and reopen Claude Desktop, then ask it to callbantamkit_status. -
Undo / re-run: there is no uninstall flag. Delete the
bantamkitentry or restoreclaude_desktop_config.json.backup-<date>. A matching re-run printsbantamkit is already installed in claude-desktop and matches; a differing entry needs--force.
Connect to Cursor
-
Command:
<env>/bin/bantamkit-mcp --install cursor -
File:
~/.cursor/mcp.jsonon every OS (%USERPROFILE%\.cursor\mcp.jsonon Windows);.cursor/mcp.jsonfor one project, by hand. -
Entry (key
mcpServers):{"mcpServers": {"bantamkit": {"command": "/absolute/path/to/env/bin/bantamkit-mcp", "args": []}}}
-
Confirm: it prints
installed bantamkit into cursorandkey : mcpServers. Restart Cursor and ask the agent to callbantamkit_status. -
Undo / re-run: delete the entry or restore
mcp.json.backup-<date>. A differing entry, such as an oldpipx runone, is refused and printed beside the one it would write; replace it with<env>/bin/bantamkit-mcp --install cursor --force.
Connect to VS Code (GitHub Copilot)
-
Command:
<env>/bin/bantamkit-mcp --install copilot -
File: macOS
~/Library/Application Support/Code/User/mcp.json· Windows%APPDATA%\Code\User\mcp.json· Linux~/.config/Code/User/mcp.json;.vscode/mcp.jsonfor one workspace, or MCP: Open User Configuration, by hand. -
Entry: the key is
servers, notmcpServers, plus"type": "stdio". This is the detail that catches people out:{"servers": {"bantamkit": {"type": "stdio", "command": "/absolute/path/to/env/bin/bantamkit-mcp", "args": []}}}
-
Confirm: it prints
installed bantamkit into copilotandkey : servers. Restart VS Code and ask Copilot to callbantamkit_status. -
Undo / re-run: delete the entry or restore
mcp.json.backup-<date>;--forcereplaces a differing entry.
Connect other MCP clients
Anything that speaks MCP over stdio runs the same command/args and talks JSON-RPC on stdin
and stdout; nothing in this package is host-specific. Codex and a generic JSON config:
docs/mcp.md → Client setup.
Configuration
Flags go in the entry's args; environment variables in its env block (or
claude mcp add -e NAME=value). Both runtimes print the same --help.
| Setting | What it does | Default | Example |
|---|---|---|---|
BANTAMKIT_MEMORY_DIR |
Pins the store to one absolute path; a relative or unreachable path refuses at startup | unset: nearest existing .bantamkit/memory at or above the start directory |
"env": {"BANTAMKIT_MEMORY_DIR": "/abs/project/.bantamkit/memory"} |
--store STORE |
One store, layering off; outranks BANTAMKIT_MEMORY_DIR |
off (layered) | "--store", "/abs/store" |
--start START |
Where project-store discovery starts; not with --store |
cwd | "--start", "/abs/project" |
| Layered memory | Recall reads the project store, stores granted in .bantamkit/config.yaml, and ~/.bantamkit/memory; saves go to the project store |
on | docs/memory.md → Layers |
--k K |
Default recall budget | 3 |
"--k", "5" |
--index-budget BYTES |
Memory index byte budget | 24000 |
"--index-budget", "32000" |
BANTAMKIT_EVENT_LOG |
Logs tool outcomes as JSONL | off; on → <store>/events/mcp.jsonl; other values are a path |
"env": {"BANTAMKIT_EVENT_LOG": "on"} |
BANTAMKIT_ASSETS |
Your own asset pack (skills, rubrics, schemas) | the pack inside the package | "env": {"BANTAMKIT_ASSETS": "/abs/my-assets"} |
BANTAMKIT_HOST_LOG_ROOT |
Where --mcp-report finds the host's MCP logs |
macOS ~/Library/Caches/claude-cli-nodejs; elsewhere unset |
BANTAMKIT_HOST_LOG_ROOT=/abs/logs bantamkit-mcp --mcp-report |
BANTAMKIT_PRICES |
Price table for the token ledger | pricing/default.json in the asset pack |
"env": {"BANTAMKIT_PRICES": "/abs/prices.json"} |
Don't add --store by reflex: the default is layered, and the layering is most of the value.
One-shot commands that print and exit: --install {claude,claude-desktop,copilot,cursor} (with
--force), --update, --assets-root, --mcp-report, --statusline, -h. More:
store binding ·
pinning ·
event log ·
prices.
Update
<env>/bin/bantamkit-mcp --update # a pip install from PyPI: runs pip install --upgrade bantamkit
pip install -U "bantamkit[mcp]" # the same, by hand
pipx upgrade bantamkit # pipx
uv tool upgrade bantamkit # uv
--update (check the package index and update this install if it differs, then exit) upgrades
an install from PyPI with this interpreter's pip. An editable install, a local file or a source
tree is refused with exit 1 and a sentence naming the manual route (for a clone, git pull). It
is the only network access here, and only when you type it. For a wheelhouse, repeat the
download and install with the new version.
Then restart the server in the host (/mcp → reconnect in Claude Code; a full restart of
Claude Desktop): a running server keeps the code it started with. bantamkit_status prints the
version and the build_id of the code answering you; a new version with an old build_id
means an old process.
Troubleshooting
| Symptom | Fix |
|---|---|
| The host times out; the server never answers | The entry uses pipx run and pipx's cache is cold with no network. Use Install once, run offline |
ENOENT from the host |
A GUI host does not read your shell rc, so pipx is not on its PATH. --install records an absolute path |
bantamkit-mcp needs the MCP extra: pip install "bantamkit[mcp]" |
Install with the [mcp] extra |
already has a bantamkit entry with different settings … re-run with --force to replace it |
Re-run with --force; the old file is kept as .backup-<date> |
… is not valid JSON, so this refuses to touch it |
Fix the host's file by hand, then re-run |
MCP server bantamkit already exists in user config |
claude mcp remove bantamkit -s user, then install again |
pinned memory store must be an absolute path or pinned memory store is unreachable |
Give BANTAMKIT_MEMORY_DIR an absolute path that exists |
| Recall finds nothing, or the wrong store | Set BANTAMKIT_MEMORY_DIR; the reply names the store it searched (the three states) |
AssetNotFound: no assets directory found; set BANTAMKIT_ASSETS |
See The asset pack |
What it serves
The server serves 12 tools, the bantamkit_status prompt and two resource templates
(bantamkit://skills/{name}, bantamkit://rubrics/{name}):
| Tool | What it does |
|---|---|
memory_save |
store one durable fact, deduped and budgeted |
memory_recall |
retrieve facts matching a query |
memory_compact |
archive the stalest facts to fit the index budget |
memory_dream |
consolidate facts the project and profile layers hold under the same name |
validate_json |
validate a document against a JSON Schema |
skill_audit |
audit a skill catalogue for findings |
shiftwork_clock_in |
open a unit of work and get its brief |
shiftwork_clock_out |
close a unit with status and accounting |
shiftwork_status |
report the open cursor |
token_ledger |
what a session cost, read off the host's transcripts |
bantamkit_status |
report store health against its budget |
build_identity |
report the fingerprint of the source on disk |
build_identity describes the tree on disk, not the code currently executing — useful precisely
when a machine carries two installs under one name. bantamkit_read, the document reader, left
the served tools in job50 (2026-09-12); the reader itself stays in the library as
bantamkit.docread.
Requirements
Python 3.11 or newer. Three runtime dependencies — httpx, jsonschema, pyyaml — plus mcp
under the [mcp] extra.
The asset pack
Contracts, schemas, eval tasks, rubrics and tool manifests ship inside the package and are located at import time:
bantamkit-mcp --assets-root
It prints the resolved directory and its file count. A build that cannot find the pack fails
rather than producing an artifact without it — deliberately, because the silent version shipped
once. BANTAMKIT_ASSETS overrides the location.
The operator CLI: python -m bantamkit.memory
Memory-store maintenance is separate from the agent-facing tools and is not served over MCP:
python -m bantamkit.memory status # index size, budget, headroom, archive count
python -m bantamkit.memory lint # exit 1 if the store is malformed or over budget
python -m bantamkit.memory compact # archive the stalest facts
python -m bantamkit.memory archived # list what compaction has moved out
python -m bantamkit.memory archive <name>
python -m bantamkit.memory restore <name>
archive moves a fact out of the store without deleting it; restore brings it back by name.
Full reference: docs/memory.md → The operator CLI.
Share a store with the Node server
Both servers read and write the same on-disk format, so either can serve one store. A surface in one and not the other would be a way for two servers to disagree about one person's data, so every feature lands in both in the same change, and a conformance case compares the two answers before it counts as ported.
Where the Python and Node servers differ
- This side's document reader (
bantamkit.docread) reads pdf,.docand.rtf; the Node side refuses them by name. PDF is read by a stdlib reader written for this project; real OLE2.docand.rtfgo through/usr/bin/textutil, a macOS built-in that is probed at every call and refused by name where it is absent. - The operator CLI is spelled differently, and it shows in help text and error messages:
python -m bantamkit.memoryhere,bantamkit-memorythere. There is no third spelling — a pure-npm install has no Python in it, and CPython does not install that console script. build_idhashes the executing tree, and the two runtimes are two trees, so it differs by construction.assets_digestis identical, and that is the one that carries meaning.
Each is recorded in the divergence table with a conformance case pinning the wording, so the difference cannot drift unnoticed.
Development
git clone https://github.com/Ink01101011/bantamkit
cd bantamkit
python -m venv .venv && .venv/bin/pip install -e "runtime-py[dev,mcp]"
.venv/bin/python -m pytest runtime-py/tests -q
.venv/bin/ruff check runtime-py
The cross-runtime gate needs Node:
node tools/conformance/run.mjs --all
Documentation
| Page | Covers |
|---|---|
| Source on GitHub | The repository and its README |
npm package bantamkit-mcp |
The pure-Node server |
| Install | Requirements, editable install, measured MCP install detail |
| MCP | Client setup and which memory store the server binds |
| Memory | Store layout, layers, pinning, the operator CLI |
| Porting | What the two runtimes disagree about |
MIT.
Release files for bantamkit 0.34.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bantamkit-0.34.1.tar.gz | 1.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bantamkit-0.34.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:1.6 MB
Release files / bantamkit-0.34.1.tar.gz
| Download URL | bantamkit-0.34.1.tar.gz |
|---|---|
| Size | 1.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c8a722f894c66dae0ab5d67b3f026907c03fd0e3ff5dbf898776b3804454ee2
|
|
BLAKE2b-256 checksum How to use checksums |
0573a9fc03a686916d3c312a1b53fad7c787451a70a5cef927df72f285f0a373
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / bantamkit-0.34.1-py3-none-any.whl
| Download URL | bantamkit-0.34.1-py3-none-any.whl |
|---|---|
| Size | 512.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a561ea70680fa4684c55d6e98d297cc6455106d4bd1e79451c06d76a4b6fbb17
|
|
BLAKE2b-256 checksum How to use checksums |
68af7d548fd25d334ad67ae29d2991aeb8cc784a0eb8b95b12861df78ad013f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|