Spaces:
Sleeping
Sleeping
Download backend/mcp_client.py from EnvironmentalAI/WaterScopeAI-Search: direct link, hf CLI and curl.
- Browser
- Download file 2.38 kB
-
https://huggingface.co/spaces/EnvironmentalAI/WaterScopeAI-Search/resolve/main/backend/mcp_client.py
- Command line
-
hf download hf://spaces/EnvironmentalAI/WaterScopeAI-Search/backend/mcp_client.py
-
curl -L -o mcp_client.py https://huggingface.co/spaces/EnvironmentalAI/WaterScopeAI-Search/resolve/main/backend/mcp_client.py
2.38 kB
| """Persistent MCP client for the local paper retrieval server.""" | |
| from __future__ import annotations | |
| import json | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from typing import Any | |
| from mcp import ClientSession, StdioServerParameters | |
| from mcp.client.stdio import stdio_client | |
| PROJECT_ROOT = Path(__file__).resolve().parents[1] | |
| class PaperMCPClient: | |
| """Keeps one MCP session open for retrieval tool calls.""" | |
| def __init__(self, project_root: Path | None = None): | |
| self.project_root = project_root or PROJECT_ROOT | |
| self._stdio_ctx = None | |
| self._session_ctx = None | |
| self._session: ClientSession | None = None | |
| async def connect(self) -> None: | |
| if self._session is not None: | |
| return | |
| server_script = os.getenv("MCP_SERVER_SCRIPT", "waterscope_retrieval_server.py") | |
| server_params = StdioServerParameters( | |
| command=sys.executable, | |
| args=[str(self.project_root / server_script)], | |
| cwd=str(self.project_root), | |
| env={**os.environ}, | |
| ) | |
| self._stdio_ctx = stdio_client(server_params) | |
| read, write = await self._stdio_ctx.__aenter__() | |
| self._session_ctx = ClientSession(read, write) | |
| self._session = await self._session_ctx.__aenter__() | |
| await self._session.initialize() | |
| async def close(self) -> None: | |
| if self._session_ctx is not None: | |
| await self._session_ctx.__aexit__(None, None, None) | |
| self._session_ctx = None | |
| self._session = None | |
| if self._stdio_ctx is not None: | |
| await self._stdio_ctx.__aexit__(None, None, None) | |
| self._stdio_ctx = None | |
| async def call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> Any: | |
| if self._session is None: | |
| raise RuntimeError("MCP client is not connected.") | |
| payload = {key: value for key, value in (arguments or {}).items() if value is not None} | |
| result = await self._session.call_tool(name, payload) | |
| if result.isError: | |
| message = result.content[0].text if result.content else "Unknown MCP tool error" | |
| raise RuntimeError(message) | |
| if not result.content: | |
| return {} | |
| text = result.content[0].text | |
| return json.loads(text) | |