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
- return str(response.json())
 
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=self._create_resource_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
- or f"Resource for {self._route.path}", # Provide default if None
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"