Skip to content

feat: implement HTTP transport with per-request authentication, dynam…#696

Merged
ashwin31 merged 1 commit into
masterfrom
dev
Jun 2, 2026
Merged

feat: implement HTTP transport with per-request authentication, dynam…#696
ashwin31 merged 1 commit into
masterfrom
dev

Conversation

@ashwin31

@ashwin31 ashwin31 commented Jun 2, 2026

Copy link
Copy Markdown
Member

…ic client resolution, and ASGI integration.

Summary by CodeRabbit

New Features

  • MCP server now supports HTTP transport mode alongside the default stdio mode
  • Configurable hosting options: host, port, and path parameters for HTTP servers
  • Per-request Bearer token authentication for HTTP mode
  • Multi-user access support with individual request tokens
  • Backward compatible with existing stdio transport mode

Copilot AI review requested due to automatic review settings June 2, 2026 03:24
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e6fe4c33-9abd-4e66-93fc-9c114f0a2128

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab79d7 and cf6d4d8.

⛔ Files ignored due to path filters (1)
  • backend/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • backend/crm/asgi.py
  • backend/pyproject.toml
  • mcp_server/README.md
  • mcp_server/src/bcrm_mcp/auth.py
  • mcp_server/src/bcrm_mcp/config.py
  • mcp_server/src/bcrm_mcp/server.py
  • mcp_server/tests/test_auth.py
  • mcp_server/tests/test_config.py
  • mcp_server/tests/test_resolver.py

📝 Walkthrough

Walkthrough

The PR adds HTTP transport support to the MCP server alongside the existing stdio mode. It introduces per-request bearer-token authentication for HTTP, extends configuration to support transport-specific environment variables, implements request-aware client resolution (fresh clients per HTTP request, cached for stdio), mounts the MCP server at /mcp in Django's ASGI layer with authorization gating, and provides optional dependency setup with updated documentation.

Changes

HTTP Transport Support for MCP Server

Layer / File(s) Summary
HTTP Bearer Token Authentication
mcp_server/src/bcrm_mcp/auth.py, mcp_server/tests/test_auth.py
New AuthError exception and extract_bearer_token(headers) function safely parse Authorization headers for Bearer-scheme tokens, returning token or None without raising. Tests verify extraction, case-insensitive scheme matching, whitespace trimming, and invalid-input handling.
Transport Configuration & Environment Validation
mcp_server/src/bcrm_mcp/config.py, mcp_server/tests/test_config.py
Configuration adds STDIO and HTTP transport constants, extends Settings with optional token, transport, host, port, and path fields. Settings.from_env() now validates BCRM_TRANSPORT, enforces transport-specific BCRM_TOKEN rules (required for stdio, forbidden for http), parses integer port, and reads optional host/path. Comprehensive tests validate all required fields, token enforcement, case-insensitive parsing, slash stripping, and error cases.
Transport-Aware Client Resolution
mcp_server/tests/test_resolver.py
Tests verify ClientResolver behaves differently per transport: HTTP mode creates fresh CrmClient per get() call with bearer token from request headers (no caching, prevents cross-request leakage), stdio mode loads settings once and caches a single client across calls. Tests also confirm build_http_app() returns ASGI-mountable app with lifespan and HTTP auth validation raises AuthError on missing/invalid tokens.
Django ASGI Integration with MCP Path Routing
backend/crm/asgi.py
Updated ASGI entrypoint uses _build_application() wrapper that conditionally mounts MCP at /mcp when BCRM_MCP_ENABLED is set and bcrm_mcp is available. Router intercepts /mcp and /mcp/... paths for HTTP/websocket, extracts Bearer token, rejects missing/invalid tokens with 401 JSON or websocket close, forwards authorized requests to MCP app, and routes other traffic to Django.
Project Dependencies and Documentation
backend/pyproject.toml, mcp_server/README.md
Added optional mcp dependency sourced from local editable ../mcp_server path. Updated README documents two transport modes, environment variable requirements per mode (token required for stdio, forbidden for http), HTTP hosting config (BCRM_HOST, BCRM_PORT, BCRM_PATH), and updated module layout to include new auth.py.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 A server hops through two modes, now with HTTP cheer—
Request-bound tokens flow when distant clients draw near,
Cached for stdio's path, fresh per HTTP call,
Django guards the gateway at /mcp, standing tall! 🎭

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ashwin31 ashwin31 merged commit f44fcaf into master Jun 2, 2026
5 of 7 checks passed
@ashwin31 ashwin31 deleted the dev branch June 2, 2026 03:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an HTTP transport mode for the BottleCRM MCP server with strict per-request bearer-token authentication, plus an optional ASGI mount inside the Django app so clients can connect remotely at /mcp without a local install.

Changes:

  • Implement http transport with per-request Authorization: Bearer <pat> auth and dynamic client resolution (no cross-request client caching).
  • Add build_http_app() and wire an optional /mcp mount into backend/crm/asgi.py (guarded by BCRM_MCP_ENABLED and optional dependency install).
  • Expand configuration (BCRM_TRANSPORT, host/port/path) and add pytest coverage for auth, config parsing, and resolver behavior.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
mcp_server/tests/test_resolver.py Tests resolver behavior: injected client precedence, per-request HTTP auth, stdio caching, and build_http_app() lifespan.
mcp_server/tests/test_config.py Tests env parsing/validation for stdio vs http transport (token requirements, port parsing, invalid transport).
mcp_server/tests/test_auth.py Tests bearer-token extraction logic (case/whitespace handling, missing/invalid headers).
mcp_server/src/bcrm_mcp/server.py Adds ClientResolver, HTTP header dependency plumbing, build_http_app(), and main() http/stdio transport selection.
mcp_server/src/bcrm_mcp/config.py Extends settings to support transport selection and http serving parameters; validates env combinations.
mcp_server/src/bcrm_mcp/auth.py Introduces per-request bearer token extraction and AuthError.
mcp_server/README.md Documents stdio vs http transports, hosted usage, env vars, and client configuration.
backend/pyproject.toml Adds optional mcp extra and local editable source mapping for bcrm-mcp.
backend/crm/asgi.py Optionally mounts MCP server at /mcp under ASGI with edge auth and lifespan forwarding.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 3 to 5
Wraps the plain async tool functions in ``bcrm_mcp.tools`` as FastMCP tools and
exposes a ``build_server(client=None)`` factory plus a ``main()`` console entry
point (the ``bcrm-mcp`` script points at ``bcrm_mcp.server:main``).
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