Skip to main content
Glama
Aderali06

sqlite-mcp-server

sqlite-mcp-server

An open-source Model Context Protocol (MCP) server connecting LLM assistants (such as Claude Desktop and Cursor) to local SQLite databases with strict read-only security, context overflow protection, and structured AI error handling.

CI M8ven Score Glama Score License: MIT Python 3.10+


๐ŸŒŸ Key Features

  • Automated Schema Discovery: Automatically inspect table lists, object types (tables/views), row count estimates, columns, primary keys, foreign keys, and complete DDL definitions.

  • Strict Read-Only Query Security:

    • Parser-Level Validation: Rejects all mutation statements (INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, ATTACH, VACUUM, REINDEX, etc.).

    • Statement Chaining Prevention: Blocks execution of multiple chained statements separated by ;.

    • Restricted PRAGMAs: Prohibits dangerous PRAGMAs (writable_schema, permissions, and configuration mutation).

    • Engine-Level Enforcement: SQLite connections are opened using read-only URI mode (file:path?mode=ro) with PRAGMA query_only = ON;.

  • Context Overflow Protection (max_rows): Safely truncates large query results with an informative warning advising AI models to use LIMIT and OFFSET clauses.

  • Structured Error Handling for AI: Returns standardized JSON error envelopes (error_type, message, query, and suggestion) to allow AI models to self-correct queries without hallucinations.

  • Full MCP Capabilities: Exposes Tools, direct Resources (sqlite://schema, sqlite://tables), and guided Prompts (schema_analysis, safe_query_assistant).

  • Flexible Configuration: Set the database path via CLI argument (--db-path), environment variable (SQLITE_DB_PATH), or dynamically per tool invocation (db_path).


Related MCP server: DB Insights MCP Server

๐Ÿ› ๏ธ MCP Tools

Tool Name

Description

Key Arguments

list_tables

Lists all tables and views in the database with estimated row counts.

db_path (optional)

describe_table

Retrieves column definitions, data types, nullability, default values, primary keys, foreign keys, and indexes for a specific table.

table_name (required), db_path (optional)

get_database_schema

Returns the complete DDL schema definition for all tables, views, and indexes.

db_path (optional)

read_query

Safely executes a read-only SELECT or EXPLAIN query and returns structured row records.

query (required), params (optional), max_rows (optional, default: 1000), db_path (optional)


๐Ÿ“ฆ MCP Resources & Prompts

MCP Resources (Direct Context Access)

Clients that support MCP Resources can inspect the database context directly without invoking a tool:

  • sqlite://schema: Returns the full formatted SQL DDL schema of the database.

  • sqlite://tables: Returns a concise list of all tables, views, and their respective row counts.

MCP Prompts (Interactive Assistant Guides)

  • schema_analysis: Prompts the AI model to inspect database structure, relationships, normalization, and optimization opportunities.

  • safe_query_assistant(user_goal): Guides the AI model in formulating an optimized, safe SELECT query tailored to the user's objective.


๐Ÿ“‹ Structured Error Format

When a syntax or validation error occurs, the server responds with a structured JSON object designed for LLM consumption:

{
  "success": false,
  "error_type": "DisallowedQueryError",
  "message": "Forbidden modification keyword 'DROP' detected. Only read operations are allowed.",
  "query": "DROP TABLE employees;",
  "suggestion": "Remove any data modification or schema alteration commands. Only SELECT queries are permitted."
}

Supported error categories:

  • DisallowedQueryError: Query attempts data modification or invokes forbidden SQL operations.

  • SyntaxError: SQLite syntax error.

  • TableNotFoundError: Table was not found (includes advice to run list_tables).

  • ColumnNotFoundError: Column was not found (includes advice to run describe_table).

  • DatabaseNotFoundError: Database file does not exist at the specified path.

  • DatabaseConfigError: No database path was provided or configured.

  • ValidationError: Invalid input parameter (e.g. empty table name or max_rows < 1).


๐Ÿš€ Installation & Getting Started

Option 1: Run with uvx (Recommended)

If you have uv installed, run the server instantly without cloning:

uvx sqlite-mcp-server --db-path "/path/to/database.db"

Option 2: Install from Source

# 1. Clone repository
git clone https://github.com/Aderali06/sqlite-mcp-server.git
cd sqlite-mcp-server

# 2. Create virtual environment
python -m venv .venv

# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate

# 3. Install package and development dependencies
pip install -e ".[dev]"

โš™๏ธ Claude Desktop Configuration

Add the server to your claude_desktop_config.json:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Configuration Example:

{
  "mcpServers": {
    "sqlite": {
      "command": "uvx",
      "args": [
        "sqlite-mcp-server",
        "--db-path",
        "C:/Users/A2/Documents/database.db"
      ]
    }
  }
}

Or using local Python:

{
  "mcpServers": {
    "sqlite": {
      "command": "python",
      "args": [
        "-m",
        "src.server",
        "--db-path",
        "C:/Users/A2/Documents/database.db"
      ],
      "env": {
        "PYTHONIOENCODING": "utf-8"
      }
    }
  }
}

๐Ÿ’ป Cursor Integration

Method 1: Via Cursor Settings UI

  1. Open Cursor Settings (Ctrl + Shift + J on Windows/Linux or Cmd + , on macOS).

  2. Navigate to Features > MCP Servers.

  3. Click + Add New MCP Server.

  4. Fill in:

    • Name: sqlite-mcp-server

    • Type: command

    • Command: python -m src.server --db-path "C:/path/to/database.sqlite"

Method 2: Project-Level Configuration (.cursor/mcp.json)

Create .cursor/mcp.json in your project root:

{
  "mcpServers": {
    "sqlite": {
      "command": "python",
      "args": [
        "-m",
        "src.server",
        "--db-path",
        "${workspaceFolder}/data/app.db"
      ]
    }
  }
}

๐Ÿงช Testing

Run the automated test suite with pytest:

# Run all tests
pytest

# Run tests with test coverage reporting
pytest --cov=src --cov-report=term-missing

๐Ÿ“‚ Project Structure

sqlite-mcp-server/
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ workflows/
โ”‚       โ”œโ”€โ”€ ci.yml              # Multi-OS CI testing (Linux & Windows)
โ”‚       โ””โ”€โ”€ publish.yml         # Automated PyPI release workflow
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ __init__.py             # Package version & metadata
โ”‚   โ””โ”€โ”€ server.py               # FastMCP server, tools, resources, prompts & SQL validation
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ test_server.py          # 29 unit & integration pytest tests
โ”œโ”€โ”€ .gitignore                  # Git ignore rules
โ”œโ”€โ”€ LICENSE                     # Official MIT License
โ”œโ”€โ”€ pyproject.toml              # Build system, CLI entrypoint, & package metadata
โ”œโ”€โ”€ README.md                   # Project documentation & configuration guide
โ””โ”€โ”€ requirements.txt            # Python dependencies

๐Ÿ“„ License

This project is licensed under the MIT License.

Available Tools

4 tools
describe_tableA

Get detailed schema information for a specific table or view, including columns, primary keys, foreign keys, and indexes.

Args: table_name: The name of the table or view to inspect. db_path: Optional path to SQLite file. If omitted, uses default database path.

ParametersJSON Schema
NameRequiredDescriptionDefault
db_pathNo
table_nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the full behavioral burden. It does disclose the content of the result (columns, keys, indexes), which signals a read-only inspection operation, but it never states that the operation is non-mutating, what happens when the table does not exist, or whether it errors versus returning empty. Adequate but with clear gaps for a zero-annotation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose sentence is front-loaded and the Args block is compact with one line per parameter. Slightly wasteful to repeat 'table_name' and 'db_path' labels for only two parameters, but nothing is padded or off-topic.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not detail return formatting, and it does not need to; it still usefully names the result elements. For a two-parameter read tool the coverage is nearly complete, with only error/edge-case behavior left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it explains table_name as the table or view to inspect and db_path as an optional SQLite file path whose omission falls back to the default database path. This adds the default-fallback semantics that the bare schema (anyOf string/null, default null) does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Get) and resource (schema information) scoped to 'a specific table or view', and enumerates the returned elements (columns, primary keys, foreign keys, indexes). This clearly separates it from the sibling get_database_schema (whole database) and list_tables without needing either schema opened.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the scope ('a specific table or view'), so an agent can infer it is for inspecting one object's structure rather than listing or querying. However, there is no explicit when-to-use guidance, no named alternative such as get_database_schema for whole-database introspection, and no statement of prerequisites or failure conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_database_schemaA

Get the full CREATE DDL statements and schema definitions for all tables, views, and indexes.

Args: db_path: Optional path to SQLite file. If omitted, uses default database path.

ParametersJSON Schema
NameRequiredDescriptionDefault
db_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses what is returned (DDL for tables, views, indexes) and that it is a read-style retrieval, but says nothing about cost, permissions, or behavior on a missing/invalid db_path. Reasonable for a simple read, but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence of purpose followed by a compact Args block; the core behavior is front-loaded and there is no filler. The 'Args:' formatting is slightly boilerplate but not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value detail is not required, and the description still summarizes the returned content. For a zero-required-param read tool this is essentially complete; only the missing sibling routing keeps it from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it explains that db_path is an optional SQLite file path and that omitting it falls back to the default database path. That fully covers the single parameter's meaning and default behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Get the full CREATE DDL statements and schema definitions') and scopes it to 'all tables, views, and indexes', which implicitly separates it from describe_table (single table) and list_tables (names only). It does not explicitly name the siblings, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by 'full ... for all tables' โ€” an agent can infer this is the whole-database dump versus per-table inspection โ€” but there is no explicit when-to-use or when-not-to-use guidance and no named alternative. Adequate but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tablesB

List all user tables and views in the SQLite database with their row count.

Args: db_path: Optional path to SQLite file. If omitted, uses default database path.

ParametersJSON Schema
NameRequiredDescriptionDefault
db_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It does disclose useful behavior โ€” user tables plus views, scoped to a specific database, with row counts โ€” but says nothing about permissions, cost on large databases, or read-only semantics beyond what 'List' implies.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One lead sentence covering purpose, then a compact Args block for the single parameter. Front-loaded and efficient; the Args block mildly duplicates the schema but adds the default-fallback detail that justifies its presence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter read tool with an output schema, the description covers the resource, the scope, and the parameter's default behavior. Only miss is any mention of how this relates to the sibling schema/introspection tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it explains db_path is an optional path to the SQLite file and that omitting it falls back to a default database path. That is exactly the semantics an agent needs and the schema does not supply.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') plus resource ('user tables and views in the SQLite database') and adds output scope ('with their row count'). It does not explicitly distinguish itself from siblings like get_database_schema or describe_table, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to pick this over get_database_schema or describe_table, and no stated prerequisites. The only usage context is the implicit meaning of db_path's default.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_queryA

Execute a safe, read-only SELECT query against the SQLite database.

Args: query: The SQL SELECT query to execute. Mutation queries (INSERT, UPDATE, DELETE, DROP, etc.) are strictly rejected. params: Optional list of query parameters for prepared statements (? placeholders). max_rows: Maximum number of rows to return (default: 1000). Protects against context overflow. db_path: Optional path to SQLite file. If omitted, uses default database path.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
paramsNo
db_pathNo
max_rowsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does disclose the key traits: read-only safety, strict rejection of INSERT/UPDATE/DELETE/DROP, a default 1000-row cap that protects against context overflow, and default database fallback. It omits error/transaction behavior, which keeps it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose sentence is front-loaded and the Args block is compact and scannable. Every line earns its place; the docstring formatting is conventional but not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. Combined with full parameter documentation, mutation rejection, and row-cap rationale, the definition gives an agent enough to call the tool correctly; only edge-case behavior (errors, transactions) is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it documents all four parameters with meaning: query semantics plus mutation rejection, params as prepared-statement '?' placeholders, max_rows default and overflow rationale, and db_path default behavior. It stops short of examples or type/format details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Execute a safe, read-only SELECT query against the SQLite database') and the safety constraint up front. This is clearly distinguishable from the introspection siblings (list_tables, describe_table, get_database_schema), which return metadata rather than rows.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: an agent infers it should call this when it needs actual data. The rejection of mutation queries is a useful negative boundary, but the description never routes the agent to a sibling (e.g., use get_database_schema first to discover tables) or states prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observeddescribe_table
    • First observedget_database_schema
    • First observedlist_tables
    • First observedread_query

TDQS

A3.8/5.0

Scored across 4 tools

Disambiguation4/5

list_tables, describe_table, and get_database_schema have some overlap in scope (schema/table inspection), but each operates at a clearly different granularity: table list with counts, single-table detail, and full DDL. read_query is cleanly distinct as the data-retrieval tool. An agent can reasonably pick the right one.

Naming Consistency4/5

Names are snake_case verb_noun throughout (list_tables, describe_table, get_database_schema, read_query), which is readable and predictable. Minor deviation in that three verbs (list/describe/get) are used for closely related inspection tasks rather than one consistent verb.

Tool Count5/5

Four tools is well-scoped for a read-only SQLite inspection server, with each tool earning its place and no redundancy. Nothing feels padded or thin for the stated purpose.

Completeness4/5

The read-only inspection surface (list tables, describe table, full DDL, run SELECT) covers the core discovery and query workflow with no dead ends. Gaps exist around write/mutation operations and query-plan/explain introspection, but those are plausibly out of scope for a deliberately read-only server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to query SQL databases safely with read-only access, allowing schema discovery and SELECT queries while blocking writes and DDL operations.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to explore and query SQLite databases through read-only tools, with defense-in-depth sandboxing preventing any data modifications.
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    Enables AI assistants to query SQLite databases using plain language, with strict read-only enforcement and column-level access control to prevent damage or unauthorized data reads.
    4
    -