rubien-mcp-server 0.3.0 → 0.3.2

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 CHANGED
@@ -18,7 +18,7 @@ The server is only a wrapper. It needs **Node.js ≥ 20** and the `rubien-cli` b
18
18
  ```
19
19
  Tarball: <https://github.com/devzhk/Rubien-releases/releases>. Don't put the bare binary on `PATH` alone — it loses its resource bundles.
20
20
 
21
- At startup the server checks the CLI's build and exits with an update instruction if it's too old. Update via Rubien.app / Sparkle on Mac, or `rubien-cli self-update` on Linux.
21
+ The server checks the CLI's build (`MIN_CLI_BUILD`). In stdio mode it starts either way: if the CLI is missing or too old, every tool call returns the update instruction as its result, re-checked per call — so updating Rubien mid-session recovers on the next call, with no client restart. (Versions ≤ 0.3.0 exited at startup instead, which Claude Desktop rendered as an opaque "Server disconnected" — see [Troubleshooting](#troubleshooting-server-disconnected-in-claude-desktop).) In `--http` mode the server still exits at startup, where stderr is visible in your terminal. Update via Rubien.app / Sparkle on Mac, or `rubien-cli self-update` on Linux.
22
22
 
23
23
  ## Install
24
24
 
@@ -54,10 +54,17 @@ The `npx -y rubien-mcp-server` install is **unpinned**, so there is nothing to r
54
54
  1. **Update Rubien first** — Sparkle on Mac (Rubien → Settings → Check Now), `rubien-cli self-update` on Linux. The server needs the new `rubien-cli`.
55
55
  2. **Restart your MCP client** — quit/reopen Claude Desktop, or start a new Claude Code session. The respawned server is the latest release.
56
56
 
57
- The pairing is guarded in one direction: a new server against a too-old Rubien **exits at startup with an update instruction** (`MIN_CLI_BUILD`), so a half-upgrade fails fast instead of half-working. The other direction is why upgrading matters — an old server against a new Rubien breaks at tool-call time when it shells subcommands that no longer exist (server < 0.3.0 vs Rubien ≥ 0.4.0: the 0.4.0 CLI cutover removed `import`, `add --identifier`, `views --query`, and the legacy `properties` write flags that 0.1.x/0.2.x servers shell out to; those server versions are deprecated on npm for this reason).
57
+ The pairing is guarded in one direction: a new server against a too-old Rubien **refuses every tool call with an update instruction** (`MIN_CLI_BUILD`), so a half-upgrade fails loudly instead of half-working. The other direction is why upgrading matters — an old server against a new Rubien breaks at tool-call time when it shells subcommands that no longer exist (server < 0.3.0 vs Rubien ≥ 0.4.0: the 0.4.0 CLI cutover removed `import`, `add --identifier`, `views --query`, and the legacy `properties` write flags that 0.1.x/0.2.x servers shell out to; those server versions are deprecated on npm for this reason).
58
58
 
59
59
  If a stale `npx` cache ever keeps serving an old version after a restart, clear it (`rm -rf ~/.npm/_npx`) or pin `rubien-mcp-server@latest` in the config. HTTP mode (below) runs as a long-lived process you started yourself — it does not auto-upgrade; restart it after updating Rubien.
60
60
 
61
+ ### Troubleshooting: "Server disconnected" in Claude Desktop
62
+
63
+ Claude Desktop never shows an MCP server's stderr — the actual error is in `~/Library/Logs/Claude/mcp-server-rubien.log`. Two known causes, both typically surfacing right after a reboot, because Claude Desktop only respawns MCP servers when the app itself relaunches:
64
+
65
+ - **Stale Rubien vs auto-upgraded server.** The unpinned `npx -y` install picks up new server releases at respawn; if Rubien.app hasn't been updated, the log shows `needs build >= N`. Fix: open Rubien.app and let Sparkle update it. Server ≥ 0.3.1 no longer disconnects for this — the instruction is returned to Claude on each tool call instead — but older servers exited at startup with only this log line as evidence.
66
+ - **No network at spawn.** `npx` resolves the package version against the npm registry on *every* spawn, even with a warm cache. If Claude Desktop launches at login before Wi-Fi/VPN is up, the spawn fails (`ENOTFOUND`/`ECONNREFUSED registry.npmjs.org` in the log) and Claude Desktop does not retry. Fix: quit and reopen Claude Desktop once online. To remove the network dependency entirely, install globally and point the config at the absolute path (`npm install -g rubien-mcp-server`, then `which rubien-mcp-server`) — at the cost of upgrading by hand with `npm update -g rubien-mcp-server`.
67
+
61
68
  ## claude.ai web (remote MCP server)
62
69
 
63
70
  claude.ai connects to rubien as a **remote MCP server** over Streamable HTTP — it can't spawn a local process. It's the *same npm package* in HTTP mode: the server still runs on your Mac (where the library and `rubien-cli` live), and claude.ai reaches it through a Cloudflare Tunnel, with a bearer token to keep strangers out.
@@ -129,7 +136,7 @@ claude mcp add rubien -- node $(pwd)/dist/index.js # Claude Code
129
136
 
130
137
  ## Tool catalog
131
138
 
132
- 27 tools on the `{op}_{target}` grid — CRUD operations always carry the target suffix (`create_reference`, `update_property`); a bare verb appears only when the operation is unique and unambiguous (`cite`, `export`):
139
+ 28 tools — CRUD operations always carry the target suffix (`create_reference`, `update_property`); a bare verb appears only when the operation is unique and unambiguous (`cite`, `export`):
133
140
 
134
141
  | Surface | Tools |
135
142
  |---|---|
@@ -137,6 +144,7 @@ claude mcp add rubien -- node $(pwd)/dist/index.js # Claude Code
137
144
  | Citations | `rubien_cite`, `rubien_list_styles` |
138
145
  | Export | `rubien_export` |
139
146
  | Reading | `rubien_read_text`, `rubien_read_annotations`, `rubien_grep_text` |
147
+ | Activity | `rubien_reading_activity` |
140
148
  | PDFs | `rubien_get_pdf_info`, `rubien_render_pdf_page`, `rubien_download_pdf` |
141
149
  | Properties (columns + options, incl. Tags) | `rubien_list_properties`, `rubien_create_property`, `rubien_update_property`, `rubien_delete_property`, `rubien_create_option`, `rubien_update_option`, `rubien_delete_option` |
142
150
  | Saved views | `rubien_list_views`, `rubien_create_view`, `rubien_update_view`, `rubien_delete_view` |
package/dist/cli.js CHANGED
@@ -110,24 +110,60 @@ function extractFormat(args) {
110
110
  export async function invokeCliTyped(args, options = {}) {
111
111
  return (await invokeCli(args, options));
112
112
  }
113
+ /** Generous because the first exec of a signed binary after a reboot can be
114
+ * slowed by cold caches and Gatekeeper assessment; `rubien-cli version`
115
+ * itself is trivial (prints constants, never opens the database). The env
116
+ * override exists for tests. */
117
+ const PROBE_TIMEOUT_MS = 15_000;
118
+ function probeTimeoutMs() {
119
+ const env = Number(process.env.RUBIEN_MCP_PROBE_TIMEOUT_MS);
120
+ return Number.isFinite(env) && env > 0 ? env : PROBE_TIMEOUT_MS;
121
+ }
113
122
  /**
114
- * Probe `rubien-cli version` with a short timeout. Returns the parsed
115
- * {version, build} or null on any failure (missing subcommand on an old CLI,
116
- * non-zero exit, malformed output, timeout). Never throws.
123
+ * Probe `rubien-cli version` and classify the outcome. Never throws — the
124
+ * result feeds evaluateCliProbe (versionGuard.ts), which turns it into a
125
+ * startup log line or a per-tool-call error message.
117
126
  */
118
- export async function getCliVersion() {
127
+ export async function probeCliVersion() {
128
+ const envOverride = Boolean(process.env.RUBIEN_CLI?.length);
129
+ let cliPath;
130
+ try {
131
+ cliPath = resolveCliPath();
132
+ }
133
+ catch (err) {
134
+ return { kind: "not-found", detail: err.message, envOverride };
135
+ }
136
+ const timeoutMs = probeTimeoutMs();
119
137
  try {
120
- const result = await invokeCli(["version"], { timeoutMs: 5_000 });
121
- if (result &&
122
- typeof result === "object" &&
123
- typeof result.version === "string" &&
124
- typeof result.build === "number") {
125
- return result;
138
+ const { stdout } = await execFileAsync(cliPath, ["version"], {
139
+ timeout: timeoutMs,
140
+ maxBuffer: 1024 * 1024,
141
+ });
142
+ const parsed = JSON.parse(stdout.trim());
143
+ if (parsed &&
144
+ typeof parsed === "object" &&
145
+ typeof parsed.version === "string" &&
146
+ typeof parsed.build === "number") {
147
+ return { kind: "ok", info: parsed, envOverride };
126
148
  }
127
- return null;
149
+ return { kind: "no-version", path: cliPath, envOverride };
128
150
  }
129
- catch {
130
- return null;
151
+ catch (err) {
152
+ const e = err;
153
+ if (e.code === "ENOENT") {
154
+ return {
155
+ kind: "not-found",
156
+ detail: `no rubien-cli at ${cliPath}`,
157
+ envOverride,
158
+ };
159
+ }
160
+ // execFile sets killed:true when IT terminated the child at `timeout`;
161
+ // a child that died of its own signal (e.g. SIGSEGV) has killed:false
162
+ // and falls through to no-version.
163
+ if (e.killed === true) {
164
+ return { kind: "timeout", path: cliPath, timeoutMs, envOverride };
165
+ }
166
+ return { kind: "no-version", path: cliPath, envOverride };
131
167
  }
132
168
  }
133
169
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,QAAuB,EACvB,MAAc;QAE9B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,aAAQ,GAAR,QAAQ,CAAe;QACvB,WAAM,GAAN,MAAM,CAAQ;QAG9B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IAC3C,IAAI,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,oEAAoE;QACpE,gDAAgD;QAChD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,oDAAoD,WAAW,EAAE,CAClE,CAAC;QACJ,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,sDAAsD;QACtD,IAAI,CAAC,OAAO,EAAE,EAAE,qDAAqD,CAAC;QACtE,kDAAkD;QAClD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,8CAA8C,CAAC;QACnE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iDAAiD,CAAC;KACvE,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,2EAA2E;IAC3E,sEAAsE;IACtE,gDAAgD;IAChD,OAAO,YAAY,CAAC;AACtB,CAAC;AAWD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAc,EACd,UAAsB,EAAE;IAExB,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE;YACzC,OAAO;YACP,SAAS,EAAE,kBAAkB;SAC9B,CAAC,CAAC;QACH,0EAA0E;QAC1E,qEAAqE;QACrE,sDAAsD;QACtD,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACtB,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAChC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACzC,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC;QAE/B,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,kEAAkE;QAClE,MAAM,CAAC,GAAG,GAMT,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,uEAAuE;QACvE,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,OAAO,GACX,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,8BAA8B,CAAC,CAAC;QAC7E,MAAM,IAAI,QAAQ,CAChB,OAAO,EACP,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAC1C,MAAM,CACP,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;iEACiE;AACjE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAI,IAAc,EAAE,UAAsB,EAAE;IAC9E,OAAO,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAM,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,IACE,MAAM;YACN,OAAO,MAAM,KAAK,QAAQ;YAC1B,OAAQ,MAAkC,CAAC,OAAO,KAAK,QAAQ;YAC/D,OAAQ,MAAkC,CAAC,KAAK,KAAK,QAAQ,EAC7D,CAAC;YACD,OAAO,MAA+B,CAAC;QACzC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,8 +6,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
6
6
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
7
  import { buildServer } from "./server.js";
8
8
  import { requireBearer } from "./auth.js";
9
- import { getCliVersion } from "./cli.js";
10
- import { MIN_CLI_BUILD, evaluateCliVersion } from "./versionGuard.js";
9
+ import { MIN_CLI_BUILD, ensureCliCompatible } from "./versionGuard.js";
11
10
  const USAGE = `Usage:
12
11
  rubien-mcp-server [--stdio]
13
12
  rubien-mcp-server --http --port <port> --bearer-token <token>
@@ -65,6 +64,19 @@ async function runStdio() {
65
64
  const transport = new StdioServerTransport();
66
65
  await server.connect(transport);
67
66
  // MCP stdio transport keeps the process alive via stdin.
67
+ //
68
+ // CLI compatibility is deliberately NOT checked before connecting —
69
+ // buildServer gates every tool call instead (see cliGateError in
70
+ // toolHelpers.ts for why). The startup probe below only logs the verdict
71
+ // to stderr (e.g. ~/Library/Logs/Claude/mcp-server-rubien.log).
72
+ void ensureCliCompatible().then((guard) => {
73
+ process.stderr.write(guard.ok
74
+ ? `rubien-mcp-server: rubien-cli build ${guard.info?.build ?? "?"} >= ${MIN_CLI_BUILD} — compatible\n`
75
+ : `${guard.message}\n`);
76
+ }, () => {
77
+ // ensureCliCompatible never rejects by contract; guard anyway so a
78
+ // bug there can't become an unhandled rejection that kills the server.
79
+ });
68
80
  }
69
81
  async function runHttp(port, bearerToken) {
70
82
  const server = buildServer();
@@ -94,25 +106,26 @@ async function runHttp(port, bearerToken) {
94
106
  }
95
107
  async function main() {
96
108
  const args = parseCliArgs(process.argv.slice(2));
97
- // Version guard: probe the resolved CLI once, before connecting any
98
- // transport. `--help` already exited inside parseCliArgs, so help works
99
- // even with no CLI installed.
100
- const guard = evaluateCliVersion(await getCliVersion(), MIN_CLI_BUILD);
109
+ if (args.mode === "stdio") {
110
+ await runStdio();
111
+ return;
112
+ }
113
+ // HTTP mode keeps the fail-fast startup guard: the process is started by
114
+ // hand in a terminal where stderr is actually visible, and a long-lived
115
+ // degraded server behind a tunnel would be easier to miss than an
116
+ // immediate exit. `--help` already exited inside parseCliArgs, so help
117
+ // works even with no CLI installed.
118
+ const guard = await ensureCliCompatible();
101
119
  if (!guard.ok) {
102
120
  // Set exitCode + return rather than process.exit(1): the async stderr
103
121
  // write to a pipe can truncate if we exit immediately. No transport is
104
122
  // connected and the probe child has finished, so the event loop drains
105
123
  // and the process exits with code 1 after stderr flushes.
106
- process.stderr.write((guard.message ?? "rubien-cli version check failed") + "\n");
124
+ process.stderr.write(guard.message + "\n");
107
125
  process.exitCode = 1;
108
126
  return;
109
127
  }
110
- if (args.mode === "stdio") {
111
- await runStdio();
112
- }
113
- else {
114
- await runHttp(args.port, args.bearerToken);
115
- }
128
+ await runHttp(args.port, args.bearerToken);
116
129
  }
117
130
  main().catch((err) => {
118
131
  process.stderr.write(`fatal: ${err.stack ?? err.message}\n`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { cliGateError } from "./toolHelpers.js";
2
3
  import { registerReferenceTools } from "./tools/references.js";
3
4
  import { registerCitationTools } from "./tools/citations.js";
4
5
  import { registerIOTools } from "./tools/io.js";
@@ -7,14 +8,16 @@ import { registerViewTools } from "./tools/views.js";
7
8
  import { registerSyncTools } from "./tools/sync.js";
8
9
  import { registerPdfTools } from "./tools/pdf.js";
9
10
  import { registerReadTools } from "./tools/read.js";
11
+ import { registerActivityTools } from "./tools/activity.js";
10
12
  export const SERVER_INFO = {
11
13
  name: "rubien-mcp-server",
12
- version: "0.3.0",
14
+ version: "0.3.2",
13
15
  };
14
16
  export function buildServer() {
15
17
  const server = new McpServer(SERVER_INFO, {
16
18
  capabilities: { tools: {} },
17
19
  });
20
+ gateAllTools(server);
18
21
  registerReferenceTools(server);
19
22
  registerCitationTools(server);
20
23
  registerIOTools(server);
@@ -25,7 +28,28 @@ export function buildServer() {
25
28
  registerViewTools(server);
26
29
  registerPdfTools(server);
27
30
  registerReadTools(server);
31
+ registerActivityTools(server);
28
32
  registerSyncTools(server);
29
33
  return server;
30
34
  }
35
+ /**
36
+ * Prefix every tool registered after this call with the rubien-cli
37
+ * compatibility gate (cliGateError). Applied at the registration seam so the
38
+ * invariant is structural: every tool shells out to rubien-cli, so none can
39
+ * do anything useful with an incompatible one, and a future bespoke handler
40
+ * that skips runCliAsTool (like rubien_render_pdf_page's typed-image path)
41
+ * cannot silently ship ungated. test/gate-invariant.test.ts enforces this
42
+ * across the whole catalog.
43
+ */
44
+ function gateAllTools(server) {
45
+ const original = server.registerTool.bind(server);
46
+ // registerTool's generic signature doesn't survive a wrapping assignment;
47
+ // the cast is contained here.
48
+ server.registerTool = ((name, config, handler) => original(name, config, (async (...handlerArgs) => {
49
+ const gateError = await cliGateError();
50
+ if (gateError)
51
+ return gateError;
52
+ return handler(...handlerArgs);
53
+ })));
54
+ }
31
55
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,OAAO;CACR,CAAC;AAEX,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,EAAE;QACxC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;KAC5B,CAAC,CAAC;IAEH,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,wEAAwE;IACxE,sEAAsE;IACtE,6DAA6D;IAC7D,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,OAAO;CACR,CAAC;AAEX,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,EAAE;QACxC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;KAC5B,CAAC,CAAC;IAEH,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,wEAAwE;IACxE,sEAAsE;IACtE,6DAA6D;IAC7D,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,MAAiB;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClD,0EAA0E;IAC1E,8BAA8B;IAC9B,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,WAAsB,EAAE,EAAE;QAC1D,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;QACvC,IAAI,SAAS;YAAE,OAAO,SAAS,CAAC;QAChC,OAAQ,OAAwC,CAAC,GAAG,WAAW,CAAC,CAAC;IACnE,CAAC,CAAmB,CAAC,CAA+B,CAAC;AACzD,CAAC"}
@@ -1,4 +1,27 @@
1
1
  import { CliError, invokeCli } from "./cli.js";
2
+ import { ensureCliCompatible } from "./versionGuard.js";
3
+ /** An `isError` CallToolResult carrying plain text. */
4
+ export function errorResult(text) {
5
+ return {
6
+ content: [{ type: "text", text }],
7
+ isError: true,
8
+ };
9
+ }
10
+ /**
11
+ * Version gate applied to every registered tool by buildServer (server.ts):
12
+ * when rubien-cli is missing or too old, return the update instruction as an
13
+ * `isError` tool result instead of failing some other way. Stdio clients
14
+ * (Claude Desktop) hide server stderr behind a generic "Server disconnected",
15
+ * so tool-call text is the only surface the user actually sees; the gate
16
+ * re-probes on every failing call, so updating Rubien mid-session recovers
17
+ * without a client restart. Returns null when the CLI is compatible.
18
+ */
19
+ export async function cliGateError() {
20
+ const guard = await ensureCliCompatible();
21
+ if (guard.ok)
22
+ return null;
23
+ return errorResult(guard.message);
24
+ }
2
25
  /**
3
26
  * Invoke rubien-cli and wrap the result as a CallToolResult. Errors from the
4
27
  * CLI are mapped to `isError: true` with the stderr message. Any other error
@@ -19,10 +42,7 @@ export async function runCliAsTool(args, options = {}) {
19
42
  }
20
43
  catch (err) {
21
44
  if (err instanceof CliError) {
22
- return {
23
- content: [{ type: "text", text: err.message }],
24
- isError: true,
25
- };
45
+ return errorResult(err.message);
26
46
  }
27
47
  throw err;
28
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"toolHelpers.js","sourceRoot":"","sources":["../src/toolHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAmB,MAAM,UAAU,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc,EAAE,UAAsB,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GACV,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBACvD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAkE;IAElE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,KAAK;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"toolHelpers.js","sourceRoot":"","sources":["../src/toolHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAmB,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,KAAK,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC1C,IAAI,KAAK,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc,EAAE,UAAsB,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GACV,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAkE;IAElE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,KAAK;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import { runCliAsTool } from "../toolHelpers.js";
3
+ export function registerActivityTools(server) {
4
+ server.registerTool("rubien_reading_activity", {
5
+ title: "Reading activity",
6
+ description: "Return Rubien's tracked reading and Assistant activity. A paper-day qualifies after at least 60 estimated foreground-reader seconds; only yearActivity is limited by year.",
7
+ inputSchema: {
8
+ year: z.number().int().min(1970).max(9999).optional(),
9
+ },
10
+ annotations: { readOnlyHint: true },
11
+ }, async ({ year }) => {
12
+ const args = ["stats"];
13
+ if (year !== undefined)
14
+ args.push("--year", String(year));
15
+ return runCliAsTool(args);
16
+ });
17
+ }
18
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/tools/activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,4KAA4K;QAC9K,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;SACtD;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;AACJ,CAAC"}
package/dist/tools/pdf.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { CliError, invokeCliTyped } from "../cli.js";
3
- import { flagsFromOptions, runCliAsTool } from "../toolHelpers.js";
3
+ import { errorResult, flagsFromOptions, runCliAsTool } from "../toolHelpers.js";
4
4
  export function registerPdfTools(server) {
5
5
  server.registerTool("rubien_get_pdf_info", {
6
6
  title: "Probe PDF metadata + outline",
@@ -70,10 +70,7 @@ export function registerPdfTools(server) {
70
70
  }
71
71
  catch (err) {
72
72
  if (err instanceof CliError) {
73
- return {
74
- content: [{ type: "text", text: err.message }],
75
- isError: true,
76
- };
73
+ return errorResult(err.message);
77
74
  }
78
75
  throw err;
79
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/tools/pdf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/tools/pdf.ts"],"names":[],"mappings":"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"}
@@ -1,32 +1,93 @@
1
+ import { probeCliVersion } from "./cli.js";
1
2
  /**
2
3
  * The minimum rubien-cli build this server requires. Equals the build that
3
- * shipped the unified {op}_{target} surface (add --source one-door, update
4
- * --properties, properties --update/--update-option, list --view) that the
5
- * 0.3.0 catalog shells out to. Bump only when a future server release
4
+ * first shipped `stats`, which backs `rubien_reading_activity` in the 0.3.2
5
+ * catalog. Bump only when a future server release
6
6
  * genuinely needs a newer CLI feature; the released CLI's build must always
7
7
  * be >= this value.
8
8
  */
9
- export const MIN_CLI_BUILD = 26;
9
+ export const MIN_CLI_BUILD = 28;
10
10
  const RELEASES = "https://github.com/devzhk/Rubien-releases/releases";
11
- /** Pure decision: is the discovered CLI new enough? `info` is null when the
12
- * CLI has no `version` subcommand (i.e. predates this mechanism). */
13
- export function evaluateCliVersion(info, minBuild) {
14
- if (info === null) {
15
- return {
16
- ok: false,
17
- message: `rubien-mcp-server: cannot determine rubien-cli version ` +
18
- `(your rubien-cli predates the 'version' command). ` +
19
- `Update Rubien.app (Mac) or download a newer rubien-cli from ${RELEASES} (Linux).`,
20
- };
11
+ const UPDATE_HINT = `Update Rubien.app (Mac) or download a newer rubien-cli from ${RELEASES} (Linux).`;
12
+ /** When rubien-cli came from $RUBIEN_CLI, "update the app" is dead advice —
13
+ * the override wins no matter what is installed. */
14
+ function overrideHint(probe) {
15
+ return probe.envOverride
16
+ ? ` Note: rubien-cli is resolved from your RUBIEN_CLI override — point it ` +
17
+ `at a newer binary, or unset it to use the one bundled with Rubien.app.`
18
+ : "";
19
+ }
20
+ /** Pure decision: turn a CLI probe outcome into a verdict + user-facing
21
+ * message. Messages must say what to DO — in stdio mode they are returned
22
+ * as tool-call text, the only surface Claude Desktop users ever see. */
23
+ export function evaluateCliProbe(probe, minBuild) {
24
+ switch (probe.kind) {
25
+ case "ok":
26
+ if (probe.info.build < minBuild) {
27
+ return {
28
+ ok: false,
29
+ message: `rubien-mcp-server: installed rubien-cli is build ${probe.info.build}, ` +
30
+ `but this server needs build >= ${minBuild}. ${UPDATE_HINT}` +
31
+ overrideHint(probe),
32
+ };
33
+ }
34
+ return { ok: true, info: probe.info };
35
+ case "not-found":
36
+ return {
37
+ ok: false,
38
+ message: `rubien-mcp-server: rubien-cli not found (${probe.detail}). ` +
39
+ `Install Rubien.app (Mac) — the CLI ships inside it — or download ` +
40
+ `rubien-cli from ${RELEASES} and set RUBIEN_CLI to its path (Linux).` +
41
+ overrideHint(probe),
42
+ };
43
+ case "timeout":
44
+ return {
45
+ ok: false,
46
+ message: `rubien-mcp-server: rubien-cli at ${probe.path} did not answer ` +
47
+ `'version' within ${Math.round(probe.timeoutMs / 1000)}s. This can ` +
48
+ `happen on the first launch after a reboot — retry in a moment. ` +
49
+ `If it persists, reinstall Rubien.app (Mac) or check the binary (Linux).` +
50
+ overrideHint(probe),
51
+ };
52
+ case "no-version":
53
+ // Reachable both by a genuinely old CLI (no `version` subcommand) and
54
+ // by a binary that ran but failed (crash, EACCES, garbage output) —
55
+ // don't claim to know which.
56
+ return {
57
+ ok: false,
58
+ message: `rubien-mcp-server: the binary at ${probe.path} did not report a ` +
59
+ `version — it either predates the 'version' command or is broken. ` +
60
+ `${UPDATE_HINT}` + overrideHint(probe),
61
+ };
21
62
  }
22
- if (info.build < minBuild) {
23
- return {
24
- ok: false,
25
- message: `rubien-mcp-server: installed rubien-cli is build ${info.build}, ` +
26
- `but this server needs build >= ${minBuild}. ` +
27
- `Update Rubien.app (Mac) or download a newer rubien-cli from ${RELEASES} (Linux).`,
28
- };
63
+ }
64
+ let compatible = false;
65
+ let inFlight = null;
66
+ /**
67
+ * Probe-and-evaluate with success caching: once a compatible CLI is seen the
68
+ * check short-circuits for the life of the process; failures are never
69
+ * cached, so every failing tool call re-probes. Updating Rubien.app
70
+ * mid-session therefore recovers on the next call — important because
71
+ * Claude Desktop only respawns MCP servers when the app itself relaunches.
72
+ *
73
+ * Concurrent callers share one in-flight probe (the startup log probe and a
74
+ * first tool call routinely race, and a degraded server can get a burst of
75
+ * calls) — without collapsing recovery: the shared promise is dropped once
76
+ * settled, so the next call after a failure re-probes.
77
+ */
78
+ export async function ensureCliCompatible() {
79
+ if (compatible)
80
+ return { ok: true };
81
+ if (!inFlight) {
82
+ inFlight = (async () => {
83
+ const verdict = evaluateCliProbe(await probeCliVersion(), MIN_CLI_BUILD);
84
+ if (verdict.ok)
85
+ compatible = true;
86
+ return verdict;
87
+ })().finally(() => {
88
+ inFlight = null;
89
+ });
29
90
  }
30
- return { ok: true };
91
+ return inFlight;
31
92
  }
32
93
  //# sourceMappingURL=versionGuard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"versionGuard.js","sourceRoot":"","sources":["../src/versionGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAYhC,MAAM,QAAQ,GAAG,oDAAoD,CAAC;AAEtE;sEACsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,IAAuB,EACvB,QAAgB;IAEhB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,yDAAyD;gBACzD,oDAAoD;gBACpD,+DAA+D,QAAQ,WAAW;SACrF,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,oDAAoD,IAAI,CAAC,KAAK,IAAI;gBAClE,kCAAkC,QAAQ,IAAI;gBAC9C,+DAA+D,QAAQ,WAAW;SACrF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"versionGuard.js","sourceRoot":"","sources":["../src/versionGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAiB,MAAM,UAAU,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAWhC,MAAM,QAAQ,GAAG,oDAAoD,CAAC;AACtE,MAAM,WAAW,GAAG,+DAA+D,QAAQ,WAAW,CAAC;AAEvG;qDACqD;AACrD,SAAS,YAAY,CAAC,KAAe;IACnC,OAAO,KAAK,CAAC,WAAW;QACtB,CAAC,CAAC,yEAAyE;YACzE,wEAAwE;QAC1E,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED;;yEAEyE;AACzE,MAAM,UAAU,gBAAgB,CAC9B,KAAe,EACf,QAAgB;IAEhB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,IAAI;YACP,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;gBAChC,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EACL,oDAAoD,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI;wBACxE,kCAAkC,QAAQ,KAAK,WAAW,EAAE;wBAC5D,YAAY,CAAC,KAAK,CAAC;iBACtB,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QACxC,KAAK,WAAW;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,4CAA4C,KAAK,CAAC,MAAM,KAAK;oBAC7D,mEAAmE;oBACnE,mBAAmB,QAAQ,0CAA0C;oBACrE,YAAY,CAAC,KAAK,CAAC;aACtB,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,oCAAoC,KAAK,CAAC,IAAI,kBAAkB;oBAChE,oBAAoB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc;oBACpE,iEAAiE;oBACjE,yEAAyE;oBACzE,YAAY,CAAC,KAAK,CAAC;aACtB,CAAC;QACJ,KAAK,YAAY;YACf,sEAAsE;YACtE,oEAAoE;YACpE,6BAA6B;YAC7B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,oCAAoC,KAAK,CAAC,IAAI,oBAAoB;oBAClE,mEAAmE;oBACnE,GAAG,WAAW,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;aACzC,CAAC;IACN,CAAC;AACH,CAAC;AAED,IAAI,UAAU,GAAG,KAAK,CAAC;AACvB,IAAI,QAAQ,GAAgC,IAAI,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,CAAC,KAAK,IAAI,EAAE;YACrB,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,eAAe,EAAE,EAAE,aAAa,CAAC,CAAC;YACzE,IAAI,OAAO,CAAC,EAAE;gBAAE,UAAU,GAAG,IAAI,CAAC;YAClC,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YAChB,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rubien-mcp-server",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "MCP server wrapping rubien-cli so Claude Code and claude.ai can manage the Rubien reference library.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "devzhk",