Skip to content

Commit 5335321

Browse files
author
shiraayal-tadata
committed
add mintlify-formatted docs
1 parent 4a6c4a5 commit 5335321

File tree

15 files changed

+812
-0
lines changed

15 files changed

+812
-0
lines changed

docs/advanced/auth.mdx

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
---
2+
title: Authentication & Authorization
3+
icon: key
4+
---
5+
6+
FastAPI-MCP supports authentication and authorization using your existing FastAPI dependencies.
7+
8+
It also supports the full OAuth 2 flow, compliant with [MCP Spec 2025-03-26](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization).
9+
10+
It's worth noting that most MCP clients currently do not support the latest MCP spec, so for our examples we might use a bridge client such as `npx mcp-remote`. We recommend you use it as well, and we'll show our examples using it.
11+
12+
## Basic Token Passthrough
13+
14+
If you just want to be able to pass a valid authorization header, without supporting a full authentication flow, you don't need to do anything special.
15+
16+
You just need to make sure your MCP client is sending it:
17+
18+
```json {8-9, 13}
19+
{
20+
"mcpServers": {
21+
"remote-example": {
22+
"command": "npx",
23+
"args": [
24+
"mcp-remote",
25+
"http://localhost:8000/mcp",
26+
"--header",
27+
"Authorization:${AUTH_HEADER}"
28+
]
29+
},
30+
"env": {
31+
"AUTH_HEADER": "Bearer <your-token>"
32+
}
33+
}
34+
}
35+
```
36+
37+
This is enough to pass the authorization header to your FastAPI endpoints.
38+
39+
Optionally, if you want your MCP server to reject requests without an authorization header, you can add a dependency:
40+
41+
```python {1-2, 7-9}
42+
from fastapi import Depends
43+
from fastapi_mcp import FastApiMCP, AuthConfig
44+
45+
mcp = FastApiMCP(
46+
app,
47+
name="Protected MCP",
48+
auth_config=AuthConfig(
49+
dependencies=[Depends(verify_auth)],
50+
),
51+
)
52+
mcp.mount()
53+
```
54+
55+
For a complete working example of authorization header, check out the [Token Passthrough Example](https://github.com/tadata-org/fastapi_mcp/blob/main/examples/08_auth_example_token_passthrough.py) in the examples folder.
56+
57+
## OAuth Flow
58+
59+
FastAPI-MCP supports the full OAuth 2 flow, compliant with [MCP Spec 2025-03-26](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization).
60+
61+
It would look something like this:
62+
63+
```python {7-16}
64+
from fastapi import Depends
65+
from fastapi_mcp import FastApiMCP, AuthConfig
66+
67+
mcp = FastApiMCP(
68+
app,
69+
name="MCP With OAuth",
70+
auth_config=AuthConfig(
71+
issuer=f"https://auth.example.com/",
72+
authorize_url=f"https://auth.example.com/authorize",
73+
oauth_metadata_url=f"https://auth.example.com/.well-known/oauth-authorization-server",
74+
audience="my-audience",
75+
client_id="my-client-id",
76+
client_secret="my-client-secret",
77+
dependencies=[Depends(verify_auth)],
78+
setup_proxies=True,
79+
),
80+
)
81+
82+
mcp.mount()
83+
```
84+
85+
And you can call it like:
86+
87+
```json
88+
{
89+
"mcpServers": {
90+
"fastapi-mcp": {
91+
"command": "npx",
92+
"args": [
93+
"mcp-remote",
94+
"http://localhost:8000/mcp",
95+
"8080" // Optional port number. Necessary if you want your OAuth to work and you don't have dynamic client registration.
96+
]
97+
}
98+
}
99+
}
100+
```
101+
102+
You can use it with any OAuth provider that supports the OAuth 2 spec. See explanation on [AuthConfig](#authconfig-explained) for more details.
103+
104+
## Custom OAuth Metadata
105+
106+
If you already have a properly configured OAuth server that works with MCP clients, or if you want full control over the metadata, you can provide your own OAuth metadata directly:
107+
108+
```python {9, 22}
109+
from fastapi import Depends
110+
from fastapi_mcp import FastApiMCP, AuthConfig
111+
112+
mcp = FastApiMCP(
113+
app,
114+
name="MCP With Custom OAuth",
115+
auth_config=AuthConfig(
116+
# Provide your own complete OAuth metadata
117+
custom_oauth_metadata={
118+
"issuer": "https://auth.example.com",
119+
"authorization_endpoint": "https://auth.example.com/authorize",
120+
"token_endpoint": "https://auth.example.com/token",
121+
"registration_endpoint": "https://auth.example.com/register",
122+
"scopes_supported": ["openid", "profile", "email"],
123+
"response_types_supported": ["code"],
124+
"grant_types_supported": ["authorization_code"],
125+
"token_endpoint_auth_methods_supported": ["none"],
126+
"code_challenge_methods_supported": ["S256"]
127+
},
128+
129+
# Your auth checking dependency
130+
dependencies=[Depends(verify_auth)],
131+
),
132+
)
133+
134+
mcp.mount()
135+
```
136+
137+
This approach gives you complete control over the OAuth metadata and is useful when:
138+
- You have a fully MCP-compliant OAuth server already configured
139+
- You need to customize the OAuth flow beyond what the proxy approach offers
140+
- You're using a custom or specialized OAuth implementation
141+
142+
For this to work, you have to make sure mcp-remote is running [on a fixed port](#add-a-fixed-port-to-mcp-remote), for example `8080`, and then configure the callback URL to `http://127.0.0.1:8080/oauth/callback` in your OAuth provider.
143+
144+
## Working Example with Auth0
145+
146+
For a complete working example of OAuth integration with Auth0, check out the [Auth0 Example](https://github.com/tadata-org/fastapi_mcp/blob/main/examples/09_auth_example_auth0.py) in the examples folder. This example demonstrates the simple case of using Auth0 as an OAuth provider, with a working example of the OAuth flow.
147+
148+
For it to work, you need an .env file in the root of the project with the following variables:
149+
150+
```
151+
AUTH0_DOMAIN=your-tenant.auth0.com
152+
AUTH0_AUDIENCE=https://your-tenant.auth0.com/api/v2/
153+
AUTH0_CLIENT_ID=your-client-id
154+
AUTH0_CLIENT_SECRET=your-client-secret
155+
```
156+
157+
You also need to make sure to configure callback URLs properly in your Auth0 dashboard.
158+
159+
## AuthConfig Explained
160+
161+
### `setup_proxies=True`
162+
163+
Most OAuth providers need some adaptation to work with MCP clients. This is where `setup_proxies=True` comes in - it creates proxy endpoints that make your OAuth provider compatible with MCP clients:
164+
165+
```python
166+
mcp = FastApiMCP(
167+
app,
168+
auth_config=AuthConfig(
169+
# Your OAuth provider information
170+
issuer="https://auth.example.com",
171+
authorize_url="https://auth.example.com/authorize",
172+
oauth_metadata_url="https://auth.example.com/.well-known/oauth-authorization-server",
173+
174+
# Credentials registered with your OAuth provider
175+
client_id="your-client-id",
176+
client_secret="your-client-secret",
177+
178+
# Recommended, since some clients don't specify them
179+
audience="your-api-audience",
180+
default_scope="openid profile email",
181+
182+
# Your auth checking dependency
183+
dependencies=[Depends(verify_auth)],
184+
185+
# Create compatibility proxies - usually needed!
186+
setup_proxies=True,
187+
),
188+
)
189+
```
190+
191+
You also need to make sure to configure callback URLs properly in your OAuth provider. With mcp-remote for example, you have to [use a fixed port](#add-a-fixed-port-to-mcp-remote).
192+
193+
### Why Use Proxies?
194+
195+
Proxies solve several problems:
196+
197+
1. **Missing registration endpoints**:
198+
The MCP spec expects OAuth providers to support [dynamic client registration (RFC 7591)](https://datatracker.ietf.org/doc/html/rfc7591), but many don't.
199+
Furthermore, dynamic client registration is probably overkill for most use cases.
200+
The `setup_fake_dynamic_registration` option (True by default) creates a compatible endpoint that just returns a static client ID and secret.
201+
202+
2. **Scope handling**:
203+
Some MCP clients don't properly request scopes, so our proxy adds the necessary scopes for you.
204+
205+
3. **Audience requirements**:
206+
Some OAuth providers require an audience parameter that MCP clients don't always provide. The proxy adds this automatically.
207+
208+
### Add a fixed port to mcp-remote
209+
210+
```json
211+
{
212+
"mcpServers": {
213+
"example": {
214+
"command": "npx",
215+
"args": [
216+
"mcp-remote",
217+
"http://localhost:8000/mcp",
218+
"8080"
219+
]
220+
}
221+
}
222+
}
223+
```
224+
225+
Normally, mcp-remote will start on a random port, making it impossible to configure the OAuth provider's callback URL properly.
226+
227+
You have to make sure mcp-remote is running on a fixed port, for example `8080`, and then configure the callback URL to `http://127.0.0.1:8080/oauth/callback` in your OAuth provider.

docs/advanced/deploy.mdx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
title: Deploying the Server
3+
icon: play
4+
---
5+
6+
## Deploying separately from original FastAPI app
7+
8+
You are not limited to serving the MCP on the same FastAPI app from which it was created.
9+
10+
You can create an MCP server from one FastAPI app, and mount it to a different app:
11+
12+
```python {9, 15, }
13+
from fastapi import FastAPI
14+
from fastapi_mcp import FastApiMCP
15+
16+
# Your API app
17+
api_app = FastAPI()
18+
# ... define your API endpoints on api_app ...
19+
20+
# A separate app for the MCP server
21+
mcp_app = FastAPI()
22+
23+
# Create MCP server from the API app
24+
mcp = FastApiMCP(api_app)
25+
26+
# Mount the MCP server to the separate app
27+
mcp.mount(mcp_app)
28+
```
29+
30+
Then, you can run both apps separately:
31+
32+
```bash
33+
uvicorn main:api_app --host api-host --port 8001
34+
uvicorn main:mcp_app --host mcp-host --port 8000
35+
```

docs/advanced/refresh.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: Refreshing the Server
3+
description: Adding endpoints after MCP server creation
4+
icon: arrows-rotate
5+
---
6+
7+
If you add endpoints to your FastAPI app after creating the MCP server, you'll need to refresh the server to include them:
8+
9+
```python {9-12, 15}
10+
from fastapi import FastAPI
11+
from fastapi_mcp import FastApiMCP
12+
13+
app = FastAPI()
14+
15+
mcp = FastApiMCP(app)
16+
mcp.mount()
17+
18+
# Add new endpoints after MCP server creation
19+
@app.get("/new/endpoint/", operation_id="new_endpoint")
20+
async def new_endpoint():
21+
return {"message": "Hello, world!"}
22+
23+
# Refresh the MCP server to include the new endpoint
24+
mcp.setup_server()
25+
```

docs/advanced/transport.mdx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: Transport
3+
description: How to communicate with the FastAPI app
4+
icon: car
5+
---
6+
7+
FastAPI-MCP uses ASGI transport by default, which means it communicates directly with your FastAPI app without making HTTP requests. This is more efficient and doesn't require a base URL.
8+
9+
It's not even necessary that the FastAPI server will run.
10+
11+
If you need to specify a custom base URL or use a different transport method, you can provide your own `httpx.AsyncClient`:
12+
13+
```python {7-10, 14}
14+
import httpx
15+
from fastapi import FastAPI
16+
from fastapi_mcp import FastApiMCP
17+
18+
app = FastAPI()
19+
20+
custom_client = httpx.AsyncClient(
21+
base_url="https://api.example.com",
22+
timeout=30.0
23+
)
24+
25+
mcp = FastApiMCP(
26+
app,
27+
http_client=custom_client
28+
)
29+
30+
mcp.mount()
31+
```

0 commit comments

Comments
 (0)