Skip to content

feat: add MCP server endpoint with OAuth 2.0 authentication#1014

Open
srtab wants to merge 7 commits intomainfrom
claude/mcp-endpoint-auth-NdEni
Open

feat: add MCP server endpoint with OAuth 2.0 authentication#1014
srtab wants to merge 7 commits intomainfrom
claude/mcp-endpoint-auth-NdEni

Conversation

@srtab
Copy link
Copy Markdown
Owner

@srtab srtab commented Apr 3, 2026

Expose a remote MCP (Model Context Protocol) server at /mcp/ that MCP
clients like Claude Code can connect to. Authentication uses OAuth 2.1
with PKCE via django-oauth-toolkit, with browser-based login through
the existing allauth flow (GitHub/GitLab/email).

New components:

  • mcp_server app: FastMCP server with submit_job, get_job_status, and
    list_repositories tools
  • OAuth2 middleware: Bearer token validation for MCP requests
  • OAuth metadata discovery: /.well-known/oauth-authorization-server
  • Dynamic client registration: POST /oauth/register/ (RFC 7591)
  • ASGI routing: /mcp/* dispatched to MCP server, rest to Django

claude and others added 2 commits April 3, 2026 07:50
Expose a remote MCP (Model Context Protocol) server at /mcp/ that MCP
clients like Claude Code can connect to. Authentication uses OAuth 2.1
with PKCE via django-oauth-toolkit, with browser-based login through
the existing allauth flow (GitHub/GitLab/email).

New components:
- mcp_server app: FastMCP server with submit_job, get_job_status, and
  list_repositories tools
- OAuth2 middleware: Bearer token validation for MCP requests
- OAuth metadata discovery: /.well-known/oauth-authorization-server
- Dynamic client registration: POST /oauth/register/ (RFC 7591)
- ASGI routing: /mcp/* dispatched to MCP server, rest to Django

https://claude.ai/code/session_017YfDWNCnbPsdbVJZ9t4XV4
- Add proper type annotations to ASGI app and auth middleware
- Add OAuth token scope validation and DB error handling
- Fix broken test_server.py tests (.fn attribute doesn't exist)
- Add transaction=True to async DB tests in test_auth.py
- Make list_repositories async to avoid blocking the event loop
- Remove redundant RepoClient.create_instance() in NotImplementedError handler
- Remove unused conf.py (ENABLED flag was never checked)
- Validate redirect_uris entries are strings in client registration
- Add lifespan startup/shutdown error logging in ASGI app
- Add MCP endpoint documentation and Nginx rate limiting guide
- Add custom OAuth authorize page matching DAIV design system
@srtab srtab self-assigned this Apr 3, 2026
srtab added 5 commits April 3, 2026 21:20
…fy ASGI

- Move oauth_register_client to Django Ninja router with Pydantic
  schemas, AnonRateThrottle (5/m), and automatic validation
- Use django.urls.reverse() in oauth_metadata instead of hardcoded paths
- Simplify ASGI app by delegating lifespan to MCP Starlette app
- Fix scope validation to use allow_scopes() instead of substring check
- Nest NotImplementedError retry inside outer except Exception block
- Add logging around Application.objects.create in registration
- Remove redundant Nginx rate limiting docs (app-level throttle suffices)
Add optional `wait` parameter to both MCP tools that polls until the
job completes (up to 10 minutes), returning the full result inline.
Eliminates the need for clients to manually poll get_job_status.

Also fixes duplicate CHANGELOG sections, stale Django docs URL,
incorrect OAuth registration path in docs, and adds tests for
previously uncovered error branches (DB exceptions during polling,
timeout with job never found).
Restructure around quick-start setup for Claude Code, Cursor, and Codex
CLI. Remove internal OAuth details, security considerations, and rate
limiting sections. Add usage examples with natural-language prompts.
Claude Code SDK expects client_secret to be absent (not null) for
public clients. Use a model_serializer to strip None fields from the
registration response JSON.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants