Files
2026-07-13 12:39:17 +08:00

101 lines
3.0 KiB
Python

import asyncio
import os
import shutil
import socket
import subprocess
import time
from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
from typing import Any, cast
from agents import Agent, Runner, gen_trace_id, trace
from agents.mcp import MCPServerSse
from agents.model_settings import ModelSettings
SSE_HOST = os.getenv("SSE_HOST", "127.0.0.1")
REMOTE_SSE_URL = os.getenv("MCP_SSE_REMOTE_URL")
def _choose_port() -> int:
env_port = os.getenv("SSE_PORT")
if env_port:
return int(env_port)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((SSE_HOST, 0))
address = cast(tuple[str, int], sock.getsockname())
return address[1]
@contextmanager
def local_sse_server() -> Iterator[str]:
if not shutil.which("uv"):
raise RuntimeError(
"uv is not installed. Please install it: "
"https://docs.astral.sh/uv/getting-started/installation/"
)
sse_port = _choose_port()
sse_url = f"http://{SSE_HOST}:{sse_port}/sse"
server_file = Path(__file__).resolve().parents[1] / "sse_example" / "server.py"
print(f"Starting local SSE server at {sse_url} ...", flush=True)
env = os.environ.copy()
env.setdefault("SSE_HOST", SSE_HOST)
env["SSE_PORT"] = str(sse_port)
process: subprocess.Popen[Any] | None = None
try:
process = subprocess.Popen(["uv", "run", str(server_file)], env=env)
time.sleep(3)
yield sse_url
finally:
if process is not None:
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
process.wait()
async def run(url: str, name: str) -> None:
async with MCPServerSse(
name=name,
params={
"url": url,
"timeout": 5,
"sse_read_timeout": 30,
},
) as server:
agent = Agent(
name="SSE Assistant",
instructions="Use the available MCP tools to answer the user.",
mcp_servers=[server],
model_settings=ModelSettings(tool_choice="required"),
)
trace_id = gen_trace_id()
with trace(workflow_name="SSE MCP Server Example", trace_id=trace_id):
print(f"View trace: https://platform.openai.com/traces/trace?trace_id={trace_id}\n")
result = await Runner.run(agent, "Use the MCP add tool to add 7 and 22.")
print(result.final_output)
async def main() -> None:
if REMOTE_SSE_URL:
print(f"Connecting to remote SSE server at {REMOTE_SSE_URL} ...", flush=True)
await run(REMOTE_SSE_URL, "Remote SSE Server")
return
print(
"MCP_SSE_REMOTE_URL is not set; using the bundled local SSE server for this demo.",
flush=True,
)
with local_sse_server() as url:
await run(url, "Local SSE Server")
if __name__ == "__main__":
asyncio.run(main())