Django views that wrap MCP stdio servers and expose them over Streamable HTTP
Project description
django-mcp-wrapper
Django views that wrap MCP stdio servers and expose them over Streamable HTTP.
Installation
pip install django-mcp-wrapper
For OAuth 2.0 support (Claude for Web, dynamic client registration):
pip install django-mcp-wrapper[oauth]
Quick Start
Define a wrapper class and mount it at a URL path:
# mcp_wrappers.py
from django_mcp_wrapper import StdioMcpWrapper
class FileSystemMcp(StdioMcpWrapper):
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
# urls.py
from django.urls import path
from .mcp_wrappers import FileSystemMcp
urlpatterns = [
path("mcp", FileSystemMcp.as_view()),
]
Override get_command(), get_args(), or get_env() for per-request customization:
class DynamicMcp(StdioMcpWrapper):
command = "npx"
def get_args(self):
directory = os.environ.get("MCP_DIR", os.getcwd())
return ["-y", "@modelcontextprotocol/server-filesystem", directory]
Mount multiple wrappers at different paths:
urlpatterns = [
path("desktop/mcp", DesktopMcp.as_view()),
path("project/mcp", ProjectMcp.as_view()),
]
Authentication
API Key
Override authenticate() to add request-level auth. Return None to allow
the request, or an HttpResponse to reject it:
class SecureMcp(StdioMcpWrapper):
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
def authenticate(self, request):
valid_keys = {"my-secret-key"}
if request.GET.get("apiKey") not in valid_keys:
return HttpResponse("Invalid API key", status=401)
return None
See examples/apikey/ for a full working example.
OAuth 2.0 with Dynamic Client Registration (Claude for Web)
For MCP clients that use OAuth (like Claude for Web), django-mcp-wrapper
provides RFC 9728 protected resource metadata and bearer token validation,
with RFC 7591 dynamic client registration via
django-oauth-toolkit-dcr,
all backed by django-oauth-toolkit:
# mcp_wrappers.py
from django_mcp_wrapper import StdioMcpWrapper
from django_mcp_wrapper.oauth import bearer_token_authenticate
class OAuthMcp(StdioMcpWrapper):
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
def authenticate(self, request):
return bearer_token_authenticate(request)
# urls.py
from django_mcp_wrapper.oauth import oauth_urlpatterns
urlpatterns = [
path("mcp", OAuthMcp.as_view()),
*oauth_urlpatterns(
resource_url="https://yourserver.com/mcp",
authorization_server_url="https://yourserver.com/o",
),
]
This wires up:
/.well-known/oauth-protected-resource/mcp— resource metadata (RFC 9728)/o/register/— dynamic client registration (RFC 7591, viadjango-oauth-toolkit-dcr)/o/authorize/,/o/token/— authorization code + PKCE flow (django-oauth-toolkit)
See examples/oauth/ for a full working example with settings.
Development
cd django-mcp-wrapper
python -m venv venv
source venv/bin/activate
pip install -e '.[dev]'
python -m pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_mcp_wrapper-0.1.tar.gz.
File metadata
- Download URL: django_mcp_wrapper-0.1.tar.gz
- Upload date:
- Size: 14.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31f3064b508460d128a0de08d0fc573067ad2a7ce89f84300b6ca835d519e036
|
|
| MD5 |
543db8b5e8fc6fad084a2f05057b04db
|
|
| BLAKE2b-256 |
094bb338e73a6041a2a1cd8c748af19800f8ebf87ca3b6e917a7693002853104
|
Provenance
The following attestation bundles were made for django_mcp_wrapper-0.1.tar.gz:
Publisher:
publish.yml on player1537-playground/django-mcp-wrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_mcp_wrapper-0.1.tar.gz -
Subject digest:
31f3064b508460d128a0de08d0fc573067ad2a7ce89f84300b6ca835d519e036 - Sigstore transparency entry: 2256670464
- Sigstore integration time:
-
Permalink:
player1537-playground/django-mcp-wrapper@711a8d345301050536471a55c77567c8c444e9e1 -
Branch / Tag:
refs/tags/v0.1 - Owner: https://github.com/player1537-playground
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@711a8d345301050536471a55c77567c8c444e9e1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_mcp_wrapper-0.1-py3-none-any.whl.
File metadata
- Download URL: django_mcp_wrapper-0.1-py3-none-any.whl
- Upload date:
- Size: 13.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59806420b4fe50290292b7af30354df06789fc4a043866e7c2b0dcdf68d948a1
|
|
| MD5 |
a4e251c2b092a1ebf07abe0da46d858b
|
|
| BLAKE2b-256 |
eb24a5ff0b09ba51ad0cd36352d6703fb5d0a1c5e9080d50b133918c43e97e56
|
Provenance
The following attestation bundles were made for django_mcp_wrapper-0.1-py3-none-any.whl:
Publisher:
publish.yml on player1537-playground/django-mcp-wrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_mcp_wrapper-0.1-py3-none-any.whl -
Subject digest:
59806420b4fe50290292b7af30354df06789fc4a043866e7c2b0dcdf68d948a1 - Sigstore transparency entry: 2256670470
- Sigstore integration time:
-
Permalink:
player1537-playground/django-mcp-wrapper@711a8d345301050536471a55c77567c8c444e9e1 -
Branch / Tag:
refs/tags/v0.1 - Owner: https://github.com/player1537-playground
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@711a8d345301050536471a55c77567c8c444e9e1 -
Trigger Event:
release
-
Statement type: