LlamaIndex
Connect a LlamaIndex agent to Edison Watch using BasicMCPClient and McpToolSpec, keeping a stable session per conversation so data-leak protection holds across every turn.
LlamaIndex connects to Edison with BasicMCPClient, which auto-selects streamable HTTP for an https:// URL like Edison's. McpToolSpec turns the server's tools into LlamaIndex tools. Your connection URL carries your API key, so no auth header is needed.
pip install llama-index-tools-mcp llama-index-llms-openai llama-indeximport asyncio
import os
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import FunctionAgent
async def main() -> None:
client = BasicMCPClient(os.environ["EDISON_MCP_URL"])
tools = await McpToolSpec(client=client).to_tool_list_async()
agent = FunctionAgent(tools=tools, llm=OpenAI(model="gpt-5.4-mini"))
response = await agent.run("List my available tools.")
print(response)
asyncio.run(main())Set EDISON_MCP_URL to your connection URL, e.g. https://mcp.edison.watch/mcp/<your-api-key>/?client=llamaindex.
llama-index-llms-openai resolves each model against a hardcoded context-window
table and raises ValueError: Unknown model for anything not in it - so a
brand-new model id can fail until you upgrade the integration. Pick a model your
installed version knows (upgrade with pip install -U llama-index-llms-openai),
or use OpenAILike from llama-index-llms-openai-like to skip the table
entirely.
Keep a stable session across turns to preserve data-leak protection
Send a stable x-edison-conversation-id header on every turn of the same conversation. That header is what keeps Edison's data-leak protection intact across a multi-turn run: Edison tracks lethal-trifecta risk per session, so if each turn looks like a brand-new session, that protection resets - and a later turn can leak data that the accumulated risk should have blocked.
Hosted clients (Claude Code, VS Code) send it automatically. For a custom LlamaIndex agent, set the header on BasicMCPClient, keyed to your own conversation or thread id:
# Reuse one stable conversation_id for every turn of the same conversation.
client = BasicMCPClient(
os.environ["EDISON_MCP_URL"],
headers={"x-edison-conversation-id": conversation_id},
)Without a stable x-edison-conversation-id, each connection is treated as a fresh session that starts with empty risk state - so risk accumulated on an earlier turn won't be there to block a later exfiltration. The ?client= label is only a dashboard tag, not a session key. Use a unique id per conversation (a UUID is ideal); ids are scoped to your API key, so don't reuse one string for two different conversations.
Optional: the encrypted-secrets header
For servers with zero-knowledge-encrypted secrets, BasicMCPClient accepts a headers dict, alongside x-edison-conversation-id:
client = BasicMCPClient(
os.environ["EDISON_MCP_URL"],
headers={
"x-edison-conversation-id": conversation_id,
"x-edison-secret-key": os.environ["EDISON_SECRET_KEY"],
},
)The convenience helpers get_tools_from_mcp_url / aget_tools_from_mcp_url don't take a headers argument. To send a custom header with them, pass a pre-built client: aget_tools_from_mcp_url(url, client=BasicMCPClient(url, headers=...)).
Pydantic AI
Connect a Pydantic AI agent to Edison Watch over streamable HTTP, and keep a stable session per conversation so data-leak protection holds across every turn.
Google ADK
Connect a Google Agent Development Kit (ADK) agent to Edison Watch using MCPToolset, keeping a stable session per conversation so data-leak protection holds across every turn.

