Connect your agent
Grain speaks the Model Context Protocol, so agent clients — Claude Desktop, Claude Code, Cursor, Copilot, Windsurf, Codex — can run queries, list schemas, and describe tables against your own databases.
The one command
There is one command, and it is the same on macOS, Linux, and Windows:
npx -y grain-tools --stdio
That is the whole setup contract. Everything below is how to hand that one command to a particular client.
--stdio takes no value. -y skips npm’s install prompt — an MCP client launches the server with no terminal attached, so a prompt would have nobody to answer it. Do not drop the flag.
Before you connect
- Have connections. Install the extension and add a connection profile, or supply profiles through
GRAIN_CONNECTIONS— see Headless connections. - Turn the MCP surface on. It ships off. Set
grain.mcpEnabledin the Grain settings panel, or"mcp": { "enabled": true }in~/.grain/daemon.json. Without it the bridge refuses explicitly rather than failing quietly. - Leave safe mode on unless you intend agents to run mutating SQL.
Clients that take a command
Claude Code
claude mcp add grain -- npx -y grain-tools --stdio
Cursor
Settings → MCP Servers → Add new MCP server. Type command, name grain, command npx -y grain-tools --stdio.
Windsurf
Settings → Cascade → MCP Servers → Add Server, then paste the same JSON as Claude Desktop below into ~/.codeium/windsurf/mcp_config.json.
VS Code and Copilot
VS Code reads MCP servers from .vscode/mcp.json in the workspace, or from your user mcp.json via MCP: Open User Configuration in the command palette. Note the key is servers, not mcpServers:
{
"servers": {
"grain": {
"type": "stdio",
"command": "npx",
"args": ["-y", "grain-tools", "--stdio"]
}
}
}
Copilot Chat in agent mode picks the server up from the same file.
Codex
Add the server to ~/.codex/config.toml:
[mcp_servers.grain]
command = "npx"
args = ["-y", "grain-tools", "--stdio"]
Clients that take only a config file
Claude Desktop has no command-line registration, so it is configured by file. The JSON is a transcription of the one command above, not a second way of setting Grain up — if the two ever disagree, the command is right.
Config file location:
- macOS —
~/Library/Application Support/Claude/claude_desktop_config.json - Windows —
%APPDATA%\Claude\claude_desktop_config.json. Paste that path intoWin + R; create the file if it is not there.
{
"mcpServers": {
"grain": {
"command": "npx",
"args": ["-y", "grain-tools", "--stdio"]
}
}
}
Restart the client fully after editing. If the file already has an mcpServers object, add only the "grain" entry inside it.
Headless connections
By default the bridge attaches to the daemon your editor is already running, so agent queries land in the same result tabs as your own. For CI, or for a client that should not share the editor’s daemon, give the server its own profiles:
{
"mcpServers": {
"grain": {
"command": "npx",
"args": ["-y", "grain-tools", "--stdio"],
"env": {
"GRAIN_CONNECTIONS": "[{\"id\":\"analytics\",\"name\":\"Analytics\",\"type\":\"postgres\",\"host\":\"localhost\",\"port\":5432,\"user\":\"analyst\",\"database\":\"warehouse\",\"password\":\"YOUR_PASSWORD\"}]",
"GRAIN_EMBEDDED": "1"
}
}
}
}
GRAIN_EMBEDDED=1 forces an isolated daemon rather than attaching to a shared one, which is what you want in CI.
Plaintext passwords in a config file are convenient and not secure. Prefer a driver-specific variable such as PGPASSWORD where the connector supports it, or create the profile in the editor and let the bridge read the daemon’s own credentials.
Environment variables
| Variable | Effect |
|---|---|
GRAIN_CONNECTIONS |
JSON array of connection profiles, for headless use |
GRAIN_MCP_SAFE_MODE |
false allows mutating SQL. Defaults to true |
GRAIN_MAX_ROWS |
Row cap for query tools. Defaults to 10000 |
GRAIN_HOME |
Which config directory — and so which daemon — is used |
GRAIN_EMBEDDED |
1 forces an isolated daemon instead of attaching |
Running without a registry
If npx cannot reach npm — an offline machine, or a blocked registry — run the server file directly. It is the same file the three published commands alias.
{
"mcpServers": {
"grain": {
"command": "node",
"args": ["C:\\Users\\YourName\\grain\\standalone.js", "--stdio"]
}
}
}
Use forward slashes or doubled backslashes in JSON paths.
The tools you get
Grain advertises 20 tools. A tool a profile does not permit is still advertised and still answers — with an explicit refusal naming the profile, so an agent can tell “not allowed here” from “does not exist”.
| Group | Tools |
|---|---|
| Query | run_query, cancel_query |
| Schema | list_schemas, list_tables, describe_table |
| Connections | list_connectors, list_connections, test_connection, save_connection, delete_connection, request_connection_credentials |
| Result tabs | get_tab_info, close_tab, list_sessions |
| Charts | render_chart, save_chart, list_charts |
| Audit | ledger_stats, verify_ledger |
| Telemetry | record_ui_event |
An agent attached through the packaged bridge runs under the agent profile: it may read, query, and chart, but save_connection, delete_connection, and request_connection_credentials are refused. It cannot change your saved connections or ask for your stored credentials.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| No tools appear in the client | Node is missing, or the client was not fully restarted |
npx not found on Windows |
Reinstall Node.js LTS with “Add to PATH” checked |
| The bridge starts and then stops | grain.mcpEnabled is off. Turn it on, or set mcp.enabled in ~/.grain/daemon.json |
| Agent queries are not in the grid | The bridge found no shared daemon and started its own. The initialize response reports Grain isolation mode: shared or isolated |
| A tool answers with a refusal | The profile refuses that tool’s resource class. The message names both |
Identifiers
- VS Code extension id
pattrnlabs.grain- npm package name
grain-tools- stdio command
npx -y grain-tools --stdio
MCP Configuration
{
"mcpServers": {
"grain": {
"command": "npx",
"args": [
"-y",
"grain-tools",
"--stdio"
]
}
}
}