# interpro_entry_tool.py
"""
InterPro Entry API tool for ToolUniverse.
Provides access to InterPro REST API for retrieving domain/family
entries associated with a protein, and searching InterPro entries
by keyword.
API: https://www.ebi.ac.uk/interpro/api/
No authentication required. Free public access.
"""
import requests
from typing import Dict, Any
from .base_tool import BaseTool
INTERPRO_BASE_URL = "https://www.ebi.ac.uk/interpro/api"
[docs]
class InterProEntryTool(BaseTool):
"""
Tool for InterPro entry API providing protein-to-domain mappings
and domain/family search.
Complements existing InterPro tools by offering reverse lookups
(protein -> all domains) and keyword-based entry search.
No authentication required.
"""
[docs]
def __init__(self, tool_config: Dict[str, Any]):
super().__init__(tool_config)
self.timeout = tool_config.get("timeout", 60)
fields = tool_config.get("fields", {})
self.endpoint = fields.get("endpoint", "entries_for_protein")
[docs]
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Execute the InterPro entry API call."""
try:
return self._query(arguments)
except requests.exceptions.Timeout:
return {"error": f"InterPro API timed out after {self.timeout}s"}
except requests.exceptions.ConnectionError:
return {"error": "Failed to connect to InterPro API"}
except requests.exceptions.HTTPError as e:
code = e.response.status_code if e.response is not None else "unknown"
if code == 404:
return {
"error": f"Not found: {arguments.get('accession', arguments.get('query', ''))}"
}
return {"error": f"InterPro API HTTP error: {code}"}
except Exception as e:
return {"error": f"Unexpected error querying InterPro API: {str(e)}"}
[docs]
def _query(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Route to appropriate endpoint."""
if self.endpoint == "entries_for_protein":
return self._get_entries_for_protein(arguments)
elif self.endpoint == "search_entries":
return self._search_entries(arguments)
else:
return {"error": f"Unknown endpoint: {self.endpoint}"}
[docs]
def _get_entries_for_protein(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Get all InterPro domain/family entries annotated on a protein."""
accession = arguments.get("accession", "")
if not accession:
return {
"error": "accession parameter is required (UniProt accession, e.g., 'P04637')"
}
url = f"{INTERPRO_BASE_URL}/entry/interpro/protein/uniprot/{accession}"
params = {"page_size": 200}
response = requests.get(
url,
params=params,
headers={"Accept": "application/json"},
timeout=self.timeout,
)
response.raise_for_status()
data = response.json()
results = data.get("results", [])
entries = []
for r in results:
meta = r.get("metadata", {})
name_obj = meta.get("name", {})
if isinstance(name_obj, dict):
name = name_obj.get("name", "")
short_name = name_obj.get("short", "")
else:
name = str(name_obj) if name_obj else ""
short_name = ""
entries.append(
{
"accession": meta.get("accession"),
"name": name,
"short_name": short_name,
"type": meta.get("type"),
"source_database": meta.get("source_database"),
}
)
return {
"data": {
"protein_accession": accession,
"total_entries": data.get("count", len(entries)),
"entries": entries,
},
"metadata": {
"source": "InterPro API - Entries for Protein",
"accession": accession,
},
}
[docs]
def _search_entries(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Search InterPro entries by keyword."""
query = arguments.get("query", "")
if not query:
return {
"error": "query parameter is required (e.g., 'zinc finger', 'kinase', 'p53')"
}
entry_type = arguments.get("entry_type", None)
page_size = arguments.get("page_size", 20)
url = f"{INTERPRO_BASE_URL}/entry/interpro"
params = {
"search": query,
"page_size": min(page_size, 50),
}
if entry_type:
params["type"] = entry_type
response = requests.get(
url,
params=params,
headers={"Accept": "application/json"},
timeout=self.timeout,
)
response.raise_for_status()
data = response.json()
results = data.get("results", [])
entries = []
for r in results:
meta = r.get("metadata", {})
name_obj = meta.get("name", {})
if isinstance(name_obj, dict):
name = name_obj.get("name", "")
short_name = name_obj.get("short", "")
else:
name = str(name_obj) if name_obj else ""
short_name = ""
counters = meta.get("counters", {})
entries.append(
{
"accession": meta.get("accession"),
"name": name,
"short_name": short_name,
"type": meta.get("type"),
"protein_count": counters.get("proteins"),
"structure_count": counters.get("structures"),
"taxa_count": counters.get("taxa"),
}
)
return {
"data": {
"query": query,
"total_results": data.get("count", len(entries)),
"returned": len(entries),
"entries": entries,
},
"metadata": {
"source": "InterPro API - Entry Search",
"query": query,
},
}