@hiai-gg/docsmint 0.9.2 → 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 CHANGED
@@ -14,32 +14,36 @@ Apache-2.0 application on your own infrastructure.
14
14
  [![Release](https://img.shields.io/github/v/release/hiai-gg/docsmint?sort=semver)](https://github.com/hiai-gg/docsmint/releases)
15
15
  [![npm](https://img.shields.io/npm/v/@hiai-gg/docsmint?logo=npm)](https://www.npmjs.com/package/@hiai-gg/docsmint)
16
16
  [![Docker Pulls](https://img.shields.io/docker/pulls/vgalibov/docsmint?logo=docker)](https://hub.docker.com/r/vgalibov/docsmint)
17
- [![Stars](https://img.shields.io/github/stars/hiai-gg/docsmint)](https://github.com/hiai-gg/docsmint/stargazers)
18
17
  [![CI](https://github.com/hiai-gg/docsmint/actions/workflows/ci.yml/badge.svg)](https://github.com/hiai-gg/docsmint/actions/workflows/ci.yml)
18
+
19
+ [![DocsMint MCP server](https://glama.ai/mcp/servers/HiAi-gg/docsmint/badges/score.svg)](https://glama.ai/mcp/servers/HiAi-gg/docsmint)
20
+ [![MCP Badge](https://lobehub.com/badge/mcp/hiai-gg-docsmint)](https://lobehub.com/mcp/hiai-gg-docsmint)
21
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-Listed-0891b2)](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.HiAi-gg%2Fdocsmint/versions/latest)
22
+ [![DocsMint Cloud](https://img.shields.io/badge/DocsMint_Cloud-Connect-16a34a)](https://docsmint.com/mcp/connect?source=github_mcp)
23
+
19
24
  [![Bun](https://img.shields.io/badge/Runtime-Bun_1.4-black?logo=bun&logoColor=white)](https://bun.sh)
20
25
  [![TypeScript](https://img.shields.io/badge/TypeScript-6.x-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org)
21
26
  [![Svelte](https://img.shields.io/badge/Svelte-5.x-FF3E00?logo=svelte&logoColor=white)](https://svelte.dev)
22
27
  [![Elysia](https://img.shields.io/badge/Elysia-1.4-lightgrey?logo=elysia&logoColor=white)](https://elysiajs.com)
23
28
  [![Tailwind_CSS](https://img.shields.io/badge/Tailwind_CSS-v4-06B6D4?logo=tailwindcss&logoColor=white)](https://tailwindcss.com)
24
29
  [![Drizzle_ORM](https://img.shields.io/badge/Drizzle_ORM-0.45-C5F74F?logo=drizzle&logoColor=black)](https://orm.drizzle.team)
30
+ [![Stars](https://img.shields.io/github/stars/hiai-gg/docsmint)](https://github.com/hiai-gg/docsmint/stargazers)
25
31
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
26
- [![MCP Badge](https://lobehub.com/badge/mcp/hiai-gg-docsmint)](https://lobehub.com/mcp/hiai-gg-docsmint)
27
- [![DocsMint Cloud](https://img.shields.io/badge/DocsMint_Cloud-Connect-16a34a)](https://docsmint.com/mcp/connect?source=github_mcp)
28
- [![MCP Registry](https://img.shields.io/badge/MCP_Registry-Listed-0891b2)](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 use your own self-hosted deployment. Search,
35
- read, create, organize and update persistent knowledge through MCP with hybrid
36
- retrieval, reranking and GraphRAG.
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
- create an MCP/API credential in the authenticated browser UI, follow your client's
41
- instructions, and verify the connection. Hosted MCP follows your plan and
42
- workspace permissions. Prefer workspace-bound or category-scoped credentials.
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,11 +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`. The npm package is a stdio
57
- bridge to your own API, not a server installer or hosted OAuth server. See the
58
- [MCP guide](https://github.com/HiAi-gg/docsmint/blob/main/packages/mcp-server/README.md) for client configuration.
59
- The open-source [Glama Server directory](https://glama.ai/mcp/servers) uses this
60
- stdio bridge; the hosted DocsMint Cloud Connector is a separate listing.
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.
61
67
 
62
68
  ## Why DocsMint?
63
69
 
@@ -74,15 +80,14 @@ stdio bridge; the hosted DocsMint Cloud Connector is a separate listing.
74
80
  - **Choose how you run it.** Use [managed DocsMint](https://docsmint.com) or
75
81
  self-host the application, database, search, queues, and files.
76
82
 
77
- ## What's new in 0.9.2?
83
+ ## What's new in 0.9.4?
78
84
 
79
- - Prepare the open-source MCP stdio bridge for a separate Glama Server listing
80
- with a schema-valid organization maintainer claim.
81
- - Clarify that Glama-hosted stdio needs a reachable self-hosted DocsMint API
82
- and an API key; DocsMint Cloud remains a separate hosted Connector.
83
- - Keep the existing 21 tools, 2 prompts, 3 resources, and API-key behavior.
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.
84
89
 
85
- This release adds no database migration. See the [release notes](https://github.com/HiAi-gg/docsmint/releases/tag/v0.9.2)
90
+ This release adds no database migration. See the [release notes](https://github.com/HiAi-gg/docsmint/releases/tag/v0.9.4)
86
91
  and [changelog](https://github.com/HiAi-gg/docsmint/blob/main/CHANGELOG.md).
87
92
 
88
93
  ## Install with an AI agent
@@ -135,7 +140,7 @@ docker pull vgalibov/docsmint:web-latest
135
140
  docker pull vgalibov/docsmint:caddy-latest
136
141
  ```
137
142
 
138
- Use versioned tags `api-v0.9.2`, `web-v0.9.2`, and `caddy-v0.9.2` for
143
+ Use versioned tags `api-v0.9.4`, `web-v0.9.4`, and `caddy-v0.9.4` for
139
144
  reproducible deploys. Caddy is the supporting reverse proxy with rate limiting;
140
145
  it is separate from the API and web application. The quickstart still builds the Compose stack from this repository so PostgreSQL,
141
146
  Redis, and SeaweedFS start together with the application.
@@ -238460,7 +238460,7 @@ var swaggerConfig = {
238460
238460
  },
238461
238461
  info: {
238462
238462
  title: "DocsMint API",
238463
- version: "0.9.2",
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 z14 } from "zod";
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/capabilities.ts
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: z3.object({}),
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: z3.object({
876
- name: z3.string().trim().min(1).max(255).describe("Non-empty display name, up to 255 characters, for example Project notes.")
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: z3.object({}),
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: z3.object({
900
- documentId: z3.string().min(1).describe("Document ID returned by search_documents or list_documents; it must be readable in the active scope."),
901
- limit: z3.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
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: z3.object({
914
- query: z3.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."),
915
- docIds: z3.array(z3.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."),
916
- limit: z3.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
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: z3.object({
929
- documentId: z3.string().uuid().describe("UUID of a document returned by search_documents or list_documents; it must be readable in the active scope.")
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: z3.object({
942
- documentId: z3.string().uuid().describe("UUID of the document to refresh, obtained from search_documents or list_documents and visible in the active scope.")
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: z3.object({
949
- objective: z3.string(),
950
- language: z3.string().optional()
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: z3.object({
966
- question: z3.string(),
967
- language: z3.string().optional()
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 z4 } from "zod";
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: z4.string().min(1).max(500).optional().describe("Optional title from 1 to 500 characters; omit to use the API default \u201CUntitled\u201D."),
1114
- content: z4.string().optional().describe("Optional initial Markdown content; omit to create an empty document."),
1115
- folderId: z4.string().uuid().optional().describe("Optional folder UUID from list_folders; the folder must be writable in the active workspace or category."),
1116
- categoryId: z4.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.")
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 z5 } from "zod";
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: z5.string().min(1).max(255).describe("Non-empty folder name up to 255 characters."),
1137
- parentId: z5.string().uuid().nullable().optional().describe("Optional parent folder UUID from list_folders; omit or pass null to create a root-level folder."),
1138
- categoryId: z5.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.")
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 z6 } from "zod";
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: z6.string().uuid().describe("UUID of the existing document, obtained from search_documents or list_documents and visible in the active scope."),
1159
- label: z6.string().min(1).max(200).describe("Non-empty snapshot label up to 200 characters, for example 'v1.0-release'."),
1160
- description: z6.string().max(1000).optional().describe("Optional snapshot note up to 1,000 characters; omit if not needed.")
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 z7 } from "zod";
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: z7.string().uuid().describe("UUID of the readable document to export, obtained from search_documents or list_documents.")
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 z8 } from "zod";
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: z8.string().uuid().describe("UUID of the document, obtained from search_documents or list_documents, and visible in the active scope.")
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 z9 } from "zod";
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: z9.string().uuid().optional().describe("Optional folder UUID from list_folders to limit the listing."),
1222
- tag: z9.string().uuid().optional().describe("Optional tag UUID from list_tags to filter the documents."),
1223
- page: z9.number().int().min(1).optional().describe("1-indexed result page; defaults to 1."),
1224
- limit: z9.number().int().min(1).max(1000).optional().describe("Number of documents per page, from 1 to 1,000; defaults to 20.")
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 z10 } from "zod";
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: z10.string().uuid().optional().describe("Optional parent folder UUID from list_folders; omit to list root folders.")
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 z11 } from "zod";
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: z11.string().describe("Text to search for; preserve the language and terms relevant to the user request."),
1265
- folder: z11.string().optional().describe("Optional folder UUID from list_folders to scope retrieval."),
1266
- tags: z11.array(z11.string()).optional().describe("Optional tag names as shown by list_tags; documents match when they have any supplied tag name."),
1267
- limit: z11.number().int().positive().max(100).optional().describe("Maximum result count, from 1 to 100; defaults to 20.")
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 z12 } from "zod";
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: z12.string().uuid().describe("UUID of the existing document, obtained from search_documents, list_documents, or get_document."),
1293
- title: z12.string().min(1).max(500).optional().describe("Optional replacement title, 1 to 500 characters; omit to leave the current title unchanged."),
1294
- content: z12.string().optional().describe("New markdown content for the document."),
1295
- folderId: z12.string().uuid().nullable().optional().describe("Optional destination folder UUID from list_folders; omit to keep current placement or pass null to remove folder placement."),
1296
- categoryId: z12.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.")
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 z13 } from "zod";
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: z13.string().uuid().describe("UUID of the readable document whose version history you need; obtain it from search_documents or list_documents."),
1318
- onlySnapshots: z13.boolean().optional().describe("When true, return only named snapshots and omit auto-saved revisions; omit or use false for the full history.")
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: z14.object(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.2" });
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;
@@ -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 z14 } from "zod";
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/capabilities.ts
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: z3.object({}),
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: z3.object({
903
- name: z3.string().trim().min(1).max(255).describe("Non-empty display name, up to 255 characters, for example Project notes.")
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: z3.object({}),
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: z3.object({
927
- documentId: z3.string().min(1).describe("Document ID returned by search_documents or list_documents; it must be readable in the active scope."),
928
- limit: z3.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
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: z3.object({
941
- query: z3.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."),
942
- docIds: z3.array(z3.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."),
943
- limit: z3.number().int().min(1).max(100).optional().describe("Maximum related documents to return, from 1 to 100. Omit to use the server default.")
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: z3.object({
956
- documentId: z3.string().uuid().describe("UUID of a document returned by search_documents or list_documents; it must be readable in the active scope.")
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: z3.object({
969
- documentId: z3.string().uuid().describe("UUID of the document to refresh, obtained from search_documents or list_documents and visible in the active scope.")
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: z3.object({
976
- objective: z3.string(),
977
- language: z3.string().optional()
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: z3.object({
993
- question: z3.string(),
994
- language: z3.string().optional()
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 z4 } from "zod";
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: z4.string().min(1).max(500).optional().describe("Optional title from 1 to 500 characters; omit to use the API default \u201CUntitled\u201D."),
1141
- content: z4.string().optional().describe("Optional initial Markdown content; omit to create an empty document."),
1142
- folderId: z4.string().uuid().optional().describe("Optional folder UUID from list_folders; the folder must be writable in the active workspace or category."),
1143
- categoryId: z4.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.")
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 z5 } from "zod";
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: z5.string().min(1).max(255).describe("Non-empty folder name up to 255 characters."),
1164
- parentId: z5.string().uuid().nullable().optional().describe("Optional parent folder UUID from list_folders; omit or pass null to create a root-level folder."),
1165
- categoryId: z5.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.")
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 z6 } from "zod";
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: z6.string().uuid().describe("UUID of the existing document, obtained from search_documents or list_documents and visible in the active scope."),
1186
- label: z6.string().min(1).max(200).describe("Non-empty snapshot label up to 200 characters, for example 'v1.0-release'."),
1187
- description: z6.string().max(1000).optional().describe("Optional snapshot note up to 1,000 characters; omit if not needed.")
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 z7 } from "zod";
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: z7.string().uuid().describe("UUID of the readable document to export, obtained from search_documents or list_documents.")
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 z8 } from "zod";
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: z8.string().uuid().describe("UUID of the document, obtained from search_documents or list_documents, and visible in the active scope.")
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 z9 } from "zod";
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: z9.string().uuid().optional().describe("Optional folder UUID from list_folders to limit the listing."),
1249
- tag: z9.string().uuid().optional().describe("Optional tag UUID from list_tags to filter the documents."),
1250
- page: z9.number().int().min(1).optional().describe("1-indexed result page; defaults to 1."),
1251
- limit: z9.number().int().min(1).max(1000).optional().describe("Number of documents per page, from 1 to 1,000; defaults to 20.")
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 z10 } from "zod";
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: z10.string().uuid().optional().describe("Optional parent folder UUID from list_folders; omit to list root folders.")
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 z11 } from "zod";
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: z11.string().describe("Text to search for; preserve the language and terms relevant to the user request."),
1292
- folder: z11.string().optional().describe("Optional folder UUID from list_folders to scope retrieval."),
1293
- tags: z11.array(z11.string()).optional().describe("Optional tag names as shown by list_tags; documents match when they have any supplied tag name."),
1294
- limit: z11.number().int().positive().max(100).optional().describe("Maximum result count, from 1 to 100; defaults to 20.")
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 z12 } from "zod";
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: z12.string().uuid().describe("UUID of the existing document, obtained from search_documents, list_documents, or get_document."),
1320
- title: z12.string().min(1).max(500).optional().describe("Optional replacement title, 1 to 500 characters; omit to leave the current title unchanged."),
1321
- content: z12.string().optional().describe("New markdown content for the document."),
1322
- folderId: z12.string().uuid().nullable().optional().describe("Optional destination folder UUID from list_folders; omit to keep current placement or pass null to remove folder placement."),
1323
- categoryId: z12.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.")
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 z13 } from "zod";
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: z13.string().uuid().describe("UUID of the readable document whose version history you need; obtain it from search_documents or list_documents."),
1345
- onlySnapshots: z13.boolean().optional().describe("When true, return only named snapshots and omit auto-saved revisions; omit or use false for the full history.")
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: z14.object(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.2" });
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hiai-gg/docsmint",
3
3
  "mcpName": "io.github.HiAi-gg/docsmint",
4
- "version": "0.9.2",
4
+ "version": "0.9.4",
5
5
  "type": "module",
6
6
  "browser": {
7
7
  "./dist/backend-launcher.js": false,
@@ -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.2';
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.2",
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.2",
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": 21,
90
+ "tools": 31,
91
91
  "prompts": 2,
92
92
  "resources": 3
93
93
  }