mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-24 06:24:18 +02:00
Merge branch 'main' into stdio_not_exiting
This commit is contained in:
commit
338b669931
4 changed files with 76 additions and 34 deletions
|
|
@ -10,20 +10,51 @@ tag: NEW
|
|||
|
||||
FastMCP Cloud is a young product and we welcome your feedback. Please join our [Discord](https://discord.com/invite/aGsSC3yDF4) to share your thoughts and ideas, and you can expect to see new features and improvements every week.
|
||||
|
||||
|
||||
<Note>
|
||||
FastMCP Cloud supports both **FastMCP 2.0** servers and also **FastMCP 1.0** servers that were created with the official MCP Python SDK.
|
||||
</Note>
|
||||
|
||||
<Tip>
|
||||
FastMCP Cloud is completely free while in beta!
|
||||
</Tip>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To use FastMCP Cloud, you'll need a [GitHub](https://github.com) account. In addition, you'll need a GitHub repo that contains a FastMCP server instance. If you don't want to create one yet, you can proceed to [step 1](#step-1-create-a-project) and use the FastMCP Cloud quickstart repo.
|
||||
|
||||
Your repo can be public or private, but must include at least a Python file that contains a FastMCP server instance.
|
||||
<Tip>
|
||||
To ensure your file is compatible with FastMCP Cloud, you can run `fastmcp inspect <file.py:server_object>` to see what FastMCP Cloud will see when it runs your server.
|
||||
</Tip>
|
||||
|
||||
If you have a `requirements.txt` or `pyproject.toml` in the repo, FastMCP Cloud will automatically detect your server's dependencies and install them for you. Note that your file *can* have an `if __name__ == "__main__"` block, but it will be ignored by FastMCP Cloud.
|
||||
|
||||
For example, a minimal server file might look like:
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("MyServer")
|
||||
|
||||
@mcp.tool
|
||||
def hello(name: str) -> str:
|
||||
return f"Hello, {name}!"
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Deploying to FastMCP Cloud takes just three simple steps.
|
||||
There are just three steps to deploying a server to FastMCP Cloud:
|
||||
|
||||
### Step 1: Create a Project
|
||||
|
||||
Visit [fastmcp.cloud](https://fastmcp.cloud) and sign in with your GitHub account. Create a project either by selecting an existing repository or using the FastMCP Cloud quickstart repo.
|
||||
Visit [fastmcp.cloud](https://fastmcp.cloud) and sign in with your GitHub account. Then, create a project. Each project corresponds to a GitHub repo, and you can create one from either your own repo or using the FastMCP Cloud quickstart repo.
|
||||
|
||||
<img src="/assets/images/fastmcp_cloud/quickstart.png" alt="FastMCP Cloud Quickstart Screen" />
|
||||
|
||||
### Step 2: Configure Your Server
|
||||
Next, you'll be prompted to configure your project.
|
||||
|
||||
<img src="/assets/images/fastmcp_cloud/create_project.png" alt="FastMCP Cloud Configuration Screen" />
|
||||
|
||||
The configuration screen lets you specify:
|
||||
- **Name**: The name of your project. This will be used to generate a unique URL for your server.
|
||||
|
|
@ -32,31 +63,27 @@ The configuration screen lets you specify:
|
|||
|
||||
Note that FastMCP Cloud will automatically detect yours server's Python dependencies from either a `requirements.txt` or `pyproject.toml` file.
|
||||
|
||||
<img src="/assets/images/fastmcp_cloud/create_project.png" alt="FastMCP Cloud Configuration Screen" />
|
||||
### Step 2: Deploy Your Server
|
||||
|
||||
### Step 3: Deploy
|
||||
|
||||
Once you create your project, FastMCP Cloud will:
|
||||
1. Create the repository (if using quickstart)
|
||||
Once you configure your project, FastMCP Cloud will:
|
||||
1. Clone the repository
|
||||
2. Build your FastMCP server
|
||||
3. Deploy it to a unique URL
|
||||
4. Make it immediately available for connections
|
||||
|
||||
<img src="/assets/images/fastmcp_cloud/deployment.png" alt="FastMCP Cloud Deployment Screen" />
|
||||
|
||||
FastMCP Cloud will monitor your repo and redeploy your server whenever you push a change to the `main` branch. In addition, FastMCP Cloud will build and deploy servers for every PR your open, hosting them on unique URLs, so you can test changes before updating your production server.
|
||||
|
||||
## Connect to Your Server
|
||||
### Step 3: Connect to Your Server
|
||||
|
||||
Your deployed server will be accessible at a URL like:
|
||||
Once your server is deployed, it will be accessible at a URL like:
|
||||
|
||||
```
|
||||
https://your-project-name.fastmcp.app/mcp
|
||||
```
|
||||
|
||||
You should be able to connect to it as soon as you see the deployment succeed! In addition, you can instantly connect your server to a variety of popular LLM clients:
|
||||
You should be able to connect to it as soon as you see the deployment succeed! FastMCP Cloud provides instant connection options for popular LLM clients:
|
||||
|
||||
<img src="/assets/images/fastmcp_cloud/connect.png" alt="FastMCP Cloud Connection Screen" />
|
||||
|
||||
## Testing Changes
|
||||
|
||||
Any time you open a PR to your connected repo, FastMCP Cloud will create a new server for that branch and deploy it on a unique URL. This allows you to test your changes before merging to production. Each merge to main will trigger a new deployment of the "production" version of your server.
|
||||
|
|
@ -122,7 +122,10 @@
|
|||
{
|
||||
"group": "Essentials",
|
||||
"icon": "cube",
|
||||
"pages": ["clients/client", "clients/transports"]
|
||||
"pages": [
|
||||
"clients/client",
|
||||
"clients/transports"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Core Operations",
|
||||
|
|
@ -148,7 +151,10 @@
|
|||
{
|
||||
"group": "Authentication",
|
||||
"icon": "user-shield",
|
||||
"pages": ["clients/auth/oauth", "clients/auth/bearer"]
|
||||
"pages": [
|
||||
"clients/auth/oauth",
|
||||
"clients/auth/bearer"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -194,12 +200,17 @@
|
|||
},
|
||||
{
|
||||
"anchor": "What's New",
|
||||
"pages": ["updates", "changelog"]
|
||||
"pages": [
|
||||
"updates",
|
||||
"changelog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"anchor": "Community",
|
||||
"icon": "users",
|
||||
"pages": ["community/showcase"]
|
||||
"pages": [
|
||||
"community/showcase"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ sidebarTitle: oauth
|
|||
|
||||
## Functions
|
||||
|
||||
### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L34" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L36" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
default_cache_dir() -> Path
|
||||
```
|
||||
|
||||
### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L152" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
check_if_auth_required(mcp_url: str, httpx_kwargs: dict[str, Any] | None = None) -> bool
|
||||
|
|
@ -28,7 +28,7 @@ Check if the MCP endpoint requires authentication by making a test request.
|
|||
|
||||
## Classes
|
||||
|
||||
### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L38" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
File-based token storage implementation for OAuth credentials and tokens.
|
||||
|
|
@ -39,7 +39,7 @@ Each instance is tied to a specific server URL for proper token isolation.
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L55" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_base_url(url: str) -> str
|
||||
|
|
@ -48,7 +48,7 @@ get_base_url(url: str) -> str
|
|||
Extract the base URL (scheme + host) from a URL.
|
||||
|
||||
|
||||
#### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L58" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_cache_key(self) -> str
|
||||
|
|
@ -57,7 +57,7 @@ get_cache_key(self) -> str
|
|||
Generate a safe filesystem key from the server's base URL.
|
||||
|
||||
|
||||
#### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L73" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L75" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_tokens(self) -> OAuthToken | None
|
||||
|
|
@ -66,7 +66,7 @@ get_tokens(self) -> OAuthToken | None
|
|||
Load tokens from file storage.
|
||||
|
||||
|
||||
#### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L90" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L92" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
set_tokens(self, tokens: OAuthToken) -> None
|
||||
|
|
@ -75,7 +75,7 @@ set_tokens(self, tokens: OAuthToken) -> None
|
|||
Save tokens to file storage.
|
||||
|
||||
|
||||
#### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L96" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L98" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_client_info(self) -> OAuthClientInformationFull | None
|
||||
|
|
@ -84,7 +84,7 @@ get_client_info(self) -> OAuthClientInformationFull | None
|
|||
Load client information from file storage.
|
||||
|
||||
|
||||
#### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L124" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
set_client_info(self, client_info: OAuthClientInformationFull) -> None
|
||||
|
|
@ -93,7 +93,7 @@ set_client_info(self, client_info: OAuthClientInformationFull) -> None
|
|||
Save client information to file storage.
|
||||
|
||||
|
||||
#### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L130" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L132" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
clear(self) -> None
|
||||
|
|
@ -102,7 +102,7 @@ clear(self) -> None
|
|||
Clear all cached data for this server.
|
||||
|
||||
|
||||
#### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L139" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L141" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
clear_all(cls, cache_dir: Path | None = None) -> None
|
||||
|
|
@ -111,7 +111,7 @@ clear_all(cls, cache_dir: Path | None = None) -> None
|
|||
Clear all cached data for all servers.
|
||||
|
||||
|
||||
### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L182" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L184" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
OAuth client provider for MCP servers with browser-based authentication.
|
||||
|
|
@ -122,7 +122,7 @@ a browser for user authorization and running a local callback server.
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L248" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L250" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
redirect_handler(self, authorization_url: str) -> None
|
||||
|
|
@ -131,7 +131,7 @@ redirect_handler(self, authorization_url: str) -> None
|
|||
Open browser for authorization.
|
||||
|
||||
|
||||
#### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L253" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
callback_handler(self) -> tuple[str, str | None]
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
import asyncio
|
||||
import json
|
||||
import webbrowser
|
||||
from asyncio import Future
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
from urllib.parse import urlparse
|
||||
|
|
@ -18,6 +19,7 @@ from mcp.shared.auth import (
|
|||
OAuthToken as OAuthToken,
|
||||
)
|
||||
from pydantic import AnyHttpUrl, ValidationError
|
||||
from uvicorn.server import Server
|
||||
|
||||
from fastmcp import settings as fastmcp_global_settings
|
||||
from fastmcp.client.oauth_callback import (
|
||||
|
|
@ -253,10 +255,10 @@ class OAuth(OAuthClientProvider):
|
|||
async def callback_handler(self) -> tuple[str, str | None]:
|
||||
"""Handle OAuth callback and return (auth_code, state)."""
|
||||
# Create a future to capture the OAuth response
|
||||
response_future = asyncio.get_running_loop().create_future()
|
||||
response_future: Future[Any] = asyncio.get_running_loop().create_future()
|
||||
|
||||
# Create server with the future
|
||||
server = create_oauth_callback_server(
|
||||
server: Server = create_oauth_callback_server(
|
||||
port=self.redirect_port,
|
||||
server_url=self.server_base_url,
|
||||
response_future=response_future,
|
||||
|
|
@ -280,3 +282,5 @@ class OAuth(OAuthClientProvider):
|
|||
server.should_exit = True
|
||||
await asyncio.sleep(0.1) # Allow server to shutdown gracefully
|
||||
tg.cancel_scope.cancel()
|
||||
|
||||
raise RuntimeError("OAuth callback handler could not be started")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue