feat: Update .env.example and server.py to clarify Frappe credentials handling for different deployment modes

This commit is contained in:
MOHAN 2026-04-21 21:00:33 +05:30
parent c051804170
commit 7289a91b66
2 changed files with 43 additions and 26 deletions

View File

@ -1,25 +1,37 @@
# ══════════════════════════════════════════════════════════════════════════════
# DEPLOYMENT MODE
# THREE SUPPORTED MODES
# ══════════════════════════════════════════════════════════════════════════════
#
# SSE / VPS mode (hosted server — recommended):
# Frappe credentials are NOT stored here. Each user passes their own
# X-Frappe-URL, X-Frappe-API-Key, X-Frappe-API-Secret headers when connecting.
# Only set MCP_HOST, MCP_PORT, MCP_BEARER_TOKEN below.
# MODE 1 — Local / stdio (single user, your machine)
# Run: frappe-mcp
# Config: Set FRAPPE_URL + credentials below.
# Claude Desktop spawns the process directly via stdio.
#
# Local / stdio mode:
# Credentials are read from this file. Run: frappe-mcp (no --sse flag).
# Uncomment the Frappe Connection block below.
# MODE 2 — VPS / SSE, multi-tenant (public hosted server)
# Run: frappe-mcp --sse
# Config: Set only MCP_HOST, MCP_PORT, MCP_BEARER_TOKEN here.
# Each connecting user supplies their own Frappe credentials as
# request headers: X-Frappe-URL, X-Frappe-API-Key, X-Frappe-API-Secret
# No Frappe credentials are stored on the server.
#
# ── SSE Server Settings (VPS hosting) ────────────────────────────────────────
# MODE 3 — VPS / SSE, single-tenant (you host it for yourself)
# Run: frappe-mcp --sse
# Config: Set BOTH the MCP server settings AND Frappe credentials here.
# Users connect without sending credential headers — the server's
# .env credentials are used for everyone.
#
# ── SSE Server Settings (modes 2 & 3) ────────────────────────────────────────
MCP_HOST=0.0.0.0
MCP_PORT=8001
# Shared access token — all users must send this as: Authorization: Bearer <token>
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
# Shared access token — clients must send: Authorization: Bearer <token>
# Generate: python -c "import secrets; print(secrets.token_hex(32))"
MCP_BEARER_TOKEN=change_this_to_a_strong_random_token
# ── Frappe Connection (local/stdio mode only) ─────────────────────────────────
# ── Frappe Connection (modes 1 & 3) ──────────────────────────────────────────
# Required for local stdio mode (mode 1).
# Optional for SSE mode — set these only if you want a single fixed Frappe
# instance for all connections (mode 3). Leave commented for multi-tenant (mode 2).
# FRAPPE_URL=http://YOUR_VPS_IP:8000
# FRAPPE_API_KEY=your_api_key_here
# FRAPPE_API_SECRET=your_api_secret_here

View File

@ -83,18 +83,22 @@ def _run_sse():
if auth != f"Bearer {bearer_token}":
return Response("Unauthorized", status_code=401)
# Extract per-user Frappe credentials from request headers
# Per-user Frappe credentials via request headers (optional).
# If omitted, FrappeClient falls back to .env values — useful when the
# server owner is the only user, or for a single-tenant VPS deployment.
frappe_url = request.headers.get("X-Frappe-URL", "")
api_key = request.headers.get("X-Frappe-API-Key", "")
api_secret = request.headers.get("X-Frappe-API-Secret", "")
site_name = request.headers.get("X-Frappe-Site-Name", "")
if not frappe_url or not api_key or not api_secret:
if frappe_url or api_key or api_secret:
# At least one header present — require all three to be explicit
if not (frappe_url and api_key and api_secret):
return Response(
"Missing required headers: X-Frappe-URL, X-Frappe-API-Key, X-Frappe-API-Secret",
"Partial credentials: supply all three headers together — "
"X-Frappe-URL, X-Frappe-API-Key, X-Frappe-API-Secret",
status_code=400,
)
from frappe_mcp.session import SessionConfig, set_session
set_session(SessionConfig(
frappe_url=frappe_url,
@ -102,6 +106,7 @@ def _run_sse():
api_secret=api_secret,
site_name=site_name,
))
# else: no headers — FrappeClient will use .env credentials
async with sse.connect_sse(
request.scope, request.receive, request._send