Include header in custom_provider to merge MCP tools#46
Conversation
With the current addition of lightspeed-core/lightspeed-stack#1435, we can now specify the X-LCS-MMerge-Server-Tools header to allow LCS to merge the mcp tools calls and prevent the server-side mcp tools to leak on the client side
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
d293874 to
6860c61
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@data/release/goose/custom_goose-proxy.json`:
- Around line 19-21: The chat_completions endpoint in src/goose_proxy/v1.py must
accept the incoming Request object and merge its headers into the hardcoded
headers before creating/passing headers to httpx.AsyncClient; update the
chat_completions function signature to include a fastapi.Request (or
starlette.requests.Request) parameter, read request.headers, copy/normalize them
into a dict, then merge (with hardcoded headers taking precedence where needed,
e.g., "X-LCS-Merge-Server-Tools") and pass the merged headers to the AsyncClient
request call so incoming headers are forwarded to the lightspeed-stack backend.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 3a565b43-6485-450e-80b8-d3ca33f8c62b
📒 Files selected for processing (1)
data/release/goose/custom_goose-proxy.json
| "headers": { | ||
| "X-LCS-Merge-Server-Tools": "true" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Search for code that reads headers from the configuration file
# Search for code that accesses the 'headers' field from config/settings
rg -n -C3 '\b(config|settings|provider).*headers\b' --type=py
# Search for where custom_goose-proxy.json is loaded/parsed
rg -n -C3 'custom_goose-proxy\.json' --type=py
# Search for httpx.AsyncClient initialization to see all header usage
ast-grep --pattern 'httpx.AsyncClient($$$)'Repository: rhel-lightspeed/goose-proxy
Length of output: 515
🏁 Script executed:
#!/bin/bash
# Search for where provider configuration is loaded/parsed
rg -n 'provider\|backend\|config' --type=py -A 3 | head -100
# Search for all JSON config file references
fd -type f -name '*.json' | xargs grep -l 'headers'
# Search for get_http_client function and its callers
rg -n 'get_http_client' --type=py -B 5 -A 10
# Look for provider configuration class definitions
ast-grep --pattern 'class Provider { $$$ }'Repository: rhel-lightspeed/goose-proxy
Length of output: 3591
🏁 Script executed:
#!/bin/bash
# Find get_settings function definition
rg -n 'def get_settings\|from.*get_settings' --type=py
# Find settings/config related files
fd -type f -name '*settings*' -o -name '*config*'
# Look for backend class definition
rg -n 'class Backend' --type=py -A 10
# Search for where custom_goose-proxy.json is used in the entire repo
fd -type f | xargs grep -l 'custom_goose-proxy.json'Repository: rhel-lightspeed/goose-proxy
Length of output: 1187
🏁 Script executed:
#!/bin/bash
# View the full Backend class definition
cat -n src/goose_proxy/config.py | head -150
# Find get_settings function
rg -n 'def get_settings'
# Find where json files are loaded
rg -n 'custom_goose-proxy\.json'Repository: rhel-lightspeed/goose-proxy
Length of output: 6691
🏁 Script executed:
#!/bin/bash
# View get_settings function
sed -n '155,200p' src/goose_proxy/config.py
# Check if there's any JSON loading in goose-proxy code
rg -n 'json\|JSON' src/goose_proxy/ --type=py
# Search the entire repo to understand what custom_goose-proxy.json is for
rg -n 'custom_goose-proxy' -B 3 -A 3Repository: rhel-lightspeed/goose-proxy
Length of output: 4664
🏁 Script executed:
#!/bin/bash
# View the full custom_goose-proxy.json file to understand its structure
cat -n data/release/goose/custom_goose-proxy.json
# Also check the development version
cat -n data/development/goose/custom_providers/custom_goose-proxy.jsonRepository: rhel-lightspeed/goose-proxy
Length of output: 1752
🏁 Script executed:
#!/bin/bash
# Search for any handling of X-LCS-Merge-Server-Tools header
rg -n 'X-LCS-Merge-Server-Tools'
# Search for header reading in v1.py request handlers
rg -n 'request\.' src/goose_proxy/v1.py -A 3
# Search for all header processing in the codebase
rg -n 'headers' src/goose_proxy/ -B 2 -A 2Repository: rhel-lightspeed/goose-proxy
Length of output: 896
🏁 Script executed:
#!/bin/bash
# View chat_completions endpoint fully to see how request is handled
sed -n '86,110p' src/goose_proxy/v1.py
# Check if there's any code that reads incoming request headers
rg -n 'request\.' src/goose_proxy/ -B 2 -A 2 | head -50
# Search for translate_request to see what happens with the request
rg -n 'def translate_request' src/goose_proxy/ -A 15Repository: rhel-lightspeed/goose-proxy
Length of output: 4317
🏁 Script executed:
#!/bin/bash
# Check if list_models endpoint shows how to capture Request object
sed -n '103,120p' src/goose_proxy/v1.py
# Check all endpoint signatures to see if any capture Request object
rg -n '@router\.' src/goose_proxy/v1.py -A 3
# Search for any middleware or dependency that could read headers
rg -n 'Request\|Header' src/goose_proxy/ -B 2 -A 2
# Look for any code that might use X-LCS-Merge-Server-Tools or similar headers
rg -n 'merge\|tools\|leak' src/goose_proxy/ -iRepository: rhel-lightspeed/goose-proxy
Length of output: 926
🏁 Script executed:
#!/bin/bash
# Check git history for this file to understand the context
git log --oneline data/release/goose/custom_goose-proxy.json | head -5
# Check if there's any README or documentation about X-LCS-Merge-Server-Tools
rg -n 'Merge.*Tool\|MCP.*tool\|leak' . -i -type f
# Check if there's any FastAPI middleware that could process headers
rg -n 'app\.middleware\|@app\.' src/goose_proxy/ -A 5
# Look for main.py or where the FastAPI app is created
fd 'main\|app' src/goose_proxy/ -type fRepository: rhel-lightspeed/goose-proxy
Length of output: 347
🏁 Script executed:
#!/bin/bash
# Check the git commit that added this header
git show 6860c61
# Search for any code that processes incoming request headers
rg -n 'request\.headers\|Headers' src/goose_proxy/ -B 2 -A 2
# Look for main app file
cat -n src/goose_proxy/main.py 2>/dev/null || cat -n src/goose_proxy/__main__.py 2>/dev/null || fd 'main' src/goose_proxy/Repository: rhel-lightspeed/goose-proxy
Length of output: 50386
🏁 Script executed:
#!/bin/bash
# Check if goose-proxy forwards request headers to the backend
# Look at how requests are made to the backend
sed -n '50,100p' src/goose_proxy/v1.py
# Look for create_response and stream_response functions
rg -n 'def create_response\|def stream_response' src/goose_proxy/ -A 10Repository: rhel-lightspeed/goose-proxy
Length of output: 1845
🏁 Script executed:
#!/bin/bash
# Check if chat_completions endpoint can access request headers
rg -n 'async def chat_completions' src/goose_proxy/v1.py -A 20
# Check if Request object is available via FastAPI dependency
rg -n 'from fastapi import' src/goose_proxy/
# Check if any endpoint accesses request.headers
rg -n '\.headers' src/goose_proxy/Repository: rhel-lightspeed/goose-proxy
Length of output: 1236
🏁 Script executed:
#!/bin/bash
# Check if there's any code that reads request headers from incoming requests
rg -n 'request\.headers\|Request\)' src/goose_proxy/v1.py -B 2 -A 5
# Check the full chat_completions signature more carefully
sed -n '86,105p' src/goose_proxy/v1.py
# Look for middleware that might process headers
fd -type f -name '*.py' -path 'src/goose_proxy/*' -exec grep -l 'middleware\|add_middleware' {} \;
# Check app.py to see how the app is configured
cat src/goose_proxy/app.pyRepository: rhel-lightspeed/goose-proxy
Length of output: 1791
Implementation incomplete: incoming request headers are not forwarded to the backend.
The X-LCS-Merge-Server-Tools header configuration in custom_goose-proxy.json instructs GOOSE to send this header to goose-proxy. However, the chat_completions endpoint in src/goose_proxy/v1.py does not capture or read incoming request headers, so they are never forwarded to the lightspeed-stack backend where this header is needed for merging MCP tools.
The endpoint signature must be updated to accept a Request parameter and merge incoming headers with the hardcoded headers before passing them to httpx.AsyncClient. Without this, the PR's objective (merge MCP tools, prevent server-side tool leakage) will not be achieved.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@data/release/goose/custom_goose-proxy.json` around lines 19 - 21, The
chat_completions endpoint in src/goose_proxy/v1.py must accept the incoming
Request object and merge its headers into the hardcoded headers before
creating/passing headers to httpx.AsyncClient; update the chat_completions
function signature to include a fastapi.Request (or starlette.requests.Request)
parameter, read request.headers, copy/normalize them into a dict, then merge
(with hardcoded headers taking precedence where needed, e.g.,
"X-LCS-Merge-Server-Tools") and pass the merged headers to the AsyncClient
request call so incoming headers are forwarded to the lightspeed-stack backend.
With the current addition of
lightspeed-core/lightspeed-stack#1435, we can now specify the X-LCS-MMerge-Server-Tools header to allow LCS to merge the mcp tools calls and prevent the server-side mcp tools to leak on the client side
Summary by CodeRabbit