deckbuilder 1.0.0b1__py3-none-any.whl
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.
- deckbuilder/__init__.py +22 -0
- deckbuilder/cli.py +544 -0
- deckbuilder/cli_tools.py +739 -0
- deckbuilder/engine.py +1546 -0
- deckbuilder/image_handler.py +291 -0
- deckbuilder/layout_intelligence.json +288 -0
- deckbuilder/layout_intelligence.py +398 -0
- deckbuilder/naming_conventions.py +541 -0
- deckbuilder/placeholder_types.py +101 -0
- deckbuilder/placekitten_integration.py +280 -0
- deckbuilder/structured_frontmatter.py +862 -0
- deckbuilder/table_styles.py +37 -0
- deckbuilder-1.0.0b1.dist-info/METADATA +378 -0
- deckbuilder-1.0.0b1.dist-info/RECORD +37 -0
- deckbuilder-1.0.0b1.dist-info/WHEEL +5 -0
- deckbuilder-1.0.0b1.dist-info/entry_points.txt +3 -0
- deckbuilder-1.0.0b1.dist-info/licenses/LICENSE +201 -0
- deckbuilder-1.0.0b1.dist-info/top_level.txt +4 -0
- mcp_server/__init__.py +9 -0
- mcp_server/content_analysis.py +436 -0
- mcp_server/content_optimization.py +822 -0
- mcp_server/layout_recommendations.py +595 -0
- mcp_server/main.py +550 -0
- mcp_server/tools.py +492 -0
- placekitten/README.md +561 -0
- placekitten/__init__.py +44 -0
- placekitten/core.py +184 -0
- placekitten/filters.py +183 -0
- placekitten/images/ACuteKitten-1.png +0 -0
- placekitten/images/ACuteKitten-2.png +0 -0
- placekitten/images/ACuteKitten-3.png +0 -0
- placekitten/images/TwoKitttens Playing-1.png +0 -0
- placekitten/images/TwoKitttens Playing-2.png +0 -0
- placekitten/images/TwoKitttensSleeping-1.png +0 -0
- placekitten/processor.py +262 -0
- placekitten/smart_crop.py +314 -0
- shared/__init__.py +9 -0
mcp_server/main.py
ADDED
@@ -0,0 +1,550 @@
|
|
1
|
+
import asyncio
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
from collections.abc import AsyncIterator
|
6
|
+
from contextlib import asynccontextmanager
|
7
|
+
from dataclasses import dataclass
|
8
|
+
|
9
|
+
from dotenv import load_dotenv
|
10
|
+
from mcp.server.fastmcp import Context, FastMCP
|
11
|
+
|
12
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
13
|
+
|
14
|
+
from deckbuilder.engine import get_deckbuilder_client # noqa: E402
|
15
|
+
|
16
|
+
# Import content-first tools (will be implemented later)
|
17
|
+
try:
|
18
|
+
from .content_analysis import analyze_presentation_needs
|
19
|
+
from .content_optimization import optimize_content_for_layout
|
20
|
+
from .layout_recommendations import recommend_slide_approach
|
21
|
+
except ImportError:
|
22
|
+
# Placeholder functions for when these modules don't exist yet
|
23
|
+
def analyze_presentation_needs(*args, **kwargs):
|
24
|
+
return "Content analysis tool not implemented yet"
|
25
|
+
|
26
|
+
def recommend_slide_approach(*args, **kwargs):
|
27
|
+
return "Layout recommendation tool not implemented yet"
|
28
|
+
|
29
|
+
def optimize_content_for_layout(*args, **kwargs):
|
30
|
+
return "Content optimization tool not implemented yet"
|
31
|
+
|
32
|
+
|
33
|
+
deck = get_deckbuilder_client()
|
34
|
+
|
35
|
+
|
36
|
+
load_dotenv()
|
37
|
+
|
38
|
+
|
39
|
+
# Create a dataclass for our application context
|
40
|
+
@dataclass
|
41
|
+
class DeckbuilderContext:
|
42
|
+
"""Context for the Deckbuilder MCP server."""
|
43
|
+
|
44
|
+
deckbuilder_client: str
|
45
|
+
|
46
|
+
|
47
|
+
@asynccontextmanager
|
48
|
+
async def deckbuilder_lifespan(server: FastMCP) -> AsyncIterator[DeckbuilderContext]:
|
49
|
+
"""
|
50
|
+
Manages the Deckbuilder client lifecycle.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
server: The Deckbuilder server instance
|
54
|
+
|
55
|
+
Yields:
|
56
|
+
PresentationContext: The context containing the Deckbuilder client
|
57
|
+
"""
|
58
|
+
|
59
|
+
# Create and return the Deckbuilder Client with the helper function in deckbuilder.py
|
60
|
+
deckbuilder_client = get_deckbuilder_client()
|
61
|
+
|
62
|
+
try:
|
63
|
+
yield DeckbuilderContext(deckbuilder_client=deckbuilder_client)
|
64
|
+
finally:
|
65
|
+
# Explicit cleanup goes here if any is required
|
66
|
+
pass
|
67
|
+
|
68
|
+
|
69
|
+
# Initialize FastMCP server with the Deckbuilder client as context
|
70
|
+
mcp = FastMCP(
|
71
|
+
"deckbuilder",
|
72
|
+
description="MCP server for creation of powerpoint decks",
|
73
|
+
lifespan=deckbuilder_lifespan,
|
74
|
+
host=os.getenv("HOST", "0.0.0.0"), # nosec B104
|
75
|
+
port=os.getenv("PORT", "8050"),
|
76
|
+
)
|
77
|
+
|
78
|
+
|
79
|
+
@mcp.tool()
|
80
|
+
async def create_presentation(
|
81
|
+
ctx: Context,
|
82
|
+
json_data: dict,
|
83
|
+
fileName: str = "Sample_Presentation",
|
84
|
+
templateName: str = "default",
|
85
|
+
) -> str:
|
86
|
+
"""Create a complete PowerPoint presentation from JSON data
|
87
|
+
|
88
|
+
This tool accepts JSON data containing all slides and creates a complete presentation
|
89
|
+
with automatic saving. Supports all slide types: title, content, table, and all
|
90
|
+
available layouts with inline formatting.
|
91
|
+
|
92
|
+
IMPORTANT: Use the provided JSON data exactly as given by the user. Do not modify,
|
93
|
+
reformat, or adjust the JSON structure unless the tool fails with specific errors
|
94
|
+
that require fixes.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
ctx: MCP context
|
98
|
+
json_data: JSON object containing presentation data with slides (use as-is)
|
99
|
+
fileName: Output filename (default: Sample_Presentation)
|
100
|
+
templateName: Template to use (default: default)
|
101
|
+
|
102
|
+
Example JSON format:
|
103
|
+
{
|
104
|
+
"presentation": {
|
105
|
+
"slides": [
|
106
|
+
{
|
107
|
+
"type": "title",
|
108
|
+
"title": "**My Title** with *formatting*",
|
109
|
+
"subtitle": "Subtitle with ___underline___"
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"type": "content",
|
113
|
+
"title": "Content Slide",
|
114
|
+
"content": [
|
115
|
+
"**Bold** bullet point",
|
116
|
+
"*Italic* text with ___underline___",
|
117
|
+
"***Bold italic*** combination"
|
118
|
+
]
|
119
|
+
},
|
120
|
+
{
|
121
|
+
"type": "table",
|
122
|
+
"title": "Table Example",
|
123
|
+
"table": {
|
124
|
+
"header_style": "dark_blue_white_text",
|
125
|
+
"row_style": "alternating_light_gray",
|
126
|
+
"data": [
|
127
|
+
["**Header 1**", "*Header 2*", "___Header 3___"],
|
128
|
+
["Data 1", "Data 2", "Data 3"]
|
129
|
+
]
|
130
|
+
}
|
131
|
+
},
|
132
|
+
{
|
133
|
+
"type": "Picture with Caption",
|
134
|
+
"title": "Image Example",
|
135
|
+
"image_1": "path/to/image.png",
|
136
|
+
"text_caption_1": "**Professional** image with *automatic* fallback"
|
137
|
+
}
|
138
|
+
]
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
Supported slide types:
|
143
|
+
- title: Title slide with title and subtitle
|
144
|
+
- content: Content slide with rich text, bullets, headings
|
145
|
+
- table: Table slide with full styling support
|
146
|
+
- Picture with Caption: Image slides with automatic PlaceKitten fallback
|
147
|
+
- All PowerPoint layout types are supported via the template mapping
|
148
|
+
|
149
|
+
Image support:
|
150
|
+
- Direct image insertion via image_1, image_2, etc. fields
|
151
|
+
- Automatic PlaceKitten fallback for missing images
|
152
|
+
- Professional styling: grayscale filter + smart cropping
|
153
|
+
- Intelligent face detection and rule-of-thirds composition
|
154
|
+
- Optimized caching for performance
|
155
|
+
|
156
|
+
Inline formatting support:
|
157
|
+
- **bold** - Bold text
|
158
|
+
- *italic* - Italic text
|
159
|
+
- ___underline___ - Underlined text
|
160
|
+
- ***bold italic*** - Combined bold and italic
|
161
|
+
- ***___all three___*** - Bold, italic, and underlined
|
162
|
+
|
163
|
+
Table styling options:
|
164
|
+
- header_style: dark_blue_white_text, light_blue_dark_text, etc.
|
165
|
+
- row_style: alternating_light_gray, solid_white, etc.
|
166
|
+
- border_style: thin_gray, thick_gray, no_borders, etc.
|
167
|
+
- custom_colors: Custom hex color overrides
|
168
|
+
|
169
|
+
IMPORTANT: Do NOT include markdown table separator lines (|---|---|---|) in table data.
|
170
|
+
Only include actual table rows with content.
|
171
|
+
|
172
|
+
USER CONTENT POLICY: When users provide JSON or markdown content (pasted or referenced),
|
173
|
+
use it exactly as provided. Do not modify, reformat, or "improve" the structure unless
|
174
|
+
the tool fails with specific errors requiring fixes. Respect the user's formatting choices.
|
175
|
+
"""
|
176
|
+
try:
|
177
|
+
# Create presentation
|
178
|
+
deck.create_presentation(templateName, fileName)
|
179
|
+
|
180
|
+
# Add slides from JSON data
|
181
|
+
deck.add_slide_from_json(json_data)
|
182
|
+
|
183
|
+
# Automatically save the presentation
|
184
|
+
write_result = deck.write_presentation(fileName)
|
185
|
+
|
186
|
+
return f"Successfully created presentation: {fileName}. {write_result}"
|
187
|
+
except Exception as e:
|
188
|
+
return f"Error creating presentation: {str(e)}"
|
189
|
+
|
190
|
+
|
191
|
+
@mcp.tool()
|
192
|
+
async def analyze_presentation_needs_tool(
|
193
|
+
ctx: Context,
|
194
|
+
user_input: str,
|
195
|
+
audience: str = "general",
|
196
|
+
constraints: str = None,
|
197
|
+
presentation_goal: str = "inform",
|
198
|
+
) -> str:
|
199
|
+
"""
|
200
|
+
Analyze user's presentation needs and recommend structure.
|
201
|
+
|
202
|
+
Content-first approach: Understand communication goals before suggesting layouts.
|
203
|
+
Acts as intelligent presentation consultant, not layout picker.
|
204
|
+
|
205
|
+
Args:
|
206
|
+
ctx: MCP context
|
207
|
+
user_input: Raw description of what they want to present
|
208
|
+
audience: Target audience ("board", "team", "customers", "technical", "general")
|
209
|
+
constraints: Time/slide constraints ("10 minutes", "5 slides max", "data-heavy")
|
210
|
+
presentation_goal: Primary goal ("persuade", "inform", "report", "update", "train")
|
211
|
+
|
212
|
+
Returns:
|
213
|
+
JSON string with content analysis and structural recommendations
|
214
|
+
|
215
|
+
Example:
|
216
|
+
user_input: "I need to present our Q3 results to the board. We had 23% revenue
|
217
|
+
growth, expanded to 3 new markets, but customer churn increased to 8%.
|
218
|
+
I want to show we're growing but acknowledge the churn issue and present
|
219
|
+
our retention strategy."
|
220
|
+
audience: "board"
|
221
|
+
presentation_goal: "report"
|
222
|
+
|
223
|
+
Returns analysis with:
|
224
|
+
- Content analysis (key messages, narrative arc, complexity level)
|
225
|
+
- Audience considerations (expertise level, attention span, preferred format)
|
226
|
+
- Recommended structure (slide sequence with purpose and timing)
|
227
|
+
- Presentation strategy (opening/closing approach, engagement tactics)
|
228
|
+
"""
|
229
|
+
try:
|
230
|
+
analysis_result = analyze_presentation_needs(
|
231
|
+
user_input, audience, constraints, presentation_goal
|
232
|
+
)
|
233
|
+
return json.dumps(analysis_result, indent=2)
|
234
|
+
except Exception as e:
|
235
|
+
return f"Error analyzing presentation needs: {str(e)}"
|
236
|
+
|
237
|
+
|
238
|
+
@mcp.tool()
|
239
|
+
async def recommend_slide_approach_tool(
|
240
|
+
ctx: Context, content_piece: str, message_intent: str, presentation_context: str = None
|
241
|
+
) -> str:
|
242
|
+
"""
|
243
|
+
Recommend optimal slide layouts based on specific content and communication intent.
|
244
|
+
|
245
|
+
Content-first approach: Analyzes what you want to communicate with this specific
|
246
|
+
content piece and recommends the most effective slide layouts.
|
247
|
+
|
248
|
+
Args:
|
249
|
+
ctx: MCP context
|
250
|
+
content_piece: Specific content to present (e.g., "We increased revenue 25%,
|
251
|
+
expanded to 3 markets, but churn rose to 8%")
|
252
|
+
message_intent: What you want this content to communicate (e.g.,
|
253
|
+
"show growth while acknowledging challenges")
|
254
|
+
presentation_context: Optional JSON string from analyze_presentation_needs_tool output
|
255
|
+
|
256
|
+
Returns:
|
257
|
+
JSON string with layout recommendations, confidence scores, and content suggestions
|
258
|
+
|
259
|
+
Example:
|
260
|
+
content_piece: "Our mobile app has these key features: real-time notifications,
|
261
|
+
offline mode, cloud sync, and advanced analytics dashboard"
|
262
|
+
message_intent: "showcase the comprehensive feature set to potential customers"
|
263
|
+
|
264
|
+
Returns recommendations like:
|
265
|
+
- Four Columns layout (confidence: 0.90) for feature comparison grid
|
266
|
+
- Title and Content layout (confidence: 0.75) for traditional feature list
|
267
|
+
- Content structuring suggestions and YAML preview
|
268
|
+
|
269
|
+
This tool bridges the gap between content analysis (Tool #1) and content optimization (Tool #3)
|
270
|
+
by providing specific layout guidance for individual content pieces.
|
271
|
+
"""
|
272
|
+
try:
|
273
|
+
# Parse presentation context if provided
|
274
|
+
context_dict = None
|
275
|
+
if presentation_context:
|
276
|
+
try:
|
277
|
+
context_dict = json.loads(presentation_context)
|
278
|
+
except json.JSONDecodeError:
|
279
|
+
# If parsing fails, continue without context
|
280
|
+
pass
|
281
|
+
|
282
|
+
# Get layout recommendations
|
283
|
+
recommendations = recommend_slide_approach(content_piece, message_intent, context_dict)
|
284
|
+
|
285
|
+
return json.dumps(recommendations, indent=2)
|
286
|
+
|
287
|
+
except Exception as e:
|
288
|
+
return f"Error recommending slide approach: {str(e)}"
|
289
|
+
|
290
|
+
|
291
|
+
@mcp.tool()
|
292
|
+
async def optimize_content_for_layout_tool(
|
293
|
+
ctx: Context, content: str, chosen_layout: str, slide_context: str = None
|
294
|
+
) -> str:
|
295
|
+
"""
|
296
|
+
Optimize content structure and generate ready-to-use YAML for immediate presentation creation.
|
297
|
+
|
298
|
+
Final step in content-first workflow: Takes raw content and chosen layout, then optimizes
|
299
|
+
the content structure and generates production-ready YAML that can be used directly
|
300
|
+
with create_presentation_from_markdown.
|
301
|
+
|
302
|
+
Args:
|
303
|
+
ctx: MCP context
|
304
|
+
content: Raw content to optimize (e.g., "Our platform offers real-time
|
305
|
+
analytics, automated reporting, custom dashboards, and API integration")
|
306
|
+
chosen_layout: Layout to optimize for (e.g., "Four Columns" from
|
307
|
+
recommend_slide_approach_tool)
|
308
|
+
slide_context: Optional JSON string with context from previous tools
|
309
|
+
(analyze_presentation_needs, recommend_slide_approach)
|
310
|
+
|
311
|
+
Returns:
|
312
|
+
JSON string with optimized YAML structure, gap analysis, and presentation tips
|
313
|
+
|
314
|
+
Example:
|
315
|
+
content: "Traditional approach costs $50K annually with 2-week deployment
|
316
|
+
vs our solution at $30K with same-day setup"
|
317
|
+
chosen_layout: "Comparison"
|
318
|
+
|
319
|
+
Returns:
|
320
|
+
- optimized_content.yaml_structure: Ready-to-use YAML for create_presentation_from_markdown
|
321
|
+
- gap_analysis: Content fit assessment and recommendations
|
322
|
+
- presentation_tips: Delivery guidance and timing estimates
|
323
|
+
- image_recommendations: Suggested visual content with PlaceKitten fallback support
|
324
|
+
|
325
|
+
Complete Content-First Workflow:
|
326
|
+
1. analyze_presentation_needs_tool() -> overall structure
|
327
|
+
2. recommend_slide_approach_tool() -> layout recommendations
|
328
|
+
3. optimize_content_for_layout_tool() -> production-ready YAML ✅ THIS TOOL
|
329
|
+
4. create_presentation_from_markdown() -> final PowerPoint
|
330
|
+
"""
|
331
|
+
try:
|
332
|
+
# Parse slide context if provided
|
333
|
+
context_dict = None
|
334
|
+
if slide_context:
|
335
|
+
try:
|
336
|
+
context_dict = json.loads(slide_context)
|
337
|
+
except json.JSONDecodeError:
|
338
|
+
# If parsing fails, continue without context
|
339
|
+
pass
|
340
|
+
|
341
|
+
# Optimize content for the chosen layout
|
342
|
+
optimization_result = optimize_content_for_layout(content, chosen_layout, context_dict)
|
343
|
+
|
344
|
+
return json.dumps(optimization_result, indent=2)
|
345
|
+
|
346
|
+
except Exception as e:
|
347
|
+
return f"Error optimizing content for layout: {str(e)}"
|
348
|
+
|
349
|
+
|
350
|
+
@mcp.tool()
|
351
|
+
async def create_presentation_from_file(
|
352
|
+
ctx: Context,
|
353
|
+
file_path: str,
|
354
|
+
fileName: str = "Sample_Presentation",
|
355
|
+
templateName: str = "default",
|
356
|
+
) -> str:
|
357
|
+
"""Create a complete PowerPoint presentation from JSON or markdown file
|
358
|
+
|
359
|
+
This tool reads presentation data directly from a local file without passing
|
360
|
+
content through the context window.
|
361
|
+
Supports both JSON files (.json) and markdown files (.md) with frontmatter.
|
362
|
+
Automatically detects file type and processes accordingly.
|
363
|
+
|
364
|
+
IMPORTANT: Process the file content exactly as provided. Do not modify the JSON
|
365
|
+
structure or markdown formatting unless the tool fails with specific errors
|
366
|
+
that require fixes.
|
367
|
+
|
368
|
+
Args:
|
369
|
+
ctx: MCP context
|
370
|
+
file_path: Absolute path to JSON or markdown file (process content as-is)
|
371
|
+
fileName: Output filename (default: Sample_Presentation)
|
372
|
+
templateName: Template to use (default: default)
|
373
|
+
|
374
|
+
Supported file types:
|
375
|
+
- .json files: JSON format with presentation data
|
376
|
+
- .md files: Markdown with frontmatter slide definitions
|
377
|
+
|
378
|
+
Example usage:
|
379
|
+
file_path: "/path/to/test_comprehensive_layouts.json"
|
380
|
+
file_path: "/path/to/presentation.md"
|
381
|
+
|
382
|
+
Benefits:
|
383
|
+
- No token usage for large presentation files
|
384
|
+
- Direct file system access
|
385
|
+
- Supports both JSON and markdown formats
|
386
|
+
- Automatic file type detection
|
387
|
+
"""
|
388
|
+
try:
|
389
|
+
# Check if file exists
|
390
|
+
if not os.path.exists(file_path):
|
391
|
+
return f"Error: File not found: {file_path}"
|
392
|
+
|
393
|
+
# Determine file type and process accordingly
|
394
|
+
file_extension = os.path.splitext(file_path)[1].lower()
|
395
|
+
|
396
|
+
if file_extension == ".json":
|
397
|
+
# Read JSON file
|
398
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
399
|
+
json_data = json.load(f)
|
400
|
+
|
401
|
+
# Create presentation from JSON
|
402
|
+
deck.create_presentation(templateName, fileName)
|
403
|
+
deck.add_slide_from_json(json_data)
|
404
|
+
write_result = deck.write_presentation(fileName)
|
405
|
+
|
406
|
+
return f"Successfully created presentation from JSON file: {file_path}. {write_result}"
|
407
|
+
|
408
|
+
elif file_extension == ".md":
|
409
|
+
# Read markdown file
|
410
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
411
|
+
markdown_content = f.read()
|
412
|
+
|
413
|
+
# Create presentation from markdown
|
414
|
+
slides = deck.parse_markdown_with_frontmatter(markdown_content)
|
415
|
+
deck.create_presentation(templateName, fileName)
|
416
|
+
|
417
|
+
for slide_data in slides:
|
418
|
+
deck._add_slide(slide_data)
|
419
|
+
|
420
|
+
write_result = deck.write_presentation(fileName)
|
421
|
+
|
422
|
+
return (
|
423
|
+
f"Successfully created presentation from markdown file: "
|
424
|
+
f"{file_path} with {len(slides)} slides. {write_result}"
|
425
|
+
)
|
426
|
+
|
427
|
+
else:
|
428
|
+
return f"Error: Unsupported file type '{file_extension}'. Supported types: .json, .md"
|
429
|
+
|
430
|
+
except json.JSONDecodeError as e:
|
431
|
+
return f"Error parsing JSON file: {str(e)}"
|
432
|
+
except Exception as e:
|
433
|
+
return f"Error creating presentation from file: {str(e)}"
|
434
|
+
|
435
|
+
|
436
|
+
@mcp.tool()
|
437
|
+
async def create_presentation_from_markdown(
|
438
|
+
ctx: Context,
|
439
|
+
markdown_content: str,
|
440
|
+
fileName: str = "Sample_Presentation",
|
441
|
+
templateName: str = "default",
|
442
|
+
) -> str:
|
443
|
+
"""Create presentation from formatted markdown with frontmatter
|
444
|
+
|
445
|
+
This tool accepts markdown content with frontmatter slide definitions and
|
446
|
+
creates a complete presentation.
|
447
|
+
Each slide is defined using YAML frontmatter followed by markdown content.
|
448
|
+
This tool automatically saves the presentation to disk after creation.
|
449
|
+
|
450
|
+
IMPORTANT: Use the provided markdown content exactly as given by the user. Do not
|
451
|
+
modify the frontmatter structure, markdown formatting, or content unless the tool
|
452
|
+
fails with specific errors that require fixes.
|
453
|
+
|
454
|
+
Args:
|
455
|
+
ctx: MCP context
|
456
|
+
markdown_content: Markdown string with frontmatter (use as-is)
|
457
|
+
fileName: Output filename (default: Sample_Presentation)
|
458
|
+
templateName: Template/theme to use (default: default)
|
459
|
+
|
460
|
+
Example markdown format:
|
461
|
+
---
|
462
|
+
layout: title
|
463
|
+
---
|
464
|
+
# Main Title
|
465
|
+
## Subtitle
|
466
|
+
|
467
|
+
---
|
468
|
+
layout: content
|
469
|
+
---
|
470
|
+
# Key Points
|
471
|
+
|
472
|
+
## Overview
|
473
|
+
This section covers the main features of our product.
|
474
|
+
|
475
|
+
- Advanced analytics dashboard
|
476
|
+
- Real-time data processing
|
477
|
+
- Seamless API integration
|
478
|
+
|
479
|
+
The system scales automatically based on demand.
|
480
|
+
|
481
|
+
---
|
482
|
+
layout: table
|
483
|
+
style: dark_blue_white_text
|
484
|
+
---
|
485
|
+
# Sales Report
|
486
|
+
| Name | Sales | Region |
|
487
|
+
| John Smith | $125,000 | North |
|
488
|
+
| Sarah Johnson | $98,500 | South |
|
489
|
+
|
490
|
+
---
|
491
|
+
layout: Picture with Caption
|
492
|
+
title: System **Architecture** Overview
|
493
|
+
media:
|
494
|
+
image_path: "diagrams/system_architecture.png"
|
495
|
+
alt_text: "System architecture diagram showing microservices"
|
496
|
+
caption: "***Scalable*** microservices with *intelligent* load balancing"
|
497
|
+
---
|
498
|
+
|
499
|
+
Supported layouts:
|
500
|
+
- title: Title slide with title and subtitle
|
501
|
+
- content: Content slide with rich text support (headings, paragraphs, bullets)
|
502
|
+
- table: Table slide with styling options
|
503
|
+
- Picture with Caption: Image slides with PlaceKitten fallback support
|
504
|
+
|
505
|
+
Image features:
|
506
|
+
- Smart fallback: Missing images automatically use PlaceKitten placeholders
|
507
|
+
- Professional styling: Grayscale filter + intelligent cropping
|
508
|
+
- Face detection: Optimized cropping for portrait images
|
509
|
+
- Performance: Intelligent caching system for repeated use
|
510
|
+
- Accessibility: Alt text support for screen readers
|
511
|
+
|
512
|
+
Table styling options:
|
513
|
+
- style: Header style (dark_blue_white_text, light_blue_dark_text, etc.)
|
514
|
+
- row_style: Row style (alternating_light_gray, solid_white, etc.)
|
515
|
+
- border_style: Border style (thin_gray, thick_gray, no_borders, etc.)
|
516
|
+
- custom_colors: Custom color overrides (header_bg, header_text, alt_row, border_color)
|
517
|
+
"""
|
518
|
+
try:
|
519
|
+
slides = deck.parse_markdown_with_frontmatter(markdown_content)
|
520
|
+
|
521
|
+
# Create presentation
|
522
|
+
deck.create_presentation(templateName, fileName)
|
523
|
+
|
524
|
+
# Add all slides to the presentation
|
525
|
+
for slide_data in slides:
|
526
|
+
deck._add_slide(slide_data)
|
527
|
+
|
528
|
+
# Automatically save the presentation to disk after creation
|
529
|
+
write_result = deck.write_presentation(fileName)
|
530
|
+
|
531
|
+
return (
|
532
|
+
f"Successfully created presentation with {len(slides)} slides "
|
533
|
+
f"from markdown. {write_result}"
|
534
|
+
)
|
535
|
+
except Exception as e:
|
536
|
+
return f"Error creating presentation from markdown: {str(e)}"
|
537
|
+
|
538
|
+
|
539
|
+
async def main():
|
540
|
+
transport = os.getenv("TRANSPORT", "sse")
|
541
|
+
if transport == "sse":
|
542
|
+
# Run the MCP server with sse transport
|
543
|
+
await mcp.run_sse_async()
|
544
|
+
else:
|
545
|
+
# Run the MCP server with stdio transport
|
546
|
+
await mcp.run_stdio_async()
|
547
|
+
|
548
|
+
|
549
|
+
if __name__ == "__main__":
|
550
|
+
asyncio.run(main())
|