MCPcopy
hub / github.com/modelcontextprotocol/python-sdk / SseServerTransport

Class SseServerTransport

src/mcp/server/sse.py:64–262  ·  view source on GitHub ↗

SSE server transport for MCP. This class provides two ASGI applications, suitable for use with a framework like Starlette and a server like Hypercorn: 1. connect_sse() is an ASGI application which receives incoming GET requests, and sets up a new SSE stream to send server mes

Source from the content-addressed store, hash-verified

62
63
64class SseServerTransport:
65 """SSE server transport for MCP. This class provides two ASGI applications,
66 suitable for use with a framework like Starlette and a server like Hypercorn:
67
68 1. connect_sse() is an ASGI application which receives incoming GET requests,
69 and sets up a new SSE stream to send server messages to the client.
70 2. handle_post_message() is an ASGI application which receives incoming POST
71 requests, which should contain client messages that link to a
72 previously-established SSE session.
73 """
74
75 _endpoint: str
76 _read_stream_writers: dict[UUID, ContextSendStream[SessionMessage | Exception]]
77 # Identity of the credential that created each session; requests for a
78 # session must present the same credential.
79 _session_owners: dict[UUID, AuthorizationContext]
80 _security: TransportSecurityMiddleware
81
82 def __init__(self, endpoint: str, security_settings: TransportSecuritySettings | None = None) -> None:
83 """Creates a new SSE server transport, which will direct the client to POST
84 messages to the relative path given.
85
86 Args:
87 endpoint: A relative path where messages should be posted
88 (e.g., "/messages/").
89 security_settings: Optional security settings for DNS rebinding protection.
90
91 Note:
92 We use relative paths instead of full URLs for several reasons:
93 1. Security: Prevents cross-origin requests by ensuring clients only connect
94 to the same origin they established the SSE connection with
95 2. Flexibility: The server can be mounted at any path without needing to
96 know its full URL
97 3. Portability: The same endpoint configuration works across different
98 environments (development, staging, production)
99
100 Raises:
101 ValueError: If the endpoint is a full URL instead of a relative path
102 """
103
104 super().__init__()
105
106 # Validate that endpoint is a relative path and not a full URL
107 if "://" in endpoint or endpoint.startswith("//") or "?" in endpoint or "#" in endpoint:
108 raise ValueError(
109 f"Given endpoint: {endpoint} is not a relative path (e.g., '/messages/'), "
110 "expecting a relative path (e.g., '/messages/')."
111 )
112
113 # Ensure endpoint starts with a forward slash
114 if not endpoint.startswith("/"):
115 endpoint = "/" + endpoint
116
117 self._endpoint = endpoint
118 self._read_stream_writers = {}
119 self._session_owners = {}
120 self._security = TransportSecurityMiddleware(security_settings)
121 logger.debug(f"SseServerTransport initialized with endpoint: {endpoint}")

Calls

no outgoing calls