Auth0이 없는 모든 Claude 플랫폼의 개인 MCP 서버
hackernews
|
|
🔬 연구
#claude
#fastmcp
#mcp
#oauth
#review
#인증
#oauth 2.1
원문 출처: hackernews · Genesis Park에서 요약 및 분석
요약
Hmm, 사용자가 Hacker News에 올라온 기사를 한국어로 2-4문장으로 요약해달라고 요청했군. 기사 내용을 보면 Auth0 없이 Claude 플랫폼에 개인용 MCP 서버를 구축한 내용이야. 사용자가 강조한 포인트는 원문을 그대로 번역하지 말고 핵심 정보만 추출하라는 거야.
본문
A drop-in OAuth 2.1 auth provider for FastMCP that makes your personal MCP server work on every Claude platform — web, mobile, Desktop, and Code. No external identity provider (Google, GitHub, Auth0) required. FastMCP ships with two auth options: | Provider | Persistence | Security | External IdP required | |---|---|---|---| InMemoryOAuthProvider | None (test only) | None (auto-approves everything) | No | OAuthProxy | Yes | Full OAuth | Yes (Google, GitHub, etc.) | Neither works for the common case: "I have a personal MCP server and I want Claude.ai and Claude mobile to connect to it securely." PersonalAuthProvider fills that gap: | Persistence | Security | External IdP required | | |---|---|---|---| PersonalAuthProvider | File-backed (survives restarts) | Domain-restricted + optional password | No | pip install 'fastmcp[auth]' from fastmcp import FastMCP from personal_auth import PersonalAuthProvider auth = PersonalAuthProvider( base_url="https://your-domain.com", # your public URL ) mcp = FastMCP(name="my-server", auth=auth) @mcp.tool def hello(name: str) -> str: return f"Hello, {name}!" mcp.run(transport="streamable-http", host="0.0.0.0", port=8050) That's it. Your server now has: - OAuth 2.1 with Dynamic Client Registration (DCR) and PKCE .well-known discovery endpoints Claude.ai expects- Streamable HTTP transport - Tokens persisted to .oauth-state/oauth_tokens.json - Authorization restricted to claude.ai ,claude.com , andlocalhost by default Settings → Connectors → Add custom connector → URL: https://your-domain.com/mcp Add to claude_desktop_config.json (~/Library/Application Support/Claude/ on macOS): { "mcpServers": { "my-server": { "command": "npx", "args": ["-y", "mcp-remote", "https://your-domain.com/mcp"] } } } Requires Node.js. The mcp-remote bridge handles the OAuth flow (opens a browser for one-time auth). claude mcp add my-server --transport http "https://your-domain.com/mcp" Add the connector on claude.ai web (above). It syncs to mobile automatically. You cannot add connectors directly from the mobile app. auth = PersonalAuthProvider( # Required: your public URL (used for OAuth discovery). # Must match exactly how clients will reach your server. base_url="https://your-domain.com", # Optional: password gate on /authorize (default: None) # In practice, the domain restriction is the primary security gate. password="my-secret", # Optional: allowed redirect domains (default shown below) # Only these domains can complete the OAuth authorization flow. # Set to None to allow all domains (not recommended). allowed_redirect_domains=["claude.ai", "claude.com", "localhost"], # Optional: access token lifetime (default: 30 days) access_token_expiry_seconds=30 * 24 * 60 * 60, # Optional: directory for token persistence (default: ".oauth-state") state_dir=".oauth-state", ) - DCR is open — any client can register (required by Claude.ai's OAuth flow) /authorize is restricted — only redirect URIs matchingallowed_redirect_domains are approved. A random person hitting your server can register a client, but they can't get a token because their redirect URI won't matchclaude.ai orlocalhost - Tokens are opaque — random hex strings, not JWTs with extractable claims - Refresh tokens don't expire — access tokens last 30 days and can be refreshed indefinitely - Tokens persist to disk — you don't re-auth after server restarts These are real issues we hit building this. They're not documented well elsewhere. 1. DCR must be explicitly enabled FastMCP's ClientRegistrationOptions defaults to enabled=False . Without it, /register returns 404 and Claude.ai silently fails to connect. PersonalAuthProvider enables this for you. 2. base_url must match your public URL exactly The OAuth discovery endpoint at /.well-known/oauth-authorization-server advertises endpoints using base_url . If this doesn't match how Claude.ai reaches your server (e.g., http://localhost vs https://your-domain.com ), the OAuth flow will fail with redirect mismatches. 3. Do NOT use FastAPI's BaseHTTPMiddleware If you wrap your MCP server in FastAPI and add middleware via @app.middleware("http") or BaseHTTPMiddleware , it will break streaming responses. Streamable HTTP and SSE both fail because the middleware tries to iterate the response body, which asserts on SSE message types. Use raw ASGI middleware instead, or — better — let FastMCP handle everything via mcp.run() . 4. Use mcp.run() , not a FastAPI wrapper FastMCP's mcp.run(transport="streamable-http") sets up all the OAuth endpoints, transport, and routing correctly. If you mount it manually on FastAPI, you'll need to handle path prefixes, lifespan, and well-known endpoints yourself. Just use mcp.run() . 5. Streamable HTTP responses are SSE, not JSON Even though the transport is called "streamable-http", tool call responses come back as text/event-stream (SSE format), not application/json . If you're writing a custom client, parse the data: lines: def parse_sse(text): for line in text.split('\n'): if l
Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.
공유