mcpserve-py
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcpserve-pylist all tables in the database"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcpserve-py
A Model Context Protocol (MCP) server built in Python ā exposes database query tools and document resources over JSON-RPC 2.0 stdio transport, enabling AI assistants to interact with SQLite databases and markdown documents.
What is MCP?
The Model Context Protocol is an open standard for connecting AI assistants to external tools and data sources. MCP servers expose tools (functions the AI can call) and resources (data the AI can read) over a JSON-RPC 2.0 transport.
This server implements the MCP protocol from scratch using raw JSON-RPC 2.0 over stdio ā no SDK dependency required.
Related MCP server: SQLite MCP Server
Features
š§ 8 tools ā database queries, document CRUD, search, date/time
š Resource providers ā documents and database schemas as readable resources
š”ļø SQL injection protection ā only SELECT queries allowed, with regex validation
š YAML frontmatter ā documents stored as markdown with structured metadata
š Stdio transport ā line-delimited JSON-RPC 2.0 over stdin/stdout
ā” Zero SDK dependency ā hand-rolled MCP protocol implementation
ā Well-tested ā 113 tests covering protocol, tools, resources, and integration
Quick Start
# Clone and install
git clone https://github.com/devaloi/mcpserve-py.git
cd mcpserve-py
pip install -e ".[dev]"
# Run the server
python -m mcpserve_py
# Run tests
python -m pytest -vEnvironment Variables
Variable | Default | Description |
|
| Directory for documents and data |
|
| Path to SQLite database |
|
| Log level (DEBUG, INFO, WARNING, ERROR) |
Claude Desktop Configuration
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"mcpserve-py": {
"command": "python",
"args": ["-m", "mcpserve_py"],
"env": {
"MCPSERVE_DATA_DIR": "./data",
"MCPSERVE_DB_PATH": "./data/mcpserve.db"
}
}
}
}Tools
Tool | Description | Parameters |
| Execute read-only SQL query |
|
| List all tables in database | ā |
| Get table schema |
|
| Create a markdown document |
|
| Read document by title |
|
| List all documents |
|
| Full-text search across documents |
|
| Current date/time |
|
Resources
URI Pattern | Description | MIME Type |
| Document content |
|
| Full database schema |
|
| Single table schema |
|
Architecture
src/mcpserve_py/
āāā __main__.py # Entry point: python -m mcpserve_py
āāā server.py # MCP server: receive ā dispatch ā respond
āāā protocol.py # JSON-RPC 2.0 types and encoding
āāā transport.py # Stdio transport (line-delimited JSON)
āāā config.py # Pydantic settings
āāā tools/
ā āāā registry.py # Tool registry
ā āāā database.py # SQLite tools (query, list_tables, describe)
ā āāā documents.py # Document tools (CRUD + search)
ā āāā system.py # System tools (get_datetime)
āāā resources/
āāā provider.py # Resource provider interface + registry
āāā documents.py # Document resource provider
āāā database.py # Database schema resource providerDesign Decisions
No MCP SDK ā The protocol is implemented directly using JSON-RPC 2.0 dataclasses. This demonstrates deep understanding of the protocol rather than SDK usage.
Synchronous ā Stdio is inherently sequential; async adds complexity without benefit here.
Pydantic Settings ā Configuration via environment variables with type validation and
.envfile support.Tool registry pattern ā Tools register themselves with a central registry, keeping the server dispatch clean.
Read-only SQL ā Mutations are rejected via regex before reaching SQLite, preventing data corruption by AI assistants.
YAML frontmatter ā Documents use the same format as static site generators (Jekyll, Hugo), making them human-readable and tool-friendly.
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
make test
# Lint
make lint
# Type check
make typecheck
# Format
make format
# All checks
make allLicense
MIT
Contributing
See CONTRIBUTING.md. PRs welcome ā run make all before submitting.
Available Tools
8 toolscreate_documentB
Create a new markdown document with optional tags.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Optional tags for categorization | |
| title | Yes | Document title | |
| content | Yes | Markdown content |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'Create a new markdown document' implies a mutation, but the description does not state whether tags are applied at creation or must exist beforehand, whether the operation is idempotent, what permissions are required, or what the return value contains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler. It could be slightly more informative, but it is appropriately sized for a simple creation tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a creation tool with no annotations, no output schema, and 3 parameters, the description is minimally adequate. It does not explain what the created document's identifier or response looks like, nor whether tags affect discoverability elsewhere. More context would help the agent call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so each parameter is already documented in the schema. The description mentions 'optional tags' which matches the schema's 'Optional tags for categorization', but adds no syntax, format, or semantic detail beyond that. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (create) and resource (markdown document) plus the optional tags aspect. It does not explicitly distinguish itself from siblings like read_document or list_documents, but the creation semantics are clear from the verb alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage is clear from the verb 'Create' ā the agent knows this is for new document creation. However, there is no explicit when-to-use guidance, no mention of alternatives, prerequisites, or constraints (e.g., whether documents must be in a workspace, whether title must be unique).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_tableB
Get the schema of a specific table including column names, types, and constraints.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | Name of the table to describe |
TDQS
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 implies a read-only inspection and sketches the return shape, but says nothing about failure modes (nonexistent table), permissions, or whether the output is a fixed dump versus a summary. Adequate but thin for a completely unannotated tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the verb and the returned fields, with zero filler. Nothing could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a trivial single-parameter read tool with no output schema, the description covers the essentials by naming what the returned schema contains. It could be slightly more complete by noting behavior on an unknown table, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the single 'table' parameter is already fully documented in the schema. The description's phrase 'specific table' adds no new semantics. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get') and resource ('schema of a specific table'), and enumerates the returned content (column names, types, constraints). It is clear on its own but does not distinguish itself from siblings like list_tables or query_database.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites, and no mention of the sibling alternatives (e.g., list_tables to enumerate tables, query_database to read data). The agent must infer that this is the schema-inspection step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_datetimeA
Get the current date and time, optionally in a specific timezone.
| Name | Required | Description | Default |
|---|---|---|---|
| timezone | No | IANA timezone name (e.g. 'America/New_York', 'Europe/London'). Defaults to UTC. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden. It signals a live, non-mutating read by saying 'current', but it does not disclose the return format (ISO 8601? epoch?), precision, or whether an invalid timezone errors or silently falls back to UTC ā the last being a real behavioral question given the phrasing 'Defaults to UTC' in the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the core action, with the optional qualifier trailing. Nothing is wasted and nothing essential is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter, side-effect-free tool with a fully documented schema, the description is nearly sufficient. The single remaining gap is the return format, which no output schema covers, so the description could have stated it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the single parameter is fully documented in the schema including an IANA example and the UTC default. The description only restates the optionality, adding no syntax or edge-case meaning beyond the schema; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get the current date and time') plus the optional scope ('specific timezone'). The intent is unambiguous and no sibling tool in the list offers datetime functionality, so no differentiation is needed. Not a 5 only because it is a very simple, near-tautological statement of a self-evident operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage (call it when you need the current time, pass a timezone when you need local time) but provides no explicit when-to-use framing, no guidance on what to do if the timezone is unknown, and no alternatives since none exist. Adequate but minimal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_documentsB
List all documents, optionally filtered by tag.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Optional tag to filter by |
TDQS
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 mentions optional filtering but does not disclose behavior such as whether it returns all documents by default (potential performance concern), pagination limits, permissions required, or what the output structure looks like. For a list operation with no structured behavioral hints, this is insufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One concise sentence that front-loads the primary action and specifies the optional filter. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations, no output schema, and a crowded set of sibling tools, the description is too sparse. An agent lacks critical context: default behavior, return shape, performance implications, and how to choose between this tool and siblings like search_documents or query_database.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already explains the single parameter. The description adds the word 'optionally' and clarifies that filtering is by tag, which is consistent with the schema and provides slight reinforcing value. Baseline 4 is appropriate for zero required params and full coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb (List) and resource (documents) with added scope (optional tag filter). However, it does not differentiate from sibling tools like search_documents or query_database, which is important for correct tool selection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus alternatives. The description implies it is a general listing tool, but with siblings like search_documents and query_database, an agent needs to know when to prefer each. No when-to-use or when-not-to-use information is provided.
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 tables in the SQLite database.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It implies a read-only listing, but never states that it is non-mutating, what permissions are needed, or what the return shape is (e.g. bare table names vs. rows). For a zero-param introspection tool the risk is low, but the disclosure is minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that wastes no words. It is appropriately sized for a trivial listing tool, though the database qualifier could be trimmed or expanded to name the actual DB.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-param, no-output-schema listing tool the description is nearly sufficient, but it leaves the return format unspecified (names only? schema-qualified?) and offers no routing cues to the sibling describe_table, which an agent would likely need right after listing tables.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there are no parameter semantics to document; the baseline for a parameterless tool is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') and resource ('all tables') with a clear scope ('in the SQLite database'), so the agent knows exactly what it returns. However, it does not differentiate itself from the sibling describe_table or query_database, which could also surface table information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no when-to-use guidance, no prerequisites, and never mentions alternatives such as describe_table for column-level detail or query_database for data retrieval. The agent must infer the appropriate context entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_databaseA
Execute a read-only SQL query against the SQLite database. Only SELECT statements are allowed.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | SQL SELECT query to execute | |
| params | No | Optional query parameters for parameterized queries |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It usefully discloses the read-only guarantee and the SELECT-only restriction, which is real value, but says nothing about result size limits, pagination, timeout behavior, or error handling for rejected statements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the primary capability is front-loaded ahead of the constraint. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool this is roughly adequate, but with no output schema and no annotations the description could reasonably describe the result shape or constraints on returned rows. It stops just short of complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (sql, params) are already documented in the schema, setting the baseline at 3. The description reinforces the SELECT-only constraint on the sql parameter but adds no syntax, formatting, or parameterization guidance beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Execute) and resource (read-only SQL query against the SQLite database), which is clear on its own. It does not, however, explicitly distinguish itself from siblings like describe_table or list_tables, so an agent must infer that this is the tool for arbitrary data retrieval rather than schema introspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The read-only/SELECT-only constraint implies the usage context (safe data retrieval, not mutation), but there is no explicit when-to-use guidance or mention of alternatives such as describe_table for schema discovery. Usage is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_documentC
Read a document by its title.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Document title to read |
TDQS
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 does not say what happens if the title is not found, whether matching is exact or fuzzy, or what the return value contains ā significant gaps for a retrieval tool with zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short, front-loaded sentence with no wasted words. It is efficient, though arguably under-specified rather than truly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with full schema coverage, the description is minimally viable. Missing are the failure behavior for a missing title and the shape of the returned document, which an agent would want before invoking it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single parameter is fully documented in the schema. The description's 'by its title' merely restates the parameter, so the schema does the heavy lifting; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Read a document') and adds the lookup key ('by its title'), which distinguishes it somewhat from list_documents. However it does not distinguish itself from search_documents, which plausibly also retrieves documents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this versus search_documents, list_documents, or query_database. The agent must infer that this is an exact-title lookup rather than a search.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_documentsC
Search documents by content and title.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query string |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it discloses almost nothing: no matching semantics (exact vs fuzzy), ranking, pagination, result limits, or permission requirements. For a search tool with zero annotation coverage this is a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence, front-loaded and free of filler. It is not under-specified to the point of uselessness, but it is too terse to earn a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (one required string param, no nested objects), so minimal description is defensible, but with no output schema the return shape (list of documents? ranked hits?) is left unspecified and the description never addresses it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single 'query' parameter, so the baseline is 3. The description adds only that the query matches content and title, which is marginally useful context beyond the schema's bare 'Search query string'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear verb+resource (search documents) and the fields searched (content and title). It does not distinguish itself from siblings like list_documents or read_document, so an agent gets no routing signal from the description alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No indication of when to use this versus list_documents, read_document, or query_database. The only implicit hint is that it is a search rather than a list, but no conditions or alternatives are named.
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.
8 tool updates
v0.1.0- First observed
create_document - First observed
describe_table - First observed
get_datetime - First observed
list_documents - First observed
list_tables - First observed
query_database - First observed
read_document - First observed
search_documents
TDQS
Scored across 8 tools
Most tools target clearly distinct resources and actions, so an agent can pick correctly with little hesitation. The only mild overlap is between list_documents (tag filter) and search_documents (content/title query), which descriptions do disentangle.
Every tool follows a clean verb_noun snake_case pattern: query_database, list_tables, describe_table, create_document, read_document, list_documents, search_documents, get_datetime. No deviations or mixed conventions.
Eight tools is well-scoped for a lightweight multi-purpose server covering database introspection, document management, and a datetime utility. Each tool earns its place with no redundancy.
Document handling lacks update and delete operations, and the database surface is read-only with no insert/update/delete, so lifecycle coverage is partial. The lone get_datetime tool also sits outside either domain, leaving a somewhat heterogeneous surface.
Related MCP Connectors
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
- dataOAuthco.thinair
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Query 40 databases from Claude, ChatGPT, or Cursor ā on any device. Read-only, encrypted, audited.
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server implementation that enables AI assistants to execute SQL queries and interact with SQLite databases through a structured interface.7MIT
- AlicenseNot gradedqualityDmaintenanceImplements a Model Context Protocol server that enables natural language interactions with SQLite databases, providing tools to list tables, retrieve schemas, count rows, and execute read-only SQL queries.MIT
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for SQLite databases, enabling AI assistants to safely query and inspect database schemas without write access.MIT
- FlicenseNot gradedqualityCmaintenanceExposes any SQLite database as read-only MCP tools for AI assistants, enabling listing tables, describing schemas, and running SELECT queries with filtering, ordering, and pagination.-