# csv-mcp-server

A read-only MCP server over one CSV file. Two tools, no network, nothing writes.
Tested 2026-09-17: Node 20.19, `@modelcontextprotocol/server` 2.0.0, zod 4.6, Claude Code `claude mcp add`.
From the No Bullshit AI Course (Distru), lesson 06-04. MIT; copy it, change it.

| tool | what it does | arguments |
|---|---|---|
| `list_rows` | rows as JSON, with the column names; paged | `limit` (1-50, default 10), `offset` |
| `find_by_tag` | rows whose `tags` column contains the text, case-insensitive | `tag`, optional `column` |

Both tools carry `readOnlyHint: true`. The CSV is read once at start; restart to load a new export.

## Run it

```bash
npm install
CSV_PATH=./sample.csv npm test        # starts the server, lists tools, calls both. No AI involved.
```

Expected: `tool: list_rows readOnly=true`, `tool: find_by_tag readOnly=true`, then two results and one deliberate error (`No column "nope"`).

## Wire it into Claude Code

```bash
claude mcp add --env CSV_PATH=/absolute/path/to/menu-export.csv menu -- node /absolute/path/to/server.mjs
claude mcp list          # menu: ✔ Connected
```

Inside a session, `/mcp` shows the two tools. Ask: "Using the menu server, which SKUs are tagged infused?"
Remove with `claude mcp remove menu`.

## Wire it into Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "menu": {
      "command": "node",
      "args": ["/absolute/path/to/server.mjs"],
      "env": { "CSV_PATH": "/absolute/path/to/menu-export.csv" }
    }
  }
}
```

Quit and reopen Claude Desktop. Server logs land in `~/Library/Logs/Claude/mcp-server-menu.log`.

## Settings (environment variables)

- `CSV_PATH` the file (or pass it as the first argument)
- `TAG_COLUMN` column `find_by_tag` searches (default `tags`)
- `MAX_ROWS` cap per call (default 50). Tool output goes into the model's context; keep it small.

## What it does not do

- No writes, no second file, no joins. Add a tool only when a real question needs it; every tool definition rides on every turn.
- No auth: it reads a file you already have. Do not point it at a file with customer PII you would not paste into a chat.
- Numbers come back as strings, exactly as the CSV had them. The model does the arithmetic; check it.

Files: `server.mjs` (the server), `test-client.mjs` (raw JSON-RPC smoke test), `sample.csv` (fake menu), `package.json`.
Spec: https://modelcontextprotocol.io/specification/2025-06-18/server/tools · Tutorial: https://modelcontextprotocol.io/docs/develop/build-server
