🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@mdedit/mcp-server

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mdedit/mcp-server - npm Package Compare versions

Comparing version
0.2.3
to
0.2.4
+100
-24
dist/index.js

@@ -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",

@@ -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