Files
odoo-ai/agent_service/routers/mcp_router.py
Carlos Garcia c769fca79f fix: resolve all 5 startup constructor errors + add DB retry
Fixes all errors reported in docker compose logs agent-service:

1. config.py: add ollama_max_concurrent, claude_timeout, claude_max_concurrent
   fields so LLMRouter(config=settings) can read them without AttributeError.

2. main.py - LLM router: drop manual OllamaBackend/ClaudeBackend construction;
   call LLMRouter(config=settings, pg_pool=pool) to match class signature.
   Fixes: OllamaBackend.__init__() unexpected kwarg 'base_url'.

3. main.py - DB: add 5-attempt retry with 2s backoff and redacted DSN logging.
   Fixes: connection refused race on startup before Postgres accepts connections.

4. main.py - AgentRegistry: call AgentRegistry() with no args (class takes none),
   then await agent_registry.load_from_odoo(odoo) to populate active agents.
   Fixes: AgentRegistry.__init__() unexpected kwarg 'odoo'.

5. main.py - PeerBus: pass registry=agent_registry at construction; register
   specialist agents on agent_registry (not peer_bus, which has no register()).
   peer_bus.py: make directive_id optional (default None) — bus is a singleton
   at startup; directive_id is only needed per-request.
   Fixes: PeerBus.__init__() missing positional args 'registry' and 'directive_id'.

6. main.py - MasterAgent: drop unexpected peer_bus= kwarg from constructor call.
   Fixes: MasterAgent.__init__() unexpected kwarg 'peer_bus'.

7. mcp_router.py: pass NotificationOptions() instance instead of None.
   Fixes: AttributeError 'NoneType' has no attribute 'tools_changed' (was applied
   in running container but not committed; now committed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 16:48:23 -04:00

59 lines
1.9 KiB
Python

"""
MCP gateway router — mounts SSE transport at /mcp/sse and /mcp/messages.
All requests that invoke agents are forced to local (Ollama) mode inside
server.py before any agent reasoning begins. The MCP client (e.g. Claude Code
CLI) only ever receives tool *results*, not any LLM completions.
"""
from __future__ import annotations
import logging
from mcp.server.models import InitializationOptions
from mcp.server.lowlevel import NotificationOptions
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Route
from ..mcp.server import create_mcp_server, build_sse_transport
logger = logging.getLogger(__name__)
# Singletons created once at module import time
_mcp_server = create_mcp_server()
_sse_transport = build_sse_transport()
_INIT_OPTIONS = InitializationOptions(
server_name='activeblue-ai',
server_version='0.1.0',
capabilities=_mcp_server.get_capabilities(
notification_options=NotificationOptions(),
experimental_capabilities={},
),
)
async def handle_sse(request: Request) -> Response:
"""SSE endpoint — client connects here to establish a session."""
logger.debug('MCP SSE connection from %s', request.client)
async with _sse_transport.connect_sse(
request.scope, request.receive, request._send
) as streams:
await _mcp_server.run(streams[0], streams[1], _INIT_OPTIONS)
return Response()
async def handle_post_message(request: Request) -> Response:
"""POST endpoint — client sends JSON-RPC tool call messages here."""
await _sse_transport.handle_post_message(
request.scope, request.receive, request._send
)
return Response()
# Starlette routes to be added to the FastAPI app
mcp_routes = [
Route('/mcp/sse', endpoint=handle_sse, methods=['GET']),
Route('/mcp/messages', endpoint=handle_post_message, methods=['POST']),
]