Skip to main content
Glama
isaacgounton

SQLite MCP Server

by isaacgounton
README.md
# SQLite MCP Server

[![CI](https://github.com/isaacgounton/sqlite-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/isaacgounton/sqlite-mcp-server/actions/workflows/ci.yml)
[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](LICENSE)
[![smithery badge](https://smithery.ai/badge/@isaacgounton/sqlite-mcp-server)](https://smithery.ai/server/@isaacgounton/sqlite-mcp-server)

A Model Context Protocol (MCP) server that provides SQLite database operations. Supports both **stdio** (for Claude Desktop, Cursor, etc.) and **Streamable HTTP** (for remote clients) transports.

## Features

- In-memory or file-based SQLite database
- Dual transport: stdio and Streamable HTTP
- SQL operations with input validation and injection protection
- Table management (CREATE, DROP, LIST, DESCRIBE)
- Database schema exposed as an MCP resource
- Business insights memo tracking
- Docker support

## Quick Start

### Stdio (Claude Desktop, Cursor, etc.)

```bash
npm install && npm run build
node build/index.js
```

Add to your Claude Desktop config (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "sqlite": {
      "command": "node",
      "args": ["/path/to/sqlite-mcp-server/build/index.js"]
    }
  }
}
```

With a file-based database:

```json
{
  "mcpServers": {
    "sqlite": {
      "command": "node",
      "args": ["/path/to/sqlite-mcp-server/build/index.js", "/path/to/database.db"]
    }
  }
}
```

### Streamable HTTP (remote clients)

```bash
node build/index.js --http
```

The server exposes a single endpoint at `http://localhost:3000/mcp` following the MCP Streamable HTTP specification. By default it binds to `127.0.0.1`. To reach it from another host or a container, set `HOST=0.0.0.0` — but read the [Security](#security) section first: the HTTP transport has no authentication.

### Docker

```bash
docker build -t sqlite-mcp-server .
docker run -d -p 3000:3000 -e HOST=0.0.0.0 --name sqlite-mcp sqlite-mcp-server
```

`HOST=0.0.0.0` is required so the server is reachable through the published port. Connecting from the host via `localhost:3000` works out of the box; to reach it under any other hostname, add that host to `MCP_ALLOWED_HOSTS`.

## Configuration

| Option | Description | Default |
|--------|-------------|---------|
| `--http` | Use Streamable HTTP transport instead of stdio | stdio |
| First non-flag argument | Path to SQLite database file | `:memory:` |
| `SQLITE_DB_PATH` | Database path (env var alternative) | `:memory:` |
| `PORT` | HTTP server port (HTTP mode only) | `3000` |
| `HOST` | Interface to bind in HTTP mode. Use `0.0.0.0` to expose beyond localhost | `127.0.0.1` |
| `MCP_ALLOWED_HOSTS` | Comma-separated `Host` header allow-list for DNS-rebinding protection | `localhost:$PORT,127.0.0.1:$PORT` |
| `MCP_AUTH_TOKEN` | Bearer token required on all `/mcp` requests (HTTP mode). Unset = auth disabled | _(none)_ |

Examples:

```bash
# In-memory database on stdio
node build/index.js

# File-based database on stdio
node build/index.js ./data.db

# HTTP mode with custom port
PORT=8080 node build/index.js --http ./data.db

# Using environment variable
SQLITE_DB_PATH=./data.db node build/index.js --http
```

## Available Tools

| Tool | Description |
|------|-------------|
| `read_query` | Execute SELECT, WITH (CTE), or EXPLAIN queries |
| `write_query` | Execute INSERT, UPDATE, DELETE, or REPLACE queries |
| `create_table` | Create a new table with a CREATE TABLE statement |
| `drop_table` | Drop a table (irreversible) |
| `list_tables` | List all user-created tables |
| `describe_table` | Get table schema: columns, indexes, and foreign keys |
| `append_insight` | Add a business insight to the memo resource |

## Resources

| URI | Description |
|-----|-------------|
| `sqlite://{db}/schema` | Full schema (CREATE statements) for all tables |
| `memo://insights` | Accumulated business insights from analysis |

## Prompts

| Name | Description |
|------|-------------|
| `mcp-demo` | Guided walkthrough: creates tables, inserts sample data, runs queries for a given topic |

## Remote Connection

### Streamable HTTP

Connect any MCP-compatible client to `http://your-host:3000/mcp`. The server supports:

- `POST /mcp` — send MCP messages (session created on initialize)
- `GET /mcp` — SSE stream for session resumability
- `DELETE /mcp` — terminate a session
- `GET /health` — health check endpoint

Sessions are managed via the `Mcp-Session-Id` header.

### Authentication

Set `MCP_AUTH_TOKEN` to require a bearer token on every `/mcp` request (`/health` stays open):

```bash
MCP_AUTH_TOKEN=$(openssl rand -hex 32) HOST=0.0.0.0 node build/index.js --http
```

Clients then send `Authorization: Bearer <token>`. When `MCP_AUTH_TOKEN` is unset, authentication is disabled — fine for a localhost-only bind, but do not expose the server publicly without it.

## Security

- Query validation: each tool only accepts its intended SQL statement type
- Multi-statement injection blocked: stacked statements are rejected, with string literals and comments stripped before the check
- Table names validated against `^[a-zA-Z_][a-zA-Z0-9_]*$`
- Foreign keys enabled by default
- HTTP transport binds to `127.0.0.1` by default, with DNS-rebinding protection (`MCP_ALLOWED_HOSTS`)
- Optional bearer-token auth on the HTTP transport via `MCP_AUTH_TOKEN` (timing-safe check)

**Set `MCP_AUTH_TOKEN` before exposing the HTTP transport beyond localhost.** For production, also front it with a reverse proxy that terminates TLS. See [SECURITY.md](SECURITY.md) for the full model and how to report a vulnerability.

## Development

```bash
npm install
npm run build
npm test           # build + run the validator test suite
npm start          # stdio mode
npm run start:http # HTTP mode
```

## License

[ISC](LICENSE)

TDQS

B3.4/5.0

Scored across 1 tool

Disambiguation5/5

With only one tool, there is no possibility of confusion between tools. The single tool's purpose is clearly distinct by default.

Naming Consistency5/5

With a single tool, naming consistency is trivially maintained. The name 'create_table' follows a clear verb_noun pattern.

Tool Count2/5

A single tool for a SQLite server is far too few for the apparent scope. Typical database operations are missing, making the tool set feel extremely thin.

Completeness2/5

The server only supports table creation, lacking essential operations like querying, inserting, updating, deleting, or dropping tables. This represents significant gaps for any database interaction.

Maintenance

ActivityStale
ResponsivenessSlow