{"_id":"@abhishekmcp/sql","name":"@abhishekmcp/sql","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@abhishekmcp/sql","version":"0.1.0","description":"MCP server for SQL databases — read-only querying and schema introspection over Postgres and SQLite, with a gated write mode, from any MCP client.","mcpName":"io.github.Abhishekkumar2021/sql","type":"module","bin":{"mcp-sql":"dist/index.js"},"publishConfig":{"access":"public","provenance":true},"scripts":{"build":"tsc","watch":"tsc --watch","start":"node dist/index.js","dev":"tsc && node dist/index.js","test":"npm run build && node --test test/*.test.mjs","build:mcpb":"node scripts/build-mcpb.mjs","prepublishOnly":"npm run build"},"keywords":["mcp","modelcontextprotocol","sql","postgres","sqlite","claude"],"author":{"name":"Abhishek","url":"https://github.com/Abhishekkumar2021"},"license":"MIT","homepage":"https://github.com/Abhishekkumar2021/mcp-suite/tree/main/servers/sql#readme","repository":{"type":"git","url":"git+https://github.com/Abhishekkumar2021/mcp-suite.git","directory":"servers/sql"},"bugs":{"url":"https://github.com/Abhishekkumar2021/mcp-suite/issues"},"engines":{"node":">=18"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","pg":"^8.13.0","sql.js":"^1.14.0","zod":"^3.23.8"},"devDependencies":{"@types/node":"^22.0.0","@types/pg":"^8.11.0","@types/sql.js":"^1.4.9","typescript":"^5.6.0"},"gitHead":"123bc4d496efd696e99f022a34c7aa2079dbad40","_id":"@abhishekmcp/sql@0.1.0","_nodeVersion":"24.13.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-rryY9ub730mIqWzj8BKxkN8bYduVk9/+PM0divDgI576rx+D0LCrw3TunOGaa1l2cwemiLzC37KvU6dyNwFSnw==","shasum":"41e368eef3688b163d31444d97345e39c6c41b3d","tarball":"https://registry.npmjs.org/@abhishekmcp/sql/-/sql-0.1.0.tgz","fileCount":29,"unpackedSize":70564,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCqKBU9Fy7ecWC31U0fMGDjFjJbUjciDMn0k9ZQZCyWWwIgGN3goiuQTqF7/HF3O9uJLVNAFAG3hfnAv+95xB8vXhM="}]},"_npmUser":{"name":"abhishek.opensource","email":"abhishek.opensource.dev@gmail.com"},"directories":{},"maintainers":[{"name":"abhishek.opensource","email":"abhishek.opensource.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sql_0.1.0_1783187216782_0.8997675723374106"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-04T17:46:56.557Z","0.1.0":"2026-07-04T17:46:56.922Z","modified":"2026-07-04T17:46:57.147Z"},"maintainers":[{"name":"abhishek.opensource","email":"abhishek.opensource.dev@gmail.com"}],"description":"MCP server for SQL databases — read-only querying and schema introspection over Postgres and SQLite, with a gated write mode, from any MCP client.","homepage":"https://github.com/Abhishekkumar2021/mcp-suite/tree/main/servers/sql#readme","keywords":["mcp","modelcontextprotocol","sql","postgres","sqlite","claude"],"repository":{"type":"git","url":"git+https://github.com/Abhishekkumar2021/mcp-suite.git","directory":"servers/sql"},"author":{"name":"Abhishek","url":"https://github.com/Abhishekkumar2021"},"bugs":{"url":"https://github.com/Abhishekkumar2021/mcp-suite/issues"},"license":"MIT","readme":"# @abhishekmcp/sql\n\nA read-first SQL [MCP](https://modelcontextprotocol.io) server: query and introspect **Postgres** and\n**SQLite** databases from any MCP client. Built on pure-JS drivers — `pg` for Postgres and `sql.js`\n(WebAssembly) for SQLite — so there are **no native dependencies** and nothing to compile. Databases are\nreferenced by **named connections** (`DB_CONN_<name>`); credentials never appear in tool arguments or logs.\n\nReads are the default and are enforced with defense-in-depth; writes are **off unless you opt in** with\n`DB_WRITABLE=1`.\n\n## Tools\n\n**Read (always):**\n- `list_connections` — configured connection names + types (no credentials returned)\n- `list_schemas` — schemas in a connection (SQLite returns `main`)\n- `list_tables` — tables and views in a schema\n- `describe_table` — columns (type/nullable/default), primary key, foreign keys, and indexes\n- `list_indexes` — indexes on a table (name, columns, uniqueness)\n- `relationships` — foreign-key relationships in a schema (`from table.column → to table.column`)\n- `query` — run a read-only `SELECT`/`WITH`/`VALUES` (positional params; row/cell-capped)\n- `explain` — query plan for a `SELECT` (server prepends `EXPLAIN`; nothing is executed)\n- `sample_table` — up to `limit` rows from a table (`SELECT * … LIMIT`)\n\n**Write (only when `DB_WRITABLE=1`):**\n- `execute` — run one write statement (`INSERT`/`UPDATE`/`DELETE`/DDL), positional params\n- `execute_script` — run multiple statements in a single transaction (rolls back on error)\n\n> Write tools are simply **not registered** (absent from `tools/list`) unless `DB_WRITABLE` is set.\n\n## Configuration\n\n| Variable | Default | Effect |\n|----------|---------|--------|\n| `DB_CONN_<name>` | — | Defines a connection called `<name>`. Value is a connection URL: `postgres://user:pass@host:5432/db` or `sqlite:/absolute/path/app.db`. Define as many as you like (e.g. `DB_CONN_pg`, `DB_CONN_local`). **SQLite paths must be ABSOLUTE.** |\n| `DB_WRITABLE` | `0` | `1`/`true` registers the write tools (`execute`, `execute_script`). |\n| `DB_MAX_ROWS` | `1000` | Max rows returned by `query`/`sample_table` (result is truncated + flagged). |\n| `DB_MAX_CELL_BYTES` | `8192` | Max bytes per cell before truncation (keeps output token-cheap). |\n| `DB_STATEMENT_TIMEOUT_MS` | `15000` | Per-statement timeout — **Postgres only** (`SET statement_timeout`). SQLite queries run synchronously in-process (`sql.js`), so they can't be interrupted by a wall-clock timer; they're bounded by the row cap (`DB_MAX_ROWS`) and file-size cap (`DB_SQLITE_MAX_BYTES`) instead. |\n| `DB_SQLITE_MAX_BYTES` | `536870912` (512 MB) | Refuse to open a SQLite file larger than this (`sql.js` loads the DB into memory). |\n| `SQL_AUDIT_LOG` | — | Path to a JSON-lines file; each executed **write** statement is appended (never contains credentials). |\n\nConnection URLs carry credentials, so they live only in the environment — tools take a connection **name**,\nnever a URL. Any credential that leaks into an error message is redacted.\n\n## Read-only enforcement\n\nRead tools are protected at three layers, so a bypass at one layer is still caught by the next:\n\n1. **Statement guard** — `query`/`explain` reject anything that isn't a single `SELECT`/`WITH`/`VALUES`\n   statement (comments stripped; multiple statements rejected).\n2. **Postgres** — the query runs inside a `READ ONLY` transaction, so the engine itself refuses writes.\n3. **SQLite** — the connection sets `PRAGMA query_only = ON` for read tools, so writes error at the engine.\n\n## Limitations\n\n- `execute_script` splits the input on top-level `;` and does **not** support Postgres dollar-quoted bodies\n  (`$$ … $$`, e.g. `CREATE FUNCTION`). Run those through `execute` as a single statement instead.\n- MySQL is not supported; connections are runtime-static (defined via env, not added at runtime); no migrations.\n\n## Usage\n\n```bash\n# Claude Code (plugin):  /plugin marketplace add Abhishekkumar2021/mcp-suite  →  /plugin install sql\n# Claude Code (manual):\nclaude mcp add sql --env DB_CONN_local=sqlite:/abs/path/app.db -- npx -y @abhishekmcp/sql\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"sql\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@abhishekmcp/sql\"],\n      \"env\": {\n        \"DB_CONN_pg\": \"postgres://user:pass@localhost:5432/app\",\n        \"DB_CONN_local\": \"sqlite:/absolute/path/to/app.db\",\n        \"DB_WRITABLE\": \"0\"\n      }\n    }\n  }\n}\n```\n\n**Claude Desktop (MCPB):** drag `sql-*.mcpb` from the [latest release](https://github.com/Abhishekkumar2021/mcp-suite/releases) into Settings → Extensions, then set the connection URL (mapped to the `default` connection) and, optionally, enable writes. Build it locally with `npm run build:mcpb -w servers/sql`.\n\n## Manual Postgres check\n\nCI covers SQLite only (hermetic — no server needed). To verify Postgres against a live database:\n\n```bash\n# 1. Start a throwaway Postgres (Docker) and load a row:\ndocker run --rm -d --name sqlmcp-pg -e POSTGRES_PASSWORD=pw -p 5432:5432 postgres:16\nsleep 5\ndocker exec -i sqlmcp-pg psql -U postgres -c \\\n  \"CREATE TABLE author (id serial primary key, name text); INSERT INTO author(name) VALUES ('Ada');\"\n\n# 2. Build, then run a stdio smoke test against the connection:\nnpm run build -w servers/sql\nexport DB_CONN_pg=\"postgres://postgres:pw@localhost:5432/postgres\"\nnode servers/sql/dist/index.js   # then write JSON-RPC to stdin:\n#   {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"t\",\"version\":\"1\"}}}\n#   {\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}\n#   {\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"query\",\"arguments\":{\"connection\":\"pg\",\"sql\":\"SELECT name FROM author\"}}}\n# Expect a result row containing \"Ada\". Also try list_tables / describe_table.\n\ndocker rm -f sqlmcp-pg\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-a5f78dc58b717efea8804a91fc62e9e6"}