@papermark/mcp-server 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SHARED_TOOL_OUTPUT_SCHEMAS,
4
+ addDataroomGroupMembersContract,
4
5
  addDocumentVersionContract,
5
6
  attachDataroomDocumentContract,
6
7
  createDataroomContract,
7
8
  createDataroomFolderContract,
9
+ createDataroomGroupContract,
8
10
  createFolderContract,
9
11
  createLinkContract,
10
12
  deleteDataroomContract,
11
13
  deleteDataroomFolderContract,
14
+ deleteDataroomGroupContract,
12
15
  deleteDocumentContract,
13
16
  deleteFolderContract,
14
17
  deleteLinkContract,
@@ -17,16 +20,21 @@ import {
17
20
  getDataroomAnalyticsContract,
18
21
  getDataroomContract,
19
22
  getDataroomFolderContract,
23
+ getDataroomGroupContract,
24
+ getDataroomGroupPermissionsContract,
20
25
  getDocumentAnalyticsContract,
21
26
  getDocumentContract,
22
27
  getDocumentVersionContract,
23
28
  getFolderContract,
24
29
  getLinkAnalyticsContract,
25
30
  getLinkContract,
31
+ getLinkPermissionsContract,
26
32
  getViewAnalyticsContract,
27
33
  getVisitorContract,
28
34
  listDataroomDocumentsContract,
29
35
  listDataroomFoldersContract,
36
+ listDataroomGroupMembersContract,
37
+ listDataroomGroupsContract,
30
38
  listDataroomsContract,
31
39
  listDocumentVersionsContract,
32
40
  listDocumentsContract,
@@ -39,14 +47,18 @@ import {
39
47
  moveDataroomFolderContract,
40
48
  moveFolderContract,
41
49
  promoteDocumentVersionContract,
50
+ removeDataroomGroupMemberContract,
42
51
  searchDataroomsContract,
43
52
  searchDocumentsContract,
53
+ setDataroomGroupPermissionsContract,
54
+ setLinkPermissionsContract,
44
55
  updateDataroomContract,
45
56
  updateDataroomFolderContract,
57
+ updateDataroomGroupContract,
46
58
  updateDocumentContract,
47
59
  updateFolderContract,
48
60
  updateLinkContract
49
- } from "./chunk-DA26JZA2.js";
61
+ } from "./chunk-IKMPOGEB.js";
50
62
 
51
63
  // src/index.ts
52
64
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -249,6 +261,14 @@ var api = {
249
261
  createLink: (body, token) => request("/v1/links", { method: "POST", body, token }),
250
262
  updateLink: (id, body, token) => request(`/v1/links/${id}`, { method: "PATCH", body, token }),
251
263
  deleteLink: (id, token) => request(`/v1/links/${id}`, { method: "DELETE", token }),
264
+ getLinkPermissions: (id, token) => request(`/v1/links/${id}/permissions`, { token }),
265
+ // Full-replace semantics: the payload is the complete desired state;
266
+ // items not listed lose their override.
267
+ setLinkPermissions: (id, body, token) => request(`/v1/links/${id}/permissions`, {
268
+ method: "PUT",
269
+ body,
270
+ token
271
+ }),
252
272
  listViews: (linkId, query, token) => request(`/v1/links/${linkId}/views`, { query, token }),
253
273
  // Datarooms
254
274
  listDatarooms: (query, token) => request("/v1/datarooms", { query, token }),
@@ -299,6 +319,47 @@ var api = {
299
319
  body,
300
320
  token
301
321
  }),
322
+ // Dataroom groups
323
+ listDataroomGroups: (id, query, token) => request(`/v1/datarooms/${id}/groups`, { query, token }),
324
+ createDataroomGroup: (id, body, token) => request(`/v1/datarooms/${id}/groups`, {
325
+ method: "POST",
326
+ body,
327
+ token
328
+ }),
329
+ getDataroomGroup: (id, gid, token) => request(`/v1/datarooms/${id}/groups/${gid}`, { token }),
330
+ updateDataroomGroup: (id, gid, body, token) => request(`/v1/datarooms/${id}/groups/${gid}`, {
331
+ method: "PATCH",
332
+ body,
333
+ token
334
+ }),
335
+ // Also deletes every share link pointing at the group (matching the
336
+ // dashboard).
337
+ deleteDataroomGroup: (id, gid, token) => request(`/v1/datarooms/${id}/groups/${gid}`, {
338
+ method: "DELETE",
339
+ token
340
+ }),
341
+ listDataroomGroupMembers: (id, gid, query, token) => request(
342
+ `/v1/datarooms/${id}/groups/${gid}/members`,
343
+ { query, token }
344
+ ),
345
+ addDataroomGroupMembers: (id, gid, body, token) => request(
346
+ `/v1/datarooms/${id}/groups/${gid}/members`,
347
+ { method: "POST", body, token }
348
+ ),
349
+ removeDataroomGroupMember: (id, gid, mid, token) => request(
350
+ `/v1/datarooms/${id}/groups/${gid}/members/${mid}`,
351
+ { method: "DELETE", token }
352
+ ),
353
+ listDataroomGroupPermissions: (id, gid, query, token) => request(
354
+ `/v1/datarooms/${id}/groups/${gid}/permissions`,
355
+ { query, token }
356
+ ),
357
+ // Upsert-delta semantics: entries sent are upserted, entries omitted keep
358
+ // their current state; ancestor folders of visible items are auto-shown.
359
+ setDataroomGroupPermissions: (id, gid, body, token) => request(
360
+ `/v1/datarooms/${id}/groups/${gid}/permissions`,
361
+ { method: "PUT", body, token }
362
+ ),
302
363
  // Visitors
303
364
  listVisitors: (query, token) => request("/v1/visitors", { query, token }),
304
365
  getVisitor: (id, token) => request(`/v1/visitors/${id}`, { token }),
@@ -359,6 +420,18 @@ var TOOL_ANNOTATIONS = {
359
420
  update_dataroom_folder: destructiveTool(),
360
421
  delete_dataroom_folder: destructiveTool(),
361
422
  move_dataroom_folder: destructiveTool(),
423
+ list_dataroom_groups: readTool(),
424
+ get_dataroom_group: readTool(),
425
+ create_dataroom_group: writeTool(),
426
+ update_dataroom_group: destructiveTool(),
427
+ delete_dataroom_group: destructiveTool(),
428
+ list_dataroom_group_members: readTool(),
429
+ add_dataroom_group_members: writeTool(),
430
+ remove_dataroom_group_member: destructiveTool(),
431
+ get_dataroom_group_permissions: readTool(),
432
+ set_dataroom_group_permissions: destructiveTool(),
433
+ get_link_permissions: readTool(),
434
+ set_link_permissions: destructiveTool(),
362
435
  get_visitor: readTool()
363
436
  };
364
437
  var TOOL_OUTPUT_SCHEMAS = {
@@ -498,14 +571,17 @@ function registerTools(server) {
498
571
  "upload_document",
499
572
  {
500
573
  title: "Upload a document",
501
- description: `Upload a document to Papermark from a local file path OR a public HTTPS URL.
574
+ description: `Add a document to Papermark from a local file path, a public HTTPS URL to fetch, OR a non-file source (an external link / public Notion page).
502
575
 
503
576
  WORKFLOW:
504
- (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.
505
- (2) Confirm the target \`name\` if the user wants something other than the filename.
577
+ (1) Resolve the source \u2014 exactly one of:
578
+ \u2022 \`file_path\` (local filesystem \u2014 stdio mode only). 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.
579
+ \u2022 \`source_url\` (public HTTPS) \u2014 the server fetches and stores the file.
580
+ \u2022 \`type\` (\`link\` or \`notion\`) + \`external_url\` \u2014 stores a document that points at the URL without downloading it. Use \`notion\` for a publicly-accessible Notion page, \`link\` for any other external page.
581
+ (2) Confirm the target \`name\` if the user wants something other than the filename / URL.
506
582
  (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.
507
583
 
508
- Don't upload any file the user didn't explicitly point at. Requires scope \`documents.write\`.`,
584
+ Don't add any source the user didn't explicitly point at. Requires scope \`documents.write\`.`,
509
585
  inputSchema: {
510
586
  file_path: z.string().optional().describe(
511
587
  "Absolute local path \u2014 only works when the MCP server runs on the same machine as the file (stdio mode)"
@@ -513,9 +589,17 @@ Don't upload any file the user didn't explicitly point at. Requires scope \`docu
513
589
  source_url: z.string().url().refine((s) => s.startsWith("https://"), {
514
590
  message: "source_url must use https:// (http is rejected by the API)"
515
591
  }).optional().describe(
516
- "Public HTTPS URL the server should fetch (alternative to file_path)"
592
+ "Public HTTPS URL the server should fetch and store (alternative to file_path)"
593
+ ),
594
+ type: z.enum(["link", "notion"]).optional().describe(
595
+ "Create a non-file document from `external_url`: `link` (any external page) or `notion` (a public Notion page). Omit for file uploads via file_path/source_url."
596
+ ),
597
+ external_url: z.string().url().refine((s) => s.startsWith("https://"), {
598
+ message: "external_url must use https:// (http is rejected by the API)"
599
+ }).optional().describe(
600
+ "Target URL stored as-is (not downloaded) for `type` link/notion documents. Required when `type` is set."
517
601
  ),
518
- name: z.string().optional().describe("Display name; defaults to the filename"),
602
+ name: z.string().optional().describe("Display name; defaults to the filename or URL"),
519
603
  content_type: z.string().optional().describe("MIME type; inferred from extension when omitted"),
520
604
  folder_id: z.string().optional().describe(
521
605
  "Destination folder id (created beforehand via `create_folder`). Omit for the team-library root."
@@ -524,6 +608,31 @@ Don't upload any file the user didn't explicitly point at. Requires scope \`docu
524
608
  }
525
609
  },
526
610
  async (args) => run(async () => {
611
+ if (args.type) {
612
+ if (!args.external_url) {
613
+ throw new Error(
614
+ `external_url is required when type is "${args.type}".`
615
+ );
616
+ }
617
+ if (args.file_path || args.source_url) {
618
+ throw new Error(
619
+ "For type link/notion, provide external_url only (not file_path or source_url)."
620
+ );
621
+ }
622
+ const doc2 = await api.createDocument({
623
+ name: args.name ?? args.external_url,
624
+ type: args.type,
625
+ external_url: args.external_url,
626
+ folder_id: args.folder_id,
627
+ create_link: args.create_link
628
+ });
629
+ return { document: doc2 };
630
+ }
631
+ if (args.external_url) {
632
+ throw new Error(
633
+ 'external_url requires type to be "link" or "notion".'
634
+ );
635
+ }
527
636
  if (!args.file_path && !args.source_url) {
528
637
  throw new Error(
529
638
  "Provide either file_path (local) or source_url (remote)."
@@ -847,8 +956,14 @@ Don't upload any file the user didn't explicitly point at. Requires scope \`docu
847
956
  inputSchema: addDocumentVersionContract.inputSchema
848
957
  },
849
958
  async (args) => run(async () => {
959
+ if (!!args.source_url === !!args.external_url) {
960
+ throw new Error(
961
+ "Provide exactly one of source_url (file documents) or external_url (link/notion documents)."
962
+ );
963
+ }
850
964
  const v = await api.addDocumentVersion(args.document_id, {
851
- source_url: args.source_url
965
+ source_url: args.source_url,
966
+ external_url: args.external_url
852
967
  });
853
968
  return { version: v };
854
969
  }, "add_document_version")
@@ -1153,6 +1268,186 @@ Don't upload any file the user didn't explicitly point at. Requires scope \`docu
1153
1268
  return { folder: f };
1154
1269
  }, "move_dataroom_folder")
1155
1270
  );
1271
+ server.registerTool(
1272
+ listDataroomGroupsContract.name,
1273
+ {
1274
+ title: listDataroomGroupsContract.title,
1275
+ description: listDataroomGroupsContract.description,
1276
+ inputSchema: listDataroomGroupsContract.inputSchema
1277
+ },
1278
+ async (args) => run(async () => {
1279
+ const list = await api.listDataroomGroups(args.dataroom_id, {
1280
+ limit: args.limit,
1281
+ cursor: args.cursor
1282
+ });
1283
+ return { groups: list.data, next_cursor: list.next_cursor };
1284
+ }, "list_dataroom_groups")
1285
+ );
1286
+ server.registerTool(
1287
+ getDataroomGroupContract.name,
1288
+ {
1289
+ title: getDataroomGroupContract.title,
1290
+ description: getDataroomGroupContract.description,
1291
+ inputSchema: getDataroomGroupContract.inputSchema
1292
+ },
1293
+ async (args) => run(
1294
+ () => api.getDataroomGroup(args.dataroom_id, args.group_id),
1295
+ "get_dataroom_group"
1296
+ )
1297
+ );
1298
+ server.registerTool(
1299
+ createDataroomGroupContract.name,
1300
+ {
1301
+ title: createDataroomGroupContract.title,
1302
+ description: createDataroomGroupContract.description,
1303
+ inputSchema: createDataroomGroupContract.inputSchema
1304
+ },
1305
+ async (args) => run(async () => {
1306
+ const { dataroom_id, ...body } = args;
1307
+ const group = await api.createDataroomGroup(dataroom_id, body);
1308
+ return { group };
1309
+ }, "create_dataroom_group")
1310
+ );
1311
+ server.registerTool(
1312
+ updateDataroomGroupContract.name,
1313
+ {
1314
+ title: updateDataroomGroupContract.title,
1315
+ description: updateDataroomGroupContract.description,
1316
+ inputSchema: updateDataroomGroupContract.inputSchema
1317
+ },
1318
+ async (args) => run(async () => {
1319
+ const { dataroom_id, group_id, ...body } = args;
1320
+ if (Object.keys(body).length === 0) {
1321
+ throw new Error(
1322
+ "Provide at least one of `name`, `allow_all`, `domains`."
1323
+ );
1324
+ }
1325
+ const group = await api.updateDataroomGroup(
1326
+ dataroom_id,
1327
+ group_id,
1328
+ body
1329
+ );
1330
+ return { group };
1331
+ }, "update_dataroom_group")
1332
+ );
1333
+ server.registerTool(
1334
+ deleteDataroomGroupContract.name,
1335
+ {
1336
+ title: deleteDataroomGroupContract.title,
1337
+ description: deleteDataroomGroupContract.description,
1338
+ inputSchema: deleteDataroomGroupContract.inputSchema
1339
+ },
1340
+ async (args) => run(
1341
+ () => api.deleteDataroomGroup(args.dataroom_id, args.group_id),
1342
+ "delete_dataroom_group"
1343
+ )
1344
+ );
1345
+ server.registerTool(
1346
+ listDataroomGroupMembersContract.name,
1347
+ {
1348
+ title: listDataroomGroupMembersContract.title,
1349
+ description: listDataroomGroupMembersContract.description,
1350
+ inputSchema: listDataroomGroupMembersContract.inputSchema
1351
+ },
1352
+ async (args) => run(async () => {
1353
+ const list = await api.listDataroomGroupMembers(
1354
+ args.dataroom_id,
1355
+ args.group_id,
1356
+ { limit: args.limit, cursor: args.cursor }
1357
+ );
1358
+ return { members: list.data, next_cursor: list.next_cursor };
1359
+ }, "list_dataroom_group_members")
1360
+ );
1361
+ server.registerTool(
1362
+ addDataroomGroupMembersContract.name,
1363
+ {
1364
+ title: addDataroomGroupMembersContract.title,
1365
+ description: addDataroomGroupMembersContract.description,
1366
+ inputSchema: addDataroomGroupMembersContract.inputSchema
1367
+ },
1368
+ async (args) => run(async () => {
1369
+ const list = await api.addDataroomGroupMembers(
1370
+ args.dataroom_id,
1371
+ args.group_id,
1372
+ { emails: args.emails }
1373
+ );
1374
+ return { members: list.data, next_cursor: list.next_cursor };
1375
+ }, "add_dataroom_group_members")
1376
+ );
1377
+ server.registerTool(
1378
+ removeDataroomGroupMemberContract.name,
1379
+ {
1380
+ title: removeDataroomGroupMemberContract.title,
1381
+ description: removeDataroomGroupMemberContract.description,
1382
+ inputSchema: removeDataroomGroupMemberContract.inputSchema
1383
+ },
1384
+ async (args) => run(
1385
+ () => api.removeDataroomGroupMember(
1386
+ args.dataroom_id,
1387
+ args.group_id,
1388
+ args.member_id
1389
+ ),
1390
+ "remove_dataroom_group_member"
1391
+ )
1392
+ );
1393
+ server.registerTool(
1394
+ getDataroomGroupPermissionsContract.name,
1395
+ {
1396
+ title: getDataroomGroupPermissionsContract.title,
1397
+ description: getDataroomGroupPermissionsContract.description,
1398
+ inputSchema: getDataroomGroupPermissionsContract.inputSchema
1399
+ },
1400
+ async (args) => run(async () => {
1401
+ const list = await api.listDataroomGroupPermissions(
1402
+ args.dataroom_id,
1403
+ args.group_id,
1404
+ { limit: args.limit, cursor: args.cursor }
1405
+ );
1406
+ return { permissions: list.data, next_cursor: list.next_cursor };
1407
+ }, "get_dataroom_group_permissions")
1408
+ );
1409
+ server.registerTool(
1410
+ setDataroomGroupPermissionsContract.name,
1411
+ {
1412
+ title: setDataroomGroupPermissionsContract.title,
1413
+ description: setDataroomGroupPermissionsContract.description,
1414
+ inputSchema: setDataroomGroupPermissionsContract.inputSchema
1415
+ },
1416
+ async (args) => run(async () => {
1417
+ const res = await api.setDataroomGroupPermissions(
1418
+ args.dataroom_id,
1419
+ args.group_id,
1420
+ { permissions: args.permissions }
1421
+ );
1422
+ return { permissions: res.data };
1423
+ }, "set_dataroom_group_permissions")
1424
+ );
1425
+ server.registerTool(
1426
+ getLinkPermissionsContract.name,
1427
+ {
1428
+ title: getLinkPermissionsContract.title,
1429
+ description: getLinkPermissionsContract.description,
1430
+ inputSchema: getLinkPermissionsContract.inputSchema
1431
+ },
1432
+ async (args) => run(async () => {
1433
+ const res = await api.getLinkPermissions(args.link_id);
1434
+ return { permissions: res.data };
1435
+ }, "get_link_permissions")
1436
+ );
1437
+ server.registerTool(
1438
+ setLinkPermissionsContract.name,
1439
+ {
1440
+ title: setLinkPermissionsContract.title,
1441
+ description: setLinkPermissionsContract.description,
1442
+ inputSchema: setLinkPermissionsContract.inputSchema
1443
+ },
1444
+ async (args) => run(async () => {
1445
+ const res = await api.setLinkPermissions(args.link_id, {
1446
+ permissions: args.permissions
1447
+ });
1448
+ return { permissions: res.data };
1449
+ }, "set_link_permissions")
1450
+ );
1156
1451
  server.registerTool(
1157
1452
  getVisitorContract.name,
1158
1453
  {