Spaces:
Running
Running
Jeremiah Lowin commited on
Commit ·
e1fcc29
1
Parent(s): d2069f2
Fix issues with simple str response
Browse files
src/fastmcp/server/openapi.py
CHANGED
|
@@ -301,7 +301,8 @@ class OpenAPIResource(Resource):
|
|
| 301 |
content_type = response.headers.get("content-type", "").lower()
|
| 302 |
|
| 303 |
if "application/json" in content_type:
|
| 304 |
-
|
|
|
|
| 305 |
elif any(ct in content_type for ct in ["text/", "application/xml"]):
|
| 306 |
return response.text
|
| 307 |
else:
|
|
@@ -343,56 +344,13 @@ class OpenAPIResourceTemplate(ResourceTemplate):
|
|
| 343 |
uri_template=uri_template,
|
| 344 |
name=name,
|
| 345 |
description=description,
|
| 346 |
-
fn=
|
| 347 |
parameters=parameters,
|
| 348 |
tags=tags,
|
| 349 |
)
|
| 350 |
self._client = client
|
| 351 |
self._route = route
|
| 352 |
|
| 353 |
-
async def _create_resource_fn(self, **kwargs):
|
| 354 |
-
"""Create a resource with parameters."""
|
| 355 |
-
# Prepare the path with parameters
|
| 356 |
-
path = self._route.path
|
| 357 |
-
for param_name, param_value in kwargs.items():
|
| 358 |
-
path = path.replace(f"{{{param_name}}}", str(param_value))
|
| 359 |
-
|
| 360 |
-
try:
|
| 361 |
-
response = await self._client.request(
|
| 362 |
-
method=self._route.method,
|
| 363 |
-
url=path,
|
| 364 |
-
timeout=30.0, # Default timeout
|
| 365 |
-
)
|
| 366 |
-
|
| 367 |
-
# Raise for 4xx/5xx responses
|
| 368 |
-
response.raise_for_status()
|
| 369 |
-
|
| 370 |
-
# Determine content type and return appropriate format
|
| 371 |
-
content_type = response.headers.get("content-type", "").lower()
|
| 372 |
-
|
| 373 |
-
if "application/json" in content_type:
|
| 374 |
-
return str(response.json())
|
| 375 |
-
elif any(ct in content_type for ct in ["text/", "application/xml"]):
|
| 376 |
-
return response.text
|
| 377 |
-
else:
|
| 378 |
-
return response.content
|
| 379 |
-
|
| 380 |
-
except httpx.HTTPStatusError as e:
|
| 381 |
-
error_message = (
|
| 382 |
-
f"HTTP error {e.response.status_code}: {e.response.reason_phrase}"
|
| 383 |
-
)
|
| 384 |
-
try:
|
| 385 |
-
error_data = e.response.json()
|
| 386 |
-
error_message += f" - {error_data}"
|
| 387 |
-
except (json.JSONDecodeError, ValueError):
|
| 388 |
-
if e.response.text:
|
| 389 |
-
error_message += f" - {e.response.text}"
|
| 390 |
-
|
| 391 |
-
raise ValueError(error_message)
|
| 392 |
-
|
| 393 |
-
except httpx.RequestError as e:
|
| 394 |
-
raise ValueError(f"Request error: {str(e)}")
|
| 395 |
-
|
| 396 |
async def create_resource(self, uri: str, params: dict[str, Any]) -> Resource:
|
| 397 |
"""Create a resource with the given parameters."""
|
| 398 |
# Generate a URI for this resource instance
|
|
@@ -406,9 +364,8 @@ class OpenAPIResourceTemplate(ResourceTemplate):
|
|
| 406 |
route=self._route,
|
| 407 |
uri=uri,
|
| 408 |
name=f"{self.name}-{'-'.join(uri_parts)}",
|
| 409 |
-
description=self.description
|
| 410 |
-
|
| 411 |
-
mime_type="application/json", # Default, will be updated when read
|
| 412 |
tags=set(self._route.tags or []),
|
| 413 |
)
|
| 414 |
|
|
|
|
| 301 |
content_type = response.headers.get("content-type", "").lower()
|
| 302 |
|
| 303 |
if "application/json" in content_type:
|
| 304 |
+
result = response.json()
|
| 305 |
+
return json.dumps(result)
|
| 306 |
elif any(ct in content_type for ct in ["text/", "application/xml"]):
|
| 307 |
return response.text
|
| 308 |
else:
|
|
|
|
| 344 |
uri_template=uri_template,
|
| 345 |
name=name,
|
| 346 |
description=description,
|
| 347 |
+
fn=lambda **kwargs: None,
|
| 348 |
parameters=parameters,
|
| 349 |
tags=tags,
|
| 350 |
)
|
| 351 |
self._client = client
|
| 352 |
self._route = route
|
| 353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 354 |
async def create_resource(self, uri: str, params: dict[str, Any]) -> Resource:
|
| 355 |
"""Create a resource with the given parameters."""
|
| 356 |
# Generate a URI for this resource instance
|
|
|
|
| 364 |
route=self._route,
|
| 365 |
uri=uri,
|
| 366 |
name=f"{self.name}-{'-'.join(uri_parts)}",
|
| 367 |
+
description=self.description or f"Resource for {self._route.path}",
|
| 368 |
+
mime_type="application/json",
|
|
|
|
| 369 |
tags=set(self._route.tags or []),
|
| 370 |
)
|
| 371 |
|
tests/server/test_openapi.py
CHANGED
|
@@ -6,6 +6,7 @@ import httpx
|
|
| 6 |
import pytest
|
| 7 |
from dirty_equals import IsStr
|
| 8 |
from fastapi import FastAPI, HTTPException, Response
|
|
|
|
| 9 |
from httpx import ASGITransport, AsyncClient
|
| 10 |
from mcp.types import BlobResourceContents, TextContent, TextResourceContents
|
| 11 |
from pydantic import BaseModel, TypeAdapter
|
|
@@ -67,7 +68,7 @@ def fastapi_app(users_db: dict[int, User]) -> FastAPI:
|
|
| 67 |
user.name = name
|
| 68 |
return user
|
| 69 |
|
| 70 |
-
@app.get("/ping")
|
| 71 |
async def ping() -> str:
|
| 72 |
"""Ping the server."""
|
| 73 |
return "pong"
|
|
|
|
| 6 |
import pytest
|
| 7 |
from dirty_equals import IsStr
|
| 8 |
from fastapi import FastAPI, HTTPException, Response
|
| 9 |
+
from fastapi.responses import PlainTextResponse
|
| 10 |
from httpx import ASGITransport, AsyncClient
|
| 11 |
from mcp.types import BlobResourceContents, TextContent, TextResourceContents
|
| 12 |
from pydantic import BaseModel, TypeAdapter
|
|
|
|
| 68 |
user.name = name
|
| 69 |
return user
|
| 70 |
|
| 71 |
+
@app.get("/ping", response_class=PlainTextResponse)
|
| 72 |
async def ping() -> str:
|
| 73 |
"""Ping the server."""
|
| 74 |
return "pong"
|