@masaki39/marp-mcp 0.1.0 → 0.3.0

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
@@ -1,45 +1,15 @@
1
1
  # Marp MCP Server
2
2
 
3
- A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for managing [Marp](https://marp.app/) presentation projects with academic theme support. Optimized for use with Claude Code, Cursor, and other AI-powered editors.
3
+ An MCP server for creating and editing Marp presentations with AI assistance.
4
4
 
5
- ## Features
5
+ ## Setup
6
6
 
7
- - 🎨 **Academic Theme Support** - Pre-configured academic_custom.css theme
8
- - 📁 **Project Initialization** - Automatic directory structure setup
9
- - 🎯 **Structured Slide Generation** - 6 layout templates for consistent design
10
- - 🔧 **Editor Integration** - Designed for Claude Code and Cursor
11
- - 📝 **Markdown Output** - Generate slides as markdown strings for easy editing
12
-
13
- ## Installation
14
-
15
- ### Via npx (Recommended)
16
-
17
- ```bash
18
- npx @masaki39/marp-mcp
19
- ```
20
-
21
- ### Global Installation
22
-
23
- ```bash
24
- npm install -g @masaki39/marp-mcp
25
- ```
26
-
27
- ### Local Installation
28
-
29
- ```bash
30
- npm install @masaki39/marp-mcp
31
- ```
32
-
33
- ## Configuration
34
-
35
- ### Claude Desktop
36
-
37
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
7
+ Add to your MCP client configuration:
38
8
 
39
9
  ```json
40
10
  {
41
11
  "mcpServers": {
42
- "marp": {
12
+ "marp-mcp": {
43
13
  "command": "npx",
44
14
  "args": ["-y", "@masaki39/marp-mcp"]
45
15
  }
@@ -47,301 +17,44 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
47
17
  }
48
18
  ```
49
19
 
50
- Or with global installation:
20
+ ## Tools
51
21
 
52
- ```json
53
- {
54
- "mcpServers": {
55
- "marp": {
56
- "command": "marp-mcp"
57
- }
58
- }
59
- }
60
- ```
61
-
62
- ### Claude Code / Cursor
63
-
64
- The server works seamlessly with Claude Code and Cursor. The generated markdown can be directly inserted into your editor.
65
-
66
- ## Available Tools
67
-
68
- ### 1. `init_presentation`
69
-
70
- Initialize a new Marp presentation project with complete directory structure.
71
-
72
- **Parameters:**
73
- - `projectPath` (string) - Directory where project will be created
74
- - `projectName` (string) - Name of the presentation project
75
- - `presentationTitle` (string) - Title of the presentation
76
- - `presentationSubtitle` (string, optional) - Subtitle
77
- - `description` (string, optional) - Brief description
78
-
79
- **Generated Structure:**
80
- ```
81
- my-presentation/
82
- ├── slides.md # Main presentation file
83
- ├── themes/
84
- │ └── academic_custom.css # Academic theme
85
- ├── attachments/
86
- │ ├── images/ # Image files
87
- │ ├── videos/ # Video files
88
- │ └── data/ # Data files
89
- ├── .gitignore
90
- └── README.md
91
- ```
92
-
93
- **Example:**
94
- ```javascript
95
- {
96
- "projectPath": "/Users/yourname/presentations",
97
- "projectName": "research-2024",
98
- "presentationTitle": "Research Findings",
99
- "presentationSubtitle": "Annual Report 2024",
100
- "description": "Research results presentation"
101
- }
102
- ```
103
-
104
- ### 2. `generate_slide`
105
-
106
- Generate a slide using academic theme layouts. Returns markdown string for copy-paste.
107
-
108
- **Parameters:**
109
- - `layoutType` (string) - Layout type (title, lead, content, table, multi-column, quote)
110
- - `params` (object) - Layout-specific parameters
111
-
112
- **Example:**
113
- ```javascript
114
- {
115
- "layoutType": "title",
116
- "params": {
117
- "title": "Presentation Title",
118
- "subtitle": "Subtitle"
119
- }
120
- }
121
- ```
122
-
123
- ### 3. `list_slide_layouts`
124
-
125
- List all available slide layouts with their parameters and descriptions.
126
-
127
- **No parameters required.**
22
+ | Tool | Description |
23
+ |------|-------------|
24
+ | `list_layouts` | List all available slide layouts with parameters and descriptions |
25
+ | `manage_slide` | Insert, replace, or delete slides in a Marp markdown file |
128
26
 
129
27
  ## Available Layouts
130
28
 
131
- ### Title Slide (`title`)
132
- Centered title and subtitle with `.title` class.
133
-
134
- **Parameters:**
135
- - `title` (required, max 60 chars)
136
- - `subtitle` (optional, max 100 chars)
137
-
138
- **Output:**
139
- ```markdown
140
- # Presentation Title
141
- ## Subtitle
142
-
143
- <!-- _class: title -->
144
- ```
145
-
146
- ### Lead Slide (`lead`)
147
- Left-aligned with maroon color headings using `.lead` class.
148
-
149
- **Parameters:**
150
- - `heading` (required, max 80 chars)
151
- - `content` (optional, markdown supported)
29
+ | Layout | Description |
30
+ |--------|-------------|
31
+ | `title` | Title slide with left-aligned heading and metadata |
32
+ | `section` | Section divider with centered title and subtitle |
33
+ | `list` | Content slide with heading and bullet points or text |
34
+ | `table` | Table layout with customizable size and alignment |
35
+ | `two-column` | Two-column layout for side-by-side content |
36
+ | `image-right` | Layout with image on the right side |
37
+ | `image-center` | Centered image layout with adjustable dimensions |
152
38
 
153
- **Output:**
154
- ```markdown
155
- # Main Heading
39
+ ## Example
156
40
 
157
- Content goes here
158
-
159
- <!-- _class: lead -->
160
- ```
161
-
162
- ### Content Slide (`content`)
163
- Standard content slide with optional heading.
164
-
165
- **Parameters:**
166
- - `heading` (optional, max 80 chars)
167
- - `content` (required, markdown supported)
168
-
169
- **Output:**
170
- ```markdown
171
- # Heading
172
-
173
- Content with markdown support
174
- - List item 1
175
- - List item 2
176
- ```
41
+ See the [example presentation](./assets/example.html) demonstrating all available layouts.
177
42
 
178
- ### Table Slide (`table`)
179
- Table with customizable size and alignment.
43
+ The example was created entirely using this MCP server and showcases:
44
+ - Title and section slides
45
+ - List and table layouts
46
+ - Two-column layout
47
+ - Image layouts (center and right)
180
48
 
181
- **Parameters:**
182
- - `heading` (optional, max 80 chars)
183
- - `tableMarkdown` (required, markdown table)
184
- - `tableClass` (optional: "center", "100", "tiny", "small", "large")
185
-
186
- **Output:**
187
- ```markdown
188
- # Table Heading
189
-
190
- | Column 1 | Column 2 |
191
- |----------|----------|
192
- | Data 1 | Data 2 |
193
-
194
- <!-- _class: table-center table-100 -->
195
- ```
196
-
197
- ### Multi-Column Slide (`multi-column`)
198
- 2-3 column layout using double blockquote syntax.
199
-
200
- **Parameters:**
201
- - `heading` (optional, max 80 chars)
202
- - `columns` (required, array of strings)
203
-
204
- **Output:**
205
- ```markdown
206
- # Comparison
207
-
208
- > > Column 1 content
209
- > > - Point 1
210
- >
211
- > > Column 2 content
212
- > > - Point 2
213
- ```
214
-
215
- ### Quote Slide (`quote`)
216
- Quote with citation in footer.
217
-
218
- **Parameters:**
219
- - `heading` (optional, max 80 chars)
220
- - `content` (optional)
221
- - `quote` (required, max 300 chars)
222
- - `citation` (optional, max 100 chars)
223
-
224
- **Output:**
225
- ```markdown
226
- # Heading
227
-
228
- Main content
229
-
230
- > Quote text here — Citation
231
- ```
232
-
233
- ## Academic Theme Features
234
-
235
- The included `academic_custom.css` theme provides:
236
-
237
- - **Page numbering** - Automatic slide numbers
238
- - **Custom fonts** - Noto Sans JP and Source Code Pro
239
- - **Color scheme** - Maroon highlights (#800000)
240
- - **Table styles** - Multiple size and alignment options
241
- - **Multi-column support** - Flexible column layouts
242
- - **Header support** - Customizable presentation headers
243
-
244
- ### CSS Classes
245
-
246
- - `.title` - Title slide (centered)
247
- - `.lead` - Lead slide (left-aligned, maroon)
248
- - `.table-center` - Centered table
249
- - `.table-100` - Full-width table
250
- - `.table-tiny` - Small font table (0.7em)
251
- - `.table-small` - Small font table (0.8em)
252
- - `.table-large` - Large font table (1.1em)
253
-
254
- ## Building Presentations
255
-
256
- ### Prerequisites
257
-
258
- Install Marp CLI:
259
-
260
- ```bash
261
- npm install -g @marp-team/marp-cli
262
- ```
263
-
264
- ### Build to PDF
265
-
266
- ```bash
267
- marp slides.md -o slides.pdf
268
- ```
269
-
270
- ### Build to HTML
271
-
272
- ```bash
273
- marp slides.md -o slides.html
274
- ```
275
-
276
- ### Build to PowerPoint
277
-
278
- ```bash
279
- marp slides.md -o slides.pptx
280
- ```
281
-
282
- ### Preview in VS Code
283
-
284
- Install [Marp for VS Code](https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode) extension for live preview.
285
-
286
- ## Development
287
-
288
- ### Building from Source
289
-
290
- ```bash
291
- git clone https://github.com/masaki39/marp-mcp.git
292
- cd marp-mcp
293
- npm install
294
- npm run build
295
- ```
296
-
297
- ### Testing Locally
298
-
299
- ```bash
300
- npm link
301
- ```
302
-
303
- Then configure Claude Desktop to use the local version.
304
-
305
- ## Troubleshooting
306
-
307
- ### Server Not Starting
308
-
309
- Check logs in `~/Library/Logs/Claude/`:
310
- ```bash
311
- tail -f ~/Library/Logs/Claude/mcp*.log
312
- ```
313
-
314
- ### Template Files Not Found
315
-
316
- Ensure the package was built correctly:
317
- ```bash
318
- npm run build
319
- ls build/templates/
320
- ```
321
-
322
- Should show:
323
- - `academic_custom.css`
324
- - `slides.template.md`
325
- - `README.template.md`
326
- - `gitignore.template`
327
-
328
- ## Contributing
329
-
330
- Contributions are welcome! Please feel free to submit a Pull Request.
49
+ Source: [example.md](./assets/example.md)
331
50
 
332
51
  ## License
333
52
 
334
- MIT License - see LICENSE file for details
335
-
336
- ## Credits
337
-
338
- - Academic theme based on [marp-theme-academic](https://github.com/kaisugi/marp-theme-academic) by kaisugi
339
- - Built on [Model Context Protocol](https://modelcontextprotocol.io)
340
- - Powered by [Marp](https://marp.app/)
53
+ MIT License
341
54
 
342
55
  ## Links
343
56
 
344
- - [GitHub Repository](https://github.com/masaki39/marp-mcp)
345
- - [npm Package](https://www.npmjs.com/package/@masaki39/marp-mcp)
346
- - [Marp Documentation](https://marpit.marp.app/)
347
- - [MCP Documentation](https://modelcontextprotocol.io)
57
+ - [GitHub](https://github.com/masaki39/marp-mcp)
58
+ - [npm](https://www.npmjs.com/package/@masaki39/marp-mcp)
59
+ - [Marp](https://marp.app/)
60
+ - [Model Context Protocol](https://modelcontextprotocol.io)
package/build/index.js CHANGED
@@ -7,28 +7,26 @@
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
9
  // Import tools
10
- import { initPresentationSchema, initPresentation } from "./tools/init.js";
11
- import { generateSlideSchema, generateSlide, listSlideLayoutsSchema, listSlideLayouts, } from "./tools/generate.js";
10
+ import { listLayoutsSchema, listLayouts, } from "./tools/list_layouts.js";
11
+ import { manageSlideSchema, manageSlide, } from "./tools/manage_slide.js";
12
12
  // Create server instance
13
13
  const server = new McpServer({
14
14
  name: "marp-mcp",
15
- version: "2.0.0",
15
+ version: "0.3.0",
16
16
  capabilities: {
17
17
  resources: {},
18
18
  tools: {},
19
19
  },
20
20
  });
21
21
  // Register tools
22
- server.tool("init_presentation", "Initialize a new Marp presentation project with directory structure, theme, and templates", initPresentationSchema.shape, initPresentation);
23
- server.tool("generate_slide", "Generate a slide using academic theme layouts (returns markdown string for copy-paste)", generateSlideSchema.shape, generateSlide);
24
- server.tool("list_slide_layouts", "List all available slide layouts with their parameters and descriptions", listSlideLayoutsSchema.shape, listSlideLayouts);
22
+ server.tool("list_layouts", "ALWAYS read this first before creating Marp slides - lists all available layouts with parameters and descriptions", listLayoutsSchema.shape, listLayouts);
23
+ server.tool("manage_slide", "Create slides using this tool with appropriate layouts, then fine-tune by direct editing if needed", manageSlideSchema.shape, manageSlide);
25
24
  // Start the server
26
25
  async function main() {
27
26
  const transport = new StdioServerTransport();
28
27
  await server.connect(transport);
29
- console.error("Marp MCP Server v2.0 running on stdio");
30
- console.error("Optimized for Claude Code and Cursor");
31
- console.error("Tools: init_presentation, generate_slide, list_slide_layouts");
28
+ console.error("Marp MCP Server v0.3.0 running on stdio");
29
+ console.error("Tools: list_layouts, manage_slide");
32
30
  }
33
31
  main().catch((error) => {
34
32
  console.error("Fatal error in main():", error);
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Default content slide
3
+ */
4
+ export const contentLayout = {
5
+ name: "content",
6
+ description: "Standard content slide with optional h2 heading",
7
+ params: {
8
+ heading: {
9
+ type: "string",
10
+ description: "Slide heading (max 80 chars, displays as h2)",
11
+ required: false,
12
+ maxLength: 80,
13
+ },
14
+ content: {
15
+ type: "string",
16
+ description: "Content (markdown supported, keep concise - max 800 chars recommended)",
17
+ required: true,
18
+ maxLength: 1500,
19
+ },
20
+ citations: {
21
+ type: "array",
22
+ description: "Citations/references (array of strings)",
23
+ required: false,
24
+ },
25
+ },
26
+ template: (params) => {
27
+ let slide = "";
28
+ if (params.heading) {
29
+ slide += `## ${params.heading}\n\n`;
30
+ }
31
+ slide += params.content;
32
+ // Add citations
33
+ if (params.citations && params.citations.length > 0) {
34
+ slide += '\n\n';
35
+ params.citations.forEach((citation) => {
36
+ slide += `> ${citation}\n`;
37
+ });
38
+ }
39
+ return slide;
40
+ },
41
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Figure layout - content with background image
3
+ */
4
+ export const figureLayout = {
5
+ name: "figure",
6
+ description: "Slide with background image and content overlay",
7
+ params: {
8
+ heading: {
9
+ type: "string",
10
+ description: "Slide heading (max 50 chars, displays as h2)",
11
+ required: false,
12
+ maxLength: 50,
13
+ },
14
+ content: {
15
+ type: "string",
16
+ description: "Content text (max 300 chars recommended, markdown supported)",
17
+ required: false,
18
+ maxLength: 500,
19
+ },
20
+ imagePath: {
21
+ type: "string",
22
+ description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
23
+ required: true,
24
+ },
25
+ imagePosition: {
26
+ type: "string",
27
+ description: "Image position: 'right' or 'left' (default: 'right')",
28
+ required: false,
29
+ },
30
+ imageSize: {
31
+ type: "string",
32
+ description: "Image size: 'cover' or 'contain' (default: 'contain')",
33
+ required: false,
34
+ },
35
+ citations: {
36
+ type: "array",
37
+ description: "Citations/references (array of strings)",
38
+ required: false,
39
+ },
40
+ },
41
+ template: (params) => {
42
+ let slide = "";
43
+ if (params.heading) {
44
+ slide += `## ${params.heading}\n\n`;
45
+ }
46
+ if (params.content) {
47
+ slide += `${params.content}\n\n`;
48
+ }
49
+ // Build background image directive
50
+ const position = params.imagePosition || 'right';
51
+ const size = params.imageSize || 'contain';
52
+ slide += `![bg ${position} ${size}](${params.imagePath})`;
53
+ // Add citations
54
+ if (params.citations && params.citations.length > 0) {
55
+ slide += '\n\n';
56
+ params.citations.forEach((citation) => {
57
+ slide += `> ${citation}\n`;
58
+ });
59
+ }
60
+ return slide;
61
+ },
62
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Image layout - centered image display
3
+ */
4
+ export const imageLayout = {
5
+ name: "image-center",
6
+ description: "Slide with centered image (fixed h:350)",
7
+ params: {
8
+ heading: {
9
+ type: "string",
10
+ description: "Slide heading (max 40 chars, ~22 chars for Japanese)",
11
+ required: true,
12
+ maxLength: 40,
13
+ },
14
+ imagePath: {
15
+ type: "string",
16
+ description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
17
+ required: true,
18
+ },
19
+ description: {
20
+ type: "string",
21
+ description: "Image description below image (max 55 chars, ~33 chars for Japanese)",
22
+ required: false,
23
+ maxLength: 55,
24
+ },
25
+ citations: {
26
+ type: "string",
27
+ description: "Citation (max 50 chars, ~30 chars for Japanese, no line break)",
28
+ required: false,
29
+ maxLength: 50,
30
+ },
31
+ },
32
+ template: (params) => {
33
+ let slide = "";
34
+ if (params.heading) {
35
+ slide += `## ${params.heading}\n\n`;
36
+ }
37
+ // Fixed image directive: center h:350
38
+ slide += `![center h:350](${params.imagePath})`;
39
+ // Image description (optional)
40
+ if (params.description) {
41
+ slide += `\n\n${params.description}`;
42
+ }
43
+ // Citation (single, no line break)
44
+ if (params.citations) {
45
+ slide += `\n\n> ${params.citations}`;
46
+ }
47
+ return slide;
48
+ },
49
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Image-right layout - content list with background image on right
3
+ */
4
+ export const imageRightLayout = {
5
+ name: "image-right",
6
+ description: "Slide with image on right and content list (allows more explanation than image-center)",
7
+ params: {
8
+ heading: {
9
+ type: "string",
10
+ description: "Slide heading (max 17 chars, ~10 chars for Japanese)",
11
+ required: true,
12
+ maxLength: 17,
13
+ },
14
+ list: {
15
+ type: "array",
16
+ description: "List items (max 8 items, each max 23 chars, ~14 chars for Japanese)",
17
+ required: true,
18
+ maxItems: 8,
19
+ maxLength: 23,
20
+ },
21
+ imagePath: {
22
+ type: "string",
23
+ description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
24
+ required: true,
25
+ },
26
+ citations: {
27
+ type: "string",
28
+ description: "Citation (max 50 chars, ~30 chars for Japanese, no line break)",
29
+ required: false,
30
+ maxLength: 50,
31
+ },
32
+ },
33
+ template: (params) => {
34
+ let slide = "";
35
+ if (params.heading) {
36
+ slide += `## ${params.heading}\n\n`;
37
+ }
38
+ // List items
39
+ params.list.forEach((item) => {
40
+ slide += `- ${item}\n`;
41
+ });
42
+ // Fixed background image: bg right:50% contain
43
+ slide += `\n![bg right:50% contain](${params.imagePath})`;
44
+ // Citation (single, no line break)
45
+ if (params.citations) {
46
+ slide += `\n\n> ${params.citations}`;
47
+ }
48
+ return slide;
49
+ },
50
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Image layout - centered image display
3
+ */
4
+ export const imageLayout = {
5
+ name: "image",
6
+ description: "Slide with centered image",
7
+ params: {
8
+ heading: {
9
+ type: "string",
10
+ description: "Slide heading (max 50 chars, displays as h2)",
11
+ required: false,
12
+ maxLength: 50,
13
+ },
14
+ imagePath: {
15
+ type: "string",
16
+ description: "Image file path (local paths supported, e.g., ./attachments/image.png)",
17
+ required: true,
18
+ },
19
+ height: {
20
+ type: "number",
21
+ description: "Image height in pixels (e.g., 330)",
22
+ required: false,
23
+ },
24
+ width: {
25
+ type: "string",
26
+ description: "Image width (e.g., '80%', '500px')",
27
+ required: false,
28
+ },
29
+ citations: {
30
+ type: "array",
31
+ description: "Citations/references (array of strings)",
32
+ required: false,
33
+ },
34
+ },
35
+ template: (params) => {
36
+ let slide = "";
37
+ if (params.heading) {
38
+ slide += `## ${params.heading}\n\n`;
39
+ }
40
+ // Build image directive
41
+ let imageDirective = "![center";
42
+ if (params.height) {
43
+ imageDirective += ` h:${params.height}`;
44
+ }
45
+ if (params.width) {
46
+ imageDirective += ` w:${params.width}`;
47
+ }
48
+ imageDirective += `](${params.imagePath})`;
49
+ slide += imageDirective;
50
+ // Add citations
51
+ if (params.citations && params.citations.length > 0) {
52
+ slide += '\n\n';
53
+ params.citations.forEach((citation) => {
54
+ slide += `> ${citation}\n`;
55
+ });
56
+ }
57
+ return slide;
58
+ },
59
+ };