mcp-oauth-test
FastMCP OIDC Server
FastMCP로 작성된, OIDC 로그인으로 보호되는 MCP server입니다. FastMCP의 OIDCProxy를 사용합니다. MCP 클라이언트는 서버가 노출하는 OAuth 메타데이터를 통해 인증을 완료하며, 실제 로그인과 token exchange는 QA OIDC provider로 전달됩니다.
현재 QA MGT OpenAPI가 연동되어 있으며, trainee, 주문, 상품, 고객, 캠퍼스 채용 및 국제 채용 관련 MCP tools가 생성됩니다.
OIDC discovery 주소는 기본값으로 다음과 같이 설정되어 있습니다:
https://auth-qa.drillinsight.com/.well-known/openid-configuration인증 준비
먼저 auth-qa.drillinsight.com에서 OAuth 애플리케이션을 등록하고, 다음 콜백 주소를 화이트리스트에 추가합니다:
http://localhost:8000/auth/callback다른 주소에 배포할 경우 http://localhost:8000을 BASE_URL 값으로 교체합니다. 콜백 주소는 FastMCP의 BASE_URL과 정확히 일치해야 합니다.
로컬 실행
cp .env.example .env
# 编辑 .env,至少填写 OIDC_CLIENT_ID 和 OIDC_CLIENT_SECRET
uv sync
uv run mcp-oidc-server모듈을 직접 실행할 수도 있습니다:
uv run python -m oidc_mcp_server.server서비스는 기본적으로 http://127.0.0.1:8000에서 수신 대기합니다. MCP 클라이언트가 다른 머신이나 컨테이너에서 실행되는 경우, 클라이언트가 접근 가능한 BASE_URL과 적절한 HOST(예: 0.0.0.0)를 설정하세요.
Claude Code 플러그인
저장소에는 프라이빗 Claude Code marketplace와 MCP 플러그인이 포함되어 있습니다:
.claude-plugin/marketplace.json
└── plugins/mcp-oauth-test/
├── .claude-plugin/plugin.json
├── .mcp.json
└── README.md플러그인은 Claude Code를 이미 배포된 원격 MCP 서비스에 연결하는 역할만 하며, 로컬에서 Python 서비스를 시작하지 않습니다. 개발 테스트 시 직접 로드할 수 있습니다:
claude --plugin-dir ./plugins/mcp-oauth-test플러그인은 개발 환경 MCP Server에 고정 연결되어 있습니다:
https://api-mcp-oauth-dev.beaconfireinc.com/mcp프라이빗 marketplace에서 설치할 수도 있습니다:
/plugin marketplace add /path/to/mcp-oauth-test
/plugin install mcp-oauth-test@authsome-internal현재 marketplace 루트 디렉터리는 저장소 루트 디렉터리입니다. 해당 marketplace를 회사 프라이빗 GitHub 저장소에 유지하고, 공개 marketplace에는 커밋하지 마세요. 공유 환경에서는 HTTPS 주소를 사용하고, 회사 IdP 및 MCP Server 측에서 회사 사용자만 접근할 수 있도록 제한하세요.
OIDCProxy를 사용하는 이유
업스트림 auth-qa.drillinsight.com은 DCR 또는 CIMD를 지원할 필요가 없습니다. OIDCProxy는 바로 이러한 시나리오를 위한 것입니다:
ChatGPT ── MCP OAuth / CIMD ──> FastMCP OIDCProxy
│
└── 固定 client_id/client_secret ──> auth-qa.drillinsight.com업스트림에 사전 등록해야 하는 것은 FastMCP OAuth 애플리케이션뿐이며, ${BASE_URL}/auth/callback을 구성해야 합니다. ChatGPT가 사용하는 CIMD는 FastMCP 프록시 계층에서 처리되며, 업스트림 OAuth server로 전달되지 않습니다.
ChatGPT CIMD 구성
ChatGPT에서 커스텀 MCP를 생성할 때, OAuth 고급 설정의 "클라이언트 등록"에서 다음을 선택하세요:
客户端标识元数据文档(CIMD)현재 ChatGPT 커넥터가 생성하는 정보는 다음과 같습니다:
CIMD Client ID / 客户端元数据 URL:
https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
ChatGPT Callback URL:
https://chatgpt.com/connector/oauth/0Buhw3sHVv1-CIMD URL 자체가 ChatGPT가 FastMCP OAuth 프록시에 접근할 때 사용하는 client_id입니다. 이는 업스트림 auth-qa.drillinsight.com에 등록할 필요가 없으며, 등록해서도 안 됩니다.
이 프로젝트에는 두 가지 서로 다른 OAuth Client ID 계층이 존재합니다:
OAuth 경로 |
| 구성 위치 |
ChatGPT → FastMCP OIDCProxy |
| ChatGPT가 자동 제공, CIMD 선택 시 수동 입력 불필요 |
FastMCP OIDCProxy → |
| MCP Server의 |
해당 데이터 흐름은 다음과 같습니다:
ChatGPT
│ client_id=https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
▼
FastMCP OIDCProxy
│ client_id=app_74a4b555-5b87-4212-9dda-d584fa78caf8
▼
auth-qa.drillinsight.comMCP Server의 환경 변수 구성:
OIDC_CLIENT_ID=app_74a4b555-5b87-4212-9dda-d584fa78caf8
OIDC_CLIENT_SECRET=<上游 OAuth Server 颁发的客户端密钥>업스트림 OAuth Server는 해당 app_... 애플리케이션에 FastMCP의 콜백 주소만 구성하면 됩니다:
https://heroic-verbally-crawdad.ngrok-free.app/auth/callbackChatGPT의 콜백 주소 https://chatgpt.com/connector/oauth/...를 업스트림 OAuth Server에 구성하지 마세요. 해당 주소는 인증 완료 후 FastMCP 프록시 계층에서 사용됩니다.
인증 시작 시 정상 로그에는 먼저 ChatGPT의 CIMD Client ID가 나타나야 합니다:
CIMD document fetched and validated
GET /authorize?client_id=https://chatgpt.com/oauth/.../client.json ... 302그런 다음 FastMCP가 app_74a4b555-...를 사용하여 업스트림 OAuth Server로 이동합니다.
MCP 클라이언트 구성
MCP 주소를 다음과 같이 구성합니다:
http://localhost:8000/mcpFastMCP는 다음 인증 발견 주소를 제공합니다:
http://localhost:8000/.well-known/oauth-authorization-server
http://localhost:8000/.well-known/oauth-protected-resource/mcp클라이언트는 이러한 MCP/OAuth discovery endpoint를 자동으로 읽어야 합니다. 로그인 성공 후 두 개의 보호된 도구를 호출할 수 있습니다:
ping: 상태 확인.who_am_i: FastMCP가 현재 인증 토큰에서 추출한client_id, scope 및 claims를 반환합니다.
구성 항목
환경 변수 | 필수 | 기본값 | 설명 |
| 예 | - | 업스트림 OIDC 클라이언트 ID |
| 둘 중 하나 | - | confidential client secret |
| 둘 중 하나 | - | public PKCE client 또는 프로덕션 환경의 FastMCP token 서명 키 |
| 아니요 | QA discovery URL | OIDC discovery 주소 |
| 아니요 |
| MCP server 공개 주소 |
| 아니요 |
| OAuth 인증 요청/기본 광고 scope; access token scope 검증에는 사용되지 않음 |
| 아니요 | OIDC discovery issuer | JWT |
| 아니요 |
| 커스텀 token issuer의 JWKS 주소 |
| 아니요 | - | 선택적 JWT |
| 아니요 |
| 수신 대기 주소 |
| 아니요 |
| 수신 대기 포트 |
| 아니요 | QA MGT 주소 | MGT API 실제 호출 Base URL |
| 아니요 |
| 로컬 OpenAPI spec 경로 |
프로덕션 환경에서는 임의의 JWT_SIGNING_KEY를 명시적으로 설정하고, HTTPS BASE_URL을 사용하세요. .env 또는 client secret을 Git에 커밋하지 마세요.
커스텀 Token Issuer
토큰의 iss가 OIDC discovery가 반환하는 issuer가 아니라 auth middleware에 의해 테넌트 주소로 변경된 경우, 예를 들어:
实际 token iss:
https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/다음과 같이 설정합니다:
OIDC_TOKEN_ISSUER=https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/
OIDC_JWKS_URI=https://auth-qa.drillinsight.com/oauth/jwksOIDC_CONFIG_URL은 여전히 OAuth 로그인 및 인증 엔드포인트 발견에 사용됩니다. OIDC_TOKEN_ISSUER는 JWT access token의 iss 검증에만 사용됩니다. 둘은 다를 수 있습니다. OIDC_TOKEN_ISSUER는 끝의 /를 포함하여 토큰의 iss와 정확히 일치해야 합니다.
현재 프로젝트는 access token의 scope 또는 scp claim을 검증하지 않습니다. MGT 레거시 토큰이 비표준 scope 형식을 사용하기 때문입니다. OIDC_REQUIRED_SCOPES는 여전히 OAuth 인증 요청에 사용되지만, 표준 scope claim이 없는 유효한 토큰을 차단하지는 않습니다. 서명, issuer, audience, 만료 시간 및 JWKS 검증은 계속 유지됩니다.
QA MGT OpenAPI 연동
QA OpenAPI spec은 다음 경로에 고정 저장되어 있습니다:
specs/mgt-qa-openapi.jsonMCP는 런타임에 온라인 /api-docs에 접근하지 않으므로, 향후 프로덕션 환경에서 API 문서를 공개하지 않아도 실행에 영향을 주지 않습니다. MGT_API_BASE_URL을 통해 실제 API 주소만 전환하면 됩니다. Docker 이미지는 specs/mgt-qa-openapi.json을 /app/specs/mgt-qa-openapi.json으로 복사하고, MGT_OPENAPI_SPEC_PATH를 자동으로 설정합니다.
첫 번째 버전에서 노출되는 API 범위:
/api/v1/user/current
/course/list
/batch/list
/batch/trainee/list
/equity/userequity/give
/api/v1/order/**
/api/v1/item/**
/api/v1/open/getSku*
/api/v1/customers
/api/v1/campus-recruitment/**(排除 export)
/api/v1/recruitment-info/**(排除 export)주문 결제 링크 인터페이스는 현재 요구 사항에 따라 연동됩니다:
/api/v1/order/queryPayLink
/api/v1/order/reGenaratePayLink환불, 결제 콜백 및 고객 데이터 내보내기 인터페이스는 여전히 제외됩니다:
/mall/v1/order/refund
/alipay/**
/stripe/**
/weixin/refund/**
/api/v1/customers/export
/api/v1/campus-recruitment/export
/api/v1/recruitment-info/exportMGT를 호출할 때마다 OpenAPI 클라이언트는 현재 FastMCP 요청에서 사용자의 업스트림 OAuth access token을 가져와 다음을 전송합니다:
Authorization: Bearer <user access token>
X-Application-Id: <token.app_id>여기서 X-Application-Id는 추가 구성이 필요 없으며, 검증된 JWT의 app_id claim에서 직접 읽습니다. app_id가 없는 토큰은 거부되어 MGT에 불완전한 요청이 전송되는 것을 방지합니다.
따라서 MGT는 auth-qa.drillinsight.com이 발급한 사용자 토큰을 신뢰하고, 사용자 신원에 따라 권한 제어를 수행해야 합니다.
ChatGPT CIMD timeout 문제 해결
로그에 다음이 포함된 경우:
CIMD fetch failed for https://chatgpt.com/.../client.json: Timeout fetching
Unregistered client_id=https://chatgpt.com/.../client.jsonFastMCP가 ChatGPT가 호스팅하는 클라이언트 메타데이터에 직접 접근할 수 없음을 의미합니다. 현재 머신이 신뢰할 수 있는 아웃바운드 프록시를 통해 외부 네트워크에 접근해야 하는 경우 다음을 구성하세요:
FASTMCP_SSRF_TRUST_PROXY=true
HTTPS_PROXY=http://127.0.0.1:7897그런 다음 서비스를 완전히 중지하고 다시 시작합니다. 프로그램은 FastMCP를 import하기 전에 프로젝트 루트의 .env를 자동으로 로드합니다. FastMCP는 기본적으로 CIMD/JWKS 요청에 대해 DNS 검증 및 IP 고정을 수행하므로 일반 프록시 환경 변수를 자동으로 사용하지 않습니다. 이 옵션을 활성화하면 SSRF 방어 책임이 지정된 프록시에 위임되고 NO_PROXY는 무시됩니다. 신뢰할 수 있는 프록시에서만 활성화하세요.
로그의 첫 번째 POST /mcp 401은 클라이언트가 인증 전에 보호된 리소스를 탐색하는 것입니다. 여러 /.well-known/... 주소에 대한 404도 ChatGPT의 호환성 탐색입니다. /.well-known/oauth-authorization-server가 200을 반환하면 이는 실패 원인이 아닙니다.
로그에 Unregistered client_id=app_... 또는 다른 URL이 아닌 client ID가 표시되면, ChatGPT가 서버 측 저장소에서 이미 손실된 이전 DCR 등록을 캐시한 것입니다. JWT_SIGNING_KEY를 고정하고 서비스를 재시작한 다음, ChatGPT에서 해당 커스텀 MCP를 삭제하고 다시 생성하여 /register를 다시 호출하세요. 로그인만 재시도해도 서버가 알지 못하는 이전 client ID는 복구되지 않습니다.
테스트
uv run pytestThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for AI access to Swagger by SmartBear.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/beaconfire-projects/mcp-oauth-test'
If you have feedback or need assistance with the MCP directory API, please join our Discord server