coffre ObsiGate Phase 4 (issue #22) : app/services/mcp_client.py
FlowDeck CI / lint (push) Failing after 1s
FlowDeck CI / test (push) Failing after 1s
FlowDeck CI / docker (push) Skipped

This commit is contained in:
2026-10-27 23:48:03 -04:00
parent 4f13068c85
commit 30387c4ed4
+19 -9
View File
@@ -189,7 +189,8 @@ async def _handshake(url: str, headers: dict | None) -> dict:
return session
def _server(connector_id: int) -> dict:
def _server(connector_id: int, *, workspace_id: int | None = None,
distribute=None) -> dict:
row = get(connector_id)
if row is None:
raise ValueError("Serveur MCP introuvable")
@@ -198,7 +199,8 @@ def _server(connector_id: int) -> dict:
if not row["enabled"]:
raise ValueError("Serveur MCP désactivé")
return {"id": row["id"], "name": row["name"], "url": row["url"],
"headers": _headers(connector_id)}
"headers": _headers(connector_id, workspace_id=workspace_id,
distribute=distribute)}
def _normalize(server: dict, raw: list) -> list[dict]:
@@ -226,10 +228,16 @@ def _save_tools(connector_id: int, tools: list[dict]) -> None:
conn.commit()
async def initialize_and_list(connector_id: int) -> list[dict]:
"""Handshake + ``tools/list`` → met à jour le cache de la base."""
srv = _server(connector_id)
url = _with_secret(srv["url"], connector_id)
async def initialize_and_list(connector_id: int, *, workspace_id: int | None = None,
distribute=None) -> list[dict]:
"""Handshake + ``tools/list`` → met à jour le cache de la base.
Pour un serveur à référence ObsiGate, ``workspace_id`` est obligatoire
(isolation vérifiée avant distribution, voir ``connectors``).
"""
srv = _server(connector_id, workspace_id=workspace_id, distribute=distribute)
url = _with_secret(srv["url"], connector_id, workspace_id=workspace_id,
distribute=distribute)
session = await _handshake(url, srv["headers"])
data = await _rpc(url, {"jsonrpc": "2.0", "id": 2, "method": "tools/list",
"params": {}}, session)
@@ -276,14 +284,16 @@ def _content_text(result: dict) -> str:
return "\n".join(p for p in parts if p) or json.dumps(result, ensure_ascii=False)[:4000]
async def call_tool(connector_id: int, tool: str, arguments: dict | None = None) -> dict:
async def call_tool(connector_id: int, tool: str, arguments: dict | None = None, *,
workspace_id: int | None = None, distribute=None) -> dict:
"""``tools/call`` → {status, text} (isError → error, borné à 20 000 car.).
Le handshake (avec session éventuelle) précède systématiquement
l'appel : c'est la condition T0 des serveurs à session.
"""
srv = _server(connector_id)
url = _with_secret(srv["url"], connector_id)
srv = _server(connector_id, workspace_id=workspace_id, distribute=distribute)
url = _with_secret(srv["url"], connector_id, workspace_id=workspace_id,
distribute=distribute)
session = await _handshake(url, srv["headers"])
data = await _rpc(url, {
"jsonrpc": "2.0", "id": 3, "method": "tools/call",