@papermark/mcp-server 0.0.1 → 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/README.md +63 -4
- package/dist/chunk-S3ALJ4YG.js +606 -0
- package/dist/chunk-S3ALJ4YG.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1072 -0
- package/dist/index.js.map +1 -0
- package/dist/tools-contract.d.ts +617 -0
- package/dist/tools-contract.js +90 -0
- package/dist/tools-contract.js.map +1 -0
- package/package.json +50 -8
package/dist/index.js
ADDED
|
@@ -0,0 +1,1072 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
addDocumentVersionContract,
|
|
4
|
+
attachDataroomDocumentContract,
|
|
5
|
+
createDataroomContract,
|
|
6
|
+
createDataroomFolderContract,
|
|
7
|
+
createFolderContract,
|
|
8
|
+
createLinkContract,
|
|
9
|
+
deleteDataroomContract,
|
|
10
|
+
deleteDataroomFolderContract,
|
|
11
|
+
deleteDocumentContract,
|
|
12
|
+
deleteFolderContract,
|
|
13
|
+
deleteLinkContract,
|
|
14
|
+
getDataroomAnalyticsContract,
|
|
15
|
+
getDataroomContract,
|
|
16
|
+
getDataroomFolderContract,
|
|
17
|
+
getDocumentAnalyticsContract,
|
|
18
|
+
getDocumentContract,
|
|
19
|
+
getDocumentVersionContract,
|
|
20
|
+
getFolderContract,
|
|
21
|
+
getLinkAnalyticsContract,
|
|
22
|
+
getLinkContract,
|
|
23
|
+
getViewAnalyticsContract,
|
|
24
|
+
getVisitorContract,
|
|
25
|
+
listDataroomDocumentsContract,
|
|
26
|
+
listDataroomFoldersContract,
|
|
27
|
+
listDataroomsContract,
|
|
28
|
+
listDocumentVersionsContract,
|
|
29
|
+
listDocumentsContract,
|
|
30
|
+
listFoldersContract,
|
|
31
|
+
listLinkViewsContract,
|
|
32
|
+
listLinksContract,
|
|
33
|
+
listVisitorViewsContract,
|
|
34
|
+
listVisitorsContract,
|
|
35
|
+
moveDataroomFolderContract,
|
|
36
|
+
moveFolderContract,
|
|
37
|
+
promoteDocumentVersionContract,
|
|
38
|
+
searchDataroomsContract,
|
|
39
|
+
searchDocumentsContract,
|
|
40
|
+
updateDataroomContract,
|
|
41
|
+
updateDataroomFolderContract,
|
|
42
|
+
updateDocumentContract,
|
|
43
|
+
updateFolderContract,
|
|
44
|
+
updateLinkContract
|
|
45
|
+
} from "./chunk-S3ALJ4YG.js";
|
|
46
|
+
|
|
47
|
+
// src/index.ts
|
|
48
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
49
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
50
|
+
|
|
51
|
+
// src/tools.ts
|
|
52
|
+
import { readFile, stat } from "fs/promises";
|
|
53
|
+
import { basename } from "path";
|
|
54
|
+
import { lookup as lookupMimeType } from "mime-types";
|
|
55
|
+
import { z } from "zod";
|
|
56
|
+
|
|
57
|
+
// src/config.ts
|
|
58
|
+
var DEFAULT_API_URL = "https://api.papermark.com";
|
|
59
|
+
function getToken() {
|
|
60
|
+
return process.env.PAPERMARK_TOKEN?.trim() || void 0;
|
|
61
|
+
}
|
|
62
|
+
function getApiUrl() {
|
|
63
|
+
return process.env.PAPERMARK_API_URL?.trim() || DEFAULT_API_URL;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/client.ts
|
|
67
|
+
var ApiError = class extends Error {
|
|
68
|
+
code;
|
|
69
|
+
status;
|
|
70
|
+
docUrl;
|
|
71
|
+
details;
|
|
72
|
+
constructor(status, body) {
|
|
73
|
+
const message = typeof body === "string" ? body : body.message;
|
|
74
|
+
super(message);
|
|
75
|
+
this.status = status;
|
|
76
|
+
if (typeof body === "string") {
|
|
77
|
+
this.code = "unknown";
|
|
78
|
+
} else {
|
|
79
|
+
this.code = body.code;
|
|
80
|
+
this.docUrl = body.doc_url;
|
|
81
|
+
this.details = body.details;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var AuthRequiredError = class extends Error {
|
|
86
|
+
constructor() {
|
|
87
|
+
super(
|
|
88
|
+
"No API token configured. Set PAPERMARK_TOKEN in the MCP server env (get one from papermark.com/settings/tokens)."
|
|
89
|
+
);
|
|
90
|
+
this.name = "AuthRequiredError";
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
var NetworkError = class extends Error {
|
|
94
|
+
url;
|
|
95
|
+
cause;
|
|
96
|
+
constructor(url, cause) {
|
|
97
|
+
const reason = extractNetworkReason(cause);
|
|
98
|
+
super(`Network request to ${url} failed: ${reason}`);
|
|
99
|
+
this.name = "NetworkError";
|
|
100
|
+
this.url = url;
|
|
101
|
+
this.cause = cause;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
function extractNetworkReason(err) {
|
|
105
|
+
if (err && typeof err === "object" && "cause" in err) {
|
|
106
|
+
const c = err.cause;
|
|
107
|
+
if (c && typeof c === "object") {
|
|
108
|
+
const code = c.code;
|
|
109
|
+
const msg = c.message;
|
|
110
|
+
if (code || msg) return `${code ?? ""}${code && msg ? " \u2014 " : ""}${msg ?? ""}`.trim();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (err instanceof Error) return err.message;
|
|
114
|
+
return String(err);
|
|
115
|
+
}
|
|
116
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
117
|
+
function buildUrl(path, query) {
|
|
118
|
+
const base = getApiUrl().replace(/\/$/, "");
|
|
119
|
+
let fullPath = path.startsWith("/") ? path : `/${path}`;
|
|
120
|
+
if (base.endsWith("/api") && fullPath.startsWith("/api/")) {
|
|
121
|
+
fullPath = fullPath.slice(4);
|
|
122
|
+
}
|
|
123
|
+
const url = new URL(base + fullPath);
|
|
124
|
+
if (query) {
|
|
125
|
+
for (const [k, v] of Object.entries(query)) {
|
|
126
|
+
if (v !== void 0 && v !== null && v !== "") {
|
|
127
|
+
url.searchParams.set(k, String(v));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return url.toString();
|
|
132
|
+
}
|
|
133
|
+
async function request(path, opts = {}) {
|
|
134
|
+
const headers = {
|
|
135
|
+
Accept: "application/json",
|
|
136
|
+
...opts.headers ?? {}
|
|
137
|
+
};
|
|
138
|
+
if (!opts.anonymous) {
|
|
139
|
+
const token = opts.token ?? getToken();
|
|
140
|
+
if (!token) throw new AuthRequiredError();
|
|
141
|
+
headers.Authorization = `Bearer ${token}`;
|
|
142
|
+
}
|
|
143
|
+
let body;
|
|
144
|
+
if (opts.body !== void 0) {
|
|
145
|
+
if (opts.body instanceof Uint8Array || opts.body instanceof ArrayBuffer) {
|
|
146
|
+
body = opts.body;
|
|
147
|
+
} else {
|
|
148
|
+
body = JSON.stringify(opts.body);
|
|
149
|
+
headers["Content-Type"] = "application/json";
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const url = buildUrl(path, opts.query);
|
|
153
|
+
const controller = new AbortController();
|
|
154
|
+
const timeoutMs = opts.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
155
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
156
|
+
let res;
|
|
157
|
+
try {
|
|
158
|
+
res = await fetch(url, {
|
|
159
|
+
method: opts.method ?? (opts.body ? "POST" : "GET"),
|
|
160
|
+
headers,
|
|
161
|
+
body,
|
|
162
|
+
signal: controller.signal
|
|
163
|
+
});
|
|
164
|
+
} catch (err) {
|
|
165
|
+
if (controller.signal.aborted || err instanceof Error && err.name === "AbortError") {
|
|
166
|
+
throw new NetworkError(
|
|
167
|
+
url,
|
|
168
|
+
new Error(`Request exceeded ${timeoutMs}ms timeout`)
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
throw new NetworkError(url, err);
|
|
172
|
+
} finally {
|
|
173
|
+
clearTimeout(timer);
|
|
174
|
+
}
|
|
175
|
+
if (res.status === 204) return void 0;
|
|
176
|
+
const text = await res.text();
|
|
177
|
+
const parsed = text ? safeParseJson(text) : null;
|
|
178
|
+
if (!res.ok) {
|
|
179
|
+
if (parsed && typeof parsed === "object" && "error" in parsed) {
|
|
180
|
+
throw new ApiError(res.status, parsed.error);
|
|
181
|
+
}
|
|
182
|
+
const looksLikeHtml = text.trimStart().toLowerCase().startsWith("<");
|
|
183
|
+
const msg = looksLikeHtml ? `HTTP ${res.status} (server returned HTML, not JSON \u2014 is the API reachable?)` : text || `HTTP ${res.status}`;
|
|
184
|
+
throw new ApiError(res.status, msg);
|
|
185
|
+
}
|
|
186
|
+
return parsed ?? void 0;
|
|
187
|
+
}
|
|
188
|
+
function safeParseJson(s) {
|
|
189
|
+
try {
|
|
190
|
+
return JSON.parse(s);
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
var api = {
|
|
196
|
+
// Documents
|
|
197
|
+
listDocuments: (query, token) => request("/v1/documents", { query, token }),
|
|
198
|
+
getDocument: (id, token) => request(`/v1/documents/${id}`, { token }),
|
|
199
|
+
searchDocuments: (q, limit, token) => request("/v1/documents/search", { query: { q, limit }, token }),
|
|
200
|
+
updateDocument: (id, body, token) => request(`/v1/documents/${id}`, {
|
|
201
|
+
method: "PATCH",
|
|
202
|
+
body,
|
|
203
|
+
token
|
|
204
|
+
}),
|
|
205
|
+
deleteDocument: (id, token) => request(`/v1/documents/${id}`, { method: "DELETE", token }),
|
|
206
|
+
uploadUrl: (body, token) => request("/v1/documents/upload-url", {
|
|
207
|
+
method: "POST",
|
|
208
|
+
body,
|
|
209
|
+
token
|
|
210
|
+
}),
|
|
211
|
+
createDocument: (body, token) => request("/v1/documents", { method: "POST", body, token }),
|
|
212
|
+
// Document versions
|
|
213
|
+
listDocumentVersions: (id, token) => request(`/v1/documents/${id}/versions`, { token }),
|
|
214
|
+
addDocumentVersion: (id, body, token) => request(`/v1/documents/${id}/versions`, {
|
|
215
|
+
method: "POST",
|
|
216
|
+
body,
|
|
217
|
+
token
|
|
218
|
+
}),
|
|
219
|
+
getDocumentVersion: (id, vid, token) => request(`/v1/documents/${id}/versions/${vid}`, {
|
|
220
|
+
token
|
|
221
|
+
}),
|
|
222
|
+
promoteDocumentVersion: (id, vid, token) => request(`/v1/documents/${id}/versions/${vid}`, {
|
|
223
|
+
method: "PATCH",
|
|
224
|
+
body: { is_primary: true },
|
|
225
|
+
token
|
|
226
|
+
}),
|
|
227
|
+
// Folders
|
|
228
|
+
listFolders: (query, token) => request("/v1/folders", { query, token }),
|
|
229
|
+
createFolder: (body, token) => request("/v1/folders", { method: "POST", body, token }),
|
|
230
|
+
getFolder: (id, token) => request(`/v1/folders/${id}`, { token }),
|
|
231
|
+
updateFolder: (id, body, token) => request(`/v1/folders/${id}`, { method: "PATCH", body, token }),
|
|
232
|
+
deleteFolder: (id, opts, token) => request(`/v1/folders/${id}`, {
|
|
233
|
+
method: "DELETE",
|
|
234
|
+
query: opts?.cascade ? { cascade: "true" } : void 0,
|
|
235
|
+
token
|
|
236
|
+
}),
|
|
237
|
+
moveFolder: (id, body, token) => request(`/v1/folders/${id}/move`, {
|
|
238
|
+
method: "POST",
|
|
239
|
+
body,
|
|
240
|
+
token
|
|
241
|
+
}),
|
|
242
|
+
// Links
|
|
243
|
+
listLinks: (query, token) => request("/v1/links", { query, token }),
|
|
244
|
+
getLink: (id, token) => request(`/v1/links/${id}`, { token }),
|
|
245
|
+
createLink: (body, token) => request("/v1/links", { method: "POST", body, token }),
|
|
246
|
+
updateLink: (id, body, token) => request(`/v1/links/${id}`, { method: "PATCH", body, token }),
|
|
247
|
+
deleteLink: (id, token) => request(`/v1/links/${id}`, { method: "DELETE", token }),
|
|
248
|
+
listViews: (linkId, query, token) => request(`/v1/links/${linkId}/views`, { query, token }),
|
|
249
|
+
// Datarooms
|
|
250
|
+
listDatarooms: (query, token) => request("/v1/datarooms", { query, token }),
|
|
251
|
+
getDataroom: (id, token) => request(`/v1/datarooms/${id}`, { token }),
|
|
252
|
+
createDataroom: (body, token) => request("/v1/datarooms", { method: "POST", body, token }),
|
|
253
|
+
updateDataroom: (id, body, token) => request(`/v1/datarooms/${id}`, { method: "PATCH", body, token }),
|
|
254
|
+
deleteDataroom: (id, token) => request(`/v1/datarooms/${id}`, { method: "DELETE", token }),
|
|
255
|
+
listDataroomDocuments: (id, query, token) => request(`/v1/datarooms/${id}/documents`, { query, token }),
|
|
256
|
+
attachDataroomDocument: (id, body, token) => request(`/v1/datarooms/${id}/documents`, {
|
|
257
|
+
method: "POST",
|
|
258
|
+
body,
|
|
259
|
+
token
|
|
260
|
+
}),
|
|
261
|
+
// Dataroom folders
|
|
262
|
+
listDataroomFolders: (id, query, token) => request(`/v1/datarooms/${id}/folders`, {
|
|
263
|
+
query,
|
|
264
|
+
token
|
|
265
|
+
}),
|
|
266
|
+
createDataroomFolder: (id, body, token) => request(`/v1/datarooms/${id}/folders`, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
body,
|
|
269
|
+
token
|
|
270
|
+
}),
|
|
271
|
+
getDataroomFolder: (id, fid, token) => request(`/v1/datarooms/${id}/folders/${fid}`, {
|
|
272
|
+
token
|
|
273
|
+
}),
|
|
274
|
+
updateDataroomFolder: (id, fid, body, token) => request(`/v1/datarooms/${id}/folders/${fid}`, {
|
|
275
|
+
method: "PATCH",
|
|
276
|
+
body,
|
|
277
|
+
token
|
|
278
|
+
}),
|
|
279
|
+
deleteDataroomFolder: (id, fid, opts, token) => request(`/v1/datarooms/${id}/folders/${fid}`, {
|
|
280
|
+
method: "DELETE",
|
|
281
|
+
query: opts?.cascade ? { cascade: "true" } : void 0,
|
|
282
|
+
token
|
|
283
|
+
}),
|
|
284
|
+
moveDataroomFolder: (id, fid, body, token) => request(`/v1/datarooms/${id}/folders/${fid}/move`, {
|
|
285
|
+
method: "POST",
|
|
286
|
+
body,
|
|
287
|
+
token
|
|
288
|
+
}),
|
|
289
|
+
// Visitors
|
|
290
|
+
listVisitors: (query, token) => request("/v1/visitors", { query, token }),
|
|
291
|
+
getVisitor: (id, token) => request(`/v1/visitors/${id}`, { token }),
|
|
292
|
+
listVisitorViews: (id, query, token) => request(`/v1/visitors/${id}/views`, { query, token }),
|
|
293
|
+
// Analytics
|
|
294
|
+
documentAnalytics: (id, query, token) => request(`/v1/analytics/documents/${id}`, { query, token }),
|
|
295
|
+
linkAnalytics: (id, query, token) => request(`/v1/analytics/links/${id}`, { query, token }),
|
|
296
|
+
dataroomAnalytics: (id, query, token) => request(`/v1/analytics/datarooms/${id}`, { query, token }),
|
|
297
|
+
viewAnalytics: (id, token) => request(`/v1/analytics/views/${id}`, { token })
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/tools.ts
|
|
301
|
+
async function run(fn, label) {
|
|
302
|
+
try {
|
|
303
|
+
const result = await fn();
|
|
304
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
305
|
+
} catch (err) {
|
|
306
|
+
if (err instanceof ApiError) {
|
|
307
|
+
const detail = err.details !== void 0 && err.details !== null ? `
|
|
308
|
+
Details: ${JSON.stringify(err.details)}` : "";
|
|
309
|
+
const hint = err.docUrl ? `
|
|
310
|
+
Docs: ${err.docUrl}` : "";
|
|
311
|
+
return {
|
|
312
|
+
isError: true,
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: "text",
|
|
316
|
+
text: `${label} failed (${err.status} ${err.code}): ${err.message}${detail}${hint}`
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (err instanceof NetworkError) {
|
|
322
|
+
return {
|
|
323
|
+
isError: true,
|
|
324
|
+
content: [{ type: "text", text: `${label} failed: ${err.message}` }]
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (err instanceof AuthRequiredError) {
|
|
328
|
+
return { isError: true, content: [{ type: "text", text: err.message }] };
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
isError: true,
|
|
332
|
+
content: [
|
|
333
|
+
{ type: "text", text: `${label} failed: ${err instanceof Error ? err.message : String(err)}` }
|
|
334
|
+
]
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function guessContentType(fileName) {
|
|
339
|
+
return lookupMimeType(fileName) || "application/octet-stream";
|
|
340
|
+
}
|
|
341
|
+
function filenameFromUrl(rawUrl) {
|
|
342
|
+
try {
|
|
343
|
+
const u = new URL(rawUrl);
|
|
344
|
+
const last = u.pathname.split("/").filter(Boolean).pop();
|
|
345
|
+
if (!last) return "document";
|
|
346
|
+
return decodeURIComponent(last);
|
|
347
|
+
} catch {
|
|
348
|
+
return "document";
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function summarizeDocument(d) {
|
|
352
|
+
return {
|
|
353
|
+
id: d.id,
|
|
354
|
+
object: d.object,
|
|
355
|
+
name: d.name,
|
|
356
|
+
content_type: d.content_type,
|
|
357
|
+
num_pages: d.num_pages,
|
|
358
|
+
created: d.created
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function summarizeLink(l) {
|
|
362
|
+
return {
|
|
363
|
+
id: l.id,
|
|
364
|
+
object: l.object,
|
|
365
|
+
url: l.url,
|
|
366
|
+
name: l.name,
|
|
367
|
+
target_type: l.target_type,
|
|
368
|
+
document_id: l.document_id,
|
|
369
|
+
dataroom_id: l.dataroom_id,
|
|
370
|
+
expires_at: l.expires_at,
|
|
371
|
+
is_password_protected: l.is_password_protected,
|
|
372
|
+
email_protected: l.email_protected,
|
|
373
|
+
allow_download: l.allow_download
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function summarizeView(v) {
|
|
377
|
+
return {
|
|
378
|
+
id: v.id,
|
|
379
|
+
link_id: v.link_id,
|
|
380
|
+
viewer_email: v.viewer_email,
|
|
381
|
+
viewed_at: v.viewed_at,
|
|
382
|
+
downloaded_at: v.downloaded_at
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function registerTools(server) {
|
|
386
|
+
server.registerTool(
|
|
387
|
+
listDocumentsContract.name,
|
|
388
|
+
{
|
|
389
|
+
title: listDocumentsContract.title,
|
|
390
|
+
description: listDocumentsContract.description,
|
|
391
|
+
inputSchema: listDocumentsContract.inputSchema
|
|
392
|
+
},
|
|
393
|
+
async (args) => run(async () => {
|
|
394
|
+
const list = await api.listDocuments({
|
|
395
|
+
limit: args.limit,
|
|
396
|
+
cursor: args.cursor,
|
|
397
|
+
query: args.query
|
|
398
|
+
});
|
|
399
|
+
return {
|
|
400
|
+
documents: list.data.map(summarizeDocument),
|
|
401
|
+
next_cursor: list.next_cursor
|
|
402
|
+
};
|
|
403
|
+
}, "list_documents")
|
|
404
|
+
);
|
|
405
|
+
server.registerTool(
|
|
406
|
+
getDocumentContract.name,
|
|
407
|
+
{
|
|
408
|
+
title: getDocumentContract.title,
|
|
409
|
+
description: getDocumentContract.description,
|
|
410
|
+
inputSchema: getDocumentContract.inputSchema
|
|
411
|
+
},
|
|
412
|
+
async (args) => run(() => api.getDocument(args.document_id), "get_document")
|
|
413
|
+
);
|
|
414
|
+
server.registerTool(
|
|
415
|
+
searchDocumentsContract.name,
|
|
416
|
+
{
|
|
417
|
+
title: searchDocumentsContract.title,
|
|
418
|
+
description: searchDocumentsContract.description,
|
|
419
|
+
inputSchema: searchDocumentsContract.inputSchema
|
|
420
|
+
},
|
|
421
|
+
async (args) => run(async () => {
|
|
422
|
+
const list = await api.searchDocuments(args.query, args.limit);
|
|
423
|
+
return { documents: list.data.map(summarizeDocument), next_cursor: list.next_cursor };
|
|
424
|
+
}, "search_documents")
|
|
425
|
+
);
|
|
426
|
+
server.registerTool(
|
|
427
|
+
"upload_document",
|
|
428
|
+
{
|
|
429
|
+
title: "Upload a document",
|
|
430
|
+
description: `Upload a document to Papermark from a local file path OR a public HTTPS URL.
|
|
431
|
+
|
|
432
|
+
WORKFLOW:
|
|
433
|
+
(1) Resolve the source: the user must name either a \`file_path\` (local filesystem \u2014 stdio mode only) OR a \`source_url\` (public HTTPS). Never guess a path; if the user attached a file in chat but didn't give a local path, ASK them to save it and provide the path.
|
|
434
|
+
(2) Confirm the target \`name\` if the user wants something other than the filename.
|
|
435
|
+
(3) If the user wants a share link in the same breath, set \`create_link: true\` \u2014 otherwise follow up with \`create_link\` so you can set password/expiry/email gating explicitly.
|
|
436
|
+
|
|
437
|
+
Don't upload any file the user didn't explicitly point at. Requires scope \`documents.write\`.`,
|
|
438
|
+
inputSchema: {
|
|
439
|
+
file_path: z.string().optional().describe(
|
|
440
|
+
"Absolute local path \u2014 only works when the MCP server runs on the same machine as the file (stdio mode)"
|
|
441
|
+
),
|
|
442
|
+
source_url: z.string().url().refine((s) => s.startsWith("https://"), {
|
|
443
|
+
message: "source_url must use https:// (http is rejected by the API)"
|
|
444
|
+
}).optional().describe("Public HTTPS URL the server should fetch (alternative to file_path)"),
|
|
445
|
+
name: z.string().optional().describe("Display name; defaults to the filename"),
|
|
446
|
+
content_type: z.string().optional().describe("MIME type; inferred from extension when omitted"),
|
|
447
|
+
folder_id: z.string().optional().describe(
|
|
448
|
+
"Destination folder id (created beforehand via `create_folder`). Omit for the team-library root."
|
|
449
|
+
),
|
|
450
|
+
create_link: z.boolean().optional().describe("Create a default share link after upload")
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
async (args) => run(async () => {
|
|
454
|
+
if (!args.file_path && !args.source_url) {
|
|
455
|
+
throw new Error("Provide either file_path (local) or source_url (remote).");
|
|
456
|
+
}
|
|
457
|
+
if (args.file_path && args.source_url) {
|
|
458
|
+
throw new Error("Provide only one of file_path or source_url.");
|
|
459
|
+
}
|
|
460
|
+
if (args.source_url) {
|
|
461
|
+
const name = args.name ?? filenameFromUrl(args.source_url);
|
|
462
|
+
const doc2 = await api.createDocument({
|
|
463
|
+
name,
|
|
464
|
+
source_url: args.source_url,
|
|
465
|
+
folder_id: args.folder_id,
|
|
466
|
+
create_link: args.create_link
|
|
467
|
+
});
|
|
468
|
+
return { document: summarizeDocument(doc2) };
|
|
469
|
+
}
|
|
470
|
+
const filePath = args.file_path;
|
|
471
|
+
const stats = await stat(filePath);
|
|
472
|
+
const fileName = basename(filePath);
|
|
473
|
+
const contentType = args.content_type ?? guessContentType(fileName);
|
|
474
|
+
const body = await readFile(filePath);
|
|
475
|
+
const presigned = await api.uploadUrl({
|
|
476
|
+
fileName,
|
|
477
|
+
contentType,
|
|
478
|
+
contentLength: stats.size
|
|
479
|
+
});
|
|
480
|
+
const putController = new AbortController();
|
|
481
|
+
const putTimer = setTimeout(() => putController.abort(), 5 * 6e4);
|
|
482
|
+
let put;
|
|
483
|
+
try {
|
|
484
|
+
put = await fetch(presigned.upload_url, {
|
|
485
|
+
method: "PUT",
|
|
486
|
+
headers: presigned.required_headers,
|
|
487
|
+
body,
|
|
488
|
+
signal: putController.signal
|
|
489
|
+
});
|
|
490
|
+
} catch (err) {
|
|
491
|
+
if (putController.signal.aborted || err instanceof Error && err.name === "AbortError") {
|
|
492
|
+
throw new Error(
|
|
493
|
+
"Storage PUT aborted: presigned upload exceeded 5 minute timeout. The connection to object storage stalled \u2014 retry with a smaller file or a faster network."
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
throw err;
|
|
497
|
+
} finally {
|
|
498
|
+
clearTimeout(putTimer);
|
|
499
|
+
}
|
|
500
|
+
if (!put.ok) {
|
|
501
|
+
throw new Error(`Storage PUT failed: HTTP ${put.status} ${put.statusText}`);
|
|
502
|
+
}
|
|
503
|
+
const doc = await api.createDocument({
|
|
504
|
+
name: args.name ?? fileName,
|
|
505
|
+
upload_id: presigned.upload_id,
|
|
506
|
+
folder_id: args.folder_id,
|
|
507
|
+
create_link: args.create_link
|
|
508
|
+
});
|
|
509
|
+
return { document: summarizeDocument(doc) };
|
|
510
|
+
}, "upload_document")
|
|
511
|
+
);
|
|
512
|
+
server.registerTool(
|
|
513
|
+
createLinkContract.name,
|
|
514
|
+
{
|
|
515
|
+
title: createLinkContract.title,
|
|
516
|
+
description: createLinkContract.description,
|
|
517
|
+
inputSchema: createLinkContract.inputSchema
|
|
518
|
+
},
|
|
519
|
+
async (args) => run(async () => {
|
|
520
|
+
const hasDoc = Boolean(args.document_id);
|
|
521
|
+
const hasDr = Boolean(args.dataroom_id);
|
|
522
|
+
if (!hasDoc && !hasDr) {
|
|
523
|
+
throw new Error("Provide document_id or dataroom_id.");
|
|
524
|
+
}
|
|
525
|
+
if (hasDoc && hasDr) {
|
|
526
|
+
throw new Error(
|
|
527
|
+
"Provide exactly one of document_id or dataroom_id, not both."
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
const link = await api.createLink(args);
|
|
531
|
+
return { link: summarizeLink(link) };
|
|
532
|
+
}, "create_link")
|
|
533
|
+
);
|
|
534
|
+
server.registerTool(
|
|
535
|
+
listLinksContract.name,
|
|
536
|
+
{
|
|
537
|
+
title: listLinksContract.title,
|
|
538
|
+
description: listLinksContract.description,
|
|
539
|
+
inputSchema: listLinksContract.inputSchema
|
|
540
|
+
},
|
|
541
|
+
async (args) => run(async () => {
|
|
542
|
+
const list = await api.listLinks(args);
|
|
543
|
+
return { links: list.data.map(summarizeLink), next_cursor: list.next_cursor };
|
|
544
|
+
}, "list_links")
|
|
545
|
+
);
|
|
546
|
+
server.registerTool(
|
|
547
|
+
listLinkViewsContract.name,
|
|
548
|
+
{
|
|
549
|
+
title: listLinkViewsContract.title,
|
|
550
|
+
description: listLinkViewsContract.description,
|
|
551
|
+
inputSchema: listLinkViewsContract.inputSchema
|
|
552
|
+
},
|
|
553
|
+
async (args) => run(async () => {
|
|
554
|
+
const list = await api.listViews(args.link_id, {
|
|
555
|
+
limit: args.limit,
|
|
556
|
+
cursor: args.cursor
|
|
557
|
+
});
|
|
558
|
+
return { views: list.data.map(summarizeView), next_cursor: list.next_cursor };
|
|
559
|
+
}, "list_link_views")
|
|
560
|
+
);
|
|
561
|
+
server.registerTool(
|
|
562
|
+
listDataroomsContract.name,
|
|
563
|
+
{
|
|
564
|
+
title: listDataroomsContract.title,
|
|
565
|
+
description: listDataroomsContract.description,
|
|
566
|
+
inputSchema: listDataroomsContract.inputSchema
|
|
567
|
+
},
|
|
568
|
+
async (args) => run(async () => {
|
|
569
|
+
const list = await api.listDatarooms(args);
|
|
570
|
+
return { datarooms: list.data, next_cursor: list.next_cursor };
|
|
571
|
+
}, "list_datarooms")
|
|
572
|
+
);
|
|
573
|
+
server.registerTool(
|
|
574
|
+
searchDataroomsContract.name,
|
|
575
|
+
{
|
|
576
|
+
title: searchDataroomsContract.title,
|
|
577
|
+
description: searchDataroomsContract.description,
|
|
578
|
+
inputSchema: searchDataroomsContract.inputSchema
|
|
579
|
+
},
|
|
580
|
+
async (args) => run(async () => {
|
|
581
|
+
const list = await api.listDatarooms({
|
|
582
|
+
query: args.query,
|
|
583
|
+
limit: args.limit ?? 10
|
|
584
|
+
});
|
|
585
|
+
return { datarooms: list.data, next_cursor: list.next_cursor };
|
|
586
|
+
}, "search_datarooms")
|
|
587
|
+
);
|
|
588
|
+
server.registerTool(
|
|
589
|
+
getDataroomContract.name,
|
|
590
|
+
{
|
|
591
|
+
title: getDataroomContract.title,
|
|
592
|
+
description: getDataroomContract.description,
|
|
593
|
+
inputSchema: getDataroomContract.inputSchema
|
|
594
|
+
},
|
|
595
|
+
async (args) => run(() => api.getDataroom(args.dataroom_id), "get_dataroom")
|
|
596
|
+
);
|
|
597
|
+
server.registerTool(
|
|
598
|
+
createDataroomContract.name,
|
|
599
|
+
{
|
|
600
|
+
title: createDataroomContract.title,
|
|
601
|
+
description: createDataroomContract.description,
|
|
602
|
+
inputSchema: createDataroomContract.inputSchema
|
|
603
|
+
},
|
|
604
|
+
async (args) => run(async () => {
|
|
605
|
+
const dr = await api.createDataroom(args);
|
|
606
|
+
return { dataroom: dr };
|
|
607
|
+
}, "create_dataroom")
|
|
608
|
+
);
|
|
609
|
+
server.registerTool(
|
|
610
|
+
listDataroomDocumentsContract.name,
|
|
611
|
+
{
|
|
612
|
+
title: listDataroomDocumentsContract.title,
|
|
613
|
+
description: listDataroomDocumentsContract.description,
|
|
614
|
+
inputSchema: listDataroomDocumentsContract.inputSchema
|
|
615
|
+
},
|
|
616
|
+
async (args) => run(async () => {
|
|
617
|
+
const list = await api.listDataroomDocuments(args.dataroom_id, {
|
|
618
|
+
limit: args.limit,
|
|
619
|
+
cursor: args.cursor,
|
|
620
|
+
folder_id: args.folder_id
|
|
621
|
+
});
|
|
622
|
+
return { documents: list.data, next_cursor: list.next_cursor };
|
|
623
|
+
}, "list_dataroom_documents")
|
|
624
|
+
);
|
|
625
|
+
server.registerTool(
|
|
626
|
+
listVisitorsContract.name,
|
|
627
|
+
{
|
|
628
|
+
title: listVisitorsContract.title,
|
|
629
|
+
description: listVisitorsContract.description,
|
|
630
|
+
inputSchema: listVisitorsContract.inputSchema
|
|
631
|
+
},
|
|
632
|
+
async (args) => run(async () => {
|
|
633
|
+
const list = await api.listVisitors(args);
|
|
634
|
+
return { visitors: list.data, next_cursor: list.next_cursor };
|
|
635
|
+
}, "list_visitors")
|
|
636
|
+
);
|
|
637
|
+
server.registerTool(
|
|
638
|
+
listVisitorViewsContract.name,
|
|
639
|
+
{
|
|
640
|
+
title: listVisitorViewsContract.title,
|
|
641
|
+
description: listVisitorViewsContract.description,
|
|
642
|
+
inputSchema: listVisitorViewsContract.inputSchema
|
|
643
|
+
},
|
|
644
|
+
async (args) => run(async () => {
|
|
645
|
+
const list = await api.listVisitorViews(args.visitor_id, {
|
|
646
|
+
limit: args.limit,
|
|
647
|
+
cursor: args.cursor
|
|
648
|
+
});
|
|
649
|
+
return { views: list.data, next_cursor: list.next_cursor };
|
|
650
|
+
}, "list_visitor_views")
|
|
651
|
+
);
|
|
652
|
+
server.registerTool(
|
|
653
|
+
getDocumentAnalyticsContract.name,
|
|
654
|
+
{
|
|
655
|
+
title: getDocumentAnalyticsContract.title,
|
|
656
|
+
description: getDocumentAnalyticsContract.description,
|
|
657
|
+
inputSchema: getDocumentAnalyticsContract.inputSchema
|
|
658
|
+
},
|
|
659
|
+
async (args) => run(
|
|
660
|
+
() => api.documentAnalytics(args.document_id, {
|
|
661
|
+
since: args.since,
|
|
662
|
+
until: args.until
|
|
663
|
+
}),
|
|
664
|
+
"get_document_analytics"
|
|
665
|
+
)
|
|
666
|
+
);
|
|
667
|
+
server.registerTool(
|
|
668
|
+
getLinkAnalyticsContract.name,
|
|
669
|
+
{
|
|
670
|
+
title: getLinkAnalyticsContract.title,
|
|
671
|
+
description: getLinkAnalyticsContract.description,
|
|
672
|
+
inputSchema: getLinkAnalyticsContract.inputSchema
|
|
673
|
+
},
|
|
674
|
+
async (args) => run(
|
|
675
|
+
() => api.linkAnalytics(args.link_id, {
|
|
676
|
+
since: args.since,
|
|
677
|
+
until: args.until
|
|
678
|
+
}),
|
|
679
|
+
"get_link_analytics"
|
|
680
|
+
)
|
|
681
|
+
);
|
|
682
|
+
server.registerTool(
|
|
683
|
+
getDataroomAnalyticsContract.name,
|
|
684
|
+
{
|
|
685
|
+
title: getDataroomAnalyticsContract.title,
|
|
686
|
+
description: getDataroomAnalyticsContract.description,
|
|
687
|
+
inputSchema: getDataroomAnalyticsContract.inputSchema
|
|
688
|
+
},
|
|
689
|
+
async (args) => run(
|
|
690
|
+
() => api.dataroomAnalytics(args.dataroom_id, {
|
|
691
|
+
since: args.since,
|
|
692
|
+
until: args.until
|
|
693
|
+
}),
|
|
694
|
+
"get_dataroom_analytics"
|
|
695
|
+
)
|
|
696
|
+
);
|
|
697
|
+
server.registerTool(
|
|
698
|
+
getViewAnalyticsContract.name,
|
|
699
|
+
{
|
|
700
|
+
title: getViewAnalyticsContract.title,
|
|
701
|
+
description: getViewAnalyticsContract.description,
|
|
702
|
+
inputSchema: getViewAnalyticsContract.inputSchema
|
|
703
|
+
},
|
|
704
|
+
async (args) => run(() => api.viewAnalytics(args.view_id), "get_view_analytics")
|
|
705
|
+
);
|
|
706
|
+
server.registerTool(
|
|
707
|
+
updateDocumentContract.name,
|
|
708
|
+
{
|
|
709
|
+
title: updateDocumentContract.title,
|
|
710
|
+
description: updateDocumentContract.description,
|
|
711
|
+
inputSchema: updateDocumentContract.inputSchema
|
|
712
|
+
},
|
|
713
|
+
async (args) => run(async () => {
|
|
714
|
+
const body = {};
|
|
715
|
+
if (args.name !== void 0) body.name = args.name;
|
|
716
|
+
if (args.folder_id !== void 0) body.folder_id = args.folder_id;
|
|
717
|
+
if (Object.keys(body).length === 0) {
|
|
718
|
+
throw new Error("Provide at least one of `name` or `folder_id`.");
|
|
719
|
+
}
|
|
720
|
+
const doc = await api.updateDocument(args.document_id, body);
|
|
721
|
+
return { document: summarizeDocument(doc) };
|
|
722
|
+
}, "update_document")
|
|
723
|
+
);
|
|
724
|
+
server.registerTool(
|
|
725
|
+
deleteDocumentContract.name,
|
|
726
|
+
{
|
|
727
|
+
title: deleteDocumentContract.title,
|
|
728
|
+
description: deleteDocumentContract.description,
|
|
729
|
+
inputSchema: deleteDocumentContract.inputSchema
|
|
730
|
+
},
|
|
731
|
+
async (args) => run(async () => {
|
|
732
|
+
return await api.deleteDocument(args.document_id);
|
|
733
|
+
}, "delete_document")
|
|
734
|
+
);
|
|
735
|
+
server.registerTool(
|
|
736
|
+
listDocumentVersionsContract.name,
|
|
737
|
+
{
|
|
738
|
+
title: listDocumentVersionsContract.title,
|
|
739
|
+
description: listDocumentVersionsContract.description,
|
|
740
|
+
inputSchema: listDocumentVersionsContract.inputSchema
|
|
741
|
+
},
|
|
742
|
+
async (args) => run(async () => {
|
|
743
|
+
const list = await api.listDocumentVersions(args.document_id);
|
|
744
|
+
return { versions: list.data };
|
|
745
|
+
}, "list_document_versions")
|
|
746
|
+
);
|
|
747
|
+
server.registerTool(
|
|
748
|
+
getDocumentVersionContract.name,
|
|
749
|
+
{
|
|
750
|
+
title: getDocumentVersionContract.title,
|
|
751
|
+
description: getDocumentVersionContract.description,
|
|
752
|
+
inputSchema: getDocumentVersionContract.inputSchema
|
|
753
|
+
},
|
|
754
|
+
async (args) => run(
|
|
755
|
+
() => api.getDocumentVersion(args.document_id, args.version_id),
|
|
756
|
+
"get_document_version"
|
|
757
|
+
)
|
|
758
|
+
);
|
|
759
|
+
server.registerTool(
|
|
760
|
+
addDocumentVersionContract.name,
|
|
761
|
+
{
|
|
762
|
+
title: addDocumentVersionContract.title,
|
|
763
|
+
description: addDocumentVersionContract.description,
|
|
764
|
+
inputSchema: addDocumentVersionContract.inputSchema
|
|
765
|
+
},
|
|
766
|
+
async (args) => run(async () => {
|
|
767
|
+
const v = await api.addDocumentVersion(args.document_id, {
|
|
768
|
+
source_url: args.source_url
|
|
769
|
+
});
|
|
770
|
+
return { version: v };
|
|
771
|
+
}, "add_document_version")
|
|
772
|
+
);
|
|
773
|
+
server.registerTool(
|
|
774
|
+
promoteDocumentVersionContract.name,
|
|
775
|
+
{
|
|
776
|
+
title: promoteDocumentVersionContract.title,
|
|
777
|
+
description: promoteDocumentVersionContract.description,
|
|
778
|
+
inputSchema: promoteDocumentVersionContract.inputSchema
|
|
779
|
+
},
|
|
780
|
+
async (args) => run(async () => {
|
|
781
|
+
const v = await api.promoteDocumentVersion(
|
|
782
|
+
args.document_id,
|
|
783
|
+
args.version_id
|
|
784
|
+
);
|
|
785
|
+
return { version: v };
|
|
786
|
+
}, "promote_document_version")
|
|
787
|
+
);
|
|
788
|
+
server.registerTool(
|
|
789
|
+
listFoldersContract.name,
|
|
790
|
+
{
|
|
791
|
+
title: listFoldersContract.title,
|
|
792
|
+
description: listFoldersContract.description,
|
|
793
|
+
inputSchema: listFoldersContract.inputSchema
|
|
794
|
+
},
|
|
795
|
+
async (args) => run(async () => {
|
|
796
|
+
const list = await api.listFolders(args);
|
|
797
|
+
return { folders: list.data, next_cursor: list.next_cursor };
|
|
798
|
+
}, "list_folders")
|
|
799
|
+
);
|
|
800
|
+
server.registerTool(
|
|
801
|
+
getFolderContract.name,
|
|
802
|
+
{
|
|
803
|
+
title: getFolderContract.title,
|
|
804
|
+
description: getFolderContract.description,
|
|
805
|
+
inputSchema: getFolderContract.inputSchema
|
|
806
|
+
},
|
|
807
|
+
async (args) => run(() => api.getFolder(args.folder_id), "get_folder")
|
|
808
|
+
);
|
|
809
|
+
server.registerTool(
|
|
810
|
+
createFolderContract.name,
|
|
811
|
+
{
|
|
812
|
+
title: createFolderContract.title,
|
|
813
|
+
description: createFolderContract.description,
|
|
814
|
+
inputSchema: createFolderContract.inputSchema
|
|
815
|
+
},
|
|
816
|
+
async (args) => run(async () => {
|
|
817
|
+
const f = await api.createFolder(args);
|
|
818
|
+
return { folder: f };
|
|
819
|
+
}, "create_folder")
|
|
820
|
+
);
|
|
821
|
+
server.registerTool(
|
|
822
|
+
updateFolderContract.name,
|
|
823
|
+
{
|
|
824
|
+
title: updateFolderContract.title,
|
|
825
|
+
description: updateFolderContract.description,
|
|
826
|
+
inputSchema: updateFolderContract.inputSchema
|
|
827
|
+
},
|
|
828
|
+
async (args) => run(async () => {
|
|
829
|
+
const body = {};
|
|
830
|
+
if (args.name !== void 0) body.name = args.name;
|
|
831
|
+
if (args.icon !== void 0) body.icon = args.icon;
|
|
832
|
+
if (args.color !== void 0) body.color = args.color;
|
|
833
|
+
if (Object.keys(body).length === 0) {
|
|
834
|
+
throw new Error("Provide at least one of `name`, `icon`, `color`.");
|
|
835
|
+
}
|
|
836
|
+
const f = await api.updateFolder(args.folder_id, body);
|
|
837
|
+
return { folder: f };
|
|
838
|
+
}, "update_folder")
|
|
839
|
+
);
|
|
840
|
+
server.registerTool(
|
|
841
|
+
deleteFolderContract.name,
|
|
842
|
+
{
|
|
843
|
+
title: deleteFolderContract.title,
|
|
844
|
+
description: deleteFolderContract.description,
|
|
845
|
+
inputSchema: deleteFolderContract.inputSchema
|
|
846
|
+
},
|
|
847
|
+
async (args) => run(async () => {
|
|
848
|
+
return await api.deleteFolder(args.folder_id, {
|
|
849
|
+
cascade: args.cascade
|
|
850
|
+
});
|
|
851
|
+
}, "delete_folder")
|
|
852
|
+
);
|
|
853
|
+
server.registerTool(
|
|
854
|
+
moveFolderContract.name,
|
|
855
|
+
{
|
|
856
|
+
title: moveFolderContract.title,
|
|
857
|
+
description: moveFolderContract.description,
|
|
858
|
+
inputSchema: moveFolderContract.inputSchema
|
|
859
|
+
},
|
|
860
|
+
async (args) => run(async () => {
|
|
861
|
+
const f = await api.moveFolder(args.folder_id, {
|
|
862
|
+
parent_id: args.parent_id
|
|
863
|
+
});
|
|
864
|
+
return { folder: f };
|
|
865
|
+
}, "move_folder")
|
|
866
|
+
);
|
|
867
|
+
server.registerTool(
|
|
868
|
+
getLinkContract.name,
|
|
869
|
+
{
|
|
870
|
+
title: getLinkContract.title,
|
|
871
|
+
description: getLinkContract.description,
|
|
872
|
+
inputSchema: getLinkContract.inputSchema
|
|
873
|
+
},
|
|
874
|
+
async (args) => run(async () => {
|
|
875
|
+
const link = await api.getLink(args.link_id);
|
|
876
|
+
return { link: summarizeLink(link) };
|
|
877
|
+
}, "get_link")
|
|
878
|
+
);
|
|
879
|
+
server.registerTool(
|
|
880
|
+
updateLinkContract.name,
|
|
881
|
+
{
|
|
882
|
+
title: updateLinkContract.title,
|
|
883
|
+
description: updateLinkContract.description,
|
|
884
|
+
inputSchema: updateLinkContract.inputSchema
|
|
885
|
+
},
|
|
886
|
+
async (args) => run(async () => {
|
|
887
|
+
const { link_id, ...rest } = args;
|
|
888
|
+
if (Object.keys(rest).length === 0) {
|
|
889
|
+
throw new Error("Provide at least one field to update.");
|
|
890
|
+
}
|
|
891
|
+
const link = await api.updateLink(link_id, rest);
|
|
892
|
+
return { link: summarizeLink(link) };
|
|
893
|
+
}, "update_link")
|
|
894
|
+
);
|
|
895
|
+
server.registerTool(
|
|
896
|
+
deleteLinkContract.name,
|
|
897
|
+
{
|
|
898
|
+
title: deleteLinkContract.title,
|
|
899
|
+
description: deleteLinkContract.description,
|
|
900
|
+
inputSchema: deleteLinkContract.inputSchema
|
|
901
|
+
},
|
|
902
|
+
async (args) => run(async () => {
|
|
903
|
+
return await api.deleteLink(args.link_id);
|
|
904
|
+
}, "delete_link")
|
|
905
|
+
);
|
|
906
|
+
server.registerTool(
|
|
907
|
+
updateDataroomContract.name,
|
|
908
|
+
{
|
|
909
|
+
title: updateDataroomContract.title,
|
|
910
|
+
description: updateDataroomContract.description,
|
|
911
|
+
inputSchema: updateDataroomContract.inputSchema
|
|
912
|
+
},
|
|
913
|
+
async (args) => run(async () => {
|
|
914
|
+
const { dataroom_id, ...rest } = args;
|
|
915
|
+
if (Object.keys(rest).length === 0) {
|
|
916
|
+
throw new Error("Provide at least one field to update.");
|
|
917
|
+
}
|
|
918
|
+
const dr = await api.updateDataroom(dataroom_id, rest);
|
|
919
|
+
return { dataroom: dr };
|
|
920
|
+
}, "update_dataroom")
|
|
921
|
+
);
|
|
922
|
+
server.registerTool(
|
|
923
|
+
deleteDataroomContract.name,
|
|
924
|
+
{
|
|
925
|
+
title: deleteDataroomContract.title,
|
|
926
|
+
description: deleteDataroomContract.description,
|
|
927
|
+
inputSchema: deleteDataroomContract.inputSchema
|
|
928
|
+
},
|
|
929
|
+
async (args) => run(async () => {
|
|
930
|
+
return await api.deleteDataroom(args.dataroom_id);
|
|
931
|
+
}, "delete_dataroom")
|
|
932
|
+
);
|
|
933
|
+
server.registerTool(
|
|
934
|
+
attachDataroomDocumentContract.name,
|
|
935
|
+
{
|
|
936
|
+
title: attachDataroomDocumentContract.title,
|
|
937
|
+
description: attachDataroomDocumentContract.description,
|
|
938
|
+
inputSchema: attachDataroomDocumentContract.inputSchema
|
|
939
|
+
},
|
|
940
|
+
async (args) => run(async () => {
|
|
941
|
+
const item = await api.attachDataroomDocument(args.dataroom_id, {
|
|
942
|
+
document_id: args.document_id,
|
|
943
|
+
folder_id: args.folder_id
|
|
944
|
+
});
|
|
945
|
+
return { item };
|
|
946
|
+
}, "attach_dataroom_document")
|
|
947
|
+
);
|
|
948
|
+
server.registerTool(
|
|
949
|
+
listDataroomFoldersContract.name,
|
|
950
|
+
{
|
|
951
|
+
title: listDataroomFoldersContract.title,
|
|
952
|
+
description: listDataroomFoldersContract.description,
|
|
953
|
+
inputSchema: listDataroomFoldersContract.inputSchema
|
|
954
|
+
},
|
|
955
|
+
async (args) => run(async () => {
|
|
956
|
+
const list = await api.listDataroomFolders(args.dataroom_id, {
|
|
957
|
+
parent_id: args.parent_id,
|
|
958
|
+
limit: args.limit,
|
|
959
|
+
cursor: args.cursor
|
|
960
|
+
});
|
|
961
|
+
return { folders: list.data, next_cursor: list.next_cursor };
|
|
962
|
+
}, "list_dataroom_folders")
|
|
963
|
+
);
|
|
964
|
+
server.registerTool(
|
|
965
|
+
getDataroomFolderContract.name,
|
|
966
|
+
{
|
|
967
|
+
title: getDataroomFolderContract.title,
|
|
968
|
+
description: getDataroomFolderContract.description,
|
|
969
|
+
inputSchema: getDataroomFolderContract.inputSchema
|
|
970
|
+
},
|
|
971
|
+
async (args) => run(
|
|
972
|
+
() => api.getDataroomFolder(args.dataroom_id, args.folder_id),
|
|
973
|
+
"get_dataroom_folder"
|
|
974
|
+
)
|
|
975
|
+
);
|
|
976
|
+
server.registerTool(
|
|
977
|
+
createDataroomFolderContract.name,
|
|
978
|
+
{
|
|
979
|
+
title: createDataroomFolderContract.title,
|
|
980
|
+
description: createDataroomFolderContract.description,
|
|
981
|
+
inputSchema: createDataroomFolderContract.inputSchema
|
|
982
|
+
},
|
|
983
|
+
async (args) => run(async () => {
|
|
984
|
+
const { dataroom_id, ...body } = args;
|
|
985
|
+
const f = await api.createDataroomFolder(dataroom_id, body);
|
|
986
|
+
return { folder: f };
|
|
987
|
+
}, "create_dataroom_folder")
|
|
988
|
+
);
|
|
989
|
+
server.registerTool(
|
|
990
|
+
updateDataroomFolderContract.name,
|
|
991
|
+
{
|
|
992
|
+
title: updateDataroomFolderContract.title,
|
|
993
|
+
description: updateDataroomFolderContract.description,
|
|
994
|
+
inputSchema: updateDataroomFolderContract.inputSchema
|
|
995
|
+
},
|
|
996
|
+
async (args) => run(async () => {
|
|
997
|
+
const body = {};
|
|
998
|
+
if (args.name !== void 0) body.name = args.name;
|
|
999
|
+
if (args.icon !== void 0) body.icon = args.icon;
|
|
1000
|
+
if (args.color !== void 0) body.color = args.color;
|
|
1001
|
+
if (Object.keys(body).length === 0) {
|
|
1002
|
+
throw new Error("Provide at least one of `name`, `icon`, `color`.");
|
|
1003
|
+
}
|
|
1004
|
+
const f = await api.updateDataroomFolder(
|
|
1005
|
+
args.dataroom_id,
|
|
1006
|
+
args.folder_id,
|
|
1007
|
+
body
|
|
1008
|
+
);
|
|
1009
|
+
return { folder: f };
|
|
1010
|
+
}, "update_dataroom_folder")
|
|
1011
|
+
);
|
|
1012
|
+
server.registerTool(
|
|
1013
|
+
deleteDataroomFolderContract.name,
|
|
1014
|
+
{
|
|
1015
|
+
title: deleteDataroomFolderContract.title,
|
|
1016
|
+
description: deleteDataroomFolderContract.description,
|
|
1017
|
+
inputSchema: deleteDataroomFolderContract.inputSchema
|
|
1018
|
+
},
|
|
1019
|
+
async (args) => run(async () => {
|
|
1020
|
+
return await api.deleteDataroomFolder(
|
|
1021
|
+
args.dataroom_id,
|
|
1022
|
+
args.folder_id,
|
|
1023
|
+
{ cascade: args.cascade }
|
|
1024
|
+
);
|
|
1025
|
+
}, "delete_dataroom_folder")
|
|
1026
|
+
);
|
|
1027
|
+
server.registerTool(
|
|
1028
|
+
moveDataroomFolderContract.name,
|
|
1029
|
+
{
|
|
1030
|
+
title: moveDataroomFolderContract.title,
|
|
1031
|
+
description: moveDataroomFolderContract.description,
|
|
1032
|
+
inputSchema: moveDataroomFolderContract.inputSchema
|
|
1033
|
+
},
|
|
1034
|
+
async (args) => run(async () => {
|
|
1035
|
+
const f = await api.moveDataroomFolder(
|
|
1036
|
+
args.dataroom_id,
|
|
1037
|
+
args.folder_id,
|
|
1038
|
+
{ parent_id: args.parent_id }
|
|
1039
|
+
);
|
|
1040
|
+
return { folder: f };
|
|
1041
|
+
}, "move_dataroom_folder")
|
|
1042
|
+
);
|
|
1043
|
+
server.registerTool(
|
|
1044
|
+
getVisitorContract.name,
|
|
1045
|
+
{
|
|
1046
|
+
title: getVisitorContract.title,
|
|
1047
|
+
description: getVisitorContract.description,
|
|
1048
|
+
inputSchema: getVisitorContract.inputSchema
|
|
1049
|
+
},
|
|
1050
|
+
async (args) => run(() => api.getVisitor(args.visitor_id), "get_visitor")
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// src/index.ts
|
|
1055
|
+
var SERVER_INFO = {
|
|
1056
|
+
name: "papermark-mcp",
|
|
1057
|
+
version: "0.1.0"
|
|
1058
|
+
};
|
|
1059
|
+
async function main() {
|
|
1060
|
+
const server = new McpServer(SERVER_INFO, { capabilities: { tools: {} } });
|
|
1061
|
+
registerTools(server);
|
|
1062
|
+
const transport = new StdioServerTransport();
|
|
1063
|
+
await server.connect(transport);
|
|
1064
|
+
}
|
|
1065
|
+
main().catch((err) => {
|
|
1066
|
+
process.stderr.write(
|
|
1067
|
+
`[papermark-mcp] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}
|
|
1068
|
+
`
|
|
1069
|
+
);
|
|
1070
|
+
process.exit(1);
|
|
1071
|
+
});
|
|
1072
|
+
//# sourceMappingURL=index.js.map
|