Skip to content

fix: Allow REST tweaks to MCP server#10599

Merged
edwinjosechittilappilly merged 25 commits into
langflow-ai:mainfrom
stevehaertel:tweak_mcp_server
Dec 2, 2025
Merged

fix: Allow REST tweaks to MCP server#10599
edwinjosechittilappilly merged 25 commits into
langflow-ai:mainfrom
stevehaertel:tweak_mcp_server

Conversation

@stevehaertel
Copy link
Copy Markdown
Contributor

@stevehaertel stevehaertel commented Nov 14, 2025

Enables tweaks to MCP servers

I have been told that this fix is related to https://datastax.jira.com/browse/LFOSS-2800 but I don't have permission to view that so I don't know if that's true.

  • Edited process.py and mcp_component.py to allow tweak updates to MCP servers
  • Updated test_process.py and test_mcp_component.py for unit tests
  • Added some unrelated fixes to test_embedding_model_component.py and test_language_model_component.py because UTs were failing unless that was fixed.

MCP Server default config
image

Without tweaks: Error
image

With auth tweak: Successfully authenticated 🥳
image

Summary by CodeRabbit

  • New Features

    • MCP field-type handling improved (better file-path and MCP value handling).
    • MCP component now prefers database-stored server config, with value/API configs used as fallbacks.
    • Cache and tool-refresh behavior refined to ensure fresh tooling when cache is disabled.
  • Bug Fixes

    • Safer field-type extraction to avoid errors during tweak application.
  • Tests

    • Added and updated unit tests covering MCP precedence, apply_tweaks behavior, and mock paths.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions Bot added the community Pull Request from an external contributor label Nov 14, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 14, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds field_type-aware tweak handling (including "mcp") in apply_tweaks, updates MCP component logic to prefer provided server configs and refine cache/invalidation, rewrites MCPTools initialization in a starter project file, and updates/extends unit tests and mock patch paths for reorganized modules.

Changes

Cohort / File(s) Summary
Tweak processing
src/backend/base/langflow/processing/process.py, src/backend/tests/unit/test_process.py
Extracts field_type via .get("type", ""); branches for NestedDict, mcp, file, and scalar values; assigns/propagates values accordingly; adds tests validating MCP handling and safe type extraction.
MCP component logic
src/lfx/src/lfx/components/models_and_agents/mcp_component.py, src/backend/tests/unit/components/models_and_agents/test_mcp_component.py
update_tool_list now attempts DB get_server() and falls back to provided server_config_from_value; refines cache invalidation, tool refresh triggers, and rebuilding of tool configs; adds tests for config precedence scenarios using mocks.
Test patch updates
src/backend/tests/unit/components/models_and_agents/test_embedding_model_component.py, src/backend/tests/unit/components/models_and_agents/test_language_model_component.py
Updated mock patch targets to lfx.components.models_and_agents.*; added pragma allowlist comments to api_key assignments in tests.
Starter project metadata / MCPTools rewrite
src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json
Replaced MCPToolsComponent implementation block and updated component code_hash to reflect the rewritten internal logic and initialization/caching behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Process as apply_tweaks()
    participant Template as template_data
    Caller->>Process: call apply_tweaks(tweaks, template_data)
    alt tweak field_type == "NestedDict"
        Process->>Template: validate/repair JSON -> assign to ["value"]
    else tweak field_type == "mcp"
        Process->>Template: assign tweak_value directly -> ["value"]
    else tweak_value is dict
        alt field_type == "file"
            Process->>Template: map keys -> use "file_path" key
        else
            Process->>Template: propagate dict keys into template entry
        end
    else
        alt field_type == "file"
            Process->>Template: set ["file_path"]=tweak_value
        else
            Process->>Template: set ["value"]=tweak_value
        end
    end
    Process-->>Caller: return updated template_data
Loading
sequenceDiagram
    participant Caller
    participant MCP as update_tool_list()
    participant DB as Database
    participant Cache
    Caller->>MCP: call update_tool_list(server_config_from_value, use_cache)
    alt server_config_from_value provided
        MCP->>MCP: use server_config_from_value
    else
        MCP->>DB: get_server()
        alt DB returns server_config
            DB-->>MCP: server_config
        else
            MCP->>MCP: fallback to value or API-fetch path
        end
    end
    alt use_cache == false
        MCP->>Cache: clear server-specific cache
        MCP->>MCP: refresh tools from server_config
    else
        MCP->>Cache: use cached tools if present else fetch
    end
    MCP-->>Caller: return tools/options
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • src/backend/base/langflow/processing/process.py — verify all branches for field_type are correct and don't regress other tweak types.
    • src/lfx/src/lfx/components/models_and_agents/mcp_component.py — ensure DB fallback, cache invalidation, and tool rebuild logic are correct and thread-safe.
    • src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json — large internal rewrite of MCPToolsComponent; validate metadata and consistency with runtime expectations.
    • New/updated tests — confirm mocks/patch targets match refactored module paths.

Possibly related PRs

Suggested labels

size:XL, lgtm

Suggested reviewers

  • lucaseduoli
  • Adam-Aghili

Pre-merge checks and finishing touches

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 4 warnings)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error Tests use improperly configured async mocks (MagicMock instead of AsyncMock) and don't validate all implementation changes, causing runtime TypeErrors and incomplete coverage. Refactor async mocks using AsyncMock for awaitables and @asynccontextmanager for session_scope; validate Pydantic v2 compatibility, tools_metadata whitelist addition, and field_order updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.89% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Test Quality And Coverage ⚠️ Warning TestMCPComponentConfigPriority tests use MagicMock for async dependencies without new_callable=AsyncMock, causing runtime failures when awaiting mocks. Tests for apply_tweaks mentioned in PR summary cannot be located in repository. Apply new_callable=AsyncMock to async function patches, use @asynccontextmanager for session_scope, verify test_process.py tests are committed, and add parametrized tests covering all field_type branches with both success and error scenarios.
Test File Naming And Structure ⚠️ Warning Test file uses correct pytest naming pattern but has critical async mocking deficiencies that cause runtime TypeErrors. Use AsyncMock for async functions and @asynccontextmanager for session_scope; add negative and edge case tests; ensure descriptive test names.
Excessive Mock Usage Warning ⚠️ Warning Test uses 4+ simultaneous patches and mocks async functions as MagicMock instead of AsyncMock, causing runtime failures and obscuring actual component behavior. Extract configuration logic into pure resolve_mcp_config() function, use AsyncMock for async functions, and replace heavy mocking with fixtures to reduce patches from 4+ to 1-2 per test.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: enabling REST tweaks to MCP servers. It matches the primary purpose documented in the PR description and is supported by the changes across process.py and mcp_component.py.

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.

@stevehaertel stevehaertel changed the title Allow REST tweaks to MCP server Fix: Allow REST tweaks to MCP server Nov 14, 2025
@stevehaertel stevehaertel marked this pull request as draft November 14, 2025 23:02
@stevehaertel stevehaertel marked this pull request as ready for review November 14, 2025 23:03
@stevehaertel stevehaertel reopened this Nov 14, 2025
@stevehaertel stevehaertel force-pushed the tweak_mcp_server branch 2 times, most recently from 55fe314 to 34cbdd5 Compare November 14, 2025 23:58
@stevehaertel
Copy link
Copy Markdown
Contributor Author

@edwinjosechittilappilly
@lucaseduoli
@mfortman11
Hi team!

  • I'm having some trouble getting the autofix.ci to update my component index.
  • When I run the playwright tests manually, I get passes.

May I humbly ask for some troubleshooting tips?

@stevehaertel stevehaertel force-pushed the tweak_mcp_server branch 3 times, most recently from 06a381a to 56c4382 Compare November 15, 2025 19:00
@stevehaertel stevehaertel marked this pull request as draft November 16, 2025 01:30
@stevehaertel stevehaertel marked this pull request as ready for review November 16, 2025 01:39
@stevehaertel stevehaertel force-pushed the tweak_mcp_server branch 2 times, most recently from 5b5f837 to 967285c Compare November 16, 2025 20:35
@stevehaertel
Copy link
Copy Markdown
Contributor Author

stevehaertel commented Nov 16, 2025

UPDATE: GOOD NEWS: Got the tests passing

[previous comment below - no longer valid with latest update]

  • While these changes successfully work for what I wanted them to do (can tweak mcp server params from REST call)
  • These changes break the mcp-server.spec.ts test mcp server tools should be refreshed when editing a server

I will need help from the langflow folks on how to proceed.

@stevehaertel
Copy link
Copy Markdown
Contributor Author

Okay I stayed with this for a while and made some more changes and got a green pipeline :)

image

@stevehaertel stevehaertel reopened this Dec 2, 2025
@stevehaertel
Copy link
Copy Markdown
Contributor Author

@coderabbitai Why is git reporting a conflict for src/lfx/src/lfx/_assets/compoent_index.json?

origin/main: SHA256 ce585c481955964169fc6a5f543f5b9ac7a86691659fd50ffd6689d8a52a5590
origin/tweak_mcp_server: SHA256 ce585c481955964169fc6a5f543f5b9ac7a86691659fd50ffd6689d8a52a5590

Are the files not identical?

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 2, 2025

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

echo "=== Checking for component index files (both spellings) ==="
fd -t f "component_index.json" src/lfx/
fd -t f "compoent_index.json" src/lfx/

echo -e "\n=== Git status to see actual conflicts ==="
git status

echo -e "\n=== Checking current branch ==="
git branch --show-current

echo -e "\n=== Looking for merge conflict markers in component_index.json ==="
if [ -f "src/lfx/src/lfx/_assets/component_index.json" ]; then
    echo "File exists: src/lfx/src/lfx/_assets/component_index.json"
    head -50 src/lfx/src/lfx/_assets/component_index.json | grep -E "^<<<<<<<|^=======|^>>>>>>>" || echo "No conflict markers found in first 50 lines"
fi

echo -e "\n=== Checking file SHA256 on current branch ==="
if [ -f "src/lfx/src/lfx/_assets/component_index.json" ]; then
    sha256sum src/lfx/src/lfx/_assets/component_index.json
fi

echo -e "\n=== Comparing with origin/main ==="
git fetch origin main 2>/dev/null || true
git diff origin/main HEAD -- src/lfx/src/lfx/_assets/component_index.json | head -100

echo -e "\n=== Checking if there's a merge in progress ==="
if [ -d .git/MERGE_HEAD ]; then
    echo "Merge in progress"
    cat .git/MERGE_HEAD
else
    echo "No merge in progress"
fi

Length of output: 295710


🏁 Script executed:

#!/bin/bash
set -e

PATH1="src/lfx/src/lfx/_assets/component_index.json"
PATH_TYPO="src/lfx/src/lfx/_assets/compoent_index.json"

echo "=== Verify paths present in repo ==="
if [ -f "$PATH1" ]; then echo "Exists: $PATH1"; fi
if [ -f "$PATH_TYPO" ]; then echo "Exists: $PATH_TYPO"; else echo "Not found (typo path): $PATH_TYPO"; fi

echo -e "\n=== Fetch remote branches ==="
git fetch origin main tweak_mcp_server >/dev/null 2>&1 || true

echo -e "\n=== Compute SHA256 for component_index.json across branches (Python) ==="
python - << 'PYCODE'
import hashlib, subprocess, sys, os, json

def sha256_bytes(b: bytes)->str:
    h=hashlib.sha256(); h.update(b); return h.hexdigest()

path="src/lfx/src/lfx/_assets/component_index.json"

# HEAD
with open(path, "rb") as f:
    head_b=f.read()
print("HEAD:", sha256_bytes(head_b), f"(bytes={len(head_b)})")

# origin/main
try:
    main_b = subprocess.check_output(["git","show",f"origin/main:{path}"])
    print("origin/main:", sha256_bytes(main_b), f"(bytes={len(main_b)})")
except subprocess.CalledProcessError:
    print("origin/main: file not found")

# origin/tweak_mcp_server
try:
    tmc_b = subprocess.check_output(["git","show",f"origin/tweak_mcp_server:{path}"])
    print("origin/tweak_mcp_server:", sha256_bytes(tmc_b), f"(bytes={len(tmc_b)})")
except subprocess.CalledProcessError:
    print("origin/tweak_mcp_server: file not found")

# Check for CRLF in each blob
def has_crlf(b: bytes)->bool:
    return b.count(b"\r\n")>0

print("HEAD CRLF:", has_crlf(head_b))
print("origin/main CRLF:", has_crlf(main_b) if 'main_b' in locals() else "n/a")
print("origin/tweak_mcp_server CRLF:", has_crlf(tmc_b) if 'tmc_b' in locals() else "n/a")
PYCODE

echo -e "\n=== File mode bits across branches ==="
git ls-tree -r --name-only HEAD | grep -F "$PATH1" >/dev/null && git ls-tree -r HEAD "$PATH1"
git ls-tree -r origin/main "$PATH1" || true
git ls-tree -r origin/tweak_mcp_server "$PATH1" || true

echo -e "\n=== Show minimal diff headers vs origin/main ==="
git diff --stat origin/main -- "$PATH1" || true

Length of output: 1052


@stevehaertel You’re seeing a real conflict — the files aren’t identical on the branches I can see.

What I found

  • Path check: the repo has src/lfx/src/lfx/_assets/component_index.json. The path you mentioned has a typo: src/lfx/src/lfx/_assets/compoent_index.json (doesn’t exist).
  • Hashes from the repo snapshot here:
    • HEAD: ce585c481955964169fc6a5f543f5b9ac7a86691659fd50ffd6689d8a52a5590
    • origin/main: a22f68164e2a0d06aaf98af4ae435f520dd658b9e0535cdae47e198b3037da0
  • Diff stat vs origin/main: 1 insertion, 1 deletion (the file is a single minified line, so any change shows up as a 1-line diff).

Why this happens

  • component_index.json is minified to one line. If both branches touch that line, Git treats it as overlapping edits and will often require a manual resolution. If the content were truly identical byte-for-byte, Git would usually auto-merge; here, it’s not identical.

How to resolve cleanly

  1. Update your branch with latest main:
  • Rebase (keeps history clean):
    • git fetch upstream
    • git checkout tweak_mcp_server
    • git rebase upstream/main
    • If you don’t have “upstream” set to langflow-ai/langflow, substitute the correct remote.
  • Or merge (simpler):
    • git fetch upstream
    • git checkout tweak_mcp_server
    • git merge upstream/main
  1. Regenerate the index on top of the updated code, then commit:
  • FX_DEV=1 uv run python scripts/build_component_index.py
  • git add src/lfx/src/lfx/_assets/component_index.json
  • git commit -m "chore: rebuild component index after updating main"
  • If you rebased: git push -f origin tweak_mcp_server; if merged: git push origin tweak_mcp_server
  1. Optional verification (no sha256sum needed):
  • Current branch file:
    • python - <<'PY'\nimport hashlib,sys\nb=open('src/lfx/src/lfx/_assets/component_index.json','rb').read()\nprint(hashlib.sha256(b).hexdigest())\nPY
  • Compare a branch’s blob directly:
    • git show upstream/main:src/lfx/src/lfx/_assets/component_index.json | python - <<'PY'\nimport hashlib,sys\nprint(hashlib.sha256(sys.stdin.buffer.read()).hexdigest())\nPY

Notes

  • If your PR branch lives on your fork, origin/main may point to your fork’s main. Make sure you’re comparing against the upstream main (often named “upstream”). Check with git remote -v.
  • In the future, to reduce churn/conflicts on this generated one-liner, we could consider pretty-printing the JSON or adding a merge attribute in .gitattributes, but that’s a repo-level choice.

If you want, I can also open a small follow-up to propose marking this file as generated and documenting the rebuild step to avoid repeated conflicts.


🧠 Learnings used
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-05T22:51:27.961Z
Learning: The TestComposioComponentAuth test in src/backend/tests/unit/components/bundles/composio/test_base_composio.py demonstrates proper integration testing patterns for external API components, including real API calls with mocking for OAuth completion, comprehensive resource cleanup, and proper environment variable handling with pytest.skip() fallbacks.

Learnt from: deon-sanchez
Repo: langflow-ai/langflow PR: 9158
File: src/backend/base/langflow/api/v1/mcp_projects.py:404-404
Timestamp: 2025-07-23T21:19:22.567Z
Learning: In langflow MCP projects configuration, prefer using dynamically computed URLs (like the `sse_url` variable) over hardcoded localhost URLs to ensure compatibility across different deployment environments.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Dec 2, 2025
@stevehaertel
Copy link
Copy Markdown
Contributor Author

💚All green! Quick! Someone merge this now while it's hot!
image

@edwinjosechittilappilly edwinjosechittilappilly added this pull request to the merge queue Dec 2, 2025
Merged via the queue into langflow-ai:main with commit 692d659 Dec 2, 2025
86 checks passed
@stevehaertel stevehaertel deleted the tweak_mcp_server branch January 20, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working community Pull Request from an external contributor needs-docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants