@cueai/omni-reader-mcp 1.0.2 → 1.1.1
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 +115 -26
- package/dist/artifact-store.d.ts +11 -0
- package/dist/artifact-store.js +94 -48
- package/dist/cli/agent-config.d.ts +29 -4
- package/dist/cli/agent-config.js +910 -107
- package/dist/cli/arguments.d.ts +32 -0
- package/dist/cli/arguments.js +120 -0
- package/dist/cli/doctor.d.ts +42 -1
- package/dist/cli/doctor.js +109 -36
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.js +103 -18
- package/dist/cli/uninstall.d.ts +6 -0
- package/dist/cli/uninstall.js +37 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +7 -0
- package/dist/cube-client.d.ts +5 -3
- package/dist/cube-client.js +16 -11
- package/dist/cursor.js +2 -0
- package/dist/errors.d.ts +32 -1
- package/dist/errors.js +26 -1
- package/dist/iiis-client.d.ts +18 -4
- package/dist/iiis-client.js +194 -40
- package/dist/index.d.ts +3 -0
- package/dist/index.js +93 -32
- package/dist/multipart-body.js +2 -0
- package/dist/onboarding-policy.d.ts +10 -0
- package/dist/onboarding-policy.js +58 -0
- package/dist/operation-journal.d.ts +50 -1
- package/dist/operation-journal.js +473 -114
- package/dist/operation-manager.d.ts +75 -0
- package/dist/operation-manager.js +1324 -0
- package/dist/path-security.d.ts +1 -0
- package/dist/path-security.js +26 -6
- package/dist/progress.d.ts +6 -1
- package/dist/protocol.d.ts +26 -13
- package/dist/protocol.js +34 -10
- package/dist/remote-client.d.ts +17 -0
- package/dist/remote-client.js +233 -0
- package/dist/result-contract.d.ts +199 -0
- package/dist/result-contract.js +235 -0
- package/dist/server.js +21 -4
- package/dist/source.d.ts +8 -0
- package/dist/source.js +37 -0
- package/dist/task-runtime.d.ts +13 -0
- package/dist/task-runtime.js +94 -0
- package/dist/tools.d.ts +19 -1
- package/dist/tools.js +317 -112
- package/package.json +3 -3
package/dist/tools.js
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { CallToolRequestSchema, CancelTaskRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
2
3
|
import { createClientRequestId as newClientRequestId, } from "./cube-client.js";
|
|
3
4
|
import { OmniBridgeError } from "./errors.js";
|
|
4
5
|
import { openAllowedFile, } from "./path-security.js";
|
|
5
6
|
import { NOOP_PROGRESS } from "./progress.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
7
|
+
import { MACHINE_INSTRUCTIONS, cancelParseSchema, discardResultSchema, getParseStatusSchema, parseSchema, readResultSchema, } from "./protocol.js";
|
|
8
|
+
import { discardResultOutputSchema, discardResultToolOutputSchema, parseResultSchema, parseToolOutputSchema, readResultOutputSchema, readResultToolOutputSchema, structuredResult, } from "./result-contract.js";
|
|
9
|
+
import { classifySource } from "./source.js";
|
|
10
|
+
import { TaskRuntime } from "./task-runtime.js";
|
|
11
|
+
function bridgeError(code, message, facts = {}) {
|
|
8
12
|
return new OmniBridgeError({
|
|
9
13
|
code,
|
|
14
|
+
failureScope: "bridge",
|
|
10
15
|
message,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
operationCreated: facts.operationCreated ?? false,
|
|
17
|
+
fileUploaded: facts.fileUploaded ?? false,
|
|
18
|
+
parserStarted: facts.parserStarted ?? false,
|
|
19
|
+
billed: facts.billed ?? false,
|
|
20
|
+
contentReleased: facts.contentReleased ?? false,
|
|
21
|
+
retryable: facts.retryable ?? false,
|
|
15
22
|
});
|
|
16
23
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
24
|
+
function stableError(error) {
|
|
25
|
+
return error instanceof OmniBridgeError
|
|
19
26
|
? error
|
|
20
27
|
: bridgeError("BRIDGE_INTERNAL_ERROR", "The local Omni Bridge could not complete the request.");
|
|
21
|
-
return {
|
|
22
|
-
isError: true,
|
|
23
|
-
content: [{ type: "text", text: JSON.stringify(stable.toJSON()) }],
|
|
24
|
-
};
|
|
25
28
|
}
|
|
26
|
-
function
|
|
27
|
-
return {
|
|
28
|
-
content: [{ type: "text", text: JSON.stringify(value) }],
|
|
29
|
-
};
|
|
29
|
+
function failed(error) {
|
|
30
|
+
return { status: "failed", error: stableError(error).toJSON() };
|
|
30
31
|
}
|
|
31
32
|
function progressSink(extra) {
|
|
32
33
|
const progressToken = extra._meta?.progressToken;
|
|
@@ -41,41 +42,63 @@ function progressSink(extra) {
|
|
|
41
42
|
},
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
|
-
function
|
|
45
|
+
function completedLocalResult(local) {
|
|
46
|
+
const dataHandling = {
|
|
47
|
+
processing_copy: "deleted",
|
|
48
|
+
temporary_data: "deleted",
|
|
49
|
+
delivery_result: "deleted_after_ack",
|
|
50
|
+
original_source: "unchanged",
|
|
51
|
+
remote_content_retained: false,
|
|
52
|
+
};
|
|
45
53
|
if (local.kind === "inline") {
|
|
46
|
-
return
|
|
54
|
+
return {
|
|
55
|
+
status: "completed",
|
|
47
56
|
operation_id: local.operationId,
|
|
48
|
-
text: local.text,
|
|
49
|
-
|
|
57
|
+
result: { kind: "inline", text: local.text },
|
|
58
|
+
data_handling: dataHandling,
|
|
59
|
+
};
|
|
50
60
|
}
|
|
51
61
|
if (local.nextCursor === undefined) {
|
|
52
|
-
throw bridgeError("LOCAL_RESULT_INTEGRITY_FAILED", "The local result artifact cursor is missing."
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
throw bridgeError("LOCAL_RESULT_INTEGRITY_FAILED", "The local result artifact cursor is missing.", {
|
|
63
|
+
operationCreated: true,
|
|
64
|
+
fileUploaded: true,
|
|
65
|
+
parserStarted: true,
|
|
66
|
+
contentReleased: true,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
status: "completed",
|
|
71
|
+
operation_id: local.operationId,
|
|
72
|
+
result: {
|
|
73
|
+
kind: "artifact",
|
|
74
|
+
result_id: local.resultId,
|
|
75
|
+
result_bytes: local.resultBytes,
|
|
76
|
+
expires_at: local.expiresAt,
|
|
77
|
+
preview: local.preview,
|
|
78
|
+
next_cursor: local.nextCursor,
|
|
79
|
+
},
|
|
80
|
+
data_handling: dataHandling,
|
|
81
|
+
local_result_cache: {
|
|
82
|
+
expires_at: local.expiresAt,
|
|
83
|
+
discard_action: "discard_result",
|
|
84
|
+
},
|
|
85
|
+
};
|
|
62
86
|
}
|
|
63
|
-
async function
|
|
87
|
+
async function parseLocal(args, clientRequestId, signal, progress, dependencies) {
|
|
64
88
|
const openFile = dependencies.openFile ?? openAllowedFile;
|
|
65
|
-
const opened = await openFile(args.
|
|
89
|
+
const opened = await openFile(args.source, {
|
|
66
90
|
workspace: dependencies.workspace,
|
|
67
91
|
extraRoots: dependencies.extraRoots,
|
|
68
92
|
});
|
|
69
93
|
let primaryError;
|
|
70
94
|
try {
|
|
71
|
-
const clientRequestId = (dependencies.createClientRequestId ?? newClientRequestId)();
|
|
72
95
|
const granted = await dependencies.cubeClient.createGrant({
|
|
73
96
|
contentLength: opened.size,
|
|
74
97
|
contentType: opened.contentType,
|
|
75
98
|
fileExtension: opened.safeExtension,
|
|
76
|
-
noStore:
|
|
77
|
-
output:
|
|
78
|
-
}, clientRequestId,
|
|
99
|
+
noStore: true,
|
|
100
|
+
output: "markdown",
|
|
101
|
+
}, clientRequestId, signal);
|
|
79
102
|
const retention = dependencies.artifactStore.createRetention();
|
|
80
103
|
const operation = {
|
|
81
104
|
parseGrant: granted.parseGrant,
|
|
@@ -85,12 +108,12 @@ async function parseDocument(args, extra, dependencies) {
|
|
|
85
108
|
expiresAt: granted.expiresAt,
|
|
86
109
|
openedFile: opened,
|
|
87
110
|
retention,
|
|
88
|
-
progress
|
|
89
|
-
signal
|
|
111
|
+
progress,
|
|
112
|
+
signal,
|
|
90
113
|
};
|
|
91
114
|
await dependencies.iiisClient.uploadAndWait(operation);
|
|
92
115
|
const local = retention.result();
|
|
93
|
-
const result =
|
|
116
|
+
const result = completedLocalResult(local);
|
|
94
117
|
await dependencies.iiisClient.ack(operation);
|
|
95
118
|
return result;
|
|
96
119
|
}
|
|
@@ -104,121 +127,303 @@ async function parseDocument(args, extra, dependencies) {
|
|
|
104
127
|
}
|
|
105
128
|
catch {
|
|
106
129
|
if (primaryError === undefined) {
|
|
107
|
-
throw bridgeError("FILE_CLOSE_FAILED", "The local source file could not be closed safely."
|
|
130
|
+
throw bridgeError("FILE_CLOSE_FAILED", "The local source file could not be closed safely.", {
|
|
131
|
+
operationCreated: true,
|
|
132
|
+
fileUploaded: true,
|
|
133
|
+
parserStarted: true,
|
|
134
|
+
contentReleased: true,
|
|
135
|
+
});
|
|
108
136
|
}
|
|
109
137
|
}
|
|
110
138
|
}
|
|
111
139
|
}
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
140
|
+
async function parseValue(args, signal, progress, dependencies) {
|
|
141
|
+
try {
|
|
142
|
+
const source = classifySource(args.source);
|
|
143
|
+
const clientRequestId = (dependencies.createClientRequestId ?? newClientRequestId)();
|
|
144
|
+
if (dependencies.operationManager !== undefined) {
|
|
145
|
+
const sourceHash = `sha256:${createHash("sha256")
|
|
146
|
+
.update(source.source, "utf8")
|
|
147
|
+
.digest("hex")}`;
|
|
148
|
+
let sourceFingerprint;
|
|
149
|
+
if (source.kind === "local") {
|
|
150
|
+
const openFile = dependencies.openFile ?? openAllowedFile;
|
|
151
|
+
try {
|
|
152
|
+
const opened = await openFile(source.source, {
|
|
153
|
+
workspace: dependencies.workspace,
|
|
154
|
+
extraRoots: dependencies.extraRoots,
|
|
155
|
+
});
|
|
156
|
+
try {
|
|
157
|
+
sourceFingerprint = opened.sourceFingerprint;
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
await opened.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (!(error instanceof OmniBridgeError) || error.code !== "FILE_NOT_FOUND") {
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return await dependencies.operationManager.submitResult({
|
|
170
|
+
sourceKind: source.kind,
|
|
171
|
+
sourceFacts: {
|
|
172
|
+
sourceHash,
|
|
173
|
+
...(sourceFingerprint === undefined ? {} : { sourceFingerprint }),
|
|
174
|
+
},
|
|
175
|
+
clientRequestId,
|
|
176
|
+
signal,
|
|
177
|
+
context: source.kind === "local"
|
|
178
|
+
? { source: source.source, progress }
|
|
179
|
+
: { source: source.source },
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (source.kind === "url") {
|
|
183
|
+
if (dependencies.remoteClient === undefined) {
|
|
184
|
+
throw bridgeError("REMOTE_PARSE_UNAVAILABLE", "Remote URL parsing is not available in this Bridge build.", { retryable: true });
|
|
185
|
+
}
|
|
186
|
+
return await dependencies.remoteClient.parse(source.source, clientRequestId, signal);
|
|
187
|
+
}
|
|
188
|
+
return await parseLocal(args, clientRequestId, signal, progress, dependencies);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
return failed(error);
|
|
192
|
+
}
|
|
120
193
|
}
|
|
121
|
-
function
|
|
122
|
-
return
|
|
194
|
+
async function callParse(args, extra, dependencies) {
|
|
195
|
+
return structuredResult(parseResultSchema, await parseValue(args, extra.signal, progressSink(extra), dependencies));
|
|
123
196
|
}
|
|
124
|
-
async function
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return invalidArgumentsResult();
|
|
129
|
-
try {
|
|
130
|
-
return await parseDocument(parsed.data, extra, dependencies);
|
|
197
|
+
async function statusValue(operationId, waitMs, signal, dependencies) {
|
|
198
|
+
try {
|
|
199
|
+
if (dependencies.statusOperation !== undefined) {
|
|
200
|
+
return await dependencies.statusOperation(operationId, waitMs, signal);
|
|
131
201
|
}
|
|
132
|
-
|
|
133
|
-
|
|
202
|
+
if (dependencies.operationManager !== undefined) {
|
|
203
|
+
try {
|
|
204
|
+
return await dependencies.operationManager.statusResult(operationId, waitMs, signal);
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
if (!(error instanceof OmniBridgeError) || error.code !== "OPERATION_NOT_FOUND") {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
134
211
|
}
|
|
212
|
+
if (dependencies.remoteClient !== undefined) {
|
|
213
|
+
return await dependencies.remoteClient.status(operationId, waitMs, signal);
|
|
214
|
+
}
|
|
215
|
+
throw bridgeError("OPERATION_NOT_FOUND", "The requested parse operation is not available.", { operationCreated: true });
|
|
135
216
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
217
|
+
catch (error) {
|
|
218
|
+
return failed(error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function callStatus(operationId, waitMs, extra, dependencies) {
|
|
222
|
+
return structuredResult(parseResultSchema, await statusValue(operationId, waitMs, extra.signal, dependencies));
|
|
223
|
+
}
|
|
224
|
+
async function cancelValue(operationId, signal, dependencies) {
|
|
225
|
+
try {
|
|
226
|
+
if (dependencies.cancelOperation !== undefined) {
|
|
227
|
+
return await dependencies.cancelOperation(operationId, signal);
|
|
142
228
|
}
|
|
143
|
-
|
|
144
|
-
|
|
229
|
+
if (dependencies.operationManager !== undefined) {
|
|
230
|
+
try {
|
|
231
|
+
return await dependencies.operationManager.cancelResult(operationId, signal);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (!(error instanceof OmniBridgeError) || error.code !== "OPERATION_NOT_FOUND") {
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
145
238
|
}
|
|
239
|
+
if (dependencies.remoteClient !== undefined) {
|
|
240
|
+
return await dependencies.remoteClient.cancel(operationId, signal);
|
|
241
|
+
}
|
|
242
|
+
throw bridgeError("OPERATION_NOT_FOUND", "The requested parse operation is not available.", { operationCreated: true });
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
return failed(error);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function callCancel(operationId, extra, dependencies) {
|
|
249
|
+
return structuredResult(parseResultSchema, await cancelValue(operationId, extra.signal, dependencies));
|
|
250
|
+
}
|
|
251
|
+
async function callReadResult(resultId, cursor, maxBytes, dependencies) {
|
|
252
|
+
try {
|
|
253
|
+
const result = await dependencies.artifactStore.read(resultId, cursor, maxBytes);
|
|
254
|
+
return structuredResult(readResultOutputSchema, {
|
|
255
|
+
status: "completed",
|
|
256
|
+
result: {
|
|
257
|
+
result_id: result.resultId,
|
|
258
|
+
result_bytes: result.resultBytes,
|
|
259
|
+
expires_at: result.expiresAt,
|
|
260
|
+
text: result.text,
|
|
261
|
+
...(result.nextCursor === undefined ? {} : { next_cursor: result.nextCursor }),
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
return structuredResult(readResultOutputSchema, failed(error));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function callDiscardResult(resultId, dependencies) {
|
|
270
|
+
try {
|
|
271
|
+
return structuredResult(discardResultOutputSchema, {
|
|
272
|
+
status: "completed",
|
|
273
|
+
result_id: resultId,
|
|
274
|
+
discarded: await dependencies.artifactStore.discard(resultId),
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
return structuredResult(discardResultOutputSchema, failed(error));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function invalidArgumentsResult(name) {
|
|
282
|
+
const error = failed(bridgeError("INVALID_TOOL_ARGUMENTS", "The Omni tool arguments are invalid."));
|
|
283
|
+
if (name === "read_result")
|
|
284
|
+
return structuredResult(readResultOutputSchema, error);
|
|
285
|
+
if (name === "discard_result")
|
|
286
|
+
return structuredResult(discardResultOutputSchema, error);
|
|
287
|
+
return structuredResult(parseResultSchema, error);
|
|
288
|
+
}
|
|
289
|
+
async function dispatchTool(name, rawArguments, extra, dependencies) {
|
|
290
|
+
if (name === "parse") {
|
|
291
|
+
const parsed = parseSchema.safeParse(rawArguments ?? {});
|
|
292
|
+
return parsed.success
|
|
293
|
+
? callParse(parsed.data, extra, dependencies)
|
|
294
|
+
: invalidArgumentsResult(name);
|
|
295
|
+
}
|
|
296
|
+
if (name === "get_parse_status") {
|
|
297
|
+
const parsed = getParseStatusSchema.safeParse(rawArguments ?? {});
|
|
298
|
+
return parsed.success
|
|
299
|
+
? callStatus(parsed.data.operation_id, parsed.data.wait_ms, extra, dependencies)
|
|
300
|
+
: invalidArgumentsResult(name);
|
|
301
|
+
}
|
|
302
|
+
if (name === "cancel_parse") {
|
|
303
|
+
const parsed = cancelParseSchema.safeParse(rawArguments ?? {});
|
|
304
|
+
return parsed.success
|
|
305
|
+
? callCancel(parsed.data.operation_id, extra, dependencies)
|
|
306
|
+
: invalidArgumentsResult(name);
|
|
307
|
+
}
|
|
308
|
+
if (name === "read_result") {
|
|
309
|
+
const parsed = readResultSchema.safeParse(rawArguments ?? {});
|
|
310
|
+
return parsed.success
|
|
311
|
+
? callReadResult(parsed.data.result_id, parsed.data.cursor, parsed.data.max_bytes, dependencies)
|
|
312
|
+
: invalidArgumentsResult(name);
|
|
146
313
|
}
|
|
147
314
|
if (name === "discard_result") {
|
|
148
315
|
const parsed = discardResultSchema.safeParse(rawArguments ?? {});
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return successResult({
|
|
153
|
-
result_id: parsed.data.result_id,
|
|
154
|
-
discarded: await dependencies.artifactStore.discard(parsed.data.result_id),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
return errorResult(error);
|
|
159
|
-
}
|
|
316
|
+
return parsed.success
|
|
317
|
+
? callDiscardResult(parsed.data.result_id, dependencies)
|
|
318
|
+
: invalidArgumentsResult(name);
|
|
160
319
|
}
|
|
161
|
-
return
|
|
320
|
+
return structuredResult(parseResultSchema, failed(bridgeError("TOOL_NOT_FOUND", "The requested Omni tool is not available.")));
|
|
162
321
|
}
|
|
163
|
-
export function registerOmniTools(server, dependencies) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
322
|
+
export function registerOmniTools(server, dependencies, taskStore) {
|
|
323
|
+
const taskRuntime = new TaskRuntime({
|
|
324
|
+
parse: (source, signal) => parseValue({ source }, signal, NOOP_PROGRESS, dependencies),
|
|
325
|
+
status: (operationId, waitMs, signal) => statusValue(operationId, waitMs, signal, dependencies),
|
|
326
|
+
cancel: (operationId, signal) => cancelValue(operationId, signal, dependencies),
|
|
327
|
+
});
|
|
328
|
+
const createParseTask = async (args, extra) => {
|
|
329
|
+
const requestedTtl = extra.taskRequestedTtl ?? 600_000;
|
|
330
|
+
const task = await extra.taskStore.createTask({
|
|
331
|
+
ttl: Math.min(600_000, Math.max(1_000, requestedTtl)),
|
|
332
|
+
pollInterval: 1_000,
|
|
333
|
+
});
|
|
334
|
+
void taskRuntime.start(task.taskId, args.source, extra.taskStore)
|
|
335
|
+
.catch(() => undefined);
|
|
336
|
+
return { task };
|
|
337
|
+
};
|
|
338
|
+
const parseInputShape = parseSchema.shape;
|
|
339
|
+
const parseTaskHandler = {
|
|
340
|
+
createTask: createParseTask,
|
|
341
|
+
getTask: async (_args, extra) => extra.taskStore.getTask(extra.taskId),
|
|
342
|
+
getTaskResult: async (_args, extra) => await extra.taskStore.getTaskResult(extra.taskId),
|
|
343
|
+
};
|
|
344
|
+
server.experimental.tasks.registerToolTask("parse", {
|
|
345
|
+
description: `${MACHINE_INSTRUCTIONS}\n\nParse one local file or HTTP(S) URL through Omni.`,
|
|
346
|
+
inputSchema: parseInputShape,
|
|
347
|
+
outputSchema: parseToolOutputSchema,
|
|
348
|
+
execution: { taskSupport: "optional" },
|
|
167
349
|
annotations: {
|
|
168
350
|
readOnlyHint: false,
|
|
169
351
|
destructiveHint: false,
|
|
170
352
|
idempotentHint: false,
|
|
171
353
|
openWorldHint: true,
|
|
172
354
|
},
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
355
|
+
}, parseTaskHandler);
|
|
356
|
+
server.registerTool("get_parse_status", {
|
|
357
|
+
description: "Read the current state of one existing Omni parse operation.",
|
|
358
|
+
inputSchema: getParseStatusSchema,
|
|
359
|
+
outputSchema: parseToolOutputSchema,
|
|
360
|
+
annotations: {
|
|
361
|
+
readOnlyHint: true,
|
|
362
|
+
destructiveHint: false,
|
|
363
|
+
idempotentHint: true,
|
|
364
|
+
openWorldHint: true,
|
|
365
|
+
},
|
|
366
|
+
}, (args, extra) => callStatus(args.operation_id, args.wait_ms, extra, dependencies));
|
|
367
|
+
server.registerTool("cancel_parse", {
|
|
368
|
+
description: "Request cancellation of one existing Omni parse operation.",
|
|
369
|
+
inputSchema: cancelParseSchema,
|
|
370
|
+
outputSchema: parseToolOutputSchema,
|
|
371
|
+
annotations: {
|
|
372
|
+
readOnlyHint: false,
|
|
373
|
+
destructiveHint: true,
|
|
374
|
+
idempotentHint: true,
|
|
375
|
+
openWorldHint: true,
|
|
376
|
+
},
|
|
377
|
+
}, (args, extra) => callCancel(args.operation_id, extra, dependencies));
|
|
181
378
|
server.registerTool("read_result", {
|
|
182
379
|
description: "Read one UTF-8 chunk from a Bridge-created local result artifact.",
|
|
183
380
|
inputSchema: readResultSchema,
|
|
381
|
+
outputSchema: readResultToolOutputSchema,
|
|
184
382
|
annotations: {
|
|
185
383
|
readOnlyHint: true,
|
|
186
384
|
destructiveHint: false,
|
|
187
385
|
idempotentHint: true,
|
|
188
386
|
openWorldHint: false,
|
|
189
387
|
},
|
|
190
|
-
},
|
|
191
|
-
try {
|
|
192
|
-
return readSuccess(await dependencies.artifactStore.read(args.result_id, args.cursor, args.max_bytes));
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
return errorResult(error);
|
|
196
|
-
}
|
|
197
|
-
});
|
|
388
|
+
}, (args) => callReadResult(args.result_id, args.cursor, args.max_bytes, dependencies));
|
|
198
389
|
server.registerTool("discard_result", {
|
|
199
390
|
description: "Immediately delete one Bridge-created local result artifact.",
|
|
200
391
|
inputSchema: discardResultSchema,
|
|
392
|
+
outputSchema: discardResultToolOutputSchema,
|
|
201
393
|
annotations: {
|
|
202
394
|
readOnlyHint: false,
|
|
203
395
|
destructiveHint: true,
|
|
204
396
|
idempotentHint: true,
|
|
205
397
|
openWorldHint: false,
|
|
206
398
|
},
|
|
207
|
-
},
|
|
208
|
-
try {
|
|
209
|
-
return successResult({
|
|
210
|
-
result_id: args.result_id,
|
|
211
|
-
discarded: await dependencies.artifactStore.discard(args.result_id),
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
return errorResult(error);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
399
|
+
}, (args) => callDiscardResult(args.result_id, dependencies));
|
|
218
400
|
server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
219
401
|
if (request.params.task !== undefined) {
|
|
220
|
-
|
|
402
|
+
if (request.params.name !== "parse") {
|
|
403
|
+
return structuredResult(parseResultSchema, failed(bridgeError("TOOL_TASK_UNSUPPORTED", "Task augmentation is supported only for Omni parse calls.")));
|
|
404
|
+
}
|
|
405
|
+
const parsed = parseSchema.safeParse(request.params.arguments ?? {});
|
|
406
|
+
if (!parsed.success || extra.taskStore === undefined) {
|
|
407
|
+
return invalidArgumentsResult(request.params.name);
|
|
408
|
+
}
|
|
409
|
+
return createParseTask(parsed.data, extra);
|
|
221
410
|
}
|
|
222
411
|
return dispatchTool(request.params.name, request.params.arguments, extra, dependencies);
|
|
223
412
|
});
|
|
413
|
+
server.server.setRequestHandler(CancelTaskRequestSchema, async (request, extra) => {
|
|
414
|
+
const task = await taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
415
|
+
if (task === null) {
|
|
416
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request.params.taskId}`);
|
|
417
|
+
}
|
|
418
|
+
if (["completed", "failed", "cancelled"].includes(task.status)) {
|
|
419
|
+
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
420
|
+
}
|
|
421
|
+
await taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
422
|
+
await taskRuntime.cancel(request.params.taskId);
|
|
423
|
+
const canceled = await taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
424
|
+
if (canceled === null) {
|
|
425
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request.params.taskId}`);
|
|
426
|
+
}
|
|
427
|
+
return { _meta: {}, ...canceled };
|
|
428
|
+
});
|
|
224
429
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cueai/omni-reader-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Local stdio MCP bridge for direct Omni document parsing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc -p tsconfig.json",
|
|
22
|
-
"test": "vitest run",
|
|
22
|
+
"test": "npm run build && vitest run",
|
|
23
23
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
24
24
|
"prepack": "npm run test && npm run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "
|
|
27
|
+
"@modelcontextprotocol/sdk": "1.30.0",
|
|
28
28
|
"zod": "^3.25.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|