Edison Watch
Developers

Microsoft Agent Framework

Connect a Microsoft Agent Framework agent to Edison Watch using MCPStreamableHTTPTool, keeping a stable session per conversation so data-leak protection holds across every turn.

The Microsoft Agent Framework (the successor unifying Semantic Kernel and AutoGen) connects to Edison with MCPStreamableHTTPTool. Your connection URL carries your API key, so no auth header is needed.

pip install agent-framework

MCPStreamableHTTPTool is an async context manager - enter it with async with before running the agent. On a slim install you may also need pip install mcp --pre to pull in the MCP tool classes.

import asyncio
import os

from agent_framework import MCPStreamableHTTPTool, Agent
from agent_framework.openai import OpenAIChatClient

async def main() -> None:
    edison = MCPStreamableHTTPTool(
        name="edison",
        url=os.environ["EDISON_MCP_URL"],
    )
    async with edison:
        agent = Agent(
            OpenAIChatClient(model="gpt-5.6-luna"),
            name="assistant",
            instructions="Use the Edison tools to answer.",
            tools=edison,
        )
        result = await agent.run("List my available tools.")
        print(result)

asyncio.run(main())

Set EDISON_MCP_URL to your connection URL, e.g. https://mcp.edison.watch/mcp/<your-api-key>/?client=agent-framework.

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 Agent Framework agent, attach the header through a custom http_client. MCPStreamableHTTPTool has no headers= argument, so the client is how you get the header onto every request - including the initial tool listing that establishes the session:

import httpx

# Reuse one stable conversation_id for every turn of the same conversation.
http_client = httpx.AsyncClient(
    headers={"x-edison-conversation-id": conversation_id},
)
edison = MCPStreamableHTTPTool(
    name="edison",
    url=os.environ["EDISON_MCP_URL"],
    http_client=http_client,
)
# You own the client's lifecycle - wrap it in `async with httpx.AsyncClient(...)`
# or close it when the conversation ends.

The framework's header_provider hook is not enough here: it injects headers per tool call but not on the tool-listing request, so Edison would still see that first request as an unidentified client. A custom http_client puts the header on every request.

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, add x-edison-secret-key to the same http_client, alongside x-edison-conversation-id:

http_client = httpx.AsyncClient(
    headers={
        "x-edison-conversation-id": conversation_id,
        "x-edison-secret-key": os.environ["EDISON_SECRET_KEY"],
    },
)
edison = MCPStreamableHTTPTool(
    name="edison",
    url=os.environ["EDISON_MCP_URL"],
    http_client=http_client,
)