SSE 전송

SSE 전송 (SSE Transport)

SSE(Server-Sent Events)는 웹 서버가 단일의 장기 HTTP 연결을 통해 클라이언트에게 업데이트를 보내는 표준 방식이에요. MCP 맥락에서 SSE는 원격 서버가 툴 응답 같은 데이터를 CrewAI 애플리케이션에 실시간으로 스트리밍하는 데 사용돼요.

출처: 문서

본문

Overview (개요)

Key Concepts (핵심 개념)

  • Remote Servers — SSE는 원격으로 호스팅되는 MCP 서버에 적합해요.
  • Unidirectional Stream — 보통 SSE는 서버에서 클라이언트로의 단방향 통신 채널이에요.
  • MCPServerAdapter Configuration — SSE에서는 서버의 URL을 제공하고 전송 유형을 지정하면 돼요.

Connecting via SSE (SSE로 연결하기)

SSE 기반 MCP 서버에는 연결 수명주기를 관리하는 두 가지 접근 방식이 있어요.

1. 완전 관리형 연결 (권장)

Python 컨텍스트 매니저(with 문)를 사용하는 것이 권장돼요. SSE MCP 서버와의 연결 수립과 종료를 자동으로 처리해 줘요.

from crewai import Agent, Task, Crew, Process
from crewai_tools import MCPServerAdapter

server_params = {
    "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL
    "transport": "sse" 
}

# Using MCPServerAdapter with a context manager
try:
    with MCPServerAdapter(server_params) as tools:
        print(f"Available tools from SSE MCP server: {[tool.name for tool in tools]}")

        # Example: Using a tool from the SSE MCP server
        sse_agent = Agent(
            role="Remote Service User",
            goal="Utilize a tool provided by a remote SSE MCP server.",
            backstory="An AI agent that connects to external services via SSE.",
            tools=tools,
            reasoning=True,
            verbose=True,
        )

        sse_task = Task(
            description="Fetch real-time stock updates for 'AAPL' using an SSE tool.",
            expected_output="The latest stock price for AAPL.",
            agent=sse_agent,
            markdown=True
        )

        sse_crew = Crew(
            agents=[sse_agent],
            tasks=[sse_task],
            verbose=True,
            process=Process.sequential
        )
        
        if tools: # Only kickoff if tools were loaded
            result = sse_crew.kickoff() # Add inputs={'stock_symbol': 'AAPL'} if tool requires it
            print("\nCrew Task Result (SSE - Managed):\n", result)
        else:
            print("Skipping crew kickoff as tools were not loaded (check server connection).")

except Exception as e:
    print(f"Error connecting to or using SSE MCP server (Managed): {e}")
    print("Ensure the SSE MCP server is running and accessible at the specified URL.")

"http://localhost:8000/sse"를 실제 SSE MCP 서버의 URL로 바꾸세요.

2. 수동 연결 수명주기 관리

더 세밀한 제어가 필요하다면 MCPServerAdapter 연결 수명주기를 수동으로 관리할 수 있어요.

연결이 닫히고 리소스가 해제되도록 하려면 반드시 mcp_server_adapter.stop()을 호출해야 해요. try...finally 블록을 사용하는 것을 강력히 권장해요.

from crewai import Agent, Task, Crew, Process
from crewai_tools import MCPServerAdapter

server_params = {
    "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL
    "transport": "sse"
}

mcp_server_adapter = None 
try:
    mcp_server_adapter = MCPServerAdapter(server_params)
    mcp_server_adapter.start()
    tools = mcp_server_adapter.tools
    print(f"Available tools (manual SSE): {[tool.name for tool in tools]}")

    manual_sse_agent = Agent(
        role="Remote Data Analyst",
        goal="Analyze data fetched from a remote SSE MCP server using manual connection management.",
        backstory="An AI skilled in handling SSE connections explicitly.",
        tools=tools,
        verbose=True
    )
    
    analysis_task = Task(
        description="Fetch and analyze the latest user activity trends from the SSE server.",
        expected_output="A summary report of user activity trends.",
        agent=manual_sse_agent
    )
    
    analysis_crew = Crew(
        agents=[manual_sse_agent],
        tasks=[analysis_task],
        verbose=True,
        process=Process.sequential
    )
    
    result = analysis_crew.kickoff()
    print("\nCrew Task Result (SSE - Manual):\n", result)

except Exception as e:
    print(f"An error occurred during manual SSE MCP integration: {e}")
    print("Ensure the SSE MCP server is running and accessible.")
finally:
    if mcp_server_adapter and mcp_server_adapter.is_connected:
        print("Stopping SSE MCP server connection (manual)...")
        mcp_server_adapter.stop()  # **Crucial: Ensure stop is called**
    elif mcp_server_adapter:
        print("SSE MCP server adapter was not connected. No stop needed or start failed.")

SSE의 보안 고려 사항

DNS Rebinding 공격: SSE 전송은 MCP 서버가 제대로 보호되지 않으면 DNS rebinding 공격에 취약할 수 있어요. 이는 악성 웹사이트가 로컬 또는 인트라넷 기반 MCP 서버와 상호작용하게 만들 수 있어요.

이 위험을 완화하려면:

  • MCP 서버 구현은 들어오는 SSE 연결의 Origin 헤더를 검증해야 해요.
  • 개발용 로컬 SSE MCP 서버를 실행할 때는 모든 네트워크 인터페이스(0.0.0.0)가 아닌 localhost(127.0.0.1)에만 바인딩하세요.
  • 민감한 툴이나 데이터를 노출한다면 모든 SSE 연결에 적절한 인증을 구현하세요.

보안 모범 사례에 대한 종합적인 개요는 보안 고려 사항 페이지와 공식 MCP Transport Security 문서를 참조하세요.

더 알아보기 (Learn more)