Multi-Database CRUD MCP Server
Planned integration to provide tools for CRUD operations on a MySQL database, following the same pattern as SQLite and PostgreSQL.
Provides tools for CRUD operations on a PostgreSQL database, including creating, reading, updating, and deleting product records.
Provides tools for CRUD operations on a SQLite database, including creating, reading, updating, and deleting product records.
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., "@Multi-Database CRUD MCP Serveradd a product called 'Headphones' with price 79.99"
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.
Multi-Database CRUD MCP Server
This learning project exposes typed MCP tools for product CRUD operations. SQLite works by default, PostgreSQL is supported through configuration, and MySQL can be added later without changing the MCP tools.
Architecture
User -> AI/MCP client -> MCP tools (server.py)
-> database adapter (database.py)
-> SQLite or PostgreSQL
<- structured result <- databaseThe AI never connects directly to the database or generates unrestricted SQL. It selects a narrow tool such as create_product, and the server validates the input before the database adapter executes parameterized SQL.
Related MCP server: MCP Universal DB Client
Available MCP tools
database_healthcreate_productget_productlist_productsupdate_productdelete_product
Start with SQLite
SQLite is included with Python. It does not require Docker, a database server, username, or password.
Install dependencies:
uv syncSelect SQLite in PowerShell:
$env:DB_BACKEND="sqlite" $env:SQLITE_PATH="data/mcp_demo.db"Run the tests:
uv run pytestStart MCP Inspector:
uv run mcp dev src/mcp_database/server.py
The first database tool call automatically creates data/mcp_demo.db and its products table. Call database_health; it should return:
{"connected": true, "backend": "sqlite"}Then try create_product, list_products, update_product, and delete_product in Inspector.
Connect an MCP client to SQLite
Use an absolute path for the project and SQLite file:
{
"mcpServers": {
"database-crud": {
"command": "uv",
"args": [
"--directory",
"C:\\absolute\\path\\to\\MCP_Database",
"run",
"mcp-database"
],
"env": {
"DB_BACKEND": "sqlite",
"SQLITE_PATH": "C:\\absolute\\path\\to\\MCP_Database\\data\\mcp_demo.db"
}
}
}
}The selected database is controlled by DB_BACKEND. The older mcp-postgres command remains available as a compatibility alias.
Switch to PostgreSQL later
The MCP tools require no code changes. Start PostgreSQL and change the environment variables.
Start the provided PostgreSQL container:
docker compose up -d docker compose psSelect PostgreSQL:
$env:DB_BACKEND="postgresql" $env:DATABASE_URL="postgresql://mcp_user:mcp_password@localhost:5432/mcp_demo" uv run mcp dev src/mcp_database/server.py
The container runs sql/init.sql on its first startup. SQLITE_PATH is ignored in PostgreSQL mode.
For an MCP client, replace its environment section with:
"env": {
"DB_BACKEND": "postgresql",
"DATABASE_URL": "postgresql://mcp_user:mcp_password@localhost:5432/mcp_demo"
}MySQL in the future
MySQL is not implemented yet. DB_BACKEND=mysql deliberately returns a clear configuration error. To add it:
Add
PyMySQLormysql-connector-pythontopyproject.toml.Add a MySQL connection context manager in
database.py.Implement the same six data functions using MySQL parameterized queries.
Use MySQL schema syntax such as
AUTO_INCREMENT.Add MySQL integration tests.
server.py will remain unchanged because the backend-specific code is isolated in database.py.
Important SQL differences
Concern | SQLite | PostgreSQL | MySQL |
Driver | Built-in |
| Future driver |
Placeholder |
|
| Usually |
Generated ID |
|
|
|
Server needed | No | Yes | Yes |
Current status | Implemented | Implemented | Planned |
The adapter handles SQLite and PostgreSQL differences while presenting the same functions to the MCP server.
Project files
src/mcp_database/server.py: stable MCP contract and validation.src/mcp_database/database.py: backend selection and database-specific SQL.sql/init.sql: PostgreSQL schema and sample records.compose.yaml: local PostgreSQL service.tests/test_server.py: MCP tool unit tests.tests/test_sqlite_database.py: real SQLite CRUD integration tests..env.example: configuration examples. A plain.envis not loaded automatically; supply variables through PowerShell or MCP client configuration.
How to explain it to a manager
“This proof of concept places a controlled MCP service between an AI assistant and a database. Instead of giving the model unrestricted SQL access, it exposes six typed and auditable operations. A database adapter lets developers use zero-setup SQLite locally and move to PostgreSQL later without changing the MCP contract.”
For production, add authentication, user-level authorization, secret management, audit logging, connection pooling, rate limiting, migrations, monitoring, backups, and separate read/write database roles.
Troubleshooting
DATABASE_URL is required for PostgreSQL: set it whenDB_BACKEND=postgresql.SQLite file missing: call any database tool once; it is created automatically.
PostgreSQL connection refused: verify
docker compose psreports a healthy container.Inspector port 6274 is occupied: close the older Inspector terminal/session before starting another.
Tools do not appear: use an absolute project path and restart the MCP client.
This project uses the official MCP Python SDK.
Available Tools
6 toolscreate_productB
Create one product. Price and stock must be zero or greater.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| price | Yes | ||
| stock | No | ||
| description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses price/stock constraints but does not mention side effects, return behavior, required authorization, or behavior on duplicate products. This leaves critical behavioral aspects unspecified.
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?
The description is two short sentences, front-loaded with the action and followed by a relevant constraint. 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?
For a create mutation with no annotations, the description is minimal. While an output schema exists, the description omits behavioral context like id generation, duplicate handling, and prerequisites. It fails to fully prepare the agent for using the tool effectively.
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 0%, so the description must compensate. It adds validation constraints for price and stock but leaves name and description unexplained. The addition is partial and insufficient for a 4-parameter tool.
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 clearly states the action (create) and resource (product), distinguishing it from siblings like update_product, delete_product, and get_product. 'One product' also clarifies scope, preventing confusion with bulk operations.
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 implies its use case (creating a new product) but provides no explicit alternatives or exclusions. The constraint on price/stock gives some context, but the tool's role relative to siblings is only implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
database_healthA
Check the selected database backend and its connection.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It only states 'Check' which implies a read-only operation, but it does not disclose any side effects, permissions needed, return format, or failure behavior. The description is too minimal to provide meaningful behavioral transparency beyond the basic action.
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?
The description is a single concise sentence (8 words) that front-loads the purpose. There is zero wasted wording, making it extremely efficient and easy to parse.
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?
Given the tool's low complexity (no parameters) and the presence of an output schema, the description is mostly sufficient. It could be slightly more explicit about what constitutes a healthy check or what the output indicates, but for a read-only health check of a database connection, it provides a clear enough scope.
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 has zero parameters, so the input schema is empty. The description does not need to explain parameters, and the baseline for zero parameters is 4. The description does not contradict the schema, so this score 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?
The description clearly states the tool's function: 'Check the selected database backend and its connection.' This is a specific verb (check) with a specific resource (database backend and connection), and it clearly distinguishes from sibling product CRUD tools.
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 usage context is implied: use this tool to verify database health. However, there is no explicit guidance about when to use it versus alternatives or when not to use it. With only one sentence, it provides no exclusions or alternative references.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_productA
Permanently delete one product by ID. Confirm user intent first.
| Name | Required | Description | Default |
|---|---|---|---|
| product_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the destructive nature ('permanently delete') and adds a safety requirement (confirm user intent). This is more transparent than a generic 'delete' description, though it doesn't detail related data effects or error conditions.
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 concise sentences with the most critical information front-loaded. Every word earns its place, and the reminder to confirm user intent is a valuable addition without unnecessary verbosity.
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 simple delete operation with one parameter and an existing output schema, the description is complete. It notes permanence and a required safety step, which covers the main context an agent needs. No significant gaps are apparent.
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 schema has zero description coverage and only one required integer parameter. The description adds 'by ID' but does not explain the product_id semantics beyond what the parameter name and type imply. It's sufficient for a simple identifier, but the description could have explicitly stated that product_id is the identifier of the product to be deleted.
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 clearly states the action ('Permanently delete'), the resource ('one product'), and the scope ('by ID'). It distinguishes itself from sibling tools like create_product, update_product, and list_products by specifying deletion semantics and permanence.
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 includes a crucial usage guideline: 'Confirm user intent first,' which warns the agent to verify user intent before invoking this destructive action. It doesn't explicitly mention alternatives, but the purpose is clear enough that an agent would know when to use this over update_product or list_products.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_productA
Read one product by its positive numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| product_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It explicitly says "Read," indicating a non-destructive operation, and specifies a positive numeric ID constraint. However, it does not disclose behavior for missing/invalid IDs, authentication requirements, or return format nuances, leaving gaps beyond the basic read action.
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?
The description is a single, front-loaded sentence with no wasted words. It immediately communicates the tool's purpose and key constraint.
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 with one parameter and an output schema that likely covers return values. The description is largely sufficient, but it does not mention what happens when the product ID does not exist (e.g., error vs. null), which would make it fully 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?
The schema only defines product_id as an integer with no description (0% coverage). The description adds meaningful semantics: "positive numeric ID" implies a validation constraint and clarifies the parameter's role as an identifier. This exceeds what the bare schema provides.
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 "Read one product by its positive numeric ID" clearly states the verb (Read), resource (product), and scope (one product by ID). It distinguishes from siblings like list_products (multiple), create_product, update_product, and delete_product (mutations).
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 implies the usage context: use when you have a product ID and need a single product. It does not explicitly name alternatives or exclusions, but the contrast with list_products and mutation tools is clear from the wording and sibling context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_productsA
List products with pagination. Limit is between 1 and 100.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the disclosure burden. It mentions pagination and the limit constraint, which is useful. However, it does not describe offset behavior, default sorting, possible empty results, or whether authentication is required. The added limit range is a small but positive contribution.
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?
The description is two short sentences, front-loaded with the primary function, and contains no filler. Every word earns its place, making it highly efficient.
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 simple list tool with an output schema, the description provides the core purpose and one parameter constraint. However, it leaves offset undefined and omits behavioral details like ordering or edge cases. Given the lack of annotations and schema descriptions, it is minimally sufficient but not thorough.
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 0%, so the description must compensate. It explains 'Limit is between 1 and 100,' adding meaning to the limit parameter. However, the offset parameter is not explained at all, only implied by the word 'pagination.' The description covers one of two parameters partially.
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 clearly states the tool's function: 'List products with pagination.' The verb 'list' is specific and distinguishes it from sibling tools like create_product, get_product, update_product, and delete_product. The resource 'products' is unambiguous.
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 implies usage for listing products, but it does not explicitly state when to choose this over get_product or provide any exclusion criteria. The mention of pagination hints at use for large result sets, but no concrete guidance is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_productC
Replace the editable fields of an existing product.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| price | Yes | ||
| stock | Yes | ||
| product_id | Yes | ||
| description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It only says 'Replace the editable fields', which is ambiguous about whether it performs a full replacement or partial update, and it omits any mention of validation, side effects, or error handling.
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?
The description is a single, concise sentence with no wasted words. It is front-loaded and easy to read, though its brevity contributes to insufficient detail.
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?
Given 5 parameters, no annotations, and the presence of an output schema, the description is too sparse. It fails to explain important context like whether the product must exist, whether fields are fully replaced, or how the update interacts with related tools, making it incomplete for reliable use.
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 schema has zero description coverage, and the tool description does not compensate by explaining any of the 5 parameters. The term 'editable fields' is generic and does not clarify the meaning, purpose, or constraints of product_id, name, price, stock, or description.
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 uses a specific verb 'replace' and identifies the resource as 'existing product', which clearly distinguishes it from sibling tools like create_product and delete_product. However, 'editable fields' is vague and doesn't specify which fields are affected.
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 is given on when to use this tool versus alternatives like create_product or update alternatives. There is no mention of prerequisites, exclusions, or a clear use case beyond the implied 'modify an existing product'.
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.
6 tool updates
v0.1.0- First observed
create_product - First observed
database_health - First observed
delete_product - First observed
get_product - First observed
list_products - First observed
update_product
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: health check, create, get, list, update, delete. No overlapping functionality or ambiguity between tools.
CRUD tools follow a consistent verb_noun pattern (create_product, get_product, list_products, update_product, delete_product). database_health breaks the pattern by being noun-only, but it is a single minor deviation.
Six tools is well-scoped for a CRUD server with a health check. Each tool earns its place with no unnecessary additions.
The tool set covers the full product lifecycle: create, read (single and list), update, and delete. The health check adds operational coverage. No obvious gaps for the stated purpose.
Maintenance
Related MCP Connectors
Hosted MCP server for AI-driven data ops. Create apps, manage schemas, and CRUD structured data.
Build multi-tenant apps over MCP. Schemas, CRUD, deploys — access control enforced server-side.
UN FAOSTAT global food & agriculture statistics over a local SQLite mirror, via MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA small MCP server that manages a product inventory using SQLite, providing CRUD operations through exposed MCP tools.-
- AlicenseAqualityCmaintenanceEnables connecting to and querying multiple database types (PostgreSQL, MySQL, SQLite) through a unified interface. Supports managing multiple concurrent database connections with connection pooling and SQL query execution through MCP tools.533 npmMIT
- AlicenseNot gradedqualityAmaintenanceProvides safe, configurable SQL database access via MCP tools, enabling schema introspection, predefined queries, and structured updates with multi-backend support.2MIT
- AlicenseNot gradedqualityCmaintenanceExposes sqlite3 database functionality as MCP tools, enabling SQL query execution, schema management, and CRUD operations.1MIT