mcp-server-sqlite
An MCP server for SQLite with fine-grained access control
Install / Use
claude mcp add 0xOmarA -- npx -y github:0xOmarA/mcp-server-sqliteIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
Data & AnalyticsSupported Platforms
Our assessment of mcp-server-sqlite
mcp-server-sqlite scores 71/100 on our quality scale, 552nd of 597 Data & Analytics skills we index.
Its MCP Server is 18 KB long, well organised into 38 sections with 25 code examples: a thorough specification that gives an agent plenty to work with.
It has 3 GitHub stars, so there is little community track record yet; judge it on its content.
Maintenance, license and trust
- The repository was last updated about 7 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
- It is released under the Apache-2.0 license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 81/100, with 3 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
mcp-server-sqlite compared with similar skills
All 4 of these similar skills score higher than mcp-server-sqlite; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| mcp-server-sqlite (this skill)by 0xOmarA | 71 | 3 | 7mo ago | MCP Server |
| claude-memby thedotmack | 100 | 110.6k | today | CLAUDE.md |
| Agent-Reachby Panniantong | 100 | 108.0k | 1d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 78.7k | today | CLAUDE.md |
| CowAgentby zhayujie | 100 | 47.8k | today | CLAUDE.md |
Frequently asked questions
- How do I install mcp-server-sqlite?
- Run
claude mcp add 0xOmarA -- npx -y github:0xOmarA/mcp-server-sqlite. The install tabs above show the steps for each supported agent. - Which AI agents does mcp-server-sqlite work with?
- It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
- Is mcp-server-sqlite safe to use?
- It is Apache-2.0-licensed and scores 81/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is mcp-server-sqlite still maintained?
- The repository was last updated about 7 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
Skill content
View source on GitHubWhy this exists
Every existing MCP server for SQLite falls short in at least one critical way. The official reference server from Anthropic is a ~300-line Python script with known unpatched SQL injection vulnerabilities, no parameterized queries, no transactions, no read-only mode, and a hardcoded demo prompt. It was archived in May 2025 with Anthropic declining to fix the security issues, yet it was forked over 5,000 times. The community alternatives each solve one or two problems but none solves them comprehensively.
This server was built to be the SQLite MCP server you can actually trust in production. It is written in Rust, ships as a single binary with no runtime dependencies, and uses SQLite's own sqlite3_set_authorizer API to enforce access control at the query-preparation level, before any SQL ever executes. The access control system supports column-level granularity, specificity-based rule resolution, and five built-in presets ranging from deny-everything to allow-everything.
Features
- Authorizer-based access control. Uses SQLite's native authorizer callback to intercept every operation at prepare time. Supports 30+ selector types covering reads, writes, DDL, pragmas, functions, transactions, attach/detach, and virtual tables, all with per-table, per-column, and per-function granularity.
- Five permission presets.
deny-everything,read-only(default),read-write,full-ddl, andallow-everything. Layer--allowand--denyoverrides on top with a specificity-based resolution algorithm where deny wins ties. - 13 tools. A single
executetool for arbitrary SQL, plus purpose-built tools for schema introspection, full-text search, query planning, backups, and database maintenance. - Full-text search. First-class FTS5 support with dedicated tools for creating indexes and searching with BM25 ranking and highlighted snippets.
- Query timeouts. Optional per-server timeout that uses SQLite's progress handler to abort runaway queries before they can tie up resources.
- Connection pooling. Built on
r2d2for connection reuse with per-connection authorizer and timeout installation. - Init scripts. Seed schemas and data on first run with
--init-sqlfiles that are skipped when the database already exists. - Single binary. Compiles SQLite statically via
rusqlite'sbundledfeature. No Python, no Node, no runtime dependencies.
Installation
From crates.io
cargo install mcp-server-sqlite
From source
git clone https://github.com/0xOmarA/mcp-server-sqlite.git
cd mcp-server-sqlite
cargo install --path .
Quick start
Start a read-only server with an in-memory database:
mcp-server-sqlite
Start a read-write server on a persistent database with a schema init file:
mcp-server-sqlite --database ./app.db --preset read-write --init-sql schema.sql
Claude Desktop configuration
Add the following to your Claude Desktop MCP config file:
{
"mcpServers": {
"sqlite": {
"command": "mcp-server-sqlite",
"args": [
"--database", "./my-database.db",
"--preset", "read-only"
]
}
}
}
Tools
The server exposes 13 tools over MCP. Each tool validates inputs, enforces the configured access control policy, and returns structured typed output.
execute
Runs any SQL query against the database. This is the primary tool. It handles SELECT, INSERT, UPDATE, DELETE, DDL, and everything else SQLite supports. Returns typed result rows (preserving NULL, Integer, Real, Text, and Blob types) and a count of rows changed.
execute({ "query": "SELECT name, age FROM students WHERE age > 20" })
Access control is enforced at the SQLite authorizer level, so denied operations never execute. If the configured policy denies any part of the query (a table read, a column access, a function call), the entire statement is rejected with a clear error message.
list_tables
Lists all tables in the database with their names and CREATE TABLE definitions.
describe_table
Returns column metadata for a specific table: column name, declared type, NOT NULL constraint, default value, and whether it is part of the primary key.
describe_table({ "table_name": "students" })
list_indexes
Lists indexes in the database. Optionally filter by table. Returns the index name, table name, uniqueness flag, ordered column list, and the WHERE clause for partial indexes.
list_indexes({ "table_name": "students" })
list_foreign_keys
Returns foreign key constraints for a given table, including the local column, referenced table and column, and the ON UPDATE/ON DELETE actions.
list_foreign_keys({ "table_name": "enrollments" })
list_views
Lists all views with their names and defining SQL.
list_triggers
Lists triggers in the database. Optionally filter by table. Returns the trigger name, attached table, event (INSERT/UPDATE/DELETE), timing (BEFORE/AFTER/INSTEAD OF), and full SQL definition.
list_triggers({ "table_name": "students" })
explain_query
Returns the EXPLAIN QUERY PLAN output for a query without executing it. Shows how SQLite will access tables, which indexes it will use, and how it will join data. Useful for understanding query performance.
explain_query({ "query": "SELECT * FROM students WHERE name = 'Omar'" })
backup
Creates a full backup of the database to a file path using SQLite's online backup API. Runs incrementally in pages so it does not block other operations for long. Returns the number of pages copied and the destination path.
backup({ "destination": "/tmp/app-backup.db" })
create_fts_index
Creates an FTS5 virtual table over specified columns of an existing table. The virtual table name defaults to {table}_fts but can be customized.
create_fts_index({
"table_name": "articles",
"columns": ["title", "body"]
})
search_fts
Runs a full-text search query against an FTS5 virtual table. Returns results ranked by BM25 relevance with highlighted snippets showing where the query matched. Configurable result limit, snippet length, and highlight markers.
search_fts({
"fts_table": "articles_fts",
"query": "sqlite AND indexing",
"limit": 5
})
vacuum
Runs the SQLite VACUUM command to rebuild the database file, reclaim unused space, and defragment storage.
database_info
Returns database metadata: SQLite version, page size, page count, total size in bytes, journal mode, WAL checkpoint status (when in WAL mode), freelist page count, and the number of tables and indexes.
Access control
The access control system is the core differentiator of this server. It is built on SQLite's sqlite3_set_authorizer callback, which means SQLite itself parses every query and reports every operation it will perform. The server then evaluates each operation against the configured policy. Denied operations cause the entire statement to be rejected at prepare time, before any data is read or modified.
This approach has several important properties:
- Zero parsing gaps. SQLite does the parsing, not a third-party SQL parser. Every valid SQLite statement is handled correctly, including edge cases like triggers, views, CTEs, and virtual tables.
- Column-level granularity. The
ReadandUpdateselectors accept both a table name and a column name, so you can deny access to specific columns (e.g.--deny Read(Users.ssn)). - Indirect operation tracking. If a trigger on table A fires an INSERT into table B, the authorizer catches the INSERT on table B. Operations hidden inside triggers and views are not invisible to the policy.
- Fail-closed by default. The default preset is
read-only. When allow and deny rules conflict at the same specificity level, deny wins.
Presets
Presets define the baseline permissions before any --allow/--deny overrides are applied.
| Preset | Allows | Denies |
|---|---|---|
| deny-everything | Nothing | Everything |
| read-only (default) | Read, Select, Transaction, Function, Recursive, Pragma | Insert, Update, Delete, all DDL, Attach, Detach |
| read-write | Extends read-only with Insert, Update, Delete, Savepoint, Analyze, Reindex, temp objects | Permanent DDL, Attach, Detach |
| full-ddl | Extends read-write with CreateTable, DropTable, AlterTable, CreateIndex, DropIndex, CreateTrigger, DropTrigger, CreateView, DropView | Attach, Detach, virtual tables |
| allow-everything | Everything | Nothing |
Selectors
Selectors identify the operation and, optionally, the exact resources a rule applies to. The syntax is Action or Action(field1.field2) where * is a wildcard.
Data operations:
| Selector | Fields | Example |
|---|---|---|
| Read | table_name.column_name | Read(Users.email) |
| Insert | table_name | Insert(AuditLog) |
| Update | table_name.column_name | Update(Users.password) |
| Delete | table_name | Delete(Sessions) |
| Select | (none) | Select |
Transactions:
| Selector | Fields | Example |
|---|---|---|
| Transaction | operation | Transaction(BEGIN) |
| Savepoint | operation.savepoint_name | Savepoint(*.my_sp) |
DDL (permanent):
| Selector | Fields | Example |
|---|---|---|
| CreateTable | table_name | CreateTable(TempData) |
| DropTable | table_name | DropTable(OldRecords) |
| AlterTable | database_name.table_name | AlterTable(*.Users) |
| CreateIndex | table_name.index_name | CreateIndex(Users.idx_email) |
| DropIndex | table_name.index_name | DropIndex |
| CreateView | view_name | CreateView(ActiveUsers) |
| DropView | view_name | DropView |
| CreateTrigger | table_name.trigger_name | CreateTrigger(Users.*) |
| DropTrigger | table_name.trigger_name | DropTrigger |
DDL (temporary):
| Selector | Fields | Example |
|---|---|---|
| CreateTempTable | table_name | CreateTempTable |
| DropTempTable | table_name | DropTempTable |
| CreateTempIndex | table_name.index_name | CreateTempIndex |
| DropTempIndex | table_name.index_name | DropTempIndex |
| CreateTempView | view_name | CreateTempView |
| DropTempView | view_name | DropTempView |
| CreateTempTrigger | table_name.trigger_name | CreateTempTrigger |
| DropTempTrigger | table_name.trigger_name | DropTempTrigger |
Other operations:
| Selector | Fields | Example |
|---|---|---|
| Pragma | pragma_name | Pragma(journal_mode) |
| Function | function_name | Function(count) |
| Attach | filename | Attach |
| Detach | database_name | Detach |
| Reindex | index_name | Reindex |
| Analyze | table_name | Analyze(Users) |
| CreateVtable | `table_name.modul
Truncated for display — read the full file on GitHub.
Related Skills
claude-mem
110.6kPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode + More
Agent-Reach
108.0kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
78.7kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
CowAgent
47.8kOpen-source personal AI assistant & Agent Harness. Plans tasks, runs tools and skills, self-evolves with memory and knowledge. Multi-agent, multi-model, multi-channel. Lightweight, extensible, one-line install.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
