60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
122 lines
4.0 KiB
Python
122 lines
4.0 KiB
Python
"""Mounted OAuth servers example for FastMCP.
|
|
|
|
This example demonstrates mounting multiple OAuth-protected MCP servers in a single
|
|
application, each with its own provider. It showcases RFC 8414 path-aware discovery
|
|
where each server has its own authorization server metadata endpoint.
|
|
|
|
URL structure:
|
|
- GitHub MCP: http://127.0.0.1:8000/api/mcp/github/mcp
|
|
- Google MCP: http://127.0.0.1:8000/api/mcp/google/mcp
|
|
- GitHub discovery: http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/github
|
|
- Google discovery: http://127.0.0.1:8000/.well-known/oauth-authorization-server/api/mcp/google
|
|
|
|
Required environment variables:
|
|
- FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID: Your GitHub OAuth app client ID
|
|
- FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET: Your GitHub OAuth app client secret
|
|
- FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID: Your Google OAuth client ID
|
|
- FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET: Your Google OAuth client secret
|
|
|
|
To run:
|
|
python server.py
|
|
"""
|
|
|
|
import os
|
|
|
|
import uvicorn
|
|
from starlette.applications import Starlette
|
|
from starlette.routing import Mount
|
|
|
|
from fastmcp import FastMCP
|
|
from fastmcp.server.auth.providers.github import GitHubProvider
|
|
from fastmcp.server.auth.providers.google import GoogleProvider
|
|
|
|
# Configuration
|
|
ROOT_URL = "http://127.0.0.1:8000"
|
|
API_PREFIX = "/api/mcp"
|
|
|
|
# --- GitHub OAuth Server ---
|
|
github_auth = GitHubProvider(
|
|
client_id=os.getenv("FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID") or "",
|
|
client_secret=os.getenv("FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET") or "",
|
|
base_url=f"{ROOT_URL}{API_PREFIX}/github",
|
|
redirect_path="/auth/callback/github",
|
|
)
|
|
|
|
github_mcp = FastMCP("GitHub Server", auth=github_auth)
|
|
|
|
|
|
@github_mcp.tool
|
|
def github_echo(message: str) -> str:
|
|
"""Echo from the GitHub-authenticated server."""
|
|
return f"[GitHub] {message}"
|
|
|
|
|
|
@github_mcp.tool
|
|
def github_info() -> str:
|
|
"""Get info about the GitHub server."""
|
|
return "This is the GitHub OAuth protected MCP server"
|
|
|
|
|
|
# --- Google OAuth Server ---
|
|
google_auth = GoogleProvider(
|
|
client_id=os.getenv("FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID") or "",
|
|
client_secret=os.getenv("FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET") or "",
|
|
base_url=f"{ROOT_URL}{API_PREFIX}/google",
|
|
redirect_path="/auth/callback/google",
|
|
)
|
|
|
|
google_mcp = FastMCP("Google Server", auth=google_auth)
|
|
|
|
|
|
@google_mcp.tool
|
|
def google_echo(message: str) -> str:
|
|
"""Echo from the Google-authenticated server."""
|
|
return f"[Google] {message}"
|
|
|
|
|
|
@google_mcp.tool
|
|
def google_info() -> str:
|
|
"""Get info about the Google server."""
|
|
return "This is the Google OAuth protected MCP server"
|
|
|
|
|
|
# --- Create ASGI apps ---
|
|
github_app = github_mcp.http_app(path="/mcp")
|
|
google_app = google_mcp.http_app(path="/mcp")
|
|
|
|
# Get well-known routes for each provider (path-aware per RFC 8414)
|
|
github_well_known = github_auth.get_well_known_routes(mcp_path="/mcp")
|
|
google_well_known = google_auth.get_well_known_routes(mcp_path="/mcp")
|
|
|
|
# --- Combine into single application ---
|
|
# Note: Each provider has its own path-aware discovery endpoint:
|
|
# - /.well-known/oauth-authorization-server/api/mcp/github
|
|
# - /.well-known/oauth-authorization-server/api/mcp/google
|
|
app = Starlette(
|
|
routes=[
|
|
# Well-known routes at root level (path-aware)
|
|
*github_well_known,
|
|
*google_well_known,
|
|
# MCP servers under /api/mcp prefix
|
|
Mount(f"{API_PREFIX}/github", app=github_app),
|
|
Mount(f"{API_PREFIX}/google", app=google_app),
|
|
],
|
|
# Use one of the app lifespans (they're functionally equivalent)
|
|
lifespan=github_app.lifespan,
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
print("Starting mounted OAuth servers...")
|
|
print(f" GitHub MCP: {ROOT_URL}{API_PREFIX}/github/mcp")
|
|
print(f" Google MCP: {ROOT_URL}{API_PREFIX}/google/mcp")
|
|
print()
|
|
print("Discovery endpoints (RFC 8414 path-aware):")
|
|
print(
|
|
f" GitHub: {ROOT_URL}/.well-known/oauth-authorization-server{API_PREFIX}/github"
|
|
)
|
|
print(
|
|
f" Google: {ROOT_URL}/.well-known/oauth-authorization-server{API_PREFIX}/google"
|
|
)
|
|
print()
|
|
uvicorn.run(app, host="0.0.0.0", port=8000)
|