@docrouter/mcp 0.2.2 → 0.3.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 CHANGED
@@ -4,8 +4,8 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
4
4
  import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
5
5
  import { z } from 'zod';
6
6
  import { DocRouterAccount, DocRouterOrg } from '@docrouter/sdk';
7
- import { readFileSync, existsSync } from 'fs';
8
- import { dirname, join } from 'path';
7
+ import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync } from 'fs';
8
+ import { isAbsolute, resolve, extname, basename, join, dirname } from 'path';
9
9
  import { fileURLToPath } from 'url';
10
10
 
11
11
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -156,16 +156,19 @@ var server = new Server(
156
156
  }
157
157
  );
158
158
  var docrouterClient;
159
+ var docrouterAccountClient;
160
+ var orgToken;
159
161
  async function initializeClient(config) {
160
162
  try {
161
163
  console.error("Resolving organization ID from token...");
162
- const accountClient = new DocRouterAccount({
164
+ docrouterAccountClient = new DocRouterAccount({
163
165
  baseURL: config.baseURL,
164
166
  accountToken: config.orgToken,
165
167
  timeout: config.timeout,
166
168
  retries: config.retries
167
169
  });
168
- const tokenResponse = await accountClient.getOrganizationFromToken(config.orgToken);
170
+ orgToken = config.orgToken;
171
+ const tokenResponse = await docrouterAccountClient.getOrganizationFromToken(config.orgToken);
169
172
  const organizationId = tokenResponse.organization_id;
170
173
  if (!organizationId) {
171
174
  throw new Error("Token is an account-level token, not an organization-specific token. Please use an organization API token.");
@@ -562,7 +565,7 @@ var tools = [
562
565
  // ========== DOCUMENTS ==========
563
566
  {
564
567
  name: "upload_documents",
565
- description: "Upload documents to DocRouter",
568
+ description: "Upload documents to DocRouter from file paths",
566
569
  inputSchema: {
567
570
  type: "object",
568
571
  properties: {
@@ -572,12 +575,12 @@ var tools = [
572
575
  items: {
573
576
  type: "object",
574
577
  properties: {
575
- name: { type: "string", description: "Document name" },
576
- content: { type: "string", description: "Base64 encoded document content (supports both plain base64 and data URLs)" },
578
+ file_path: { type: "string", description: "Path to the document file on disk" },
579
+ name: { type: "string", description: "Document name (optional, defaults to filename)" },
577
580
  tag_ids: { type: "array", items: { type: "string" }, description: "Optional list of tag IDs" },
578
581
  metadata: { type: "object", description: "Optional metadata" }
579
582
  },
580
- required: ["name", "content"]
583
+ required: ["file_path"]
581
584
  }
582
585
  }
583
586
  },
@@ -600,12 +603,13 @@ var tools = [
600
603
  },
601
604
  {
602
605
  name: "get_document",
603
- description: "Get document by ID from DocRouter",
606
+ description: "Get document metadata (state, tags, metadata) and optionally download the file to disk",
604
607
  inputSchema: {
605
608
  type: "object",
606
609
  properties: {
607
610
  documentId: { type: "string", description: "ID of the document to retrieve" },
608
- fileType: { type: "string", description: "File type to retrieve (pdf, image, etc.)", default: "pdf" }
611
+ fileType: { type: "string", description: "File type to retrieve (original or pdf)", default: "original" },
612
+ save_path: { type: "string", description: "Optional file path or directory to save the document. If directory, uses original filename. If not provided, file is not downloaded." }
609
613
  },
610
614
  required: ["documentId"]
611
615
  }
@@ -942,9 +946,12 @@ var tools = [
942
946
  type: "object",
943
947
  properties: {
944
948
  promptId: { type: "string", description: "ID of the prompt" },
945
- content: { type: "string", description: "Prompt content" }
949
+ content: { type: "string", description: "Prompt content" },
950
+ model: { type: "string", description: "LLM model to use" },
951
+ schema_id: { type: "string", description: "Schema ID to link" },
952
+ tag_ids: { type: "array", items: { type: "string" }, description: "Tag IDs that trigger this prompt" }
946
953
  },
947
- required: ["promptId", "content"]
954
+ required: ["promptId"]
948
955
  }
949
956
  },
950
957
  {
@@ -1078,6 +1085,22 @@ var tools = [
1078
1085
  required: ["messages", "model"]
1079
1086
  }
1080
1087
  },
1088
+ {
1089
+ name: "get_organization",
1090
+ description: "Get information about the current organization (name, type, ID)",
1091
+ inputSchema: {
1092
+ type: "object",
1093
+ properties: {}
1094
+ }
1095
+ },
1096
+ {
1097
+ name: "list_llm_models",
1098
+ description: "List enabled LLM models available for use in prompts for this organization",
1099
+ inputSchema: {
1100
+ type: "object",
1101
+ properties: {}
1102
+ }
1103
+ },
1081
1104
  // ========== HELPER TOOLS ==========
1082
1105
  {
1083
1106
  name: "help",
@@ -1139,21 +1162,57 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1139
1162
  };
1140
1163
  }
1141
1164
  case "get_document": {
1142
- const result = await docrouterClient.getDocument({
1143
- documentId: getArg(args, "documentId"),
1144
- fileType: getArg(args, "fileType", "pdf")
1165
+ const documentId = getArg(args, "documentId");
1166
+ const fileType = getArg(args, "fileType", "original");
1167
+ const savePath = getOptionalArg(args, "save_path");
1168
+ const fileResult = await docrouterClient.getDocument({
1169
+ documentId,
1170
+ fileType
1145
1171
  });
1146
- const base64Content = Buffer.from(result.content).toString("base64");
1172
+ const response = {
1173
+ id: fileResult.id,
1174
+ pdf_id: fileResult.pdf_id,
1175
+ document_name: fileResult.document_name,
1176
+ upload_date: fileResult.upload_date,
1177
+ uploaded_by: fileResult.uploaded_by,
1178
+ state: fileResult.state,
1179
+ tag_ids: fileResult.tag_ids,
1180
+ type: fileResult.type,
1181
+ metadata: fileResult.metadata
1182
+ };
1183
+ if (savePath) {
1184
+ let finalPath;
1185
+ if (isAbsolute(savePath)) {
1186
+ finalPath = savePath;
1187
+ } else {
1188
+ finalPath = resolve(process.cwd(), savePath);
1189
+ }
1190
+ let isDirectory = false;
1191
+ try {
1192
+ const stats = statSync(finalPath);
1193
+ isDirectory = stats.isDirectory();
1194
+ } catch {
1195
+ isDirectory = savePath.endsWith("/") || savePath.endsWith("\\");
1196
+ }
1197
+ if (isDirectory) {
1198
+ const extension = fileType === "pdf" ? ".pdf" : extname(fileResult.document_name) || ".pdf";
1199
+ const fileName = basename(fileResult.document_name, extname(fileResult.document_name)) + extension;
1200
+ finalPath = join(finalPath, fileName);
1201
+ }
1202
+ const targetDir = dirname(finalPath);
1203
+ if (!existsSync(targetDir)) {
1204
+ mkdirSync(targetDir, { recursive: true });
1205
+ }
1206
+ const fileBuffer = Buffer.from(fileResult.content);
1207
+ writeFileSync(finalPath, fileBuffer);
1208
+ response.saved_path = finalPath;
1209
+ response.file_size = fileBuffer.length;
1210
+ }
1147
1211
  return {
1148
1212
  content: [
1149
1213
  {
1150
1214
  type: "text",
1151
- text: JSON.stringify({
1152
- ...serializeDates(result),
1153
- content: base64Content,
1154
- content_type: "base64",
1155
- content_size: result.content.byteLength
1156
- }, null, 2)
1215
+ text: JSON.stringify(response, null, 2)
1157
1216
  }
1158
1217
  ]
1159
1218
  };
@@ -1276,7 +1335,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1276
1335
  // ========== DOCUMENTS ==========
1277
1336
  case "upload_documents": {
1278
1337
  const documentsInput = getArg(args, "documents");
1279
- const result = await docrouterClient.uploadDocuments({ documents: documentsInput });
1338
+ const documents = [];
1339
+ for (const doc of documentsInput) {
1340
+ let filePath;
1341
+ if (isAbsolute(doc.file_path)) {
1342
+ filePath = doc.file_path;
1343
+ } else {
1344
+ filePath = resolve(process.cwd(), doc.file_path);
1345
+ }
1346
+ if (!existsSync(filePath)) {
1347
+ throw new Error(`File not found: ${filePath}`);
1348
+ }
1349
+ const fileBuffer = readFileSync(filePath);
1350
+ const base64Content = fileBuffer.toString("base64");
1351
+ const fileName = doc.name || filePath.split(/[/\\]/).pop() || "document";
1352
+ documents.push({
1353
+ name: fileName,
1354
+ content: base64Content,
1355
+ tag_ids: doc.tag_ids,
1356
+ metadata: doc.metadata
1357
+ });
1358
+ }
1359
+ const result = await docrouterClient.uploadDocuments({ documents });
1280
1360
  return {
1281
1361
  content: [
1282
1362
  {
@@ -1531,7 +1611,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1531
1611
  }
1532
1612
  case "update_prompt": {
1533
1613
  const promptId = getArg(args, "promptId");
1534
- const content = getArg(args, "content");
1614
+ const content = getOptionalArg(args, "content");
1615
+ const model = getOptionalArg(args, "model");
1616
+ const schema_id = getOptionalArg(args, "schema_id");
1617
+ const tag_ids = getOptionalArg(args, "tag_ids");
1535
1618
  let currentPrompt = null;
1536
1619
  const allPrompts = await docrouterClient.listPrompts({});
1537
1620
  for (const p of allPrompts.prompts) {
@@ -1547,11 +1630,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1547
1630
  promptId,
1548
1631
  prompt: {
1549
1632
  name: currentPrompt.name,
1550
- content,
1551
- schema_id: currentPrompt.schema_id,
1633
+ content: content ?? currentPrompt.content,
1634
+ schema_id: schema_id ?? currentPrompt.schema_id,
1552
1635
  schema_version: currentPrompt.schema_version,
1553
- tag_ids: currentPrompt.tag_ids,
1554
- model: currentPrompt.model
1636
+ tag_ids: tag_ids ?? currentPrompt.tag_ids,
1637
+ model: model ?? currentPrompt.model
1555
1638
  }
1556
1639
  });
1557
1640
  return {
@@ -1736,6 +1819,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1736
1819
  ]
1737
1820
  };
1738
1821
  }
1822
+ case "get_organization": {
1823
+ const result = await docrouterAccountClient.getOrganizationFromToken(orgToken);
1824
+ return {
1825
+ content: [
1826
+ {
1827
+ type: "text",
1828
+ text: JSON.stringify(serializeDates(result), null, 2)
1829
+ }
1830
+ ]
1831
+ };
1832
+ }
1833
+ case "list_llm_models": {
1834
+ const result = await docrouterClient.listLLMModels();
1835
+ return {
1836
+ content: [
1837
+ {
1838
+ type: "text",
1839
+ text: JSON.stringify(serializeDates(result), null, 2)
1840
+ }
1841
+ ]
1842
+ };
1843
+ }
1739
1844
  // ========== HELPER TOOLS ==========
1740
1845
  case "help": {
1741
1846
  const helpText = `
@@ -1746,7 +1851,7 @@ This server provides access to DocRouter resources and tools.
1746
1851
  ## Available Tools
1747
1852
 
1748
1853
  ### Documents
1749
- - \`upload_documents(documents)\` - Upload documents
1854
+ - \`upload_documents(documents)\` - Upload documents from file paths
1750
1855
  - \`list_documents(skip, limit, tagIds, nameSearch, metadataSearch)\` - List documents
1751
1856
  - \`get_document(documentId, fileType)\` - Get document by ID
1752
1857
  - \`update_document(documentId, documentName, tagIds, metadata)\` - Update document
@@ -1800,6 +1905,10 @@ This server provides access to DocRouter resources and tools.
1800
1905
  ### LLM Chat
1801
1906
  - \`run_llm_chat(messages, model, temperature, max_tokens, stream)\` - Run chat
1802
1907
 
1908
+ ### Organization
1909
+ - \`get_organization()\` - Get information about the current organization (name, type, ID)
1910
+ - \`list_llm_models()\` - List enabled LLM models available for use in prompts
1911
+
1803
1912
  ### Help Tools
1804
1913
  - \`help()\` - Get general API help information
1805
1914
  - \`help_prompts()\` - Get detailed help on creating and configuring prompts