Retirar el servidor MCP y fijar todas las dependencias del API
MCP: se retira por completo (endpoint, paquete api/app/mcp/ y dependencia). Tres razones, en orden de peso: - Nadie lo usa. - Llevaba roto desde antes de este trabajo. Con credencial valida devolvia 500: el handler construia un StreamableHTTPServerTransport nuevo por peticion, sin manejo de sesion. Lo que estaba expuesto a internet era la puerta abierta de un cuarto averiado. - Su SDK sin fijar tumbo el API entero en produccion al saltar a 2.0.0. Retirarlo es una mitigacion mas fuerte que autenticarlo, que fue lo que hizo el commit anterior. Recuperable con `git show edb500f5:api/app/mcp/server.py`. Se limpia tambien la ruta "/mcp" que el endpoint raiz seguia anunciando, y las menciones a MCP del docstring y la descripcion de Swagger. Dependencias: once de las doce eran rangos `>=` sin techo, o sea que cada reconstruccion era una tirada de dados contra PyPI. `pydantic>=2.0` habria aceptado pydantic 3 con la misma alegria con la que `mcp>=1.0.0` acepto 2.0.0. Ahora todas van fijadas a la version exacta que corre sana en produccion, capturada con pip freeze del contenedor healthy. El lado Next.js ya era reproducible via package-lock.json; por eso el web nunca se cayo durante el incidente y el api si. Docs actualizados: AGENTS.md, README.md, api/COTIZADOR_API_SKILL.md y el spec, que ademas registra en su seccion 0 las tres desviaciones de Fase 0 respecto a lo disenado (el Despliegue B cancelado, la retirada del MCP y la deriva de dependencia). Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
edb500f517
commit
20f535d485
+10
-47
@@ -1,7 +1,7 @@
|
||||
"""Cotizador E3 — FastAPI Application
|
||||
|
||||
REST API + MCP Server for digital marketing quotation management.
|
||||
Optimized for n8n workflows and AI agents (OpenClaw, Claude, ChatGPT).
|
||||
REST API for digital marketing quotation management.
|
||||
Optimized for n8n workflows and other integrations.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -9,11 +9,10 @@ from __future__ import annotations
|
||||
from contextlib import asynccontextmanager
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from fastapi import Depends, FastAPI, Request
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.auth import require_auth
|
||||
from app.config import settings
|
||||
from app.database import close_db, init_db
|
||||
|
||||
@@ -29,8 +28,8 @@ app = FastAPI(
|
||||
title="Cotizador E3 API",
|
||||
description=(
|
||||
"API REST para el sistema de cotizaciones de marketing digital de Consultoría E3. "
|
||||
"Optimizada para integración con n8n y agentes de IA (OpenClaw, Claude, ChatGPT) "
|
||||
"via MCP (Model Context Protocol)."
|
||||
"Optimizada para integración con n8n y otros consumidores. "
|
||||
"Autenticación por X-API-Key o Bearer JWT."
|
||||
),
|
||||
version="1.0.0",
|
||||
lifespan=lifespan,
|
||||
@@ -99,46 +98,11 @@ app.include_router(financiamiento.router)
|
||||
app.include_router(export_.router)
|
||||
app.include_router(import_.router)
|
||||
|
||||
# Mount MCP server
|
||||
try:
|
||||
from app.mcp.server import server as mcp_server
|
||||
|
||||
from mcp.server.streamable_http import StreamableHTTPServerTransport
|
||||
|
||||
@app.post("/mcp")
|
||||
async def mcp_endpoint(request: Request, _auth: dict = Depends(require_auth)):
|
||||
"""MCP (Model Context Protocol) endpoint for AI agents.
|
||||
|
||||
Requiere autenticacion (X-API-Key o Bearer JWT), igual que el resto del API.
|
||||
Sin esto el endpoint quedaba abierto a internet: el servicio recibe dominio
|
||||
publico en produccion (docker-compose.coolify.yml, SERVICE_FQDN_API_8000) y
|
||||
las herramientas MCP leen y escriben cotizaciones directamente.
|
||||
"""
|
||||
transport = StreamableHTTPServerTransport(mcp_server)
|
||||
return await transport.handle_request(request)
|
||||
|
||||
@app.get("/mcp")
|
||||
async def mcp_info():
|
||||
"""MCP server info. Use POST for actual MCP communication."""
|
||||
return {
|
||||
"name": "cotizador-e3",
|
||||
"version": "1.0.0",
|
||||
"protocol": "mcp",
|
||||
"description": "MCP server for Cotizador E3 quotation system",
|
||||
}
|
||||
except Exception as exc: # noqa: BLE001
|
||||
# Antes esto capturaba solo ImportError. Cuando el SDK de MCP salto a 2.0.0 y
|
||||
# elimino Server.list_tools(), el import lanzo AttributeError, se escapo del
|
||||
# except y tumbo TODA la aplicacion: el REST tambien dejo de responder.
|
||||
# El servidor MCP es opcional; el REST no. Si el MCP no monta, se registra y
|
||||
# la API sigue de pie.
|
||||
import logging
|
||||
|
||||
logging.getLogger("uvicorn.error").error(
|
||||
"No se pudo montar el servidor MCP (%s: %s). El REST sigue disponible.",
|
||||
type(exc).__name__,
|
||||
exc,
|
||||
)
|
||||
# El servidor MCP se retiro (2026-07-28). No se estaba usando, su transporte
|
||||
# llevaba tiempo roto (instanciaba un StreamableHTTPServerTransport por peticion,
|
||||
# sin manejo de sesion, y devolvia 500 con credencial valida) y su SDK sin fijar
|
||||
# tumbo el API entero en produccion al saltar a 2.0.0. Si algun dia se retoma,
|
||||
# el codigo esta en el historial: `git show edb500f5:api/app/mcp/server.py`.
|
||||
|
||||
|
||||
@app.get("/", include_in_schema=False)
|
||||
@@ -149,7 +113,6 @@ async def root():
|
||||
"docs": "/docs",
|
||||
"openapi": "/openapi.json",
|
||||
"health": "/health",
|
||||
"mcp": "/mcp",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user