kardex
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@kardexCreate a vendor invoice sheet and add INV-001 Acme 1200 due 2026-09-30 unpaid"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
kardex
Google Sheets for AI agents, as an MCP server.
Agents are good at reasoning and bad at bookkeeping. Give one a CSV and it will lose rows, invent columns, misspell a name and then fail to find it, and overwrite what another agent just wrote. kardex is a small SQLite-backed store where every sheet has a typed, described schema, every row has a stable id and a version, every write is logged with its author, and lookups are fuzzy with an explicit match status. It ships as a Model Context Protocol server, so any MCP client can use it: Claude Code, Claude Desktop, Cursor, or your own agent.
you: Track vendor invoices. Add INV-001 Acme 1200 due 2026-09-30 unpaid, INV-002 Globex 450 paid, ...
then tell me what's outstanding and who we owe most.
agent: kardex_create_sheet → "Vendor Invoices" (invoice_number, vendor, amount, due_date, status: unpaid|paid|...)
kardex_append_rows → 5 rows
kardex_run_sql → SELECT vendor, SUM(amount) ... WHERE status = 'unpaid'
"Outstanding: $4,500 across 4 invoices. Largest creditor: Initech ($2,200)."Why not just a database or a spreadsheet?
Schema is data. Column descriptions, allowed options and defaults are stored with the sheet and returned by
kardex_describe_sheet, so the next agent knows how to fill a column without being told.Names are messy.
kardex_resolve_valuesandkardex_find_rowsmatch across case, accents, spacing, punctuation and common misspellings, and return a status:exact,unique_fuzzy,ambiguousornone. A fuzzy hit is never silently treated as exact.Rows are not entities. A key column, per-key counts and
latest_bymake event-log style sheets (one row per status change) answerable without double counting.Writes are safe. Optimistic versions on single-row updates; bulk updates and deletes default to a dry run and then require the expected match count; empty filters are refused; the SQL tool is read-only.
Everything is auditable.
kardex_historyshows who changed what, with before and after snapshots.
Related MCP server: DataBook
Quick start
Requirements: Python 3.10+ and uv (or pip).
git clone https://github.com/gauravhans8/kardex.git && cd kardex
uv venv && uv pip install -e ".[mcp]" # or: python -m venv .venv && .venv/bin/pip install -e ".[mcp]"
.venv/bin/kardex-mcp --helpThe server speaks MCP over stdio. It takes one option, --db PATH (or the KARDEX_DB environment
variable), and creates the SQLite file on first start.
Claude Code
Put a .mcp.json in any project folder, using absolute paths:
{
"mcpServers": {
"kardex": {
"command": "/absolute/path/to/kardex/.venv/bin/kardex-mcp",
"args": ["--db", "/absolute/path/to/your/sheets.db"]
}
}
}Open Claude Code in that folder, approve the project server when prompted, and ask: "What sheets do you have?" or "Create a sheet to track candidates." Several folders can share one database, or each can have its own.
Claude Desktop, Cursor and other clients
Same shape. Add the block above under mcpServers in the client's MCP configuration file (for Claude Desktop,
claude_desktop_config.json).
From Python, without MCP
from kardex import SheetStore
store = SheetStore("sheets.db")
store.create_sheet("Hiring Pipeline", [
{"name": "candidate", "type": "text", "required": True, "description": "Full name"},
{"name": "email", "type": "text", "description": "Identifies the person"},
{"name": "stage", "type": "select", "options": ["applied", "screen", "offer", "hired"], "default": "applied"},
], key_column="email")
store.append_rows("Hiring Pipeline", [{"candidate": "Jane Doe", "email": "jane@x.com"}], actor="me")
store.query("Hiring Pipeline", where={"stage": "applied"})
store.resolve_values("Hiring Pipeline", "candidate", "jane do") # -> status: unique_fuzzyThe core package has no dependencies beyond the standard library.
Tools
All tools are prefixed kardex_. Every result is one envelope: ok, resolved (the sheet and columns
actually used), data, warnings (facts about the data that may change the meaning of an answer),
suggestions (did-you-mean candidates), and total / returned / truncated / next_offset on lists.
Failures the agent can fix come back as isError with error.code in not_found, validation, conflict,
refused, read_only.
Discover | Read | Write |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
|
|
Column types: text, number, integer, boolean, date, datetime, select, json. Values are coerced
leniently on write ("3" becomes 3, "yes" becomes true) and rejected with a specific message when they cannot be.
Filters are ANDed conditions in any of these shapes:
{"stage": "offer"} equality {"stage": ["offer", "hired"]} IN
{"email": null} IS NULL [["score", "gte", 4], ...] triples
"candidate~~gourav hans" fuzzy "name~=renee dubois" normalized equalityOperators: eq ne gt gte lt lte in not_in contains starts_with is_null is_not_null normalized_eq fuzzy.
For OR, joins and aggregates use kardex_run_sql; tables are named by sheet slug.
How it is built
Storage. One SQLite file in WAL mode. Meta tables
_sheets,_columns,_changeshold schema and history as data; each sheet's rows live in their own table with system columns_id,_version,_created_at,_created_by,_updated_at,_updated_by. A deterministicnorm(text)SQL function provides normalized comparison. Schema version is tracked and migrated on open.Matching.
kardex/normalize.py: NFKC, strip zero-width and control characters, casefold, strip diacritics, collapse punctuation and whitespace. Scoring tiers: exact, normalized, token set, prefix, Jaro-Winkler fuzzy, phonetic. Status rules: one exact hit isexact; one fuzzy hit clearly ahead of the next isunique_fuzzy; two within 0.10 areambiguous; nothing above threshold isnone.MCP layer.
kardex_mcp/server.pyon the official PythonmcpSDK (2.x, protocol 2026-07-28 and legacy clients). Tool descriptions and server instructions are inkardex_mcp/descriptions.pyand are tuned against the eval below. Every tool has read-only, destructive and idempotent annotations and a strict input schema. Warnings state facts; guidance on what to do with them lives in the descriptions.Design documents. docs/mcp-plan.md explains which agent mistakes each tool exists to prevent. MCP_SERVER_GUIDELINES.md is the checklist the server was built against.
Development
uv pip install -e ".[dev]"
.venv/bin/python -m pytest # 48 tests: store, normalization, MCP layer, trap suite
.venv/bin/python examples/hiring_demo.py # a scripted multi-agent session against the Python API
.venv/bin/python evals/run_traps.py # model-in-the-loop eval (spends tokens, see below)The trap suite
Agents fail in predictable ways: wrong sheet, wrong spelling, counting rows as people, treating one fuzzy hit
as certain, bulk-editing with a filter that matched too much. tests/fixtures/traps.py
seeds a database that contains every one of those traps. tests/test_traps.py drives the
tool path deterministically. evals/run_traps.py runs the real server under a headless
Claude Code session (claude -p) per question, grades the tool calls and the answer, and writes transcripts to
evals/out/. Use --suite happy for the create, load, query and schema-evolution flows, --only <case> for one
case. A full run is ten cases and about two dollars of tokens; at the time of writing all ten pass.
Layout
kardex/ core library (store, types, filters, normalize, profile, search)
kardex_mcp/ MCP server (server, descriptions)
tests/ pytest suite and the trap fixture
evals/ model-in-the-loop runner
examples/ demo script
docs/ design planStatus and roadmap
Works for single-host, multi-agent use today. Not yet done:
Postgres backend behind the same
SheetStoreinterface for multi-tenant deployments.Hardened HTTP transport (auth, origin checks). The
--transport streamable-httpflag exists but is unauthenticated; do not expose it beyond localhost.Idempotency keys on
kardex_append_rowsso client retries cannot double insert.FTS5 acceleration for sheets beyond tens of thousands of rows.
CSV import and export over MCP (available in the Python API).
License
No license file yet. Add one before publishing.
This server cannot be deployed
Maintenance
Related MCP Connectors
An agent-native database over MCP: shared, validated, structured records in every AI chat.
Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.
- memnodeOAuthdev.memnode
Persistent, inspectable memory for AI agents with lineage, correction, and a hosted MCP endpoint.
System-of-record notebook for AI coding agents: pages, datastores, tasks, skills over MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides persistent, inspectable memory storage for AI agents using SQLite. Agents can store, recall, and search memories across sessions via three MCP tools.3MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage and query SQLite databases through MCP tools, supporting CRUD operations, schema management, and saved views.4 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants and teams to collaborate in a shared workspace by building and querying tables, writing documents, uploading files, and publishing live dashboards through any MCP-compatible client.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables coding agents to store, recall, and manage persistent memory across sessions through MCP tools, with reviewable handoffs and SQLite-backed local storage.1MIT