mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Migrate to MCP SDK v2.0.0b2 (httpx2) (#4503)
This commit is contained in:
parent
66c0270bc1
commit
18b5ab5852
112 changed files with 1710 additions and 678 deletions
|
|
@ -57,7 +57,7 @@ async with Client(transport) as client:
|
|||
|
||||
## `BearerAuth` Helper
|
||||
|
||||
If you prefer to be more explicit and not rely on FastMCP to transform your string token, you can use the `BearerAuth` class yourself, which implements the `httpx.Auth` interface.
|
||||
If you prefer to be more explicit and not rely on FastMCP to transform your string token, you can use the `BearerAuth` class yourself, which implements the `httpx2.Auth` interface.
|
||||
|
||||
```python {6}
|
||||
from fastmcp import Client
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ async with Client("https://your-server.fastmcp.app/mcp", auth="oauth") as client
|
|||
|
||||
### `OAuth` Helper
|
||||
|
||||
To fully configure the OAuth flow, use the `OAuth` helper and pass it to the `auth` parameter of the `Client` or transport instance. `OAuth` manages the complexities of the OAuth 2.1 Authorization Code Grant with PKCE (Proof Key for Code Exchange) for enhanced security, and implements the full `httpx.Auth` interface.
|
||||
To fully configure the OAuth flow, use the `OAuth` helper and pass it to the `auth` parameter of the `Client` or transport instance. `OAuth` manages the complexities of the OAuth 2.1 Authorization Code Grant with PKCE (Proof Key for Code Exchange) for enhanced security, and implements the full `httpx2.Auth` interface.
|
||||
|
||||
```python {2, 4, 6}
|
||||
from fastmcp import Client
|
||||
|
|
@ -61,7 +61,7 @@ You don't need to pass `mcp_url` when using `OAuth` with `Client(auth=...)` —
|
|||
- **`token_storage`** (`AsyncKeyValue`, optional): Storage backend for persisting OAuth tokens. Defaults to in-memory storage (tokens lost on restart). See [Token Storage](#token-storage) for encrypted storage options
|
||||
- **`additional_client_metadata`** (`dict[str, Any]`, optional): Extra metadata for client registration
|
||||
- **`callback_port`** (`int`, optional): Fixed port for OAuth callback server. If not specified, uses a random available port
|
||||
- **`httpx_client_factory`** (`McpHttpClientFactory`, optional): Factory for creating httpx clients
|
||||
- **`httpx_client_factory`** (`McpHttpClientFactory`, optional): Factory for creating httpx2 clients
|
||||
|
||||
|
||||
## OAuth Flow
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ client = Client(
|
|||
|
||||
### SSL Verification
|
||||
|
||||
By default, HTTPS connections verify the server's SSL certificate. You can customize this behavior with the `verify` parameter, which accepts the same values as [httpx](https://www.python-httpx.org/advanced/ssl/):
|
||||
By default, HTTPS connections verify the server's SSL certificate. You can customize this behavior with the `verify` parameter, which accepts the same values as httpx2 (documented in [httpx's SSL guide](https://www.python-httpx.org/advanced/ssl/), which httpx2 follows):
|
||||
|
||||
```python
|
||||
from fastmcp import Client
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ client = Client("my_mcp_server.py", timeout=30.0) # also works
|
|||
|
||||
### `get_session_id` via header sniff — Bridged
|
||||
|
||||
The SDK dropped `get_session_id` from the streamable-HTTP transport with no replacement (the SDK source has an author TODO acknowledging it breaks the Transport protocol). FastMCP reconstructs it by registering an httpx response event hook on the client it owns, capturing the `mcp-session-id` response header. The removal trigger is the upstream TODO.
|
||||
The SDK dropped `get_session_id` from the streamable-HTTP transport with no replacement (the SDK source has an author TODO acknowledging it breaks the Transport protocol). FastMCP reconstructs it by registering an httpx2 response event hook on the client it owns, capturing the `mcp-session-id` response header (httpx2 preserves httpx's `event_hooks` API). The removal trigger is the upstream TODO.
|
||||
|
||||
*Verify:* `fastmcp_slim/fastmcp/client/transports/http.py` (`_capture_session_id`, `get_session_id`).
|
||||
|
||||
|
|
@ -261,6 +261,23 @@ FastMCP owns DNS-rebinding protection through its `HostOriginGuardMiddleware`, w
|
|||
|
||||
*Verify:* `fastmcp_slim/fastmcp/server/http.py` (`enable_dns_rebinding_protection=False`, `HostOriginGuardMiddleware`).
|
||||
|
||||
### httpx2 replaces httpx — Breaking (custom client/factory, typing) / Absorbed (everything else)
|
||||
|
||||
SDK v2.0.0b2 replaces `httpx` + `httpx-sse` with [httpx2](https://pypi.org/project/httpx2/) (`>=2.5.0`), a next-generation httpx fork with built-in SSE. httpx2 is a near drop-in fork: the public API (`AsyncClient`, `Auth`, `Request`, `Response`, `Timeout`, `MockTransport`, exception hierarchy, `event_hooks`) matches httpx name-for-name. The SDK duck-types the client you hand it — `streamable_http_client(http_client=...)` and `sse_client(httpx_client_factory=...)` are type-hinted `httpx2.AsyncClient` with no `isinstance` gate — but the objects that cross into the SDK must be httpx2.
|
||||
|
||||
FastMCP now uses **httpx2 exclusively** and no longer depends on `httpx`. Every FastMCP-owned HTTP path moves to httpx2: the client transports (`client/transports/{base,http,sse}.py`), client auth (`client/auth/{oauth,bearer}.py` — `BearerAuth`/`OAuth` subclass `httpx2.Auth`), the client-side exception-group handler (`utilities/exceptions.py`), the proxy's upstream client (`server/providers/proxy.py`), the `MCPConfig` client-auth field (`mcp_config.py`), **and** all the server-side code that the earlier seam pass had left on httpx — the ~15 server auth providers' upstream IdP calls, the OpenAPI provider, `from_openapi`/`from_fastapi`, `version_check`, `resources/types.py`, the SSRF download guard, and the `apps_dev` CLI. `httpx` is dropped from the `mcp` extra entirely (it may still arrive transitively via other libraries, but FastMCP never imports it). The ~170 `httpx_mock` calls across the security-critical server-auth test files are ported to a local httpx2-backed `httpx_mock` fixture (`tests/utilities/httpx2_mock.py`) that preserves the `add_response`/`add_exception`/`get_request(s)` API verbatim, so `pytest-httpx` is dropped too.
|
||||
|
||||
User-visible deltas:
|
||||
|
||||
- **Custom client factory / client.** `StreamableHttpTransport(httpx_client_factory=...)`, `SSETransport(httpx_client_factory=...)`, and `OAuth(httpx_client_factory=...)` factories must now return `httpx2.AsyncClient`; a custom `httpx.Auth` passed as `Client(auth=...)` should become `httpx2.Auth`. httpx2 is a drop-in fork, so the change is an import swap (`import httpx` → `import httpx2`). This is a typing break; at runtime a duck-compatible httpx client still satisfies the SDK, but mixing `httpx.Timeout`/`httpx.Auth` with an httpx2 client is unsupported.
|
||||
- **OpenAPI client.** `FastMCP.from_openapi(client=...)` and `OpenAPIProvider(client=...)` are now type-hinted `httpx2.AsyncClient`. There is no `isinstance` gate, so an existing `httpx.AsyncClient` still works at runtime via duck-typing this release; the typing nudges you to httpx2.
|
||||
- **TLS trust store.** httpx2 verifies TLS against the OS trust store via `truststore` (honoring `SSL_CERT_FILE`/`SSL_CERT_DIR` first) instead of the bundled certifi CA set. This now applies to **all** FastMCP HTTP, including server-auth upstream IdP calls — not just the client path. Corporate-CA and certifi-pinned setups may see different trust behavior.
|
||||
- **Logger renames.** FastMCP HTTP now logs under `httpx2` and `httpcore2.*` (was `httpx`/`httpcore.*`). Anyone filtering FastMCP HTTP logs by logger name must update the names.
|
||||
|
||||
The session-id header hook (below) works unchanged: httpx2 keeps httpx's `event_hooks` API. FastMCP's tool/resource/prompt handlers still map upstream 429/timeout errors to actionable `ToolError`/`ResourceError`; because a user's own tool may raise from either library, `server/server.py` catches both `httpx2` and (if installed) legacy `httpx` `HTTPStatusError`/`TimeoutException` via a defensive `try: import httpx` shim.
|
||||
|
||||
*Verify:* `fastmcp_slim/pyproject.toml` (`mcp` extra lists only `httpx2`); no FastMCP source imports `httpx` except the documented defensive shim in `server/server.py`.
|
||||
|
||||
## Protocol eras
|
||||
|
||||
The SDK v2 serves multiple protocol eras from one server, and FastMCP formally embraces this.
|
||||
|
|
@ -343,7 +360,7 @@ Deprecations that warned in 3.x are removed in 4.0. Each entry below is a hard r
|
|||
- **`fastmcp.experimental.server.openapi`** and **`fastmcp.experimental.utilities.openapi`** shims (deprecated 2.14) — Breaking. Import from `fastmcp.server.providers.openapi` and `fastmcp.utilities.openapi` respectively.
|
||||
- **`fastmcp.server.apps`** and **`fastmcp.server.app`** shims (deprecated 3.2) — Breaking. Import from `fastmcp.apps` (e.g. `AppConfig`) or `fastmcp` (`FastMCPApp`) instead.
|
||||
- **`PromptToolMiddleware`** and **`ResourceToolMiddleware`** (deprecated 3.1) — Breaking. Use the `PromptsAsTools` / `ResourcesAsTools` transforms from `fastmcp.server.transforms` instead. The non-deprecated `ToolInjectionMiddleware` base class is retained.
|
||||
- **`StreamableHttpTransport(sse_read_timeout=...)`** (deprecated no-op) — Breaking. The parameter had no effect under the SDK v2 client; configure timeouts via `read_timeout_seconds` in `session_kwargs` or on the httpx client via `httpx_client_factory`. `SSETransport` still accepts `sse_read_timeout`.
|
||||
- **`StreamableHttpTransport(sse_read_timeout=...)`** (deprecated no-op) — Breaking. The parameter had no effect under the SDK v2 client; configure timeouts via `read_timeout_seconds` in `session_kwargs` or on the httpx2 client via `httpx_client_factory`. `SSETransport` still accepts `sse_read_timeout`.
|
||||
|
||||
### `FastMCP` server methods and `mount()` kwargs
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ BREAKING CHANGES (will crash at import or runtime):
|
|||
|
||||
6. WSTRANSPORT: Removed. Use StreamableHttpTransport.
|
||||
|
||||
7. OPENAPI: timeout parameter removed from OpenAPIProvider. Set timeout on the httpx.AsyncClient instead.
|
||||
7. OPENAPI: timeout parameter removed from OpenAPIProvider. Set timeout on the httpx2.AsyncClient instead.
|
||||
|
||||
8. METADATA: Namespace changed from "_fastmcp" to "fastmcp" in tool.meta. The include_fastmcp_meta parameter is removed (always included).
|
||||
|
||||
|
|
@ -276,14 +276,14 @@ transport = StreamableHttpTransport("http://localhost:8000/mcp")
|
|||
|
||||
**OpenAPI `timeout` parameter removed**
|
||||
|
||||
`OpenAPIProvider` no longer accepts a `timeout` parameter. Configure timeout on the httpx client directly. The `client` parameter is also now optional — when omitted, a default client is created from the spec's `servers` URL with a 30-second timeout:
|
||||
`OpenAPIProvider` no longer accepts a `timeout` parameter. Configure timeout on the httpx2 client directly. The `client` parameter is also now optional — when omitted, a default client is created from the spec's `servers` URL with a 30-second timeout:
|
||||
|
||||
```python
|
||||
# Before
|
||||
provider = OpenAPIProvider(spec, client, timeout=60)
|
||||
|
||||
# After
|
||||
client = httpx.AsyncClient(base_url="https://api.example.com", timeout=60)
|
||||
client = httpx2.AsyncClient(base_url="https://api.example.com", timeout=60)
|
||||
provider = OpenAPIProvider(spec, client)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,43 @@ Catching and `err.error.code` are unchanged — only construction moved.
|
|||
|
||||
**Raw session access sees v2 objects.** If you reach past FastMCP's client and server surfaces into `client.session`, `ctx.session`, or the internals of `ctx.request_context`, you're now holding raw SDK v2 objects with snake_case fields and the v2 method signatures. FastMCP does not wrap these; code that depends on their v1 shape needs updating.
|
||||
|
||||
**FastMCP now uses httpx2 exclusively.** FastMCP has replaced `httpx` with [httpx2](https://pypi.org/project/httpx2/), a next-generation httpx fork, across its entire HTTP stack — client transports and every server-side path (auth providers, the OpenAPI integration, the version check). `httpx` is no longer a FastMCP dependency. If you pass a custom client or factory into a FastMCP client transport — `StreamableHttpTransport(httpx_client_factory=...)`, `SSETransport(httpx_client_factory=...)`, `OAuth(httpx_client_factory=...)`, or a custom `httpx.Auth` as `Client(auth=...)` — those objects must now be httpx2. httpx2 is a drop-in fork with the same public API, so the change is an import swap:
|
||||
|
||||
```python
|
||||
# Before
|
||||
import httpx
|
||||
|
||||
transport = StreamableHttpTransport(
|
||||
"https://example.com/mcp",
|
||||
httpx_client_factory=lambda **kwargs: httpx.AsyncClient(verify=False, **kwargs),
|
||||
)
|
||||
|
||||
# After
|
||||
import httpx2
|
||||
|
||||
transport = StreamableHttpTransport(
|
||||
"https://example.com/mcp",
|
||||
httpx_client_factory=lambda **kwargs: httpx2.AsyncClient(verify=False, **kwargs),
|
||||
)
|
||||
```
|
||||
|
||||
The `client` you pass to `FastMCP.from_openapi(client=...)` (and `OpenAPIProvider(client=...)`) is now type-hinted `httpx2.AsyncClient`. FastMCP does not gate on the type, so an existing `httpx.AsyncClient` keeps working at runtime via duck-typing this release — but switching it to `httpx2.AsyncClient` clears the type hint and is the supported path going forward. HTTP made inside your own tools is entirely yours and is unaffected either way.
|
||||
|
||||
**The subtlest break is exception handlers, and no type checker will catch it.** `httpx` very likely remains installed in your environment (the Anthropic, OpenAI, and Google SDKs all depend on it), so code that catches old-httpx exceptions around FastMCP calls still imports and still type-checks — it just never matches, because FastMCP now raises `httpx2` exceptions. The handler silently becomes dead code:
|
||||
|
||||
```python
|
||||
import httpx # still installed transitively — this import works
|
||||
|
||||
try:
|
||||
result = await client.call_tool("fetch", {"url": url})
|
||||
except httpx.ConnectError: # dead code: FastMCP now raises httpx2.ConnectError
|
||||
return fallback()
|
||||
```
|
||||
|
||||
Grep your codebase for `except httpx.` and move those handlers to `httpx2`. The exception hierarchies match name-for-name, so the fix is an import swap — the hard part is remembering to look. One place you are covered automatically: exceptions raised *inside your tools and resources* (for example, a tool whose own old-httpx call gets a 429) are still mapped to `ToolError`/`ResourceError` by FastMCP's error boundary, which recognizes both libraries' exceptions during the transition.
|
||||
|
||||
Two runtime behaviors shift with httpx2, and because the switch is now wholesale they apply to **all** FastMCP HTTP — including server-auth upstream calls, not just the client path. TLS verification uses the operating system's trust store (via `truststore`, honoring `SSL_CERT_FILE`/`SSL_CERT_DIR`) instead of the bundled certifi CA set, so corporate-CA or certifi-pinned setups may verify differently. And the FastMCP HTTP loggers are renamed from `httpx`/`httpcore.*` to `httpx2`/`httpcore2.*` — update any logging filters that select the HTTP stack by logger name.
|
||||
|
||||
## Deprecation timeline
|
||||
|
||||
The camelCase bridge is a migration aid, not a permanent fixture. It works today and warns on every bridged read so you can find and update the affected call sites. Plan to migrate your reads to snake_case: the shims will be removed in a future release, after which only the snake_case names resolve — the same state you get today by setting `mcp_camelcase_compat = False`. Turning the setting off is a good way to surface every remaining camelCase read in your code as a hard `AttributeError` before the shims go away.
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ The `EntraOBOToken` dependency handles the complete OBO flow automatically. Decl
|
|||
```python
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.auth.providers.azure import AzureProvider, EntraOBOToken
|
||||
import httpx
|
||||
import httpx2
|
||||
|
||||
auth_provider = AzureProvider(
|
||||
client_id="your-client-id",
|
||||
|
|
@ -431,7 +431,7 @@ async def get_recent_emails(
|
|||
graph_token: str = EntraOBOToken(["https://graph.microsoft.com/Mail.Read"]),
|
||||
) -> list[dict]:
|
||||
"""Get the user's recent emails from Microsoft Graph."""
|
||||
async with httpx.AsyncClient() as client:
|
||||
async with httpx2.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
f"https://graph.microsoft.com/v1.0/me/messages?$top={count}",
|
||||
headers={"Authorization": f"Bearer {graph_token}"},
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@ We recommend using the FastAPI integration for bootstrapping and prototyping, no
|
|||
To convert an OpenAPI specification to an MCP server, use the `FastMCP.from_openapi()` class method:
|
||||
|
||||
```python server.py
|
||||
import httpx
|
||||
import httpx2
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Create an HTTP client for your API
|
||||
client = httpx.AsyncClient(base_url="https://api.example.com")
|
||||
client = httpx2.AsyncClient(base_url="https://api.example.com")
|
||||
|
||||
# Load your OpenAPI spec
|
||||
openapi_spec = httpx.get("https://api.example.com/openapi.json").json()
|
||||
openapi_spec = httpx2.get("https://api.example.com/openapi.json").json()
|
||||
|
||||
# Create the MCP server
|
||||
mcp = FastMCP.from_openapi(
|
||||
|
|
@ -51,11 +51,11 @@ if __name__ == "__main__":
|
|||
If your API requires authentication, configure it on the HTTP client:
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import httpx2
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Bearer token authentication
|
||||
api_client = httpx.AsyncClient(
|
||||
api_client = httpx2.AsyncClient(
|
||||
base_url="https://api.example.com",
|
||||
headers={"Authorization": "Bearer YOUR_TOKEN"}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ When not set, `scopes_supported` defaults to the token verifier's `required_scop
|
|||
You can extend `RemoteAuthProvider` to add additional endpoints beyond the standard OAuth protected resource metadata. These don't have to be OAuth-specific - you can add any endpoints your authentication integration requires.
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import httpx2
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import Route
|
||||
|
||||
|
|
@ -173,7 +173,7 @@ class CompanyAuthProvider(RemoteAuthProvider):
|
|||
|
||||
# Add authorization server metadata forwarding for client convenience
|
||||
async def authorization_server_metadata(request):
|
||||
async with httpx.AsyncClient() as client:
|
||||
async with httpx2.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
"https://auth.yourcompany.com/.well-known/oauth-authorization-server"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -327,21 +327,21 @@ This pattern enables comprehensive testing of JWT validation logic without depen
|
|||
|
||||
<VersionBadge version="2.18.0" />
|
||||
|
||||
All token verifiers that make HTTP calls accept an optional `http_client` parameter. This lets you provide your own `httpx.AsyncClient` for connection pooling, custom TLS configuration, or proxy settings.
|
||||
All token verifiers that make HTTP calls accept an optional `http_client` parameter. This lets you provide your own `httpx2.AsyncClient` for connection pooling, custom TLS configuration, or proxy settings.
|
||||
|
||||
### Connection Pooling
|
||||
|
||||
By default, each token verification call creates a fresh HTTP client. Under high load, this means repeated TCP connections and TLS handshakes. Providing a shared client enables connection pooling across calls:
|
||||
|
||||
```python
|
||||
import httpx
|
||||
import httpx2
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.auth.providers.introspection import IntrospectionTokenVerifier
|
||||
|
||||
# Create a shared client with connection pooling
|
||||
http_client = httpx.AsyncClient(
|
||||
http_client = httpx2.AsyncClient(
|
||||
timeout=10,
|
||||
limits=httpx.Limits(max_connections=20, max_keepalive_connections=10),
|
||||
limits=httpx2.Limits(max_connections=20, max_keepalive_connections=10),
|
||||
)
|
||||
|
||||
verifier = IntrospectionTokenVerifier(
|
||||
|
|
@ -378,7 +378,7 @@ from contextlib import asynccontextmanager
|
|||
from fastmcp import FastMCP
|
||||
from fastmcp.server.auth.providers.introspection import IntrospectionTokenVerifier
|
||||
|
||||
http_client = httpx.AsyncClient(timeout=10)
|
||||
http_client = httpx2.AsyncClient(timeout=10)
|
||||
|
||||
verifier = IntrospectionTokenVerifier(
|
||||
introspection_url="https://auth.example.com/introspect",
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ from contextlib import asynccontextmanager
|
|||
from collections.abc import AsyncIterator, Sequence
|
||||
from fastmcp.server.providers import Provider
|
||||
from fastmcp.resources import Resource
|
||||
import httpx
|
||||
import httpx2
|
||||
|
||||
class ApiResourceProvider(Provider):
|
||||
"""Provides resources backed by an external API."""
|
||||
|
|
@ -199,7 +199,7 @@ class ApiResourceProvider(Provider):
|
|||
|
||||
@asynccontextmanager
|
||||
async def lifespan(self) -> AsyncIterator[None]:
|
||||
self.client = httpx.AsyncClient(
|
||||
self.client = httpx2.AsyncClient(
|
||||
base_url=self.base_url,
|
||||
headers={"Authorization": f"Bearer {self.api_key}"}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ if data_dir_path.is_dir():
|
|||
- `TextResource`: For simple string content.
|
||||
- `BinaryResource`: For raw `bytes` content.
|
||||
- `FileResource`: Reads content from a local file path. Handles text/binary modes, encoding, and lazy reading.
|
||||
- `HttpResource`: Fetches content from an HTTP(S) URL (requires `httpx`).
|
||||
- `HttpResource`: Fetches content from an HTTP(S) URL (requires `httpx2`).
|
||||
- `DirectoryResource`: Lists files in a local directory (returns JSON).
|
||||
- (`FunctionResource`: Internal class used by `@mcp.resource`).
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ For this tutorial, we'll use the [JSONPlaceholder API](https://jsonplaceholder.t
|
|||
|
||||
## Step 2: Create the MCP Server
|
||||
|
||||
Now for the magic. We'll use `FastMCP.from_openapi`. This method takes an `httpx.AsyncClient` configured for your API and its OpenAPI specification, and automatically converts **every endpoint** into a callable MCP `Tool`.
|
||||
Now for the magic. We'll use `FastMCP.from_openapi`. This method takes an `httpx2.AsyncClient` configured for your API and its OpenAPI specification, and automatically converts **every endpoint** into a callable MCP `Tool`.
|
||||
|
||||
<Tip>
|
||||
Learn more about working with OpenAPI specs in the [OpenAPI integration docs](/integrations/openapi).
|
||||
|
|
@ -45,11 +45,11 @@ For this tutorial, we'll use a simplified OpenAPI spec directly in the code. In
|
|||
Create a file named `api_server.py`:
|
||||
|
||||
```python api_server.py {31-35}
|
||||
import httpx
|
||||
import httpx2
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# Create an HTTP client for the target API
|
||||
client = httpx.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
client = httpx2.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
|
||||
# Define a simplified OpenAPI spec for JSONPlaceholder
|
||||
openapi_spec = {
|
||||
|
|
@ -150,13 +150,13 @@ Learn more about route maps in the [OpenAPI integration docs](/integrations/open
|
|||
Here’s how you can add custom route maps to turn `GET` requests into `Resources` and `ResourceTemplates` (if they have path parameters):
|
||||
|
||||
```python api_server_with_resources.py {3, 37-42}
|
||||
import httpx
|
||||
import httpx2
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.providers.openapi import RouteMap, MCPType
|
||||
|
||||
|
||||
# Create an HTTP client for the target API
|
||||
client = httpx.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
client = httpx2.AsyncClient(base_url="https://jsonplaceholder.typicode.com")
|
||||
|
||||
# Define a simplified OpenAPI spec for JSONPlaceholder
|
||||
openapi_spec = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue