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