grain-tools 0.10.8 → 0.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -15
- package/dist/web-app.html +3 -3
- package/out/server/standalone.js +36 -9
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -105,38 +105,41 @@ named connection profile when you open **Grain: Show Welcome Guide** or
|
|
|
105
105
|
|
|
106
106
|
## Quick Start: MCP Agents
|
|
107
107
|
|
|
108
|
-
###
|
|
108
|
+
### Install once, then connect every client
|
|
109
109
|
|
|
110
110
|
```
|
|
111
|
-
|
|
111
|
+
grain --stdio
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
This is the normal command for an installed Grain setup on every platform. It
|
|
115
|
+
attaches to the shared local Grain service when that service is available, so
|
|
116
|
+
connections and result tabs stay shared. If the service cannot be reached, the
|
|
117
|
+
bridge reports isolated mode and its sessions do not appear in the editor.
|
|
116
118
|
|
|
117
119
|
1. Run **Grain: Manage Connections** and confirm your active connection.
|
|
118
120
|
2. Open the Grain settings panel and **enable the MCP server** (`grain.mcpEnabled`).
|
|
119
121
|
This is required and ships **off** — the daemon serves no MCP surface until you turn it on.
|
|
120
122
|
3. Keep safe mode enabled unless you explicitly want agents to run mutating SQL.
|
|
121
123
|
4. Give your client the command:
|
|
122
|
-
- **Claude Code**: `claude mcp add grain --
|
|
124
|
+
- **Claude Code**: `claude mcp add grain -- grain --stdio`
|
|
123
125
|
- **Cursor**: Settings → MCP Servers → Add new MCP server, type `command`,
|
|
124
|
-
command `
|
|
125
|
-
- **VS Code**:
|
|
126
|
-
|
|
127
|
-
the command
|
|
126
|
+
command `grain --stdio`
|
|
127
|
+
- **VS Code**: add `grain --stdio` through **MCP: Open User Configuration**;
|
|
128
|
+
VS Code uses a `servers` key rather than `mcpServers`
|
|
128
129
|
- **Claude Desktop and other file-configured clients**: see
|
|
129
130
|
[the setup guide](docs/engineering/guides/mcp-client-setup.md), which
|
|
130
131
|
transcribes the same command into that client's config file
|
|
131
132
|
|
|
132
|
-
This bridges to the
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
This bridges to the shared Grain service, so agent queries and sessions show up
|
|
134
|
+
in the results grid alongside anything you run from the editor. It works with
|
|
135
|
+
every MCP client — including ones that cannot send
|
|
135
136
|
custom HTTP headers, such as Claude Desktop — and it needs no credential in your
|
|
136
137
|
config, because the bridge reads the daemon's access token itself.
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
To try Grain without installing it, use `npx -y grain-tools --stdio`. This
|
|
140
|
+
requires Node.js and may run in isolated mode when no shared Grain service is
|
|
141
|
+
available, so it is a trial and headless path rather than the recommended
|
|
142
|
+
desktop setup.
|
|
140
143
|
|
|
141
144
|
Enabling `grain.mcpEnabled` in the Grain settings panel is required
|
|
142
145
|
for this stdio bridge too. Launching the bridge without it produces a clear
|
|
@@ -199,7 +202,7 @@ command carries its own connection profiles through the environment:
|
|
|
199
202
|
|
|
200
203
|
```bash
|
|
201
204
|
GRAIN_CONNECTIONS='[{"id":"analytics","name":"Analytics","type":"postgres","host":"localhost","port":5432,"user":"analyst","database":"warehouse","password":"YOUR_PASSWORD"}]' \
|
|
202
|
-
|
|
205
|
+
grain --stdio --embedded
|
|
203
206
|
```
|
|
204
207
|
|
|
205
208
|
The same variable goes in an `env` block for a file-configured client; see
|
package/dist/web-app.html
CHANGED
|
@@ -150744,8 +150744,8 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
150744
150744
|
const mcpClientConfig = `{
|
|
150745
150745
|
"mcpServers": {
|
|
150746
150746
|
"grain": {
|
|
150747
|
-
"command": "
|
|
150748
|
-
"args": ["
|
|
150747
|
+
"command": "grain",
|
|
150748
|
+
"args": ["--stdio"]
|
|
150749
150749
|
}
|
|
150750
150750
|
}
|
|
150751
150751
|
}`;
|
|
@@ -151291,7 +151291,7 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151291
151291
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Client configuration (recommended)" }),
|
|
151292
151292
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsCopyButton, { text: mcpClientConfig, label: "Copy client configuration" })
|
|
151293
151293
|
] }),
|
|
151294
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-description", children: "
|
|
151294
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-description", children: "Uses the installed Grain service, so connections and result tabs stay shared. GUI clients that cannot find your shell PATH may need the full path to Grain." }),
|
|
151295
151295
|
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-settings-code-block", "data-testid": "mcp-client-config", children: mcpClientConfig })
|
|
151296
151296
|
] }),
|
|
151297
151297
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
package/out/server/standalone.js
CHANGED
|
@@ -21724,6 +21724,9 @@ async function probeRegistration(runner, command, args) {
|
|
|
21724
21724
|
const result = await runner.run(command, args);
|
|
21725
21725
|
return result.exitCode === 0;
|
|
21726
21726
|
}
|
|
21727
|
+
function isCommandMissing(error52) {
|
|
21728
|
+
return error52?.code === "ENOENT";
|
|
21729
|
+
}
|
|
21727
21730
|
function createSupervisorAdapter(platform2, runner, uid) {
|
|
21728
21731
|
if (platform2 === "darwin") {
|
|
21729
21732
|
const target = (identifier) => `gui/${uid}/${identifier}`;
|
|
@@ -21736,10 +21739,26 @@ function createSupervisorAdapter(platform2, runner, uid) {
|
|
|
21736
21739
|
}
|
|
21737
21740
|
if (platform2 === "linux") {
|
|
21738
21741
|
return {
|
|
21739
|
-
isRegistered: (identifier) =>
|
|
21742
|
+
isRegistered: async (identifier) => {
|
|
21743
|
+
try {
|
|
21744
|
+
return await probeRegistration(runner, "systemctl", ["--user", "is-enabled", identifier]);
|
|
21745
|
+
} catch (error52) {
|
|
21746
|
+
if (isCommandMissing(error52)) {
|
|
21747
|
+
return false;
|
|
21748
|
+
}
|
|
21749
|
+
throw error52;
|
|
21750
|
+
}
|
|
21751
|
+
},
|
|
21740
21752
|
register: async (_unitPath, identifier) => {
|
|
21741
|
-
|
|
21742
|
-
|
|
21753
|
+
try {
|
|
21754
|
+
await runRegistration(platform2, runner, "systemctl", ["--user", "daemon-reload"]);
|
|
21755
|
+
await runRegistration(platform2, runner, "systemctl", ["--user", "enable", identifier]);
|
|
21756
|
+
} catch (error52) {
|
|
21757
|
+
if (isCommandMissing(error52)) {
|
|
21758
|
+
throw new ServiceManagerMissingError("systemctl was not found");
|
|
21759
|
+
}
|
|
21760
|
+
throw error52;
|
|
21761
|
+
}
|
|
21743
21762
|
},
|
|
21744
21763
|
unregister: async (identifier) => {
|
|
21745
21764
|
await runner.run("systemctl", ["--user", "stop", identifier]);
|
|
@@ -21766,13 +21785,15 @@ function createSupervisorAdapter(platform2, runner, uid) {
|
|
|
21766
21785
|
start: (identifier) => runStart(runner, "schtasks", ["/Run", "/TN", identifier])
|
|
21767
21786
|
};
|
|
21768
21787
|
}
|
|
21769
|
-
var import_child_process2, UserServicesForbiddenError;
|
|
21788
|
+
var import_child_process2, UserServicesForbiddenError, ServiceManagerMissingError;
|
|
21770
21789
|
var init_supervisorAdapter = __esm({
|
|
21771
21790
|
"src/server/install/supervisorAdapter.ts"() {
|
|
21772
21791
|
"use strict";
|
|
21773
21792
|
import_child_process2 = require("child_process");
|
|
21774
21793
|
UserServicesForbiddenError = class extends Error {
|
|
21775
21794
|
};
|
|
21795
|
+
ServiceManagerMissingError = class extends UserServicesForbiddenError {
|
|
21796
|
+
};
|
|
21776
21797
|
}
|
|
21777
21798
|
});
|
|
21778
21799
|
|
|
@@ -21783,7 +21804,7 @@ var require_package = __commonJS({
|
|
|
21783
21804
|
name: "grain",
|
|
21784
21805
|
displayName: "Grain SQL",
|
|
21785
21806
|
description: "Run SQL in VS Code and expose safe, visible MCP database tools for Claude, Cursor, and other AI agents.",
|
|
21786
|
-
version: "0.10.
|
|
21807
|
+
version: "0.10.9",
|
|
21787
21808
|
license: "UNLICENSED",
|
|
21788
21809
|
mcpName: "io.github.pattrnlabs/grain",
|
|
21789
21810
|
publisher: "pattrnlabs",
|
|
@@ -22185,7 +22206,7 @@ var require_package = __commonJS({
|
|
|
22185
22206
|
"grain.mcpEnabled": {
|
|
22186
22207
|
type: "boolean",
|
|
22187
22208
|
default: false,
|
|
22188
|
-
description: "(Beta) Serve the MCP surface so LLM agents can interact with Grain. When off, the daemon does not register /mcp at all. Changing this restarts the daemon.
|
|
22209
|
+
description: "(Beta) Serve the MCP surface so LLM agents can interact with Grain. When off, the daemon does not register /mcp at all. Changing this restarts the daemon. An explicitly launched stdio bridge is treated as consent and still works; to refuse MCP everywhere, set mcp.enabled to false in ~/.grain/daemon.json.",
|
|
22189
22210
|
order: 20
|
|
22190
22211
|
},
|
|
22191
22212
|
"grain.mcpSafeMode": {
|
|
@@ -249855,9 +249876,15 @@ async function installCommand(deps = {}) {
|
|
|
249855
249876
|
} catch {
|
|
249856
249877
|
}
|
|
249857
249878
|
writeServiceMode(fileSystem, configHome, { mode: "spawn-on-demand" });
|
|
249858
|
-
|
|
249859
|
-
|
|
249860
|
-
|
|
249879
|
+
if (error52 instanceof ServiceManagerMissingError) {
|
|
249880
|
+
writeOutput(
|
|
249881
|
+
"This machine has no service manager (systemctl was not found). Grain will start when needed instead of staying running; the first request may take a moment longer."
|
|
249882
|
+
);
|
|
249883
|
+
} else {
|
|
249884
|
+
writeOutput(
|
|
249885
|
+
"This machine does not permit background services. Grain will start when needed instead of staying running; the first request may take a moment longer."
|
|
249886
|
+
);
|
|
249887
|
+
}
|
|
249861
249888
|
return 0;
|
|
249862
249889
|
}
|
|
249863
249890
|
const failure = new AppError("service_supervisor_registration_failed", describeError(error52), {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grain-tools",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9",
|
|
4
4
|
"mcpName": "io.github.pattrnlabs/grain",
|
|
5
5
|
"description": "Standalone Grain MCP database server for VS Code, Claude Desktop, Cursor, and other MCP clients.",
|
|
6
6
|
"main": "out/server/standalone.js",
|
package/server.json
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
"source": "github",
|
|
9
9
|
"id": "1348511592"
|
|
10
10
|
},
|
|
11
|
-
"version": "0.10.
|
|
11
|
+
"version": "0.10.9",
|
|
12
12
|
"websiteUrl": "https://grain.tools",
|
|
13
13
|
"packages": [
|
|
14
14
|
{
|
|
15
15
|
"registryType": "npm",
|
|
16
16
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
17
17
|
"identifier": "grain-tools",
|
|
18
|
-
"version": "0.10.
|
|
18
|
+
"version": "0.10.9",
|
|
19
19
|
"runtimeHint": "npx",
|
|
20
20
|
"runtimeArguments": [
|
|
21
21
|
{
|