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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"supports_cache_control": null
}
],
"headers": null,
"headers": {
"X-LCS-Merge-Server-Tools": "true"
},
"timeout_seconds": null,
"supports_streaming": true,
"requires_auth": true
Expand Down
4 changes: 3 additions & 1 deletion data/release/goose/custom_goose-proxy.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"supports_cache_control": null
}
],
"headers": null,
"headers": {
"X-LCS-Merge-Server-Tools": "true"
},
Comment on lines +19 to +21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 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 3

Repository: 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.json

Repository: 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 2

Repository: 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 15

Repository: 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/ -i

Repository: 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 f

Repository: 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 10

Repository: 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.py

Repository: 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.

"timeout_seconds": null,
"supports_streaming": true,
"requires_auth": true
Expand Down