fastmcp 2.2.9__py3-none-any.whl → 2.3.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastmcp/__init__.py +2 -1
- fastmcp/cli/cli.py +1 -1
- fastmcp/client/client.py +3 -2
- fastmcp/client/transports.py +45 -1
- fastmcp/prompts/prompt.py +10 -15
- fastmcp/prompts/prompt_manager.py +3 -10
- fastmcp/resources/resource.py +2 -7
- fastmcp/resources/resource_manager.py +2 -4
- fastmcp/resources/template.py +11 -24
- fastmcp/resources/types.py +15 -44
- fastmcp/server/__init__.py +1 -0
- fastmcp/server/context.py +50 -38
- fastmcp/server/dependencies.py +35 -0
- fastmcp/server/http.py +309 -0
- fastmcp/server/openapi.py +5 -16
- fastmcp/server/proxy.py +4 -13
- fastmcp/server/server.py +196 -271
- fastmcp/server/streamable_http_manager.py +241 -0
- fastmcp/settings.py +20 -0
- fastmcp/tools/tool.py +40 -33
- fastmcp/tools/tool_manager.py +3 -9
- fastmcp/utilities/cache.py +26 -0
- fastmcp/utilities/tests.py +113 -0
- fastmcp/utilities/types.py +4 -7
- {fastmcp-2.2.9.dist-info → fastmcp-2.3.0rc1.dist-info}/METADATA +6 -2
- fastmcp-2.3.0rc1.dist-info/RECORD +55 -0
- fastmcp/utilities/http.py +0 -44
- fastmcp-2.2.9.dist-info/RECORD +0 -51
- {fastmcp-2.2.9.dist-info → fastmcp-2.3.0rc1.dist-info}/WHEEL +0 -0
- {fastmcp-2.2.9.dist-info → fastmcp-2.3.0rc1.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.2.9.dist-info → fastmcp-2.3.0rc1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, ParamSpec, TypeVar
|
|
4
|
+
|
|
5
|
+
from starlette.requests import Request
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from fastmcp.server.context import Context
|
|
9
|
+
|
|
10
|
+
P = ParamSpec("P")
|
|
11
|
+
R = TypeVar("R")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# --- Context ---
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_context() -> Context:
|
|
18
|
+
from fastmcp.server.context import _current_context
|
|
19
|
+
|
|
20
|
+
context = _current_context.get()
|
|
21
|
+
if context is None:
|
|
22
|
+
raise RuntimeError("No active context found.")
|
|
23
|
+
return context
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# --- HTTP Request ---
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_http_request() -> Request:
|
|
30
|
+
from fastmcp.server.http import _current_http_request
|
|
31
|
+
|
|
32
|
+
request = _current_http_request.get()
|
|
33
|
+
if request is None:
|
|
34
|
+
raise RuntimeError("No active HTTP request found.")
|
|
35
|
+
return request
|
fastmcp/server/http.py
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncGenerator, Callable, Generator
|
|
4
|
+
from contextlib import asynccontextmanager, contextmanager
|
|
5
|
+
from contextvars import ContextVar
|
|
6
|
+
from typing import TYPE_CHECKING, cast
|
|
7
|
+
|
|
8
|
+
from mcp.server.auth.middleware.auth_context import AuthContextMiddleware
|
|
9
|
+
from mcp.server.auth.middleware.bearer_auth import (
|
|
10
|
+
BearerAuthBackend,
|
|
11
|
+
RequireAuthMiddleware,
|
|
12
|
+
)
|
|
13
|
+
from mcp.server.auth.provider import OAuthAuthorizationServerProvider
|
|
14
|
+
from mcp.server.auth.routes import create_auth_routes
|
|
15
|
+
from mcp.server.auth.settings import AuthSettings
|
|
16
|
+
from mcp.server.sse import SseServerTransport
|
|
17
|
+
from starlette.applications import Starlette
|
|
18
|
+
from starlette.middleware import Middleware
|
|
19
|
+
from starlette.middleware.authentication import AuthenticationMiddleware
|
|
20
|
+
from starlette.requests import Request
|
|
21
|
+
from starlette.responses import Response
|
|
22
|
+
from starlette.routing import Mount, Route
|
|
23
|
+
from starlette.types import Receive, Scope, Send
|
|
24
|
+
|
|
25
|
+
# This import is vendored until it is finalized in the upstream SDK
|
|
26
|
+
from fastmcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
|
27
|
+
from fastmcp.utilities.logging import get_logger
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from fastmcp.server.server import FastMCP
|
|
31
|
+
|
|
32
|
+
logger = get_logger(__name__)
|
|
33
|
+
|
|
34
|
+
_current_http_request: ContextVar[Request | None] = ContextVar(
|
|
35
|
+
"http_request",
|
|
36
|
+
default=None,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@contextmanager
|
|
41
|
+
def set_http_request(request: Request) -> Generator[Request, None, None]:
|
|
42
|
+
token = _current_http_request.set(request)
|
|
43
|
+
try:
|
|
44
|
+
yield request
|
|
45
|
+
finally:
|
|
46
|
+
_current_http_request.reset(token)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class RequestContextMiddleware:
|
|
50
|
+
"""
|
|
51
|
+
Middleware that stores each request in a ContextVar
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, app):
|
|
55
|
+
self.app = app
|
|
56
|
+
|
|
57
|
+
async def __call__(self, scope, receive, send):
|
|
58
|
+
if scope["type"] == "http":
|
|
59
|
+
with set_http_request(Request(scope)):
|
|
60
|
+
await self.app(scope, receive, send)
|
|
61
|
+
else:
|
|
62
|
+
await self.app(scope, receive, send)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def setup_auth_middleware_and_routes(
|
|
66
|
+
auth_server_provider: OAuthAuthorizationServerProvider | None,
|
|
67
|
+
auth_settings: AuthSettings | None,
|
|
68
|
+
) -> tuple[list[Middleware], list[Route | Mount], list[str]]:
|
|
69
|
+
"""Set up authentication middleware and routes if auth is enabled.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
auth_server_provider: The OAuth authorization server provider
|
|
73
|
+
auth_settings: The auth settings
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Tuple of (middleware, auth_routes, required_scopes)
|
|
77
|
+
"""
|
|
78
|
+
middleware: list[Middleware] = []
|
|
79
|
+
auth_routes: list[Route | Mount] = []
|
|
80
|
+
required_scopes: list[str] = []
|
|
81
|
+
|
|
82
|
+
if auth_server_provider:
|
|
83
|
+
if not auth_settings:
|
|
84
|
+
raise ValueError(
|
|
85
|
+
"auth_settings must be provided when auth_server_provider is specified"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
middleware = [
|
|
89
|
+
Middleware(
|
|
90
|
+
AuthenticationMiddleware,
|
|
91
|
+
backend=BearerAuthBackend(provider=auth_server_provider),
|
|
92
|
+
),
|
|
93
|
+
Middleware(AuthContextMiddleware),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
required_scopes = auth_settings.required_scopes or []
|
|
97
|
+
|
|
98
|
+
auth_routes.extend(
|
|
99
|
+
create_auth_routes(
|
|
100
|
+
provider=auth_server_provider,
|
|
101
|
+
issuer_url=auth_settings.issuer_url,
|
|
102
|
+
service_documentation_url=auth_settings.service_documentation_url,
|
|
103
|
+
client_registration_options=auth_settings.client_registration_options,
|
|
104
|
+
revocation_options=auth_settings.revocation_options,
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return middleware, auth_routes, required_scopes
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def create_base_app(
|
|
112
|
+
routes: list[Route | Mount],
|
|
113
|
+
middleware: list[Middleware],
|
|
114
|
+
debug: bool,
|
|
115
|
+
lifespan: Callable | None = None,
|
|
116
|
+
) -> Starlette:
|
|
117
|
+
"""Create a base Starlette app with common middleware and routes.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
routes: List of routes to include in the app
|
|
121
|
+
middleware: List of middleware to include in the app
|
|
122
|
+
debug: Whether to enable debug mode
|
|
123
|
+
lifespan: Optional lifespan manager for the app
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
A Starlette application
|
|
127
|
+
"""
|
|
128
|
+
# Always add RequestContextMiddleware as the outermost middleware
|
|
129
|
+
middleware.append(Middleware(RequestContextMiddleware))
|
|
130
|
+
|
|
131
|
+
# Create the app
|
|
132
|
+
app_kwargs = {
|
|
133
|
+
"debug": debug,
|
|
134
|
+
"routes": routes,
|
|
135
|
+
"middleware": middleware,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if lifespan:
|
|
139
|
+
app_kwargs["lifespan"] = lifespan
|
|
140
|
+
|
|
141
|
+
return Starlette(**app_kwargs)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def create_sse_app(
|
|
145
|
+
server: FastMCP,
|
|
146
|
+
message_path: str,
|
|
147
|
+
sse_path: str,
|
|
148
|
+
auth_server_provider: OAuthAuthorizationServerProvider | None = None,
|
|
149
|
+
auth_settings: AuthSettings | None = None,
|
|
150
|
+
debug: bool = False,
|
|
151
|
+
additional_routes: list[Route] | list[Mount] | list[Route | Mount] | None = None,
|
|
152
|
+
) -> Starlette:
|
|
153
|
+
"""Return an instance of the SSE server app.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
server: The FastMCP server instance
|
|
157
|
+
message_path: Path for SSE messages
|
|
158
|
+
sse_path: Path for SSE connections
|
|
159
|
+
auth_server_provider: Optional auth provider
|
|
160
|
+
auth_settings: Optional auth settings
|
|
161
|
+
debug: Whether to enable debug mode
|
|
162
|
+
additional_routes: Optional list of custom routes
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
A Starlette application with RequestContextMiddleware
|
|
166
|
+
"""
|
|
167
|
+
# Set up SSE transport
|
|
168
|
+
sse = SseServerTransport(message_path)
|
|
169
|
+
|
|
170
|
+
# Create handler for SSE connections
|
|
171
|
+
async def handle_sse(scope: Scope, receive: Receive, send: Send) -> Response:
|
|
172
|
+
async with sse.connect_sse(scope, receive, send) as streams:
|
|
173
|
+
await server._mcp_server.run(
|
|
174
|
+
streams[0],
|
|
175
|
+
streams[1],
|
|
176
|
+
server._mcp_server.create_initialization_options(),
|
|
177
|
+
)
|
|
178
|
+
return Response()
|
|
179
|
+
|
|
180
|
+
# Get auth middleware and routes
|
|
181
|
+
middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
|
|
182
|
+
auth_server_provider, auth_settings
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# Initialize routes with auth routes
|
|
186
|
+
routes: list[Route | Mount] = auth_routes.copy()
|
|
187
|
+
|
|
188
|
+
# Add SSE routes with or without auth
|
|
189
|
+
if auth_server_provider:
|
|
190
|
+
# Auth is enabled, wrap endpoints with RequireAuthMiddleware
|
|
191
|
+
routes.append(
|
|
192
|
+
Route(
|
|
193
|
+
sse_path,
|
|
194
|
+
endpoint=RequireAuthMiddleware(handle_sse, required_scopes),
|
|
195
|
+
methods=["GET"],
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
routes.append(
|
|
199
|
+
Mount(
|
|
200
|
+
message_path,
|
|
201
|
+
app=RequireAuthMiddleware(sse.handle_post_message, required_scopes),
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
# No auth required
|
|
206
|
+
async def sse_endpoint(request: Request) -> Response:
|
|
207
|
+
return await handle_sse(request.scope, request.receive, request._send) # type: ignore[reportPrivateUsage]
|
|
208
|
+
|
|
209
|
+
routes.append(
|
|
210
|
+
Route(
|
|
211
|
+
sse_path,
|
|
212
|
+
endpoint=sse_endpoint,
|
|
213
|
+
methods=["GET"],
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
routes.append(
|
|
217
|
+
Mount(
|
|
218
|
+
message_path,
|
|
219
|
+
app=sse.handle_post_message,
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Add custom routes with lowest precedence
|
|
224
|
+
if additional_routes:
|
|
225
|
+
routes.extend(cast(list[Route | Mount], additional_routes))
|
|
226
|
+
|
|
227
|
+
# Create and return the app
|
|
228
|
+
return create_base_app(routes, middleware, debug)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def create_streamable_http_app(
|
|
232
|
+
server: FastMCP,
|
|
233
|
+
streamable_http_path: str,
|
|
234
|
+
event_store: None = None,
|
|
235
|
+
auth_server_provider: OAuthAuthorizationServerProvider | None = None,
|
|
236
|
+
auth_settings: AuthSettings | None = None,
|
|
237
|
+
json_response: bool = False,
|
|
238
|
+
stateless_http: bool = False,
|
|
239
|
+
debug: bool = False,
|
|
240
|
+
additional_routes: list[Route] | list[Mount] | list[Route | Mount] | None = None,
|
|
241
|
+
) -> Starlette:
|
|
242
|
+
"""Return an instance of the StreamableHTTP server app.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
server: The FastMCP server instance
|
|
246
|
+
streamable_http_path: Path for StreamableHTTP connections
|
|
247
|
+
event_store: Optional event store for session management
|
|
248
|
+
auth_server_provider: Optional auth provider
|
|
249
|
+
auth_settings: Optional auth settings
|
|
250
|
+
json_response: Whether to use JSON response format
|
|
251
|
+
stateless_http: Whether to use stateless mode (new transport per request)
|
|
252
|
+
debug: Whether to enable debug mode
|
|
253
|
+
additional_routes: Optional list of custom routes
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
A Starlette application with StreamableHTTP support
|
|
257
|
+
"""
|
|
258
|
+
# Create session manager using the provided event store
|
|
259
|
+
session_manager = StreamableHTTPSessionManager(
|
|
260
|
+
app=server._mcp_server,
|
|
261
|
+
event_store=event_store,
|
|
262
|
+
json_response=json_response,
|
|
263
|
+
stateless=stateless_http,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Create the ASGI handler
|
|
267
|
+
async def handle_streamable_http(
|
|
268
|
+
scope: Scope, receive: Receive, send: Send
|
|
269
|
+
) -> None:
|
|
270
|
+
await session_manager.handle_request(scope, receive, send)
|
|
271
|
+
|
|
272
|
+
# Get auth middleware and routes
|
|
273
|
+
middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
|
|
274
|
+
auth_server_provider, auth_settings
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Initialize routes with auth routes
|
|
278
|
+
routes: list[Route | Mount] = auth_routes.copy()
|
|
279
|
+
|
|
280
|
+
# Add StreamableHTTP routes with or without auth
|
|
281
|
+
if auth_server_provider:
|
|
282
|
+
# Auth is enabled, wrap endpoint with RequireAuthMiddleware
|
|
283
|
+
routes.append(
|
|
284
|
+
Mount(
|
|
285
|
+
streamable_http_path,
|
|
286
|
+
app=RequireAuthMiddleware(handle_streamable_http, required_scopes),
|
|
287
|
+
)
|
|
288
|
+
)
|
|
289
|
+
else:
|
|
290
|
+
# No auth required
|
|
291
|
+
routes.append(
|
|
292
|
+
Mount(
|
|
293
|
+
streamable_http_path,
|
|
294
|
+
app=handle_streamable_http,
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Add custom routes with lowest precedence
|
|
299
|
+
if additional_routes:
|
|
300
|
+
routes.extend(cast(list[Route | Mount], additional_routes))
|
|
301
|
+
|
|
302
|
+
# Create a lifespan manager to start and stop the session manager
|
|
303
|
+
@asynccontextmanager
|
|
304
|
+
async def lifespan(app: Starlette) -> AsyncGenerator[None, None]:
|
|
305
|
+
async with session_manager.run():
|
|
306
|
+
yield
|
|
307
|
+
|
|
308
|
+
# Create and return the app with lifespan
|
|
309
|
+
return create_base_app(routes, middleware, debug, lifespan)
|
fastmcp/server/openapi.py
CHANGED
|
@@ -25,9 +25,6 @@ from fastmcp.utilities.openapi import (
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
28
|
-
from mcp.server.session import ServerSessionT
|
|
29
|
-
from mcp.shared.context import LifespanContextT
|
|
30
|
-
|
|
31
28
|
from fastmcp.server import Context
|
|
32
29
|
|
|
33
30
|
logger = get_logger(__name__)
|
|
@@ -132,7 +129,6 @@ class OpenAPITool(Tool):
|
|
|
132
129
|
description=description,
|
|
133
130
|
parameters=parameters,
|
|
134
131
|
fn=self._execute_request, # We'll use an instance method instead of a global function
|
|
135
|
-
context_kwarg="context", # Default context keyword argument
|
|
136
132
|
tags=tags,
|
|
137
133
|
annotations=annotations,
|
|
138
134
|
serializer=serializer,
|
|
@@ -258,12 +254,10 @@ class OpenAPITool(Tool):
|
|
|
258
254
|
raise ValueError(f"Request error: {str(e)}")
|
|
259
255
|
|
|
260
256
|
async def run(
|
|
261
|
-
self,
|
|
262
|
-
arguments: dict[str, Any],
|
|
263
|
-
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
|
257
|
+
self, arguments: dict[str, Any]
|
|
264
258
|
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
265
259
|
"""Run the tool with arguments and optional context."""
|
|
266
|
-
response = await self._execute_request(**arguments
|
|
260
|
+
response = await self._execute_request(**arguments)
|
|
267
261
|
return _convert_to_content(response)
|
|
268
262
|
|
|
269
263
|
|
|
@@ -292,9 +286,7 @@ class OpenAPIResource(Resource):
|
|
|
292
286
|
self._route = route
|
|
293
287
|
self._timeout = timeout
|
|
294
288
|
|
|
295
|
-
async def read(
|
|
296
|
-
self, context: Context[ServerSessionT, LifespanContextT] | None = None
|
|
297
|
-
) -> str | bytes:
|
|
289
|
+
async def read(self) -> str | bytes:
|
|
298
290
|
"""Fetch the resource data by making an HTTP request."""
|
|
299
291
|
try:
|
|
300
292
|
# Extract path parameters from the URI if present
|
|
@@ -399,7 +391,6 @@ class OpenAPIResourceTemplate(ResourceTemplate):
|
|
|
399
391
|
fn=lambda **kwargs: None,
|
|
400
392
|
parameters=parameters,
|
|
401
393
|
tags=tags,
|
|
402
|
-
context_kwarg=None,
|
|
403
394
|
)
|
|
404
395
|
self._client = client
|
|
405
396
|
self._route = route
|
|
@@ -409,7 +400,7 @@ class OpenAPIResourceTemplate(ResourceTemplate):
|
|
|
409
400
|
self,
|
|
410
401
|
uri: str,
|
|
411
402
|
params: dict[str, Any],
|
|
412
|
-
context: Context
|
|
403
|
+
context: Context | None = None,
|
|
413
404
|
) -> Resource:
|
|
414
405
|
"""Create a resource with the given parameters."""
|
|
415
406
|
# Generate a URI for this resource instance
|
|
@@ -650,7 +641,5 @@ class FastMCPOpenAPI(FastMCP):
|
|
|
650
641
|
|
|
651
642
|
async def _mcp_call_tool(self, name: str, arguments: dict[str, Any]) -> Any:
|
|
652
643
|
"""Override the call_tool method to return the raw result without converting to content."""
|
|
653
|
-
|
|
654
|
-
context = self.get_context()
|
|
655
|
-
result = await self._tool_manager.call_tool(name, arguments, context=context)
|
|
644
|
+
result = await self._tool_manager.call_tool(name, arguments)
|
|
656
645
|
return result
|
fastmcp/server/proxy.py
CHANGED
|
@@ -27,9 +27,6 @@ from fastmcp.tools.tool import Tool
|
|
|
27
27
|
from fastmcp.utilities.logging import get_logger
|
|
28
28
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
30
|
-
from mcp.server.session import ServerSessionT
|
|
31
|
-
from mcp.shared.context import LifespanContextT
|
|
32
|
-
|
|
33
30
|
from fastmcp.server import Context
|
|
34
31
|
|
|
35
32
|
logger = get_logger(__name__)
|
|
@@ -57,7 +54,7 @@ class ProxyTool(Tool):
|
|
|
57
54
|
async def run(
|
|
58
55
|
self,
|
|
59
56
|
arguments: dict[str, Any],
|
|
60
|
-
context: Context
|
|
57
|
+
context: Context | None = None,
|
|
61
58
|
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
62
59
|
# the client context manager will swallow any exceptions inside a TaskGroup
|
|
63
60
|
# so we return the raw result and raise an exception ourselves
|
|
@@ -89,9 +86,7 @@ class ProxyResource(Resource):
|
|
|
89
86
|
mime_type=resource.mimeType,
|
|
90
87
|
)
|
|
91
88
|
|
|
92
|
-
async def read(
|
|
93
|
-
self, context: Context[ServerSessionT, LifespanContextT] | None = None
|
|
94
|
-
) -> str | bytes:
|
|
89
|
+
async def read(self) -> str | bytes:
|
|
95
90
|
if self._value is not None:
|
|
96
91
|
return self._value
|
|
97
92
|
|
|
@@ -127,7 +122,7 @@ class ProxyTemplate(ResourceTemplate):
|
|
|
127
122
|
self,
|
|
128
123
|
uri: str,
|
|
129
124
|
params: dict[str, Any],
|
|
130
|
-
context: Context
|
|
125
|
+
context: Context | None = None,
|
|
131
126
|
) -> ProxyResource:
|
|
132
127
|
# dont use the provided uri, because it may not be the same as the
|
|
133
128
|
# uri_template on the remote server.
|
|
@@ -171,11 +166,7 @@ class ProxyPrompt(Prompt):
|
|
|
171
166
|
fn=_proxy_passthrough,
|
|
172
167
|
)
|
|
173
168
|
|
|
174
|
-
async def render(
|
|
175
|
-
self,
|
|
176
|
-
arguments: dict[str, Any],
|
|
177
|
-
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
|
178
|
-
) -> list[PromptMessage]:
|
|
169
|
+
async def render(self, arguments: dict[str, Any]) -> list[PromptMessage]:
|
|
179
170
|
async with self._client:
|
|
180
171
|
result = await self._client.get_prompt(self.name, arguments)
|
|
181
172
|
return result.messages
|