valv — Claude Code MCP server: query SQL databases safely
Hooks your agent up to a live database through a connection string. Reads only by default, and your policies decide what it can see.
claude mcp add --env DATABASE_URL=<DATABASE_URL> --env VALV_PROVIDER=<VALV_PROVIDER> --env VALV_DATABASE=<VALV_DATABASE> --env VALV_TABLES=<VALV_TABLES> --env VALV_EXCLUDE=<VALV_EXCLUDE> --transport stdio mcp -- npx -y @valv/mcpWhat valv does
The server takes a database URL, inspects the schema on its own, and exposes four tools to the agent: list_resources, search_resources, describe_resource and query. No SQL text ever reaches the model — it goes through those calls instead. PostgreSQL, MySQL, SQLite, CockroachDB, ClickHouse and MongoDB are supported.
Setup runs fastest with npx @valv/mcp init. It probes the database, shows your tables, asks which access level you want, then merges the server entry into Claude, Claude Desktop, Cursor or Codex without touching what is already in the config. Doing it by hand means an mcpServers block in .mcp.json with DATABASE_URL under env. ClickHouse wants an HTTP URL plus a database name in VALV_DATABASE; MongoDB needs VALV_DATABASE when the URL does not pick one.
With no policy file, every table is readable. The moment you set VALV_POLICY_FILE, tables that have no policy are denied — deny-all. Hiding columns or filtering rows also happens in that module. Per-request scoping by tenant or user does not belong here; your app supplies real identity through @valv/mcp-sdk.
What it helps with
- let an agent read a database without handing it SQL access
- expose only chosen tables with the
VALV_TABLESallow-list - keep internal columns away from the model via a policy
- wire one database into several editors
- serve the server over HTTP instead of stdio with
VALV_HTTP_PORT
Example prompts for the agent
- List the tables in this database and describe the
ordersschema - Find everything in the database related to last month's orders
- Build a
valv-map.htmloverview of the database
How to install valv
Platform CLI
claude mcp add --env DATABASE_URL=<DATABASE_URL> --env VALV_PROVIDER=<VALV_PROVIDER> --env VALV_DATABASE=<VALV_DATABASE> --env VALV_TABLES=<VALV_TABLES> --env VALV_EXCLUDE=<VALV_EXCLUDE> --transport stdio mcp -- npx -y @valv/mcpReplace <…> with your own values. 3 more environment variables are in the server README
Platform CLI
codex mcp add mcp --env DATABASE_URL=<DATABASE_URL> --env VALV_PROVIDER=<VALV_PROVIDER> --env VALV_DATABASE=<VALV_DATABASE> --env VALV_TABLES=<VALV_TABLES> --env VALV_EXCLUDE=<VALV_EXCLUDE> -- npx -y @valv/mcpReplace <…> with your own values. 3 more environment variables are in the server README
Config file
{
"mcpServers": {
"mcp": {
"command": "npx",
"args": [
"-y",
"@valv/mcp"
],
"env": {
"DATABASE_URL": "<DATABASE_URL>",
"VALV_PROVIDER": "<VALV_PROVIDER>",
"VALV_DATABASE": "<VALV_DATABASE>",
"VALV_TABLES": "<VALV_TABLES>",
"VALV_EXCLUDE": "<VALV_EXCLUDE>"
}
}
}
}Replace <…> with your own values. 3 more environment variables are in the server README
Config file
{
"servers": {
"mcp": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@valv/mcp"
],
"env": {
"DATABASE_URL": "<DATABASE_URL>",
"VALV_PROVIDER": "<VALV_PROVIDER>",
"VALV_DATABASE": "<VALV_DATABASE>",
"VALV_TABLES": "<VALV_TABLES>",
"VALV_EXCLUDE": "<VALV_EXCLUDE>"
}
}
}
}Replace <…> with your own values. 3 more environment variables are in the server README
Platform CLI
gemini mcp add -e DATABASE_URL=<DATABASE_URL> -e VALV_PROVIDER=<VALV_PROVIDER> -e VALV_DATABASE=<VALV_DATABASE> -e VALV_TABLES=<VALV_TABLES> -e VALV_EXCLUDE=<VALV_EXCLUDE> mcp npx -y @valv/mcpReplace <…> with your own values. 3 more environment variables are in the server README
Step by step, with commands for each platform: How to add an MCP server to Claude Code, Codex, Cursor, VS Code, Gemini CLI and more
Questions about valv
How do I install valv in Claude Code?
Run claude mcp add mcp -e DATABASE_URL=<DATABASE_URL> -- npx -y @valv/mcp. For provider, database, table lists and exclusions, use the longer form with `--env VALV_PROVIDER=<VALV_PROVIDER> --env VALV_DATABASE=<VALV_DATABASE> --env VALV_TABLES=<VALV_TABLES> --env VALV_EXCLUDE=<VALV_EXCLUDE> and --transport stdio`.
What does valv do?
It introspects the connected database and gives the agent four tools for browsing and querying it. Access is read-only by default, and policies control which tables and columns are visible at all.
What limits what the agent can read?
VALV_TABLES sets an allow-list of tables and VALV_EXCLUDE a deny-list applied after it. A policy file set through VALV_POLICY_FILE hides columns and filters rows, and tables without a policy are closed.