Write one tool
Here's a real read-only tool from the kit — it answers "do you have X, and how many?" by reading one JSON file. It returns plain data; it never writes or sends anything.
// search_inventory — find products by name, SKU, or category. // The AI reads this description to decide when to call it. export async function searchInventory({ query = "", inStockOnly = false }) { const data = await loadData(); // your shop.json let results = data.inventory; if (query) results = results.filter(i => (i.name + i.sku + i.category).toLowerCase().includes(query.toLowerCase())); if (inStockOnly) results = results.filter(i => i.in_stock > 0); return { count: results.length, items: results }; // just reads }
Two more ship with the kit —
read_pricelist and get_hours — written the same way. Three tools,
one data file. That's a complete MCP server.
Call your tool — and watch the request/response shape
Read-only: the response is data the AI reads back to the person — nothing was written, sent, or charged to produce it.
Run the server, then point Claude at it
With the kit downloaded:
# 1. set up (writes .env — Claude key is optional) npm install npm run setup # 2. prove it works with NO key and NO network beyond localhost npm run dryrun # 3. let Claude drive the tools npm start # server on http://127.0.0.1:8765/mcp — leave running npm run agent -- "Do you sell painter's tape, and is it in stock?"
127.0.0.1 only —
your data never leaves your computer. The agent demo is the one piece that
talks to the internet, and only to send your question and the tool results
to Claude so it can phrase an answer. The dry-run talks to nothing but localhost.Prefer the Claude desktop app over the CLI?
Run npm start and add the server at http://127.0.0.1:8765/mcp
(Streamable HTTP) as a connector — Claude lists the same three tools and calls them in chat.
claude-opus-4-8 (smartest). Set ANTHROPIC_MODEL=claude-haiku-4-5
in .env for a cheaper, faster swap on high-volume questions.That's a real MCP — and you now understand this better than most devs.
You wrote a tool, ran a real server, saw the request/response shape, and watched an AI fire it against your data. The kit is genuinely yours: free, MIT-licensed, no neutered features. Take it apart.
Get the free first-mcp-kit on GitHub →Make it about your business
- Copy
data/shop.sample.jsontodata/my-shop.json. - Replace its contents with your hours, inventory, and prices (same shape).
- Run
npm run setupagain and give it the new path (or setDATA_FILEin.env). - Run
npm run dryrun— same tools, now answering about your business.
The file lives on your machine and is yours to own and edit. The kit never invents data it can't read from that file.
The safety chapter — read-only first, write tools behind a gate
draft_order returns "here's the order I'd place: 3× PVC pipe, $14.37 —
approve?" and stops. Nothing is charged until a person clicks approve in your own app.Before you wire any AI into real tools, run the 5 questions from Lesson 1's safety panel against every tool:
- What can it touch? Scope each tool to one narrow action.
- Can it spend money? If yes — it drafts only; a human approves.
- Can it be undone? Prefer reversible actions; log everything.
- Who sees the result? Show the plan before it happens, not after.
- What if it's wrong? A draft that's wrong costs nothing. Ship drafts.
The kit's src/server.js
carries a commented "ADDING A WRITE TOOL SAFELY" section. You copy it in
deliberately, when you understand it — it is not enabled by default.
Going from this toy MCP to a production one is the gap we close.
Making it secure, audited, and wired to your real systems — your inventory, your CRM, your bookings, behind auth and rate limits, with write tools properly gated and logged across your whole stack — is real work. That's our day job.
See what Rabbithole builds →New here? Start with Lesson 1 — What is an MCP? · or browse all lessons.