@presentations-ai/cloudy-runtime
v0.2.2
Published
Create presentations with natural language using Claude and the Presentations.AI MCP server
Maintainers
Readme
@presentations-ai/cloudy-runtime
Build a Claude-powered chatbot that creates presentations. The user types a natural-language message; the runtime returns a presentation URL. No manual tool routing, no async polling logic — just one chat() call.
When to use this
You're building something that takes natural language as input — a Slack bot, a chat product, an AI agent — and you want "create a presentation" to be one of its capabilities.
A user types "make me a 12-slide pitch deck for an AI healthcare startup, targeting Series B VCs." You forward that message to cloudy.chat(). Behind the scenes Claude figures out which Presentations.AI tool to use, calls it, and returns a clean response with the deck URL.
If your code already knows the exact topic, slide count, and format — no LLM needed in the middle — use @presentations-ai/api-client instead.
Installation
npm install @presentations-ai/cloudy-runtimeYou'll need two API keys: an Anthropic API key for Claude, and a Presentations.AI API key for the MCP server.
Quick start
import { CloudyRuntime } from '@presentations-ai/cloudy-runtime';
const cloudy = new CloudyRuntime({
anthropicApiKey: process.env.ANTHROPIC_API_KEY!,
});
const response = await cloudy.chat(
'Create a 12-slide investor pitch deck for an AI-powered design platform',
process.env.PRESENTATIONS_AI_API_KEY!,
);
console.log(response.text); // What Cloudy said back
console.log(response.presentationUrl); // The deck — share this URL
console.log(response.documentId); // For follow-up editsThat's the happy path. The rest of this README covers conversation history, configuration, the response shape, and error handling.
How it works
The runtime uses Anthropic's MCP Connector to give Claude access to the Presentations.AI MCP server and its 9 tools. Your message goes to Claude → Claude picks the right tool → the MCP server creates the presentation → you get a unified response.
You don't manage tool selection, async polling, or response parsing — the runtime handles all of that. You only see the final result.
Multi-turn conversations
For follow-ups like "add a slide comparing our timeline against competitors," pass the prior conversation back in:
const apiKey = process.env.PRESENTATIONS_AI_API_KEY!;
const turn1 = await cloudy.chat(
'Create a product roadmap presentation for Q1 2025',
apiKey,
);
const turn2 = await cloudy.chat(
'Add a slide comparing our timeline against competitors',
apiKey,
[
{ role: 'user', content: 'Create a product roadmap presentation for Q1 2025' },
{ role: 'assistant', content: turn1.text },
],
);Cloudy will reuse the document ID from turn 1 and edit the existing deck rather than creating a new one.
Configuration
const cloudy = new CloudyRuntime({
anthropicApiKey: 'sk-ant-...', // Required
mcpServerUrl: '...', // Default: https://api.presentations.ai/mcp
model: 'claude-sonnet-4-5-20250929', // Default Claude model
maxTokens: 4096, // Max tokens in Claude's response
maxContinuations: 5, // How many pause_turn continuations to follow
systemPrompt: '...', // Override Cloudy's persona/instructions
});Most users only need anthropicApiKey. The rest have sensible defaults.
Response shape
interface CloudyResponse {
text: string; // Cloudy's natural-language reply
presentationUrl?: string; // The deck URL (when one was created)
documentId?: number; // Document ID (use this for follow-up edits)
animatedUrl?: string; // Animated preview (some export types)
jobId?: string; // Async job ID (when the tool fired async)
toolCalls: CloudyToolCall[]; // Every MCP tool called this turn
stopReason: string; // Why the turn ended
usage: { inputTokens: number; outputTokens: number };
}presentationUrl and documentId are present when a presentation was created or edited. They're undefined for purely conversational turns ("hi", "what can you do?", etc.).
Error handling
Failures throw a StructuredError from @presentations-ai/shared:
import { StructuredError } from '@presentations-ai/shared';
try {
await cloudy.chat('Create a presentation', apiKey);
} catch (error) {
if (error instanceof StructuredError) {
error.code; // e.g. "MCP_TOOL_EXECUTION_FAILED"
error.message; // e.g. "Anthropic API call failed: 401 Unauthorized"
error.remediation; // e.g. "Check your Anthropic API key..."
}
}Each error carries a remediation field with an actionable next step — show this to your user when appropriate.
Requirements
- Node.js >= 20.0.0
- Anthropic API key — the runtime adds the MCP Connector beta header automatically
- Presentations.AI API key
License
MIT
