@hiai-gg/docsmint 0.9.0 → 0.9.4
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 +28 -25
- package/dist/backend/index.js +1 -1
- package/dist/client.d.ts +8 -1
- package/dist/client.js +9 -0
- package/dist/mcp-cli.js +187 -64
- package/dist/mcp-server.js +198 -65
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
- package/packages/cli/src/index.ts +1 -1
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -14,32 +14,36 @@ Apache-2.0 application on your own infrastructure.
|
|
|
14
14
|
[](https://github.com/hiai-gg/docsmint/releases)
|
|
15
15
|
[](https://www.npmjs.com/package/@hiai-gg/docsmint)
|
|
16
16
|
[](https://hub.docker.com/r/vgalibov/docsmint)
|
|
17
|
-
[](https://github.com/hiai-gg/docsmint/stargazers)
|
|
18
17
|
[](https://github.com/hiai-gg/docsmint/actions/workflows/ci.yml)
|
|
18
|
+
|
|
19
|
+
[](https://glama.ai/mcp/servers/HiAi-gg/docsmint)
|
|
20
|
+
[](https://lobehub.com/mcp/hiai-gg-docsmint)
|
|
21
|
+
[](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.HiAi-gg%2Fdocsmint/versions/latest)
|
|
22
|
+
[](https://docsmint.com/mcp/connect?source=github_mcp)
|
|
23
|
+
|
|
19
24
|
[](https://bun.sh)
|
|
20
25
|
[](https://www.typescriptlang.org)
|
|
21
26
|
[](https://svelte.dev)
|
|
22
27
|
[](https://elysiajs.com)
|
|
23
28
|
[](https://tailwindcss.com)
|
|
24
29
|
[](https://orm.drizzle.team)
|
|
30
|
+
[](https://github.com/hiai-gg/docsmint/stargazers)
|
|
25
31
|
[](CONTRIBUTING.md)
|
|
26
|
-
[](https://lobehub.com/mcp/hiai-gg-docsmint)
|
|
27
|
-
[](https://docsmint.com/mcp/connect?source=github_mcp)
|
|
28
|
-
[](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.HiAi-gg%2Fdocsmint/versions/latest)
|
|
29
32
|
|
|
30
33
|
<img width="1920" height="974" alt="DocsMint installable document workspace" src="https://github.com/user-attachments/assets/94701d01-a361-4ca1-b16d-de2a0c64d684" />
|
|
31
34
|
|
|
32
35
|
## Connect your AI agent
|
|
33
36
|
|
|
34
|
-
Connect DocsMint Cloud instantly or
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
Connect DocsMint Cloud instantly or run the self-hosted stdio bridge against
|
|
38
|
+
your own DocsMint API. Both paths give agents access to persistent knowledge;
|
|
39
|
+
the self-hosted bridge exposes 31 tools, 2 prompts, and 3 resources.
|
|
37
40
|
|
|
38
41
|
**Recommended: [DocsMint Cloud setup](https://docsmint.com/mcp/connect?source=github_mcp).**
|
|
39
42
|
No server installation is required. Sign up or log in, choose your workspace,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
and follow your client's connection instructions. OAuth-capable clients use
|
|
44
|
+
browser consent; API-key clients create an MCP/API credential in the authenticated
|
|
45
|
+
browser UI. Hosted MCP follows your plan and workspace permissions. Prefer
|
|
46
|
+
workspace-bound or category-scoped credentials.
|
|
43
47
|
|
|
44
48
|
The Cloud endpoint is `https://docsmint.com/mcp` (Streamable HTTP). OAuth-capable
|
|
45
49
|
clients discover the hosted resource and authorization-server metadata; current
|
|
@@ -53,9 +57,13 @@ management belongs to the signed-in browser session.
|
|
|
53
57
|
|
|
54
58
|
**Self-hosted alternative:** run [DocsMint with Docker](#quickstart), create an API
|
|
55
59
|
key in its browser UI, and configure `HIAI_DOCS_URL` and `HIAI_DOCS_API_KEY` for
|
|
56
|
-
`npx --yes --package @hiai-gg/docsmint docsmint-mcp`.
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
`npx --yes --package @hiai-gg/docsmint docsmint-mcp`. Install Bun 1.3.14 or
|
|
61
|
+
later to execute the published binary. The npm package is a stdio bridge to
|
|
62
|
+
your own API; it does not install the DocsMint application or Cloud OAuth server.
|
|
63
|
+
See the [MCP guide](https://github.com/HiAi-gg/docsmint/blob/main/packages/mcp-server/README.md)
|
|
64
|
+
for client configuration. The [Glama OSS Server listing](https://glama.ai/mcp/servers/HiAi-gg/docsmint)
|
|
65
|
+
describes this bridge; the hosted [DocsMint Cloud Connector](https://glama.ai/mcp/connectors/io.github.HiAi-gg/docsmint)
|
|
66
|
+
is a separate listing.
|
|
59
67
|
|
|
60
68
|
## Why DocsMint?
|
|
61
69
|
|
|
@@ -72,19 +80,14 @@ bridge to your own API, not a server installer or hosted OAuth server. See the
|
|
|
72
80
|
- **Choose how you run it.** Use [managed DocsMint](https://docsmint.com) or
|
|
73
81
|
self-host the application, database, search, queues, and files.
|
|
74
82
|
|
|
75
|
-
## What's new in 0.9.
|
|
83
|
+
## What's new in 0.9.4?
|
|
76
84
|
|
|
77
|
-
-
|
|
78
|
-
folder and category
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
expose the canonical `capabilityCatalog` for hosted contract checks.
|
|
82
|
-
- Reject category-scoped document creation when the selected folder belongs to
|
|
83
|
-
a different category.
|
|
84
|
-
- Keep category-list response types and Cloud connection guidance aligned with
|
|
85
|
-
the public API and supported setup flow.
|
|
85
|
+
- Expand the self-hosted MCP bridge to 31 tools, adding tag management,
|
|
86
|
+
folder and category updates, and document trash recovery or permanent purge.
|
|
87
|
+
- Keep workspace and category permissions enforced by the existing DocsMint API.
|
|
88
|
+
- Preserve the separate DocsMint Cloud Connector and the self-hosted API-key bridge.
|
|
86
89
|
|
|
87
|
-
This release adds no database migration. See the [release notes](https://github.com/HiAi-gg/docsmint/releases/tag/v0.9.
|
|
90
|
+
This release adds no database migration. See the [release notes](https://github.com/HiAi-gg/docsmint/releases/tag/v0.9.4)
|
|
88
91
|
and [changelog](https://github.com/HiAi-gg/docsmint/blob/main/CHANGELOG.md).
|
|
89
92
|
|
|
90
93
|
## Install with an AI agent
|
|
@@ -137,7 +140,7 @@ docker pull vgalibov/docsmint:web-latest
|
|
|
137
140
|
docker pull vgalibov/docsmint:caddy-latest
|
|
138
141
|
```
|
|
139
142
|
|
|
140
|
-
Use versioned tags `api-v0.9.
|
|
143
|
+
Use versioned tags `api-v0.9.4`, `web-v0.9.4`, and `caddy-v0.9.4` for
|
|
141
144
|
reproducible deploys. Caddy is the supporting reverse proxy with rate limiting;
|
|
142
145
|
it is separate from the API and web application. The quickstart still builds the Compose stack from this repository so PostgreSQL,
|
|
143
146
|
Redis, and SeaweedFS start together with the application.
|
package/dist/backend/index.js
CHANGED
|
@@ -238460,7 +238460,7 @@ var swaggerConfig = {
|
|
|
238460
238460
|
},
|
|
238461
238461
|
info: {
|
|
238462
238462
|
title: "DocsMint API",
|
|
238463
|
-
version: "0.9.
|
|
238463
|
+
version: "0.9.4",
|
|
238464
238464
|
description: "Self-hosted AI-native knowledge workspace and installable PWA with hybrid search, GraphRAG, REST, SDK, CLI, and MCP access for people and AI agents.",
|
|
238465
238465
|
contact: { name: "HiAi-gg", url: "https://github.com/HiAi-gg/docsmint" },
|
|
238466
238466
|
license: {
|
package/dist/client.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* failures (502 / 503 / 504 / timeout / network reset) are retried
|
|
8
8
|
* with exponential backoff up to `config.retries` attempts.
|
|
9
9
|
*/
|
|
10
|
-
import type { DocsApiKeyCreated, DocsApiKeyListResponse, DocsAttachment, DocsAttachmentConfirmInput, DocsAttachmentListResponse, DocsAttachmentPresignInput, DocsAttachmentPresignResponse, DocsCategory, DocsCategoryListItem, DocsCategoryInput, DocsCategoryUpdate, DocsDocument, DocsDocumentCreateInput, DocsDocumentCursorPage, DocsDocumentIndexRefresh, DocsDocumentIndexStatus, DocsDocumentKnowledgeSummary, DocsDocumentListResponse, DocsDocumentPipeline, DocsPipelineWarningRetry, DocsDocumentUpdateInput, DocsFolder, DocsFolderCreateInput, DocsFolderUpdateInput, DocsGraphEntitiesResponse, DocsGraphRelatedResponse, DocsGraphSearchResponse, DocsHealthResponse, DocsRequestContext, DocsSearchOptions, DocsSearchResponse, DocsSearchSuggestItem, DocsSharedContent, DocsShareLink, DocsShareListResponse, DocsShareRole, DocsTag, DocsVersion, DocsVersionDiff } from "./types.js";
|
|
10
|
+
import type { DocsApiKeyCreated, DocsApiKeyListResponse, DocsAttachment, DocsAttachmentConfirmInput, DocsAttachmentListResponse, DocsAttachmentPresignInput, DocsAttachmentPresignResponse, DocsCategory, DocsCategoryListItem, DocsCategoryInput, DocsCategoryUpdate, DocsDocument, DocsDocumentCreateInput, DocsDocumentCursorPage, DocsDocumentIndexRefresh, DocsDocumentIndexStatus, DocsDocumentKnowledgeSummary, DocsDocumentListResponse, DocsDocumentPipeline, DocsPipelineWarningRetry, DocsDocumentUpdateInput, DocsFolder, DocsFolderCreateInput, DocsFolderUpdateInput, DocsGraphEntitiesResponse, DocsGraphRelatedResponse, DocsGraphSearchResponse, DocsHealthResponse, DocsRequestContext, DocsSearchOptions, DocsSearchResponse, DocsSearchSuggestItem, DocsSharedContent, DocsShareLink, DocsShareListResponse, DocsShareRole, DocsTag, DocsTrashResponse, DocsVersion, DocsVersionDiff } from "./types.js";
|
|
11
11
|
export interface DocsClientConfig {
|
|
12
12
|
/** Base URL of the DocsMint API, e.g. `http://localhost:50700`. */
|
|
13
13
|
baseUrl: string;
|
|
@@ -124,6 +124,13 @@ export declare class DocsClient {
|
|
|
124
124
|
color?: string;
|
|
125
125
|
}, context?: DocsRequestContext): Promise<DocsTag>;
|
|
126
126
|
deleteTag(id: string, context?: DocsRequestContext): Promise<void>;
|
|
127
|
+
listTrash(context?: DocsRequestContext): Promise<DocsTrashResponse>;
|
|
128
|
+
restoreTrashedDocument(id: string, context?: DocsRequestContext): Promise<{
|
|
129
|
+
success: true;
|
|
130
|
+
}>;
|
|
131
|
+
permanentlyDeleteDocument(id: string, context?: DocsRequestContext): Promise<{
|
|
132
|
+
success: true;
|
|
133
|
+
}>;
|
|
127
134
|
addTagToDoc(documentId: string, tagId: string, context?: DocsRequestContext): Promise<void>;
|
|
128
135
|
removeTagFromDoc(documentId: string, tagId: string, context?: DocsRequestContext): Promise<void>;
|
|
129
136
|
listCategories(context?: DocsRequestContext): Promise<DocsCategoryListItem[]>;
|
package/dist/client.js
CHANGED
|
@@ -222,6 +222,15 @@ export class DocsClient {
|
|
|
222
222
|
async deleteTag(id, context) {
|
|
223
223
|
await this.request("DELETE", `/api/tags/${encodeURIComponent(id)}`, undefined, context);
|
|
224
224
|
}
|
|
225
|
+
async listTrash(context) {
|
|
226
|
+
return this.request("GET", "/api/trash", undefined, context);
|
|
227
|
+
}
|
|
228
|
+
async restoreTrashedDocument(id, context) {
|
|
229
|
+
return this.request("POST", `/api/trash/documents/${encodeURIComponent(id)}/restore`, undefined, context);
|
|
230
|
+
}
|
|
231
|
+
async permanentlyDeleteDocument(id, context) {
|
|
232
|
+
return this.request("DELETE", `/api/trash/documents/${encodeURIComponent(id)}`, undefined, context);
|
|
233
|
+
}
|
|
225
234
|
async addTagToDoc(documentId, tagId, context) {
|
|
226
235
|
await this.request("POST", `/api/documents/${encodeURIComponent(documentId)}/tags`, { json: { tagId } }, context);
|
|
227
236
|
}
|
package/dist/mcp-cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
|
20
20
|
|
|
21
21
|
// ../mcp-server/src/server.ts
|
|
22
22
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
23
|
-
import { z as
|
|
23
|
+
import { z as z15 } from "zod";
|
|
24
24
|
|
|
25
25
|
// dist/client.js
|
|
26
26
|
var docsApiErrorBrand = Symbol.for("io.github.hiai-gg.docsmint.DocsApiError");
|
|
@@ -199,6 +199,15 @@ class DocsClient {
|
|
|
199
199
|
async deleteTag(id, context) {
|
|
200
200
|
await this.request("DELETE", `/api/tags/${encodeURIComponent(id)}`, undefined, context);
|
|
201
201
|
}
|
|
202
|
+
async listTrash(context) {
|
|
203
|
+
return this.request("GET", "/api/trash", undefined, context);
|
|
204
|
+
}
|
|
205
|
+
async restoreTrashedDocument(id, context) {
|
|
206
|
+
return this.request("POST", `/api/trash/documents/${encodeURIComponent(id)}/restore`, undefined, context);
|
|
207
|
+
}
|
|
208
|
+
async permanentlyDeleteDocument(id, context) {
|
|
209
|
+
return this.request("DELETE", `/api/trash/documents/${encodeURIComponent(id)}`, undefined, context);
|
|
210
|
+
}
|
|
202
211
|
async addTagToDoc(documentId, tagId, context) {
|
|
203
212
|
await this.request("POST", `/api/documents/${encodeURIComponent(documentId)}/tags`, { json: { tagId } }, context);
|
|
204
213
|
}
|
|
@@ -799,7 +808,17 @@ var toolOutputSchemas = {
|
|
|
799
808
|
delete_document: deleteAcknowledgmentSchema,
|
|
800
809
|
delete_folder: deleteAcknowledgmentSchema,
|
|
801
810
|
delete_category: deleteAcknowledgmentSchema,
|
|
802
|
-
restore_document_version: documentSchema
|
|
811
|
+
restore_document_version: documentSchema,
|
|
812
|
+
create_tag: tagSchema,
|
|
813
|
+
update_tag: tagSchema,
|
|
814
|
+
delete_tag: deleteAcknowledgmentSchema,
|
|
815
|
+
add_tag_to_document: z.looseObject({ documentId: z.string().uuid(), tagId: z.string().uuid(), assigned: z.literal(true) }),
|
|
816
|
+
remove_tag_from_document: z.looseObject({ documentId: z.string().uuid(), tagId: z.string().uuid(), removed: z.literal(true) }),
|
|
817
|
+
update_folder: folderSchema,
|
|
818
|
+
update_category: categorySchema,
|
|
819
|
+
list_trash: z.looseObject({ documents: z.array(z.looseObject({ id: z.string().uuid(), title: z.string(), deletedAt: z.string(), purgeAfter: z.string().nullable() })), folders: z.array(z.unknown()) }),
|
|
820
|
+
restore_trashed_document: z.looseObject({ success: z.literal(true) }),
|
|
821
|
+
permanently_delete_document: deleteAcknowledgmentSchema
|
|
803
822
|
};
|
|
804
823
|
|
|
805
824
|
// ../mcp-server/src/lifecycle.ts
|
|
@@ -850,8 +869,101 @@ function registerLifecycleCapabilities(server, client, wrap) {
|
|
|
850
869
|
}, wrap("restore_document_version", async ({ documentId, versionId }) => client.restoreDocumentVersion ? client.restoreDocumentVersion(documentId, versionId) : unsupported("restore_document_version")));
|
|
851
870
|
}
|
|
852
871
|
|
|
853
|
-
// ../mcp-server/src/
|
|
872
|
+
// ../mcp-server/src/management.ts
|
|
854
873
|
import { z as z3 } from "zod";
|
|
874
|
+
var uuid = z3.string().uuid().describe("UUID of the target object, obtained from the corresponding list tool.");
|
|
875
|
+
var write = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
876
|
+
var update = { ...write, destructiveHint: true };
|
|
877
|
+
var read = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
878
|
+
var purge = { ...write, destructiveHint: true };
|
|
879
|
+
function unsupported2(name) {
|
|
880
|
+
throw new Error(`The injected legacy MCP client does not support ${name}; use a public DocsClient.`);
|
|
881
|
+
}
|
|
882
|
+
function registerManagementCapabilities(server, client, wrap) {
|
|
883
|
+
server.registerTool("create_tag", {
|
|
884
|
+
description: "Create a tag in the active workspace. Requires full workspace write access; category-scoped credentials cannot manage tags. Use add_tag_to_document to assign it.",
|
|
885
|
+
annotations: write,
|
|
886
|
+
inputSchema: z3.object({ name: z3.string().min(1).max(100).describe("New tag name, up to 100 characters."), color: z3.string().max(20).optional().describe("Optional display color for the new tag, up to 20 characters.") }),
|
|
887
|
+
outputSchema: toolOutputSchemas.create_tag
|
|
888
|
+
}, wrap("create_tag", async (input) => client.createTag ? client.createTag(input) : unsupported2("create_tag")));
|
|
889
|
+
server.registerTool("update_tag", {
|
|
890
|
+
description: "Rename or recolor an existing tag. Requires full workspace write access; category-scoped credentials cannot manage tags. Affected documents are reindexed by the API.",
|
|
891
|
+
annotations: update,
|
|
892
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(100).optional().describe("Replacement tag name; omit to keep the current name."), color: z3.string().max(20).optional().describe("Replacement display color; omit to keep the current color.") }).refine((value) => value.name !== undefined || value.color !== undefined),
|
|
893
|
+
outputSchema: toolOutputSchemas.update_tag
|
|
894
|
+
}, wrap("update_tag", async ({ id, ...input }) => client.updateTag ? client.updateTag(id, input) : unsupported2("update_tag")));
|
|
895
|
+
server.registerTool("delete_tag", {
|
|
896
|
+
description: "Delete a tag in the active workspace and remove its document assignments. Requires full workspace write access; category-scoped credentials cannot manage tags.",
|
|
897
|
+
annotations: purge,
|
|
898
|
+
inputSchema: z3.object({ id: uuid }),
|
|
899
|
+
outputSchema: toolOutputSchemas.delete_tag
|
|
900
|
+
}, wrap("delete_tag", async ({ id }) => {
|
|
901
|
+
if (!client.deleteTag)
|
|
902
|
+
return unsupported2("delete_tag");
|
|
903
|
+
await client.deleteTag(id);
|
|
904
|
+
return { id, deleted: true };
|
|
905
|
+
}));
|
|
906
|
+
server.registerTool("add_tag_to_document", {
|
|
907
|
+
description: "Assign a tag from list_tags to an existing document. Requires edit access to the document and permission to use the tag.",
|
|
908
|
+
annotations: write,
|
|
909
|
+
inputSchema: z3.object({ documentId: uuid.describe("UUID of the document to tag."), tagId: uuid.describe("UUID of the tag returned by list_tags.") }),
|
|
910
|
+
outputSchema: toolOutputSchemas.add_tag_to_document
|
|
911
|
+
}, wrap("add_tag_to_document", async ({ documentId, tagId }) => {
|
|
912
|
+
if (!client.addTagToDocument)
|
|
913
|
+
return unsupported2("add_tag_to_document");
|
|
914
|
+
await client.addTagToDocument(documentId, tagId);
|
|
915
|
+
return { documentId, tagId, assigned: true };
|
|
916
|
+
}));
|
|
917
|
+
server.registerTool("remove_tag_from_document", {
|
|
918
|
+
description: "Remove a tag assignment from a document. Requires edit access; the tag itself is preserved.",
|
|
919
|
+
annotations: update,
|
|
920
|
+
inputSchema: z3.object({ documentId: uuid.describe("UUID of the document whose tag assignment changes."), tagId: uuid.describe("UUID of the assigned tag to remove.") }),
|
|
921
|
+
outputSchema: toolOutputSchemas.remove_tag_from_document
|
|
922
|
+
}, wrap("remove_tag_from_document", async ({ documentId, tagId }) => {
|
|
923
|
+
if (!client.removeTagFromDocument)
|
|
924
|
+
return unsupported2("remove_tag_from_document");
|
|
925
|
+
await client.removeTagFromDocument(documentId, tagId);
|
|
926
|
+
return { documentId, tagId, removed: true };
|
|
927
|
+
}));
|
|
928
|
+
server.registerTool("update_folder", {
|
|
929
|
+
description: "Rename or move a folder; changes to category or parent follow API scope rules and trigger reindexing. Requires write access.",
|
|
930
|
+
annotations: update,
|
|
931
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(255).optional().describe("Replacement folder name; omit to preserve the name."), parentId: uuid.nullable().optional().describe("New parent folder UUID, or null for a root folder."), categoryId: uuid.nullable().optional().describe("New category UUID, or null to clear the category."), order: z3.number().int().nonnegative().optional().describe("New non-negative order within the containing folder.") }).refine((value) => value.name !== undefined || value.parentId !== undefined || value.categoryId !== undefined || value.order !== undefined),
|
|
932
|
+
outputSchema: toolOutputSchemas.update_folder
|
|
933
|
+
}, wrap("update_folder", async ({ id, ...input }) => client.updateFolder ? client.updateFolder(id, input) : unsupported2("update_folder")));
|
|
934
|
+
server.registerTool("update_category", {
|
|
935
|
+
description: "Rename or reorder a category. Requires full workspace write access; category-scoped credentials cannot modify categories.",
|
|
936
|
+
annotations: update,
|
|
937
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(255).optional().describe("New category name, up to 255 characters."), order: z3.number().int().nonnegative().optional().describe("New non-negative category order.") }).refine((value) => value.name !== undefined || value.order !== undefined),
|
|
938
|
+
outputSchema: toolOutputSchemas.update_category
|
|
939
|
+
}, wrap("update_category", async ({ id, ...input }) => client.updateCategory ? client.updateCategory(id, input) : unsupported2("update_category")));
|
|
940
|
+
server.registerTool("list_trash", {
|
|
941
|
+
description: "List soft-deleted documents visible to the active workspace/category. Requires read access.",
|
|
942
|
+
annotations: read,
|
|
943
|
+
inputSchema: z3.object({}),
|
|
944
|
+
outputSchema: toolOutputSchemas.list_trash
|
|
945
|
+
}, wrap("list_trash", async () => client.listTrash ? client.listTrash() : unsupported2("list_trash")));
|
|
946
|
+
server.registerTool("restore_trashed_document", {
|
|
947
|
+
description: "Restore a soft-deleted document from list_trash. Requires write access. This is different from restoring a content version.",
|
|
948
|
+
annotations: write,
|
|
949
|
+
inputSchema: z3.object({ id: uuid }),
|
|
950
|
+
outputSchema: toolOutputSchemas.restore_trashed_document
|
|
951
|
+
}, wrap("restore_trashed_document", async ({ id }) => client.restoreTrashedDocument ? client.restoreTrashedDocument(id) : unsupported2("restore_trashed_document")));
|
|
952
|
+
server.registerTool("permanently_delete_document", {
|
|
953
|
+
description: "Irreversibly purge a document already in trash, including its content and version history. Requires write access. Use only on explicit user request after checking list_trash.",
|
|
954
|
+
annotations: purge,
|
|
955
|
+
inputSchema: z3.object({ id: uuid }),
|
|
956
|
+
outputSchema: toolOutputSchemas.permanently_delete_document
|
|
957
|
+
}, wrap("permanently_delete_document", async ({ id }) => {
|
|
958
|
+
if (!client.permanentlyDeleteDocument)
|
|
959
|
+
return unsupported2("permanently_delete_document");
|
|
960
|
+
await client.permanentlyDeleteDocument(id);
|
|
961
|
+
return { id, deleted: true };
|
|
962
|
+
}));
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// ../mcp-server/src/capabilities.ts
|
|
966
|
+
import { z as z4 } from "zod";
|
|
855
967
|
function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
856
968
|
server.registerTool("list_categories", {
|
|
857
969
|
annotations: {
|
|
@@ -861,7 +973,7 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
861
973
|
openWorldHint: false
|
|
862
974
|
},
|
|
863
975
|
description: "List categories visible in the active workspace or category scope. Requires read access; a category-scoped credential sees only its configured category. Use this before create_document or create_folder when you need an existing category ID.",
|
|
864
|
-
inputSchema:
|
|
976
|
+
inputSchema: z4.object({}),
|
|
865
977
|
outputSchema: toolOutputSchemas.list_categories
|
|
866
978
|
}, wrapHandler("list_categories", async () => client.listCategories()));
|
|
867
979
|
server.registerTool("create_category", {
|
|
@@ -872,8 +984,8 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
872
984
|
openWorldHint: false
|
|
873
985
|
},
|
|
874
986
|
description: "Create a new category for the active workspace. Requires workspace-level write access; category-scoped credentials cannot create categories. Returns the created category. Use list_categories to inspect existing categories.",
|
|
875
|
-
inputSchema:
|
|
876
|
-
name:
|
|
987
|
+
inputSchema: z4.object({
|
|
988
|
+
name: z4.string().trim().min(1).max(255).describe("Non-empty display name, up to 255 characters, for example Project notes.")
|
|
877
989
|
}),
|
|
878
990
|
outputSchema: toolOutputSchemas.create_category
|
|
879
991
|
}, wrapHandler("create_category", async (input) => client.createCategory(input)));
|
|
@@ -885,7 +997,7 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
885
997
|
openWorldHint: false
|
|
886
998
|
},
|
|
887
999
|
description: "List tags visible in the active workspace or configured category scope. Requires read access; use returned tag IDs to filter list_documents and returned tag names to filter search_documents.",
|
|
888
|
-
inputSchema:
|
|
1000
|
+
inputSchema: z4.object({}),
|
|
889
1001
|
outputSchema: toolOutputSchemas.list_tags
|
|
890
1002
|
}, wrapHandler("list_tags", async () => client.listTags()));
|
|
891
1003
|
server.registerTool("get_related_documents", {
|
|
@@ -896,9 +1008,9 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
896
1008
|
openWorldHint: false
|
|
897
1009
|
},
|
|
898
1010
|
description: "Traverse graph relations from one readable document without a text query. Requires read access and returns related document IDs plus relation metadata. Use search_knowledge_graph to rank graph neighbors with query text, or search_documents for normal hybrid retrieval. Results stay in the active scope and may be empty when graph data is unavailable.",
|
|
899
|
-
inputSchema:
|
|
900
|
-
documentId:
|
|
901
|
-
limit:
|
|
1011
|
+
inputSchema: z4.object({
|
|
1012
|
+
documentId: z4.string().min(1).describe("Document ID returned by search_documents or list_documents; it must be readable in the active scope."),
|
|
1013
|
+
limit: z4.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
|
|
902
1014
|
}),
|
|
903
1015
|
outputSchema: toolOutputSchemas.get_related_documents
|
|
904
1016
|
}, wrapHandler("get_related_documents", async ({ documentId, limit }) => client.getRelatedDocuments(documentId, limit)));
|
|
@@ -910,10 +1022,10 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
910
1022
|
openWorldHint: false
|
|
911
1023
|
},
|
|
912
1024
|
description: "Search graph relations from one or more readable seed documents, optionally using query text to filter and rank related documents. Requires read access and returns seed entities plus relatedDocs. Use search_documents first to obtain authorized seed IDs; use get_related_documents for one-seed neighbors without graph search. Results stay in the active scope and graph data may be empty when unavailable.",
|
|
913
|
-
inputSchema:
|
|
914
|
-
query:
|
|
915
|
-
docIds:
|
|
916
|
-
limit:
|
|
1025
|
+
inputSchema: z4.object({
|
|
1026
|
+
query: z4.string().max(2000).optional().describe("Optional search text up to 2,000 characters to filter and rank graph-related documents; omit it to inspect relations without query filtering."),
|
|
1027
|
+
docIds: z4.array(z4.string().min(1)).min(1).max(50).describe("Between 1 and 50 document IDs returned by search_documents or list_documents; each seed must be readable in the active scope."),
|
|
1028
|
+
limit: z4.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
|
|
917
1029
|
}),
|
|
918
1030
|
outputSchema: toolOutputSchemas.search_knowledge_graph
|
|
919
1031
|
}, wrapHandler("search_knowledge_graph", async (input) => client.searchGraph(input)));
|
|
@@ -925,8 +1037,8 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
925
1037
|
openWorldHint: false
|
|
926
1038
|
},
|
|
927
1039
|
description: "Read indexing and knowledge-pipeline status for an existing document without starting work. Requires read access. Use after a save or refresh_document_index to check progress or failures.",
|
|
928
|
-
inputSchema:
|
|
929
|
-
documentId:
|
|
1040
|
+
inputSchema: z4.object({
|
|
1041
|
+
documentId: z4.string().uuid().describe("UUID of a document returned by search_documents or list_documents; it must be readable in the active scope.")
|
|
930
1042
|
}),
|
|
931
1043
|
outputSchema: toolOutputSchemas.get_document_index_status
|
|
932
1044
|
}, wrapHandler("get_document_index_status", async ({ documentId }) => client.getDocumentIndexStatus(documentId)));
|
|
@@ -938,16 +1050,16 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
938
1050
|
openWorldHint: false
|
|
939
1051
|
},
|
|
940
1052
|
description: "Queue an explicit reindex for an existing document; processing is asynchronous and the response acknowledges the generation. Requires write access. Normal content and placement changes schedule indexing when needed, so use get_document_index_status first and refresh only when a retry is intended.",
|
|
941
|
-
inputSchema:
|
|
942
|
-
documentId:
|
|
1053
|
+
inputSchema: z4.object({
|
|
1054
|
+
documentId: z4.string().uuid().describe("UUID of the document to refresh, obtained from search_documents or list_documents and visible in the active scope.")
|
|
943
1055
|
}),
|
|
944
1056
|
outputSchema: toolOutputSchemas.refresh_document_index
|
|
945
1057
|
}, wrapHandler("refresh_document_index", async ({ documentId }) => client.refreshDocumentIndex(documentId)));
|
|
946
1058
|
server.registerPrompt("organize_workspace", {
|
|
947
1059
|
description: "Plan safe document organization using DocsMint categories and folders.",
|
|
948
|
-
argsSchema:
|
|
949
|
-
objective:
|
|
950
|
-
language:
|
|
1060
|
+
argsSchema: z4.object({
|
|
1061
|
+
objective: z4.string(),
|
|
1062
|
+
language: z4.string().optional()
|
|
951
1063
|
})
|
|
952
1064
|
}, ({ objective, language }) => ({
|
|
953
1065
|
messages: [
|
|
@@ -962,9 +1074,9 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
962
1074
|
}));
|
|
963
1075
|
server.registerPrompt("research_workspace", {
|
|
964
1076
|
description: "Research a question with hybrid search and GraphRAG while citing DocsMint document IDs.",
|
|
965
|
-
argsSchema:
|
|
966
|
-
question:
|
|
967
|
-
language:
|
|
1077
|
+
argsSchema: z4.object({
|
|
1078
|
+
question: z4.string(),
|
|
1079
|
+
language: z4.string().optional()
|
|
968
1080
|
})
|
|
969
1081
|
}, ({ question, language }) => ({
|
|
970
1082
|
messages: [
|
|
@@ -1055,6 +1167,16 @@ function sanitizeMcpRequestContext(context) {
|
|
|
1055
1167
|
function createMcpDocsClient(docsClient, requestContext) {
|
|
1056
1168
|
const context = sanitizeMcpRequestContext(requestContext);
|
|
1057
1169
|
return {
|
|
1170
|
+
createTag: (input) => docsClient.createTag(input, context),
|
|
1171
|
+
updateTag: (id, input) => docsClient.updateTag(id, input, context),
|
|
1172
|
+
deleteTag: (id) => docsClient.deleteTag(id, context),
|
|
1173
|
+
addTagToDocument: (documentId, tagId) => docsClient.addTagToDoc(documentId, tagId, context),
|
|
1174
|
+
removeTagFromDocument: (documentId, tagId) => docsClient.removeTagFromDoc(documentId, tagId, context),
|
|
1175
|
+
updateFolder: (id, input) => docsClient.updateFolder(id, input, context),
|
|
1176
|
+
updateCategory: (id, input) => docsClient.updateCategory(id, input, context),
|
|
1177
|
+
listTrash: () => docsClient.listTrash(context),
|
|
1178
|
+
restoreTrashedDocument: (id) => docsClient.restoreTrashedDocument(id, context),
|
|
1179
|
+
permanentlyDeleteDocument: (id) => docsClient.permanentlyDeleteDocument(id, context),
|
|
1058
1180
|
deleteDocument: (id) => docsClient.deleteDoc(id, context),
|
|
1059
1181
|
deleteFolder: (id) => docsClient.deleteFolder(id, context),
|
|
1060
1182
|
deleteCategory: (id) => docsClient.deleteCategory(id, context),
|
|
@@ -1105,15 +1227,15 @@ __export(exports_create_document, {
|
|
|
1105
1227
|
definition: () => definition,
|
|
1106
1228
|
handler: () => handler
|
|
1107
1229
|
});
|
|
1108
|
-
import { z as
|
|
1230
|
+
import { z as z5 } from "zod";
|
|
1109
1231
|
var definition = {
|
|
1110
1232
|
name: "create_document",
|
|
1111
1233
|
description: "Create a new DocsMint document when no existing document should be modified. Optionally set a title, initial Markdown content, and folder or category placement; an omitted title defaults to \u201CUntitled\u201D. Requires write access in the target scope. A category-scoped credential must create inside its configured category, by selecting that category or a folder within it. Normal creation schedules indexing asynchronously and returns the created document. Use update_document for an existing document.",
|
|
1112
1234
|
inputSchema: {
|
|
1113
|
-
title:
|
|
1114
|
-
content:
|
|
1115
|
-
folderId:
|
|
1116
|
-
categoryId:
|
|
1235
|
+
title: z5.string().min(1).max(500).optional().describe("Optional title from 1 to 500 characters; omit to use the API default \u201CUntitled\u201D."),
|
|
1236
|
+
content: z5.string().optional().describe("Optional initial Markdown content; omit to create an empty document."),
|
|
1237
|
+
folderId: z5.string().uuid().optional().describe("Optional folder UUID from list_folders; the folder must be writable in the active workspace or category."),
|
|
1238
|
+
categoryId: z5.string().uuid().nullable().optional().describe("Optional category UUID from list_categories; omit or pass null to leave the explicit category unset. A categorized folder still supplies the document\u2019s effective category; without one the document remains uncategorized. Category-scoped credentials stay bound to their configured category.")
|
|
1117
1239
|
}
|
|
1118
1240
|
};
|
|
1119
1241
|
var createHandler = (api) => async function createDocument(args) {
|
|
@@ -1128,14 +1250,14 @@ __export(exports_create_folder, {
|
|
|
1128
1250
|
definition: () => definition2,
|
|
1129
1251
|
handler: () => handler2
|
|
1130
1252
|
});
|
|
1131
|
-
import { z as
|
|
1253
|
+
import { z as z6 } from "zod";
|
|
1132
1254
|
var definition2 = {
|
|
1133
1255
|
name: "create_folder",
|
|
1134
1256
|
description: "Create a new folder in the active workspace or category scope. Requires write access and returns the created folder. A nested folder inherits its parent category; for a root folder, pass categoryId when using a category-scoped credential. Category-scoped credentials cannot create outside their configured category.",
|
|
1135
1257
|
inputSchema: {
|
|
1136
|
-
name:
|
|
1137
|
-
parentId:
|
|
1138
|
-
categoryId:
|
|
1258
|
+
name: z6.string().min(1).max(255).describe("Non-empty folder name up to 255 characters."),
|
|
1259
|
+
parentId: z6.string().uuid().nullable().optional().describe("Optional parent folder UUID from list_folders; omit or pass null to create a root-level folder."),
|
|
1260
|
+
categoryId: z6.string().uuid().nullable().optional().describe("Optional category UUID from list_categories for a root-level folder. A nested folder inherits its parent category; category-scoped credentials cannot escape their configured category.")
|
|
1139
1261
|
}
|
|
1140
1262
|
};
|
|
1141
1263
|
var createHandler2 = (api) => async function createFolder(args) {
|
|
@@ -1150,14 +1272,14 @@ __export(exports_create_snapshot, {
|
|
|
1150
1272
|
definition: () => definition3,
|
|
1151
1273
|
handler: () => handler3
|
|
1152
1274
|
});
|
|
1153
|
-
import { z as
|
|
1275
|
+
import { z as z7 } from "zod";
|
|
1154
1276
|
var definition3 = {
|
|
1155
1277
|
name: "create_snapshot",
|
|
1156
1278
|
description: "Save a named, retained snapshot of an existing document\u2019s current content before a planned change. Requires edit access and adds an entry to get_version_history without changing the document itself. Use restore_document_version with the returned version ID to restore its content later.",
|
|
1157
1279
|
inputSchema: {
|
|
1158
|
-
documentId:
|
|
1159
|
-
label:
|
|
1160
|
-
description:
|
|
1280
|
+
documentId: z7.string().uuid().describe("UUID of the existing document, obtained from search_documents or list_documents and visible in the active scope."),
|
|
1281
|
+
label: z7.string().min(1).max(200).describe("Non-empty snapshot label up to 200 characters, for example 'v1.0-release'."),
|
|
1282
|
+
description: z7.string().max(1000).optional().describe("Optional snapshot note up to 1,000 characters; omit if not needed.")
|
|
1161
1283
|
}
|
|
1162
1284
|
};
|
|
1163
1285
|
var createHandler3 = (api) => async function createSnapshot(args) {
|
|
@@ -1173,12 +1295,12 @@ __export(exports_export_document, {
|
|
|
1173
1295
|
definition: () => definition4,
|
|
1174
1296
|
handler: () => handler4
|
|
1175
1297
|
});
|
|
1176
|
-
import { z as
|
|
1298
|
+
import { z as z8 } from "zod";
|
|
1177
1299
|
var definition4 = {
|
|
1178
1300
|
name: "export_document",
|
|
1179
1301
|
description: "Render one readable document as portable Markdown and return a markdown string in the response object. Does not modify the document or include its complete metadata; use get_document to inspect the editable document.",
|
|
1180
1302
|
inputSchema: {
|
|
1181
|
-
id:
|
|
1303
|
+
id: z8.string().uuid().describe("UUID of the readable document to export, obtained from search_documents or list_documents.")
|
|
1182
1304
|
}
|
|
1183
1305
|
};
|
|
1184
1306
|
var createHandler4 = (api) => async function exportDocument(args) {
|
|
@@ -1193,12 +1315,12 @@ __export(exports_get_document, {
|
|
|
1193
1315
|
definition: () => definition5,
|
|
1194
1316
|
handler: () => handler5
|
|
1195
1317
|
});
|
|
1196
|
-
import { z as
|
|
1318
|
+
import { z as z9 } from "zod";
|
|
1197
1319
|
var definition5 = {
|
|
1198
1320
|
name: "get_document",
|
|
1199
1321
|
description: "Read an existing document by UUID with its content, metadata, and tags before editing or citing it. Requires read access in the active workspace/category. Use export_document when you only need the portable Markdown body.",
|
|
1200
1322
|
inputSchema: {
|
|
1201
|
-
id:
|
|
1323
|
+
id: z9.string().uuid().describe("UUID of the document, obtained from search_documents or list_documents, and visible in the active scope.")
|
|
1202
1324
|
}
|
|
1203
1325
|
};
|
|
1204
1326
|
var createHandler5 = (api) => async function getDocument(args) {
|
|
@@ -1213,15 +1335,15 @@ __export(exports_list_documents, {
|
|
|
1213
1335
|
definition: () => definition6,
|
|
1214
1336
|
handler: () => handler6
|
|
1215
1337
|
});
|
|
1216
|
-
import { z as
|
|
1338
|
+
import { z as z10 } from "zod";
|
|
1217
1339
|
var definition6 = {
|
|
1218
1340
|
name: "list_documents",
|
|
1219
1341
|
description: "List readable documents in the active workspace or category with page-based results. Optionally filter by folder or tag; page defaults to 1 and limit to 20 (maximum 1,000). Use search_documents for text or semantic retrieval.",
|
|
1220
1342
|
inputSchema: {
|
|
1221
|
-
folderId:
|
|
1222
|
-
tag:
|
|
1223
|
-
page:
|
|
1224
|
-
limit:
|
|
1343
|
+
folderId: z10.string().uuid().optional().describe("Optional folder UUID from list_folders to limit the listing."),
|
|
1344
|
+
tag: z10.string().uuid().optional().describe("Optional tag UUID from list_tags to filter the documents."),
|
|
1345
|
+
page: z10.number().int().min(1).optional().describe("1-indexed result page; defaults to 1."),
|
|
1346
|
+
limit: z10.number().int().min(1).max(1000).optional().describe("Number of documents per page, from 1 to 1,000; defaults to 20.")
|
|
1225
1347
|
}
|
|
1226
1348
|
};
|
|
1227
1349
|
var createHandler6 = (api) => async function listDocuments(args) {
|
|
@@ -1236,12 +1358,12 @@ __export(exports_list_folders, {
|
|
|
1236
1358
|
definition: () => definition7,
|
|
1237
1359
|
handler: () => handler7
|
|
1238
1360
|
});
|
|
1239
|
-
import { z as
|
|
1361
|
+
import { z as z11 } from "zod";
|
|
1240
1362
|
var definition7 = {
|
|
1241
1363
|
name: "list_folders",
|
|
1242
1364
|
description: "List folders readable in the active workspace/category. Omit parentId to list root folders, or supply a parent UUID to list its immediate children as a flat list. Use create_folder to add a folder.",
|
|
1243
1365
|
inputSchema: {
|
|
1244
|
-
parentId:
|
|
1366
|
+
parentId: z11.string().uuid().optional().describe("Optional parent folder UUID from list_folders; omit to list root folders.")
|
|
1245
1367
|
}
|
|
1246
1368
|
};
|
|
1247
1369
|
var createHandler7 = (api) => async function listFolders(args) {
|
|
@@ -1256,15 +1378,15 @@ __export(exports_search, {
|
|
|
1256
1378
|
definition: () => definition8,
|
|
1257
1379
|
handler: () => handler8
|
|
1258
1380
|
});
|
|
1259
|
-
import { z as
|
|
1381
|
+
import { z as z12 } from "zod";
|
|
1260
1382
|
var definition8 = {
|
|
1261
1383
|
name: "search_documents",
|
|
1262
1384
|
description: "Search readable DocsMint documents with hybrid full-text and semantic retrieval, optionally filtered by folder and tag names. Requires read access and stays within the active workspace/category. Use search_knowledge_graph for graph relations from seed documents or get_related_documents for neighbors without a text query.",
|
|
1263
1385
|
inputSchema: {
|
|
1264
|
-
query:
|
|
1265
|
-
folder:
|
|
1266
|
-
tags:
|
|
1267
|
-
limit:
|
|
1386
|
+
query: z12.string().describe("Text to search for; preserve the language and terms relevant to the user request."),
|
|
1387
|
+
folder: z12.string().optional().describe("Optional folder UUID from list_folders to scope retrieval."),
|
|
1388
|
+
tags: z12.array(z12.string()).optional().describe("Optional tag names as shown by list_tags; documents match when they have any supplied tag name."),
|
|
1389
|
+
limit: z12.number().int().positive().max(100).optional().describe("Maximum result count, from 1 to 100; defaults to 20.")
|
|
1268
1390
|
}
|
|
1269
1391
|
};
|
|
1270
1392
|
var createHandler8 = (api) => async function searchDocuments(args) {
|
|
@@ -1284,16 +1406,16 @@ __export(exports_update_document, {
|
|
|
1284
1406
|
definition: () => definition9,
|
|
1285
1407
|
handler: () => handler9
|
|
1286
1408
|
});
|
|
1287
|
-
import { z as
|
|
1409
|
+
import { z as z13 } from "zod";
|
|
1288
1410
|
var definition9 = {
|
|
1289
1411
|
name: "update_document",
|
|
1290
1412
|
description: "Modify an existing document by UUID after reading its current state. Omitted fields remain unchanged; null folderId removes folder placement and null categoryId clears the explicit category, while a categorized folder can still supply the effective category. Changing title or Markdown content requires edit access, while moving placement requires write access in the active workspace/category. The server stores the prior content in version history and queues indexing when content or placement changes. Returns the updated document. Use create_document for new content.",
|
|
1291
1413
|
inputSchema: {
|
|
1292
|
-
id:
|
|
1293
|
-
title:
|
|
1294
|
-
content:
|
|
1295
|
-
folderId:
|
|
1296
|
-
categoryId:
|
|
1414
|
+
id: z13.string().uuid().describe("UUID of the existing document, obtained from search_documents, list_documents, or get_document."),
|
|
1415
|
+
title: z13.string().min(1).max(500).optional().describe("Optional replacement title, 1 to 500 characters; omit to leave the current title unchanged."),
|
|
1416
|
+
content: z13.string().optional().describe("New markdown content for the document."),
|
|
1417
|
+
folderId: z13.string().uuid().nullable().optional().describe("Optional destination folder UUID from list_folders; omit to keep current placement or pass null to remove folder placement."),
|
|
1418
|
+
categoryId: z13.string().uuid().nullable().optional().describe("Optional destination category UUID from list_categories; omit to keep the explicit category or pass null to clear it. A categorized folder may still supply the effective category. Category-scoped credentials cannot move outside their configured category.")
|
|
1297
1419
|
}
|
|
1298
1420
|
};
|
|
1299
1421
|
var createHandler9 = (api) => async function updateDocument(args) {
|
|
@@ -1309,13 +1431,13 @@ __export(exports_version_history, {
|
|
|
1309
1431
|
definition: () => definition10,
|
|
1310
1432
|
handler: () => handler10
|
|
1311
1433
|
});
|
|
1312
|
-
import { z as
|
|
1434
|
+
import { z as z14 } from "zod";
|
|
1313
1435
|
var definition10 = {
|
|
1314
1436
|
name: "get_version_history",
|
|
1315
1437
|
description: "Read versions for an existing document, including saved snapshots. Requires read access and returns version IDs with content and timestamps; pass a version ID to restore_document_version when the user asks to restore content. This is read-only and does not change the document.",
|
|
1316
1438
|
inputSchema: {
|
|
1317
|
-
documentId:
|
|
1318
|
-
onlySnapshots:
|
|
1439
|
+
documentId: z14.string().uuid().describe("UUID of the readable document whose version history you need; obtain it from search_documents or list_documents."),
|
|
1440
|
+
onlySnapshots: z14.boolean().optional().describe("When true, return only named snapshots and omit auto-saved revisions; omit or use false for the full history.")
|
|
1319
1441
|
}
|
|
1320
1442
|
};
|
|
1321
1443
|
var createHandler10 = (api) => async function getVersionHistory(args) {
|
|
@@ -1365,7 +1487,7 @@ function registerDocsmintMcpCapabilities(server, client2) {
|
|
|
1365
1487
|
const register = (name, description, inputSchema, handler11) => {
|
|
1366
1488
|
server.registerTool(name, {
|
|
1367
1489
|
description,
|
|
1368
|
-
inputSchema:
|
|
1490
|
+
inputSchema: z15.object(inputSchema),
|
|
1369
1491
|
annotations: {
|
|
1370
1492
|
readOnlyHint: ![
|
|
1371
1493
|
"create_document",
|
|
@@ -1402,9 +1524,10 @@ function registerDocsmintMcpCapabilities(server, client2) {
|
|
|
1402
1524
|
}
|
|
1403
1525
|
registerExtendedCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1404
1526
|
registerLifecycleCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1527
|
+
registerManagementCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1405
1528
|
}
|
|
1406
1529
|
function createDocsmintMcpServer(options = {}) {
|
|
1407
|
-
const server = new McpServer({ name: "docsmint", version: "0.9.
|
|
1530
|
+
const server = new McpServer({ name: "docsmint", version: "0.9.4" });
|
|
1408
1531
|
const client2 = options.docsClient ? createMcpDocsClient(options.docsClient, options.requestContext) : options.client ?? createMcpDocsClient(createDefaultDocsClient(), options.requestContext);
|
|
1409
1532
|
registerDocsmintMcpCapabilities(server, client2);
|
|
1410
1533
|
return server;
|
package/dist/mcp-server.js
CHANGED
|
@@ -16,7 +16,7 @@ var __export = (target, all) => {
|
|
|
16
16
|
|
|
17
17
|
// ../mcp-server/src/server.ts
|
|
18
18
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
19
|
-
import { z as
|
|
19
|
+
import { z as z15 } from "zod";
|
|
20
20
|
|
|
21
21
|
// dist/client.js
|
|
22
22
|
var docsApiErrorBrand = Symbol.for("io.github.hiai-gg.docsmint.DocsApiError");
|
|
@@ -195,6 +195,15 @@ class DocsClient {
|
|
|
195
195
|
async deleteTag(id, context) {
|
|
196
196
|
await this.request("DELETE", `/api/tags/${encodeURIComponent(id)}`, undefined, context);
|
|
197
197
|
}
|
|
198
|
+
async listTrash(context) {
|
|
199
|
+
return this.request("GET", "/api/trash", undefined, context);
|
|
200
|
+
}
|
|
201
|
+
async restoreTrashedDocument(id, context) {
|
|
202
|
+
return this.request("POST", `/api/trash/documents/${encodeURIComponent(id)}/restore`, undefined, context);
|
|
203
|
+
}
|
|
204
|
+
async permanentlyDeleteDocument(id, context) {
|
|
205
|
+
return this.request("DELETE", `/api/trash/documents/${encodeURIComponent(id)}`, undefined, context);
|
|
206
|
+
}
|
|
198
207
|
async addTagToDoc(documentId, tagId, context) {
|
|
199
208
|
await this.request("POST", `/api/documents/${encodeURIComponent(documentId)}/tags`, { json: { tagId } }, context);
|
|
200
209
|
}
|
|
@@ -795,7 +804,17 @@ var toolOutputSchemas = {
|
|
|
795
804
|
delete_document: deleteAcknowledgmentSchema,
|
|
796
805
|
delete_folder: deleteAcknowledgmentSchema,
|
|
797
806
|
delete_category: deleteAcknowledgmentSchema,
|
|
798
|
-
restore_document_version: documentSchema
|
|
807
|
+
restore_document_version: documentSchema,
|
|
808
|
+
create_tag: tagSchema,
|
|
809
|
+
update_tag: tagSchema,
|
|
810
|
+
delete_tag: deleteAcknowledgmentSchema,
|
|
811
|
+
add_tag_to_document: z.looseObject({ documentId: z.string().uuid(), tagId: z.string().uuid(), assigned: z.literal(true) }),
|
|
812
|
+
remove_tag_from_document: z.looseObject({ documentId: z.string().uuid(), tagId: z.string().uuid(), removed: z.literal(true) }),
|
|
813
|
+
update_folder: folderSchema,
|
|
814
|
+
update_category: categorySchema,
|
|
815
|
+
list_trash: z.looseObject({ documents: z.array(z.looseObject({ id: z.string().uuid(), title: z.string(), deletedAt: z.string(), purgeAfter: z.string().nullable() })), folders: z.array(z.unknown()) }),
|
|
816
|
+
restore_trashed_document: z.looseObject({ success: z.literal(true) }),
|
|
817
|
+
permanently_delete_document: deleteAcknowledgmentSchema
|
|
799
818
|
};
|
|
800
819
|
|
|
801
820
|
// ../mcp-server/src/lifecycle.ts
|
|
@@ -846,8 +865,101 @@ function registerLifecycleCapabilities(server, client, wrap) {
|
|
|
846
865
|
}, wrap("restore_document_version", async ({ documentId, versionId }) => client.restoreDocumentVersion ? client.restoreDocumentVersion(documentId, versionId) : unsupported("restore_document_version")));
|
|
847
866
|
}
|
|
848
867
|
|
|
849
|
-
// ../mcp-server/src/
|
|
868
|
+
// ../mcp-server/src/management.ts
|
|
850
869
|
import { z as z3 } from "zod";
|
|
870
|
+
var uuid = z3.string().uuid().describe("UUID of the target object, obtained from the corresponding list tool.");
|
|
871
|
+
var write = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
872
|
+
var update = { ...write, destructiveHint: true };
|
|
873
|
+
var read = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
874
|
+
var purge = { ...write, destructiveHint: true };
|
|
875
|
+
function unsupported2(name) {
|
|
876
|
+
throw new Error(`The injected legacy MCP client does not support ${name}; use a public DocsClient.`);
|
|
877
|
+
}
|
|
878
|
+
function registerManagementCapabilities(server, client, wrap) {
|
|
879
|
+
server.registerTool("create_tag", {
|
|
880
|
+
description: "Create a tag in the active workspace. Requires full workspace write access; category-scoped credentials cannot manage tags. Use add_tag_to_document to assign it.",
|
|
881
|
+
annotations: write,
|
|
882
|
+
inputSchema: z3.object({ name: z3.string().min(1).max(100).describe("New tag name, up to 100 characters."), color: z3.string().max(20).optional().describe("Optional display color for the new tag, up to 20 characters.") }),
|
|
883
|
+
outputSchema: toolOutputSchemas.create_tag
|
|
884
|
+
}, wrap("create_tag", async (input) => client.createTag ? client.createTag(input) : unsupported2("create_tag")));
|
|
885
|
+
server.registerTool("update_tag", {
|
|
886
|
+
description: "Rename or recolor an existing tag. Requires full workspace write access; category-scoped credentials cannot manage tags. Affected documents are reindexed by the API.",
|
|
887
|
+
annotations: update,
|
|
888
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(100).optional().describe("Replacement tag name; omit to keep the current name."), color: z3.string().max(20).optional().describe("Replacement display color; omit to keep the current color.") }).refine((value) => value.name !== undefined || value.color !== undefined),
|
|
889
|
+
outputSchema: toolOutputSchemas.update_tag
|
|
890
|
+
}, wrap("update_tag", async ({ id, ...input }) => client.updateTag ? client.updateTag(id, input) : unsupported2("update_tag")));
|
|
891
|
+
server.registerTool("delete_tag", {
|
|
892
|
+
description: "Delete a tag in the active workspace and remove its document assignments. Requires full workspace write access; category-scoped credentials cannot manage tags.",
|
|
893
|
+
annotations: purge,
|
|
894
|
+
inputSchema: z3.object({ id: uuid }),
|
|
895
|
+
outputSchema: toolOutputSchemas.delete_tag
|
|
896
|
+
}, wrap("delete_tag", async ({ id }) => {
|
|
897
|
+
if (!client.deleteTag)
|
|
898
|
+
return unsupported2("delete_tag");
|
|
899
|
+
await client.deleteTag(id);
|
|
900
|
+
return { id, deleted: true };
|
|
901
|
+
}));
|
|
902
|
+
server.registerTool("add_tag_to_document", {
|
|
903
|
+
description: "Assign a tag from list_tags to an existing document. Requires edit access to the document and permission to use the tag.",
|
|
904
|
+
annotations: write,
|
|
905
|
+
inputSchema: z3.object({ documentId: uuid.describe("UUID of the document to tag."), tagId: uuid.describe("UUID of the tag returned by list_tags.") }),
|
|
906
|
+
outputSchema: toolOutputSchemas.add_tag_to_document
|
|
907
|
+
}, wrap("add_tag_to_document", async ({ documentId, tagId }) => {
|
|
908
|
+
if (!client.addTagToDocument)
|
|
909
|
+
return unsupported2("add_tag_to_document");
|
|
910
|
+
await client.addTagToDocument(documentId, tagId);
|
|
911
|
+
return { documentId, tagId, assigned: true };
|
|
912
|
+
}));
|
|
913
|
+
server.registerTool("remove_tag_from_document", {
|
|
914
|
+
description: "Remove a tag assignment from a document. Requires edit access; the tag itself is preserved.",
|
|
915
|
+
annotations: update,
|
|
916
|
+
inputSchema: z3.object({ documentId: uuid.describe("UUID of the document whose tag assignment changes."), tagId: uuid.describe("UUID of the assigned tag to remove.") }),
|
|
917
|
+
outputSchema: toolOutputSchemas.remove_tag_from_document
|
|
918
|
+
}, wrap("remove_tag_from_document", async ({ documentId, tagId }) => {
|
|
919
|
+
if (!client.removeTagFromDocument)
|
|
920
|
+
return unsupported2("remove_tag_from_document");
|
|
921
|
+
await client.removeTagFromDocument(documentId, tagId);
|
|
922
|
+
return { documentId, tagId, removed: true };
|
|
923
|
+
}));
|
|
924
|
+
server.registerTool("update_folder", {
|
|
925
|
+
description: "Rename or move a folder; changes to category or parent follow API scope rules and trigger reindexing. Requires write access.",
|
|
926
|
+
annotations: update,
|
|
927
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(255).optional().describe("Replacement folder name; omit to preserve the name."), parentId: uuid.nullable().optional().describe("New parent folder UUID, or null for a root folder."), categoryId: uuid.nullable().optional().describe("New category UUID, or null to clear the category."), order: z3.number().int().nonnegative().optional().describe("New non-negative order within the containing folder.") }).refine((value) => value.name !== undefined || value.parentId !== undefined || value.categoryId !== undefined || value.order !== undefined),
|
|
928
|
+
outputSchema: toolOutputSchemas.update_folder
|
|
929
|
+
}, wrap("update_folder", async ({ id, ...input }) => client.updateFolder ? client.updateFolder(id, input) : unsupported2("update_folder")));
|
|
930
|
+
server.registerTool("update_category", {
|
|
931
|
+
description: "Rename or reorder a category. Requires full workspace write access; category-scoped credentials cannot modify categories.",
|
|
932
|
+
annotations: update,
|
|
933
|
+
inputSchema: z3.object({ id: uuid, name: z3.string().min(1).max(255).optional().describe("New category name, up to 255 characters."), order: z3.number().int().nonnegative().optional().describe("New non-negative category order.") }).refine((value) => value.name !== undefined || value.order !== undefined),
|
|
934
|
+
outputSchema: toolOutputSchemas.update_category
|
|
935
|
+
}, wrap("update_category", async ({ id, ...input }) => client.updateCategory ? client.updateCategory(id, input) : unsupported2("update_category")));
|
|
936
|
+
server.registerTool("list_trash", {
|
|
937
|
+
description: "List soft-deleted documents visible to the active workspace/category. Requires read access.",
|
|
938
|
+
annotations: read,
|
|
939
|
+
inputSchema: z3.object({}),
|
|
940
|
+
outputSchema: toolOutputSchemas.list_trash
|
|
941
|
+
}, wrap("list_trash", async () => client.listTrash ? client.listTrash() : unsupported2("list_trash")));
|
|
942
|
+
server.registerTool("restore_trashed_document", {
|
|
943
|
+
description: "Restore a soft-deleted document from list_trash. Requires write access. This is different from restoring a content version.",
|
|
944
|
+
annotations: write,
|
|
945
|
+
inputSchema: z3.object({ id: uuid }),
|
|
946
|
+
outputSchema: toolOutputSchemas.restore_trashed_document
|
|
947
|
+
}, wrap("restore_trashed_document", async ({ id }) => client.restoreTrashedDocument ? client.restoreTrashedDocument(id) : unsupported2("restore_trashed_document")));
|
|
948
|
+
server.registerTool("permanently_delete_document", {
|
|
949
|
+
description: "Irreversibly purge a document already in trash, including its content and version history. Requires write access. Use only on explicit user request after checking list_trash.",
|
|
950
|
+
annotations: purge,
|
|
951
|
+
inputSchema: z3.object({ id: uuid }),
|
|
952
|
+
outputSchema: toolOutputSchemas.permanently_delete_document
|
|
953
|
+
}, wrap("permanently_delete_document", async ({ id }) => {
|
|
954
|
+
if (!client.permanentlyDeleteDocument)
|
|
955
|
+
return unsupported2("permanently_delete_document");
|
|
956
|
+
await client.permanentlyDeleteDocument(id);
|
|
957
|
+
return { id, deleted: true };
|
|
958
|
+
}));
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// ../mcp-server/src/capabilities.ts
|
|
962
|
+
import { z as z4 } from "zod";
|
|
851
963
|
var capabilityCatalog = {
|
|
852
964
|
tools: [
|
|
853
965
|
"search_documents",
|
|
@@ -870,7 +982,17 @@ var capabilityCatalog = {
|
|
|
870
982
|
"delete_document",
|
|
871
983
|
"delete_folder",
|
|
872
984
|
"delete_category",
|
|
873
|
-
"restore_document_version"
|
|
985
|
+
"restore_document_version",
|
|
986
|
+
"create_tag",
|
|
987
|
+
"update_tag",
|
|
988
|
+
"delete_tag",
|
|
989
|
+
"add_tag_to_document",
|
|
990
|
+
"remove_tag_from_document",
|
|
991
|
+
"update_folder",
|
|
992
|
+
"update_category",
|
|
993
|
+
"list_trash",
|
|
994
|
+
"restore_trashed_document",
|
|
995
|
+
"permanently_delete_document"
|
|
874
996
|
],
|
|
875
997
|
prompts: ["organize_workspace", "research_workspace"],
|
|
876
998
|
resources: [
|
|
@@ -888,7 +1010,7 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
888
1010
|
openWorldHint: false
|
|
889
1011
|
},
|
|
890
1012
|
description: "List categories visible in the active workspace or category scope. Requires read access; a category-scoped credential sees only its configured category. Use this before create_document or create_folder when you need an existing category ID.",
|
|
891
|
-
inputSchema:
|
|
1013
|
+
inputSchema: z4.object({}),
|
|
892
1014
|
outputSchema: toolOutputSchemas.list_categories
|
|
893
1015
|
}, wrapHandler("list_categories", async () => client.listCategories()));
|
|
894
1016
|
server.registerTool("create_category", {
|
|
@@ -899,8 +1021,8 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
899
1021
|
openWorldHint: false
|
|
900
1022
|
},
|
|
901
1023
|
description: "Create a new category for the active workspace. Requires workspace-level write access; category-scoped credentials cannot create categories. Returns the created category. Use list_categories to inspect existing categories.",
|
|
902
|
-
inputSchema:
|
|
903
|
-
name:
|
|
1024
|
+
inputSchema: z4.object({
|
|
1025
|
+
name: z4.string().trim().min(1).max(255).describe("Non-empty display name, up to 255 characters, for example Project notes.")
|
|
904
1026
|
}),
|
|
905
1027
|
outputSchema: toolOutputSchemas.create_category
|
|
906
1028
|
}, wrapHandler("create_category", async (input) => client.createCategory(input)));
|
|
@@ -912,7 +1034,7 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
912
1034
|
openWorldHint: false
|
|
913
1035
|
},
|
|
914
1036
|
description: "List tags visible in the active workspace or configured category scope. Requires read access; use returned tag IDs to filter list_documents and returned tag names to filter search_documents.",
|
|
915
|
-
inputSchema:
|
|
1037
|
+
inputSchema: z4.object({}),
|
|
916
1038
|
outputSchema: toolOutputSchemas.list_tags
|
|
917
1039
|
}, wrapHandler("list_tags", async () => client.listTags()));
|
|
918
1040
|
server.registerTool("get_related_documents", {
|
|
@@ -923,9 +1045,9 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
923
1045
|
openWorldHint: false
|
|
924
1046
|
},
|
|
925
1047
|
description: "Traverse graph relations from one readable document without a text query. Requires read access and returns related document IDs plus relation metadata. Use search_knowledge_graph to rank graph neighbors with query text, or search_documents for normal hybrid retrieval. Results stay in the active scope and may be empty when graph data is unavailable.",
|
|
926
|
-
inputSchema:
|
|
927
|
-
documentId:
|
|
928
|
-
limit:
|
|
1048
|
+
inputSchema: z4.object({
|
|
1049
|
+
documentId: z4.string().min(1).describe("Document ID returned by search_documents or list_documents; it must be readable in the active scope."),
|
|
1050
|
+
limit: z4.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
|
|
929
1051
|
}),
|
|
930
1052
|
outputSchema: toolOutputSchemas.get_related_documents
|
|
931
1053
|
}, wrapHandler("get_related_documents", async ({ documentId, limit }) => client.getRelatedDocuments(documentId, limit)));
|
|
@@ -937,10 +1059,10 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
937
1059
|
openWorldHint: false
|
|
938
1060
|
},
|
|
939
1061
|
description: "Search graph relations from one or more readable seed documents, optionally using query text to filter and rank related documents. Requires read access and returns seed entities plus relatedDocs. Use search_documents first to obtain authorized seed IDs; use get_related_documents for one-seed neighbors without graph search. Results stay in the active scope and graph data may be empty when unavailable.",
|
|
940
|
-
inputSchema:
|
|
941
|
-
query:
|
|
942
|
-
docIds:
|
|
943
|
-
limit:
|
|
1062
|
+
inputSchema: z4.object({
|
|
1063
|
+
query: z4.string().max(2000).optional().describe("Optional search text up to 2,000 characters to filter and rank graph-related documents; omit it to inspect relations without query filtering."),
|
|
1064
|
+
docIds: z4.array(z4.string().min(1)).min(1).max(50).describe("Between 1 and 50 document IDs returned by search_documents or list_documents; each seed must be readable in the active scope."),
|
|
1065
|
+
limit: z4.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
|
|
944
1066
|
}),
|
|
945
1067
|
outputSchema: toolOutputSchemas.search_knowledge_graph
|
|
946
1068
|
}, wrapHandler("search_knowledge_graph", async (input) => client.searchGraph(input)));
|
|
@@ -952,8 +1074,8 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
952
1074
|
openWorldHint: false
|
|
953
1075
|
},
|
|
954
1076
|
description: "Read indexing and knowledge-pipeline status for an existing document without starting work. Requires read access. Use after a save or refresh_document_index to check progress or failures.",
|
|
955
|
-
inputSchema:
|
|
956
|
-
documentId:
|
|
1077
|
+
inputSchema: z4.object({
|
|
1078
|
+
documentId: z4.string().uuid().describe("UUID of a document returned by search_documents or list_documents; it must be readable in the active scope.")
|
|
957
1079
|
}),
|
|
958
1080
|
outputSchema: toolOutputSchemas.get_document_index_status
|
|
959
1081
|
}, wrapHandler("get_document_index_status", async ({ documentId }) => client.getDocumentIndexStatus(documentId)));
|
|
@@ -965,16 +1087,16 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
965
1087
|
openWorldHint: false
|
|
966
1088
|
},
|
|
967
1089
|
description: "Queue an explicit reindex for an existing document; processing is asynchronous and the response acknowledges the generation. Requires write access. Normal content and placement changes schedule indexing when needed, so use get_document_index_status first and refresh only when a retry is intended.",
|
|
968
|
-
inputSchema:
|
|
969
|
-
documentId:
|
|
1090
|
+
inputSchema: z4.object({
|
|
1091
|
+
documentId: z4.string().uuid().describe("UUID of the document to refresh, obtained from search_documents or list_documents and visible in the active scope.")
|
|
970
1092
|
}),
|
|
971
1093
|
outputSchema: toolOutputSchemas.refresh_document_index
|
|
972
1094
|
}, wrapHandler("refresh_document_index", async ({ documentId }) => client.refreshDocumentIndex(documentId)));
|
|
973
1095
|
server.registerPrompt("organize_workspace", {
|
|
974
1096
|
description: "Plan safe document organization using DocsMint categories and folders.",
|
|
975
|
-
argsSchema:
|
|
976
|
-
objective:
|
|
977
|
-
language:
|
|
1097
|
+
argsSchema: z4.object({
|
|
1098
|
+
objective: z4.string(),
|
|
1099
|
+
language: z4.string().optional()
|
|
978
1100
|
})
|
|
979
1101
|
}, ({ objective, language }) => ({
|
|
980
1102
|
messages: [
|
|
@@ -989,9 +1111,9 @@ function registerExtendedCapabilities(server, client, wrapHandler) {
|
|
|
989
1111
|
}));
|
|
990
1112
|
server.registerPrompt("research_workspace", {
|
|
991
1113
|
description: "Research a question with hybrid search and GraphRAG while citing DocsMint document IDs.",
|
|
992
|
-
argsSchema:
|
|
993
|
-
question:
|
|
994
|
-
language:
|
|
1114
|
+
argsSchema: z4.object({
|
|
1115
|
+
question: z4.string(),
|
|
1116
|
+
language: z4.string().optional()
|
|
995
1117
|
})
|
|
996
1118
|
}, ({ question, language }) => ({
|
|
997
1119
|
messages: [
|
|
@@ -1082,6 +1204,16 @@ function sanitizeMcpRequestContext(context) {
|
|
|
1082
1204
|
function createMcpDocsClient(docsClient, requestContext) {
|
|
1083
1205
|
const context = sanitizeMcpRequestContext(requestContext);
|
|
1084
1206
|
return {
|
|
1207
|
+
createTag: (input) => docsClient.createTag(input, context),
|
|
1208
|
+
updateTag: (id, input) => docsClient.updateTag(id, input, context),
|
|
1209
|
+
deleteTag: (id) => docsClient.deleteTag(id, context),
|
|
1210
|
+
addTagToDocument: (documentId, tagId) => docsClient.addTagToDoc(documentId, tagId, context),
|
|
1211
|
+
removeTagFromDocument: (documentId, tagId) => docsClient.removeTagFromDoc(documentId, tagId, context),
|
|
1212
|
+
updateFolder: (id, input) => docsClient.updateFolder(id, input, context),
|
|
1213
|
+
updateCategory: (id, input) => docsClient.updateCategory(id, input, context),
|
|
1214
|
+
listTrash: () => docsClient.listTrash(context),
|
|
1215
|
+
restoreTrashedDocument: (id) => docsClient.restoreTrashedDocument(id, context),
|
|
1216
|
+
permanentlyDeleteDocument: (id) => docsClient.permanentlyDeleteDocument(id, context),
|
|
1085
1217
|
deleteDocument: (id) => docsClient.deleteDoc(id, context),
|
|
1086
1218
|
deleteFolder: (id) => docsClient.deleteFolder(id, context),
|
|
1087
1219
|
deleteCategory: (id) => docsClient.deleteCategory(id, context),
|
|
@@ -1132,15 +1264,15 @@ __export(exports_create_document, {
|
|
|
1132
1264
|
definition: () => definition,
|
|
1133
1265
|
handler: () => handler
|
|
1134
1266
|
});
|
|
1135
|
-
import { z as
|
|
1267
|
+
import { z as z5 } from "zod";
|
|
1136
1268
|
var definition = {
|
|
1137
1269
|
name: "create_document",
|
|
1138
1270
|
description: "Create a new DocsMint document when no existing document should be modified. Optionally set a title, initial Markdown content, and folder or category placement; an omitted title defaults to \u201CUntitled\u201D. Requires write access in the target scope. A category-scoped credential must create inside its configured category, by selecting that category or a folder within it. Normal creation schedules indexing asynchronously and returns the created document. Use update_document for an existing document.",
|
|
1139
1271
|
inputSchema: {
|
|
1140
|
-
title:
|
|
1141
|
-
content:
|
|
1142
|
-
folderId:
|
|
1143
|
-
categoryId:
|
|
1272
|
+
title: z5.string().min(1).max(500).optional().describe("Optional title from 1 to 500 characters; omit to use the API default \u201CUntitled\u201D."),
|
|
1273
|
+
content: z5.string().optional().describe("Optional initial Markdown content; omit to create an empty document."),
|
|
1274
|
+
folderId: z5.string().uuid().optional().describe("Optional folder UUID from list_folders; the folder must be writable in the active workspace or category."),
|
|
1275
|
+
categoryId: z5.string().uuid().nullable().optional().describe("Optional category UUID from list_categories; omit or pass null to leave the explicit category unset. A categorized folder still supplies the document\u2019s effective category; without one the document remains uncategorized. Category-scoped credentials stay bound to their configured category.")
|
|
1144
1276
|
}
|
|
1145
1277
|
};
|
|
1146
1278
|
var createHandler = (api) => async function createDocument(args) {
|
|
@@ -1155,14 +1287,14 @@ __export(exports_create_folder, {
|
|
|
1155
1287
|
definition: () => definition2,
|
|
1156
1288
|
handler: () => handler2
|
|
1157
1289
|
});
|
|
1158
|
-
import { z as
|
|
1290
|
+
import { z as z6 } from "zod";
|
|
1159
1291
|
var definition2 = {
|
|
1160
1292
|
name: "create_folder",
|
|
1161
1293
|
description: "Create a new folder in the active workspace or category scope. Requires write access and returns the created folder. A nested folder inherits its parent category; for a root folder, pass categoryId when using a category-scoped credential. Category-scoped credentials cannot create outside their configured category.",
|
|
1162
1294
|
inputSchema: {
|
|
1163
|
-
name:
|
|
1164
|
-
parentId:
|
|
1165
|
-
categoryId:
|
|
1295
|
+
name: z6.string().min(1).max(255).describe("Non-empty folder name up to 255 characters."),
|
|
1296
|
+
parentId: z6.string().uuid().nullable().optional().describe("Optional parent folder UUID from list_folders; omit or pass null to create a root-level folder."),
|
|
1297
|
+
categoryId: z6.string().uuid().nullable().optional().describe("Optional category UUID from list_categories for a root-level folder. A nested folder inherits its parent category; category-scoped credentials cannot escape their configured category.")
|
|
1166
1298
|
}
|
|
1167
1299
|
};
|
|
1168
1300
|
var createHandler2 = (api) => async function createFolder(args) {
|
|
@@ -1177,14 +1309,14 @@ __export(exports_create_snapshot, {
|
|
|
1177
1309
|
definition: () => definition3,
|
|
1178
1310
|
handler: () => handler3
|
|
1179
1311
|
});
|
|
1180
|
-
import { z as
|
|
1312
|
+
import { z as z7 } from "zod";
|
|
1181
1313
|
var definition3 = {
|
|
1182
1314
|
name: "create_snapshot",
|
|
1183
1315
|
description: "Save a named, retained snapshot of an existing document\u2019s current content before a planned change. Requires edit access and adds an entry to get_version_history without changing the document itself. Use restore_document_version with the returned version ID to restore its content later.",
|
|
1184
1316
|
inputSchema: {
|
|
1185
|
-
documentId:
|
|
1186
|
-
label:
|
|
1187
|
-
description:
|
|
1317
|
+
documentId: z7.string().uuid().describe("UUID of the existing document, obtained from search_documents or list_documents and visible in the active scope."),
|
|
1318
|
+
label: z7.string().min(1).max(200).describe("Non-empty snapshot label up to 200 characters, for example 'v1.0-release'."),
|
|
1319
|
+
description: z7.string().max(1000).optional().describe("Optional snapshot note up to 1,000 characters; omit if not needed.")
|
|
1188
1320
|
}
|
|
1189
1321
|
};
|
|
1190
1322
|
var createHandler3 = (api) => async function createSnapshot(args) {
|
|
@@ -1200,12 +1332,12 @@ __export(exports_export_document, {
|
|
|
1200
1332
|
definition: () => definition4,
|
|
1201
1333
|
handler: () => handler4
|
|
1202
1334
|
});
|
|
1203
|
-
import { z as
|
|
1335
|
+
import { z as z8 } from "zod";
|
|
1204
1336
|
var definition4 = {
|
|
1205
1337
|
name: "export_document",
|
|
1206
1338
|
description: "Render one readable document as portable Markdown and return a markdown string in the response object. Does not modify the document or include its complete metadata; use get_document to inspect the editable document.",
|
|
1207
1339
|
inputSchema: {
|
|
1208
|
-
id:
|
|
1340
|
+
id: z8.string().uuid().describe("UUID of the readable document to export, obtained from search_documents or list_documents.")
|
|
1209
1341
|
}
|
|
1210
1342
|
};
|
|
1211
1343
|
var createHandler4 = (api) => async function exportDocument(args) {
|
|
@@ -1220,12 +1352,12 @@ __export(exports_get_document, {
|
|
|
1220
1352
|
definition: () => definition5,
|
|
1221
1353
|
handler: () => handler5
|
|
1222
1354
|
});
|
|
1223
|
-
import { z as
|
|
1355
|
+
import { z as z9 } from "zod";
|
|
1224
1356
|
var definition5 = {
|
|
1225
1357
|
name: "get_document",
|
|
1226
1358
|
description: "Read an existing document by UUID with its content, metadata, and tags before editing or citing it. Requires read access in the active workspace/category. Use export_document when you only need the portable Markdown body.",
|
|
1227
1359
|
inputSchema: {
|
|
1228
|
-
id:
|
|
1360
|
+
id: z9.string().uuid().describe("UUID of the document, obtained from search_documents or list_documents, and visible in the active scope.")
|
|
1229
1361
|
}
|
|
1230
1362
|
};
|
|
1231
1363
|
var createHandler5 = (api) => async function getDocument(args) {
|
|
@@ -1240,15 +1372,15 @@ __export(exports_list_documents, {
|
|
|
1240
1372
|
definition: () => definition6,
|
|
1241
1373
|
handler: () => handler6
|
|
1242
1374
|
});
|
|
1243
|
-
import { z as
|
|
1375
|
+
import { z as z10 } from "zod";
|
|
1244
1376
|
var definition6 = {
|
|
1245
1377
|
name: "list_documents",
|
|
1246
1378
|
description: "List readable documents in the active workspace or category with page-based results. Optionally filter by folder or tag; page defaults to 1 and limit to 20 (maximum 1,000). Use search_documents for text or semantic retrieval.",
|
|
1247
1379
|
inputSchema: {
|
|
1248
|
-
folderId:
|
|
1249
|
-
tag:
|
|
1250
|
-
page:
|
|
1251
|
-
limit:
|
|
1380
|
+
folderId: z10.string().uuid().optional().describe("Optional folder UUID from list_folders to limit the listing."),
|
|
1381
|
+
tag: z10.string().uuid().optional().describe("Optional tag UUID from list_tags to filter the documents."),
|
|
1382
|
+
page: z10.number().int().min(1).optional().describe("1-indexed result page; defaults to 1."),
|
|
1383
|
+
limit: z10.number().int().min(1).max(1000).optional().describe("Number of documents per page, from 1 to 1,000; defaults to 20.")
|
|
1252
1384
|
}
|
|
1253
1385
|
};
|
|
1254
1386
|
var createHandler6 = (api) => async function listDocuments(args) {
|
|
@@ -1263,12 +1395,12 @@ __export(exports_list_folders, {
|
|
|
1263
1395
|
definition: () => definition7,
|
|
1264
1396
|
handler: () => handler7
|
|
1265
1397
|
});
|
|
1266
|
-
import { z as
|
|
1398
|
+
import { z as z11 } from "zod";
|
|
1267
1399
|
var definition7 = {
|
|
1268
1400
|
name: "list_folders",
|
|
1269
1401
|
description: "List folders readable in the active workspace/category. Omit parentId to list root folders, or supply a parent UUID to list its immediate children as a flat list. Use create_folder to add a folder.",
|
|
1270
1402
|
inputSchema: {
|
|
1271
|
-
parentId:
|
|
1403
|
+
parentId: z11.string().uuid().optional().describe("Optional parent folder UUID from list_folders; omit to list root folders.")
|
|
1272
1404
|
}
|
|
1273
1405
|
};
|
|
1274
1406
|
var createHandler7 = (api) => async function listFolders(args) {
|
|
@@ -1283,15 +1415,15 @@ __export(exports_search, {
|
|
|
1283
1415
|
definition: () => definition8,
|
|
1284
1416
|
handler: () => handler8
|
|
1285
1417
|
});
|
|
1286
|
-
import { z as
|
|
1418
|
+
import { z as z12 } from "zod";
|
|
1287
1419
|
var definition8 = {
|
|
1288
1420
|
name: "search_documents",
|
|
1289
1421
|
description: "Search readable DocsMint documents with hybrid full-text and semantic retrieval, optionally filtered by folder and tag names. Requires read access and stays within the active workspace/category. Use search_knowledge_graph for graph relations from seed documents or get_related_documents for neighbors without a text query.",
|
|
1290
1422
|
inputSchema: {
|
|
1291
|
-
query:
|
|
1292
|
-
folder:
|
|
1293
|
-
tags:
|
|
1294
|
-
limit:
|
|
1423
|
+
query: z12.string().describe("Text to search for; preserve the language and terms relevant to the user request."),
|
|
1424
|
+
folder: z12.string().optional().describe("Optional folder UUID from list_folders to scope retrieval."),
|
|
1425
|
+
tags: z12.array(z12.string()).optional().describe("Optional tag names as shown by list_tags; documents match when they have any supplied tag name."),
|
|
1426
|
+
limit: z12.number().int().positive().max(100).optional().describe("Maximum result count, from 1 to 100; defaults to 20.")
|
|
1295
1427
|
}
|
|
1296
1428
|
};
|
|
1297
1429
|
var createHandler8 = (api) => async function searchDocuments(args) {
|
|
@@ -1311,16 +1443,16 @@ __export(exports_update_document, {
|
|
|
1311
1443
|
definition: () => definition9,
|
|
1312
1444
|
handler: () => handler9
|
|
1313
1445
|
});
|
|
1314
|
-
import { z as
|
|
1446
|
+
import { z as z13 } from "zod";
|
|
1315
1447
|
var definition9 = {
|
|
1316
1448
|
name: "update_document",
|
|
1317
1449
|
description: "Modify an existing document by UUID after reading its current state. Omitted fields remain unchanged; null folderId removes folder placement and null categoryId clears the explicit category, while a categorized folder can still supply the effective category. Changing title or Markdown content requires edit access, while moving placement requires write access in the active workspace/category. The server stores the prior content in version history and queues indexing when content or placement changes. Returns the updated document. Use create_document for new content.",
|
|
1318
1450
|
inputSchema: {
|
|
1319
|
-
id:
|
|
1320
|
-
title:
|
|
1321
|
-
content:
|
|
1322
|
-
folderId:
|
|
1323
|
-
categoryId:
|
|
1451
|
+
id: z13.string().uuid().describe("UUID of the existing document, obtained from search_documents, list_documents, or get_document."),
|
|
1452
|
+
title: z13.string().min(1).max(500).optional().describe("Optional replacement title, 1 to 500 characters; omit to leave the current title unchanged."),
|
|
1453
|
+
content: z13.string().optional().describe("New markdown content for the document."),
|
|
1454
|
+
folderId: z13.string().uuid().nullable().optional().describe("Optional destination folder UUID from list_folders; omit to keep current placement or pass null to remove folder placement."),
|
|
1455
|
+
categoryId: z13.string().uuid().nullable().optional().describe("Optional destination category UUID from list_categories; omit to keep the explicit category or pass null to clear it. A categorized folder may still supply the effective category. Category-scoped credentials cannot move outside their configured category.")
|
|
1324
1456
|
}
|
|
1325
1457
|
};
|
|
1326
1458
|
var createHandler9 = (api) => async function updateDocument(args) {
|
|
@@ -1336,13 +1468,13 @@ __export(exports_version_history, {
|
|
|
1336
1468
|
definition: () => definition10,
|
|
1337
1469
|
handler: () => handler10
|
|
1338
1470
|
});
|
|
1339
|
-
import { z as
|
|
1471
|
+
import { z as z14 } from "zod";
|
|
1340
1472
|
var definition10 = {
|
|
1341
1473
|
name: "get_version_history",
|
|
1342
1474
|
description: "Read versions for an existing document, including saved snapshots. Requires read access and returns version IDs with content and timestamps; pass a version ID to restore_document_version when the user asks to restore content. This is read-only and does not change the document.",
|
|
1343
1475
|
inputSchema: {
|
|
1344
|
-
documentId:
|
|
1345
|
-
onlySnapshots:
|
|
1476
|
+
documentId: z14.string().uuid().describe("UUID of the readable document whose version history you need; obtain it from search_documents or list_documents."),
|
|
1477
|
+
onlySnapshots: z14.boolean().optional().describe("When true, return only named snapshots and omit auto-saved revisions; omit or use false for the full history.")
|
|
1346
1478
|
}
|
|
1347
1479
|
};
|
|
1348
1480
|
var createHandler10 = (api) => async function getVersionHistory(args) {
|
|
@@ -1392,7 +1524,7 @@ function registerDocsmintMcpCapabilities(server, client2) {
|
|
|
1392
1524
|
const register = (name, description, inputSchema, handler11) => {
|
|
1393
1525
|
server.registerTool(name, {
|
|
1394
1526
|
description,
|
|
1395
|
-
inputSchema:
|
|
1527
|
+
inputSchema: z15.object(inputSchema),
|
|
1396
1528
|
annotations: {
|
|
1397
1529
|
readOnlyHint: ![
|
|
1398
1530
|
"create_document",
|
|
@@ -1429,9 +1561,10 @@ function registerDocsmintMcpCapabilities(server, client2) {
|
|
|
1429
1561
|
}
|
|
1430
1562
|
registerExtendedCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1431
1563
|
registerLifecycleCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1564
|
+
registerManagementCapabilities(server, client2, (name, handler11) => wrapHandler(name, handler11, toolOutputSchemas[name]));
|
|
1432
1565
|
}
|
|
1433
1566
|
function createDocsmintMcpServer(options = {}) {
|
|
1434
|
-
const server = new McpServer({ name: "docsmint", version: "0.9.
|
|
1567
|
+
const server = new McpServer({ name: "docsmint", version: "0.9.4" });
|
|
1435
1568
|
const client2 = options.docsClient ? createMcpDocsClient(options.docsClient, options.requestContext) : options.client ?? createMcpDocsClient(createDefaultDocsClient(), options.requestContext);
|
|
1436
1569
|
registerDocsmintMcpCapabilities(server, client2);
|
|
1437
1570
|
return server;
|
package/dist/types.d.ts
CHANGED
|
@@ -141,6 +141,15 @@ export interface DocsTag {
|
|
|
141
141
|
createdAt?: string;
|
|
142
142
|
documentCount?: number;
|
|
143
143
|
}
|
|
144
|
+
export interface DocsTrashResponse {
|
|
145
|
+
documents: Array<{
|
|
146
|
+
id: string;
|
|
147
|
+
title: string;
|
|
148
|
+
deletedAt: string;
|
|
149
|
+
purgeAfter: string | null;
|
|
150
|
+
}>;
|
|
151
|
+
folders: [];
|
|
152
|
+
}
|
|
144
153
|
/**
|
|
145
154
|
* Search hit as returned by `GET /api/search`. The backend uses
|
|
146
155
|
* snake_case in the JSON payload — we mirror that exactly here so
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ import { registerSearch } from './commands/search.js';
|
|
|
25
25
|
import { registerSnapshot } from './commands/snapshot.js';
|
|
26
26
|
import { registerUpdate } from './commands/update.js';
|
|
27
27
|
|
|
28
|
-
const VERSION = '0.9.
|
|
28
|
+
const VERSION = '0.9.4';
|
|
29
29
|
|
|
30
30
|
const program = new Command();
|
|
31
31
|
program.name('docsmint').description('CLI for the DocsMint knowledge workspace').version(VERSION);
|
package/server.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"id": "1249550690",
|
|
11
11
|
"subfolder": "packages/mcp-server"
|
|
12
12
|
},
|
|
13
|
-
"version": "0.9.
|
|
13
|
+
"version": "0.9.4",
|
|
14
14
|
"icons": [
|
|
15
15
|
{
|
|
16
16
|
"src": "https://raw.githubusercontent.com/HiAi-gg/docsmint/main/frontend/static/logo-dark.png",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"registryType": "npm",
|
|
35
35
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
36
36
|
"identifier": "@hiai-gg/docsmint",
|
|
37
|
-
"version": "0.9.
|
|
37
|
+
"version": "0.9.4",
|
|
38
38
|
"runtimeHint": "npx",
|
|
39
39
|
"transport": {
|
|
40
40
|
"type": "stdio"
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"licenseFile": "https://github.com/HiAi-gg/docsmint/blob/main/LICENSE",
|
|
88
88
|
"documentationUrl": "https://docsmint.com/mcp/connect?source=mcp_registry",
|
|
89
89
|
"catalog": {
|
|
90
|
-
"tools":
|
|
90
|
+
"tools": 31,
|
|
91
91
|
"prompts": 2,
|
|
92
92
|
"resources": 3
|
|
93
93
|
}
|