Client Setup¶
This guide covers configuring MCP clients to connect to Django Admin MCP.
MCP Client¶
Any MCP-compatible client can interact with Django Admin MCP.
Project Configuration (Claude Code)¶
Create .mcp.json in your project root:
{
"mcpServers": {
"django-admin": {
"type": "http",
"url": "http://localhost:8000/mcp/",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
}
}
}
Project-Specific Tokens
Use project configuration for project-specific tokens. Add .mcp.json to .gitignore to avoid committing tokens.
Multiple Servers¶
Configure multiple Django projects:
{
"mcpServers": {
"blog-admin": {
"type": "http",
"url": "http://localhost:8000/mcp/",
"headers": {
"Authorization": "Bearer BLOG_TOKEN"
}
},
"shop-admin": {
"type": "http",
"url": "http://localhost:8001/mcp/",
"headers": {
"Authorization": "Bearer SHOP_TOKEN"
}
}
}
}
Applying Configuration¶
After editing the configuration:
- Restart your MCP client
- The MCP server should connect automatically
- Tools will be available for use
Verifying Connection¶
Ask the agent to list available tools:
User: What Django admin tools are available?
Agent: [calls tools/list]
I have access to the following Django admin tools:
- find_models: Discover available Django models
- list_article: List Article instances
- get_article: Get a single Article
...
Other MCP Clients¶
Django Admin MCP works with any MCP-compatible client that supports HTTP transport.
Web Clients (claude.ai, ChatGPT)¶
Web custom connectors register a URL and authenticate over OAuth. They have no field for a static Authorization header, so the header route cannot be used from them. Put the token in the URL instead:
Then register the token-bearing URL as the connector's server URL:
The endpoint behaves exactly like /mcp/ — same handshake, same tools, same permission checks.
Mint a dedicated token for this
The token is now part of the URL, so it lands in access logs and browser history. Create a separate token for the URL route with the narrowest permissions it needs and an expires_at, so revoking it doesn't disturb your header-authenticated clients. See MCP_ALLOW_URL_TOKEN.
Generic HTTP Client¶
The endpoint speaks JSON-RPC 2.0: tools/call takes name and arguments nested under params. Test with curl:
# Initialize (MCP handshake)
curl -X POST http://localhost:8000/mcp/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "initialize"}'
# List available tools
curl -X POST http://localhost:8000/mcp/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'
# Call a tool
curl -X POST http://localhost:8000/mcp/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {"name": "find_models", "arguments": {}}
}'
The server also supports prompts/list, prompts/get, resources/list, resources/templates/list, and resources/read — see Prompts & Resources.
Python Client¶
Using the requests library:
import requests
BASE_URL = "http://localhost:8000/mcp/"
TOKEN = "your-token-here"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
# List tools
response = requests.post(
BASE_URL,
headers=headers,
json={"jsonrpc": "2.0", "id": 1, "method": "tools/list"},
)
tools = response.json()["result"]["tools"]
# Call a tool
response = requests.post(
BASE_URL,
headers=headers,
json={
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {"name": "list_article", "arguments": {"limit": 10}},
},
)
result = response.json()["result"] # {"content": [{"type": "text", "text": "<json>"}]}
JavaScript/TypeScript Client¶
const BASE_URL = "http://localhost:8000/mcp/";
const TOKEN = "your-token-here";
async function callTool(name: string, args: object = {}) {
const response = await fetch(BASE_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: { name, arguments: args },
}),
});
const body = await response.json();
return body.result; // {"content": [{"type": "text", "text": "<json>"}]}
}
// Usage
const articles = await callTool("list_article", { limit: 10 });
Environment-Specific Setup¶
Development¶
{
"mcpServers": {
"django-admin": {
"type": "http",
"url": "http://localhost:8000/mcp/",
"headers": {
"Authorization": "Bearer DEV_TOKEN"
}
}
}
}
Staging/Production¶
{
"mcpServers": {
"django-admin": {
"type": "http",
"url": "https://staging.example.com/mcp/",
"headers": {
"Authorization": "Bearer STAGING_TOKEN"
}
}
}
}
Production Security
Always use HTTPS in production to protect tokens in transit.
Troubleshooting¶
Connection Refused¶
- Verify Django server is running
- Check the URL and port are correct —
curl http://localhost:8000/mcp/health/should return{"status": "ok", "service": "django-admin-mcp"}without a token - Ensure no firewall is blocking the connection
Authentication Failed¶
- Verify the token is correct
- Check the token is active (
is_active=True) - Ensure the token hasn't expired
Unauthorized with MCP Inspector (OAuth discovery 404s)¶
If you connect with npx @modelcontextprotocol/inspector and see a 401 on
/mcp/ followed by requests to /.well-known/oauth-protected-resource,
/.well-known/oauth-authorization-server, and /register returning 404:
Unauthorized: /mcp/
Not Found: /.well-known/oauth-protected-resource
Not Found: /.well-known/oauth-authorization-server
Not Found: /register
This is expected. Django Admin MCP uses static Bearer tokens, not OAuth —
after a 401, the Inspector automatically tries OAuth discovery, which this
server doesn't implement. To fix it, pass the token explicitly:
- In the Inspector sidebar, select transport Streamable HTTP and enter
your server URL (e.g.
http://localhost:8000/mcp/) - Open Authentication and set Header Name to
Authorizationand Bearer Token to your token (mcp_...) - Click Connect
The /.well-known/* 404 messages disappear once the Bearer token is sent
with each request.
Permission Denied¶
Tool calls that fail a permission check return HTTP 200 with an error object inside the JSON-RPC result:
- The token lacks the required permission, or its linked user does (the user caps the token)
- Grant the permission to the token (via its
permissionsorgroupsfields in the MCP Token admin) and make sure the linked user holds it too
No Tools Available¶
tools/list always includes find_models, even with zero exposed models — so a truly empty tool list means the request itself failed. If only find_models appears:
- No models have
MCPAdminMixinwithmcp_expose = True - Check your admin configuration
Next Steps¶
- Tools Overview — Learn about available tools
- Examples — See example interactions