@docrouter/mcp 0.1.0

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/dist/index.js ADDED
@@ -0,0 +1,1812 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var index_js = require('@modelcontextprotocol/sdk/server/index.js');
5
+ var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
6
+ var types_js = require('@modelcontextprotocol/sdk/types.js');
7
+ var zod = require('zod');
8
+ var sdk = require('@docrouter/sdk');
9
+ var fs = require('fs');
10
+ var path = require('path');
11
+ var url = require('url');
12
+
13
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
14
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
+ }) : x)(function(x) {
17
+ if (typeof require !== "undefined") return require.apply(this, arguments);
18
+ throw Error('Dynamic require of "' + x + '" is not supported');
19
+ });
20
+ var ConfigSchema = zod.z.object({
21
+ baseURL: zod.z.string().default("https://app.docrouter.ai/fastapi"),
22
+ organizationId: zod.z.string(),
23
+ orgToken: zod.z.string(),
24
+ timeout: zod.z.number().default(3e4),
25
+ retries: zod.z.number().default(3)
26
+ });
27
+ function parseConfig() {
28
+ const args = process.argv.slice(2);
29
+ const config = {};
30
+ for (let i = 0; i < args.length; i += 2) {
31
+ const key = args[i]?.replace("--", "");
32
+ const value = args[i + 1];
33
+ if (key && value) {
34
+ switch (key) {
35
+ case "url":
36
+ config.baseURL = value;
37
+ break;
38
+ case "org-id":
39
+ config.organizationId = value;
40
+ break;
41
+ case "org-token":
42
+ config.orgToken = value;
43
+ break;
44
+ case "timeout":
45
+ config.timeout = parseInt(value, 10);
46
+ break;
47
+ case "retries":
48
+ config.retries = parseInt(value, 10);
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ config.baseURL = config.baseURL || process.env.DOCROUTER_API_URL || "https://app.docrouter.ai/fastapi";
54
+ config.organizationId = config.organizationId || process.env.DOCROUTER_ORG_ID || "";
55
+ config.orgToken = config.orgToken || process.env.DOCROUTER_ORG_API_TOKEN || "";
56
+ return ConfigSchema.parse(config);
57
+ }
58
+ var server = new index_js.Server(
59
+ {
60
+ name: "docrouter-mcp",
61
+ version: "0.1.0"
62
+ },
63
+ {
64
+ capabilities: {
65
+ tools: {}
66
+ }
67
+ }
68
+ );
69
+ var docrouterClient;
70
+ function initializeClient(config) {
71
+ docrouterClient = new sdk.DocRouterOrg({
72
+ baseURL: config.baseURL,
73
+ orgToken: config.orgToken,
74
+ organizationId: config.organizationId,
75
+ timeout: config.timeout,
76
+ retries: config.retries
77
+ });
78
+ }
79
+ function handleError(error) {
80
+ if (error instanceof Error) {
81
+ return JSON.stringify({ error: error.message }, null, 2);
82
+ }
83
+ return JSON.stringify({ error: "Unknown error occurred" }, null, 2);
84
+ }
85
+ function serializeDates(obj) {
86
+ if (obj === null || obj === void 0) {
87
+ return obj;
88
+ }
89
+ if (obj instanceof Date) {
90
+ return obj.toISOString();
91
+ }
92
+ if (Array.isArray(obj)) {
93
+ return obj.map(serializeDates);
94
+ }
95
+ if (typeof obj === "object") {
96
+ const result = {};
97
+ for (const [key, value] of Object.entries(obj)) {
98
+ result[key] = serializeDates(value);
99
+ }
100
+ return result;
101
+ }
102
+ return obj;
103
+ }
104
+ function getArg(args, key, defaultValue) {
105
+ const value = args[key];
106
+ if (value === void 0 || value === null) {
107
+ if (defaultValue !== void 0) {
108
+ return defaultValue;
109
+ }
110
+ throw new Error(`Missing required argument: ${key}`);
111
+ }
112
+ return value;
113
+ }
114
+ function getOptionalArg(args, key, defaultValue) {
115
+ const value = args[key];
116
+ if (value === void 0 || value === null) {
117
+ return defaultValue;
118
+ }
119
+ return value;
120
+ }
121
+ function validateSchemaFormat(schema) {
122
+ const errors = [];
123
+ const warnings = [];
124
+ try {
125
+ if (!schema || typeof schema !== "object") {
126
+ errors.push("Schema must be an object");
127
+ return { valid: false, errors, warnings };
128
+ }
129
+ if (!schema.type || schema.type !== "json_schema") {
130
+ errors.push('Schema must have type: "json_schema"');
131
+ }
132
+ if (!schema.json_schema || typeof schema.json_schema !== "object") {
133
+ errors.push("Schema must have json_schema object");
134
+ } else {
135
+ const jsonSchema = schema.json_schema;
136
+ if (!jsonSchema.name || typeof jsonSchema.name !== "string") {
137
+ errors.push("json_schema must have a name field");
138
+ }
139
+ if (!jsonSchema.schema || typeof jsonSchema.schema !== "object") {
140
+ errors.push("json_schema must have a schema object");
141
+ } else {
142
+ const innerSchema = jsonSchema.schema;
143
+ if (innerSchema.type !== "object") {
144
+ errors.push('Inner schema type must be "object"');
145
+ }
146
+ if (!innerSchema.properties || typeof innerSchema.properties !== "object") {
147
+ errors.push("Schema must have properties object");
148
+ }
149
+ if (!Array.isArray(innerSchema.required)) {
150
+ errors.push("Schema must have required array");
151
+ }
152
+ if (innerSchema.additionalProperties !== false) {
153
+ errors.push("Schema must have additionalProperties: false");
154
+ }
155
+ if (jsonSchema.strict !== true) {
156
+ errors.push("Schema must have strict: true");
157
+ }
158
+ if (innerSchema.properties && Array.isArray(innerSchema.required)) {
159
+ const propertyNames = Object.keys(innerSchema.properties);
160
+ const requiredNames = innerSchema.required;
161
+ for (const propName of propertyNames) {
162
+ if (!requiredNames.includes(propName)) {
163
+ errors.push(`Property "${propName}" must be in required array (strict mode requirement)`);
164
+ }
165
+ }
166
+ for (const reqName of requiredNames) {
167
+ if (!propertyNames.includes(reqName)) {
168
+ errors.push(`Required property "${reqName}" is not defined in properties`);
169
+ }
170
+ }
171
+ }
172
+ if (innerSchema.properties) {
173
+ validateNestedObjects(innerSchema.properties, errors, warnings);
174
+ }
175
+ }
176
+ }
177
+ if (schema.json_schema?.schema?.properties) {
178
+ checkForNonPortableFeatures(schema.json_schema.schema.properties, warnings);
179
+ }
180
+ } catch (error) {
181
+ errors.push(`Schema validation error: ${error instanceof Error ? error.message : "Unknown error"}`);
182
+ }
183
+ return {
184
+ valid: errors.length === 0,
185
+ errors,
186
+ warnings
187
+ };
188
+ }
189
+ function validateNestedObjects(properties, errors, warnings) {
190
+ for (const [propName, propDef] of Object.entries(properties)) {
191
+ if (typeof propDef === "object" && propDef !== null) {
192
+ const prop = propDef;
193
+ if (prop.type === "object") {
194
+ if (!prop.properties || typeof prop.properties !== "object") {
195
+ errors.push(`Object property "${propName}" must have properties object`);
196
+ }
197
+ if (!Array.isArray(prop.required)) {
198
+ errors.push(`Object property "${propName}" must have required array`);
199
+ }
200
+ if (prop.additionalProperties !== false) {
201
+ errors.push(`Object property "${propName}" must have additionalProperties: false`);
202
+ }
203
+ if (prop.properties) {
204
+ validateNestedObjects(prop.properties, errors);
205
+ }
206
+ }
207
+ if (prop.type === "array" && prop.items) {
208
+ if (prop.items.type === "object") {
209
+ if (!prop.items.properties || typeof prop.items.properties !== "object") {
210
+ errors.push(`Array items object "${propName}" must have properties object`);
211
+ }
212
+ if (!Array.isArray(prop.items.required)) {
213
+ errors.push(`Array items object "${propName}" must have required array`);
214
+ }
215
+ if (prop.items.additionalProperties !== false) {
216
+ errors.push(`Array items object "${propName}" must have additionalProperties: false`);
217
+ }
218
+ if (prop.items.properties) {
219
+ validateNestedObjects(prop.items.properties, errors);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ function checkForNonPortableFeatures(properties, warnings) {
227
+ for (const [propName, propDef] of Object.entries(properties)) {
228
+ if (typeof propDef === "object" && propDef !== null) {
229
+ const prop = propDef;
230
+ if (prop.enum) {
231
+ warnings.push(`Property "${propName}" uses enum - consider using description instead for better portability`);
232
+ }
233
+ if (prop.pattern) {
234
+ warnings.push(`Property "${propName}" uses pattern - consider using description instead for better portability`);
235
+ }
236
+ if (prop.minimum !== void 0 || prop.maximum !== void 0) {
237
+ warnings.push(`Property "${propName}" uses min/max constraints - consider using description instead for better portability`);
238
+ }
239
+ if (prop.minItems !== void 0 || prop.maxItems !== void 0) {
240
+ warnings.push(`Property "${propName}" uses minItems/maxItems - consider using description instead for better portability`);
241
+ }
242
+ if (prop.uniqueItems !== void 0) {
243
+ warnings.push(`Property "${propName}" uses uniqueItems - consider using description instead for better portability`);
244
+ }
245
+ if (prop.type === "object" && prop.properties) {
246
+ checkForNonPortableFeatures(prop.properties, warnings);
247
+ }
248
+ if (prop.type === "array" && prop.items && prop.items.type === "object" && prop.items.properties) {
249
+ checkForNonPortableFeatures(prop.items.properties, warnings);
250
+ }
251
+ }
252
+ }
253
+ }
254
+ function validateFormFormat(form) {
255
+ const errors = [];
256
+ const warnings = [];
257
+ try {
258
+ if (!form || typeof form !== "object") {
259
+ errors.push("Form must be an object");
260
+ return { valid: false, errors, warnings };
261
+ }
262
+ if (!form.json_formio || !Array.isArray(form.json_formio)) {
263
+ errors.push("Form must have json_formio array");
264
+ return { valid: false, errors, warnings };
265
+ }
266
+ validateFormComponents(form.json_formio, errors, warnings, "");
267
+ if (form.json_formio_mapping) {
268
+ validateFieldMappings(form.json_formio_mapping, form.json_formio, errors, warnings);
269
+ }
270
+ } catch (error) {
271
+ errors.push(`Form validation error: ${error instanceof Error ? error.message : "Unknown error"}`);
272
+ }
273
+ return {
274
+ valid: errors.length === 0,
275
+ errors,
276
+ warnings
277
+ };
278
+ }
279
+ function validateFormComponents(components, errors, warnings, path) {
280
+ const validFieldTypes = [
281
+ "textfield",
282
+ "email",
283
+ "number",
284
+ "select",
285
+ "textarea",
286
+ "checkbox",
287
+ "datetime",
288
+ "phoneNumber",
289
+ "panel",
290
+ "columns",
291
+ "fieldset",
292
+ "radio",
293
+ "selectboxes",
294
+ "currency",
295
+ "day",
296
+ "time",
297
+ "url",
298
+ "password",
299
+ "file"
300
+ ];
301
+ const collectedKeys = /* @__PURE__ */ new Set();
302
+ for (let i = 0; i < components.length; i++) {
303
+ const component = components[i];
304
+ const componentPath = path ? `${path}[${i}]` : `component[${i}]`;
305
+ if (!component || typeof component !== "object") {
306
+ errors.push(`${componentPath}: Component must be an object`);
307
+ continue;
308
+ }
309
+ if (!component.type) {
310
+ errors.push(`${componentPath}: Component must have a "type" field`);
311
+ } else if (!validFieldTypes.includes(component.type)) {
312
+ warnings.push(`${componentPath}: Unknown field type "${component.type}" - may not render correctly`);
313
+ }
314
+ if (component.input === true || ["textfield", "email", "number", "select", "textarea", "checkbox", "datetime", "phoneNumber"].includes(component.type)) {
315
+ if (!component.key) {
316
+ errors.push(`${componentPath}: Input component must have a "key" field`);
317
+ } else {
318
+ if (collectedKeys.has(component.key)) {
319
+ errors.push(`${componentPath}: Duplicate key "${component.key}" found`);
320
+ }
321
+ collectedKeys.add(component.key);
322
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(component.key)) {
323
+ warnings.push(`${componentPath}: Key "${component.key}" should be a valid identifier (alphanumeric and underscore only)`);
324
+ }
325
+ }
326
+ if (!component.label) {
327
+ warnings.push(`${componentPath}: Input component should have a "label" field for better UX`);
328
+ }
329
+ }
330
+ if (component.type === "select") {
331
+ if (!component.data || !component.data.values) {
332
+ errors.push(`${componentPath}: Select field must have data.values array`);
333
+ } else if (!Array.isArray(component.data.values)) {
334
+ errors.push(`${componentPath}: data.values must be an array`);
335
+ } else if (component.data.values.length === 0) {
336
+ warnings.push(`${componentPath}: Select field has empty values array`);
337
+ }
338
+ }
339
+ if (component.type === "panel" || component.type === "fieldset") {
340
+ if (!component.components || !Array.isArray(component.components)) {
341
+ errors.push(`${componentPath}: ${component.type} must have components array`);
342
+ } else {
343
+ validateFormComponents(component.components, errors, warnings, `${componentPath}.components`);
344
+ }
345
+ }
346
+ if (component.type === "columns") {
347
+ if (!component.columns || !Array.isArray(component.columns)) {
348
+ errors.push(`${componentPath}: columns layout must have columns array`);
349
+ } else {
350
+ for (let j = 0; j < component.columns.length; j++) {
351
+ const column = component.columns[j];
352
+ if (!column.components || !Array.isArray(column.components)) {
353
+ errors.push(`${componentPath}.columns[${j}]: Column must have components array`);
354
+ } else {
355
+ validateFormComponents(column.components, errors, warnings, `${componentPath}.columns[${j}].components`);
356
+ }
357
+ }
358
+ }
359
+ }
360
+ if (component.validate) {
361
+ if (typeof component.validate !== "object") {
362
+ errors.push(`${componentPath}: validate must be an object`);
363
+ }
364
+ }
365
+ }
366
+ }
367
+ function validateFieldMappings(mappings, formComponents, errors, warnings) {
368
+ if (typeof mappings !== "object" || mappings === null) {
369
+ errors.push("json_formio_mapping must be an object");
370
+ return;
371
+ }
372
+ const formKeys = /* @__PURE__ */ new Set();
373
+ const collectKeys = (components) => {
374
+ for (const comp of components) {
375
+ if (comp.key) formKeys.add(comp.key);
376
+ if (comp.components) collectKeys(comp.components);
377
+ if (comp.columns) {
378
+ for (const col of comp.columns) {
379
+ if (col.components) collectKeys(col.components);
380
+ }
381
+ }
382
+ }
383
+ };
384
+ collectKeys(formComponents);
385
+ for (const [fieldKey, mapping] of Object.entries(mappings)) {
386
+ if (!formKeys.has(fieldKey)) {
387
+ warnings.push(`Mapping for "${fieldKey}" references a field key that doesn't exist in the form`);
388
+ }
389
+ if (typeof mapping !== "object" || mapping === null) {
390
+ errors.push(`Mapping for "${fieldKey}" must be an object`);
391
+ continue;
392
+ }
393
+ const m = mapping;
394
+ if (!m.sources || !Array.isArray(m.sources)) {
395
+ errors.push(`Mapping for "${fieldKey}" must have sources array`);
396
+ continue;
397
+ }
398
+ if (m.sources.length === 0) {
399
+ warnings.push(`Mapping for "${fieldKey}" has empty sources array`);
400
+ }
401
+ for (let i = 0; i < m.sources.length; i++) {
402
+ const source = m.sources[i];
403
+ if (!source.promptId) {
404
+ errors.push(`Mapping for "${fieldKey}".sources[${i}] must have promptId`);
405
+ }
406
+ if (!source.schemaFieldPath) {
407
+ errors.push(`Mapping for "${fieldKey}".sources[${i}] must have schemaFieldPath`);
408
+ }
409
+ }
410
+ if (!m.mappingType) {
411
+ errors.push(`Mapping for "${fieldKey}" must have mappingType`);
412
+ } else if (!["direct", "concatenated"].includes(m.mappingType)) {
413
+ errors.push(`Mapping for "${fieldKey}" has invalid mappingType "${m.mappingType}" (must be "direct" or "concatenated")`);
414
+ }
415
+ if (m.mappingType === "concatenated" && m.sources.length < 2) {
416
+ warnings.push(`Mapping for "${fieldKey}" is marked as concatenated but only has ${m.sources.length} source(s)`);
417
+ }
418
+ }
419
+ }
420
+ var tools = [
421
+ // ========== DOCUMENTS ==========
422
+ {
423
+ name: "upload_documents",
424
+ description: "Upload documents to DocRouter",
425
+ inputSchema: {
426
+ type: "object",
427
+ properties: {
428
+ documents: {
429
+ type: "array",
430
+ description: "Array of documents to upload",
431
+ items: {
432
+ type: "object",
433
+ properties: {
434
+ name: { type: "string", description: "Document name" },
435
+ content: { type: "string", description: "Base64 encoded document content" },
436
+ type: { type: "string", description: "Document type (pdf, image, etc.)" },
437
+ metadata: { type: "object", description: "Optional metadata" }
438
+ },
439
+ required: ["name", "content", "type"]
440
+ }
441
+ }
442
+ },
443
+ required: ["documents"]
444
+ }
445
+ },
446
+ {
447
+ name: "list_documents",
448
+ description: "List documents from DocRouter",
449
+ inputSchema: {
450
+ type: "object",
451
+ properties: {
452
+ skip: { type: "number", description: "Number of documents to skip", default: 0 },
453
+ limit: { type: "number", description: "Number of documents to return", default: 10 },
454
+ tagIds: { type: "string", description: "Comma-separated list of tag IDs to filter by" },
455
+ nameSearch: { type: "string", description: "Search by document name" },
456
+ metadataSearch: { type: "string", description: "Search by metadata" }
457
+ }
458
+ }
459
+ },
460
+ {
461
+ name: "get_document",
462
+ description: "Get document by ID from DocRouter",
463
+ inputSchema: {
464
+ type: "object",
465
+ properties: {
466
+ documentId: { type: "string", description: "ID of the document to retrieve" },
467
+ fileType: { type: "string", description: "File type to retrieve (pdf, image, etc.)", default: "pdf" }
468
+ },
469
+ required: ["documentId"]
470
+ }
471
+ },
472
+ {
473
+ name: "update_document",
474
+ description: "Update document metadata",
475
+ inputSchema: {
476
+ type: "object",
477
+ properties: {
478
+ documentId: { type: "string", description: "ID of the document to update" },
479
+ documentName: { type: "string", description: "New document name" },
480
+ tagIds: { type: "array", items: { type: "string" }, description: "Array of tag IDs" },
481
+ metadata: { type: "object", description: "Document metadata" }
482
+ },
483
+ required: ["documentId"]
484
+ }
485
+ },
486
+ {
487
+ name: "delete_document",
488
+ description: "Delete a document",
489
+ inputSchema: {
490
+ type: "object",
491
+ properties: {
492
+ documentId: { type: "string", description: "ID of the document to delete" }
493
+ },
494
+ required: ["documentId"]
495
+ }
496
+ },
497
+ // ========== OCR ==========
498
+ {
499
+ name: "get_ocr_blocks",
500
+ description: "Get OCR blocks for a document",
501
+ inputSchema: {
502
+ type: "object",
503
+ properties: {
504
+ documentId: { type: "string", description: "ID of the document" }
505
+ },
506
+ required: ["documentId"]
507
+ }
508
+ },
509
+ {
510
+ name: "get_ocr_text",
511
+ description: "Get OCR text for a document",
512
+ inputSchema: {
513
+ type: "object",
514
+ properties: {
515
+ documentId: { type: "string", description: "ID of the document" },
516
+ pageNum: { type: "number", description: "Optional page number" }
517
+ },
518
+ required: ["documentId"]
519
+ }
520
+ },
521
+ {
522
+ name: "get_ocr_metadata",
523
+ description: "Get OCR metadata for a document",
524
+ inputSchema: {
525
+ type: "object",
526
+ properties: {
527
+ documentId: { type: "string", description: "ID of the document" }
528
+ },
529
+ required: ["documentId"]
530
+ }
531
+ },
532
+ // ========== LLM ==========
533
+ {
534
+ name: "run_llm",
535
+ description: "Run AI extraction on a document using a specific prompt",
536
+ inputSchema: {
537
+ type: "object",
538
+ properties: {
539
+ documentId: { type: "string", description: "ID of the document" },
540
+ promptRevId: { type: "string", description: "ID of the prompt" },
541
+ force: { type: "boolean", description: "Force re-extraction", default: false }
542
+ },
543
+ required: ["documentId", "promptRevId"]
544
+ }
545
+ },
546
+ {
547
+ name: "get_llm_result",
548
+ description: "Get LLM extraction results",
549
+ inputSchema: {
550
+ type: "object",
551
+ properties: {
552
+ documentId: { type: "string", description: "ID of the document" },
553
+ promptRevId: { type: "string", description: "ID of the prompt" },
554
+ fallback: { type: "boolean", description: "Use fallback results", default: false }
555
+ },
556
+ required: ["documentId", "promptRevId"]
557
+ }
558
+ },
559
+ {
560
+ name: "update_llm_result",
561
+ description: "Update LLM extraction results",
562
+ inputSchema: {
563
+ type: "object",
564
+ properties: {
565
+ documentId: { type: "string", description: "ID of the document" },
566
+ promptId: { type: "string", description: "ID of the prompt" },
567
+ result: { type: "object", description: "Updated result data" },
568
+ isVerified: { type: "boolean", description: "Whether result is verified", default: false }
569
+ },
570
+ required: ["documentId", "promptId", "result"]
571
+ }
572
+ },
573
+ {
574
+ name: "delete_llm_result",
575
+ description: "Delete LLM extraction results",
576
+ inputSchema: {
577
+ type: "object",
578
+ properties: {
579
+ documentId: { type: "string", description: "ID of the document" },
580
+ promptId: { type: "string", description: "ID of the prompt" }
581
+ },
582
+ required: ["documentId", "promptId"]
583
+ }
584
+ },
585
+ // ========== TAGS ==========
586
+ {
587
+ name: "create_tag",
588
+ description: "Create a new tag",
589
+ inputSchema: {
590
+ type: "object",
591
+ properties: {
592
+ tag: {
593
+ type: "object",
594
+ properties: {
595
+ name: { type: "string", description: "Tag name" },
596
+ color: { type: "string", description: "Tag color" }
597
+ },
598
+ required: ["name", "color"]
599
+ }
600
+ },
601
+ required: ["tag"]
602
+ }
603
+ },
604
+ {
605
+ name: "get_tag",
606
+ description: "Get tag by ID",
607
+ inputSchema: {
608
+ type: "object",
609
+ properties: {
610
+ tagId: { type: "string", description: "ID of the tag" }
611
+ },
612
+ required: ["tagId"]
613
+ }
614
+ },
615
+ {
616
+ name: "list_tags",
617
+ description: "List all tags",
618
+ inputSchema: {
619
+ type: "object",
620
+ properties: {
621
+ skip: { type: "number", description: "Number of tags to skip", default: 0 },
622
+ limit: { type: "number", description: "Number of tags to return", default: 10 },
623
+ nameSearch: { type: "string", description: "Search by tag name" }
624
+ }
625
+ }
626
+ },
627
+ {
628
+ name: "update_tag",
629
+ description: "Update a tag",
630
+ inputSchema: {
631
+ type: "object",
632
+ properties: {
633
+ tagId: { type: "string", description: "ID of the tag" },
634
+ tag: {
635
+ type: "object",
636
+ properties: {
637
+ name: { type: "string", description: "Tag name" },
638
+ color: { type: "string", description: "Tag color" }
639
+ }
640
+ }
641
+ },
642
+ required: ["tagId", "tag"]
643
+ }
644
+ },
645
+ {
646
+ name: "delete_tag",
647
+ description: "Delete a tag",
648
+ inputSchema: {
649
+ type: "object",
650
+ properties: {
651
+ tagId: { type: "string", description: "ID of the tag" }
652
+ },
653
+ required: ["tagId"]
654
+ }
655
+ },
656
+ // ========== FORMS ==========
657
+ {
658
+ name: "create_form",
659
+ description: "Create a new form",
660
+ inputSchema: {
661
+ type: "object",
662
+ properties: {
663
+ name: { type: "string", description: "Form name" },
664
+ response_format: { type: "object", description: "Form response format" }
665
+ },
666
+ required: ["name", "response_format"]
667
+ }
668
+ },
669
+ {
670
+ name: "list_forms",
671
+ description: "List all forms",
672
+ inputSchema: {
673
+ type: "object",
674
+ properties: {
675
+ skip: { type: "number", description: "Number of forms to skip", default: 0 },
676
+ limit: { type: "number", description: "Number of forms to return", default: 10 },
677
+ tag_ids: { type: "string", description: "Comma-separated tag IDs" }
678
+ }
679
+ }
680
+ },
681
+ {
682
+ name: "get_form",
683
+ description: "Get form by ID",
684
+ inputSchema: {
685
+ type: "object",
686
+ properties: {
687
+ formRevId: { type: "string", description: "ID of the form" }
688
+ },
689
+ required: ["formRevId"]
690
+ }
691
+ },
692
+ {
693
+ name: "update_form",
694
+ description: "Update a form",
695
+ inputSchema: {
696
+ type: "object",
697
+ properties: {
698
+ formId: { type: "string", description: "ID of the form" },
699
+ form: { type: "object", description: "Form data" }
700
+ },
701
+ required: ["formId", "form"]
702
+ }
703
+ },
704
+ {
705
+ name: "delete_form",
706
+ description: "Delete a form",
707
+ inputSchema: {
708
+ type: "object",
709
+ properties: {
710
+ formId: { type: "string", description: "ID of the form" }
711
+ },
712
+ required: ["formId"]
713
+ }
714
+ },
715
+ {
716
+ name: "submit_form",
717
+ description: "Submit a form",
718
+ inputSchema: {
719
+ type: "object",
720
+ properties: {
721
+ documentId: { type: "string", description: "ID of the document" },
722
+ formRevId: { type: "string", description: "ID of the form" },
723
+ submission_data: { type: "object", description: "Form submission data" },
724
+ submitted_by: { type: "string", description: "User who submitted" }
725
+ },
726
+ required: ["documentId", "formRevId", "submission_data"]
727
+ }
728
+ },
729
+ {
730
+ name: "get_form_submission",
731
+ description: "Get form submission",
732
+ inputSchema: {
733
+ type: "object",
734
+ properties: {
735
+ documentId: { type: "string", description: "ID of the document" },
736
+ formRevId: { type: "string", description: "ID of the form" }
737
+ },
738
+ required: ["documentId", "formRevId"]
739
+ }
740
+ },
741
+ {
742
+ name: "delete_form_submission",
743
+ description: "Delete form submission",
744
+ inputSchema: {
745
+ type: "object",
746
+ properties: {
747
+ documentId: { type: "string", description: "ID of the document" },
748
+ formRevId: { type: "string", description: "ID of the form" }
749
+ },
750
+ required: ["documentId", "formRevId"]
751
+ }
752
+ },
753
+ // ========== PROMPTS ==========
754
+ {
755
+ name: "create_prompt",
756
+ description: "Create a new prompt",
757
+ inputSchema: {
758
+ type: "object",
759
+ properties: {
760
+ prompt: {
761
+ type: "object",
762
+ properties: {
763
+ name: { type: "string", description: "Prompt name" },
764
+ content: { type: "string", description: "Prompt content" }
765
+ },
766
+ required: ["name", "content"]
767
+ }
768
+ },
769
+ required: ["prompt"]
770
+ }
771
+ },
772
+ {
773
+ name: "list_prompts",
774
+ description: "List all prompts",
775
+ inputSchema: {
776
+ type: "object",
777
+ properties: {
778
+ skip: { type: "number", description: "Number of prompts to skip", default: 0 },
779
+ limit: { type: "number", description: "Number of prompts to return", default: 10 },
780
+ document_id: { type: "string", description: "Filter by document ID" },
781
+ tag_ids: { type: "string", description: "Comma-separated tag IDs" },
782
+ nameSearch: { type: "string", description: "Search by prompt name" }
783
+ }
784
+ }
785
+ },
786
+ {
787
+ name: "get_prompt",
788
+ description: "Get prompt by ID",
789
+ inputSchema: {
790
+ type: "object",
791
+ properties: {
792
+ promptRevId: { type: "string", description: "ID of the prompt" }
793
+ },
794
+ required: ["promptRevId"]
795
+ }
796
+ },
797
+ {
798
+ name: "update_prompt",
799
+ description: "Update a prompt",
800
+ inputSchema: {
801
+ type: "object",
802
+ properties: {
803
+ promptId: { type: "string", description: "ID of the prompt" },
804
+ prompt: { type: "object", description: "Prompt data" }
805
+ },
806
+ required: ["promptId", "prompt"]
807
+ }
808
+ },
809
+ {
810
+ name: "delete_prompt",
811
+ description: "Delete a prompt",
812
+ inputSchema: {
813
+ type: "object",
814
+ properties: {
815
+ promptId: { type: "string", description: "ID of the prompt" }
816
+ },
817
+ required: ["promptId"]
818
+ }
819
+ },
820
+ // ========== SCHEMAS ==========
821
+ {
822
+ name: "create_schema",
823
+ description: "Create a new schema",
824
+ inputSchema: {
825
+ type: "object",
826
+ properties: {
827
+ name: { type: "string", description: "Schema name" },
828
+ response_format: { type: "object", description: "Schema response format" }
829
+ },
830
+ required: ["name", "response_format"]
831
+ }
832
+ },
833
+ {
834
+ name: "list_schemas",
835
+ description: "List all schemas",
836
+ inputSchema: {
837
+ type: "object",
838
+ properties: {
839
+ skip: { type: "number", description: "Number of schemas to skip", default: 0 },
840
+ limit: { type: "number", description: "Number of schemas to return", default: 10 },
841
+ nameSearch: { type: "string", description: "Search by schema name" }
842
+ }
843
+ }
844
+ },
845
+ {
846
+ name: "get_schema",
847
+ description: "Get schema by ID",
848
+ inputSchema: {
849
+ type: "object",
850
+ properties: {
851
+ schemaRevId: { type: "string", description: "ID of the schema" }
852
+ },
853
+ required: ["schemaRevId"]
854
+ }
855
+ },
856
+ {
857
+ name: "update_schema",
858
+ description: "Update a schema",
859
+ inputSchema: {
860
+ type: "object",
861
+ properties: {
862
+ schemaId: { type: "string", description: "ID of the schema" },
863
+ schema: { type: "object", description: "Schema data" }
864
+ },
865
+ required: ["schemaId", "schema"]
866
+ }
867
+ },
868
+ {
869
+ name: "delete_schema",
870
+ description: "Delete a schema",
871
+ inputSchema: {
872
+ type: "object",
873
+ properties: {
874
+ schemaId: { type: "string", description: "ID of the schema" }
875
+ },
876
+ required: ["schemaId"]
877
+ }
878
+ },
879
+ {
880
+ name: "validate_against_schema",
881
+ description: "Validate data against a schema",
882
+ inputSchema: {
883
+ type: "object",
884
+ properties: {
885
+ schemaRevId: { type: "string", description: "ID of the schema" },
886
+ data: { type: "object", description: "Data to validate" }
887
+ },
888
+ required: ["schemaRevId", "data"]
889
+ }
890
+ },
891
+ {
892
+ name: "validate_schema",
893
+ description: "Validate schema format for correctness and DocRouter compliance",
894
+ inputSchema: {
895
+ type: "object",
896
+ properties: {
897
+ schema: { type: "string", description: "JSON string of the schema to validate" }
898
+ },
899
+ required: ["schema"]
900
+ }
901
+ },
902
+ {
903
+ name: "validate_form",
904
+ description: "Validate Form.io form format for correctness and DocRouter compliance",
905
+ inputSchema: {
906
+ type: "object",
907
+ properties: {
908
+ form: { type: "string", description: "JSON string of the form to validate" }
909
+ },
910
+ required: ["form"]
911
+ }
912
+ },
913
+ // ========== LLM CHAT ==========
914
+ {
915
+ name: "run_llm_chat",
916
+ description: "Run LLM chat",
917
+ inputSchema: {
918
+ type: "object",
919
+ properties: {
920
+ messages: {
921
+ type: "array",
922
+ description: "Chat messages",
923
+ items: {
924
+ type: "object",
925
+ properties: {
926
+ role: { type: "string", enum: ["system", "user", "assistant"] },
927
+ content: { type: "string" }
928
+ },
929
+ required: ["role", "content"]
930
+ }
931
+ },
932
+ model: { type: "string", description: "Model to use" },
933
+ temperature: { type: "number", description: "Temperature setting" },
934
+ max_tokens: { type: "number", description: "Maximum tokens" },
935
+ stream: { type: "boolean", description: "Enable streaming" }
936
+ },
937
+ required: ["messages"]
938
+ }
939
+ },
940
+ // ========== HELPER TOOLS ==========
941
+ {
942
+ name: "help",
943
+ description: "Get help information about using the API",
944
+ inputSchema: {
945
+ type: "object",
946
+ properties: {}
947
+ }
948
+ },
949
+ {
950
+ name: "help_prompts",
951
+ description: "Get help information about creating and configuring prompts in DocRouter",
952
+ inputSchema: {
953
+ type: "object",
954
+ properties: {}
955
+ }
956
+ },
957
+ {
958
+ name: "help_schemas",
959
+ description: "Get help information about creating and configuring schemas in DocRouter",
960
+ inputSchema: {
961
+ type: "object",
962
+ properties: {}
963
+ }
964
+ },
965
+ {
966
+ name: "help_forms",
967
+ description: "Get help information about creating and configuring forms in DocRouter",
968
+ inputSchema: {
969
+ type: "object",
970
+ properties: {}
971
+ }
972
+ }
973
+ ];
974
+ server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
975
+ return { tools };
976
+ });
977
+ server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
978
+ const { name, arguments: args } = request.params;
979
+ if (!args) {
980
+ throw new Error("No arguments provided");
981
+ }
982
+ try {
983
+ switch (name) {
984
+ case "list_documents": {
985
+ const result = await docrouterClient.listDocuments({
986
+ skip: getOptionalArg(args, "skip", 0),
987
+ limit: getOptionalArg(args, "limit", 10),
988
+ nameSearch: getOptionalArg(args, "nameSearch"),
989
+ tagIds: getOptionalArg(args, "tagIds")
990
+ });
991
+ return {
992
+ content: [
993
+ {
994
+ type: "text",
995
+ text: JSON.stringify(serializeDates(result), null, 2)
996
+ }
997
+ ]
998
+ };
999
+ }
1000
+ case "get_document": {
1001
+ const result = await docrouterClient.getDocument({
1002
+ documentId: getArg(args, "documentId"),
1003
+ fileType: getArg(args, "fileType", "pdf")
1004
+ });
1005
+ const base64Content = Buffer.from(result.content).toString("base64");
1006
+ return {
1007
+ content: [
1008
+ {
1009
+ type: "text",
1010
+ text: JSON.stringify({
1011
+ ...serializeDates(result),
1012
+ content: base64Content,
1013
+ content_type: "base64",
1014
+ content_size: result.content.byteLength
1015
+ }, null, 2)
1016
+ }
1017
+ ]
1018
+ };
1019
+ }
1020
+ case "get_ocr_text": {
1021
+ const result = await docrouterClient.getOCRText({
1022
+ documentId: getArg(args, "documentId"),
1023
+ pageNum: getOptionalArg(args, "pageNum")
1024
+ });
1025
+ return {
1026
+ content: [
1027
+ {
1028
+ type: "text",
1029
+ text: result
1030
+ }
1031
+ ]
1032
+ };
1033
+ }
1034
+ case "get_ocr_metadata": {
1035
+ const result = await docrouterClient.getOCRMetadata({
1036
+ documentId: getArg(args, "documentId")
1037
+ });
1038
+ return {
1039
+ content: [
1040
+ {
1041
+ type: "text",
1042
+ text: JSON.stringify(serializeDates(result), null, 2)
1043
+ }
1044
+ ]
1045
+ };
1046
+ }
1047
+ case "list_tags": {
1048
+ const result = await docrouterClient.listTags({
1049
+ skip: getOptionalArg(args, "skip", 0),
1050
+ limit: getOptionalArg(args, "limit", 10),
1051
+ nameSearch: getOptionalArg(args, "nameSearch")
1052
+ });
1053
+ return {
1054
+ content: [
1055
+ {
1056
+ type: "text",
1057
+ text: JSON.stringify(serializeDates(result), null, 2)
1058
+ }
1059
+ ]
1060
+ };
1061
+ }
1062
+ case "get_tag": {
1063
+ const result = await docrouterClient.getTag({
1064
+ tagId: getArg(args, "tagId")
1065
+ });
1066
+ return {
1067
+ content: [
1068
+ {
1069
+ type: "text",
1070
+ text: JSON.stringify(serializeDates(result), null, 2)
1071
+ }
1072
+ ]
1073
+ };
1074
+ }
1075
+ case "list_prompts": {
1076
+ const result = await docrouterClient.listPrompts({
1077
+ skip: getOptionalArg(args, "skip", 0),
1078
+ limit: getOptionalArg(args, "limit", 10),
1079
+ nameSearch: getOptionalArg(args, "nameSearch"),
1080
+ document_id: getOptionalArg(args, "documentId"),
1081
+ tag_ids: getOptionalArg(args, "tagIds")
1082
+ });
1083
+ return {
1084
+ content: [
1085
+ {
1086
+ type: "text",
1087
+ text: JSON.stringify(serializeDates(result), null, 2)
1088
+ }
1089
+ ]
1090
+ };
1091
+ }
1092
+ case "get_prompt": {
1093
+ const result = await docrouterClient.getPrompt({
1094
+ promptRevId: getArg(args, "promptRevId")
1095
+ });
1096
+ return {
1097
+ content: [
1098
+ {
1099
+ type: "text",
1100
+ text: JSON.stringify(serializeDates(result), null, 2)
1101
+ }
1102
+ ]
1103
+ };
1104
+ }
1105
+ case "get_llm_result": {
1106
+ const result = await docrouterClient.getLLMResult({
1107
+ documentId: getArg(args, "documentId"),
1108
+ promptRevId: getArg(args, "promptRevId"),
1109
+ fallback: getOptionalArg(args, "fallback", false)
1110
+ });
1111
+ return {
1112
+ content: [
1113
+ {
1114
+ type: "text",
1115
+ text: JSON.stringify(serializeDates(result), null, 2)
1116
+ }
1117
+ ]
1118
+ };
1119
+ }
1120
+ case "run_llm": {
1121
+ const result = await docrouterClient.runLLM({
1122
+ documentId: getArg(args, "documentId"),
1123
+ promptRevId: getArg(args, "promptRevId"),
1124
+ force: getOptionalArg(args, "force", false)
1125
+ });
1126
+ return {
1127
+ content: [
1128
+ {
1129
+ type: "text",
1130
+ text: JSON.stringify(serializeDates(result), null, 2)
1131
+ }
1132
+ ]
1133
+ };
1134
+ }
1135
+ // ========== DOCUMENTS ==========
1136
+ case "upload_documents": {
1137
+ const documentsInput = getArg(args, "documents");
1138
+ const documents = documentsInput.map((doc) => ({
1139
+ ...doc,
1140
+ content: Buffer.from(doc.content, "base64")
1141
+ }));
1142
+ const result = await docrouterClient.uploadDocuments({ documents });
1143
+ return {
1144
+ content: [
1145
+ {
1146
+ type: "text",
1147
+ text: JSON.stringify(serializeDates(result), null, 2)
1148
+ }
1149
+ ]
1150
+ };
1151
+ }
1152
+ case "update_document": {
1153
+ const result = await docrouterClient.updateDocument({
1154
+ documentId: getArg(args, "documentId"),
1155
+ documentName: getOptionalArg(args, "documentName"),
1156
+ tagIds: getOptionalArg(args, "tagIds"),
1157
+ metadata: getOptionalArg(args, "metadata")
1158
+ });
1159
+ return {
1160
+ content: [
1161
+ {
1162
+ type: "text",
1163
+ text: JSON.stringify(serializeDates(result), null, 2)
1164
+ }
1165
+ ]
1166
+ };
1167
+ }
1168
+ case "delete_document": {
1169
+ const result = await docrouterClient.deleteDocument({
1170
+ documentId: getArg(args, "documentId")
1171
+ });
1172
+ return {
1173
+ content: [
1174
+ {
1175
+ type: "text",
1176
+ text: JSON.stringify(serializeDates(result), null, 2)
1177
+ }
1178
+ ]
1179
+ };
1180
+ }
1181
+ // ========== OCR ==========
1182
+ case "get_ocr_blocks": {
1183
+ const result = await docrouterClient.getOCRBlocks({
1184
+ documentId: getArg(args, "documentId")
1185
+ });
1186
+ return {
1187
+ content: [
1188
+ {
1189
+ type: "text",
1190
+ text: JSON.stringify(serializeDates(result), null, 2)
1191
+ }
1192
+ ]
1193
+ };
1194
+ }
1195
+ // ========== LLM ==========
1196
+ case "update_llm_result": {
1197
+ const result = await docrouterClient.updateLLMResult({
1198
+ documentId: getArg(args, "documentId"),
1199
+ promptId: getArg(args, "promptId"),
1200
+ result: getArg(args, "result"),
1201
+ isVerified: getOptionalArg(args, "isVerified", false)
1202
+ });
1203
+ return {
1204
+ content: [
1205
+ {
1206
+ type: "text",
1207
+ text: JSON.stringify(serializeDates(result), null, 2)
1208
+ }
1209
+ ]
1210
+ };
1211
+ }
1212
+ case "delete_llm_result": {
1213
+ const result = await docrouterClient.deleteLLMResult({
1214
+ documentId: getArg(args, "documentId"),
1215
+ promptId: getArg(args, "promptId")
1216
+ });
1217
+ return {
1218
+ content: [
1219
+ {
1220
+ type: "text",
1221
+ text: JSON.stringify(serializeDates(result), null, 2)
1222
+ }
1223
+ ]
1224
+ };
1225
+ }
1226
+ // ========== TAGS ==========
1227
+ case "create_tag": {
1228
+ const result = await docrouterClient.createTag({
1229
+ tag: getArg(args, "tag")
1230
+ });
1231
+ return {
1232
+ content: [
1233
+ {
1234
+ type: "text",
1235
+ text: JSON.stringify(serializeDates(result), null, 2)
1236
+ }
1237
+ ]
1238
+ };
1239
+ }
1240
+ case "update_tag": {
1241
+ const result = await docrouterClient.updateTag({
1242
+ tagId: getArg(args, "tagId"),
1243
+ tag: getArg(args, "tag")
1244
+ });
1245
+ return {
1246
+ content: [
1247
+ {
1248
+ type: "text",
1249
+ text: JSON.stringify(serializeDates(result), null, 2)
1250
+ }
1251
+ ]
1252
+ };
1253
+ }
1254
+ case "delete_tag": {
1255
+ const result = await docrouterClient.deleteTag({
1256
+ tagId: getArg(args, "tagId")
1257
+ });
1258
+ return {
1259
+ content: [
1260
+ {
1261
+ type: "text",
1262
+ text: JSON.stringify(serializeDates(result), null, 2)
1263
+ }
1264
+ ]
1265
+ };
1266
+ }
1267
+ // ========== FORMS ==========
1268
+ case "create_form": {
1269
+ const result = await docrouterClient.createForm({
1270
+ name: getArg(args, "name"),
1271
+ response_format: getArg(args, "response_format")
1272
+ });
1273
+ return {
1274
+ content: [
1275
+ {
1276
+ type: "text",
1277
+ text: JSON.stringify(serializeDates(result), null, 2)
1278
+ }
1279
+ ]
1280
+ };
1281
+ }
1282
+ case "list_forms": {
1283
+ const result = await docrouterClient.listForms({
1284
+ skip: getOptionalArg(args, "skip", 0),
1285
+ limit: getOptionalArg(args, "limit", 10),
1286
+ tag_ids: getOptionalArg(args, "tag_ids")
1287
+ });
1288
+ return {
1289
+ content: [
1290
+ {
1291
+ type: "text",
1292
+ text: JSON.stringify(serializeDates(result), null, 2)
1293
+ }
1294
+ ]
1295
+ };
1296
+ }
1297
+ case "get_form": {
1298
+ const result = await docrouterClient.getForm({
1299
+ formRevId: getArg(args, "formRevId")
1300
+ });
1301
+ return {
1302
+ content: [
1303
+ {
1304
+ type: "text",
1305
+ text: JSON.stringify(serializeDates(result), null, 2)
1306
+ }
1307
+ ]
1308
+ };
1309
+ }
1310
+ case "update_form": {
1311
+ const result = await docrouterClient.updateForm({
1312
+ formId: getArg(args, "formId"),
1313
+ form: getArg(args, "form")
1314
+ });
1315
+ return {
1316
+ content: [
1317
+ {
1318
+ type: "text",
1319
+ text: JSON.stringify(serializeDates(result), null, 2)
1320
+ }
1321
+ ]
1322
+ };
1323
+ }
1324
+ case "delete_form": {
1325
+ const result = await docrouterClient.deleteForm({
1326
+ formId: getArg(args, "formId")
1327
+ });
1328
+ return {
1329
+ content: [
1330
+ {
1331
+ type: "text",
1332
+ text: JSON.stringify(serializeDates(result), null, 2)
1333
+ }
1334
+ ]
1335
+ };
1336
+ }
1337
+ case "submit_form": {
1338
+ const result = await docrouterClient.submitForm({
1339
+ documentId: getArg(args, "documentId"),
1340
+ formRevId: getArg(args, "formRevId"),
1341
+ submission_data: getArg(args, "submission_data"),
1342
+ submitted_by: getOptionalArg(args, "submitted_by")
1343
+ });
1344
+ return {
1345
+ content: [
1346
+ {
1347
+ type: "text",
1348
+ text: JSON.stringify(serializeDates(result), null, 2)
1349
+ }
1350
+ ]
1351
+ };
1352
+ }
1353
+ case "get_form_submission": {
1354
+ const result = await docrouterClient.getFormSubmission({
1355
+ documentId: getArg(args, "documentId"),
1356
+ formRevId: getArg(args, "formRevId")
1357
+ });
1358
+ return {
1359
+ content: [
1360
+ {
1361
+ type: "text",
1362
+ text: JSON.stringify(serializeDates(result), null, 2)
1363
+ }
1364
+ ]
1365
+ };
1366
+ }
1367
+ case "delete_form_submission": {
1368
+ const result = await docrouterClient.deleteFormSubmission({
1369
+ documentId: getArg(args, "documentId"),
1370
+ formRevId: getArg(args, "formRevId")
1371
+ });
1372
+ return {
1373
+ content: [
1374
+ {
1375
+ type: "text",
1376
+ text: JSON.stringify(serializeDates(result), null, 2)
1377
+ }
1378
+ ]
1379
+ };
1380
+ }
1381
+ // ========== PROMPTS ==========
1382
+ case "create_prompt": {
1383
+ const result = await docrouterClient.createPrompt({
1384
+ prompt: getArg(args, "prompt")
1385
+ });
1386
+ return {
1387
+ content: [
1388
+ {
1389
+ type: "text",
1390
+ text: JSON.stringify(serializeDates(result), null, 2)
1391
+ }
1392
+ ]
1393
+ };
1394
+ }
1395
+ case "update_prompt": {
1396
+ const result = await docrouterClient.updatePrompt({
1397
+ promptId: getArg(args, "promptId"),
1398
+ prompt: getArg(args, "prompt")
1399
+ });
1400
+ return {
1401
+ content: [
1402
+ {
1403
+ type: "text",
1404
+ text: JSON.stringify(serializeDates(result), null, 2)
1405
+ }
1406
+ ]
1407
+ };
1408
+ }
1409
+ case "delete_prompt": {
1410
+ const result = await docrouterClient.deletePrompt({
1411
+ promptId: getArg(args, "promptId")
1412
+ });
1413
+ return {
1414
+ content: [
1415
+ {
1416
+ type: "text",
1417
+ text: JSON.stringify(serializeDates(result), null, 2)
1418
+ }
1419
+ ]
1420
+ };
1421
+ }
1422
+ // ========== SCHEMAS ==========
1423
+ case "create_schema": {
1424
+ const result = await docrouterClient.createSchema({
1425
+ name: getArg(args, "name"),
1426
+ response_format: getArg(args, "response_format")
1427
+ });
1428
+ return {
1429
+ content: [
1430
+ {
1431
+ type: "text",
1432
+ text: JSON.stringify(serializeDates(result), null, 2)
1433
+ }
1434
+ ]
1435
+ };
1436
+ }
1437
+ case "list_schemas": {
1438
+ const result = await docrouterClient.listSchemas({
1439
+ skip: getOptionalArg(args, "skip", 0),
1440
+ limit: getOptionalArg(args, "limit", 10),
1441
+ nameSearch: getOptionalArg(args, "nameSearch")
1442
+ });
1443
+ return {
1444
+ content: [
1445
+ {
1446
+ type: "text",
1447
+ text: JSON.stringify(serializeDates(result), null, 2)
1448
+ }
1449
+ ]
1450
+ };
1451
+ }
1452
+ case "get_schema": {
1453
+ const result = await docrouterClient.getSchema({
1454
+ schemaRevId: getArg(args, "schemaRevId")
1455
+ });
1456
+ return {
1457
+ content: [
1458
+ {
1459
+ type: "text",
1460
+ text: JSON.stringify(serializeDates(result), null, 2)
1461
+ }
1462
+ ]
1463
+ };
1464
+ }
1465
+ case "update_schema": {
1466
+ const result = await docrouterClient.updateSchema({
1467
+ schemaId: getArg(args, "schemaId"),
1468
+ schema: getArg(args, "schema")
1469
+ });
1470
+ return {
1471
+ content: [
1472
+ {
1473
+ type: "text",
1474
+ text: JSON.stringify(serializeDates(result), null, 2)
1475
+ }
1476
+ ]
1477
+ };
1478
+ }
1479
+ case "delete_schema": {
1480
+ const result = await docrouterClient.deleteSchema({
1481
+ schemaId: getArg(args, "schemaId")
1482
+ });
1483
+ return {
1484
+ content: [
1485
+ {
1486
+ type: "text",
1487
+ text: JSON.stringify(serializeDates(result), null, 2)
1488
+ }
1489
+ ]
1490
+ };
1491
+ }
1492
+ case "validate_against_schema": {
1493
+ const result = await docrouterClient.validateAgainstSchema({
1494
+ schemaRevId: getArg(args, "schemaRevId"),
1495
+ data: getArg(args, "data")
1496
+ });
1497
+ return {
1498
+ content: [
1499
+ {
1500
+ type: "text",
1501
+ text: JSON.stringify(serializeDates(result), null, 2)
1502
+ }
1503
+ ]
1504
+ };
1505
+ }
1506
+ case "validate_schema": {
1507
+ const schemaString = getArg(args, "schema");
1508
+ try {
1509
+ const schema = JSON.parse(schemaString);
1510
+ const validationResult = validateSchemaFormat(schema);
1511
+ return {
1512
+ content: [
1513
+ {
1514
+ type: "text",
1515
+ text: JSON.stringify(validationResult, null, 2)
1516
+ }
1517
+ ]
1518
+ };
1519
+ } catch (error) {
1520
+ return {
1521
+ content: [
1522
+ {
1523
+ type: "text",
1524
+ text: JSON.stringify({
1525
+ valid: false,
1526
+ errors: [`Invalid JSON string: ${error instanceof Error ? error.message : "Unknown error"}`],
1527
+ warnings: []
1528
+ }, null, 2)
1529
+ }
1530
+ ],
1531
+ isError: true
1532
+ };
1533
+ }
1534
+ }
1535
+ case "validate_form": {
1536
+ const formString = getArg(args, "form");
1537
+ try {
1538
+ const form = JSON.parse(formString);
1539
+ const validationResult = validateFormFormat(form);
1540
+ return {
1541
+ content: [
1542
+ {
1543
+ type: "text",
1544
+ text: JSON.stringify(validationResult, null, 2)
1545
+ }
1546
+ ]
1547
+ };
1548
+ } catch (error) {
1549
+ return {
1550
+ content: [
1551
+ {
1552
+ type: "text",
1553
+ text: JSON.stringify({
1554
+ valid: false,
1555
+ errors: [`Invalid JSON string: ${error instanceof Error ? error.message : "Unknown error"}`],
1556
+ warnings: []
1557
+ }, null, 2)
1558
+ }
1559
+ ],
1560
+ isError: true
1561
+ };
1562
+ }
1563
+ }
1564
+ // ========== LLM CHAT ==========
1565
+ case "run_llm_chat": {
1566
+ const result = await docrouterClient.runLLMChat({
1567
+ messages: getArg(args, "messages"),
1568
+ model: getOptionalArg(args, "model"),
1569
+ temperature: getOptionalArg(args, "temperature"),
1570
+ max_tokens: getOptionalArg(args, "max_tokens"),
1571
+ stream: getOptionalArg(args, "stream")
1572
+ });
1573
+ return {
1574
+ content: [
1575
+ {
1576
+ type: "text",
1577
+ text: JSON.stringify(serializeDates(result), null, 2)
1578
+ }
1579
+ ]
1580
+ };
1581
+ }
1582
+ // ========== HELPER TOOLS ==========
1583
+ case "help": {
1584
+ const helpText = `
1585
+ # DocRouter API Help
1586
+
1587
+ This server provides access to DocRouter resources and tools.
1588
+
1589
+ ## Available Tools
1590
+
1591
+ ### Documents
1592
+ - \`upload_documents(documents)\` - Upload documents
1593
+ - \`list_documents(skip, limit, tagIds, nameSearch, metadataSearch)\` - List documents
1594
+ - \`get_document(documentId, fileType)\` - Get document by ID
1595
+ - \`update_document(documentId, documentName, tagIds, metadata)\` - Update document
1596
+ - \`delete_document(documentId)\` - Delete document
1597
+
1598
+ ### OCR
1599
+ - \`get_ocr_blocks(documentId)\` - Get OCR blocks
1600
+ - \`get_ocr_text(documentId, pageNum)\` - Get OCR text
1601
+ - \`get_ocr_metadata(documentId)\` - Get OCR metadata
1602
+
1603
+ ### LLM
1604
+ - \`run_llm(documentId, promptRevId, force)\` - Run AI extraction
1605
+ - \`get_llm_result(documentId, promptRevId, fallback)\` - Get extraction results
1606
+ - \`update_llm_result(documentId, promptId, result, isVerified)\` - Update results
1607
+ - \`delete_llm_result(documentId, promptId)\` - Delete results
1608
+
1609
+ ### Tags
1610
+ - \`create_tag(tag)\` - Create tag
1611
+ - \`get_tag(tagId)\` - Get tag by ID
1612
+ - \`list_tags(skip, limit, nameSearch)\` - List tags
1613
+ - \`update_tag(tagId, tag)\` - Update tag
1614
+ - \`delete_tag(tagId)\` - Delete tag
1615
+
1616
+ ### Forms
1617
+ - \`create_form(name, response_format)\` - Create form
1618
+ - \`list_forms(skip, limit, tag_ids)\` - List forms
1619
+ - \`get_form(formRevId)\` - Get form by ID
1620
+ - \`update_form(formId, form)\` - Update form
1621
+ - \`delete_form(formId)\` - Delete form
1622
+ - \`submit_form(documentId, formRevId, submission_data, submitted_by)\` - Submit form
1623
+ - \`get_form_submission(documentId, formRevId)\` - Get form submission
1624
+ - \`delete_form_submission(documentId, formRevId)\` - Delete form submission
1625
+
1626
+ ### Prompts
1627
+ - \`create_prompt(prompt)\` - Create prompt
1628
+ - \`list_prompts(skip, limit, document_id, tag_ids, nameSearch)\` - List prompts
1629
+ - \`get_prompt(promptRevId)\` - Get prompt by ID
1630
+ - \`update_prompt(promptId, prompt)\` - Update prompt
1631
+ - \`delete_prompt(promptId)\` - Delete prompt
1632
+
1633
+ ### Schemas
1634
+ - \`create_schema(name, response_format)\` - Create schema
1635
+ - \`list_schemas(skip, limit, nameSearch)\` - List schemas
1636
+ - \`get_schema(schemaRevId)\` - Get schema by ID
1637
+ - \`update_schema(schemaId, schema)\` - Update schema
1638
+ - \`delete_schema(schemaId)\` - Delete schema
1639
+ - \`validate_against_schema(schemaRevId, data)\` - Validate data
1640
+ - \`validate_schema(schema)\` - Validate schema format for correctness (takes JSON string)
1641
+
1642
+
1643
+ ### LLM Chat
1644
+ - \`run_llm_chat(messages, model, temperature, max_tokens, stream)\` - Run chat
1645
+
1646
+ ### Help Tools
1647
+ - \`help()\` - Get general API help information
1648
+ - \`help_prompts()\` - Get detailed help on creating and configuring prompts
1649
+ - \`help_schemas()\` - Get detailed help on creating and configuring schemas
1650
+
1651
+ ## Example Workflows
1652
+
1653
+ 1. List documents:
1654
+ \`\`\`
1655
+ list_documents()
1656
+ \`\`\`
1657
+
1658
+ 2. Get OCR text for a document:
1659
+ \`\`\`
1660
+ get_ocr_text("doc123")
1661
+ \`\`\`
1662
+
1663
+ 3. Run AI extraction:
1664
+ \`\`\`
1665
+ run_llm("doc123", "prompt456")
1666
+ \`\`\`
1667
+
1668
+ 4. Get extraction results:
1669
+ \`\`\`
1670
+ get_llm_result("doc123", "prompt456")
1671
+ \`\`\`
1672
+
1673
+ 5. Validate a schema format:
1674
+ \`\`\`
1675
+ validate_schema('{"type": "json_schema", "json_schema": {"name": "document_extraction", "schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Document name"}}, "required": ["name"], "additionalProperties": false}, "strict": true}}')
1676
+ \`\`\`
1677
+ `;
1678
+ return {
1679
+ content: [
1680
+ {
1681
+ type: "text",
1682
+ text: helpText
1683
+ }
1684
+ ]
1685
+ };
1686
+ }
1687
+ case "help_prompts": {
1688
+ try {
1689
+ const __filename = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
1690
+ const __dirname = path.dirname(__filename);
1691
+ const promptsPath = path.join(__dirname, "docs/knowledge_base/prompts.md");
1692
+ const promptsContent = fs.readFileSync(promptsPath, "utf-8");
1693
+ return {
1694
+ content: [
1695
+ {
1696
+ type: "text",
1697
+ text: promptsContent
1698
+ }
1699
+ ]
1700
+ };
1701
+ } catch (error) {
1702
+ return {
1703
+ content: [
1704
+ {
1705
+ type: "text",
1706
+ text: `Error reading prompts help file: ${handleError(error)}`
1707
+ }
1708
+ ],
1709
+ isError: true
1710
+ };
1711
+ }
1712
+ }
1713
+ case "help_schemas": {
1714
+ try {
1715
+ const __filename = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
1716
+ const __dirname = path.dirname(__filename);
1717
+ const schemasPath = path.join(__dirname, "docs/knowledge_base/schemas.md");
1718
+ const schemasContent = fs.readFileSync(schemasPath, "utf-8");
1719
+ return {
1720
+ content: [
1721
+ {
1722
+ type: "text",
1723
+ text: schemasContent
1724
+ }
1725
+ ]
1726
+ };
1727
+ } catch (error) {
1728
+ return {
1729
+ content: [
1730
+ {
1731
+ type: "text",
1732
+ text: `Error reading schemas help file: ${handleError(error)}`
1733
+ }
1734
+ ],
1735
+ isError: true
1736
+ };
1737
+ }
1738
+ }
1739
+ case "help_forms": {
1740
+ try {
1741
+ const __filename = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
1742
+ const __dirname = path.dirname(__filename);
1743
+ const formsPath = path.join(__dirname, "docs/knowledge_base/forms.md");
1744
+ const formsContent = fs.readFileSync(formsPath, "utf-8");
1745
+ return {
1746
+ content: [
1747
+ {
1748
+ type: "text",
1749
+ text: formsContent
1750
+ }
1751
+ ]
1752
+ };
1753
+ } catch (error) {
1754
+ return {
1755
+ content: [
1756
+ {
1757
+ type: "text",
1758
+ text: `Error reading forms help file: ${handleError(error)}`
1759
+ }
1760
+ ],
1761
+ isError: true
1762
+ };
1763
+ }
1764
+ }
1765
+ default:
1766
+ throw new Error(`Unknown tool: ${name}`);
1767
+ }
1768
+ } catch (error) {
1769
+ return {
1770
+ content: [
1771
+ {
1772
+ type: "text",
1773
+ text: handleError(error)
1774
+ }
1775
+ ],
1776
+ isError: true
1777
+ };
1778
+ }
1779
+ });
1780
+ async function main() {
1781
+ try {
1782
+ const config = parseConfig();
1783
+ if (!config.organizationId || !config.orgToken) {
1784
+ console.error("Error: DOCROUTER_ORG_ID and DOCROUTER_ORG_API_TOKEN environment variables are required");
1785
+ console.error("Or provide them as command line arguments: --org-id <id> --org-token <token>");
1786
+ process.exit(1);
1787
+ }
1788
+ initializeClient(config);
1789
+ const transport = new stdio_js.StdioServerTransport();
1790
+ await server.connect(transport);
1791
+ console.error("DocRouter MCP server started successfully");
1792
+ } catch (error) {
1793
+ console.error("Failed to start DocRouter MCP server:", error);
1794
+ process.exit(1);
1795
+ }
1796
+ }
1797
+ process.on("SIGINT", async () => {
1798
+ console.error("Shutting down DocRouter MCP server...");
1799
+ process.exit(0);
1800
+ });
1801
+ process.on("SIGTERM", async () => {
1802
+ console.error("Shutting down DocRouter MCP server...");
1803
+ process.exit(0);
1804
+ });
1805
+ if (__require.main === module) {
1806
+ main().catch((error) => {
1807
+ console.error("Unhandled error:", error);
1808
+ process.exit(1);
1809
+ });
1810
+ }
1811
+ //# sourceMappingURL=index.js.map
1812
+ //# sourceMappingURL=index.js.map