deckpipe-mcp 0.1.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 +93 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +153 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/create-deck.d.ts +43 -0
- package/dist/tools/create-deck.js +67 -0
- package/dist/tools/create-deck.js.map +1 -0
- package/dist/tools/delete-deck.d.ts +20 -0
- package/dist/tools/delete-deck.js +26 -0
- package/dist/tools/delete-deck.js.map +1 -0
- package/dist/tools/get-deck.d.ts +20 -0
- package/dist/tools/get-deck.js +26 -0
- package/dist/tools/get-deck.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-layouts.d.ts +14 -0
- package/dist/tools/list-layouts.js +88 -0
- package/dist/tools/list-layouts.js.map +1 -0
- package/dist/tools/update-deck.d.ts +45 -0
- package/dist/tools/update-deck.js +52 -0
- package/dist/tools/update-deck.js.map +1 -0
- package/dist/tools/upload-image.d.ts +28 -0
- package/dist/tools/upload-image.js +42 -0
- package/dist/tools/upload-image.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# deckpipe-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [deckpipe](https://deckpipe.com) — create and edit slide decks from any AI agent.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
**Claude Code**
|
|
8
|
+
```bash
|
|
9
|
+
claude mcp add deckpipe -- npx deckpipe-mcp
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Manual MCP config** (Claude Desktop, Cursor, etc.)
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"deckpipe": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["-y", "deckpipe-mcp"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Tools
|
|
25
|
+
|
|
26
|
+
| Tool | Description |
|
|
27
|
+
|------|-------------|
|
|
28
|
+
| `create_deck` | Create a new deck and get a shareable viewer URL |
|
|
29
|
+
| `get_deck` | Retrieve a deck by ID |
|
|
30
|
+
| `update_deck` | Update title, fonts, accent color, or individual slides by index |
|
|
31
|
+
| `delete_deck` | Delete a deck permanently |
|
|
32
|
+
| `upload_image` | Upload a base64 image, get a hosted URL |
|
|
33
|
+
| `list_layouts` | List available layouts, customization options, and style guide |
|
|
34
|
+
|
|
35
|
+
## Layouts
|
|
36
|
+
|
|
37
|
+
| Layout | Description | Required Fields |
|
|
38
|
+
|--------|-------------|----------------|
|
|
39
|
+
| `title` | Large centered title slide | `title`, optional `subtitle`, `image_url` |
|
|
40
|
+
| `title_and_body` | Title + paragraph | `title`, `body`, optional `image_url` |
|
|
41
|
+
| `title_and_bullets` | Title + bullet list | `title`, `bullets[]`, optional `image_url` |
|
|
42
|
+
| `title_and_table` | Title + data table | `title`, `table: { headers[], rows[][] }` |
|
|
43
|
+
| `two_columns` | Title + two columns | `title`, `left: { heading, body }`, `right: { heading, body }` |
|
|
44
|
+
| `section_break` | Bold section divider | `title` |
|
|
45
|
+
| `image_and_text` | Image-primary (~60%) + text | `title`, `body`, `image_url` |
|
|
46
|
+
| `image_gallery` | Horizontal row of portrait images | `images[]` (2-5 URLs), optional `title`, `caption` |
|
|
47
|
+
| `stats` | Big metrics/numbers with labels | `metrics[]: { value, label }` (2-4), optional `title` |
|
|
48
|
+
| `quote` | Large pull-quote with attribution | `quote`, optional `attribution`, `image_url` |
|
|
49
|
+
| `full_image` | Full-bleed background image with overlay text | `image_url`, optional `title`, `subtitle` |
|
|
50
|
+
|
|
51
|
+
All layouts support an optional `key_takeaway` field — a highlighted sentence rendered below the title.
|
|
52
|
+
|
|
53
|
+
## Customization
|
|
54
|
+
|
|
55
|
+
Both `create_deck` and `update_deck` accept optional styling fields:
|
|
56
|
+
|
|
57
|
+
| Field | Description | Default |
|
|
58
|
+
|-------|-------------|---------|
|
|
59
|
+
| `heading_font` | Google Font for headings (e.g. `"Playfair Display"`, `"Space Grotesk"`) | DM Sans |
|
|
60
|
+
| `body_font` | Google Font for body text (e.g. `"Inter"`, `"Roboto"`) | DM Sans |
|
|
61
|
+
| `accent_color` | Hex color (e.g. `"#ff6600"`) | `#7c3aed` (purple) |
|
|
62
|
+
|
|
63
|
+
## Example prompts
|
|
64
|
+
|
|
65
|
+
> Create a deck about the rise of electric vehicles. Search the web for relevant photos and use them. Use heading font "Space Grotesk", body font "Inter", and accent color "#0ea5e9".
|
|
66
|
+
|
|
67
|
+
> Create a deck about the Apollo 11 moon landing. Search the web for historic NASA photos and use them as full-bleed images. Include a timeline of the mission, stats on the Saturn V rocket, and a famous quote from Neil Armstrong. Use heading font "Libre Baskerville" and accent color "#1e3a5f".
|
|
68
|
+
|
|
69
|
+
> Build a lecture deck on how neural networks learn. Use a comparison table for activation functions, bullet points for key concepts, and add a key takeaway to each slide.
|
|
70
|
+
|
|
71
|
+
> Create a travel guide deck for Tokyo. Search the web for photos and include an image gallery of must-visit spots, stats on tourism, and a full-bleed image cover slide.
|
|
72
|
+
|
|
73
|
+
## Configuration
|
|
74
|
+
|
|
75
|
+
By default the MCP server connects to `https://deckpipe.com`. To use a different API endpoint:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"deckpipe": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["-y", "deckpipe-mcp"],
|
|
83
|
+
"env": {
|
|
84
|
+
"DECKPIPE_API_URL": "http://localhost:3010"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,sBAAsB;CAC/D,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { config } from './config.js';
|
|
6
|
+
const server = new McpServer({
|
|
7
|
+
name: 'deckpipe',
|
|
8
|
+
version: '0.1.0',
|
|
9
|
+
});
|
|
10
|
+
// --- create_deck ---
|
|
11
|
+
server.tool('create_deck', `Create a new slide deck and get a shareable viewer URL.
|
|
12
|
+
|
|
13
|
+
Keep slide copy short and scannable — use shorthand phrases, not full sentences. Bullets: 5-8 words max.
|
|
14
|
+
|
|
15
|
+
Layouts: "title", "title_and_body", "title_and_bullets", "title_and_table", "two_columns", "section_break", "image_and_text", "image_gallery", "stats", "quote", "full_image".
|
|
16
|
+
|
|
17
|
+
Content fields per layout (all layouts support optional key_takeaway):
|
|
18
|
+
- title: { title, subtitle?, image_url? }
|
|
19
|
+
- title_and_body: { title, body, image_url? }
|
|
20
|
+
- title_and_bullets: { title, bullets[], image_url? }
|
|
21
|
+
- title_and_table: { title, table: { headers[], rows[][], highlight_column? } }
|
|
22
|
+
- two_columns: { title, left: { heading, body }, right: { heading, body }, image_url? }
|
|
23
|
+
- section_break: { title }
|
|
24
|
+
- image_and_text: { title, body, image_url (required) }
|
|
25
|
+
- image_gallery: { title?, caption?, images[] (2-5 URLs) }
|
|
26
|
+
- stats: { title?, metrics[]: { value, label } (2-4 items) }
|
|
27
|
+
- quote: { quote, attribution?, image_url? }
|
|
28
|
+
- full_image: { image_url (required), title?, subtitle? }
|
|
29
|
+
|
|
30
|
+
Optionally set heading_font and body_font (any Google Font name) and accent_color (hex like "#ff6600") to customize the look.
|
|
31
|
+
Use upload_image first to get hosted URLs for any images.`, {
|
|
32
|
+
title: z.string().describe('Deck title'),
|
|
33
|
+
heading_font: z.string().optional().describe('Google Font for headings (e.g. "Playfair Display"). Default: DM Sans.'),
|
|
34
|
+
body_font: z.string().optional().describe('Google Font for body text (e.g. "Inter"). Default: DM Sans.'),
|
|
35
|
+
accent_color: z.string().optional().describe('Hex color (e.g. "#ff6600"). Overrides default purple accent.'),
|
|
36
|
+
slides: z.array(z.object({
|
|
37
|
+
layout: z.enum(['title', 'title_and_body', 'title_and_bullets', 'title_and_table', 'two_columns', 'section_break', 'image_and_text', 'image_gallery', 'stats', 'quote', 'full_image']),
|
|
38
|
+
content: z.record(z.unknown()).describe('Content fields (vary by layout). All layouts support optional key_takeaway.'),
|
|
39
|
+
})).describe('Array of slides'),
|
|
40
|
+
}, async (args) => {
|
|
41
|
+
const res = await fetch(`${config.apiUrl}/v1/decks`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: JSON.stringify(args),
|
|
45
|
+
});
|
|
46
|
+
const data = await res.json();
|
|
47
|
+
if (!res.ok)
|
|
48
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
49
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
50
|
+
});
|
|
51
|
+
// --- get_deck ---
|
|
52
|
+
server.tool('get_deck', 'Retrieve a deck by ID, including any user edits made in the viewer.', {
|
|
53
|
+
deck_id: z.string().describe('The deck ID (e.g. "dk_a1b2c3d4")'),
|
|
54
|
+
}, async ({ deck_id }) => {
|
|
55
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${deck_id}`);
|
|
56
|
+
const data = await res.json();
|
|
57
|
+
if (!res.ok)
|
|
58
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
59
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
60
|
+
});
|
|
61
|
+
// --- update_deck ---
|
|
62
|
+
server.tool('update_deck', `Update a deck's title, fonts, accent color, or individual slide content. Slides are updated by index with partial content merge.
|
|
63
|
+
|
|
64
|
+
Example: { "deck_id": "dk_abc", "slides": [{ "index": 2, "content": { "title": "New Title" } }] }`, {
|
|
65
|
+
deck_id: z.string().describe('Deck ID to update'),
|
|
66
|
+
title: z.string().optional().describe('New deck title'),
|
|
67
|
+
heading_font: z.string().optional().describe('Google Font for headings (e.g. "Playfair Display")'),
|
|
68
|
+
body_font: z.string().optional().describe('Google Font for body text (e.g. "Inter")'),
|
|
69
|
+
accent_color: z.string().optional().describe('Hex color (e.g. "#ff6600")'),
|
|
70
|
+
slides: z.array(z.object({
|
|
71
|
+
index: z.number().describe('Zero-based slide index'),
|
|
72
|
+
content: z.record(z.unknown()).describe('Partial content to merge'),
|
|
73
|
+
})).optional().describe('Slide updates'),
|
|
74
|
+
}, async ({ deck_id, ...body }) => {
|
|
75
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${deck_id}`, {
|
|
76
|
+
method: 'PATCH',
|
|
77
|
+
headers: { 'Content-Type': 'application/json' },
|
|
78
|
+
body: JSON.stringify(body),
|
|
79
|
+
});
|
|
80
|
+
const data = await res.json();
|
|
81
|
+
if (!res.ok)
|
|
82
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
83
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
84
|
+
});
|
|
85
|
+
// --- delete_deck ---
|
|
86
|
+
server.tool('delete_deck', 'Delete a deck permanently.', {
|
|
87
|
+
deck_id: z.string().describe('Deck ID to delete'),
|
|
88
|
+
}, async ({ deck_id }) => {
|
|
89
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${deck_id}`, { method: 'DELETE' });
|
|
90
|
+
if (res.status === 204) {
|
|
91
|
+
return { content: [{ type: 'text', text: `Deck ${deck_id} deleted successfully.` }] };
|
|
92
|
+
}
|
|
93
|
+
const data = await res.json();
|
|
94
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
95
|
+
});
|
|
96
|
+
// --- upload_image ---
|
|
97
|
+
server.tool('upload_image', `Upload a base64-encoded image to get a hosted URL for use in slide image_url fields.
|
|
98
|
+
|
|
99
|
+
Accepts PNG, JPG, WebP up to 10MB. Upload first, then use the returned URL when creating or updating a deck.`, {
|
|
100
|
+
image_data: z.string().describe('Base64-encoded image data'),
|
|
101
|
+
filename: z.string().describe('Filename with extension (e.g. "photo.jpg")'),
|
|
102
|
+
content_type: z.enum(['image/png', 'image/jpeg', 'image/webp']).describe('MIME type'),
|
|
103
|
+
}, async ({ image_data, filename, content_type }) => {
|
|
104
|
+
const buffer = Buffer.from(image_data, 'base64');
|
|
105
|
+
const blob = new Blob([buffer], { type: content_type });
|
|
106
|
+
const form = new FormData();
|
|
107
|
+
form.append('file', blob, filename);
|
|
108
|
+
const res = await fetch(`${config.apiUrl}/v1/images`, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
body: form,
|
|
111
|
+
});
|
|
112
|
+
const data = await res.json();
|
|
113
|
+
if (!res.ok)
|
|
114
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
115
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
116
|
+
});
|
|
117
|
+
// --- list_layouts ---
|
|
118
|
+
server.tool('list_layouts', 'List all available slide layouts, their content fields, and themes. Use this to discover what is supported before creating a deck.', {}, async () => {
|
|
119
|
+
const layouts = [
|
|
120
|
+
{ name: 'title', description: 'Large centered title slide.', fields: 'title (required), subtitle?, image_url?, key_takeaway?' },
|
|
121
|
+
{ name: 'title_and_body', description: 'Title + paragraph.', fields: 'title (required), body (required), image_url?, key_takeaway?' },
|
|
122
|
+
{ name: 'title_and_bullets', description: 'Title + bullet list.', fields: 'title (required), bullets[] (required), image_url?, key_takeaway?' },
|
|
123
|
+
{ name: 'title_and_table', description: 'Title + data table.', fields: 'title (required), table: { headers[], rows[][], highlight_column? }, key_takeaway?' },
|
|
124
|
+
{ name: 'two_columns', description: 'Title + two columns.', fields: 'title (required), left: { heading, body }, right: { heading, body }, image_url?, key_takeaway?' },
|
|
125
|
+
{ name: 'section_break', description: 'Bold section divider on accent bg.', fields: 'title (required), key_takeaway?' },
|
|
126
|
+
{ name: 'image_and_text', description: 'Image-primary (~60%) + text.', fields: 'title (required), body (required), image_url (required), key_takeaway?' },
|
|
127
|
+
{ name: 'image_gallery', description: 'Horizontal row of portrait images — ideal for screenshot galleries.', fields: 'images[] (2-5 URLs, required), title?, caption?, key_takeaway?' },
|
|
128
|
+
{ name: 'stats', description: 'Big metrics/numbers with labels.', fields: 'metrics[]: { value, label } (2-4 items, required), title?, key_takeaway?' },
|
|
129
|
+
{ name: 'quote', description: 'Large pull-quote with optional attribution.', fields: 'quote (required), attribution?, image_url?, key_takeaway?' },
|
|
130
|
+
{ name: 'full_image', description: 'Full-bleed background image with optional overlay text.', fields: 'image_url (required), title?, subtitle?, key_takeaway?' },
|
|
131
|
+
];
|
|
132
|
+
const customization = {
|
|
133
|
+
heading_font: 'Optional Google Font for headings (e.g. "Playfair Display"). Default: DM Sans.',
|
|
134
|
+
body_font: 'Optional Google Font for body text (e.g. "Inter"). Default: DM Sans.',
|
|
135
|
+
accent_color: 'Optional hex color (e.g. "#ff6600"). Default: #7c3aed (purple).',
|
|
136
|
+
};
|
|
137
|
+
const style_guide = {
|
|
138
|
+
copy: 'Keep text short and scannable. Use shorthand phrases, not full sentences. Bullets: 5-8 words max. Stats: abbreviate large numbers (e.g. "2.4M" not "2,400,000"). Quotes: under 30 words.',
|
|
139
|
+
images: 'Use upload_image to host images. image_gallery works best with 2-5 portrait images of consistent aspect ratio. full_image needs high-res landscape images.',
|
|
140
|
+
};
|
|
141
|
+
return { content: [{ type: 'text', text: JSON.stringify({ layouts, customization, style_guide }, null, 2) }] };
|
|
142
|
+
});
|
|
143
|
+
// Start with stdio transport
|
|
144
|
+
async function main() {
|
|
145
|
+
const transport = new StdioServerTransport();
|
|
146
|
+
await server.connect(transport);
|
|
147
|
+
console.error('Deckpipe MCP server running on stdio');
|
|
148
|
+
}
|
|
149
|
+
main().catch((err) => {
|
|
150
|
+
console.error('MCP server error:', err);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const createDeckTool: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
title: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
theme: {
|
|
12
|
+
type: string;
|
|
13
|
+
enum: string[];
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
slides: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
items: {
|
|
20
|
+
type: string;
|
|
21
|
+
properties: {
|
|
22
|
+
layout: {
|
|
23
|
+
type: string;
|
|
24
|
+
enum: string[];
|
|
25
|
+
};
|
|
26
|
+
content: {
|
|
27
|
+
type: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
required: string[];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
required: string[];
|
|
36
|
+
};
|
|
37
|
+
execute(args: Record<string, unknown>): Promise<{
|
|
38
|
+
content: {
|
|
39
|
+
type: "text";
|
|
40
|
+
text: string;
|
|
41
|
+
}[];
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
export const createDeckTool = {
|
|
3
|
+
name: 'create_deck',
|
|
4
|
+
description: `Create a new slide deck and get a shareable viewer URL.
|
|
5
|
+
|
|
6
|
+
INPUT:
|
|
7
|
+
- title (string, required): The deck title.
|
|
8
|
+
- theme (string, optional): Visual theme. One of: "minimal" (clean, light, Inter font), "modern" (bold, vibrant, DM Sans), "classic" (warm, serif headings, earth tones). Default: "minimal".
|
|
9
|
+
- slides (array, required, 1-50 items): Array of slide objects. Each slide has:
|
|
10
|
+
- layout (string, required): One of: "title", "title_and_body", "title_and_bullets", "title_and_table", "two_columns", "section_break", "image_and_text".
|
|
11
|
+
- content (object, required): Fields depend on layout:
|
|
12
|
+
- title: { title, subtitle? }
|
|
13
|
+
- title_and_body: { title, body }
|
|
14
|
+
- title_and_bullets: { title, bullets[] }
|
|
15
|
+
- title_and_table: { title, table: { headers[], rows[][], highlight_column? } }
|
|
16
|
+
- two_columns: { title, left: { heading, body }, right: { heading, body } }
|
|
17
|
+
- section_break: { title }
|
|
18
|
+
- image_and_text: { title, body, image_url (required) }
|
|
19
|
+
- All layouts except section_break accept an optional image_url field.
|
|
20
|
+
|
|
21
|
+
EXAMPLE:
|
|
22
|
+
{
|
|
23
|
+
"title": "Q1 Update",
|
|
24
|
+
"theme": "modern",
|
|
25
|
+
"slides": [
|
|
26
|
+
{ "layout": "title", "content": { "title": "Q1 Update", "subtitle": "March 2026" } },
|
|
27
|
+
{ "layout": "title_and_bullets", "content": { "title": "Highlights", "bullets": ["Revenue up 25%", "3 new features shipped"] } }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
RETURNS: { deck_id, viewer_url, created_at, slide_count }`,
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
title: { type: 'string', description: 'Deck title' },
|
|
36
|
+
theme: { type: 'string', enum: ['minimal', 'modern', 'classic'], description: 'Visual theme (default: minimal)' },
|
|
37
|
+
slides: {
|
|
38
|
+
type: 'array',
|
|
39
|
+
description: 'Array of slide objects with layout and content',
|
|
40
|
+
items: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
layout: { type: 'string', enum: ['title', 'title_and_body', 'title_and_bullets', 'title_and_table', 'two_columns', 'section_break', 'image_and_text'] },
|
|
44
|
+
content: { type: 'object', description: 'Content fields (vary by layout)' },
|
|
45
|
+
},
|
|
46
|
+
required: ['layout', 'content'],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ['title', 'slides'],
|
|
51
|
+
},
|
|
52
|
+
async execute(args) {
|
|
53
|
+
const res = await fetch(`${config.apiUrl}/v1/decks`, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: { 'Content-Type': 'application/json' },
|
|
56
|
+
body: JSON.stringify(args),
|
|
57
|
+
});
|
|
58
|
+
const data = await res.json();
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=create-deck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-deck.js","sourceRoot":"","sources":["../../src/tools/create-deck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;0DA2B2C;IACxD,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;YACpD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE;YACjH,MAAM,EAAE;gBACN,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,gDAAgD;gBAC7D,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,CAAC,EAAE;wBACvJ,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iCAAiC,EAAE;qBAC5E;oBACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;iBAChC;aACF;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;KAC9B;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,WAAW,EAAE;YACnD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC1E,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const deleteDeckTool: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
deck_id: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
required: string[];
|
|
13
|
+
};
|
|
14
|
+
execute(args: Record<string, unknown>): Promise<{
|
|
15
|
+
content: {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
export const deleteDeckTool = {
|
|
3
|
+
name: 'delete_deck',
|
|
4
|
+
description: `Delete a deck permanently.
|
|
5
|
+
|
|
6
|
+
INPUT:
|
|
7
|
+
- deck_id (string, required): The deck ID to delete.
|
|
8
|
+
|
|
9
|
+
RETURNS: Confirmation of deletion.`,
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
deck_id: { type: 'string', description: 'Deck ID to delete' },
|
|
14
|
+
},
|
|
15
|
+
required: ['deck_id'],
|
|
16
|
+
},
|
|
17
|
+
async execute(args) {
|
|
18
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${args.deck_id}`, { method: 'DELETE' });
|
|
19
|
+
if (res.status === 204) {
|
|
20
|
+
return { content: [{ type: 'text', text: `Deck ${args.deck_id} deleted successfully.` }] };
|
|
21
|
+
}
|
|
22
|
+
const data = await res.json();
|
|
23
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=delete-deck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-deck.js","sourceRoot":"","sources":["../../src/tools/delete-deck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;mCAKoB;IACjC,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;SAC9D;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,aAAa,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3F,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,QAAQ,IAAI,CAAC,OAAO,wBAAwB,EAAE,CAAC,EAAE,CAAC;QACtG,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC1F,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const getDeckTool: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
deck_id: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
required: string[];
|
|
13
|
+
};
|
|
14
|
+
execute(args: Record<string, unknown>): Promise<{
|
|
15
|
+
content: {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
export const getDeckTool = {
|
|
3
|
+
name: 'get_deck',
|
|
4
|
+
description: `Retrieve a deck's current state, including any user edits made in the viewer.
|
|
5
|
+
|
|
6
|
+
INPUT:
|
|
7
|
+
- deck_id (string, required): The deck ID (e.g. "dk_a1b2c3d4").
|
|
8
|
+
|
|
9
|
+
RETURNS: Full deck object with deck_id, title, theme, slides array, created_at, updated_at.`,
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
deck_id: { type: 'string', description: 'The deck ID to retrieve' },
|
|
14
|
+
},
|
|
15
|
+
required: ['deck_id'],
|
|
16
|
+
},
|
|
17
|
+
async execute(args) {
|
|
18
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${args.deck_id}`);
|
|
19
|
+
const data = await res.json();
|
|
20
|
+
if (!res.ok) {
|
|
21
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
22
|
+
}
|
|
23
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=get-deck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-deck.js","sourceRoot":"","sources":["../../src/tools/get-deck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE;;;;;4FAK6E;IAC1F,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;SACpE;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,aAAa,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createDeckTool } from './create-deck.js';
|
|
2
|
+
export { getDeckTool } from './get-deck.js';
|
|
3
|
+
export { updateDeckTool } from './update-deck.js';
|
|
4
|
+
export { deleteDeckTool } from './delete-deck.js';
|
|
5
|
+
export { uploadImageTool } from './upload-image.js';
|
|
6
|
+
export { listLayoutsTool } from './list-layouts.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createDeckTool } from './create-deck.js';
|
|
2
|
+
export { getDeckTool } from './get-deck.js';
|
|
3
|
+
export { updateDeckTool } from './update-deck.js';
|
|
4
|
+
export { deleteDeckTool } from './delete-deck.js';
|
|
5
|
+
export { uploadImageTool } from './upload-image.js';
|
|
6
|
+
export { listLayoutsTool } from './list-layouts.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export const listLayoutsTool = {
|
|
2
|
+
name: 'list_layouts',
|
|
3
|
+
description: `List all available slide layouts and themes. Use this to discover what layouts and content fields are supported before creating a deck. No input required.`,
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: 'object',
|
|
6
|
+
properties: {},
|
|
7
|
+
},
|
|
8
|
+
async execute() {
|
|
9
|
+
const layouts = [
|
|
10
|
+
{
|
|
11
|
+
name: 'title',
|
|
12
|
+
description: 'Opening or closing slide with a large centered title.',
|
|
13
|
+
fields: {
|
|
14
|
+
title: { type: 'string', required: true },
|
|
15
|
+
subtitle: { type: 'string', required: false },
|
|
16
|
+
image_url: { type: 'url', required: false, behavior: 'Background or centered below title' },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'title_and_body',
|
|
21
|
+
description: 'Title with a body paragraph. Good for explanatory slides.',
|
|
22
|
+
fields: {
|
|
23
|
+
title: { type: 'string', required: true },
|
|
24
|
+
body: { type: 'string', required: true },
|
|
25
|
+
image_url: { type: 'url', required: false, behavior: 'Beside text (landscape) or below (portrait)' },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'title_and_bullets',
|
|
30
|
+
description: 'Title with a bullet point list. Best for key points, features, or metrics.',
|
|
31
|
+
fields: {
|
|
32
|
+
title: { type: 'string', required: true },
|
|
33
|
+
bullets: { type: 'string[]', required: true },
|
|
34
|
+
image_url: { type: 'url', required: false, behavior: 'Right column alongside bullets' },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'title_and_table',
|
|
39
|
+
description: 'Title with a data table. Use for comparisons, pricing, feature matrices.',
|
|
40
|
+
fields: {
|
|
41
|
+
title: { type: 'string', required: true },
|
|
42
|
+
table: {
|
|
43
|
+
type: 'object', required: true,
|
|
44
|
+
properties: {
|
|
45
|
+
headers: { type: 'string[]', required: true, max_items: 6 },
|
|
46
|
+
rows: { type: 'string[][]', required: true, max_items: 8 },
|
|
47
|
+
highlight_column: { type: 'integer', required: false, description: 'Zero-indexed column to emphasize' },
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'two_columns',
|
|
54
|
+
description: 'Title with two side-by-side columns. Each column has a heading and body text. Good for comparisons.',
|
|
55
|
+
fields: {
|
|
56
|
+
title: { type: 'string', required: true },
|
|
57
|
+
left: { type: 'object', required: true, properties: { heading: 'string', body: 'string' } },
|
|
58
|
+
right: { type: 'object', required: true, properties: { heading: 'string', body: 'string' } },
|
|
59
|
+
image_url: { type: 'url', required: false, behavior: 'Spans below both columns' },
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'section_break',
|
|
64
|
+
description: 'Bold section divider with a centered title on an accent background. No image support.',
|
|
65
|
+
fields: {
|
|
66
|
+
title: { type: 'string', required: true },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'image_and_text',
|
|
71
|
+
description: 'Image-primary slide (~60% image, ~40% text). Image is required.',
|
|
72
|
+
fields: {
|
|
73
|
+
title: { type: 'string', required: true },
|
|
74
|
+
body: { type: 'string', required: true },
|
|
75
|
+
image_url: { type: 'url', required: true, behavior: 'Primary — takes ~60% of slide' },
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
const themes = ['minimal', 'modern', 'classic'];
|
|
80
|
+
return {
|
|
81
|
+
content: [{
|
|
82
|
+
type: 'text',
|
|
83
|
+
text: JSON.stringify({ layouts, themes }, null, 2),
|
|
84
|
+
}],
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=list-layouts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-layouts.js","sourceRoot":"","sources":["../../src/tools/list-layouts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,4JAA4J;IACzK,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE,EAAE;KACf;IACD,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,GAAG;YACd;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,uDAAuD;gBACpE,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC7C,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,oCAAoC,EAAE;iBAC5F;aACF;YACD;gBACE,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EAAE,2DAA2D;gBACxE,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACxC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,6CAA6C,EAAE;iBACrG;aACF;YACD;gBACE,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,4EAA4E;gBACzF,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC7C,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,gCAAgC,EAAE;iBACxF;aACF;YACD;gBACE,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EAAE,0EAA0E;gBACvF,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI;wBAC9B,UAAU,EAAE;4BACV,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE;4BAC3D,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE;4BAC1D,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,kCAAkC,EAAE;yBACxG;qBACF;iBACF;aACF;YACD;gBACE,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,qGAAqG;gBAClH,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC3F,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC5F,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,0BAA0B,EAAE;iBAClF;aACF;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,uFAAuF;gBACpG,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;iBAC1C;aACF;YACD;gBACE,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EAAE,iEAAiE;gBAC9E,MAAM,EAAE;oBACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACzC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACxC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,+BAA+B,EAAE;iBACtF;aACF;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAEhD,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;iBACnD,CAAC;SACH,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const updateDeckTool: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
deck_id: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
title: {
|
|
12
|
+
type: string;
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
theme: {
|
|
16
|
+
type: string;
|
|
17
|
+
enum: string[];
|
|
18
|
+
};
|
|
19
|
+
slides: {
|
|
20
|
+
type: string;
|
|
21
|
+
items: {
|
|
22
|
+
type: string;
|
|
23
|
+
properties: {
|
|
24
|
+
index: {
|
|
25
|
+
type: string;
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
content: {
|
|
29
|
+
type: string;
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
required: string[];
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
required: string[];
|
|
38
|
+
};
|
|
39
|
+
execute(args: Record<string, unknown>): Promise<{
|
|
40
|
+
content: {
|
|
41
|
+
type: "text";
|
|
42
|
+
text: string;
|
|
43
|
+
}[];
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
export const updateDeckTool = {
|
|
3
|
+
name: 'update_deck',
|
|
4
|
+
description: `Update an existing deck's title, theme, or individual slide content.
|
|
5
|
+
|
|
6
|
+
INPUT:
|
|
7
|
+
- deck_id (string, required): The deck ID to update.
|
|
8
|
+
- title (string, optional): New deck title.
|
|
9
|
+
- theme (string, optional): New theme ("minimal", "modern", "classic").
|
|
10
|
+
- slides (array, optional): Array of slide updates. Each has:
|
|
11
|
+
- index (number): Zero-based slide index to update.
|
|
12
|
+
- content (object): Partial content fields to merge into the existing slide content.
|
|
13
|
+
|
|
14
|
+
EXAMPLE: Update slide 2's title:
|
|
15
|
+
{ "deck_id": "dk_abc123", "slides": [{ "index": 2, "content": { "title": "New Title" } }] }
|
|
16
|
+
|
|
17
|
+
RETURNS: Full updated deck object.`,
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: 'object',
|
|
20
|
+
properties: {
|
|
21
|
+
deck_id: { type: 'string', description: 'Deck ID to update' },
|
|
22
|
+
title: { type: 'string', description: 'New deck title' },
|
|
23
|
+
theme: { type: 'string', enum: ['minimal', 'modern', 'classic'] },
|
|
24
|
+
slides: {
|
|
25
|
+
type: 'array',
|
|
26
|
+
items: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
index: { type: 'number', description: 'Zero-based slide index' },
|
|
30
|
+
content: { type: 'object', description: 'Partial content to merge' },
|
|
31
|
+
},
|
|
32
|
+
required: ['index', 'content'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ['deck_id'],
|
|
37
|
+
},
|
|
38
|
+
async execute(args) {
|
|
39
|
+
const { deck_id, ...body } = args;
|
|
40
|
+
const res = await fetch(`${config.apiUrl}/v1/decks/${deck_id}`, {
|
|
41
|
+
method: 'PATCH',
|
|
42
|
+
headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
body: JSON.stringify(body),
|
|
44
|
+
});
|
|
45
|
+
const data = await res.json();
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
48
|
+
}
|
|
49
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=update-deck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-deck.js","sourceRoot":"","sources":["../../src/tools/update-deck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;;;;mCAaoB;IACjC,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;YAC7D,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE;YACxD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;YACjE,MAAM,EAAE;gBACN,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;wBAChE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;qBACrE;oBACD,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;iBAC/B;aACF;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,aAAa,OAAO,EAAE,EAAE;YAC9D,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const uploadImageTool: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
image_data: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
filename: {
|
|
12
|
+
type: string;
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
content_type: {
|
|
16
|
+
type: string;
|
|
17
|
+
enum: string[];
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
required: string[];
|
|
21
|
+
};
|
|
22
|
+
execute(args: Record<string, unknown>): Promise<{
|
|
23
|
+
content: {
|
|
24
|
+
type: "text";
|
|
25
|
+
text: string;
|
|
26
|
+
}[];
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
export const uploadImageTool = {
|
|
3
|
+
name: 'upload_image',
|
|
4
|
+
description: `Upload a base64-encoded image to get a hosted URL for use in slide image_url fields.
|
|
5
|
+
|
|
6
|
+
Use this to upload local files (screenshots, charts, logos) from the user's machine.
|
|
7
|
+
|
|
8
|
+
INPUT:
|
|
9
|
+
- image_data (string, required): Base64-encoded image data.
|
|
10
|
+
- filename (string, required): Filename with extension (e.g. "screenshot.png").
|
|
11
|
+
- content_type (string, required): MIME type — "image/png", "image/jpeg", or "image/webp".
|
|
12
|
+
|
|
13
|
+
RETURNS: { image_id, url } — use the url in any slide's image_url field.
|
|
14
|
+
|
|
15
|
+
WORKFLOW: Upload the image first, then use the returned URL when creating or updating a deck.`,
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
image_data: { type: 'string', description: 'Base64-encoded image data' },
|
|
20
|
+
filename: { type: 'string', description: 'Filename (e.g. screenshot.png)' },
|
|
21
|
+
content_type: { type: 'string', enum: ['image/png', 'image/jpeg', 'image/webp'] },
|
|
22
|
+
},
|
|
23
|
+
required: ['image_data', 'filename', 'content_type'],
|
|
24
|
+
},
|
|
25
|
+
async execute(args) {
|
|
26
|
+
const { image_data, filename, content_type } = args;
|
|
27
|
+
const buffer = Buffer.from(image_data, 'base64');
|
|
28
|
+
const blob = new Blob([buffer], { type: content_type });
|
|
29
|
+
const form = new FormData();
|
|
30
|
+
form.append('file', blob, filename);
|
|
31
|
+
const res = await fetch(`${config.apiUrl}/v1/images`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
body: form,
|
|
34
|
+
});
|
|
35
|
+
const data = await res.json();
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
return { content: [{ type: 'text', text: `Error: ${JSON.stringify(data)}` }] };
|
|
38
|
+
}
|
|
39
|
+
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=upload-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-image.js","sourceRoot":"","sources":["../../src/tools/upload-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE;;;;;;;;;;;8FAW+E;IAC5F,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;YACxE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;YAC3E,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE;SAClF;QACD,QAAQ,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,CAAC;KACrD;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAI9C,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEpC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,YAAY,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC;CACF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "deckpipe-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Deckpipe — create, edit, and export slide decks from any AI agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"deckpipe-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx watch src/index.ts",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"slides",
|
|
19
|
+
"presentations",
|
|
20
|
+
"ai",
|
|
21
|
+
"agent"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
26
|
+
"zod": "^3.24.3"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^25.5.0",
|
|
30
|
+
"tsx": "^4.19.3",
|
|
31
|
+
"typescript": "^5.7.3"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/bjoern2000/deckpipe-mcp"
|
|
40
|
+
}
|
|
41
|
+
}
|