Skip to main content
Glama
http_server.py12.8 kB
#!/usr/bin/env python3 """ Servidor HTTP (REST API) para exponer el MCP de WordPress Permite usar las herramientas del MCP como endpoints HTTP simples Perfecto para integrar con n8n, Zapier, Make.com, etc. """ import os import asyncio from typing import Optional, Dict, Any from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from dotenv import load_dotenv # Importar el servidor MCP y clases necesarias from .server import WordPressAPI from .ai_content_generator import AIContentGenerator # Cargar variables de entorno load_dotenv() # Crear aplicación FastAPI app = FastAPI( title="WordPress MCP HTTP API", description="API HTTP para gestión de WordPress con IA integrada", version="3.0.0" ) # Configurar CORS para permitir requests desde n8n app.add_middleware( CORSMiddleware, allow_origins=["*"], # En producción, especifica los dominios permitidos allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Inicializar clientes globales wp_client: Optional[WordPressAPI] = None ai_generator: Optional[AIContentGenerator] = None # === Modelos de Request === class GeneratePostRequest(BaseModel): """Request para generar un post con IA""" prompt: str style: str = "profesional" tone: str = "informativo" language: str = "español" status: str = "draft" class CreatePostRequest(BaseModel): """Request para crear un post manual""" title: str content: str status: str = "draft" categories: Optional[list] = None tags: Optional[list] = None class ImprovePostRequest(BaseModel): """Request para mejorar un post con IA""" post_id: int improvements: str = "mejorar SEO, claridad y estructura" # === Eventos de inicio === @app.on_event("startup") async def startup_event(): """Inicializa los clientes al arrancar el servidor""" global wp_client, ai_generator # Verificar variables de entorno wp_url = os.getenv('WP_URL') wp_username = os.getenv('WP_USER') # Render usa WP_USER wp_password = os.getenv('WP_APP_PASSWORD') # Render usa WP_APP_PASSWORD # Debug: mostrar qué variables están configuradas print("=" * 60) print("DEBUG - Variables de entorno:") print(f" WP_URL: {'✅ OK' if wp_url else '❌ FALTA'}") print(f" WP_USER: {'✅ OK' if wp_username else '❌ FALTA'}") print(f" WP_APP_PASSWORD: {'✅ OK' if wp_password else '❌ FALTA'}") print("=" * 60) if not all([wp_url, wp_username, wp_password]): error_msg = f"Faltan credenciales de WordPress:\n" error_msg += f" WP_URL: {'OK' if wp_url else 'FALTA'}\n" error_msg += f" WP_USER: {'OK' if wp_username else 'FALTA'}\n" error_msg += f" WP_APP_PASSWORD: {'OK' if wp_password else 'FALTA'}" raise RuntimeError(error_msg) # Inicializar cliente de WordPress wp_client = WordPressAPI(wp_url, wp_username, wp_password) print(f"✅ WordPress client inicializado: {wp_url}") # Inicializar generador de IA (opcional) try: ai_generator = AIContentGenerator() if ai_generator.is_available(): print("✅ Generador de IA disponible") else: print("⚠️ Generador de IA NO disponible (falta ANTHROPIC_API_KEY)") except Exception as e: print(f"⚠️ Error inicializando IA: {e}") ai_generator = None # === Endpoints de Salud === @app.get("/") async def root(): """Endpoint raíz - información del servidor""" return { "name": "WordPress MCP HTTP API", "version": "3.0.0", "status": "running", "ai_available": ai_generator.is_available() if ai_generator else False, "wordpress_url": os.getenv('WP_URL') } @app.get("/health") async def health_check(): """Health check para Render y otros servicios""" return { "status": "healthy", "wordpress": wp_client is not None, "ai": ai_generator.is_available() if ai_generator else False } # === Endpoints de IA === @app.post("/ai/generate-post") async def generate_post_with_ai(request: GeneratePostRequest): """ Genera y publica un post completo usando IA Ejemplo de uso desde n8n: POST https://tu-app.render.com/ai/generate-post Body: { "prompt": "Escribe sobre los beneficios del café", "style": "casual", "tone": "informativo", "status": "draft" } """ if not ai_generator or not ai_generator.is_available(): raise HTTPException( status_code=503, detail="Generador de IA no disponible. Configure ANTHROPIC_API_KEY" ) if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: # Generar contenido con IA ai_content = ai_generator.generate_post_content( prompt=request.prompt, style=request.style, tone=request.tone, language=request.language ) if not ai_content: raise HTTPException(status_code=500, detail="Error generando contenido con IA") # Crear categorías si no existen category_ids = [] if ai_content.get('categories'): for cat_name in ai_content['categories']: cats = await wp_client.list_categories(per_page=100) found = False for cat in cats: if cat.get('name', '').lower() == cat_name.lower(): category_ids.append(cat['id']) found = True break # Crear tags si no existen tag_ids = [] if ai_content.get('tags'): for tag_name in ai_content['tags']: tags = await wp_client.list_tags(per_page=100) found = False for tag in tags: if tag.get('name', '').lower() == tag_name.lower(): tag_ids.append(tag['id']) found = True break if not found: try: new_tag = await wp_client.create_tag(name=tag_name) tag_ids.append(new_tag['id']) except: pass # Crear post en WordPress post_result = await wp_client.create_post( title=ai_content['title'], content=ai_content['content'], status=request.status, categories=category_ids if category_ids else None, tags=tag_ids if tag_ids else None ) # Añadir información extra return { "success": True, "post_id": post_result.get('id'), "title": post_result.get('title', {}).get('rendered', 'N/A'), "link": post_result.get('link'), "status": post_result.get('status'), "ai_generated": True, "ai_categories": ai_content.get('categories', []), "ai_tags": ai_content.get('tags', []), "excerpt": ai_content.get('excerpt', '') } except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") @app.post("/ai/generate-content") async def generate_content_only(request: GeneratePostRequest): """ Genera contenido con IA SIN publicar Útil para preview o edición manual antes de publicar """ if not ai_generator or not ai_generator.is_available(): raise HTTPException( status_code=503, detail="Generador de IA no disponible. Configure ANTHROPIC_API_KEY" ) try: ai_content = ai_generator.generate_post_content( prompt=request.prompt, style=request.style, tone=request.tone, language=request.language ) if not ai_content: raise HTTPException(status_code=500, detail="Error generando contenido") return { "success": True, "ai_generated": True, "content": ai_content } except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") @app.post("/ai/improve-post") async def improve_post(request: ImprovePostRequest): """Mejora un post existente usando IA""" if not ai_generator or not ai_generator.is_available(): raise HTTPException( status_code=503, detail="Generador de IA no disponible. Configure ANTHROPIC_API_KEY" ) if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: # Obtener post actual (simplificado) posts = await wp_client.list_posts(per_page=100) current_post = None for post in posts: if post.get('id') == request.post_id: current_post = post break if not current_post: raise HTTPException(status_code=404, detail=f"Post {request.post_id} no encontrado") # Mejorar contenido current_content = current_post.get('content', {}).get('rendered', '') improved_content = ai_generator.improve_content( original_content=current_content, improvements=request.improvements ) if not improved_content: raise HTTPException(status_code=500, detail="Error mejorando contenido") # Actualizar post result = await wp_client.update_post( post_id=request.post_id, content=improved_content ) return { "success": True, "post_id": result.get('id'), "ai_improved": True, "link": result.get('link') } except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") # === Endpoints de WordPress (sin IA) === @app.post("/posts/create") async def create_post(request: CreatePostRequest): """Crea un post manualmente (sin IA)""" if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: result = await wp_client.create_post( title=request.title, content=request.content, status=request.status, categories=request.categories, tags=request.tags ) return { "success": True, "post_id": result.get('id'), "title": result.get('title', {}).get('rendered', 'N/A'), "link": result.get('link'), "status": result.get('status') } except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") @app.get("/posts") async def list_posts(per_page: int = 10, page: int = 1): """Lista posts de WordPress""" if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: posts = await wp_client.list_posts(per_page=per_page, page=page) return {"success": True, "posts": posts} except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") @app.get("/categories") async def list_categories(per_page: int = 100): """Lista categorías de WordPress""" if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: categories = await wp_client.list_categories(per_page=per_page) return {"success": True, "categories": categories} except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") @app.get("/tags") async def list_tags(per_page: int = 100): """Lista tags de WordPress""" if not wp_client: raise HTTPException(status_code=500, detail="Cliente de WordPress no inicializado") try: tags = await wp_client.list_tags(per_page=per_page) return {"success": True, "tags": tags} except Exception as e: raise HTTPException(status_code=500, detail=f"Error: {str(e)}") # === Main === if __name__ == "__main__": import uvicorn port = int(os.getenv('PORT', 8000)) print("=" * 60) print("🚀 WordPress MCP HTTP Server") print("=" * 60) print(f"Puerto: {port}") print(f"WordPress: {os.getenv('WP_URL')}") print(f"IA disponible: {os.getenv('ANTHROPIC_API_KEY', 'NO')[:10]}...") print() print("Endpoints principales:") print(f" POST /ai/generate-post - Generar post con IA") print(f" POST /posts/create - Crear post manual") print(f" GET /posts - Listar posts") print() uvicorn.run(app, host="0.0.0.0", port=port)

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/JRafael2023/mcpwp'

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