Connect a Haystack pipeline to Civic’s MCP Hub using streamable HTTP transport
Connect a Haystack pipeline to Civic using MCPTool from the Haystack MCP integration. Because MCPTool wraps one named tool at a time, you first discover available tool names via the raw MCP client, then create a tool object for each.
Haystack’s MCPTool wraps a single named tool. First discover all tool names using the raw mcp client, then create MCPTool instances and pass them to AnthropicChatGenerator:
Copy
import osimport asynciofrom dotenv import load_dotenvfrom mcp.client.streamable_http import streamablehttp_clientfrom mcp import ClientSessionfrom haystack_integrations.tools.mcp import MCPTool, StreamableHttpServerInfofrom haystack.utils import Secretfrom haystack_integrations.components.generators.anthropic import AnthropicChatGeneratorfrom haystack.dataclasses import ChatMessageload_dotenv()CIVIC_URL = os.environ["CIVIC_URL"]CIVIC_TOKEN = os.environ["CIVIC_TOKEN"]async def get_tool_names(): """Discover available tool names from the Civic MCP Hub.""" headers = {"Authorization": f"Bearer {CIVIC_TOKEN}"} async with streamablehttp_client(CIVIC_URL, headers=headers) as (r, w, _): async with ClientSession(r, w) as session: await session.initialize() result = await session.list_tools() return [t.name for t in result.tools]def build_pipeline(tool_names): server_info = StreamableHttpServerInfo( url=CIVIC_URL, token=Secret.from_env_var("CIVIC_TOKEN"), ) civic_tools = [MCPTool(name=name, server_info=server_info) for name in tool_names] generator = AnthropicChatGenerator( model="claude-sonnet-4-6", tools=civic_tools, ) return generator, civic_toolsdef main(): tool_names = asyncio.run(get_tool_names()) print(f"{len(tool_names)} tools discovered") generator, _ = build_pipeline(tool_names) messages = [ ChatMessage.from_system("You are a helpful assistant with access to Civic tools."), ChatMessage.from_user("What events do I have today?"), ] response = generator.run(messages=messages) print(response["replies"][0].text)main()
MCPTool wraps a single named tool — not a server. You must discover tool names first using the raw mcp package, then create one MCPTool per name. Import AnthropicChatGenerator from haystack_integrations.components.generators.anthropic (requires the anthropic-haystack package).