Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ CORS_ORIGINS=
# ── MCP Server ───────────────────────────────────────────────────────────────
MCP_PORT=8001
CORTEX_API_URL=http://localhost:8000

# Required whenever ENVIRONMENT=production (see mcp/Dockerfile). Without it,
# the MCP server refuses all tool calls rather than trusting the legacy
# X-Cortex-Roles header, which would let any process with MCP env access
# escalate to admin/gdpr_officer.
CORTEX_API_KEY=

# ── Grafana ──────────────────────────────────────────────────────────────────
Expand Down
6 changes: 6 additions & 0 deletions mcp/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ COPY server.js ./

ENV CORTEX_API_URL=http://api:8000

# CORTEX_API_KEY is required whenever ENVIRONMENT=production. Without it, the
# MCP server refuses all tool calls instead of falling back to the legacy
# X-Cortex-Roles header (see mcp/server.js and .env.example).
ENV ENVIRONMENT=production
ENV CORTEX_API_KEY=

CMD ["npm", "start"]
16 changes: 16 additions & 0 deletions mcp/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Resolve MCP auth configuration from the environment.
*
* In production, the legacy `X-Cortex-Roles` header (trusted only in the
* API's open/dev mode) is a privilege-escalation vector: any process with
* MCP env access could claim `admin`/`gdpr_officer` without a real key. So
* MCP tool calls are refused outright when `ENVIRONMENT=production` and no
* `CORTEX_API_KEY` is configured, rather than silently falling back to the
* role header.
*/
export function resolveMcpAuth(env = process.env) {
const environment = (env.ENVIRONMENT ?? "development").trim().toLowerCase();
const apiKey = (env.CORTEX_API_KEY ?? "").trim();
const requireApiKey = environment === "production";
return { environment, apiKey, requireApiKey, blocked: requireApiKey && !apiKey };
}
Loading
Loading