Source code for tooluniverse.euhealth.euhealth_tool

"""
EU Health Information Portal tools: topic search and deep dive.

This module provides the *wrapper* layer used by the ToolUniverse MCP server.
The actual search logic resides in `tooluniverse.euhealth.tools_runtime`.

What this file does
-------------------
- Maps MCP tool calls → Python functions in tools_runtime.
- For topic search:
      EuHealthTopicSearchTool  →  euhealthinfo_search_<topic>()
- For deep dive:
      EuHealthDeepDiveTool    →  euhealthinfo_deepdive(...)

IMPORTANT
---------
The runtime layer supports *all* search parameters:

  - method: "keyword" | "embedding" | "hybrid"
  - alpha: float
  - top_k: int
  - limit: int
  - country: Optional[str]
  - language: Optional[str]
  - term_override: Optional[str]

This wrapper must forward all these inputs to preserve embedding/hybrid behavior
and ensure correct fallback warnings.
"""

from typing import Dict, Any, List, Optional
from tooluniverse.base_tool import BaseTool
from tooluniverse.tool_registry import register_tool

# The full runtime surface (topic search fns + deep dive)
from tooluniverse.euhealth import tools_runtime as rt


# ---------------------------------------------------------------------
# Topic Search Tool
# ---------------------------------------------------------------------
[docs] @register_tool("EuHealthTopicSearchTool") class EuHealthTopicSearchTool(BaseTool): """ Generic wrapper for all EU Health 'topic search' tools. The associated JSON config supplies: fields.topic = "euhealthinfo_search_cancer" (for example) Supported arguments: - limit: int - method: "keyword" | "embedding" | "hybrid" - alpha: float - top_k: int - country: Optional[str] - language: Optional[str] - term_override: Optional[str] Returns: Either: {"warning": "...", "results": [...]} (fallback) or [... shaped rows ...] """
[docs] def run(self, arguments: Dict[str, Any]) -> Any: topic = (self.tool_config.get("fields") or {}).get("topic") if not topic: return { "error": "EuHealthTopicSearchTool misconfigured: missing fields.topic" } fn = getattr(rt, topic, None) if fn is None or not callable(fn): return {"error": f"Topic function '{topic}' not found in tools_runtime"} # ---- pull ALL supported parameters ---- limit = int(arguments.get("limit", 25)) method = arguments.get("method", "hybrid") alpha = float(arguments.get("alpha", 0.5)) top_k = int(arguments.get("top_k", 25)) country = arguments.get("country", "") language = arguments.get("language", "") term_override = arguments.get("term_override", "") try: # ---- forward ALL parameters ---- return fn( limit=limit, method=method, alpha=alpha, top_k=top_k, country=country, language=language, term_override=term_override, ) except Exception as e: return {"error": f"euhealth topic search failed: {e}", "topic": topic}
# --------------------------------------------------------------------- # Deep Dive Tool # ---------------------------------------------------------------------
[docs] @register_tool("EuHealthDeepDiveTool") class EuHealthDeepDiveTool(BaseTool): """ Wrapper for the EU Health deep dive function. You can dive: - explicit UUIds: uuids=[...] - or a topic: topic="euhealthinfo_search_cancer" Supported arguments: - uuids: Optional[List[str]] - topic: Optional[str] - limit: int - links_per: int - method: "keyword" | "embedding" | "hybrid" - alpha: float - top_k: int - country: Optional[str] - language: Optional[str] - term_override: Optional[str] """
[docs] def run(self, arguments: Dict[str, Any]) -> Any: uuids = arguments.get("uuids") topic = arguments.get("topic") limit = int(arguments.get("limit", 10)) links_per = int(arguments.get("links_per", 3)) method = arguments.get("method", "hybrid") alpha = float(arguments.get("alpha", 0.5)) top_k = int(arguments.get("top_k", 25)) country = arguments.get("country", "") language = arguments.get("language", "") term_override = arguments.get("term_override", "") if not uuids and not topic: return {"error": "Provide either 'uuids' or 'topic' to run deep dive"} try: if uuids: return rt.euhealthinfo_deepdive( uuids=uuids, limit=limit, links_per=links_per, method=method, alpha=alpha, top_k=top_k, country=country, language=language, term_override=term_override, ) else: if not hasattr(rt, topic): return {"error": f"Unknown topic '{topic}' for deep dive"} return rt.euhealthinfo_deepdive( topic=topic, limit=limit, links_per=links_per, method=method, alpha=alpha, top_k=top_k, country=country, language=language, term_override=term_override, ) except Exception as e: return {"error": f"euhealth deep dive failed: {e}"}