Most MCP tutorials start with "write a server". If all you want is for Claude to answer questions from a catalogue, an FAQ or a price list, you don't need to write anything.
The 2-minute version
json-mcp-lite turns a JSON array into three tools Claude can call:
-
products_list- page through records -
products_search- keyword search where every word must match -
products_get- one record by id
git clone https://github.com/scoretracker4321/json-mcp-lite
cd json-mcp-lite && npm install
claude mcp add products -- node $(pwd)/src/server.js --file $(pwd)/examples/products.json --name products --id sku --search title,description
Now ask Claude Code: "Which teas are under 400 and in stock?" It calls products_search, reads the results and answers from your data, not from memory.
For Claude Desktop or Cursor, add the same command to the mcpServers block in the config file (the README has the JSON).
Why read-only and keyword search?
Two choices that keep it boring and safe:
- Every tool is marked
readOnlyHint, so clients know nothing can change. - Search is plain keyword matching, not embeddings. For catalogues and FAQs under a few thousand rows it is instant, needs no API key, and you can predict exactly what it returns. Claude is good at rephrasing a query when the first one misses.
When a JSON file is not enough
The moment your data lives behind a REST API, or you want the server online for a team instead of on one laptop, you need more: OpenAPI-to-tools, HTTP hosting, API keys, rate limits. I packaged that as MCP Server Kit (one config file turns an OpenAPI spec into typed tools). json-mcp-lite is the free part of it, and it stays MIT.
Top comments (2)
The read-only approach makes a lot of sense here, especially for catalogue data.
One thing I’d be interested in seeing as this grows is how much the tool definitions themselves affect retrieval quality. MCP puts a lot of weight on tool names, descriptions, and input schemas because the model uses that information to decide which tool to call.
With
products_search, the “every word must match” rule is predictable, but it also puts more responsibility on Claude to formulate the query correctly. That seems like a useful trade-off for small catalogues, while larger or more semantic catalogues may eventually need a different retrieval layer.I like that the implementation stays deliberately simple instead of turning a small JSON catalogue into an unnecessarily complex RAG stack.
Thanks, that's exactly the trade-off I was weighing. The model only sees the tool name, description and input schema, so I put the matching rule into the query parameter's description ("Every word must appear; case-insensitive") and named the searched fields in it. In practice Claude then sends short, specific queries, and if it gets nothing it retries with fewer words. That holds up well for a few hundred records. Past that, or when people search by meaning ("something warm for winter"), keyword matching isn't enough and you'd want embeddings behind the same products_search tool, so the interface stays the same and only the retrieval changes. That's the line I drew between the free tool and the bigger kit. Appreciate you reading it closely.