@cueai/omni-reader-mcp 1.3.0 → 1.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
@@ -60,7 +60,7 @@ differ from the numbers above, report the live values.
60
60
  Always use an audited exact version, never an implicit `latest`:
61
61
 
62
62
  ```sh
63
- npx -y @cueai/omni-reader-mcp@1.3.0 setup
63
+ npx -y @cueai/omni-reader-mcp@1.3.2 setup
64
64
  ```
65
65
 
66
66
  The interactive setup supports Hermes, Cursor, Claude Desktop, and generic stdio
@@ -68,9 +68,9 @@ configuration. Non-interactive installation uses the same argument parsing and w
68
68
  logic:
69
69
 
70
70
  ```sh
71
- npx -y @cueai/omni-reader-mcp@1.3.0 setup --client hermes --allowed-root /absolute/minimum/root --yes --json
72
- npx -y @cueai/omni-reader-mcp@1.3.0 setup --client cursor --add-root /absolute/minimum/root --yes --json
73
- npx -y @cueai/omni-reader-mcp@1.3.0 setup --client claude-desktop --allowed-root /absolute/minimum/root --yes --json
71
+ npx -y @cueai/omni-reader-mcp@1.3.2 setup --client hermes --allowed-root /absolute/minimum/root --yes --json
72
+ npx -y @cueai/omni-reader-mcp@1.3.2 setup --client cursor --add-root /absolute/minimum/root --yes --json
73
+ npx -y @cueai/omni-reader-mcp@1.3.2 setup --client claude-desktop --allowed-root /absolute/minimum/root --yes --json
74
74
  ```
75
75
 
76
76
  When an agent or script runs under a pty (stdin is still a TTY), declare non-interactive
@@ -78,7 +78,7 @@ mode explicitly with `--headless` (alias `--non-interactive`): no `--yes` is req
78
78
  stdin is never read:
79
79
 
80
80
  ```sh
81
- npx -y @cueai/omni-reader-mcp@1.3.0 setup --client cursor --allowed-root /absolute/minimum/root --headless --json
81
+ npx -y @cueai/omni-reader-mcp@1.3.2 setup --client cursor --allowed-root /absolute/minimum/root --headless --json
82
82
  ```
83
83
 
84
84
  ## Cache and journal isolation
@@ -205,16 +205,16 @@ new source that satisfies the constraints.
205
205
  ## Commands
206
206
 
207
207
  ```sh
208
- npx -y @cueai/omni-reader-mcp@1.3.0 doctor
209
- npx -y @cueai/omni-reader-mcp@1.3.0 doctor --json
210
- npx -y @cueai/omni-reader-mcp@1.3.0 clean
211
- npx -y @cueai/omni-reader-mcp@1.3.0 uninstall --yes --json
208
+ npx -y @cueai/omni-reader-mcp@1.3.2 doctor
209
+ npx -y @cueai/omni-reader-mcp@1.3.2 doctor --json
210
+ npx -y @cueai/omni-reader-mcp@1.3.2 clean
211
+ npx -y @cueai/omni-reader-mcp@1.3.2 uninstall --yes --json
212
212
  ```
213
213
 
214
214
  Running the pinned version without a command starts the stdio MCP server:
215
215
 
216
216
  ```sh
217
- npx -y @cueai/omni-reader-mcp@1.3.0
217
+ npx -y @cueai/omni-reader-mcp@1.3.2
218
218
  ```
219
219
 
220
220
  `doctor --json` returns package/npm/client adapter, Key present/absent, allowed-root
@@ -223,12 +223,12 @@ status; it never prints the Key, private source paths, or content.
223
223
 
224
224
  ## Uninstall and rollback
225
225
 
226
- `uninstall --yes --json` removes only a trusted 1.2.2 or 1.3.0 Bridge entry; when a
226
+ `uninstall --yes --json` removes only a trusted 1.3.1 or 1.3.2 Bridge entry; when a
227
227
  matching trusted backup exists, it restores the original URL-only `omni-reader` entry.
228
228
  Uninstall never deletes user source files and never silently removes unexpired local
229
229
  results.
230
230
 
231
- To roll back from 1.3.0:
231
+ To roll back from 1.3.2:
232
232
 
233
233
  1. stop recommending or installing that version;
234
234
  2. run `uninstall --yes --json` to restore the trusted URL-only entry;
@@ -4,7 +4,7 @@ import { chmod, lstat, mkdir, open, realpath, rename, unlink, } from "node:fs/pr
4
4
  import path from "node:path";
5
5
  import { BRIDGE_RELEASE_VERSION, REMOTE_OMNI_MCP_URL, } from "../constants.js";
6
6
  const PACKAGE_SPEC = `@cueai/omni-reader-mcp@${BRIDGE_RELEASE_VERSION}`;
7
- const PREVIOUS_PACKAGE_SPEC = "@cueai/omni-reader-mcp@1.2.2";
7
+ const PREVIOUS_PACKAGE_SPEC = "@cueai/omni-reader-mcp@1.3.1";
8
8
  const LEGACY_PACKAGE_SPEC = "@cueai/omni-reader-mcp";
9
9
  const TRUSTED_EXACT_PACKAGE_SPECS = new Set([PREVIOUS_PACKAGE_SPEC, PACKAGE_SPEC]);
10
10
  function isRecord(value) {
@@ -586,7 +586,7 @@ function expectedBridgeVersion(target, value) {
586
586
  if (!isExpectedOmniEntry(target, value))
587
587
  return undefined;
588
588
  const packageSpec = value.args[1];
589
- return packageSpec === PREVIOUS_PACKAGE_SPEC ? "1.2.2" : BRIDGE_RELEASE_VERSION;
589
+ return packageSpec === PREVIOUS_PACKAGE_SPEC ? "1.3.1" : BRIDGE_RELEASE_VERSION;
590
590
  }
591
591
  function isLegacyBridgeEntry(target, value) {
592
592
  if (!isRecord(value) || value.command !== "npx")
@@ -6,7 +6,7 @@ export declare const CUBE_GRANT_PROTOCOL_VERSION = "omni.parse_grant.v1";
6
6
  export declare const GRANTED_STREAM_PROTOCOL_VERSION = "omni.granted_parse_stream.v1";
7
7
  export declare const DEFAULT_CUBE_BASE_URL = "https://mcp.cuecue.cn";
8
8
  export declare const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
9
- export declare const BRIDGE_RELEASE_VERSION = "1.3.0";
9
+ export declare const BRIDGE_RELEASE_VERSION = "1.3.2";
10
10
  export declare const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
11
11
  export declare const FOREGROUND_BUDGET_MS = 15000;
12
12
  export declare const STATUS_LONG_POLL_MAX_MS = 20000;
package/dist/constants.js CHANGED
@@ -6,7 +6,7 @@ export const CUBE_GRANT_PROTOCOL_VERSION = "omni.parse_grant.v1";
6
6
  export const GRANTED_STREAM_PROTOCOL_VERSION = "omni.granted_parse_stream.v1";
7
7
  export const DEFAULT_CUBE_BASE_URL = "https://mcp.cuecue.cn";
8
8
  export const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
9
- export const BRIDGE_RELEASE_VERSION = "1.3.0";
9
+ export const BRIDGE_RELEASE_VERSION = "1.3.2";
10
10
  export const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
11
11
  export const FOREGROUND_BUDGET_MS = 15_000;
12
12
  export const STATUS_LONG_POLL_MAX_MS = 20_000;
@@ -5,6 +5,11 @@ import { parseReaderCapabilities, selectDirectProfile, } from "./capabilities.js
5
5
  import { OmniBridgeError } from "./errors.js";
6
6
  const GRANT_PATH = "/api/omni-reader/direct-upload/v1/parse-grants";
7
7
  const BRIDGE_PACKAGE = "@cueai/omni-reader-mcp";
8
+ // Legacy grant response for UNPROFILED (detail-less) requests. cube-mcp serves
9
+ // omni.parse_grant.v1, and since the v2 metering writer rollout (writer_v2)
10
+ // also omni.parse_grant.v2. The v2 tuple is field-identical for the Bridge's
11
+ // purposes: the parse_grant token is opaque and passed through to the
12
+ // granted-stream endpoint untouched, so both protocol versions are accepted.
8
13
  const grantResponseSchema = z
9
14
  .object({
10
15
  grant_id: z.string().min(1),
@@ -17,7 +22,7 @@ const grantResponseSchema = z
17
22
  .refine((value) => new URL(value).protocol === "https:"),
18
23
  expires_at: z.string().datetime({ offset: true }),
19
24
  max_bytes: z.literal(MAX_FILE_BYTES),
20
- protocol_version: z.literal(CUBE_GRANT_PROTOCOL_VERSION),
25
+ protocol_version: z.enum([CUBE_GRANT_PROTOCOL_VERSION, "omni.parse_grant.v2"]),
21
26
  })
22
27
  .strict();
23
28
  // Closed v3 grant response: the exact tuple of the selected direct profile is
@@ -174,7 +174,57 @@ function jsonFromSse(body, requestId) {
174
174
  }
175
175
  throw protocolError();
176
176
  }
177
- function decodeEnvelope(value, requestId) {
177
+ // Real repro (2026-08-18): cube-mcp's `parse` tool returns a BARE `{ok:false, code, ...}` object —
178
+ // no `status` field — for a pre-operation source-classification rejection. `parseResultSchema` is
179
+ // a discriminated union keyed on `status`, so this can never match it; the resulting parse failure
180
+ // was masked as a generic REMOTE_PROTOCOL_ERROR, hiding the server's own actionable error
181
+ // (UNSUPPORTED_SOURCE) from the caller. Verified end-to-end against the real remote endpoint.
182
+ //
183
+ // codex review 2026-08-18 (2 rounds, cube-mcp source inspection): an earlier version keyed off
184
+ // `failure_scope` alone ("source"/"local_capability"), reasoning those were inherently
185
+ // pre-operation — WRONG: `failure_scope` names a failure DOMAIN, not a lifecycle stage. cube-mcp's
186
+ // own `url_operations/service.py` can emit a LATE error (e.g. SOURCE_TOO_LARGE) with
187
+ // `failure_scope:"source"` while retrieving an ALREADY-CREATED operation's result — defaulting
188
+ // that case's booleans to false would fabricate "nothing happened" over a real fact. Separately,
189
+ // the claimed LOCAL_BRIDGE_REQUIRED coverage was itself wrong: cube-mcp's actual
190
+ // `local_bridge_required()` payload is missing the required `message` field and carries extra keys
191
+ // `stableErrorSchema.strict()` rejects — it was never going to validate through this fallback
192
+ // regardless. Narrowed to EXACTLY the one call (`parse`, not `status`/`cancel` — an operation
193
+ // necessarily already exists for those) and EXACTLY the one evidenced code (`UNSUPPORTED_SOURCE`)
194
+ // this fix actually verified end-to-end. Any field the server DID provide still wins over the
195
+ // default (spread order). Anything outside this exact, evidenced case is left unchanged and still
196
+ // fails loudly as REMOTE_PROTOCOL_ERROR.
197
+ //
198
+ // review 2026-08-18 (subagent, standing in for codex — quota exhausted): a SECOND server-side
199
+ // producer of this exact code exists — cube-mcp's `url_operations/service.py` falls back to
200
+ // `code="UNSUPPORTED_SOURCE"` for any unmapped-400 from the L1 create call, AFTER metering
201
+ // admission. Traced: that path always runs `fail_reservation`/`_release_metering_lease` before
202
+ // returning (the code's own `_PUBLIC_ERROR_FACTS` hardcodes `retryable=False` for it), so
203
+ // operation_created/billed:false IS accurate there too — not a live bug — but this fix only ever
204
+ // verified the FIRST (pre-flight classify_source) producer end-to-end, not this one.
205
+ function bareStableErrorFallback(candidate, toolName) {
206
+ if (toolName !== "parse"
207
+ || candidate === null
208
+ || typeof candidate !== "object"
209
+ || Array.isArray(candidate)
210
+ || candidate.status !== undefined
211
+ || candidate.ok !== false
212
+ || candidate.code !== "UNSUPPORTED_SOURCE") {
213
+ return candidate;
214
+ }
215
+ return {
216
+ status: "failed",
217
+ error: {
218
+ operation_created: false,
219
+ file_uploaded: false,
220
+ parser_started: false,
221
+ billed: false,
222
+ content_released: false,
223
+ ...candidate,
224
+ },
225
+ };
226
+ }
227
+ function decodeEnvelope(value, requestId, toolName) {
178
228
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
179
229
  throw protocolError();
180
230
  }
@@ -208,7 +258,7 @@ function decodeEnvelope(value, requestId) {
208
258
  }
209
259
  }
210
260
  try {
211
- return parseResultSchema.parse(candidate);
261
+ return parseResultSchema.parse(bareStableErrorFallback(candidate, toolName));
212
262
  }
213
263
  catch {
214
264
  throw protocolError();
@@ -395,6 +445,6 @@ export class HttpRemoteOmniClient {
395
445
  throw error;
396
446
  throw protocolError();
397
447
  }
398
- return decodeEnvelope(envelope, requestId);
448
+ return decodeEnvelope(envelope, requestId, name);
399
449
  }
400
450
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueai/omni-reader-mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Local stdio MCP bridge for direct Omni document parsing",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",