tusk-mcp
Provides read-only access to PostgreSQL databases, enabling schema introspection and the execution of SELECT-only SQL queries to retrieve data from tables and views.
Allows for secure credential retrieval by supporting HashiCorp Vault commands to fetch database passwords during connection setup.
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., "@tusk-mcpshow me the schema of the users table"
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.
tusk-mcp
PostgreSQL MCP server for AI agents. Exposes schema introspection and SELECT-only query execution over the Model Context Protocol, with write access opt-in per target.
Install
# npx (no install needed)
npx tusk-mcp --host db.example.com --database mydb
# or clone + run
bun install
bun run src/index.ts --host localhost --database mydbRelated MCP server: MCP Server for Database
Setup UI
Interactive browser-based setup that generates config for Claude Desktop, Claude Code, Cursor, Windsurf, and OpenAI Codex.
npx tusk-mcp setupBuild standalone binary
bun run build # Windows
bun run build:linux # Linux
bun run build:macos # macOS ARMConnection
Individual flags (recommended)
tusk-mcp --host db.example.com --port 5432 --user admin --password 'p@ss' --database mydbConnection string
tusk-mcp --connection-string "postgres://admin:p%40ss@db.example.com:5432/mydb"Unencoded special characters in passwords (@, #) are handled automatically.
Environment variables
PGHOST=db.example.com PGDATABASE=mydb tusk-mcpPriority: flags > --connection-string > DATABASE_URL > PG* env vars
Multiple environments / databases
A config file defines named targets: environments (local/stage/prod) or entirely different databases within one app. tusk.config.jsonc or tusk.config.json in the working directory is picked up automatically when no connection flags are given; --config <path> (relative or absolute) loads an explicit file. Connection flags cannot be combined with a config file.
{
"defaultTarget": "local", // used when a tool call omits target
"defaults": { // merged under every target
"user": "app",
"database": "myapp"
},
"targets": {
"local": { "host": "localhost", "access": "write", "description": "dev" },
"stage": {
"host": "stage.db.internal",
"password": "${STAGE_DB_PASSWORD}", // env var interpolation
"ssl": true
},
"prod": {
"connectionString": "postgres://ro:${PROD_DB_PASSWORD}@10.0.0.5:5432/myapp",
"ssh": { "host": "bastion.example.com", "user": "deploy", "key": "~/.ssh/id_rsa" },
"access": "structure", // schema visible, queries disabled
"description": "production"
},
"analytics": { "host": "warehouse.db", "database": "events" }
}
}Target fields mirror the CLI flags: host, port, user, password, passwordFile, passwordCmd, database, connectionString, ssl (true or {ca, cert, key} paths), ssh ({host, port, user, key, password}), access, description. structureOnly: true is still read as access: "structure"; setting both to different levels is a config error.
Priority: explicit fields > connectionString > defaults. ssh/ssl objects deep-merge, so defaults.ssh can hold the shared bastion and a target override just the port. ${VAR} interpolates from the environment in any string, so the file is safe to commit. Config-file targets ignore PG* env vars; use ${PGPASSWORD} explicitly if wanted.
With multiple targets every tool takes a target enum parameter (optional when defaultTarget is set, absent entirely with a single target), the target list is announced via MCP instructions, and compare-schemas becomes available. Connections are lazy per target: an unreachable bastion never blocks startup or the other targets.
Password security
# From file (Docker/K8s secrets)
tusk-mcp --host db --database mydb --password-file /run/secrets/db_pass
# From command (any secrets manager)
tusk-mcp --host db --database mydb --password-cmd 'vault kv get -field=password secret/db'
tusk-mcp --host db --database mydb --password-cmd 'op read op://vault/db/password'SSL
Providing any certificate file automatically enables SSL.
tusk-mcp --host db --database mydb --ssl-ca /path/to/ca.crt # CA verification
tusk-mcp --host db --database mydb \ # mutual TLS
--ssl-ca ca.crt --ssl-cert client.crt --ssl-key client.keySSH tunnel
tusk-mcp --host db-internal --database mydb \
--ssh-host bastion.example.com --ssh-user deploy --ssh-key ~/.ssh/id_rsaAccess levels
Each target has one access level, read by default.
| Tools | Connection |
|
| read-only transactions |
| plus | read-only transactions |
| plus | writes allowed, through |
tusk-mcp --host db --database mydb --structure-only # every target: structure
tusk-mcp --host db --database mydb --allow-writes # every target: writeThe two flags are mutually exclusive. --structure-only also narrows a config file, but --allow-writes is rejected alongside one: escalating a target to writes has to be written in the file, where it is reviewable, rather than in an MCP client's command line.
execute-query cannot mutate on any target, write-enabled ones included: every query runs inside a READ ONLY transaction, so a SELECT that hides an INSERT behind a volatile function is refused by the server, not just by the SQL parser. read and structure connections additionally start with default_transaction_read_only. Writes therefore only ever happen through execute-write, which is registered only when some target allows them and whose target parameter lists write-enabled targets only.
execute-write takes one statement per call, reports the affected row count, and previews RETURNING rows. Beyond the target gate it does not filter SQL: on a write target the database role is the boundary, so give that role only the privileges the agent should have.
Tools
Tool | Description |
| All schemas with tables, views, and estimated row counts in one call (partitions filtered out) |
| Columns, types, PKs, FKs, and enum values for one or more tables per call |
| Read-only SQL with limit (rejected on structure-only targets) |
| One mutating statement with affected rows and |
| Structural diff of a schema between two targets (multi-target only) |
Output format
Tool results use compact text in content for the AI model and JSON-safe
preview data in structuredContent for clients that support structured MCP
output. Query text uses a tab-delimited preview with null=\N; strings are
JSON-quoted, so empty strings render as "" and the literal string "\\N" is
distinct from SQL null. With multiple targets, results start with a
target=<name> line.
MCP config
{
"mcpServers": {
"tusk": {
"command": "npx",
"args": ["-y", "tusk-mcp", "--host", "localhost", "--database", "mydb"]
}
}
}Claude Code
claude mcp add --transport stdio tusk -- npx -y tusk-mcp --host localhost --database mydbOpenAI Codex (~/.codex/config.toml)
[mcp_servers.tusk]
command = "npx"
args = ["-y", "tusk-mcp", "--host", "localhost", "--database", "mydb"]All flags
Flag | Type | Default | Description |
| string | - | Multi-target config file (see above) |
| string | localhost | PostgreSQL host |
| number | 5432 | PostgreSQL port |
| string | - | Database user |
| string | - | Database password |
| string | - | Read password from file |
| string | - | Run command for password |
| string | - | Database name |
| string | - | Full connection URL |
| boolean | false | Enable SSL without certificate verification |
| string | - | CA certificate path (enables SSL) |
| string | - | Client certificate path (enables SSL) |
| string | - | Client key path (enables SSL) |
| string | - | SSH tunnel host |
| number | 22 | SSH tunnel port |
| string | - | SSH username |
| string | - | SSH private key path |
| string | - | SSH password |
| boolean | false | Schema only, no |
| boolean | false | Add |
This server cannot be deployed
Maintenance
Related MCP Connectors
- dataOAuthco.thinair
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Draxlr's remote MCP server connects AI assistants to your SQL databases and dashboards. Explore schemas, run read-only queries, manage saved queries and dashboards, and export results, all with row-level security so each user sees only their own data.
Query your Postgres from ChatGPT or Claude without exposing the database or handing over credentials. Run npx boltschema connect next to your database and it dials out over HTTPS — no inbound firewall rule, no open port, works with localhost and VPC-private databases. Read-only is enforced by a SQL guard, a Postgres READ ONLY transaction, and a scoped role generated for you.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceRead-only PostgreSQL MCP server that enables running SELECT queries, listing tables and schemas, and describing columns, with built-in protection against writes and malicious SQL attacks.442 npmMIT
- FlicenseNot gradedqualityFmaintenanceA read-only MCP server that enables AI agents to explore database schemas and execute safe queries on PostgreSQL and MySQL.-
- AlicenseNot gradedqualityAmaintenanceA hardened, read-only Postgres MCP server that enables LLMs to safely query databases without write, DDL, shell, or credential exposure.MIT
- AlicenseNot gradedqualityBmaintenanceA zero-config, read-only PostgreSQL MCP server that enforces read-only access at the database level using READ ONLY transactions, allowing AI agents to safely explore schemas and run SELECT queries without risk of mutation.13 npmMIT