@hiai-gg/docsmint 0.6.0 → 0.6.2

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.
@@ -46,6 +46,7 @@ __export(exports_schema, {
46
46
  documentRelations: () => documentRelations,
47
47
  documentPipelineRuns: () => documentPipelineRuns,
48
48
  documentPipelineBatches: () => documentPipelineBatches,
49
+ documentKnowledgeSummaries: () => documentKnowledgeSummaries,
49
50
  documentEmbeddings: () => documentEmbeddings,
50
51
  documentEmbeddingRelations: () => documentEmbeddingRelations,
51
52
  documentCreateOperations: () => documentCreateOperations,
@@ -310,6 +311,22 @@ var documentPipelineBatches = pgTable("document_pipeline_batches", {
310
311
  index("document_pipeline_batches_stage_status_available_idx").on(table.stage, table.status, table.availableAt),
311
312
  index("document_pipeline_batches_document_id_idx").on(table.documentId)
312
313
  ]);
314
+ var documentKnowledgeSummaries = pgTable("document_knowledge_summaries", {
315
+ id: uuid().primaryKey().defaultRandom(),
316
+ document_id: uuid().notNull().references(() => documents.id, { onDelete: "cascade" }),
317
+ owner_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }),
318
+ workspace_id: text(),
319
+ generation_id: uuid().notNull(),
320
+ revision: text().notNull(),
321
+ language: text().notNull(),
322
+ description: text().notNull(),
323
+ keywords: text().array().notNull().default(sql`ARRAY[]::text[]`),
324
+ created_at: timestamp().defaultNow().notNull(),
325
+ updated_at: timestamp().defaultNow().notNull()
326
+ }, (table) => [
327
+ uniqueIndex("document_knowledge_summaries_document_generation_idx").on(table.document_id, table.generation_id),
328
+ index("document_knowledge_summaries_owner_document_idx").on(table.owner_id, table.document_id)
329
+ ]);
313
330
  var tags = pgTable("tags", {
314
331
  id: uuid("id").primaryKey().defaultRandom(),
315
332
  ownerId: uuid("owner_id").notNull().references(() => users.id, { onDelete: "cascade" }),
@@ -46,6 +46,7 @@ __export(exports_schema, {
46
46
  documentRelations: () => documentRelations,
47
47
  documentPipelineRuns: () => documentPipelineRuns,
48
48
  documentPipelineBatches: () => documentPipelineBatches,
49
+ documentKnowledgeSummaries: () => documentKnowledgeSummaries,
49
50
  documentEmbeddings: () => documentEmbeddings,
50
51
  documentEmbeddingRelations: () => documentEmbeddingRelations,
51
52
  documentCreateOperations: () => documentCreateOperations,
@@ -310,6 +311,22 @@ var documentPipelineBatches = pgTable("document_pipeline_batches", {
310
311
  index("document_pipeline_batches_stage_status_available_idx").on(table.stage, table.status, table.availableAt),
311
312
  index("document_pipeline_batches_document_id_idx").on(table.documentId)
312
313
  ]);
314
+ var documentKnowledgeSummaries = pgTable("document_knowledge_summaries", {
315
+ id: uuid().primaryKey().defaultRandom(),
316
+ document_id: uuid().notNull().references(() => documents.id, { onDelete: "cascade" }),
317
+ owner_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }),
318
+ workspace_id: text(),
319
+ generation_id: uuid().notNull(),
320
+ revision: text().notNull(),
321
+ language: text().notNull(),
322
+ description: text().notNull(),
323
+ keywords: text().array().notNull().default(sql`ARRAY[]::text[]`),
324
+ created_at: timestamp().defaultNow().notNull(),
325
+ updated_at: timestamp().defaultNow().notNull()
326
+ }, (table) => [
327
+ uniqueIndex("document_knowledge_summaries_document_generation_idx").on(table.document_id, table.generation_id),
328
+ index("document_knowledge_summaries_owner_document_idx").on(table.owner_id, table.document_id)
329
+ ]);
313
330
  var tags = pgTable("tags", {
314
331
  id: uuid("id").primaryKey().defaultRandom(),
315
332
  ownerId: uuid("owner_id").notNull().references(() => users.id, { onDelete: "cascade" }),
@@ -46,6 +46,7 @@ __export(exports_schema, {
46
46
  documentRelations: () => documentRelations,
47
47
  documentPipelineRuns: () => documentPipelineRuns,
48
48
  documentPipelineBatches: () => documentPipelineBatches,
49
+ documentKnowledgeSummaries: () => documentKnowledgeSummaries,
49
50
  documentEmbeddings: () => documentEmbeddings,
50
51
  documentEmbeddingRelations: () => documentEmbeddingRelations,
51
52
  documentCreateOperations: () => documentCreateOperations,
@@ -310,6 +311,22 @@ var documentPipelineBatches = pgTable("document_pipeline_batches", {
310
311
  index("document_pipeline_batches_stage_status_available_idx").on(table.stage, table.status, table.availableAt),
311
312
  index("document_pipeline_batches_document_id_idx").on(table.documentId)
312
313
  ]);
314
+ var documentKnowledgeSummaries = pgTable("document_knowledge_summaries", {
315
+ id: uuid().primaryKey().defaultRandom(),
316
+ document_id: uuid().notNull().references(() => documents.id, { onDelete: "cascade" }),
317
+ owner_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }),
318
+ workspace_id: text(),
319
+ generation_id: uuid().notNull(),
320
+ revision: text().notNull(),
321
+ language: text().notNull(),
322
+ description: text().notNull(),
323
+ keywords: text().array().notNull().default(sql`ARRAY[]::text[]`),
324
+ created_at: timestamp().defaultNow().notNull(),
325
+ updated_at: timestamp().defaultNow().notNull()
326
+ }, (table) => [
327
+ uniqueIndex("document_knowledge_summaries_document_generation_idx").on(table.document_id, table.generation_id),
328
+ index("document_knowledge_summaries_owner_document_idx").on(table.owner_id, table.document_id)
329
+ ]);
313
330
  var tags = pgTable("tags", {
314
331
  id: uuid("id").primaryKey().defaultRandom(),
315
332
  ownerId: uuid("owner_id").notNull().references(() => users.id, { onDelete: "cascade" }),
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, DocsCategoryInput, DocsCategoryUpdate, DocsDocument, DocsDocumentCreateInput, DocsDocumentCursorPage, DocsDocumentListResponse, DocsDocumentPipeline, 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, DocsCategoryInput, DocsCategoryUpdate, DocsDocument, DocsDocumentCreateInput, DocsDocumentCursorPage, DocsDocumentIndexRefresh, DocsDocumentIndexStatus, DocsDocumentKnowledgeSummary, DocsDocumentListResponse, DocsDocumentPipeline, DocsDocumentUpdateInput, DocsFolder, DocsFolderCreateInput, DocsFolderUpdateInput, DocsGraphEntitiesResponse, DocsGraphRelatedResponse, DocsGraphSearchResponse, DocsHealthResponse, DocsRequestContext, DocsSearchOptions, DocsSearchResponse, DocsSearchSuggestItem, DocsSharedContent, DocsShareLink, DocsShareListResponse, DocsShareRole, DocsTag, DocsVersion, DocsVersionDiff } from "./types.js";
11
11
  export interface DocsClientConfig {
12
12
  /** Base URL of the hiai-docs API, e.g. `http://localhost:50700`. */
13
13
  baseUrl: string;
@@ -81,6 +81,9 @@ export declare class DocsClient {
81
81
  }, context?: DocsRequestContext): Promise<DocsDocumentCursorPage>;
82
82
  duplicateDoc(id: string, context?: DocsRequestContext): Promise<DocsDocument>;
83
83
  getDocumentPipeline(id: string, context?: DocsRequestContext): Promise<DocsDocumentPipeline>;
84
+ getDocumentKnowledgeSummary(id: string, context?: DocsRequestContext): Promise<DocsDocumentKnowledgeSummary>;
85
+ getDocumentIndexStatus(id: string, context?: DocsRequestContext): Promise<DocsDocumentIndexStatus>;
86
+ refreshDocumentIndex(id: string, context?: DocsRequestContext): Promise<DocsDocumentIndexRefresh>;
84
87
  publishDoc(id: string, context?: DocsRequestContext): Promise<DocsDocument>;
85
88
  unpublishDoc(id: string, context?: DocsRequestContext): Promise<DocsDocument>;
86
89
  /**
package/dist/client.js CHANGED
@@ -123,6 +123,15 @@ export class DocsClient {
123
123
  async getDocumentPipeline(id, context) {
124
124
  return this.request("GET", `/api/documents/${encodeURIComponent(id)}/pipeline`, undefined, context);
125
125
  }
126
+ async getDocumentKnowledgeSummary(id, context) {
127
+ return this.request("GET", `/api/documents/${encodeURIComponent(id)}/knowledge-summary`, undefined, context);
128
+ }
129
+ async getDocumentIndexStatus(id, context) {
130
+ return this.request("GET", `/api/documents/${encodeURIComponent(id)}/index-status`, undefined, context);
131
+ }
132
+ async refreshDocumentIndex(id, context) {
133
+ return this.request("POST", `/api/documents/${encodeURIComponent(id)}/index/refresh`, undefined, context);
134
+ }
126
135
  async publishDoc(id, context) {
127
136
  return this.request("POST", `/api/documents/${encodeURIComponent(id)}/publish`, undefined, context);
128
137
  }
@@ -252,6 +252,22 @@ var documentPipelineBatches = pgTable("document_pipeline_batches", {
252
252
  index("document_pipeline_batches_stage_status_available_idx").on(table.stage, table.status, table.availableAt),
253
253
  index("document_pipeline_batches_document_id_idx").on(table.documentId)
254
254
  ]);
255
+ var documentKnowledgeSummaries = pgTable("document_knowledge_summaries", {
256
+ id: uuid().primaryKey().defaultRandom(),
257
+ document_id: uuid().notNull().references(() => documents.id, { onDelete: "cascade" }),
258
+ owner_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }),
259
+ workspace_id: text(),
260
+ generation_id: uuid().notNull(),
261
+ revision: text().notNull(),
262
+ language: text().notNull(),
263
+ description: text().notNull(),
264
+ keywords: text().array().notNull().default(sql`ARRAY[]::text[]`),
265
+ created_at: timestamp().defaultNow().notNull(),
266
+ updated_at: timestamp().defaultNow().notNull()
267
+ }, (table) => [
268
+ uniqueIndex("document_knowledge_summaries_document_generation_idx").on(table.document_id, table.generation_id),
269
+ index("document_knowledge_summaries_owner_document_idx").on(table.owner_id, table.document_id)
270
+ ]);
255
271
  var tags = pgTable("tags", {
256
272
  id: uuid("id").primaryKey().defaultRandom(),
257
273
  ownerId: uuid("owner_id").notNull().references(() => users.id, { onDelete: "cascade" }),
package/dist/types.d.ts CHANGED
@@ -356,6 +356,32 @@ export interface DocsDocumentPipeline {
356
356
  };
357
357
  updatedAt: string;
358
358
  }
359
+ export interface DocsDocumentKnowledgeSummary {
360
+ documentId: string;
361
+ generationId: string;
362
+ revision: string;
363
+ language: string;
364
+ description: string;
365
+ keywords: string[];
366
+ createdAt: string;
367
+ updatedAt: string;
368
+ }
369
+ export interface DocsDocumentIndexStatus {
370
+ documentId: string;
371
+ embeddingStatus: "pending" | "processing" | "ready" | "failed" | "stale";
372
+ activeGenerationId: string | null;
373
+ pendingGenerationId: string | null;
374
+ embeddingProfile: string | null;
375
+ embeddingErrorCode: string | null;
376
+ embeddingUpdatedAt: string | null;
377
+ searchable: boolean;
378
+ pipeline: DocsDocumentPipeline | null;
379
+ }
380
+ export interface DocsDocumentIndexRefresh {
381
+ documentId: string;
382
+ generationId: string;
383
+ deduplicated: boolean;
384
+ }
359
385
  export interface DocsVersion {
360
386
  id: string;
361
387
  documentId: string;
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@hiai-gg/docsmint",
3
- "version": "0.6.0",
3
+ "mcpName": "io.github.hiai-gg/docsmint",
4
+ "version": "0.6.2",
4
5
  "type": "module",
5
6
  "browser": {
6
7
  "./dist/backend-launcher.js": false,
@@ -57,6 +58,10 @@
57
58
  "import": "./dist/index.js",
58
59
  "types": "./dist/index.d.ts"
59
60
  },
61
+ "./mcp": {
62
+ "import": "./packages/mcp-server/src/server.ts",
63
+ "types": "./packages/mcp-server/src/server.ts"
64
+ },
60
65
  "./lifecycle": {
61
66
  "browser": "./dist/server-only-browser-entry.js",
62
67
  "import": "./dist/lifecycle.js",
@@ -349,8 +354,12 @@
349
354
  "packages/cli/src/format.ts",
350
355
  "packages/cli/src/commands",
351
356
  "packages/mcp-server/src/client.ts",
357
+ "packages/mcp-server/src/index.ts",
358
+ "packages/mcp-server/src/server.ts",
359
+ "packages/mcp-server/src/capabilities.ts",
352
360
  "packages/mcp-server/src/types.ts",
353
361
  "packages/mcp-server/src/tools",
362
+ "skills",
354
363
  "backend/src/lib/redis-factory.ts",
355
364
  "backend/src/lib/storage-factory.ts",
356
365
  "backend/src/lib/logger.ts",
@@ -358,6 +367,7 @@
358
367
  "backend/src/lib/api-keys.ts",
359
368
  "backend/src/lib/api-key-encryption.ts",
360
369
  "backend/src/lib/lifecycle-service.ts",
370
+ "server.json",
361
371
  "README.md",
362
372
  "LICENSE"
363
373
  ],
@@ -376,7 +386,7 @@
376
386
  "prepublishOnly": "cd packages/sdk && bun run build"
377
387
  },
378
388
  "dependencies": {
379
- "@modelcontextprotocol/sdk": "^1.12.1",
389
+ "@modelcontextprotocol/server": "2.0.0",
380
390
  "bullmq": "^5.80.2",
381
391
  "commander": "^13.1.0",
382
392
  "ioredis": "^5.11.1",
@@ -24,7 +24,7 @@ import { registerSearch } from "./commands/search.js";
24
24
  import { registerSnapshot } from "./commands/snapshot.js";
25
25
  import { registerUpdate } from "./commands/update.js";
26
26
 
27
- const VERSION = "0.6.0";
27
+ const VERSION = "0.6.2";
28
28
 
29
29
  const program = new Command();
30
30
  program
@@ -1,14 +1,23 @@
1
- export * from "./schema";
2
- export { db, client } from "./client";
3
1
  export type { Database } from "./client";
2
+ export { client, db } from "./client";
3
+ export type {
4
+ CreateDocumentWithVersionInput,
5
+ UpdateDocumentWithVersionInput,
6
+ } from "./document-writer";
4
7
  export {
5
- withTenant,
6
- adminTenantContext,
7
- shareGuestTenantContext,
8
- createActorScopedTransactionExecutor,
9
- } from "./with-tenant";
8
+ createDocumentWithVersion,
9
+ trashDocuments,
10
+ updateDocumentWithVersion,
11
+ } from "./document-writer";
12
+ export * from "./schema";
10
13
  export type {
11
14
  ActorScopedTransactionExecutor,
12
15
  TenantContext,
13
16
  TenantTransaction,
14
17
  } from "./with-tenant";
18
+ export {
19
+ adminTenantContext,
20
+ createActorScopedTransactionExecutor,
21
+ shareGuestTenantContext,
22
+ withTenant,
23
+ } from "./with-tenant";
@@ -354,6 +354,40 @@ export const documentPipelineBatches = pgTable(
354
354
  ],
355
355
  );
356
356
 
357
+ // ============================================
358
+ // document_knowledge_summaries — generation-scoped retrieval metadata
359
+ // ============================================
360
+ export const documentKnowledgeSummaries = pgTable(
361
+ "document_knowledge_summaries",
362
+ {
363
+ id: uuid().primaryKey().defaultRandom(),
364
+ document_id: uuid()
365
+ .notNull()
366
+ .references(() => documents.id, { onDelete: "cascade" }),
367
+ owner_id: uuid()
368
+ .notNull()
369
+ .references(() => users.id, { onDelete: "cascade" }),
370
+ workspace_id: text(),
371
+ generation_id: uuid().notNull(),
372
+ revision: text().notNull(),
373
+ language: text().notNull(),
374
+ description: text().notNull(),
375
+ keywords: text().array().notNull().default(sql`ARRAY[]::text[]`),
376
+ created_at: timestamp().defaultNow().notNull(),
377
+ updated_at: timestamp().defaultNow().notNull(),
378
+ },
379
+ (table) => [
380
+ uniqueIndex("document_knowledge_summaries_document_generation_idx").on(
381
+ table.document_id,
382
+ table.generation_id,
383
+ ),
384
+ index("document_knowledge_summaries_owner_document_idx").on(
385
+ table.owner_id,
386
+ table.document_id,
387
+ ),
388
+ ],
389
+ );
390
+
357
391
  // ============================================
358
392
  // tags — document tags
359
393
  // ============================================
@@ -0,0 +1,189 @@
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { z } from 'zod';
3
+
4
+ import type { HiaiDocsClient } from './client.js';
5
+
6
+ export const capabilityCatalog = {
7
+ tools: [
8
+ 'search_documents',
9
+ 'get_document',
10
+ 'create_document',
11
+ 'update_document',
12
+ 'list_documents',
13
+ 'list_folders',
14
+ 'create_folder',
15
+ 'create_snapshot',
16
+ 'get_version_history',
17
+ 'export_document',
18
+ 'list_categories',
19
+ 'create_category',
20
+ 'list_tags',
21
+ 'get_related_documents',
22
+ 'search_knowledge_graph',
23
+ 'get_document_index_status',
24
+ 'refresh_document_index',
25
+ ] as const,
26
+ prompts: ['organize_workspace', 'research_workspace'] as const,
27
+ resources: [
28
+ 'docsmint://guide/editor',
29
+ 'docsmint://guide/search',
30
+ 'docsmint://workspace/catalog',
31
+ ] as const,
32
+ };
33
+
34
+ type TextResult = { content: Array<{ type: 'text'; text: string }> };
35
+
36
+ function jsonResult(value: unknown): TextResult {
37
+ return { content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] };
38
+ }
39
+
40
+ export function registerExtendedCapabilities(server: McpServer, client: HiaiDocsClient): void {
41
+ server.registerTool(
42
+ 'list_categories',
43
+ {
44
+ description:
45
+ 'List categories visible to the API key. Category keys receive only their bound category.',
46
+ inputSchema: z.object({}),
47
+ },
48
+ async () => jsonResult(await client.listCategories())
49
+ );
50
+ server.registerTool(
51
+ 'create_category',
52
+ {
53
+ description:
54
+ 'Create a category. Requires a workspace key with write access; category keys cannot mutate categories.',
55
+ inputSchema: z.object({
56
+ name: z.string().min(1),
57
+ description: z.string().optional(),
58
+ }),
59
+ },
60
+ async (input) => jsonResult(await client.createCategory(input))
61
+ );
62
+ server.registerTool(
63
+ 'list_tags',
64
+ {
65
+ description: 'List tags visible in the workspace or bound category.',
66
+ inputSchema: z.object({}),
67
+ },
68
+ async () => jsonResult(await client.listTags())
69
+ );
70
+ server.registerTool(
71
+ 'get_related_documents',
72
+ {
73
+ description: 'Traverse the knowledge graph from one authorized document.',
74
+ inputSchema: z.object({
75
+ documentId: z.string().min(1),
76
+ limit: z.number().int().min(1).max(50).optional(),
77
+ }),
78
+ },
79
+ async ({ documentId, limit }) => jsonResult(await client.getRelatedDocuments(documentId, limit))
80
+ );
81
+ server.registerTool(
82
+ 'search_knowledge_graph',
83
+ {
84
+ description:
85
+ 'Search connected knowledge using authorized seed documents. Category keys may use only documents in their category.',
86
+ inputSchema: z.object({
87
+ query: z.string().min(1).max(1000),
88
+ docIds: z.array(z.string().min(1)).min(1),
89
+ limit: z.number().int().min(1).max(50).optional(),
90
+ }),
91
+ },
92
+ async (input) => jsonResult(await client.searchGraph(input))
93
+ );
94
+ server.registerTool(
95
+ 'get_document_index_status',
96
+ {
97
+ description: 'Read the current indexing and knowledge-pipeline status of a document.',
98
+ inputSchema: z.object({ documentId: z.string().min(1) }),
99
+ },
100
+ async ({ documentId }) => jsonResult(await client.getDocumentIndexStatus(documentId))
101
+ );
102
+ server.registerTool(
103
+ 'refresh_document_index',
104
+ {
105
+ description: 'Request reindexing after a document or metadata change. Requires write access.',
106
+ inputSchema: z.object({ documentId: z.string().min(1) }),
107
+ },
108
+ async ({ documentId }) => jsonResult(await client.refreshDocumentIndex(documentId))
109
+ );
110
+
111
+ server.registerPrompt(
112
+ 'organize_workspace',
113
+ {
114
+ description: 'Plan safe document organization using DocsMint categories and folders.',
115
+ argsSchema: z.object({
116
+ objective: z.string(),
117
+ language: z.string().optional(),
118
+ }),
119
+ },
120
+ ({ objective, language }) => ({
121
+ messages: [
122
+ {
123
+ role: 'user',
124
+ content: {
125
+ type: 'text',
126
+ text: `Organize this DocsMint workspace for: ${objective}. Work in ${language ?? 'the document language'}. Inspect categories, folders, tags, and documents before proposing or applying changes. Preserve document content and obey the API key scope.`,
127
+ },
128
+ },
129
+ ],
130
+ })
131
+ );
132
+ server.registerPrompt(
133
+ 'research_workspace',
134
+ {
135
+ description:
136
+ 'Research a question with hybrid search and GraphRAG while citing DocsMint document IDs.',
137
+ argsSchema: z.object({
138
+ question: z.string(),
139
+ language: z.string().optional(),
140
+ }),
141
+ },
142
+ ({ question, language }) => ({
143
+ messages: [
144
+ {
145
+ role: 'user',
146
+ content: {
147
+ type: 'text',
148
+ text: `Answer this question from DocsMint: ${question}. Respond in ${language ?? 'the question language'}. Start with hybrid search, use graph traversal only from authorized result documents, and cite document IDs. Distinguish retrieved facts from inference.`,
149
+ },
150
+ },
151
+ ],
152
+ })
153
+ );
154
+
155
+ server.registerResource('editor-guide', 'docsmint://guide/editor', {}, async (uri) => ({
156
+ contents: [
157
+ {
158
+ uri: uri.href,
159
+ mimeType: 'text/markdown',
160
+ text: '# DocsMint editing rules\n\nRead a document before updating it. Preserve its language, title intent, TipTap/Markdown structure, category, folder, and tags unless the user explicitly requests a change. After content changes, verify index status and request refresh only when needed.',
161
+ },
162
+ ],
163
+ }));
164
+ server.registerResource('search-guide', 'docsmint://guide/search', {}, async (uri) => ({
165
+ contents: [
166
+ {
167
+ uri: uri.href,
168
+ mimeType: 'text/markdown',
169
+ text: '# DocsMint retrieval rules\n\nUse search_documents for normal retrieval. Use get_related_documents or search_knowledge_graph only with document IDs already authorized by the active API key. Keep multilingual queries in their original language and cite document IDs in answers.',
170
+ },
171
+ ],
172
+ }));
173
+ server.registerResource('workspace-catalog', 'docsmint://workspace/catalog', {}, async (uri) => {
174
+ const [categories, folders, tags] = await Promise.all([
175
+ client.listCategories(),
176
+ client.listFolders({}),
177
+ client.listTags(),
178
+ ]);
179
+ return {
180
+ contents: [
181
+ {
182
+ uri: uri.href,
183
+ mimeType: 'application/json',
184
+ text: JSON.stringify({ categories, folders, tags }, null, 2),
185
+ },
186
+ ],
187
+ };
188
+ });
189
+ }