@cueai/omni-reader-mcp 1.0.0 → 1.0.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
@@ -1,4 +1,4 @@
1
- # @cue/omni-reader-mcp
1
+ # @cueai/omni-reader-mcp
2
2
 
3
3
  Local stdio MCP Bridge for parsing files from an Agent workspace through Omni Reader. Source bytes upload directly from the local Bridge to IIIS; they do not pass through Cube-MCP or the model conversation before `parse_document` is called.
4
4
 
@@ -13,7 +13,7 @@ Set the existing general Cue API Key, then run the interactive user-scope setup:
13
13
 
14
14
  ```sh
15
15
  export CUE_API_KEY="YOUR_CUE_API_KEY"
16
- npx -y @cue/omni-reader-mcp setup
16
+ npx -y @cueai/omni-reader-mcp setup
17
17
  ```
18
18
 
19
19
  Setup supports Cursor, Claude Desktop, and a generic MCP configuration for other Agents. The current working directory is allowed by default. To allow additional directories, provide them during setup or configure absolute paths in `OMNI_ALLOWED_ROOTS` (colon-separated on macOS/Linux and semicolon-separated on Windows).
@@ -41,9 +41,9 @@ Local parsing defaults to `no_store=true`. Files are restricted to configured ro
41
41
  ## Commands
42
42
 
43
43
  ```sh
44
- npx -y @cue/omni-reader-mcp setup
45
- npx -y @cue/omni-reader-mcp doctor
46
- npx -y @cue/omni-reader-mcp clean
44
+ npx -y @cueai/omni-reader-mcp setup
45
+ npx -y @cueai/omni-reader-mcp doctor
46
+ npx -y @cueai/omni-reader-mcp clean
47
47
  ```
48
48
 
49
- Running `npx -y @cue/omni-reader-mcp` without a command starts the stdio MCP server.
49
+ Running `npx -y @cueai/omni-reader-mcp` without a command starts the stdio MCP server.
@@ -51,7 +51,7 @@ export function displayConfigPath(configPath, environment) {
51
51
  export function buildAgentEntry(extraRoots, platform) {
52
52
  const entry = {
53
53
  command: "npx",
54
- args: ["-y", "@cue/omni-reader-mcp"],
54
+ args: ["-y", "@cueai/omni-reader-mcp"],
55
55
  };
56
56
  if (extraRoots.length > 0) {
57
57
  entry.env = {
@@ -277,7 +277,7 @@ function isExpectedOmniEntry(value) {
277
277
  || !Array.isArray(args)
278
278
  || args.length !== 2
279
279
  || args[0] !== "-y"
280
- || args[1] !== "@cue/omni-reader-mcp")
280
+ || args[1] !== "@cueai/omni-reader-mcp")
281
281
  return false;
282
282
  if (value.env === undefined) {
283
283
  return keys.length === 2 && keys[0] === "args" && keys[1] === "command";
@@ -1,7 +1,7 @@
1
1
  import { constants as fsConstants } from "node:fs";
2
2
  import { lstat, open, readdir } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { DEFAULT_CUBE_BASE_URL, GRANTED_STREAM_PROTOCOL_VERSION, MAX_FILE_BYTES, PROTOCOL_VERSION, } from "../constants.js";
4
+ import { DEFAULT_CUBE_BASE_URL, GRANTED_STREAM_PROTOCOL_VERSION, MAX_FILE_BYTES, CUBE_GRANT_PROTOCOL_VERSION, } from "../constants.js";
5
5
  import { agentConfigPath, inspectAgentConfig, } from "./agent-config.js";
6
6
  const CUBE_HEALTH_PATH = "/api/omni-reader/direct-upload/v1/health";
7
7
  const IIIS_HEALTH_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/health";
@@ -28,7 +28,7 @@ async function fetchHealth(fetchImpl, url, authorization) {
28
28
  export async function checkCubeHealth(fetchImpl, apiKey) {
29
29
  const cubeUrl = new URL(CUBE_HEALTH_PATH, DEFAULT_CUBE_BASE_URL).toString();
30
30
  const cube = await fetchHealth(fetchImpl, cubeUrl, `Bearer ${apiKey}`);
31
- if (!cube.enabled || cube.protocol_version !== PROTOCOL_VERSION) {
31
+ if (!cube.enabled || cube.protocol_version !== CUBE_GRANT_PROTOCOL_VERSION) {
32
32
  throw new Error("Cube direct upload is disabled or incompatible");
33
33
  }
34
34
  return cube.protocol_version;
@@ -2,6 +2,6 @@ export declare const MAX_FILE_BYTES = 268435456;
2
2
  export declare const INLINE_RESULT_MAX_BYTES = 65536;
3
3
  export declare const ARTIFACT_TTL_MS: number;
4
4
  export declare const RESULT_CHUNK_MAX_BYTES = 65536;
5
- export declare const PROTOCOL_VERSION = "omni.direct_upload.v1";
5
+ 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";
package/dist/constants.js CHANGED
@@ -2,6 +2,6 @@ export const MAX_FILE_BYTES = 268435456;
2
2
  export const INLINE_RESULT_MAX_BYTES = 65536;
3
3
  export const ARTIFACT_TTL_MS = 24 * 60 * 60 * 1000;
4
4
  export const RESULT_CHUNK_MAX_BYTES = 65536;
5
- export const PROTOCOL_VERSION = "omni.direct_upload.v1";
5
+ 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";
@@ -1,6 +1,6 @@
1
1
  import { OperationJournal } from "./operation-journal.js";
2
- declare const BRIDGE_PACKAGE = "@cue/omni-reader-mcp";
3
- declare const BRIDGE_VERSION = "1.0.0";
2
+ declare const BRIDGE_PACKAGE = "@cueai/omni-reader-mcp";
3
+ declare const BRIDGE_VERSION = "1.0.2";
4
4
  export interface GrantRequestInput {
5
5
  readonly contentLength: number;
6
6
  readonly contentType: string;
@@ -1,10 +1,10 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { z } from "zod";
3
- import { DEFAULT_CUBE_BASE_URL, MAX_FILE_BYTES, PROTOCOL_VERSION, } from "./constants.js";
3
+ import { DEFAULT_CUBE_BASE_URL, MAX_FILE_BYTES, CUBE_GRANT_PROTOCOL_VERSION, } from "./constants.js";
4
4
  import { OmniBridgeError } from "./errors.js";
5
5
  const GRANT_PATH = "/api/omni-reader/direct-upload/v1/parse-grants";
6
- const BRIDGE_PACKAGE = "@cue/omni-reader-mcp";
7
- const BRIDGE_VERSION = "1.0.0";
6
+ const BRIDGE_PACKAGE = "@cueai/omni-reader-mcp";
7
+ const BRIDGE_VERSION = "1.0.2";
8
8
  const grantResponseSchema = z
9
9
  .object({
10
10
  grant_id: z.string().min(1),
@@ -17,7 +17,7 @@ const grantResponseSchema = z
17
17
  .refine((value) => new URL(value).protocol === "https:"),
18
18
  expires_at: z.string().datetime({ offset: true }),
19
19
  max_bytes: z.literal(MAX_FILE_BYTES),
20
- protocol_version: z.literal(PROTOCOL_VERSION),
20
+ protocol_version: z.literal(CUBE_GRANT_PROTOCOL_VERSION),
21
21
  })
22
22
  .strict();
23
23
  function bridgeError(code, message, retryable) {
@@ -38,6 +38,6 @@ export declare class IiisClient {
38
38
  #private;
39
39
  constructor(options?: IiisClientOptions);
40
40
  uploadAndWait(input: IiisOperationInput): Promise<ReleasedResult>;
41
- downloadResult(input: IiisOperationInput): Promise<ReleasedResult>;
41
+ downloadResult(input: IiisOperationInput, progress?: ProgressSink): Promise<ReleasedResult>;
42
42
  ack(input: IiisOperationInput): Promise<void>;
43
43
  }
@@ -110,6 +110,11 @@ function monotonicProgress(sink) {
110
110
  },
111
111
  };
112
112
  }
113
+ function parserProgress(done, total) {
114
+ return total > 0
115
+ ? 40 + Math.floor(Math.min(done / total, 1) * 59)
116
+ : 40;
117
+ }
113
118
  async function errorFromResponse(response, input) {
114
119
  try {
115
120
  const body = await response.json();
@@ -217,7 +222,7 @@ export class IiisClient {
217
222
  return this.#recover(input, true, progress);
218
223
  }
219
224
  }
220
- async downloadResult(input) {
225
+ async downloadResult(input, progress = NOOP_PROGRESS) {
221
226
  throwIfCanceled(input);
222
227
  const confirmedFacts = recoveryFacts({
223
228
  fileUploaded: true,
@@ -316,6 +321,7 @@ export class IiisClient {
316
321
  };
317
322
  await input.retention.complete(metadata);
318
323
  throwIfCanceled(input);
324
+ await progress.report(100, 100, "Completed");
319
325
  completed = true;
320
326
  return metadata;
321
327
  }
@@ -415,10 +421,7 @@ export class IiisClient {
415
421
  }
416
422
  if (event.type === "progress") {
417
423
  const parsed = progressValue(event);
418
- const scaled = parsed.total > 0
419
- ? 40 + Math.floor(Math.min(parsed.done / parsed.total, 1) * 60)
420
- : 40;
421
- await progress.report(scaled, 100, parsed.message);
424
+ await progress.report(parserProgress(parsed.done, parsed.total), 100, parsed.message);
422
425
  continue;
423
426
  }
424
427
  if (event.type === "error") {
@@ -519,8 +522,11 @@ export class IiisClient {
519
522
  }
520
523
  throw bridgeError("INVALID_SSE_EVENT", "IIIS returned an unsupported progress event.");
521
524
  }
522
- if (completedMetadata !== undefined)
525
+ if (completedMetadata !== undefined) {
526
+ throwIfCanceled(input);
527
+ await progress.report(100, 100, "Completed");
523
528
  return completedMetadata;
529
+ }
524
530
  throw new TransportFailure("SSE ended before completion");
525
531
  }
526
532
  catch (error) {
@@ -643,16 +649,13 @@ export class IiisClient {
643
649
  }
644
650
  }
645
651
  else if (status.status === "RELEASED") {
646
- return await this.downloadResult(input);
652
+ return await this.downloadResult(input, progress);
647
653
  }
648
654
  else if (ACTIVE_STATUSES.has(status.status)) {
649
655
  const page = await this.#events(input, eventCursor);
650
656
  for (const event of page.events) {
651
657
  const parsed = progressValue(event);
652
- const scaled = parsed.total > 0
653
- ? 40 + Math.floor(Math.min(parsed.done / parsed.total, 1) * 60)
654
- : 40;
655
- await progress.report(scaled, 100, parsed.message);
658
+ await progress.report(parserProgress(parsed.done, parsed.total), 100, parsed.message);
656
659
  }
657
660
  eventCursor = page.nextSequence;
658
661
  }
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFile as execFileCallback } from "node:child_process";
3
- import { readFile } from "node:fs/promises";
4
- import { pathToFileURL } from "node:url";
3
+ import { readFile, realpath } from "node:fs/promises";
4
+ import { fileURLToPath } from "node:url";
5
5
  import { createInterface } from "node:readline/promises";
6
6
  import { stdin, stdout as processStdout } from "node:process";
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -165,8 +165,17 @@ async function main() {
165
165
  if (code !== 0)
166
166
  process.exitCode = code;
167
167
  }
168
- const invokedPath = process.argv[1];
169
- if (invokedPath !== undefined && import.meta.url === pathToFileURL(invokedPath).href) {
168
+ async function isMainModule(invokedPath) {
169
+ if (invokedPath === undefined)
170
+ return false;
171
+ try {
172
+ return await realpath(invokedPath) === fileURLToPath(import.meta.url);
173
+ }
174
+ catch {
175
+ return false;
176
+ }
177
+ }
178
+ if (await isMainModule(process.argv[1])) {
170
179
  void main().catch(() => {
171
180
  process.stderr.write("Bridge startup failed.\n");
172
181
  process.exitCode = 1;
package/dist/server.js CHANGED
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { SAFETY_INSTRUCTIONS } from "./protocol.js";
3
3
  import { registerOmniTools } from "./tools.js";
4
4
  const SERVER_NAME = "omni-reader-mcp";
5
- const SERVER_VERSION = "1.0.0";
5
+ const SERVER_VERSION = "1.0.2";
6
6
  export function createOmniMcpServer(dependencies) {
7
7
  const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: SAFETY_INSTRUCTIONS });
8
8
  registerOmniTools(server, dependencies);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueai/omni-reader-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Local stdio MCP bridge for direct Omni document parsing",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",