Skip to main content
Glama

2slides MCP Server

Official
server.ts3.9 kB
import dotenv from 'dotenv'; import { z } from 'zod'; import fetch from 'node-fetch'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // Constants const API_BASE_URL = 'https://2slides.com'; dotenv.config(); const API_KEY = process.env.API_KEY ?? ''; if (!API_KEY) { // eslint-disable-next-line no-console console.error('Missing API_KEY in environment. Create .env and set API_KEY=...'); } // Initialize MCP server const mcp = new McpServer({ name: '2slides-mcp', version: '0.1.0' }); // Tool: slides_generate -> POST /api/v1/slides/generate const GenerateArgs = { themeId: z.string().min(1), userInput: z.string().min(1), responseLanguage: z.string().min(1), // Optional mode: 'sync' (default) | 'async' mode: z.enum(['sync', 'async']).optional(), }; mcp.tool( 'slides_generate', "Generate slides with 2slides. Returns job info including jobId and downloadUrl when ready. Optional 'mode' can be 'sync' (default) or 'async'.", GenerateArgs, async (args: any, _extra: any) => { const { themeId, userInput, responseLanguage, mode = 'sync' } = args as z.infer<z.ZodObject<typeof GenerateArgs>>; const url = `${API_BASE_URL}/api/v1/slides/generate`; const res = await fetch(url, { method: 'POST', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ themeId, userInput, responseLanguage, mode }), }); const data = await res.json(); if (!res.ok) { return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], isError: true, }; } return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // Tool: jobs_get -> GET /api/v1/jobs/{job-id} const JobArgs = { jobId: z.string().min(1) }; mcp.tool('jobs_get', 'Get job status/result by jobId from 2slides. Please check every 20 seconds until the status is success.', JobArgs, async (args: any, _extra: any) => { const { jobId } = args as z.infer<z.ZodObject<typeof JobArgs>>; const url = `${API_BASE_URL}/api/v1/jobs/${encodeURIComponent(jobId)}`; const res = await fetch(url, { method: 'GET', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, }); const data = await res.json(); if (!res.ok) { return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], isError: true, }; } return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; }); // Tool: themes_search -> GET /api/v1/themes/search const ThemesSearchArgs = { query: z.string().min(1), limit: z.number().int().positive().max(100).optional(), }; mcp.tool('themes_search', 'Search 2slides themes by query. Optional limit (max 100).', ThemesSearchArgs, async (args: any, _extra: any) => { const { query, limit } = args as z.infer<z.ZodObject<typeof ThemesSearchArgs>>; const search = new URLSearchParams({ query }); if (typeof limit === 'number') search.set('limit', String(limit)); const url = `${API_BASE_URL}/api/v1/themes/search?${search.toString()}`; const res = await fetch(url, { method: 'GET', headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, }); const data = await res.json(); if (!res.ok) { return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], isError: true, }; } return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; }); // Start server over stdio const transport = new StdioServerTransport(); mcp.connect(transport).catch((err: unknown) => { // eslint-disable-next-line no-console console.error('MCP server error', err); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/2slides/mcp-2slides'

If you have feedback or need assistance with the MCP directory API, please join our Discord server