tessera-mcp
Click on "Install 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., "@tessera-mcpcheck Atlas Freight for double billing"
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.
tessera-mcp
A Model Context Protocol (MCP) server that gives an AI agent seven support-ops tools for Tessera, a fictional B2B workspace SaaS. It runs over stdio with a bundled SQLite database — no hosted runtime, no API keys, no LLM calls anywhere in this repo.
Why this exists (60-second pitch). Wiring an LLM to tools is easy; wiring it safely is the hard part. This server demonstrates the pattern I ship for agentic work: typed tools with LLM-readable descriptions, a dry-run/confirm human-in-the-loop gate on every mutation, and a deterministic test suite that proves the tools behave — 20/20, no model in the loop. Point Claude Code at it and watch it run a realistic morning ops workflow: spot a double-billed customer, investigate, refund with approval, rescue a churning trial.
Quickstart
# 1. Create + seed the local database (idempotent — safe to re-run)
npx tessera-mcp --seed
# 2. Register the server with Claude Code
claude mcp add tessera -- npx tessera-mcpThat's it. Claude Code now has the seven tools below. No environment variables required — the server uses a local SQLite file at ~/.tessera-mcp/data.db. The path is home-anchored (not relative to the current directory) so the server finds the same database no matter where the host launches it from, and it auto-seeds on first run if you skip step 1.
Requires Node 20+.
Claude Desktop
Add this to your claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"tessera": { "command": "npx", "args": ["tessera-mcp"] }
}
}Claude Desktop launches MCP servers from the filesystem root, so a working-directory-relative database would be empty. This server sidesteps that by using the home-anchored ~/.tessera-mcp/data.db and seeding it on first run — no --seed step required.
Related MCP server: CRMy
The tools
Tool | Kind | What it does |
| read | Open tickets, worst priority first; optional priority filter + limit |
| read | One customer by id or email, with their invoices + tickets summary |
| read | Filter invoices — spot duplicates, overdue balances, history |
| read | Start-of-day snapshot: open tickets by priority, overdue invoices ($), trials expiring ≤7d |
| mutation | Move a ticket to open / pending / solved |
| mutation | Push a trial customer's end date out by N days |
| mutation | Refund a paid invoice (rejects already-refunded / non-paid) |
Every input field carries a description — that text is what the client LLM reads to call the tool correctly. Results come back as concise text tables, not JSON dumps. Invalid ids return clear error strings, never exceptions.
The confirm / dry-run pattern (human-in-the-loop)
MCP has no built-in "approve this action" UI — the protocol hands a tool call straight to your code. So every mutation here is gated by a confirm flag that defaults to false:
Without
confirm: truethe tool changes nothing and returns a preview:DRY RUN — would refund INV-1013 ($2,400.00, Atlas Freight) — reason: "double billed". Re-call with confirm:true to execute.With
confirm: trueit executes atomically (a single write batch that also appends an audit-log row) and reports what changed:Done — refunded INV-1013 ($2,400.00, Atlas Freight). Reason: "double billed".
The agent shows the human the dry-run preview, waits for a yes, then re-calls with confirm:true. It turns an irreversible action into a two-step, reviewable one. See DECISIONS.md for why this beats an ungated tool.
Example Claude Code session (illustrative)
Transcript below is an illustration of the intended workflow, lightly trimmed. The deterministic suite (
npm run eval) is the actual correctness metric.
You: Good morning — anything on fire?
Claude: [calls daily_summary]
Open tickets: 10 (3 urgent). 4 overdue invoices ($2,847.00). 2 trials expiring within 7 days.
One thing stands out: Atlas Freight has two identical $2,400 invoices issued the same day.
You: Dig into Atlas Freight.
Claude: [calls get_customer({ idOrEmail: "CU-1010" })]
Atlas Freight (CU-1010), enterprise. INV-1013 and INV-1014 are both $2,400.00,
both issued Jul 14, 2026 — that's a double charge.
You: Refund one of them.
Claude: [calls issue_refund({ invoiceId: "INV-1013", reason: "duplicate charge — double billed" })]
DRY RUN — would refund INV-1013 ($2,400.00, Atlas Freight). Re-call with confirm:true to execute.
Want me to go ahead?
You: Yes.
Claude: [calls issue_refund({ ..., confirm: true })]
Done — refunded INV-1013 ($2,400.00, Atlas Freight).
You: Also, Paperkite's trial is about to lapse and they're angry — give them two more weeks and close their ticket.
Claude: [extend_trial CU-1003 +14 (dry-run → confirm), then update_ticket_status TK-1003 solved (dry-run → confirm)]
Done — Paperkite's trial now ends Aug 3, 2026, and TK-1003 is solved.
You: Re-run the summary.
Claude: [calls daily_summary]
Open tickets down to 9 (2 urgent). Overdue unchanged. Trials expiring within 7 days: down to 1.Eval — the honest metric
npm run eval connects an in-process MCP client to the server over the SDK's linked in-memory transport (no child process, no network, no LLM) and replays 23 scripted cases from data/eval-cases.json against a freshly seeded, isolated database:
valid reads, filtered reads, and invalid-id errors
each mutation as dry-run and then confirmed
post-mutation state assertions (a re-read proves the change landed)
a same-status no-op that returns success, not an error
direct
audit_logassertions (exactly one row per confirmed mutation)refund-twice rejection (a second refund on an already-refunded invoice errors)
a concurrency check: two overlapping confirmed refunds race via
Promise.all; exactly one wins and exactly one audit row is written (proving the TOCTOU fix)
The eval is isolated — it runs against its own file:eval.db and never inherits TURSO_DATABASE_URL, so npm run eval can never touch your real or hosted data.
Because there is no model in the loop, the suite is fully deterministic: the gate is 100%. Anything less is a real bug and the process exits non-zero.
23/23 cases passed.
All 23 eval cases + concurrency check passed (deterministic gate: 100%).Configuration
Zero config by default. Optional environment variables:
Variable | Effect |
| Use a hosted libSQL/Turso database instead of the default |
| Auth token for the hosted database above |
| Override the demo's fixed reference clock (ISO 8601); defaults to |
| Database the eval uses (default |
| Set to |
CLI flags: --seed (create + seed, then exit), --db <path> (use a specific SQLite file), --help. The default database is ~/.tessera-mcp/data.db, auto-seeded on first run.
See env.example. This project never reads or writes .env files.
The Tessera universe
Tessera is a fictional B2B workspace SaaS used across a family of portfolio demos. Sibling repos:
docs-chat — RAG over Tessera's docs
tessera-ops-agent — the ops dashboard + copilot this data is modeled on
tessera-invoice-inbox — invoice-processing workflow
All data here is synthetic. See DECISIONS.md for architecture rationale and VIDEO-SCRIPT.md for the demo narration.
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/NDilanka/tessera-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server