@lalalic/markcut 3.2.10 → 3.2.11

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.
Files changed (2) hide show
  1. package/package.json +3 -2
  2. package/src/mcp/server.mjs +85 -66
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lalalic/markcut",
3
- "version": "3.2.10",
3
+ "version": "3.2.11",
4
4
  "description": "Markdown-to-video engine. Describe scenes in markdown, get a rendered video.",
5
5
  "bin": {
6
6
  "markcut": "bin/markcut"
@@ -38,7 +38,8 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/standalone": "^8.0.3",
41
- "@modelcontextprotocol/sdk": "^1.32.1",
41
+ "@modelcontextprotocol/ext-apps": "^2.0.3",
42
+ "@modelcontextprotocol/server": "^2.3.1",
42
43
  "@remotion/cli": "4.0.469",
43
44
  "@remotion/media-parser": "4.0.469",
44
45
  "@remotion/media-utils": "4.0.469",
@@ -1,81 +1,100 @@
1
1
  #!/usr/bin/env node
2
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import {
5
- CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema,
6
- ReadResourceRequestSchema,
7
- } from "@modelcontextprotocol/sdk/types.js";
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
4
+ import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
5
+ import { z } from "zod";
8
6
  import {
9
7
  TOOL_NAME, SUBMIT_TOOL_NAME, RESOURCE_URI, buildPreviewHtml, readMarkdownPreview, reviewResult,
10
8
  } from "./preview.mjs";
11
9
 
12
- const server = new Server(
13
- { name: "markcut", version: "3.2.0" },
14
- { capabilities: { tools: {}, resources: {} } },
15
- );
10
+ const server = new McpServer({ name: "markcut", version: "3.2.0" });
16
11
 
17
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
18
- tools: [{
19
- name: TOOL_NAME,
12
+ registerAppTool(
13
+ server,
14
+ TOOL_NAME,
15
+ {
20
16
  description: "Ask a human to review a Markdown file and return an approval or requested changes.",
21
- inputSchema: {
22
- type: "object", properties: { path: { type: "string", description: "Absolute path to a .md file" } },
23
- required: ["path"], additionalProperties: false,
17
+ inputSchema: z.object({
18
+ path: z.string().describe("Absolute path to a .md file"),
19
+ }),
20
+ _meta: {
21
+ ui: { resourceUri: RESOURCE_URI },
24
22
  },
25
- _meta: { "ui/resourceUri": RESOURCE_URI, ui: { resourceUri: RESOURCE_URI } },
26
- }, {
27
- name: SUBMIT_TOOL_NAME,
23
+ },
24
+ async ({ path }) => {
25
+ try {
26
+ const preview = await readMarkdownPreview(path);
27
+ return {
28
+ content: [{ type: "text", text: `Markdown ready for review: ${preview.path}` }],
29
+ structuredContent: { ...preview, resourceUri: RESOURCE_URI },
30
+ _meta: {
31
+ ui: { resourceUri: RESOURCE_URI, props: preview },
32
+ "ui/resourceUri": RESOURCE_URI,
33
+ },
34
+ };
35
+ } catch (error) {
36
+ return {
37
+ isError: true,
38
+ content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
39
+ };
40
+ }
41
+ },
42
+ );
43
+
44
+ registerAppTool(
45
+ server,
46
+ SUBMIT_TOOL_NAME,
47
+ {
28
48
  description: "Submit the review decision from the Markdown preview UI.",
29
- inputSchema: {
30
- type: "object",
31
- properties: {
32
- decision: { type: "string", enum: ["approved", "changes_requested"] },
33
- feedback: { type: "string" },
34
- },
35
- required: ["decision"], additionalProperties: false,
49
+ inputSchema: z.object({
50
+ decision: z.enum(["approved", "changes_requested"]),
51
+ feedback: z.string().optional(),
52
+ }),
53
+ _meta: {
54
+ ui: { visibility: ["app"] },
36
55
  },
37
- _meta: { ui: { visibility: ["app"] } },
38
- }],
39
- }));
40
-
41
- server.setRequestHandler(ListResourcesRequestSchema, async () => ({
42
- resources: [{
43
- uri: RESOURCE_URI,
44
- name: "MarkCut Markdown review",
45
- mimeType: "text/html;profile=mcp-app",
46
- _meta: { ui: { prefersBorder: true, csp: { connectDomains: [], resourceDomains: [] } } },
47
- }],
48
- }));
49
-
50
- server.setRequestHandler(ReadResourceRequestSchema, async (request) => ({
51
- contents: [{
52
- uri: RESOURCE_URI,
53
- mimeType: "text/html;profile=mcp-app",
54
- text: buildPreviewHtml({ path: "", markdown: "" }),
55
- _meta: { ui: { prefersBorder: true, csp: { connectDomains: [], resourceDomains: [] } } },
56
- }],
57
- }));
58
-
59
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
60
- try {
61
- const input = request.params.arguments ?? {};
62
- if (request.params.name === SUBMIT_TOOL_NAME) {
63
- const decision = reviewResult(input.decision, input.feedback);
64
- return { content: [{ type: "text", text: JSON.stringify(decision) }], structuredContent: decision };
56
+ },
57
+ async ({ decision, feedback }) => {
58
+ try {
59
+ const result = reviewResult(decision, feedback);
60
+ return {
61
+ content: [{ type: "text", text: JSON.stringify(result) }],
62
+ structuredContent: result,
63
+ };
64
+ } catch (error) {
65
+ return {
66
+ isError: true,
67
+ content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
68
+ };
65
69
  }
66
- if (request.params.name !== TOOL_NAME) throw new Error(`unknown tool: ${request.params.name}`);
67
- const { path, markdown } = await readMarkdownPreview(input.path);
68
- return {
69
- content: [{ type: "text", text: `Markdown ready for review: ${path}` }],
70
- structuredContent: { path, markdown, resourceUri: RESOURCE_URI },
70
+ },
71
+ );
72
+
73
+ registerAppResource(
74
+ server,
75
+ "MarkCut Markdown review",
76
+ RESOURCE_URI,
77
+ {
78
+ _meta: {
79
+ ui: {
80
+ prefersBorder: true,
81
+ csp: { connectDomains: [], resourceDomains: [] },
82
+ },
83
+ },
84
+ },
85
+ async () => ({
86
+ contents: [{
87
+ uri: RESOURCE_URI,
88
+ mimeType: RESOURCE_MIME_TYPE,
89
+ text: buildPreviewHtml({ path: "", markdown: "" }),
71
90
  _meta: {
72
- "ui/resourceUri": RESOURCE_URI,
73
- ui: { resourceUri: RESOURCE_URI, props: { path, markdown } },
91
+ ui: {
92
+ prefersBorder: true,
93
+ csp: { connectDomains: [], resourceDomains: [] },
94
+ },
74
95
  },
75
- };
76
- } catch (error) {
77
- return { isError: true, content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }] };
78
- }
79
- });
96
+ }],
97
+ }),
98
+ );
80
99
 
81
100
  await server.connect(new StdioServerTransport());