@documonster/mcp 0.8.0-canary.sha.09791dab
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/LICENSE +205 -0
- package/README.md +253 -0
- package/dist/capabilities.d.ts +29 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +188 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +64 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +189 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +66 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox.d.ts +86 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +224 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/archive-read.d.ts +31 -0
- package/dist/tools/archive-read.d.ts.map +1 -0
- package/dist/tools/archive-read.js +315 -0
- package/dist/tools/archive-read.js.map +1 -0
- package/dist/tools/archive-write.d.ts +9 -0
- package/dist/tools/archive-write.d.ts.map +1 -0
- package/dist/tools/archive-write.js +219 -0
- package/dist/tools/archive-write.js.map +1 -0
- package/dist/tools/chart.d.ts +93 -0
- package/dist/tools/chart.d.ts.map +1 -0
- package/dist/tools/chart.js +263 -0
- package/dist/tools/chart.js.map +1 -0
- package/dist/tools/doc-convert.d.ts +13 -0
- package/dist/tools/doc-convert.d.ts.map +1 -0
- package/dist/tools/doc-convert.js +209 -0
- package/dist/tools/doc-convert.js.map +1 -0
- package/dist/tools/doc-paginate.d.ts +14 -0
- package/dist/tools/doc-paginate.d.ts.map +1 -0
- package/dist/tools/doc-paginate.js +153 -0
- package/dist/tools/doc-paginate.js.map +1 -0
- package/dist/tools/doc-read.d.ts +14 -0
- package/dist/tools/doc-read.d.ts.map +1 -0
- package/dist/tools/doc-read.js +175 -0
- package/dist/tools/doc-read.js.map +1 -0
- package/dist/tools/doc-review.d.ts +17 -0
- package/dist/tools/doc-review.d.ts.map +1 -0
- package/dist/tools/doc-review.js +249 -0
- package/dist/tools/doc-review.js.map +1 -0
- package/dist/tools/doc-search.d.ts +20 -0
- package/dist/tools/doc-search.d.ts.map +1 -0
- package/dist/tools/doc-search.js +268 -0
- package/dist/tools/doc-search.js.map +1 -0
- package/dist/tools/doc-write.d.ts +11 -0
- package/dist/tools/doc-write.d.ts.map +1 -0
- package/dist/tools/doc-write.js +81 -0
- package/dist/tools/doc-write.js.map +1 -0
- package/dist/tools/document.d.ts +74 -0
- package/dist/tools/document.d.ts.map +1 -0
- package/dist/tools/document.js +157 -0
- package/dist/tools/document.js.map +1 -0
- package/dist/tools/form-fill.d.ts +20 -0
- package/dist/tools/form-fill.d.ts.map +1 -0
- package/dist/tools/form-fill.js +270 -0
- package/dist/tools/form-fill.js.map +1 -0
- package/dist/tools/formula-evaluate.d.ts +14 -0
- package/dist/tools/formula-evaluate.d.ts.map +1 -0
- package/dist/tools/formula-evaluate.js +192 -0
- package/dist/tools/formula-evaluate.js.map +1 -0
- package/dist/tools/fs-helpers.d.ts +106 -0
- package/dist/tools/fs-helpers.d.ts.map +1 -0
- package/dist/tools/fs-helpers.js +257 -0
- package/dist/tools/fs-helpers.js.map +1 -0
- package/dist/tools/help.d.ts +227 -0
- package/dist/tools/help.d.ts.map +1 -0
- package/dist/tools/help.js +262 -0
- package/dist/tools/help.js.map +1 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +78 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inspect.d.ts +14 -0
- package/dist/tools/inspect.d.ts.map +1 -0
- package/dist/tools/inspect.js +463 -0
- package/dist/tools/inspect.js.map +1 -0
- package/dist/tools/pdf-edit.d.ts +26 -0
- package/dist/tools/pdf-edit.d.ts.map +1 -0
- package/dist/tools/pdf-edit.js +390 -0
- package/dist/tools/pdf-edit.js.map +1 -0
- package/dist/tools/result.d.ts +25 -0
- package/dist/tools/result.d.ts.map +1 -0
- package/dist/tools/result.js +43 -0
- package/dist/tools/result.js.map +1 -0
- package/dist/tools/sheet-edit.d.ts +16 -0
- package/dist/tools/sheet-edit.d.ts.map +1 -0
- package/dist/tools/sheet-edit.js +325 -0
- package/dist/tools/sheet-edit.js.map +1 -0
- package/dist/tools/sheet-read.d.ts +10 -0
- package/dist/tools/sheet-read.d.ts.map +1 -0
- package/dist/tools/sheet-read.js +139 -0
- package/dist/tools/sheet-read.js.map +1 -0
- package/dist/tools/sheet-write.d.ts +15 -0
- package/dist/tools/sheet-write.d.ts.map +1 -0
- package/dist/tools/sheet-write.js +290 -0
- package/dist/tools/sheet-write.js.map +1 -0
- package/dist/tools/spreadsheet.d.ts +100 -0
- package/dist/tools/spreadsheet.d.ts.map +1 -0
- package/dist/tools/spreadsheet.js +210 -0
- package/dist/tools/spreadsheet.js.map +1 -0
- package/dist/tools/template.d.ts +18 -0
- package/dist/tools/template.d.ts.map +1 -0
- package/dist/tools/template.js +209 -0
- package/dist/tools/template.js.map +1 -0
- package/dist/tools/types.d.ts +79 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +18 -0
- package/dist/tools/types.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources and prompts.
|
|
3
|
+
*
|
|
4
|
+
* Both exist to move cost out of the model's context.
|
|
5
|
+
*
|
|
6
|
+
* **Resources** publish the help topics at stable URIs, so a client can show
|
|
7
|
+
* them and a model can read one without spending a tool call. The same content
|
|
8
|
+
* is still reachable through `documonster_help`, because not every client
|
|
9
|
+
* supports resources.
|
|
10
|
+
*
|
|
11
|
+
* **Prompts** are workflow templates the *user* invokes. They matter because the
|
|
12
|
+
* hardest part of using this server well is knowing the order to do things in —
|
|
13
|
+
* inspect, then read narrowly, then write, then verify. A prompt encodes that
|
|
14
|
+
* sequence once instead of relying on the user to describe it.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { HELP_TOPICS } from "./tools/help.js";
|
|
18
|
+
/** URI scheme for help topics. */
|
|
19
|
+
const HELP_URI_PREFIX = "documonster://help/";
|
|
20
|
+
/** Register one resource per help topic. */
|
|
21
|
+
export function registerResources(server) {
|
|
22
|
+
for (const [name, topic] of Object.entries(HELP_TOPICS)) {
|
|
23
|
+
server.registerResource(`help-${name}`, `${HELP_URI_PREFIX}${name}`, {
|
|
24
|
+
title: `documonster: ${name}`,
|
|
25
|
+
description: topic.summary,
|
|
26
|
+
mimeType: "text/markdown"
|
|
27
|
+
}, uri => ({
|
|
28
|
+
contents: [{ uri: uri.href, mimeType: "text/markdown", text: topic.body }]
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Register workflow prompts.
|
|
34
|
+
*
|
|
35
|
+
* Each returns a single user message that states the goal *and* the discipline —
|
|
36
|
+
* inspect first, keep data server-side, verify by reading back. Those three
|
|
37
|
+
* habits are what separate a cheap correct run from an expensive wrong one, and
|
|
38
|
+
* a prompt is the only place to establish them before the model starts.
|
|
39
|
+
*/
|
|
40
|
+
export function registerPrompts(server, config) {
|
|
41
|
+
const has = (group) => config.groups.has(group);
|
|
42
|
+
if (has("excel")) {
|
|
43
|
+
server.registerPrompt("summarise-spreadsheet", {
|
|
44
|
+
title: "Summarise a spreadsheet",
|
|
45
|
+
description: "Inspect a workbook and answer a question about it without reading it all.",
|
|
46
|
+
argsSchema: {
|
|
47
|
+
path: z.string().describe("Workbook path, relative to the server root."),
|
|
48
|
+
question: z.string().describe("What you want to know about it.")
|
|
49
|
+
}
|
|
50
|
+
}, ({ path, question }) => ({
|
|
51
|
+
messages: [
|
|
52
|
+
{
|
|
53
|
+
role: "user",
|
|
54
|
+
content: {
|
|
55
|
+
type: "text",
|
|
56
|
+
text: `Answer this question about ${path}: ${question}
|
|
57
|
+
|
|
58
|
+
Work in this order:
|
|
59
|
+
1. Call doc_inspect on ${path} to learn its sheets and their sizes.
|
|
60
|
+
2. Read only the range you need. If a summary sheet already holds the answer, use it rather than re-deriving it from the detail sheets.
|
|
61
|
+
3. If the answer requires a calculation, verify your arithmetic with formula_evaluate before stating it.
|
|
62
|
+
4. Quote the cell addresses your answer comes from.
|
|
63
|
+
|
|
64
|
+
Do not read a whole large sheet. If a read reports omitted rows, narrow the range instead of paging through everything.`
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
if (has("excel") && !config.readonly) {
|
|
71
|
+
server.registerPrompt("build-report", {
|
|
72
|
+
title: "Build a report from data files",
|
|
73
|
+
description: "Turn one or more CSV/Excel files into a formatted workbook.",
|
|
74
|
+
argsSchema: {
|
|
75
|
+
sources: z
|
|
76
|
+
.string()
|
|
77
|
+
.describe("The data files or archive to use, as a comma-separated list."),
|
|
78
|
+
out: z.string().describe("Output .xlsx path."),
|
|
79
|
+
goal: z.string().describe("What the report should show.")
|
|
80
|
+
}
|
|
81
|
+
}, ({ sources, out, goal }) => ({
|
|
82
|
+
messages: [
|
|
83
|
+
{
|
|
84
|
+
role: "user",
|
|
85
|
+
content: {
|
|
86
|
+
type: "text",
|
|
87
|
+
text: `Build ${out} from ${sources}. It should show: ${goal}
|
|
88
|
+
|
|
89
|
+
Work in this order:
|
|
90
|
+
1. If a source is an archive, list it with archive_read and extract only what you need.
|
|
91
|
+
2. doc_inspect each data file — CSV delimiters and encodings vary, and guessing wrong silently produces one column.
|
|
92
|
+
3. Build the workbook with a single sheet_write call. Use \`fromCsv\` to load source data server-side; do not copy rows into your reply.
|
|
93
|
+
4. Add formulas rather than pre-computed numbers, so the workbook stays live.
|
|
94
|
+
5. The write result returns an @output/... path. Read that path back with sheet_read and confirm the computed values before telling me it is done.`
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
if (has("forms") && !config.readonly) {
|
|
101
|
+
server.registerPrompt("fill-document", {
|
|
102
|
+
title: "Fill a template or form",
|
|
103
|
+
description: "Populate a Word template or a fillable form, then deliver a PDF.",
|
|
104
|
+
argsSchema: {
|
|
105
|
+
path: z.string().describe("Template or form path."),
|
|
106
|
+
data: z.string().describe("The values to put in it, in any readable form."),
|
|
107
|
+
pdf: z.string().optional().describe("Optional PDF output path.")
|
|
108
|
+
}
|
|
109
|
+
}, ({ path, data, pdf }) => ({
|
|
110
|
+
messages: [
|
|
111
|
+
{
|
|
112
|
+
role: "user",
|
|
113
|
+
content: {
|
|
114
|
+
type: "text",
|
|
115
|
+
text: `Fill ${path} with this data:
|
|
116
|
+
|
|
117
|
+
${data}
|
|
118
|
+
|
|
119
|
+
Work in this order:
|
|
120
|
+
1. doc_inspect ${path} — it will tell you whether this is a {{placeholder}} template or a form with fields, and name the tool to use.
|
|
121
|
+
2. List the placeholders (template_inspect) or the fields (form_fill with no values) before filling anything. Do not guess field names.
|
|
122
|
+
3. Fill it. If a required value is missing, stop and ask me — never invent an identifier, reference number, date or amount.
|
|
123
|
+
4. The fill result returns an @output/... path. Read it back and confirm no placeholder text survived.${pdf === undefined
|
|
124
|
+
? ""
|
|
125
|
+
: `\n5. Convert that @output path to ${pdf} with doc_convert.`}`
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
if (has("word")) {
|
|
132
|
+
server.registerPrompt("review-changes", {
|
|
133
|
+
title: "Review document changes",
|
|
134
|
+
description: "Compare two versions of a document, or review its tracked changes.",
|
|
135
|
+
argsSchema: {
|
|
136
|
+
a: z.string().describe("The document, or the earlier version."),
|
|
137
|
+
b: z.string().optional().describe("The later version, if comparing two files.")
|
|
138
|
+
}
|
|
139
|
+
}, ({ a, b }) => ({
|
|
140
|
+
messages: [
|
|
141
|
+
{
|
|
142
|
+
role: "user",
|
|
143
|
+
content: {
|
|
144
|
+
type: "text",
|
|
145
|
+
text: b === undefined
|
|
146
|
+
? `Review the tracked changes in ${a}.
|
|
147
|
+
|
|
148
|
+
1. Call doc_review on it to list every revision with its author.
|
|
149
|
+
2. Summarise what changed, grouped by intent rather than by paragraph order.
|
|
150
|
+
3. Flag anything that changes an obligation, amount, date or party name — those need a human decision.
|
|
151
|
+
4. Do not accept or reject anything unless I ask.`
|
|
152
|
+
: `Compare ${a} with ${b} and tell me what changed.
|
|
153
|
+
|
|
154
|
+
1. Call doc_review with both paths.
|
|
155
|
+
2. Summarise the differences by significance, not in document order.
|
|
156
|
+
3. Flag any change to an amount, date, party name or obligation.
|
|
157
|
+
4. If a paragraph was reworded without changing meaning, say so rather than quoting both versions in full.`
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
if ((has("word") || has("pdf") || has("excel")) && !config.readonly) {
|
|
164
|
+
server.registerPrompt("convert-document", {
|
|
165
|
+
title: "Convert a document",
|
|
166
|
+
description: "Convert a file to another format, with its limitations stated.",
|
|
167
|
+
argsSchema: {
|
|
168
|
+
from: z.string().describe("Source path."),
|
|
169
|
+
to: z.string().describe("Destination path; its extension picks the format.")
|
|
170
|
+
}
|
|
171
|
+
}, ({ from, to }) => ({
|
|
172
|
+
messages: [
|
|
173
|
+
{
|
|
174
|
+
role: "user",
|
|
175
|
+
content: {
|
|
176
|
+
type: "text",
|
|
177
|
+
text: `Convert ${from} to ${to}.
|
|
178
|
+
|
|
179
|
+
1. doc_inspect the source first — an extension can lie, and the real format decides whether the conversion is possible at all.
|
|
180
|
+
2. Use doc_convert. If that pair is not supported it will tell you what is; report that rather than trying alternatives at random.
|
|
181
|
+
3. Tell me plainly what the conversion loses, if anything.`
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `documonster-mcp` executable — stdio transport.
|
|
4
|
+
*
|
|
5
|
+
* stdio is the only transport for now because it covers every local AI client
|
|
6
|
+
* and needs no session management or auth. A remote (Streamable HTTP) entry
|
|
7
|
+
* point would live beside this file, sharing `createServer`.
|
|
8
|
+
*
|
|
9
|
+
* Nothing here may write to stdout: stdout IS the protocol channel. All
|
|
10
|
+
* diagnostics go to stderr.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `documonster-mcp` executable — stdio transport.
|
|
4
|
+
*
|
|
5
|
+
* stdio is the only transport for now because it covers every local AI client
|
|
6
|
+
* and needs no session management or auth. A remote (Streamable HTTP) entry
|
|
7
|
+
* point would live beside this file, sharing `createServer`.
|
|
8
|
+
*
|
|
9
|
+
* Nothing here may write to stdout: stdout IS the protocol channel. All
|
|
10
|
+
* diagnostics go to stderr.
|
|
11
|
+
*/
|
|
12
|
+
import { readFile } from "node:fs/promises";
|
|
13
|
+
import process from "node:process";
|
|
14
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
|
+
import { ConfigError, readMetaFlags, resolveConfig, usage } from "./config.js";
|
|
16
|
+
import { createServer } from "./server.js";
|
|
17
|
+
async function main() {
|
|
18
|
+
const argv = process.argv.slice(2);
|
|
19
|
+
const meta = readMetaFlags(argv);
|
|
20
|
+
if (meta.help) {
|
|
21
|
+
process.stdout.write(usage());
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const version = await readVersion();
|
|
25
|
+
if (meta.version) {
|
|
26
|
+
process.stdout.write(`${version}\n`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const config = resolveConfig(argv);
|
|
30
|
+
const server = createServer(config, { name: "documonster", version });
|
|
31
|
+
await server.connect(new StdioServerTransport());
|
|
32
|
+
// Report the effective sandbox on stderr so an operator can see, in the
|
|
33
|
+
// client's log, exactly what this process was allowed to touch.
|
|
34
|
+
process.stderr.write(`documonster-mcp ${version} ready — root=${config.root} output=${config.outputRoot} readonly=${config.readonly} inPlace=${config.allowInPlace} groups=${[...config.groups].join(",")}\n`);
|
|
35
|
+
}
|
|
36
|
+
/** Read the version from the package manifest, which sits beside `dist/` and `src/`. */
|
|
37
|
+
async function readVersion() {
|
|
38
|
+
try {
|
|
39
|
+
const manifestUrl = new URL("../package.json", import.meta.url);
|
|
40
|
+
const parsed = JSON.parse(await readFile(manifestUrl, "utf8"));
|
|
41
|
+
if (typeof parsed === "object" && parsed !== null && "version" in parsed) {
|
|
42
|
+
const { version } = parsed;
|
|
43
|
+
if (typeof version === "string") {
|
|
44
|
+
return version;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// A missing or malformed manifest must not stop the server from starting.
|
|
50
|
+
}
|
|
51
|
+
return "0.0.0";
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await main();
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof ConfigError) {
|
|
58
|
+
process.stderr.write(`documonster-mcp: ${error.message}\n\n${usage()}`);
|
|
59
|
+
process.exit(2);
|
|
60
|
+
}
|
|
61
|
+
process.stderr.write(`documonster-mcp: fatal: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server configuration: the command-line contract of `documonster-mcp`.
|
|
3
|
+
*
|
|
4
|
+
* Everything that constrains what the server is allowed to do lives here and
|
|
5
|
+
* is decided ONCE at startup, never per tool call. The model can therefore
|
|
6
|
+
* never widen its own permissions: `--root` and `--readonly` are invisible to it.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Tool groups, used by `--enable` to keep the number of tools exposed to a
|
|
10
|
+
* model small. Every additional tool measurably increases the chance the model
|
|
11
|
+
* picks the wrong one, so a caller who only ever touches spreadsheets should
|
|
12
|
+
* not have to pay for the Word and PDF tool descriptions in its context.
|
|
13
|
+
*
|
|
14
|
+
* `core` (`documonster_help`, `doc_inspect`) is always enabled — it is how a
|
|
15
|
+
* model orients itself before doing anything else.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TOOL_GROUPS: readonly ["core", "excel", "word", "pdf", "forms", "archive"];
|
|
18
|
+
export type ToolGroup = (typeof TOOL_GROUPS)[number];
|
|
19
|
+
export interface ServerConfig {
|
|
20
|
+
/**
|
|
21
|
+
* Absolute, symlink-resolved sandbox root. Every path a tool touches must
|
|
22
|
+
* resolve inside it (see `sandbox.ts`).
|
|
23
|
+
*/
|
|
24
|
+
readonly root: string;
|
|
25
|
+
/**
|
|
26
|
+
* Private, disjoint writable root. Plain write paths resolve here; tools and
|
|
27
|
+
* prompts expose them as `@output/...` so later calls can read the result
|
|
28
|
+
* without ever granting writes to the input root.
|
|
29
|
+
*/
|
|
30
|
+
readonly outputRoot: string;
|
|
31
|
+
/** Explicit compatibility escape hatch for modifying source files in place. */
|
|
32
|
+
readonly allowInPlace: boolean;
|
|
33
|
+
/** When true, every mutating tool is withheld from `tools/list` entirely. */
|
|
34
|
+
readonly readonly: boolean;
|
|
35
|
+
/** Enabled tool groups; always contains `core`. */
|
|
36
|
+
readonly groups: ReadonlySet<ToolGroup>;
|
|
37
|
+
/** Reject input documents larger than this many bytes. */
|
|
38
|
+
readonly maxFileSize: number;
|
|
39
|
+
/** Truncate tool output beyond this many characters. */
|
|
40
|
+
readonly maxOutputChars: number;
|
|
41
|
+
}
|
|
42
|
+
export declare class ConfigError extends Error {
|
|
43
|
+
readonly name = "ConfigError";
|
|
44
|
+
}
|
|
45
|
+
export interface ResolveConfigOptions {
|
|
46
|
+
/** Overrides `process.cwd()`; used by tests. */
|
|
47
|
+
readonly cwd?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a {@link ServerConfig} from CLI-style arguments.
|
|
51
|
+
*
|
|
52
|
+
* @param argv - Arguments *after* `node script.js`, i.e. `process.argv.slice(2)`.
|
|
53
|
+
* @throws {ConfigError} On an unknown flag, a missing value, or a `--root`
|
|
54
|
+
* that does not exist. Failing loudly at startup is deliberate: a silently
|
|
55
|
+
* defaulted root would sandbox the model somewhere the operator never chose.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveConfig(argv: readonly string[], options?: ResolveConfigOptions): ServerConfig;
|
|
58
|
+
/** True when `--help` or `--version` was passed; the CLI short-circuits on these. */
|
|
59
|
+
export declare function readMetaFlags(argv: readonly string[]): {
|
|
60
|
+
help: boolean;
|
|
61
|
+
version: boolean;
|
|
62
|
+
};
|
|
63
|
+
/** Usage text for `--help`. */
|
|
64
|
+
export declare function usage(): string;
|
|
65
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAEzF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAerD,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACxC,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,qBAAa,WAAY,SAAQ,KAAK;IACpC,SAAkB,IAAI,iBAAiB;CACxC;AAED,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,oBAAyB,GACjC,YAAY,CAuEd;AAUD,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAK1F;AA2CD,+BAA+B;AAC/B,wBAAgB,KAAK,IAAI,MAAM,CAkC9B"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server configuration: the command-line contract of `documonster-mcp`.
|
|
3
|
+
*
|
|
4
|
+
* Everything that constrains what the server is allowed to do lives here and
|
|
5
|
+
* is decided ONCE at startup, never per tool call. The model can therefore
|
|
6
|
+
* never widen its own permissions: `--root` and `--readonly` are invisible to it.
|
|
7
|
+
*/
|
|
8
|
+
import { chmodSync, mkdirSync, mkdtempSync, realpathSync } from "node:fs";
|
|
9
|
+
import os from "node:os";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { parseArgs } from "node:util";
|
|
12
|
+
/**
|
|
13
|
+
* Tool groups, used by `--enable` to keep the number of tools exposed to a
|
|
14
|
+
* model small. Every additional tool measurably increases the chance the model
|
|
15
|
+
* picks the wrong one, so a caller who only ever touches spreadsheets should
|
|
16
|
+
* not have to pay for the Word and PDF tool descriptions in its context.
|
|
17
|
+
*
|
|
18
|
+
* `core` (`documonster_help`, `doc_inspect`) is always enabled — it is how a
|
|
19
|
+
* model orients itself before doing anything else.
|
|
20
|
+
*/
|
|
21
|
+
export const TOOL_GROUPS = ["core", "excel", "word", "pdf", "forms", "archive"];
|
|
22
|
+
/** Groups enabled when `--enable` is omitted. */
|
|
23
|
+
const DEFAULT_GROUPS = ["core", "excel", "word", "pdf", "forms", "archive"];
|
|
24
|
+
/** Default ceiling for a single input document, in bytes (64 MiB). */
|
|
25
|
+
const DEFAULT_MAX_FILE_SIZE = 64 * 1024 * 1024;
|
|
26
|
+
/**
|
|
27
|
+
* Default ceiling for the text a single tool call may return, in characters.
|
|
28
|
+
* A tool result goes straight into the model's context, so this is a token
|
|
29
|
+
* budget in disguise: ~40 000 characters is roughly 10 000 tokens.
|
|
30
|
+
*/
|
|
31
|
+
const DEFAULT_MAX_OUTPUT_CHARS = 40_000;
|
|
32
|
+
export class ConfigError extends Error {
|
|
33
|
+
name = "ConfigError";
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a {@link ServerConfig} from CLI-style arguments.
|
|
37
|
+
*
|
|
38
|
+
* @param argv - Arguments *after* `node script.js`, i.e. `process.argv.slice(2)`.
|
|
39
|
+
* @throws {ConfigError} On an unknown flag, a missing value, or a `--root`
|
|
40
|
+
* that does not exist. Failing loudly at startup is deliberate: a silently
|
|
41
|
+
* defaulted root would sandbox the model somewhere the operator never chose.
|
|
42
|
+
*/
|
|
43
|
+
export function resolveConfig(argv, options = {}) {
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
parsed = parseArgs({
|
|
47
|
+
args: [...argv],
|
|
48
|
+
options: {
|
|
49
|
+
root: { type: "string" },
|
|
50
|
+
"output-root": { type: "string" },
|
|
51
|
+
"allow-in-place": { type: "boolean", default: false },
|
|
52
|
+
readonly: { type: "boolean", default: false },
|
|
53
|
+
enable: { type: "string" },
|
|
54
|
+
"max-file-size": { type: "string" },
|
|
55
|
+
"max-output-chars": { type: "string" },
|
|
56
|
+
help: { type: "boolean", short: "h", default: false },
|
|
57
|
+
version: { type: "boolean", short: "v", default: false }
|
|
58
|
+
},
|
|
59
|
+
allowPositionals: false,
|
|
60
|
+
strict: true
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (cause) {
|
|
64
|
+
throw new ConfigError(cause instanceof Error ? cause.message : String(cause), { cause });
|
|
65
|
+
}
|
|
66
|
+
const values = parsed.values;
|
|
67
|
+
const cwd = options.cwd ?? process.cwd();
|
|
68
|
+
const rootInput = values.root ?? cwd;
|
|
69
|
+
let root;
|
|
70
|
+
try {
|
|
71
|
+
// realpath, not just resolve: the containment check in `sandbox.ts`
|
|
72
|
+
// compares realpaths, so the root must already be one or a symlinked
|
|
73
|
+
// root (`/tmp` -> `/private/tmp` on macOS) would reject everything.
|
|
74
|
+
root = realpathSync(path.resolve(cwd, rootInput));
|
|
75
|
+
}
|
|
76
|
+
catch (cause) {
|
|
77
|
+
throw new ConfigError(`--root does not exist or is not readable: ${rootInput}`, { cause });
|
|
78
|
+
}
|
|
79
|
+
let outputRoot;
|
|
80
|
+
try {
|
|
81
|
+
const outputInput = values["output-root"];
|
|
82
|
+
if (outputInput === undefined) {
|
|
83
|
+
outputRoot = realpathSync(mkdtempSync(path.join(os.tmpdir(), "documonster-mcp-output-")));
|
|
84
|
+
chmodSync(outputRoot, 0o700);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const absolute = path.resolve(cwd, outputInput);
|
|
88
|
+
mkdirSync(absolute, { recursive: true, mode: 0o700 });
|
|
89
|
+
outputRoot = realpathSync(absolute);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (cause) {
|
|
93
|
+
throw new ConfigError("--output-root could not be created or is not writable", { cause });
|
|
94
|
+
}
|
|
95
|
+
if (containsPath(root, outputRoot) || containsPath(outputRoot, root)) {
|
|
96
|
+
throw new ConfigError("--output-root must be disjoint from --root (neither may contain the other)");
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
root,
|
|
100
|
+
outputRoot,
|
|
101
|
+
allowInPlace: values["allow-in-place"] ?? false,
|
|
102
|
+
readonly: values.readonly ?? false,
|
|
103
|
+
groups: parseGroups(values.enable),
|
|
104
|
+
maxFileSize: parseByteCount(values["max-file-size"], "--max-file-size", DEFAULT_MAX_FILE_SIZE),
|
|
105
|
+
maxOutputChars: parseByteCount(values["max-output-chars"], "--max-output-chars", DEFAULT_MAX_OUTPUT_CHARS)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function containsPath(parent, child) {
|
|
109
|
+
const relative = path.relative(parent, child);
|
|
110
|
+
return (relative === "" ||
|
|
111
|
+
(!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative)));
|
|
112
|
+
}
|
|
113
|
+
/** True when `--help` or `--version` was passed; the CLI short-circuits on these. */
|
|
114
|
+
export function readMetaFlags(argv) {
|
|
115
|
+
return {
|
|
116
|
+
help: argv.includes("--help") || argv.includes("-h"),
|
|
117
|
+
version: argv.includes("--version") || argv.includes("-v")
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function parseGroups(raw) {
|
|
121
|
+
if (raw === undefined) {
|
|
122
|
+
return new Set(DEFAULT_GROUPS);
|
|
123
|
+
}
|
|
124
|
+
const requested = raw
|
|
125
|
+
.split(",")
|
|
126
|
+
.map(entry => entry.trim())
|
|
127
|
+
.filter(entry => entry.length > 0);
|
|
128
|
+
if (requested.length === 0) {
|
|
129
|
+
throw new ConfigError(`--enable needs at least one group (known: ${TOOL_GROUPS.join(", ")})`);
|
|
130
|
+
}
|
|
131
|
+
const groups = new Set(["core"]);
|
|
132
|
+
for (const entry of requested) {
|
|
133
|
+
if (!isToolGroup(entry)) {
|
|
134
|
+
throw new ConfigError(`--enable: unknown group "${entry}" (known: ${TOOL_GROUPS.join(", ")})`);
|
|
135
|
+
}
|
|
136
|
+
groups.add(entry);
|
|
137
|
+
}
|
|
138
|
+
return groups;
|
|
139
|
+
}
|
|
140
|
+
function isToolGroup(value) {
|
|
141
|
+
return TOOL_GROUPS.includes(value);
|
|
142
|
+
}
|
|
143
|
+
function parseByteCount(raw, flag, fallback) {
|
|
144
|
+
if (raw === undefined) {
|
|
145
|
+
return fallback;
|
|
146
|
+
}
|
|
147
|
+
const parsedValue = Number(raw);
|
|
148
|
+
if (!Number.isInteger(parsedValue) || parsedValue <= 0) {
|
|
149
|
+
throw new ConfigError(`${flag} must be a positive integer, got "${raw}"`);
|
|
150
|
+
}
|
|
151
|
+
return parsedValue;
|
|
152
|
+
}
|
|
153
|
+
/** Usage text for `--help`. */
|
|
154
|
+
export function usage() {
|
|
155
|
+
return `documonster-mcp — Model Context Protocol server for documonster
|
|
156
|
+
|
|
157
|
+
Usage:
|
|
158
|
+
documonster-mcp [options]
|
|
159
|
+
|
|
160
|
+
Options:
|
|
161
|
+
--root <dir> Sandbox root. Every path a tool touches must
|
|
162
|
+
resolve inside it. Read-only by default.
|
|
163
|
+
--output-root <dir> Separate writable root. Default: a private 0700
|
|
164
|
+
temporary directory. Outputs are addressed as
|
|
165
|
+
@output/<path> in later tool calls.
|
|
166
|
+
--allow-in-place Permit explicit in-place edits under --root.
|
|
167
|
+
Off by default; weakens the filesystem boundary.
|
|
168
|
+
--readonly Withhold every mutating tool.
|
|
169
|
+
--enable <groups> Comma-separated tool groups to expose.
|
|
170
|
+
Known: ${TOOL_GROUPS.join(", ")}. "core" is always on.
|
|
171
|
+
Default: all.
|
|
172
|
+
--max-file-size <bytes> Reject larger input documents. Default: ${DEFAULT_MAX_FILE_SIZE}.
|
|
173
|
+
--max-output-chars <n> Truncate tool output. Default: ${DEFAULT_MAX_OUTPUT_CHARS}.
|
|
174
|
+
-h, --help Show this help.
|
|
175
|
+
-v, --version Show version.
|
|
176
|
+
|
|
177
|
+
Transport: stdio. Point an MCP client at this command, for example
|
|
178
|
+
|
|
179
|
+
{
|
|
180
|
+
"mcpServers": {
|
|
181
|
+
"documonster": {
|
|
182
|
+
"command": "npx",
|
|
183
|
+
"args": ["-y", "@documonster/mcp", "--root", "/path/to/documents"]
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error model.
|
|
3
|
+
*
|
|
4
|
+
* A tool error is not a crash — it is a message to the model, and the model
|
|
5
|
+
* will try again based on what it reads. So every error carries a machine
|
|
6
|
+
* `code` plus, wherever we can produce one, a `hint` telling the model what to
|
|
7
|
+
* do differently. Error text quality directly determines retry success rate,
|
|
8
|
+
* which makes this file part of the product rather than plumbing.
|
|
9
|
+
*/
|
|
10
|
+
export type ToolErrorCode =
|
|
11
|
+
/** Arguments were structurally valid but semantically wrong. */
|
|
12
|
+
"invalid_input"
|
|
13
|
+
/** The path does not exist. */
|
|
14
|
+
| "not_found"
|
|
15
|
+
/** The path resolved outside the sandbox root. */
|
|
16
|
+
| "outside_root"
|
|
17
|
+
/** A mutating tool was reached while `--readonly` is active. */
|
|
18
|
+
| "readonly"
|
|
19
|
+
/** Input exceeded `--max-file-size`, or output would exceed its budget. */
|
|
20
|
+
| "too_large"
|
|
21
|
+
/** A capability the server deliberately does not expose. */
|
|
22
|
+
| "unsupported"
|
|
23
|
+
/** Anything unclassified — a bug in the server or an unmapped library error. */
|
|
24
|
+
| "internal";
|
|
25
|
+
export interface McpToolErrorOptions extends ErrorOptions {
|
|
26
|
+
/** Actionable next step for the model, e.g. "call doc_inspect first". */
|
|
27
|
+
readonly hint?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* An error that is safe and useful to hand back to a model.
|
|
31
|
+
*
|
|
32
|
+
* Anything thrown that is NOT an `McpToolError` is treated as unclassified and
|
|
33
|
+
* reported as `internal` — so a stack-leaking library error can never be
|
|
34
|
+
* mistaken for a designed, model-facing message.
|
|
35
|
+
*/
|
|
36
|
+
export declare class McpToolError extends Error {
|
|
37
|
+
readonly name = "McpToolError";
|
|
38
|
+
readonly code: ToolErrorCode;
|
|
39
|
+
readonly hint: string | undefined;
|
|
40
|
+
constructor(code: ToolErrorCode, message: string, options?: McpToolErrorOptions);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Convenience constructors for the codes used most often.
|
|
44
|
+
*
|
|
45
|
+
* Each takes an optional `cause`, because documonster's own errors chain via
|
|
46
|
+
* `{ cause }` and the innermost message is usually the one naming the cell,
|
|
47
|
+
* OOXML part or ZIP entry that actually failed — dropping it would leave the
|
|
48
|
+
* model with a generic message it cannot act on.
|
|
49
|
+
*/
|
|
50
|
+
export declare const toolError: {
|
|
51
|
+
readonly invalidInput: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
52
|
+
readonly notFound: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
53
|
+
readonly outsideRoot: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
54
|
+
readonly readonly: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
55
|
+
readonly tooLarge: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
56
|
+
readonly unsupported: (message: string, hint?: string, options?: ErrorOptions) => McpToolError;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Render any thrown value as the text body of an `isError` tool result.
|
|
60
|
+
*
|
|
61
|
+
* Includes the `cause` chain because documonster's own errors chain via
|
|
62
|
+
* `{ cause }`, and the innermost message is usually the one that says which
|
|
63
|
+
* cell, part or ZIP entry actually failed.
|
|
64
|
+
*/
|
|
65
|
+
export declare function formatToolError(error: unknown): string;
|
|
66
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa;AACvB,gEAAgE;AAC9D,eAAe;AACjB,+BAA+B;GAC7B,WAAW;AACb,kDAAkD;GAChD,cAAc;AAChB,gEAAgE;GAC9D,UAAU;AACZ,2EAA2E;GACzE,WAAW;AACb,4DAA4D;GAC1D,aAAa;AACf,gFAAgF;GAC9E,UAAU,CAAC;AAEf,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,kBAAkB;IACxC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAElC,YAAY,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,EAIlF;CACF;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS;aACpB,YAAY,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;aAGlF,QAAQ,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;aAG9E,WAAW,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;aAGjF,QAAQ,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;aAG9E,QAAQ,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;aAG9E,WAAW,YAAU,MAAM,SAAS,MAAM,YAAY,YAAY,KAAG,YAAY;CAGzE,CAAC;AAEX;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAuBtD"}
|