coffre ObsiGate Phase 4 (issue #22) : app/services/mcp_client.py
This commit is contained in:
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user