# © 2026 Antonio Rodriguez Martinez / TONJ EU # All rights reserved. No use, copy, or distribution without written permission. # Legal actions built to execute. """ ulises_api.py — FastAPI app de ulises (:8001). Coherente con la arquitectura TONJ EU (FastAPI + CORS + OpenAPI 3.0). """ from __future__ import annotations from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from ulises.api.routes import health, chat, datasets, intel, excelencia from ulises.core.orchestrator import get_orchestrator from ulises.configs.settings import settings app = FastAPI( title="ulises.sty API", description=( "Sovereign Intelligence Navigator for TONJ-EU · " "Dataset Factory · EU AI Act Specialist · Regulatory Intelligence · " "Model Context Protocol Server" ), version="0.1.0", docs_url="/docs", redoc_url="/redoc", ) app.add_middleware( CORSMiddleware, allow_origins=settings.api_cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(health.router, prefix="/health", tags=["health"]) app.include_router(chat.router, prefix="/chat", tags=["specialist-llm"]) app.include_router(datasets.router, prefix="/datasets", tags=["dataset-factory"]) app.include_router(intel.router, prefix="/intel", tags=["regulatory-intel"]) app.include_router(excelencia.router, prefix="/excelencia", tags=["modo-excelencia"]) # ── MCP server (SSE) — comunicación MCP remota ─────────────────────────────── # Monta el FastMCP de gobernanza (10 tools TONJ/ulises) en /mcp para clientes # MCP remotos (SSE endpoint: /mcp/sse). Defensivo: si el paquete `mcp` o el # transporte no está disponible, ulises arranca igual (MCP sigue en stdio local). try: from ulises.mcp.server import mcp as _mcp_server _sse_factory = getattr(_mcp_server, "sse_app", None) if _sse_factory is not None: try: app.mount("/mcp", _sse_factory(mount_path="/mcp")) except TypeError: # versiones antiguas de FastMCP sin mount_path app.mount("/mcp", _sse_factory()) except Exception as _mcp_err: # pragma: no cover — nunca debe tumbar el arranque import logging logging.getLogger("ulises.api").warning("MCP SSE mount no disponible: %s", _mcp_err) # ── TON.OS montado en /tonos ───────────────────────────────────────────────── # HF bloquea crear Spaces Docker nuevos en free tier, así que TON.OS (runtime + # consolas INTAKE/ASSISTANT/Research/Delivery) se sirve desde este Space bajo # /tonos. Defensivo: si tonos no está disponible, ulises arranca igual. try: from tonos.api.tonos_api import app as _tonos_app app.mount("/tonos", _tonos_app) except Exception as _tonos_err: # pragma: no cover import logging logging.getLogger("ulises.api").warning("TON.OS mount no disponible: %s", _tonos_err) @app.on_event("startup") async def startup(): orch = get_orchestrator() await orch.startup() @app.get("/") def root(): return { "system": "ulises.sty + TONJ-EU", "version": "0.1.0", "endpoints": { "health": "GET /health", "chat": "POST /chat", "datasets": "POST /datasets/generate | GET /datasets/list", "intel": "GET /intel/status | GET /intel/threats | POST /intel/push", "excelencia": "POST /excelencia/audit | GET /excelencia/status", "docs": "GET /docs", }, "tonj_eu": { "api": "http://127.0.0.1:8000", "dashboard": "http://localhost:8502", }, "mcp": {"remote_sse": "/mcp/sse", "local_stdio": "python -m ulises.mcp.server"}, }