Skip to content

feat: Global variable passthrough in MCP Projects SSE#9890

Merged
edwinjosechittilappilly merged 1 commit into
mainfrom
global-env-passthrough
Sep 16, 2025
Merged

feat: Global variable passthrough in MCP Projects SSE#9890
edwinjosechittilappilly merged 1 commit into
mainfrom
global-env-passthrough

Conversation

@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator

@edwinjosechittilappilly edwinjosechittilappilly commented Sep 16, 2025

This pull request introduces support for passing per-request variables from HTTP headers into the backend execution context. These variables, extracted from headers prefixed with X-LANGFLOW-GLOBAL-VAR-*, are now injected into the context for project-related SSE and message handling endpoints, enabling more dynamic and customizable request processing.

Request variable extraction and context management

  • Added logic to extract variables from HTTP headers with the prefix X-LANGFLOW-GLOBAL-VAR-* in both handle_project_sse and handle_project_messages, storing them in a new context variable for each request. [1] [2]
  • Ensured proper resetting of the new request variables context at the end of request handling to avoid leakage between requests. [1] [2]
  • Introduced current_request_variables_ctx as a new ContextVar to hold these per-request variables, with a default of None.

Integration with tool execution

  • Modified handle_call_tool and related functions to include the extracted request variables in the execution context, allowing downstream processing to access them. [1] [2]

Summary by CodeRabbit

  • New Features
    • Support passing request-scoped variables via HTTP headers (e.g., X-Langflow-Global-Var-*) to customize flow and tool execution per request.
    • Works across both streaming (SSE) and message endpoints.
    • Variables are automatically cleared after each request to prevent cross-request leakage.

…SE handling

- Introduced `current_request_variables_ctx` to manage per-request variables injected via HTTP headers.
- Updated `handle_project_sse` and `handle_project_messages` to extract variables prefixed with `X-LANGFLOW-GLOBAL-VAR-*` from request headers.
- Enhanced error handling for variable extraction failures with logging for better debugging.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 16, 2025

Walkthrough

Adds per-request header-driven variables via a new ContextVar and propagates them into flow execution. Endpoints extract X-Langflow-Global-Var-* headers, set/reset the context var during request/SSE handling, and mcp_utils reads it to pass a context dict to simple_run_flow in handle_call_tool.

Changes

Cohort / File(s) Summary
Request-scoped variables context (definition and propagation)
src/backend/base/langflow/api/v1/mcp_utils.py
Adds current_request_variables_ctx: ContextVar[dict[str, str] | None]. handle_call_tool reads it and, if present, builds exec_context = {"request_variables": request_variables} and passes it as context to simple_run_flow. No other control-flow changes.
Header extraction and lifecycle in API endpoints
src/backend/base/langflow/api/v1/mcp_projects.py
Imports current_request_variables_ctx. In handle_project_sse and handle_project_messages, scans request.headers for keys prefixed with x-langflow-global-var- (case-insensitive), uppercases var names, stores dict in context via .set(...), and resets in finally. Logs exceptions on parsing but continues.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant API as mcp_projects.handle_project_messages
  participant Ctx as current_request_variables_ctx
  participant Util as mcp_utils.handle_call_tool
  participant Flow as simple_run_flow

  C->>API: POST /... (headers X-Langflow-Global-Var-*)
  API->>API: Extract headers, build {VAR: value}
  API->>Ctx: set(variables)
  note right of API: Variables available to downstream calls
  API->>Util: handle_call_tool(...)
  Util->>Ctx: get() -> variables
  Util->>Util: exec_context = {"request_variables": vars} or None
  Util->>Flow: simple_run_flow(..., context=exec_context)
  Flow-->>Util: result
  Util-->>API: result
  API-->>C: response
  API->>Ctx: reset() in finally
Loading
sequenceDiagram
  autonumber
  participant C as Client
  participant API as mcp_projects.handle_project_sse
  participant Ctx as current_request_variables_ctx
  participant Stream as SSE stream
  participant Util as mcp_utils.handle_call_tool

  C->>API: GET /.../sse (headers X-Langflow-Global-Var-*)
  API->>API: Extract headers, build {VAR: value}
  API->>Ctx: set(variables)
  API-->>C: Open SSE stream
  loop Events
    API->>Util: handle_call_tool(...) as events occur
    Util->>Ctx: get() -> variables
    Util-->>API: event payload
    API-->>Stream: send event
  end
  API->>Ctx: reset() in finally
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • phact
  • lucaseduoli
  • ogabrielluiz

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely describes the primary change—adding global-variable passthrough for MCP project SSE endpoints—so it is directly related to the main enhancement. The changeset also applies the same header-extraction and propagation to project message (POST) handling and introduces a ContextVar in mcp_utils, making the title slightly narrower than the full scope but still an accurate summary of the primary intent.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch global-env-passthrough

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 16, 2025
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
68.6% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator Author

Example MCP Server JSON:

{
  "mcpServers": {
    "lf-test": {
      "command": "uvx",
      "args": [
        "mcp-proxy",
        "--headers", "x-api-key", "sk-xxxxxxxx",
        "--headers", "X-Langflow-Global-Var-OPENAI_API_KEY", "sk-xxxxxxxx",
        "http://localhost:7861/api/v1/mcp/project/8969e510-f995-4e04-b9eb-eb62eee956c2/sse"
      ]
    }
  }
}

@edwinjosechittilappilly edwinjosechittilappilly marked this pull request as ready for review September 16, 2025 20:24
@edwinjosechittilappilly
Copy link
Copy Markdown
Collaborator Author

@coderabbitai

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 16, 2025

Tip

For best results, initiate chat on the files or code changes.

@edwinjosechittilappilly Thank you for sharing this example MCP Server JSON configuration! This is an excellent demonstration of how the global variable passthrough feature implemented in this PR would be used in practice.

The configuration perfectly showcases the key aspects of the new functionality:

  1. Header Format: The X-Langflow-Global-Var-OPENAI_API_KEY header follows the exact prefix pattern (X-LANGFLOW-GLOBAL-VAR-*) that the PR implementation extracts and processes.

  2. Integration Point: The endpoint URL http://localhost:7861/api/v1/mcp/project/.../sse matches the SSE endpoint where the header extraction logic was implemented.

  3. Practical Use Case: This shows how external MCP clients can dynamically pass API keys and other variables per-request, which will then be available in the Langflow execution context.

This example validates that the implementation correctly addresses the real-world need for dynamic variable injection from external MCP clients, making the system more flexible and secure by allowing per-request customization without hardcoding sensitive values.

The design choice to use HTTP headers with a specific prefix pattern makes it easy for MCP proxy tools like mcp-proxy to forward these variables seamlessly to Langflow.

ฅ(^◡^)ฅ

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Sep 16, 2025
Copy link
Copy Markdown
Collaborator

@lucaseduoli lucaseduoli left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Sep 16, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/backend/base/langflow/api/v1/mcp_utils.py (1)

179-182: Prefer a consistent context shape (avoid None).

Always pass a dict to downstream callers to simplify handling and avoid None checks later.

Apply this diff:

-    request_variables = current_request_variables_ctx.get()
-    exec_context = {"request_variables": request_variables} if request_variables else None
+    request_variables = current_request_variables_ctx.get()
+    exec_context = {"request_variables": request_variables or {}}
src/backend/base/langflow/api/v1/mcp_projects.py (2)

270-282: Normalize header suffix and ignore empty values; also consider bounds.

  • Map hyphens to underscores so both X-...-OPENAI-API-KEY and X-...-OPENAI_API_KEY normalize to the same key.
  • Trim values and skip empties to avoid accidental blanks.
  • Minor hardening: consider bounding the number/size of accepted headers to prevent abuse.

Apply this diff:

-    variables: dict[str, str] = {}
-    header_prefix = "x-langflow-global-var-"
+    variables: dict[str, str] = {}
+    header_prefix = "x-langflow-global-var-"
     try:
         for header_name, header_value in request.headers.items():
             header_lower = header_name.lower()
             if header_lower.startswith(header_prefix):
-                var_name = header_lower[len(header_prefix) :].upper()
-                variables[var_name] = header_value
+                raw = header_lower[len(header_prefix) :]
+                var_name = raw.replace("-", "_").upper()
+                value = header_value.strip()
+                if value:
+                    variables[var_name] = value
     except Exception:  # noqa: BLE001
         await logger.aexception("Failed to parse request variables from headers for project %s", project_id)

Optional follow-up: extract this parsing into a tiny helper to remove duplication with the POST path. I can draft it if you want.


323-335: Mirror normalization for POST path.

Keep header parsing consistent with the SSE path: normalize name and trim/skip empty values.

Apply this diff:

-    variables: dict[str, str] = {}
-    header_prefix = "x-langflow-global-var-"
+    variables: dict[str, str] = {}
+    header_prefix = "x-langflow-global-var-"
     try:
         for header_name, header_value in request.headers.items():
             header_lower = header_name.lower()
             if header_lower.startswith(header_prefix):
-                var_name = header_lower[len(header_prefix) :].upper()
-                variables[var_name] = header_value
+                raw = header_lower[len(header_prefix) :]
+                var_name = raw.replace("-", "_").upper()
+                value = header_value.strip()
+                if value:
+                    variables[var_name] = value
     except Exception:  # noqa: BLE001
         await logger.aexception("Failed to parse request variables from headers for project %s", project_id)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0ef8b and 62f1463.

📒 Files selected for processing (2)
  • src/backend/base/langflow/api/v1/mcp_projects.py (5 hunks)
  • src/backend/base/langflow/api/v1/mcp_utils.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/base/langflow/api/v1/mcp_projects.py
  • src/backend/base/langflow/api/v1/mcp_utils.py
🔇 Additional comments (5)
src/backend/base/langflow/api/v1/mcp_utils.py (2)

35-38: Per-request ContextVar introduction — LGTM

The new current_request_variables_ctx is well-scoped with a safe default of None. Good foundation for request‑scoped propagation.


233-239: simple_run_flow accepts context (no change required).

Signature is async def simple_run_flow(..., context: dict | None = None) (src/backend/base/langflow/api/v1/endpoints.py). mcp_utils.py builds exec_context = {"request_variables": ...} or None and Graph/components consume request_variables, so the call is compatible.

src/backend/base/langflow/api/v1/mcp_projects.py (3)

29-37: Import of request‑variables context — LGTM

Importing current_request_variables_ctx here is appropriate for per-request propagation.


308-309: Context reset — LGTM

Resetting current_request_variables_ctx in finally prevents leakage across requests.


345-346: Context reset — LGTM

Good symmetry with the SSE path; prevents cross-request contamination.

@edwinjosechittilappilly edwinjosechittilappilly added this pull request to the merge queue Sep 16, 2025
Merged via the queue into main with commit 859f8da Sep 16, 2025
22 of 23 checks passed
@edwinjosechittilappilly edwinjosechittilappilly deleted the global-env-passthrough branch September 16, 2025 20:58
lucaseduoli pushed a commit that referenced this pull request Sep 17, 2025
feat: add request-level variable extraction from headers in project SSE handling

- Introduced `current_request_variables_ctx` to manage per-request variables injected via HTTP headers.
- Updated `handle_project_sse` and `handle_project_messages` to extract variables prefixed with `X-LANGFLOW-GLOBAL-VAR-*` from request headers.
- Enhanced error handling for variable extraction failures with logging for better debugging.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants