Jeremiah Lowin commited on
Commit
e033dfc
·
1 Parent(s): 9077360

Clean up sse app

Browse files
Files changed (1) hide show
  1. src/fastmcp/server/http.py +25 -29
src/fastmcp/server/http.py CHANGED
@@ -78,19 +78,14 @@ def create_sse_app(
78
  additional_routes: Optional list of custom routes
79
 
80
  Returns:
81
- A Starlette application configured for SSE
82
  """
83
-
84
  # Set up SSE transport
85
  sse = SseServerTransport(message_path)
86
 
87
- async def handle_sse(scope: Scope, receive: Receive, send: Send):
88
- # Add client ID from auth context into request context if available
89
- async with sse.connect_sse(
90
- scope,
91
- receive,
92
- send,
93
- ) as streams:
94
  await server._mcp_server.run(
95
  streams[0],
96
  streams[1],
@@ -98,29 +93,31 @@ def create_sse_app(
98
  )
99
  return Response()
100
 
101
- # Create routes
102
  routes: list[Route | Mount] = []
103
  middleware: list[Middleware] = []
104
- required_scopes = []
105
 
106
- # Add auth endpoints if auth provider is configured
107
  if auth_server_provider:
108
- assert auth_settings
109
-
110
- required_scopes = auth_settings.required_scopes or []
 
 
111
 
 
112
  middleware = [
113
- # extract auth info from request (but do not require it)
114
  Middleware(
115
  AuthenticationMiddleware,
116
- backend=BearerAuthBackend(
117
- provider=auth_server_provider,
118
- ),
119
  ),
120
- # Add the auth context middleware to store
121
- # authenticated user in a contextvar
122
  Middleware(AuthContextMiddleware),
123
  ]
 
 
 
 
 
124
  routes.extend(
125
  create_auth_routes(
126
  provider=auth_server_provider,
@@ -131,9 +128,7 @@ def create_sse_app(
131
  )
132
  )
133
 
134
- # When auth is not configured, we shouldn't require auth
135
- if auth_server_provider:
136
- # Auth is enabled, wrap the endpoints with RequireAuthMiddleware
137
  routes.append(
138
  Route(
139
  sse_path,
@@ -148,10 +143,8 @@ def create_sse_app(
148
  )
149
  )
150
  else:
151
- # Auth is disabled, no need for RequireAuthMiddleware
152
- # Since handle_sse is an ASGI app, we need to create a compatible endpoint
153
  async def sse_endpoint(request: Request) -> Response:
154
- # Convert the Starlette request to ASGI parameters
155
  return await handle_sse(request.scope, request.receive, request._send) # type: ignore[reportPrivateUsage]
156
 
157
  routes.append(
@@ -168,9 +161,12 @@ def create_sse_app(
168
  )
169
  )
170
 
171
- # mount custom routes last, so they have the lowest route matching precedence
172
  if additional_routes:
173
  routes.extend(additional_routes)
174
 
175
- # Create Starlette app with routes and middleware
 
 
 
176
  return Starlette(debug=debug, routes=routes, middleware=middleware)
 
78
  additional_routes: Optional list of custom routes
79
 
80
  Returns:
81
+ A Starlette application with RequestContextMiddleware
82
  """
 
83
  # Set up SSE transport
84
  sse = SseServerTransport(message_path)
85
 
86
+ # Create handler for SSE connections
87
+ async def handle_sse(scope: Scope, receive: Receive, send: Send) -> Response:
88
+ async with sse.connect_sse(scope, receive, send) as streams:
 
 
 
 
89
  await server._mcp_server.run(
90
  streams[0],
91
  streams[1],
 
93
  )
94
  return Response()
95
 
96
+ # Configure routes and middleware
97
  routes: list[Route | Mount] = []
98
  middleware: list[Middleware] = []
 
99
 
100
+ # Handle authentication configuration
101
  if auth_server_provider:
102
+ # Ensure auth settings are provided when auth provider is present
103
+ if not auth_settings:
104
+ raise ValueError(
105
+ "auth_settings must be provided when auth_server_provider is specified"
106
+ )
107
 
108
+ # Configure auth middleware
109
  middleware = [
 
110
  Middleware(
111
  AuthenticationMiddleware,
112
+ backend=BearerAuthBackend(provider=auth_server_provider),
 
 
113
  ),
 
 
114
  Middleware(AuthContextMiddleware),
115
  ]
116
+
117
+ # Get required scopes for authentication
118
+ required_scopes = auth_settings.required_scopes or []
119
+
120
+ # Add auth routes
121
  routes.extend(
122
  create_auth_routes(
123
  provider=auth_server_provider,
 
128
  )
129
  )
130
 
131
+ # Add authenticated routes
 
 
132
  routes.append(
133
  Route(
134
  sse_path,
 
143
  )
144
  )
145
  else:
146
+ # No authentication required
 
147
  async def sse_endpoint(request: Request) -> Response:
 
148
  return await handle_sse(request.scope, request.receive, request._send) # type: ignore[reportPrivateUsage]
149
 
150
  routes.append(
 
161
  )
162
  )
163
 
164
+ # Add custom routes with lowest precedence
165
  if additional_routes:
166
  routes.extend(additional_routes)
167
 
168
+ # Add RequestContextMiddleware as the outermost middleware
169
+ middleware.append(Middleware(RequestContextMiddleware))
170
+
171
+ # Create and return the Starlette app with middleware
172
  return Starlette(debug=debug, routes=routes, middleware=middleware)