docsmith-mcp 0.0.1-beta.1 → 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts DELETED
@@ -1,496 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
- import {
6
- CallToolRequestSchema,
7
- ListToolsRequestSchema,
8
- } from "@modelcontextprotocol/sdk/types.js";
9
- import { z } from "zod";
10
- import { runPythonFile } from "./code-runner.js";
11
- import { detectFileType, getConfig, getPackages } from "./utils.js";
12
-
13
- // Tool schemas
14
- const ReadDocumentSchema = z.object({
15
- file_path: z.string().describe("Absolute path to the document file"),
16
- mode: z.enum(["raw", "paginated"]).optional().describe(
17
- "Read mode: 'raw' for full content, 'paginated' for chunked reading",
18
- ),
19
- page: z.number().optional().describe(
20
- "Page number for paginated mode (1-based)",
21
- ),
22
- page_size: z.number().optional().describe(
23
- "Items per page for paginated mode",
24
- ),
25
- sheet_name: z.string().optional().describe("Sheet name for Excel files"),
26
- });
27
-
28
- const WriteDocumentSchema = z.object({
29
- file_path: z.string().describe("Absolute path to save the document"),
30
- format: z.enum(["excel", "word", "text"]).describe("Document format"),
31
- data: z.any().describe("Document data structure"),
32
- });
33
-
34
- const GetDocumentInfoSchema = z.object({
35
- file_path: z.string().describe("Absolute path to the document file"),
36
- });
37
-
38
- // Server setup
39
- const server = new Server(
40
- {
41
- name: "docsmith-mcp",
42
- version: "0.1.0",
43
- },
44
- {
45
- capabilities: {
46
- tools: {},
47
- },
48
- },
49
- );
50
-
51
- // Output schemas (reusable)
52
- const BaseOutputSchema = {
53
- type: "object",
54
- properties: {
55
- success: { type: "boolean", description: "Operation success status" },
56
- error: { type: "string", description: "Error message if failed" },
57
- },
58
- } as const;
59
-
60
- const PaginationSchema = {
61
- current_page: { type: "number", description: "Current page number" },
62
- page_size: { type: "number", description: "Items per page" },
63
- total_pages: { type: "number", description: "Total number of pages" },
64
- page: { type: "number", description: "Current page number (alternative)" },
65
- has_more: { type: "boolean", description: "Whether more pages exist" },
66
- } as const;
67
-
68
- const ExcelReadOutputSchema = {
69
- type: "object",
70
- properties: {
71
- sheet_name: { type: "string", description: "Active sheet name" },
72
- sheets: {
73
- type: "array",
74
- items: { type: "string" },
75
- description: "All sheet names",
76
- },
77
- total_rows: { type: "number", description: "Total rows in sheet" },
78
- total_cols: { type: "number", description: "Total columns in sheet" },
79
- data: {
80
- type: "array",
81
- items: { type: "array", items: {} },
82
- description: "Sheet data as array of rows",
83
- },
84
- ...PaginationSchema,
85
- },
86
- } as const;
87
-
88
- const WordReadOutputSchema = {
89
- type: "object",
90
- properties: {
91
- paragraphs: {
92
- type: "array",
93
- items: { type: "string" },
94
- description: "Document paragraphs",
95
- },
96
- tables: {
97
- type: "array",
98
- items: {
99
- type: "array",
100
- items: { type: "array", items: { type: "string" } },
101
- },
102
- description: "Tables data",
103
- },
104
- total_paragraphs: { type: "number", description: "Total paragraph count" },
105
- total_tables: { type: "number", description: "Total table count" },
106
- ...PaginationSchema,
107
- },
108
- } as const;
109
-
110
- const PDFReadOutputSchema = {
111
- type: "object",
112
- properties: {
113
- total_pages: { type: "number", description: "Total pages in PDF" },
114
- content: {
115
- type: "array",
116
- items: {
117
- type: "object",
118
- properties: {
119
- page_number: { type: "number" },
120
- text: { type: "string" },
121
- },
122
- },
123
- description: "Page content array",
124
- },
125
- current_page_group: { type: "number" },
126
- page_size: { type: "number" },
127
- },
128
- } as const;
129
-
130
- const TextReadOutputSchema = {
131
- type: "object",
132
- properties: {
133
- ...BaseOutputSchema.properties,
134
- content: { type: "string", description: "Text content" },
135
- total_lines: { type: "number", description: "Total line count" },
136
- encoding: { type: "string", description: "File encoding" },
137
- ...PaginationSchema,
138
- },
139
- } as const;
140
-
141
- const CSVReadOutputSchema = {
142
- type: "object",
143
- properties: {
144
- ...BaseOutputSchema.properties,
145
- headers: {
146
- type: "array",
147
- items: { type: "string" },
148
- description: "CSV headers",
149
- },
150
- data: {
151
- type: "array",
152
- items: { type: "object" },
153
- description: "Structured data as array of objects",
154
- },
155
- total_rows: { type: "number", description: "Total data rows" },
156
- encoding: { type: "string", description: "File encoding" },
157
- ...PaginationSchema,
158
- },
159
- } as const;
160
-
161
- const JSONReadOutputSchema = {
162
- type: "object",
163
- properties: {
164
- ...BaseOutputSchema.properties,
165
- data: { type: "object", description: "Parsed JSON data" },
166
- encoding: { type: "string", description: "File encoding" },
167
- },
168
- } as const;
169
-
170
- const WriteOutputSchema = {
171
- type: "object",
172
- properties: {
173
- success: { type: "boolean", description: "Write operation success" },
174
- file_path: { type: "string", description: "Written file path" },
175
- message: { type: "string", description: "Success message" },
176
- error: { type: "string", description: "Error message if failed" },
177
- },
178
- } as const;
179
-
180
- const ExcelInfoOutputSchema = {
181
- type: "object",
182
- properties: {
183
- sheets: {
184
- type: "array",
185
- items: {
186
- type: "object",
187
- properties: {
188
- name: { type: "string" },
189
- rows: { type: "number" },
190
- cols: { type: "number" },
191
- },
192
- },
193
- description: "Sheet information",
194
- },
195
- file_size: { type: "number", description: "File size in bytes" },
196
- },
197
- } as const;
198
-
199
- const WordInfoOutputSchema = {
200
- type: "object",
201
- properties: {
202
- paragraphs: { type: "number", description: "Paragraph count" },
203
- tables: { type: "number", description: "Table count" },
204
- file_size: { type: "number", description: "File size in bytes" },
205
- },
206
- } as const;
207
-
208
- const PDFInfoOutputSchema = {
209
- type: "object",
210
- properties: {
211
- pages: { type: "number", description: "Page count" },
212
- file_size: { type: "number", description: "File size in bytes" },
213
- total_words: { type: "number", description: "Total word count" },
214
- },
215
- } as const;
216
-
217
- const TextInfoOutputSchema = {
218
- type: "object",
219
- properties: {
220
- ...BaseOutputSchema.properties,
221
- file_size: { type: "number", description: "File size in bytes" },
222
- line_count: { type: "number", description: "Line count" },
223
- encoding: { type: "string", description: "File encoding" },
224
- file_type: { type: "string", description: "File extension" },
225
- // CSV specific
226
- headers: { type: "array", items: { type: "string" } },
227
- total_rows: { type: "number" },
228
- total_cols: { type: "number" },
229
- // JSON specific
230
- item_count: { type: "number" },
231
- key_count: { type: "number" },
232
- },
233
- } as const;
234
-
235
- // List available tools
236
- server.setRequestHandler(ListToolsRequestSchema, async () => {
237
- return {
238
- tools: [
239
- {
240
- name: "read_document",
241
- description:
242
- "Read document content (Excel, Word, PDF, TXT, CSV, Markdown, JSON, YAML). Supports raw full read or paginated mode.",
243
- inputSchema: {
244
- type: "object",
245
- properties: {
246
- file_path: {
247
- type: "string",
248
- description: "Absolute path to the document file",
249
- },
250
- mode: {
251
- type: "string",
252
- enum: ["raw", "paginated"],
253
- description: "Read mode",
254
- },
255
- page: {
256
- type: "number",
257
- description: "Page number for paginated mode",
258
- },
259
- page_size: { type: "number", description: "Items per page" },
260
- sheet_name: {
261
- type: "string",
262
- description: "Sheet name for Excel files",
263
- },
264
- },
265
- required: ["file_path"],
266
- },
267
- outputSchema: {
268
- type: "object",
269
- description:
270
- "Returns different structures based on file type: Excel (sheet data), Word (paragraphs/tables), PDF (page content), Text (plain text), CSV (structured rows), JSON (parsed object)",
271
- oneOf: [
272
- ExcelReadOutputSchema,
273
- WordReadOutputSchema,
274
- PDFReadOutputSchema,
275
- TextReadOutputSchema,
276
- CSVReadOutputSchema,
277
- JSONReadOutputSchema,
278
- ],
279
- },
280
- },
281
- {
282
- name: "write_document",
283
- description: "Write document content (Excel, Word, Text)",
284
- inputSchema: {
285
- type: "object",
286
- properties: {
287
- file_path: {
288
- type: "string",
289
- description: "Absolute path to save the document",
290
- },
291
- format: {
292
- type: "string",
293
- enum: ["excel", "word", "text"],
294
- description: "Document format",
295
- },
296
- data: {
297
- description:
298
- "Document data structure. Excel: array of rows [[cell1, cell2], ...]. Word: {paragraphs: string[], tables?: [[[cell]]]}. Text/CSV/JSON: string or object",
299
- },
300
- },
301
- required: ["file_path", "format", "data"],
302
- },
303
- outputSchema: WriteOutputSchema,
304
- },
305
- {
306
- name: "get_document_info",
307
- description:
308
- "Get document metadata (page count, sheet count, file size, etc.)",
309
- inputSchema: {
310
- type: "object",
311
- properties: {
312
- file_path: {
313
- type: "string",
314
- description: "Absolute path to the document file",
315
- },
316
- },
317
- required: ["file_path"],
318
- },
319
- outputSchema: {
320
- type: "object",
321
- description: "Returns metadata based on file type",
322
- oneOf: [
323
- ExcelInfoOutputSchema,
324
- WordInfoOutputSchema,
325
- PDFInfoOutputSchema,
326
- TextInfoOutputSchema,
327
- ],
328
- },
329
- },
330
- ],
331
- };
332
- });
333
-
334
- // Handle tool calls
335
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
336
- const { name, arguments: args } = request.params;
337
-
338
- try {
339
- if (name === "read_document") {
340
- const params = ReadDocumentSchema.parse(args);
341
- const fileType = detectFileType(params.file_path);
342
-
343
- if (!fileType) {
344
- throw new Error(`Unsupported file type: ${params.file_path}`);
345
- }
346
-
347
- // Determine read mode
348
- const config = getConfig();
349
- const mode = params.mode || (config.rawFullRead ? "raw" : "paginated");
350
- const page = mode === "paginated" ? (params.page || 1) : undefined;
351
- const pageSize = params.page_size || config.pageSize;
352
-
353
- let scriptName: string;
354
- let scriptArgs: string[];
355
-
356
- if (fileType === "excel") {
357
- scriptName = "excel_handler.py";
358
- scriptArgs = ["read", params.file_path];
359
- if (params.sheet_name) scriptArgs.push(params.sheet_name);
360
- if (page) {
361
- scriptArgs.push(String(page));
362
- scriptArgs.push(String(pageSize));
363
- }
364
- } else if (fileType === "word") {
365
- scriptName = "word_handler.py";
366
- scriptArgs = ["read", params.file_path];
367
- if (page) {
368
- scriptArgs.push(String(page));
369
- scriptArgs.push(String(pageSize));
370
- }
371
- } else if (fileType === "pdf") {
372
- scriptName = "pdf_handler.py";
373
- scriptArgs = ["read", params.file_path];
374
- if (page) {
375
- scriptArgs.push(String(page));
376
- scriptArgs.push(String(Math.min(pageSize, 10))); // PDF pages are larger
377
- }
378
- } else {
379
- // text files
380
- scriptName = "text_handler.py";
381
- scriptArgs = ["read", params.file_path];
382
- if (page) {
383
- scriptArgs.push(String(page));
384
- scriptArgs.push(String(pageSize));
385
- }
386
- }
387
-
388
- const result = await runPythonFile(scriptName, {
389
- args: scriptArgs,
390
- packages: getPackages(fileType),
391
- filePaths: [params.file_path],
392
- });
393
- return {
394
- content: [{
395
- type: "text",
396
- text: JSON.stringify(result, null, 2),
397
- }],
398
- structuredContent: result,
399
- };
400
- }
401
-
402
- if (name === "write_document") {
403
- const params = WriteDocumentSchema.parse(args);
404
-
405
- let scriptName: string;
406
- let scriptArgs: string[];
407
-
408
- if (params.format === "excel") {
409
- scriptName = "excel_handler.py";
410
- scriptArgs = ["write", params.file_path, JSON.stringify(params.data)];
411
- } else if (params.format === "word") {
412
- scriptName = "word_handler.py";
413
- const paragraphs = params.data.paragraphs || [];
414
- const tables = params.data.tables || null;
415
- scriptArgs = ["write", params.file_path, JSON.stringify(paragraphs)];
416
- if (tables) scriptArgs.push(JSON.stringify(tables));
417
- } else if (params.format === "text") {
418
- scriptName = "text_handler.py";
419
- const content = typeof params.data === "string"
420
- ? params.data
421
- : JSON.stringify(params.data);
422
- scriptArgs = ["write", params.file_path, content];
423
- } else {
424
- throw new Error(`Unsupported write format: ${params.format}`);
425
- }
426
-
427
- const result = await runPythonFile(scriptName, {
428
- args: scriptArgs,
429
- packages: getPackages(params.format),
430
- filePaths: [params.file_path],
431
- });
432
- return {
433
- content: [{
434
- type: "text",
435
- text: JSON.stringify(result, null, 2),
436
- }],
437
- structuredContent: result,
438
- };
439
- }
440
-
441
- if (name === "get_document_info") {
442
- const params = GetDocumentInfoSchema.parse(args);
443
- const fileType = detectFileType(params.file_path);
444
-
445
- if (!fileType) {
446
- throw new Error(`Unsupported file type: ${params.file_path}`);
447
- }
448
-
449
- let scriptName: string;
450
- let scriptArgs = ["info", params.file_path];
451
-
452
- if (fileType === "excel") {
453
- scriptName = "excel_handler.py";
454
- } else if (fileType === "word") {
455
- scriptName = "word_handler.py";
456
- } else if (fileType === "pdf") {
457
- scriptName = "pdf_handler.py";
458
- } else {
459
- scriptName = "text_handler.py";
460
- }
461
-
462
- const result = await runPythonFile(scriptName, {
463
- args: scriptArgs,
464
- packages: getPackages(fileType),
465
- filePaths: [params.file_path],
466
- });
467
- return {
468
- content: [{
469
- type: "text",
470
- text: JSON.stringify(result, null, 2),
471
- }],
472
- structuredContent: result,
473
- };
474
- }
475
-
476
- throw new Error(`Unknown tool: ${name}`);
477
- } catch (error) {
478
- const errorMessage = error instanceof Error ? error.message : String(error);
479
- return {
480
- content: [{ type: "text", text: `Error: ${errorMessage}` }],
481
- isError: true,
482
- };
483
- }
484
- });
485
-
486
- // Start server
487
- async function main() {
488
- const transport = new StdioServerTransport();
489
- await server.connect(transport);
490
- console.error("Docsmith MCP server running on stdio");
491
- }
492
-
493
- main().catch((error) => {
494
- console.error("Server error:", error);
495
- process.exit(1);
496
- });
package/src/utils.ts DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * Utility functions for document processing
3
- */
4
-
5
- /**
6
- * Detect file type from file extension
7
- */
8
- export function detectFileType(
9
- filePath: string,
10
- ): "excel" | "word" | "pdf" | "text" | null {
11
- const ext = filePath.toLowerCase().split(".").pop();
12
- if (ext === "xlsx" || ext === "xls") return "excel";
13
- if (ext === "docx") return "word";
14
- if (ext === "pdf") return "pdf";
15
- if (
16
- ext === "txt" || ext === "csv" || ext === "md" || ext === "json" ||
17
- ext === "yaml" || ext === "yml"
18
- ) return "text";
19
- return null;
20
- }
21
-
22
- /**
23
- * Get required packages for each file type
24
- */
25
- export function getPackages(fileType: string): Record<string, string> {
26
- const packages: Record<string, Record<string, string>> = {
27
- excel: { openpyxl: "openpyxl" },
28
- word: { docx: "python-docx" }, // Map docx import to python-docx package
29
- pdf: { PyPDF2: "PyPDF2" },
30
- text: {}, // No external packages needed for text files
31
- };
32
- return packages[fileType] || {};
33
- }
34
-
35
- /**
36
- * Get environment configuration
37
- */
38
- export function getConfig() {
39
- return {
40
- rawFullRead: process.env.DOC_RAW_FULL_READ === "true",
41
- pageSize: parseInt(process.env.DOC_PAGE_SIZE || "100", 10),
42
- maxFileSize: parseInt(process.env.DOC_MAX_FILE_SIZE || "50", 10) * 1024 *
43
- 1024,
44
- };
45
- }