Faucet
Connect to PostgreSQL, MySQL, SQL Server, or Oracle databases hosted on Amazon RDS, exposing their schemas and data as REST endpoints and MCP tools for AI agents.
Connect to MariaDB databases (via the MySQL driver), introspect schemas, and expose tables as REST endpoints and MCP tools for CRUD operations.
Connect to MySQL databases, introspect schemas, and expose tables and stored procedures as REST endpoints and MCP tools for CRUD operations.
Connect to MySQL databases hosted on PlanetScale, exposing tables as REST endpoints and MCP tools for CRUD operations.
Connect to PostgreSQL databases, introspect schemas, and expose tables and stored procedures as REST endpoints and MCP tools for CRUD operations, filtering, pagination, and schema management.
Connect to Snowflake data warehouse, introspect schemas, and expose tables as REST endpoints and MCP tools for querying and CRUD operations.
Connect to SQLite databases (local file or in-memory), introspect schemas, and expose tables as REST endpoints and MCP tools for CRUD operations.
Connect to PostgreSQL databases hosted on Supabase, exposing tables and stored procedures as REST endpoints and MCP tools for governed CRUD operations.
What is Faucet?
Faucet is a database-to-REST-API gateway — a lightweight, self-hosted server that connects to your SQL databases, introspects the schema, and generates a full CRUD REST API with authentication, role-based access control (RBAC), and OpenAPI documentation. It also exposes an MCP server at /mcp so AI agents and AI app builders (Claude, ChatGPT, Cursor, VS Code, Windsurf, Base44, Replit) can query your data through the same roles and API keys.
Think of it as an open-source alternative to DreamFactory, PostgREST, or Hasura, with multi-database support, a built-in admin UI, and native AI agent integration, all in a single binary. See how it compares.
Use Cases
Instant backend for apps — Skip writing CRUD APIs by hand. Point Faucet at your database and start building your frontend.
AI agent data access — Give Claude, GPT, or any MCP-compatible agent governed, read/write access to your databases.
Internal tools & dashboards — Generate APIs for internal databases without modifying existing infrastructure.
Legacy database modernization — Put a REST API in front of SQL Server 2012, MySQL 5.7, or PostgreSQL 9.6 without code changes.
Multi-database aggregation — Connect PostgreSQL, MySQL, SQL Server, Oracle, and more to a single Faucet instance and query them all through one API.
Rapid prototyping — Go from empty database to working API in under 60 seconds.
Related MCP server: mcp-backend
How It Works
┌──────────────┐ ┌───────────────────────────────────────┐ ┌──────────────┐
│ PostgreSQL │ │ F A U C E T │ │ REST API │
│ MySQL │──────▶│ │──────▶│ /api/v1/* │
│ MariaDB │ SQL │ ┌─────────┐ ┌──────┐ ┌───────────┐ │ ├──────────────┤
│ SQL Server │◀──────│ │ Schema │ │ RBAC │ │ OpenAPI │ │──────▶│ OpenAPI 3.1 │
│ Oracle │ │ │ Intro- │ │ Auth │ │ Generator │ │ │ /openapi.json│
│ Snowflake │ │ │ spection│ │ │ │ │ │ ├──────────────┤
│ SQLite │ │ └─────────┘ └──────┘ └───────────┘ │──────▶│ MCP Server │
└──────────────┘ │ │ │ (AI Agents) │
│ ┌──────────────────────────────────┐ │ ├──────────────┤
│ │ Embedded Admin UI (Preact) │ │──────▶│ Admin UI │
│ └──────────────────────────────────┘ │ │ :8080/ │
└───────────────────────────────────────┘ └──────────────┘Connect any SQL database → Faucet introspects the schema → Instantly generates REST endpoints, OpenAPI docs, MCP tools, and an Admin UI — all secured with API keys, JWT auth, and role-based permissions.
Screenshots
See the Admin UI guide for a tour of every page.
Key Features
API Generation
Full CRUD REST API — GET, POST, PUT, PATCH, DELETE with filtering, ordering, and pagination
Schema introspection — Discovers tables, columns, types, and constraints at runtime
Schema DDL — Create, alter, and drop tables via API
Stored procedure calls — Execute stored procedures with typed parameters
Human-readable query filters —
(age > 21) AND (status = 'active')OpenAPI 3.1 spec — Auto-generated from live database schema at
/openapi.json
Security & Access Control
API key authentication — SHA-256 hashed keys with per-key role assignment
JWT authentication — HMAC-SHA256 signed tokens for admin sessions
Role-based access control (RBAC) — Per-table verb permissions (GET, POST, PUT, PATCH, DELETE)
Row-level security filters — Filter expressions are stored per access rule and returned by the API; applying them to queries is planned and not enforced yet
Schema contract locking — Lock your API contract against silent breaking schema changes with three modes (none, auto, strict), drift detection, and CLI management
AI Agent Integration (MCP)
Built-in MCP server — 8 tools + 2 resources for Model Context Protocol, served at
/mcpon the same port as the REST APIWorks with your AI tools — Copy-ready configs for Claude Code, Claude Desktop, Cursor, VS Code and Windsurf; ChatGPT via a Custom GPT Action on
/openapi.jsonStreamable HTTP + stdio transport — API-key authenticated over the network, or stdio on your own machine
Governed AI queries — AI agents respect the same RBAC rules as API clients
Developer Experience
Single binary — Zero external dependencies, cross-platform (Linux, macOS, Windows)
Embedded admin UI — connect databases with host, port, user and password (no connection strings), test before saving, browse schemas and data, build roles and keys, and copy ready-made MCP configs for Claude, Cursor, VS Code and more. Works offline; light and dark themes
SQLite config store — All configuration stored locally, no external database required
npm + Homebrew + Docker — Install in seconds on any platform (
npx @faucetdb/faucet)Health endpoints —
/healthzand/readyzfor Kubernetes-style probes
Supported Databases
Database | Versions | Cloud Variants | Tutorial |
PostgreSQL | 9.6 – 17 | Amazon RDS, Aurora, Supabase, Neon, Azure Database | |
MySQL | 5.7 – 9.x | Amazon RDS, Aurora MySQL, PlanetScale, Azure MySQL | |
MariaDB | 10.2 – 11.x | Via MySQL driver | |
SQL Server | 2012 – 2022 | Azure SQL Database, Amazon RDS | |
Oracle | 12c – 26ai | Oracle Cloud (OCI), Amazon RDS, Azure | |
Snowflake | Current | AWS, Azure, GCP | |
SQLite | 3.35+ | Local file, in-memory |
Connector details, SSL options and driver notes: Database connectors.
60-Second Quickstart
Install
npm (Node.js 18+):
npx @faucetdb/faucet serveHomebrew (macOS / Linux):
brew install faucetdb/tap/faucetDocker:
docker run -p 8080:8080 -v faucet-data:/data faucetdb/faucetGo:
go install github.com/faucetdb/faucet/cmd/faucet@latestBinary download: See GitHub Releases for pre-built binaries (Linux, macOS, Windows).
Run
faucet serveOpen http://localhost:8080. The setup wizard creates your admin account and connects your first database: pick the engine, enter host, port, username and password, click Test connection, and save. Every table gets REST endpoints at /api/v1/<name>/_table/<table> and MCP tools right away. Then create a role on the Roles page and an API key on the API keys page, which hands you a ready-to-run curl command and an MCP setup command that already contain the new key.
Prefer the terminal? The same steps with the CLI:
# Create an admin account and add a database (no connection string needed)
faucet admin create --email admin@example.com --password changeme123
faucet db add --name mydb --driver postgres \
--host localhost --user app --password 's3cret@!' --database mydb
# Create a role that can read every database, then an API key bound to it
faucet role create --name default --verbs GET
faucet key create --role default
# Start the server (it loads databases on startup), then query your data
faucet serve
curl -H "X-API-Key: faucet_YOUR_KEY_HERE" "http://localhost:8080/api/v1/mydb/_table/users?limit=10"--dsn still works if you already have a connection string. A running server picks up databases added through the admin UI or API immediately; databases added with faucet db add are loaded the next time the server starts.
MCP Server for AI Agents
Faucet includes a built-in Model Context Protocol (MCP) server, so AI agents such as Claude, Cursor, VS Code Copilot and Windsurf can query and modify your databases through governed, tool-based access.
faucet serve exposes the MCP server at http://localhost:8080/mcp (Streamable HTTP), on the same port as the REST API. Authenticate with an API key in the X-API-Key header. The key's role controls which databases and tables the agent can see and change, exactly as for the REST API.
The AI agents (MCP) page in the admin UI generates every config below with your key filled in. Replace YOUR_API_KEY with a key from the API keys page or faucet key create.
Claude Code
claude mcp add --transport http faucet http://localhost:8080/mcp \
--header "X-API-Key: YOUR_API_KEY"Cursor, VS Code, Windsurf
Cursor (~/.cursor/mcp.json or .cursor/mcp.json):
{
"mcpServers": {
"faucet": {
"url": "http://localhost:8080/mcp",
"headers": { "X-API-Key": "YOUR_API_KEY" }
}
}
}VS Code (.vscode/mcp.json, used by Copilot Chat in agent mode):
{
"servers": {
"faucet": {
"type": "http",
"url": "http://localhost:8080/mcp",
"headers": { "X-API-Key": "YOUR_API_KEY" }
}
}
}Windsurf (~/.codeium/windsurf/mcp_config.json): the same as Cursor, with serverUrl instead of url.
Claude Desktop
Claude Desktop's config file only launches local commands, so use the mcp-remote bridge (needs Node.js) in claude_desktop_config.json:
{
"mcpServers": {
"faucet": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8080/mcp", "--header", "X-API-Key:YOUR_API_KEY"]
}
}
}For a Faucet server on another machine over plain http://, add "--allow-http" to the args. See examples/claude-desktop-config.json.
ChatGPT
ChatGPT connectors sign in with OAuth, which Faucet does not support. Use a Custom GPT Action instead: expose Faucet over HTTPS, import https://your-host/openapi.json, and set authentication to API key with the custom header X-API-Key.
Local stdio (your machine only)
MCP clients can also launch Faucet as a subprocess. stdio mode reads the databases configured with faucet serve or faucet db add (~/.faucet by default) and runs with local admin rights: roles are not applied. Use it only on your own machine; for anything shared, use /mcp with an API key.
{
"mcpServers": {
"faucet": {
"command": "npx",
"args": ["-y", "@faucetdb/faucet", "mcp"]
}
}
}The same config is in examples/mcp-stdio-config.json. If faucet is installed (Homebrew, Go or a release binary), use "command": "faucet", "args": ["mcp"]. faucet mcp --transport http --port 3001 runs a standalone, API-key authenticated HTTP server on its own port.
Full guide, including a curl test and the OpenAI Responses API: MCP server docs.
Available MCP Tools
Tool | Description |
| List all connected databases |
| List tables in a database |
| Get column names, types, and constraints |
| Query records with filters, ordering, pagination |
| Insert new records |
| Update existing records |
| Delete records |
| Execute raw SQL (admin only) |
CLI Reference
faucet serve # Start HTTP server (default :8080)
faucet db add NAME # Add database connection
faucet db list # List configured databases
faucet db test NAME # Test database connectivity
faucet db schema NAME # Dump database schema
faucet db lock NAME # Lock schema contract
faucet db unlock NAME # Remove contract locks
faucet db diff NAME # Show schema drift
faucet db promote NAME # Promote contracts to match live schema
faucet key create # Create API key
faucet key list # List API keys
faucet role create # Create RBAC role (--verbs grants its first rule)
faucet role grant # Add an access rule to a role
faucet role list # List roles and their rules
faucet admin create # Create admin account
faucet mcp # Start MCP server (stdio)
faucet openapi # Generate OpenAPI spec
faucet config set KEY VALUE # Set configuration value
faucet version # Show version infoAccess rules (RBAC)
A role is a list of rules {service_name, component, verb_mask}. An API key inherits the rules of the role it is bound to; every request is checked against them. Admin JWT sessions (the dashboard and /api/v1/system/*) bypass RBAC.
Verb bits — combine with bitwise OR:
Verb | Bit |
GET | 1 |
POST | 2 |
PUT | 4 |
PATCH | 8 |
DELETE | 16 |
all | 31 |
Matching (case-sensitive — patterns must match the service and table names exactly as they appear in the URL):
service_name:*(any service), an exact name (mydb), or a prefix wildcard (prod_*)component:*(anything), an exact component (_table/customers,_schema), a prefix wildcard (_table/*— every table and the_tablelisting), or a bare name (customers, which matches_table/customers,_schema/customers, ...)
Fail closed. A role with no rules, a rule with verb_mask 0, or an inactive role denies everything with 403 and an error envelope that says why:
{"error":{"code":403,"message":"Role \"readonly\" does not permit POST on mydb/_table/orders",
"context":{"role":"readonly","service":"mydb","component":"_table/orders","verb":"POST"}}}Services flagged read_only reject every non-GET request regardless of role.
MCP. Tools map onto the same verbs: faucet_query = GET, faucet_insert = POST, faucet_update = PATCH, faucet_delete = DELETE, faucet_list_tables = GET on _table, faucet_describe_table = GET on _schema/{table}. faucet_raw_sql requires all five verbs on a rule matching component _sql (e.g. *). faucet_list_services only lists services the role can reach. faucet mcp in stdio mode runs with local admin privileges; faucet mcp --transport http requires the same API key or JWT credentials as the main server.
Granting rules from the CLI:
faucet role create --name readonly --verbs GET # GET on every service
faucet role grant --role readonly --service mydb --component "_table/orders" --verbs GET,POSTor through the admin API, which replaces the whole rule list:
curl -X PUT -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
http://localhost:8080/api/v1/system/role/1 -d '{
"name": "readonly",
"is_active": true,
"access": [
{"service_name": "*", "component": "*", "verb_mask": 1, "requestor_mask": 1, "filters": [], "filter_op": "AND"},
{"service_name": "mydb", "component": "_table/orders", "verb_mask": 3, "requestor_mask": 1, "filters": [], "filter_op": "AND"}
]
}'Row-level
filterson a rule are stored and returned by the API but are not yet applied to queries.
Upgrading. Before this fix, role rules were stored but never enforced for API-key requests. Roles created with faucet role create that were never given rules will now be denied with 403 — grant them rules with faucet role grant or the admin UI. Roles created in the admin UI default to GET-only on all services, so API keys that previously wrote data through such roles now need POST/PUT/PATCH/DELETE granted explicitly. On startup faucet serve logs a warning for every role that has active API keys but would deny all requests (no rules, only verb_mask: 0 rules, or inactive), together with the faucet role grant command that fixes it.
The admin JWT signing secret is no longer a built-in default: when auth.jwt_secret / FAUCET_AUTH_JWT_SECRET (alias FAUCET_JWT_SECRET) is not configured, a random secret is generated on first start and persisted in the data directory. Existing admin sessions are invalidated by the upgrade unless the secret was already configured — log in again.
API Routes
GET /healthz # Liveness probe
GET /readyz # Readiness probe
GET /openapi.json # OpenAPI 3.1 spec
POST /api/v1/system/admin/session # Admin login
GET /api/v1/system/service # List services
POST /api/v1/system/service # Create service
GET /api/v1/system/role # List roles
POST /api/v1/system/role # Create role
POST /api/v1/system/api-key # Create API key
GET /api/v1/{service}/_table # List tables
GET /api/v1/{service}/_table/{table} # Query records
POST /api/v1/{service}/_table/{table} # Insert records
PUT /api/v1/{service}/_table/{table} # Replace records
PATCH /api/v1/{service}/_table/{table} # Update records
DELETE /api/v1/{service}/_table/{table} # Delete records
GET /api/v1/{service}/_schema # List table schemas
POST /api/v1/{service}/_schema # Create table
GET /api/v1/{service}/_proc # List stored procedures
POST /api/v1/{service}/_proc/{proc} # Call procedureQuery Parameters
Parameter | Example | Description |
|
| SQL-style filter syntax with safe parameterization |
|
| Sort order |
|
| Max records to return |
|
| Skip N records for pagination |
|
| Select specific columns |
|
| Filter by primary key values |
|
| Include total record count in response metadata |
Faucet vs PostgREST vs Hasura vs DreamFactory vs Supabase
A short comparison of how each project is shaped. It covers only facts you can check in each project's own docs; if something here is out of date, please open an issue.
Faucet | PostgREST | Hasura | DreamFactory | Supabase | |
Primary API | REST + OpenAPI 3.1, plus a built-in MCP endpoint at | REST | GraphQL-first | REST | REST (via PostgREST), realtime, auth, storage |
Databases | PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, Snowflake, SQLite | PostgreSQL | PostgreSQL plus other sources via connectors | Many SQL and NoSQL sources | PostgreSQL |
Admin UI | Embedded in the binary | None | Console | Web admin app | Studio |
How you run it | Single Go binary, config in embedded SQLite | Single binary | Engine plus a Postgres metadata database (v2) | PHP/Laravel application | Hosted platform, or self-host a multi-service Docker stack |
License | MIT | MIT | Apache 2.0 (graphql-engine repo) | Apache 2.0 (open-source edition), paid editions available | Apache 2.0 |
FAQ
What is Faucet? Faucet is an open-source (MIT) single Go binary that turns a SQL database into a REST API and an MCP server for AI agents. It supports PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, Snowflake and SQLite, and includes RBAC, an OpenAPI 3.1 spec and a built-in admin UI.
Which databases does Faucet support? Seven: PostgreSQL, MySQL, MariaDB (through the MySQL driver), SQL Server, Oracle, Snowflake and SQLite. See Supported Databases for versions and per-database tutorials.
How do I connect Claude Code or Claude Desktop to my database?
Run faucet serve, connect your database in the admin UI, create an API key, then run claude mcp add --transport http faucet http://localhost:8080/mcp --header "X-API-Key: YOUR_API_KEY". Claude Desktop uses the mcp-remote bridge; see Claude Desktop.
How do I connect Cursor, VS Code or Windsurf?
Add http://localhost:8080/mcp as an HTTP MCP server with an X-API-Key header. Copy-paste configs are in Cursor, VS Code, Windsurf and on the admin UI's AI agents (MCP) page.
How do I connect ChatGPT to my database?
Expose Faucet over HTTPS, create an API key with a read-only role, and add a Custom GPT Action that imports https://your-host/openapi.json with API-key authentication (header X-API-Key). ChatGPT connectors need OAuth, which Faucet does not support.
Can I use Faucet with Base44, Replit or other AI app builders?
Yes. Expose Faucet over HTTPS and create a scoped API key. Then add https://your-host/mcp with an X-API-Key header as a custom MCP server, or call the REST API (/api/v1/...) and OpenAPI spec (/openapi.json) from your app.
Is Faucet self-hosted? Where does my data live?
Yes. Faucet runs wherever you run it (your laptop, a server next to an on-prem database, a container) and talks to your database directly; rows are not copied anywhere. Its own configuration (connections, roles, API keys, admin accounts) is stored in an embedded SQLite file in the data directory (~/.faucet by default, /data in Docker). Anonymous usage telemetry is described, with how to turn it off, in TELEMETRY.md.
Is Faucet free? Yes. Faucet is open source under the MIT license, with no paid tiers for core functionality.
How is Faucet different from PostgREST? PostgREST only supports PostgreSQL. Faucet supports 7 databases (PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, Snowflake, SQLite), includes a built-in admin UI, and provides native MCP support for AI agents, all in a single binary.
How is Faucet different from Hasura? Hasura is GraphQL-first. Faucet generates REST APIs with an OpenAPI 3.1 spec (not GraphQL), runs as a single binary that keeps its configuration in an embedded SQLite file, and includes a built-in MCP server for AI agents.
How is Faucet different from DreamFactory? DreamFactory is a PHP/Laravel application that runs on a web server stack with PHP. Faucet is a single Go binary with no runtime dependencies. Faucet is fully open-source under the MIT license with all features included, with no paid tiers required for core functionality.
How is Faucet different from Supabase? Supabase is a PostgreSQL platform (database, auth, storage, realtime) that you use hosted or self-host as a set of services. Faucet does not host your data: it puts a REST API and an MCP server in front of a database you already have, including MySQL, SQL Server, Oracle, Snowflake and SQLite.
Does Faucet support GraphQL? Not currently. Faucet generates REST APIs and OpenAPI 3.1 specs. GraphQL support may be added in the future.
Is Faucet production-ready? Faucet is under active development. It is suitable for internal tools, prototyping, and AI agent integration. Check the releases page for the latest version.
Can AI agents write data through Faucet?
Yes. MCP tools include faucet_insert, faucet_update, and faucet_delete. All operations respect RBAC roles, so you can give AI agents read-only or read-write access per table. Raw SQL is off unless you allow it for a service and grant all verbs.
Does Faucet require a separate database for configuration? No. Faucet uses an embedded SQLite database for all configuration, credentials, roles, and API keys. Everything is stored locally in a single file.
Building from Source
git clone https://github.com/faucetdb/faucet.git
cd faucet
make build # Builds UI + Go binary
make test # Runs all tests
make dev # Dev mode with hot reloadTech Stack
Go 1.25+ — Chi router, sqlx, Cobra/Viper CLI
Preact + Vite + Tailwind — Embedded admin UI
SQLite (pure Go, no CGO) — Configuration store
MCP (Model Context Protocol) — AI agent integration
Documentation
Full documentation is at wiki.faucetdb.ai:
Getting started: install, connect a database, make your first request
Admin UI guide: a tour of every page
MCP server: connect Claude, Cursor, VS Code, Windsurf and ChatGPT
Deployment: Docker, Kubernetes, systemd, reverse proxies, production checklist
Database connectors and tutorials for PostgreSQL, MySQL / MariaDB, SQL Server, Oracle, Snowflake and SQLite
LLM guide: a compact reference written for AI coding assistants
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines, or open an issue to report bugs and request features.
License
MIT — free for commercial and personal use.
Available Tools
8 toolsfaucet_deleteA
Delete records from a database table that match a filter expression. A filter is required to prevent accidental full-table deletes. Returns the number of deleted records. Requires DELETE permission on the table.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | Name of the table to delete from | |
| filter | Yes | Filter expression to select records to delete (e.g. "status = 'expired'") | |
| service | Yes | Name of the database service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only supply readOnlyHint=false, so the description usefully adds three behavioral facts: the mandatory filter guards against full-table deletes, the call returns a count of deleted records, and DELETE permission on the table is required. That is meaningful auth and safety context beyond the annotation, though reversibility/transaction behavior is unstated.
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?
Four short sentences, each adding distinct information (action, safety constraint, return value, permission requirement) with the core purpose front-loaded. No filler.
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 destructive three-parameter tool with no output schema, the description covers the safety guard, the return value, and the required permission, leaving nothing an agent needs in order to 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 all three parameters are already documented with an example filter expression; the description adds only the rationale for why filter is mandatory. This is the expected baseline when the schema carries parameter detail.
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 (Delete) and resource (records from a database table) plus the matching condition, which cleanly separates it from siblings like faucet_insert, faucet_update, and faucet_query without opening a schema.
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 imposes a hard constraint ('a filter is required') that implies usage, but never states when to choose faucet_delete over faucet_raw_sql or faucet_update, nor any exclusions. Guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_describe_tableARead-only
Get the detailed schema for a specific table, including all columns with their types, nullability, defaults, primary keys, foreign keys, and indexes. Use this to understand table structure before writing queries. Requires GET permission on the table's schema (_schema/{table}).
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | Name of the table to describe | |
| service | Yes | Name of the database service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already signals a safe read, and the description usefully adds the authorization requirement (GET permission on the table's schema). It goes beyond the annotation with an access constraint, though it does not discuss rate limits or result size behavior.
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?
Three tight clauses: what is returned, when to use it, and the permission requirement. The return contents are front-loaded and every sentence carries distinct information with no filler.
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 output schema, the description compensates by spelling out the return contents (columns, keys, indexes), and it also covers the permission prerequisite. For a two-parameter read-only tool this is sufficient for an agent to 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 both parameters (service, table) are already documented in the schema. The description adds no format, naming, or lookup detail beyond what the schema provides, which is the expected baseline when structured fields do the work.
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 (detailed schema for a specific table) and enumerates exactly what is returned: columns, types, nullability, defaults, primary keys, foreign keys, and indexes. This clearly separates it from siblings like faucet_list_tables (enumerates tables) and faucet_query (runs queries).
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?
Gives concrete usage context: 'Use this to understand table structure before writing queries.' That orients the agent well, but it names no alternative or exclusion condition (e.g., when to prefer faucet_list_tables or faucet_raw_sql), so it stops short of explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_insertA
Insert one or more records into a database table. Each record is a JSON object mapping column names to values. Returns the inserted records (with auto-generated fields like IDs) if the database supports RETURNING. Requires POST permission on the table.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | Name of the table to insert into | |
| records | Yes | Array of record objects to insert (e.g. [{"name": "Alice", "age": 30}]) | |
| service | Yes | Name of the database service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=false, a thin safety signal. The description adds real behavioral context beyond that: the record payload shape, that returned rows include auto-generated fields only when the database supports RETURNING, and the POST permission requirement. Error/conflict behavior is still unstated.
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?
Three sentences, front-loaded with the core action, with the payload format, return behavior and permission caveat each earning their place. No redundancy or filler.
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 output schema, the description usefully covers return-value behavior (RETURNING) and the permission prerequisite, and all three parameters are documented by the schema. Missing only failure/conflict semantics, which is tolerable here.
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 coverage is 100%, so the baseline is 3. The description goes slightly beyond the schema by explaining that each record maps column names to values, clarifying the semantics of the 'records' array beyond the schema's example.
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 (insert), resource (database table) and scope (one or more records), which is unambiguous next to siblings like faucet_update, faucet_delete and faucet_query. It does not, however, explicitly name or route against any sibling, 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The tool's purpose implies its use (add rows to a table), and one prerequisite is stated ('Requires POST permission on the table'). But there is no guidance on when to prefer this over faucet_raw_sql or faucet_update, and no exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_list_servicesARead-only
List all database services configured in Faucet. Returns each service's name, driver type, active status, and access mode. Use this first to discover available databases before querying. Only services your role has access to are listed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds real context beyond that: the exact shape of each returned record and the role-based access filter ('Only services your role has access to are listed'), which tells the agent results may be silently scoped. It omits pagination/empty-result behavior, so not 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action, then return shape, then usage order. Every sentence carries information an agent needs; nothing is padding.
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?
There is no output schema, and the description compensates by naming the returned fields (name, driver type, active status, access mode). Combined with the zero-parameter schema and readOnly annotation, an agent has everything needed to call this 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?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. No parameter-level gaps are possible here.
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 ('List all database services configured in Faucet') and enumerates the fields returned, which lets an agent distinguish it from faucet_list_tables and faucet_query without opening a schema. The resource scope 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?
'Use this first to discover available databases before querying' gives explicit sequencing relative to the query tools, which is genuine when-to-use guidance. It stops short of naming the closest alternative (faucet_list_tables) or stating when not to use it, so it is clear but not complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_list_tablesARead-only
List all tables in a database service, including approximate row counts and column summaries. Use this to explore what data is available before querying specific tables. Requires GET permission on _table.
| Name | Required | Description | Default |
|---|---|---|---|
| service | Yes | Name of the database service to list tables for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true, so the description adds meaningful value by disclosing the permission requirement ('Requires GET permission on _table') and the approximate nature of row counts. That is well beyond structured data. It stops short of 5 because it doesn't describe pagination behavior, scope limits, or what happens with large schemas.
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?
Three tight sentences: what it returns, when to use it, and the permission requirement. Nothing is wasted and the payload (what you get back) is front-loaded.
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 read-only, single-parameter listing tool with no output schema, the description covers purpose, usage context, return contents, and auth needs. The only gap is the absence of pagination or volume guidance, which is minor but real for a 'list all tables' operation.
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 coverage is 100% and the single 'service' parameter is fully described in the schema as the database service to list tables for. The description adds no syntax, format, or lookup guidance beyond that, so 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 and resource ('List all tables in a database service') and distinguishes itself from siblings like faucet_describe_table and faucet_query by promising row counts and column summaries. An agent can immediately tell what data comes back.
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?
Gives clear context: 'Use this to explore what data is available before querying specific tables.' That is a real when-to-use signal pointing at faucet_query as the downstream step. It does not name explicit alternatives or exclusions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_queryARead-only
Query records from a database table with optional filtering, field selection, ordering, and pagination. Returns results as JSON. Requires GET permission on the table.
Filter syntax (DreamFactory-compatible):
Simple: name = 'John'
Comparison: age > 21, price <= 100
Logical: status = 'active' AND role = 'admin'
IN: status IN ('active', 'pending')
LIKE: name LIKE 'J%'
NULL: email IS NOT NULL
BETWEEN: age BETWEEN 18 AND 65
CONTAINS: name CONTAINS 'smith'
Order syntax: 'column ASC, other_column DESC'
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | Comma-separated columns to GROUP BY (e.g. "region,status"). Aggregate in 'fields' to compute per group; order by an aggregate's alias. | |
| limit | No | Maximum number of records to return (default 25, max 1000) | |
| order | No | Order clause (e.g. "created_at DESC, name ASC") | |
| table | Yes | Name of the table to query | |
| fields | No | List of columns to return, each either a plain column or an aggregate such as "SUM(amount)", "COUNT(*)", or "AVG(price) AS avg_price". Omit for all columns. | |
| filter | No | Filter expression (e.g. "status = 'active' AND age > 21") | |
| offset | No | Number of records to skip for pagination | |
| service | Yes | Name of the database service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint=true annotation is consistent with the read semantics. The description goes beyond it by disclosing the authorization requirement (GET permission on the table) and the response format (JSON), plus default/max record behavior via the schema. It does not cover things like row-limit enforcement errors or pagination end conditions, but it adds real context over the annotation.
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?
Purpose and permission requirement are front-loaded, followed by an efficiently bulleted syntax reference. The length is justified by the query-language surface area, though the filter example list is somewhat padded with overlapping comparison forms.
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 an 8-parameter query tool with no output schema, the description covers return format, auth needs, and both filter and order grammars, which is most of what an agent needs. The main gap is the absence of any statement about limitations relative to faucet_raw_sql (joins, subqueries) and about pagination behavior such as limit/offset interaction.
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 coverage is 100%, so the baseline is 3, but the description adds materially useful semantics: a full DreamFactory-compatible filter operator reference (comparisons, AND/OR, IN, LIKE, IS NOT NULL, BETWEEN, CONTAINS) and order-clause syntax. That enriches 'filter' and 'order' well beyond the schema's single-line examples.
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 ("Query records from a database table") and enumerates its supported capabilities: filtering, field selection, ordering, pagination, JSON output. An agent can readily distinguish this from faucet_insert/delete/update. It stops short of naming a sibling (e.g. faucet_raw_sql) for advanced cases, so it is clear but not fully differentiated.
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?
"Requires GET permission on the table" is a genuinely useful precondition for deciding whether to call it. Otherwise there is no explicit when-to-use/when-not-to-use guidance and no routing to alternatives such as faucet_raw_sql for complex or join-style queries. Usage is implied by the read-oriented verb rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_raw_sqlA
Execute a raw SQL query against a database service. Only available for services with raw_sql_allowed enabled. Use faucet_list_services to check which services allow raw SQL. Because arbitrary SQL can touch any object, it requires a role rule granting all verbs (GET, POST, PUT, PATCH, DELETE) on the _sql component of the service.
The statement is executed as-is and may modify data; it is refused on services flagged read_only. Parameters should be passed as an array and referenced with positional placeholders ($1, $2 for PostgreSQL; ?, ? for MySQL).
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | SQL query to execute | |
| limit | No | Maximum number of rows to return (default 100, max 10000) | |
| params | No | Positional parameters for the SQL query | |
| service | Yes | Name of the database service | |
| timeout | No | Query timeout in seconds (default 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give readOnlyHint=false, but the description adds substantial context beyond that: the RBAC requirement (role rule granting all verbs on _sql), the as-is execution semantics, the refusal on read_only services, and the placeholder syntax per dialect. This is rich behavioral disclosure the annotations do not cover.
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?
Front-loaded with purpose and availability, then permissions, then execution semantics and parameter syntax. Every sentence earns its place with only minor density in the middle clause about role rules.
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?
Complete for a dangerous arbitrary-SQL tool: availability gate, permission requirement, mutation warning, and dialect-specific parameter syntax are all covered. A mention of return shape would help, but no output schema exists and the query-result nature is inferable.
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 coverage is 100%, so the schema already documents all five parameters. The description adds useful detail on params syntax ($1 vs ?) that goes beyond the schema's generic 'Positional parameters' text, but does not cover limit or timeout nuances.
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 ('Execute a raw SQL query') and immediately scopes when it applies ('Only available for services with raw_sql_allowed enabled'). This clearly distinguishes it from siblings like faucet_query and faucet_insert, which are narrower typed 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?
Explicitly names the alternative tool to check availability ('Use faucet_list_services to check which services allow raw SQL') and states the exclusion condition (refused on read_only services). When-to-use and when-not-to-use are both present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
faucet_updateA
Update records in a database table that match a filter expression. The record object contains the column values to set. A filter is required to prevent accidental full-table updates. Requires PATCH permission on the table.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | Name of the table to update | |
| filter | Yes | Filter expression to select records to update (e.g. "id = 42") | |
| record | Yes | Object with column names and new values (e.g. {"status": "archived"}) | |
| service | Yes | Name of the database service |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With only readOnlyHint=false provided, the description adds real behavioral context: the filter is mandatory specifically to prevent accidental full-table updates, and PATCH permission on the table is required. These are destructive-safety and auth details the annotation does not convey.
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?
Three tight sentences with the core action, the record semantics, the safety constraint, and the permission requirement front-loaded. No filler, though the record clause is mildly redundant with the schema.
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 mutation tool with no output schema, the description covers what it does, the mandatory filter safeguard, and the required permission. It omits any return-value expectation or confirmation behavior, but nothing critical to invoking it correctly 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 schema already documents all four parameters. The description reinforces that record holds column values to set and that filter selects the target rows, but adds no syntax or format details beyond the schema, so 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 clear verb (update) and resource (records in a database table matching a filter), which distinguishes it from faucet_insert and faucet_delete. It does not explicitly name a sibling or draw the line against faucet_raw_sql, 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description names a safety constraint (filter required) and a permission prerequisite, but never says when to choose this over faucet_raw_sql, faucet_query, or faucet_insert. There is no when-not guidance and no alternative routing, leaving usage largely to inference.
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
faucet_delete - First observed
faucet_describe_table - First observed
faucet_insert - First observed
faucet_list_services - First observed
faucet_list_tables - First observed
faucet_query - First observed
faucet_raw_sql - First observed
faucet_update
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose: insert/update/delete for writes, query for structured reads, raw_sql for arbitrary SQL, and list_services/list_tables/describe_table for introspection. The query vs raw_sql overlap is well-resolved by descriptions (table-scoped filtering vs arbitrary SQL). No two tools are genuinely confusable.
All eight tools share the faucet_ prefix and follow a consistent verb_noun or verb_resource pattern (faucet_insert, faucet_list_tables, faucet_describe_table, faucet_raw_sql). Naming is uniform and predictable throughout.
Eight tools is well-scoped for a database access gateway, covering discovery, introspection, CRUD, and an escape hatch without redundancy. Every tool earns its place.
The surface covers the full data lifecycle: list services, list tables, describe schema, query, insert, update, delete, plus raw SQL for advanced cases. No obvious gaps in CRUD or introspection for this domain.
Maintenance
Related MCP Connectors
Build multi-tenant apps over MCP. Schemas, CRUD, deploys — access control enforced server-side.
Hosted MCP server for AI-driven data ops. Create apps, manage schemas, and CRUD structured data.
Butterbase MCP server — manage your backend: schemas, auth, functions, storage, RAG, deploys.
Build, deploy, and host full-stack web apps from any MCP client. DB, auth, storage, cron included.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA runtime-configurable MCP server for Supabase databases that enables dynamic tool creation through JSON configuration. Build custom database operations (select, insert, update, delete) without writing code, with built-in authentication and template support.9 npm11MIT
- AlicenseBqualityCmaintenanceMCP server providing backend access to PostgreSQL, Storage (Supabase/S3), Iceberg data lake, and SQL seeds. It offers 32 tools for database queries, storage operations, seed management, and more.313MIT
- AlicenseAqualityDmaintenanceA self-hostable PostgreSQL MCP server for exploring database schemas and running guarded read/write queries with selectable access modes (readonly, readwrite, admin), plus a dry-run confirm workflow for safety.141MIT
- AlicenseNot gradedqualityAmaintenanceEnables secure, controlled access to existing relational databases via MCP, with API key authorization, read/write permissions, table-level allow/deny lists, SQL validation, rate limiting, audit logging, and a web management console. Supports PostgreSQL, MySQL, SQLite, SQL Server, and Oracle.4 npm1MIT