BirdScopeAI / langgraph_agent /mcp_clients.py
facemelter's picture
Initial commit to hf space for hackathon
ff0e97f verified
"""
MCP client configuration and setup for bird classification agents.
"""
import os
from typing import List, Dict, Any
from langchain_mcp_adapters.client import MultiServerMCPClient
from .config import AgentConfig
class MCPClientManager:
"""Manages MCP client connections to various servers"""
@staticmethod
async def create_classifier_client() -> MultiServerMCPClient:
"""
Create MCP client for Modal bird classifier only.
Returns:
MultiServerMCPClient configured for Modal server
"""
print("[STATUS]: Connecting to Modal MCP server...")
client = MultiServerMCPClient({
"bird_classifier": {
"transport": "streamable_http",
"url": AgentConfig.MODAL_MCP_URL,
"headers": {
"X-API-Key": AgentConfig.BIRD_CLASSIFIER_API_KEY
}
}
})
return client
@staticmethod
async def create_multi_server_client() -> MultiServerMCPClient:
"""
Create MCP client for both Modal classifier and Nuthatch species database.
Returns:
MultiServerMCPClient configured for both servers
"""
print("[STATUS]: Connecting to Modal and Nuthatch servers...")
servers_config = {
"bird_classifier": {
"transport": "streamable_http",
"url": AgentConfig.MODAL_MCP_URL,
"headers": {
"X-API-Key": AgentConfig.BIRD_CLASSIFIER_API_KEY
}
}
}
# Add Nuthatch server (Phase 2.5 - species reference database)
# Supports both STDIO (default) and HTTP transport
if AgentConfig.NUTHATCH_USE_STDIO:
# STDIO mode - subprocess for integrated agent use
servers_config["nuthatch"] = {
"transport": "stdio",
"command": "python",
"args": ["nuthatch_tools.py"], # Same directory as where app runs
"env": {
# Pass through critical env vars from parent process
# HuggingFace Spaces Secrets don't auto-inherit to subprocesses
"NUTHATCH_API_KEY": AgentConfig.NUTHATCH_API_KEY,
"NUTHATCH_BASE_URL": AgentConfig.NUTHATCH_BASE_URL
}
}
else:
# HTTP mode - external server (requires nuthatch_tools.py running separately)
nuthatch_config = {
"transport": "streamable_http",
"url": AgentConfig.NUTHATCH_MCP_URL
}
# Add auth header if configured (DebugTokenVerifier expects Bearer token)
if AgentConfig.NUTHATCH_MCP_AUTH_KEY:
nuthatch_config["headers"] = {
"Authorization": f"Bearer {AgentConfig.NUTHATCH_MCP_AUTH_KEY}"
}
servers_config["nuthatch"] = nuthatch_config
client = MultiServerMCPClient(servers_config)
return client
@staticmethod
async def get_tools(client: MultiServerMCPClient) -> List[Any]:
"""
Get tools from MCP client and print summary.
Args:
client: MultiServerMCPClient instance
Returns:
List of tools
"""
print("[STATUS]: Loading MCP tools...")
tools = await client.get_tools()
print(f"[LOADED]: {len(tools)} tools available")
for tool in tools:
print(f" - {tool.name}")
return tools