-
Notifications
You must be signed in to change notification settings - Fork 316
Closed
Labels
kind/bugSomething isn't workingSomething isn't working
Description
cagent implements the MCP elicitation but sends keys with the wrong case, breaking some servers - notably OpenMetaData MCP server (Java).
Output from cagent 1.20.3:
{
"capabilities": {
"elicitation": {
"Form": {},
"URL": {}
}
}
}
Expected output per https://modelcontextprotocol.io/specification/draft/client/elicitation
{
"capabilities": {
"elicitation": {
"form": {},
"url": {}
}
}
}
Version affected
1.20.3
How To Reproduce
Intercept output of cagent with this script, which detects and fixes the incorrect "Form" and "URL" keys, solving the issue.
import httpx
import json
import uvicorn
from fastapi import FastAPI, Request, Response
from fastapi.responses import JSONResponse
app = FastAPI()
TARGET_URL = "https://openmetadata.example.com/mcp"
@app.api_route("/mcp", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"])
async def proxy_mcp(request: Request):
method = request.method
headers = dict(request.headers)
headers.pop("host", None)
headers.pop("content-length", None)
# 1. Safely get the body (handle empty/non-JSON)
raw_body = await request.body()
body = None
if raw_body:
try:
body = json.loads(raw_body)
except json.JSONDecodeError:
print(f"[DEBUG] Received non-JSON {method} request. Forwarding raw.")
# 2. Fix Case-Sensitivity in Cagent Request (if it's a JSON-RPC call)
if body and "params" in body and "capabilities" in body["params"]:
caps = body["params"]["capabilities"]
if "elicitation" in caps:
print("Found Elicitation Capabilities: ", caps["elicitation"])
e = caps["elicitation"]
caps["elicitation"] = {
"form": e.get("Form") if "Form" in e else e.get("form"),
"url": e.get("URL") if "URL" in e else e.get("url")
}
print("[!!!] FIXED: Request 'Form/URL' -> lowercase")
# 3. Forward to Server
async with httpx.AsyncClient() as client:
try:
proxy_resp = await client.request(
method,
TARGET_URL,
content=json.dumps(body) if body else raw_body,
headers=headers,
timeout=30.0
)
# 4. Handle Empty Server Responses (HTTP 204)
if proxy_resp.status_code == 204 or not proxy_resp.content:
print(f"[DEBUG] Server returned empty {proxy_resp.status_code}. Forwarding as-is.")
return Response(status_code=proxy_resp.status_code)
# 5. Fix Server Response for Cagent
try:
resp_data = proxy_resp.json()
if "result" in resp_data and "capabilities" in resp_data["result"]:
# Strip 'elicitation' so cagent's strict Java parser doesn't die
if "elicitation" in resp_data["result"]["capabilities"]:
print("[!!!] FIXED: Stripping 'elicitation' from response")
del resp_data["result"]["capabilities"]["elicitation"]
# Downgrade version string for compatibility
resp_data["result"]["protocolVersion"] = "2024-11-05"
return JSONResponse(content=resp_data, status_code=proxy_resp.status_code)
except:
# If server response isn't JSON, just pass it through
return Response(content=proxy_resp.content, status_code=proxy_resp.status_code)
except Exception as e:
print(f"[ERROR] Proxy error: {e}")
return Response(content=str(e), status_code=500)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
Simple cagent definition with tool:
agents:
root:
model: openai/gpt-5
description: OpenMetaData Search
instruction: |
Use the OpenMetaData tool to search for data sets in accordance with the user instructions.
toolsets:
- type: mcp
remote:
url: http://127.0.0.1:8000/mcp
transport_type: "streamable"
headers:
Authorization: "Bearer ${env.OMD_API_KEY}"
Accept: "application/json,text/event-stream"
Results on bug-fix proxy
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Found Elicitation Capabilities: {'Form': None, 'URL': None}
[!!!] FIXED: Request 'Form/URL' -> lowercase
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
kind/bugSomething isn't workingSomething isn't working