SQLite MCP Server
by isaacgounton
README.md
# SQLite MCP Server
[](https://github.com/isaacgounton/sqlite-mcp-server/actions/workflows/ci.yml)
[](LICENSE)
[](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