@mdedit/mcp-server
Advanced tools
+100
-24
@@ -99,2 +99,12 @@ // src/index.ts | ||
| var requiredId = z.string().trim().min(1); | ||
| var reviewThreadIdSchema = z.string({ | ||
| error: "threadId is required; pass the exact add_comment.threadId value (not commandId)." | ||
| }).trim().min(1, { | ||
| error: "threadId cannot be empty; pass the exact add_comment.threadId value (not commandId)." | ||
| }).describe( | ||
| "The exact threadId returned by add_comment. Pass it with add_comment.targetId; do not pass add_comment.commandId." | ||
| ); | ||
| var reviewThreadTargetIdSchema = z.string().trim().min(1).optional().describe( | ||
| "The exact targetId returned by add_comment. Pass it with add_comment.threadId, especially for targets other than content.md." | ||
| ); | ||
| var quoteAnchorSchema = z.object({ | ||
@@ -138,2 +148,21 @@ quote: z.string().min(1), | ||
| }).strict(); | ||
| var publicationModeInputSchema = z.enum(["live", "snapshot"]).describe( | ||
| "Choose live for a link that follows later durable edits, or a frozen snapshot for a fixed artifact. Omit this only to preserve an existing link mode; new links default to live." | ||
| ); | ||
| var publicationModeOutputSchema = z.enum(["snapshot", "live"]); | ||
| var publicationSyncStatusSchema = z.enum([ | ||
| "idle", | ||
| "queued", | ||
| "syncing", | ||
| "succeeded", | ||
| "failed" | ||
| ]); | ||
| var publicationSourceOutputShape = { | ||
| sourceArticleRevision: z.number().int().nonnegative().optional(), | ||
| sourceContentRevision: z.number().int().nonnegative().optional(), | ||
| sourcePackageRevision: z.number().int().nonnegative().optional(), | ||
| sourceContentHash: z.string().optional(), | ||
| sourceVersionId: z.string().optional(), | ||
| lastSuccessfulSyncAt: z.number().optional() | ||
| }; | ||
| var mutationOptionsSchema = { | ||
@@ -186,3 +215,6 @@ targetId: z.string().min(1).optional(), | ||
| fullUrl: z.string().url(), | ||
| publishedAt: z.number() | ||
| publishedAt: z.number(), | ||
| mode: publicationModeOutputSchema, | ||
| ...publicationSourceOutputShape, | ||
| syncStatus: publicationSyncStatusSchema | ||
| }); | ||
@@ -198,3 +230,7 @@ var publishStatusOutputSchema = articleIdentityOutputSchema.extend({ | ||
| customSlug: z.string().optional(), | ||
| seoMetadata: seoMetadataSchema.optional() | ||
| seoMetadata: seoMetadataSchema.optional(), | ||
| mode: publicationModeOutputSchema.optional(), | ||
| ...publicationSourceOutputShape, | ||
| syncStatus: publicationSyncStatusSchema.optional(), | ||
| syncError: z.string().max(500).optional() | ||
| }); | ||
@@ -210,2 +246,10 @@ var unpublishOutputSchema = articleIdentityOutputSchema.extend({ | ||
| }); | ||
| var addCommentOutputSchema = reviewMutationOutputSchema.extend({ | ||
| threadId: z.string().describe( | ||
| "Stable review thread identifier. Pass this exact value with targetId to resolve_thread or reply_to_thread; do not use commandId." | ||
| ), | ||
| targetId: z.string().describe( | ||
| "Review target containing the new thread. Pass this exact value with threadId to resolve_thread or reply_to_thread." | ||
| ) | ||
| }); | ||
| var MCP_TOOL_OUTPUT_SCHEMAS = { | ||
@@ -238,3 +282,3 @@ list_workspaces: z.object({ workspaces: z.array(workspaceSummaryOutputSchema) }), | ||
| }), | ||
| add_comment: reviewMutationOutputSchema, | ||
| add_comment: addCommentOutputSchema, | ||
| add_suggestion: reviewMutationOutputSchema, | ||
@@ -251,2 +295,14 @@ reply_to_thread: reviewMutationOutputSchema, | ||
| }; | ||
| function isCreatedReviewEvent(event) { | ||
| if (typeof event !== "object" || event === null) return false; | ||
| const candidate = event; | ||
| return candidate.type === "created" && typeof candidate.reviewId === "string" && candidate.reviewId.trim().length > 0 && typeof candidate.targetId === "string" && candidate.targetId.trim().length > 0; | ||
| } | ||
| function createdReviewThread(events) { | ||
| const created = events.find(isCreatedReviewEvent); | ||
| if (!created) { | ||
| throw new Error("add_comment response did not include the created review thread identifier and target"); | ||
| } | ||
| return { threadId: created.reviewId, targetId: created.targetId }; | ||
| } | ||
| var MDEDIT_MCP_TOOL_SCOPES = { | ||
@@ -544,2 +600,7 @@ list_workspaces: ["workspaces:read"], | ||
| } | ||
| async function agentPublishRequest(dependencies, workspaceId, articleId, request) { | ||
| if (request.mode) return request; | ||
| const status = await dependencies.getPublishStatus(workspaceId, articleId); | ||
| return status.isPublished ? request : { ...request, mode: "live" }; | ||
| } | ||
| function success(value) { | ||
@@ -622,3 +683,3 @@ return { | ||
| "Use edit_article only when the API key has articles:write scope.", | ||
| "Publishing makes a document public; call publish_article only after the user explicitly confirms." | ||
| "Publishing makes a document public; call publish_article only after the user explicitly confirms. New links are live by default and follow later durable edits; request snapshot mode for a frozen artifact." | ||
| ].join(" ") | ||
@@ -759,7 +820,8 @@ } | ||
| title: "Publish a Markdown Document", | ||
| description: "Publish or update a Markdown Document at a public mded.it link. Requires publishing:write and explicit user confirmation.", | ||
| description: "Publish or update a Markdown Document at a public mded.it link. New links default to live. Later durable edits automatically update a live link at the same URL. Choose snapshot for a frozen artifact. Existing links keep their stored mode unless mode is supplied. Requires publishing:write and explicit user confirmation.", | ||
| inputSchema: articleInputSchema.extend({ | ||
| confirmPublic: z.literal(true).describe("Must be true after the user confirms that anyone with the link may view the document."), | ||
| customSlug: z.string().trim().min(1).optional(), | ||
| seoMetadata: seoMetadataSchema.optional() | ||
| seoMetadata: seoMetadataSchema.optional(), | ||
| mode: publicationModeInputSchema.optional() | ||
| }).strict(), | ||
@@ -769,10 +831,19 @@ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }, | ||
| }, | ||
| ({ workspaceId, articleId, customSlug, seoMetadata }) => invokeTool("publish_article", async () => ({ | ||
| workspaceId, | ||
| articleId, | ||
| ...await dependencies.publishArticle(workspaceId, articleId, { | ||
| customSlug, | ||
| seoMetadata | ||
| }) | ||
| })) | ||
| ({ workspaceId, articleId, customSlug, seoMetadata, mode }) => invokeTool("publish_article", async () => { | ||
| const request = await agentPublishRequest( | ||
| dependencies, | ||
| workspaceId, | ||
| articleId, | ||
| { | ||
| customSlug, | ||
| seoMetadata, | ||
| mode | ||
| } | ||
| ); | ||
| return { | ||
| workspaceId, | ||
| articleId, | ||
| ...await dependencies.publishArticle(workspaceId, articleId, request) | ||
| }; | ||
| }) | ||
| ); | ||
@@ -783,3 +854,3 @@ server.registerTool( | ||
| title: "Get Markdown Document publish status", | ||
| description: "Get the public-link publishing status, URL, metadata, and view count for a Markdown Document.", | ||
| description: "Get the stable public-link URL, stored live/snapshot mode, source revision/version, synchronization status, last successful sync, metadata, and view count for a Markdown Document.", | ||
| inputSchema: articleInputSchema, | ||
@@ -843,3 +914,3 @@ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, | ||
| title: "Add a review comment", | ||
| description: "Add an anchored review comment without directly changing document prose.", | ||
| description: "Add an anchored review comment without directly changing document prose. Returns threadId and targetId for reply_to_thread and resolve_thread.", | ||
| inputSchema: articleInputSchema.extend({ | ||
@@ -853,7 +924,11 @@ anchor: z.union([quoteAnchorSchema, rangeAnchorSchema]), | ||
| }, | ||
| ({ workspaceId, articleId, anchor, body, targetId, commandId }) => invokeTool("add_comment", () => pool.use(workspaceId, articleId, async (session) => ({ | ||
| workspaceId, | ||
| articleId, | ||
| ...await session.review.addComment({ anchor, body, targetId, commandId }) | ||
| }))) | ||
| ({ workspaceId, articleId, anchor, body, targetId, commandId }) => invokeTool("add_comment", () => pool.use(workspaceId, articleId, async (session) => { | ||
| const result = await session.review.addComment({ anchor, body, targetId, commandId }); | ||
| return { | ||
| workspaceId, | ||
| articleId, | ||
| ...result, | ||
| ...createdReviewThread(result.events) | ||
| }; | ||
| })) | ||
| ); | ||
@@ -903,6 +978,7 @@ server.registerTool( | ||
| title: "Resolve a review thread", | ||
| description: "Resolve an existing review thread.", | ||
| description: "Resolve an existing review thread using the exact threadId and targetId returned by add_comment, not commandId.", | ||
| inputSchema: articleInputSchema.extend({ | ||
| threadId: requiredId, | ||
| ...mutationOptionsSchema | ||
| threadId: reviewThreadIdSchema, | ||
| ...mutationOptionsSchema, | ||
| targetId: reviewThreadTargetIdSchema | ||
| }).strict(), | ||
@@ -909,0 +985,0 @@ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }, |
+3
-3
| { | ||
| "name": "@mdedit/mcp-server", | ||
| "version": "0.2.3", | ||
| "version": "0.2.4", | ||
| "private": false, | ||
@@ -54,4 +54,4 @@ "type": "module", | ||
| "dependencies": { | ||
| "@mdedit/agent-client": "1.0.2", | ||
| "@mdedit/sdk": "0.3.3", | ||
| "@mdedit/agent-client": "1.0.3", | ||
| "@mdedit/sdk": "0.3.4", | ||
| "@modelcontextprotocol/sdk": "^1.29.0", | ||
@@ -58,0 +58,0 @@ "@napi-rs/keyring": "^1.3.0", |
+11
-1
@@ -26,3 +26,3 @@ # @mdedit/mcp-server | ||
| Agents that publish public links need `publishing:write`; publication status only needs | ||
| `publishing:read`. Publishing does not happen implicitly after edits. | ||
| `publishing:read`. | ||
@@ -48,2 +48,12 @@ ## Tools | ||
| For a new link, `publish_article` defaults to `mode: "live"`. Later durable edits | ||
| automatically update a Live link at the same stable URL. Pass `mode: "snapshot"` for | ||
| a frozen artifact. When updating an existing link, omit `mode` to preserve the stored | ||
| mode, or pass `"live"` / `"snapshot"` to switch deliberately. | ||
| `publish_article` and `get_publish_status` return the stored mode, source | ||
| revision/version, last successful sync time, and synchronization status. A failed Live | ||
| sync leaves the last good public content and URL available; inspect `syncStatus` and | ||
| `syncError` before claiming the public page is current. | ||
| Local stdio keeps one live collaborative session open across tool calls. The | ||
@@ -50,0 +60,0 @@ hosted HTTP adapter uses operation-scoped sessions and does not depend on |
Sorry, the diff of this file is too big to display
178701
6.33%1662
4.86%83
13.7%+ Added
+ Added
- Removed
- Removed
Updated
Updated