Skip to main content
Glama
index-api.ts15.2 kB
#!/usr/bin/env node /** * EuConquisto Composer MCP Server - HTTP API Implementation * * @version 0.2.0 * @created 2025-06-28 * @updated 2025-06-28 * @author EuConquisto Development Team * * @description MCP server using direct HTTP API calls instead of browser automation */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { CompositionManager } from "./composition-manager.js"; /** * HTTP API-based MCP server - no browser automation required */ async function main(): Promise<void> { try { // Set up environment process.title = 'euconquisto-composer-mcp-api'; // Create composition manager const compositionManager = new CompositionManager(); // Handle process events process.on('SIGINT', async () => { console.error('Shutting down gracefully...'); process.exit(0); }); process.on('SIGTERM', async () => { console.error('Received SIGTERM, shutting down...'); process.exit(0); }); // Create MCP server const server = new McpServer({ name: "euconquisto-composer-api", version: "0.2.0", description: "EuConquisto Composer MCP Server - HTTP API Implementation" }); /** * Test Connection Tool - Verifies API connectivity */ server.tool( "test-connection", "Test connection to EuConquisto Composer API", {}, async () => { try { const result = await compositionManager.testConnection(); return { content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, message: result.message, timestamp: new Date().toISOString(), buildStatus: "✅ HTTP API - No browser automation required", status: result.success ? "API connection successful ✅" : "API connection failed ❌", data: result.data, error: result.error }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Connection test failed", error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }, null, 2) }] }; } } ); /** * Get Widget Information Tool */ server.tool( "get-widget-info", "Get information about available widget types and their properties", { widget: z.string().describe("Widget type (text, image, header, list, gallery, hotspot, multimedia, quiz, activities, bookmarks)") }, async (params) => { // Widget information from the TypeScript analysis const widgetInfo = { text: { type: "texto", status: "completed", properties: 8, subtypes: 9, description: "Rich text content with formatting and layout options" }, image: { type: "imagem", status: "completed", properties: 12, subtypes: 5, description: "Image display with caption and zoom functionality" }, header: { type: "cabecalho", status: "completed", properties: 44, subtypes: 6, examples: ["template-1", "template-2", "template-3"], special: "Template 3 includes SCORM LMS integration", description: "Header sections with background media, categories, and author info" }, list: { type: "lista", status: "completed", properties: 10, subtypes: 3, description: "Lists with various formatting options and rich text per item" }, gallery: { type: "galeria", status: "completed", properties: 10, subtypes: 1, description: "Slideshow/gallery for displaying multiple images with navigation" }, hotspot: { type: "interatividade", subtype: "hotspot-interactive", status: "completed", properties: 15, icons: 25, description: "Interactive image with clickable information points and 25+ icon options" }, multimedia: { type: "multimidia", status: "api-ready", description: "Audio and video content with embedded player controls" }, quiz: { type: "quiz", status: "api-ready", description: "Interactive quizzes with questions, answers, and scoring" }, activities: { type: "atividades", status: "api-ready", description: "Learning activities and exercises" }, bookmarks: { type: "marcadores", status: "api-ready", description: "Navigation bookmarks and markers" } }; const info = widgetInfo[params.widget as keyof typeof widgetInfo]; if (!info) { throw new Error(`Widget type '${params.widget}' not found`); } return { content: [{ type: "text" as const, text: JSON.stringify({ widget: params.widget, ...info, usage: "Available for composition creation via HTTP API" }, null, 2) }] }; } ); /** * Get Composer URL Tool */ server.tool( "get-composer-url", "Get the authenticated URL for the EuConquisto Composer interface", {}, async () => { try { const baseURL = "https://composer.euconquisto.com/#/embed"; const orgId = "36c92686-c494-ec11-a22a-dc984041c95d"; // Read JWT token const fs = await import('fs'); const jwtToken = fs.readFileSync('/Users/ricardokawasaki/Desktop/euconquisto-composer-mcp-poc/correct-jwt-new.txt', 'utf8').trim(); const composerURL = `${baseURL}/auth-with-token/pt_br/home/${orgId}/${jwtToken}`; return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, composerURL, tokenLength: jwtToken.length, message: "Composer URL generated with corrected JWT token", note: "This URL provides direct access to the Composer interface" }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Failed to generate Composer URL", error: error instanceof Error ? error.message : 'Unknown error' }, null, 2) }] }; } } ); /** * Create New Composition Tool - HTTP API Implementation */ server.tool( "create-new-composition", "Create a new composition using HTTP API (no browser automation required)", { title: z.string().describe("Composition title"), description: z.string().optional().describe("Composition description"), content: z.string().describe("Content to include in the composition"), widgets: z.array(z.object({ type: z.enum(['text', 'header', 'list', 'image']).describe("Widget type"), content: z.string().describe("Widget content"), properties: z.record(z.any()).optional().describe("Additional widget properties") })).optional().describe("Specific widgets to add (if not provided, content will be parsed automatically)") }, async (params) => { try { const result = await compositionManager.createFromDescription({ title: params.title, description: params.description, content: params.content, widgets: params.widgets }); return { content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, message: result.message, compositionUID: result.compositionUID, method: "HTTP API", timestamp: new Date().toISOString(), data: result.data, error: result.error }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Failed to create composition via API", error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }, null, 2) }] }; } } ); /** * Edit Composition Metadata Tool - HTTP API Implementation */ server.tool( "edit-composition-metadata", "Edit composition metadata using HTTP API", { uid: z.string().describe("Composition UID to update"), title: z.string().optional().describe("New composition title"), description: z.string().optional().describe("New composition description"), tags: z.array(z.string()).optional().describe("Composition tags") }, async (params) => { try { const result = await compositionManager.updateMetadata(params.uid, { title: params.title, description: params.description, tags: params.tags }); return { content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, message: result.message, compositionUID: result.compositionUID, method: "HTTP API", timestamp: new Date().toISOString(), data: result.data, error: result.error }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Failed to update composition metadata", error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }, null, 2) }] }; } } ); /** * Save Composition Tool - HTTP API Implementation */ server.tool( "save-composition", "Save composition using HTTP API (same as create for direct API)", { title: z.string().describe("Composition title"), description: z.string().optional().describe("Composition description"), content: z.string().describe("Content to save") }, async (params) => { try { const result = await compositionManager.createFromDescription({ title: params.title, description: params.description, content: params.content }); return { content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, message: `Composition saved: ${result.message}`, compositionUID: result.compositionUID, method: "HTTP API Storage", timestamp: new Date().toISOString(), data: result.data, error: result.error }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Failed to save composition", error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }, null, 2) }] }; } } ); /** * Complete Composition Workflow Tool - HTTP API Implementation */ server.tool( "complete-composition-workflow", "Complete end-to-end composition workflow: create, configure, and save via HTTP API", { title: z.string().describe("Composition title"), description: z.string().optional().describe("Composition description"), content: z.string().describe("Content for the composition"), widgets: z.array(z.object({ type: z.enum(['text', 'header', 'list', 'image']).describe("Widget type"), content: z.string().describe("Widget content"), properties: z.record(z.any()).optional().describe("Additional widget properties") })).optional().describe("Specific widgets to include") }, async (params) => { try { const result = await compositionManager.createFromDescription({ title: params.title, description: params.description, content: params.content, widgets: params.widgets }); return { content: [{ type: "text" as const, text: JSON.stringify({ success: result.success, message: `Complete workflow: ${result.message}`, compositionUID: result.compositionUID, workflow: "Create → Configure → Save", method: "HTTP API (Single Request)", performance: "~10x faster than browser automation", timestamp: new Date().toISOString(), data: result.data, error: result.error }, null, 2) }] }; } catch (error) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, message: "Complete workflow failed", error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }, null, 2) }] }; } } ); // Create stdio transport const transport = new StdioServerTransport(); // Start server await server.connect(transport); console.error("EuConquisto Composer MCP Server (HTTP API) is running..."); } catch (error) { console.error("Failed to start server:", error); process.exit(1); } } // Start the server main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });

Latest Blog Posts

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/rkm097git/euconquisto-composer-mcp-poc'

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