Skip to main content
Glama
djgadd

node-sqlite-mcp

by djgadd
README.md
# node-sqlite-mcp

An [MCP](https://modelcontextprotocol.io) server that lets an AI agent query
**SQLite database files** on the local machine.

It uses Node's built-in [`node:sqlite`](https://nodejs.org/api/sqlite.html)
module, so there is **no native module to compile and no system SQLite to
install** — the only thing you need on the host is a recent Node.

## Requirements

- **Node.js 22.16 or newer** (which ships `node:sqlite` unflagged). Node 24+ is
  recommended.

Check with `node --version`.

## Install

The server is published to npm and is installed into your agent with
[`add-mcp`](https://github.com/neon-solutions/add-mcp):

```bash
npx add-mcp node-sqlite-mcp
```

`add-mcp` detects your installed agents (Claude Code, Claude Desktop, Cursor,
VS Code, …) and registers the server as a local stdio command. Nothing is
cloned or installed globally — the command is fetched and run on demand.

You can also run it directly to sanity-check it:

```bash
npx -y node-sqlite-mcp
```

It speaks MCP over stdio and waits for a client; there is nothing interactive to
see.

## Tools

Every tool takes the database as an argument — `path` should be an **absolute**
path to a `.db` / `.sqlite` file. The database is always opened **read-only**.

| Tool | Arguments | Returns |
| --- | --- | --- |
| `list_tables` | `path` | The tables and views in the database. |
| `describe_table` | `path`, `table` | Columns, types, a boolean not-null flag, defaults and a boolean primary-key flag for one table or view. |
| `query` | `path`, `sql` | The rows returned by a single read-only SQL statement. |

### Output format

Results come back as **TSV**: a tab-separated header row of column names, one
line per row, then a blank line and a row count. This is used instead of JSON
because it does not repeat column names on every row, keeping the payload small.

- `NULL` is rendered as an empty field.
- Tabs, carriage returns, newlines and backslashes inside values are escaped
  (`\t`, `\r`, `\n`, `\\`). Other control characters are escaped as `\xNN`
  (e.g. NUL as `\x00`).
- BLOBs are rendered as a SQLite hex literal, e.g. `x'deadbeef'`.
- The `describe_table` `not_null` and `primary_key` columns are booleans (`true`/`false`).

### Read-only

The SQLite connection is opened read-only, so `INSERT` / `UPDATE` / `DELETE`
and schema changes fail at the engine level — not merely by convention. The
`query` tool runs a single statement per call and does **not** truncate
results, so a broad `SELECT *` on a large table can return a very large payload;
the tool description tells the agent to add a `LIMIT` and select only needed
columns.

### Security note

This is a local, trust-the-user tool. It will open **any** SQLite file the
operating-system user running the server can already read — there is no
allowlist or directory confinement.

## Development

```bash
npm install      # installs deps and builds via the "prepare" script
npm run build    # compile TypeScript to dist/
```

Source is TypeScript in `src/`; the published package ships compiled JavaScript
in `dist/` (the `bin` entry point). Consumers never run a build step.

### Releases & publishing

Releases are automated with [Release Please](https://github.com/googleapis/release-please),
driven by [Conventional Commits](https://www.conventionalcommits.org/):

- Every push to `main` opens or updates a standing **release PR** that bumps the
  version in `package.json` / `package-lock.json` and updates `CHANGELOG.md`,
  derived from the commits since the last release (`fix:` → patch, `feat:` →
  minor, a `!` or `BREAKING CHANGE:` → major).
- Merging that release PR tags the version, creates a GitHub Release, and
  triggers `npm publish` (`on-push-main.yml` → `workflow-call.release.yml`).

So the normal flow is: land Conventional-Commit PRs on `main`, then merge the
release PR when you want to cut a version — no manual tag or `npm publish`.

Publishing uses npm **trusted publishing** (OIDC) — no tokens. Configure the
trusted publisher on npmjs.com against this repository, the entry workflow
**`on-push-main.yml`**, and the **`production`** environment. The publish job
runs with `id-token: write` on npm ≥ 11.5.1, and provenance is generated
automatically.

To publish by hand instead (e.g. the first release, to bootstrap the package
before a trusted publisher can be configured), from a logged-in machine:

```bash
npm publish
```

### Commit messages

This repo uses [Conventional Commits](https://www.conventionalcommits.org/).
Because PRs are merged (not squashed), every commit lands on `main` verbatim and
is what Release Please parses — so each commit in a PR is linted against the
convention (`on-pr.yml` → `workflow-call.lint-pr.yml`, config in
`.commitlintrc.json`). Common types: `feat:`, `fix:`, `docs:`, `chore:`,
`refactor:`, `test:`, `ci:`. A `feat!:` prefix or a `BREAKING CHANGE:` footer
marks a breaking change.

## License

MIT

TDQS

A4.5/5.0

Scored across 3 tools

Disambiguation5/5

Each tool serves a distinct purpose: listing tables, describing schema, and executing read-only queries. There is no functional overlap.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (describe_table, list_tables, query). 'query' as a single verb is standard for SQL operations.

Tool Count5/5

Three tools are appropriate for a read-only SQLite explorer, covering the essential operations of listing, describing, and querying without unnecessary bloat.

Completeness5/5

The tool set fully covers the domain of exploring a SQLite database: listing tables/views, inspecting their schema, and running arbitrary read-only queries. No obvious gaps.

Maintenance

ActivityStale
ResponsivenessNo issues