google / google/adk-python

MCP tool outputSchema is dropped on the LiteLLM path

Đang mở
#6,784 1 bình luận 0 reaction 1 người được giao Được @sanketpatil06 nhận Xem trên GitHub
tools
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

## 🔴 Required Information

**Describe the Bug:**

An MCP tool's `outputSchema` never reaches the model when the agent is backed by `LiteLlm`. `MCPTool._get_declaration()` can populate `response_json_schema`, but `_function_declaration_to_tool_param()` in `lite_llm.py` builds the tool payload from `name`, `description` and `parameters` only, so the output schema is silently dropped.

The result is that the model cannot describe or rely on a tool's result shape, which is the same user-visible symptom as #2828 (fixed for the Gemini path in c8e5340, later refactored behind the `JSON_SCHEMA_FOR_FUNC_DECL` feature flag).

Enabling `ADK_ENABLE_JSON_SCHEMA_FOR_FUNC_DECL=1` does **not** help on this path: the declaration is built correctly, but the LiteLLM conversion still discards it. The payload is byte-identical with the flag on and off.

**Steps to Reproduce:**

1. `pip install google-adk==1.34.1`
2. Save the script under *Minimal Reproduction Code* as `adk_repro.py`
3. Run `python adk_repro.py`
4. Run `ADK_ENABLE_JSON_SCHEMA_FOR_FUNC_DECL=1 python adk_repro.py`
5. Compare the printed payloads — they are identical, and neither contains the output schema

**Expected Behavior:**

The declared output schema should reach the model on the LiteLLM path, as it does on the Gemini path. Most OpenAI-compatible providers have no dedicated field for a tool's result schema, so a reasonable approach would be to append a rendering of the schema to the tool `description` (which is forwarded) rather than inventing a non-standard key.

**Observed Behavior:**

```
ADK_ENABLE_JSON_SCHEMA_FOR_FUNC_DECL = 1
declaration.response is set: False
declaration.response_json_schema is set: True

Payload LiteLlm sends to the model:
{
"type": "function",
"function": {
"name": "get_widget",
"description": "Return a widget.",
"parameters": {
"type": "object",
"properties": {"service": {"type": "string"}},
"required": ["service"]
}
}
}

output schema present in payload: False
```

`declaration.response_json_schema` is set, yet nothing derived from it appears in the payload.

**Environment Details:**

- ADK Library Version (pip show google-adk): 1.34.1
- Desktop OS: macOS 26.6
- Python Version (python -V): 3.12

**Model Information:**

- Are you using LiteLLM: Yes
- Which model is being used: GPT models via a LiteLLM-compatible endpoint (not model-specific — the schema is dropped before any request is made)

---

## 🟡 Optional Information

**Regression:**

Partly. #2828 was fixed in c8e5340 by setting `response=_to_gemini_schema(output_schema)` on the `FunctionDeclaration`. That assignment no longer exists on `main`; `_get_declaration()` now sets either `parameters` alone or `parameters_json_schema` + `response_json_schema` depending on `FeatureName.JSON_SCHEMA_FOR_FUNC_DECL` (`WIP`, `default_on=False`). Either way `_function_declaration_to_tool_param()` ignores both `response` and `response_json_schema`, so the LiteLLM path has no route for it.

**Additional Context:**

Relevant code on `main`:

- `src/google/adk/tools/mcp_tool/mcp_tool.py` — `_get_declaration()` sets `response_json_schema=output_schema` only when the feature flag is enabled.
- `src/google/adk/models/lite_llm.py` — `_function_declaration_to_tool_param()` reads `parameters` / `parameters_json_schema` and returns `{"type": "function", "function": {"name", "description", "parameters"}}`.
- `src/google/adk/models/lite_llm.py` — `_build_function_declaration_log()` does read `func_decl.response`, but that is logging only and does not affect the request.

`grep -c response_json_schema src/google/adk/models/lite_llm.py` returns 0; only `google_llm.py` and `apigee_llm.py` reference it.

Happy to send a PR if the description-appending approach sounds right, or another shape if you prefer.

**Minimal Reproduction Code:**

```python
"""Minimal reproduction: an MCP tool's outputSchema never reaches a LiteLLM-backed model."""

import json
import os

from google.adk.models.lite_llm import _function_declaration_to_tool_param
from google.adk.tools.mcp_tool.mcp_tool import McpTool as AdkMcpTool
from mcp.types import Tool as McpTool

OUTPUT_SCHEMA = {
"type": "object",
"additionalProperties": False,
"required": ["status", "data"],
"properties": {
"status": {"type": "string", "enum": ["success", "error"]},
"data": {"type": "string", "description": "Preformatted text, not JSON."},
},
}
INPUT_SCHEMA = {
"type": "object",
"properties": {"service": {"type": "string"}},
"required": ["service"],
}

mcp_tool = McpTool(
name="get_widget",
description="Return a widget.",
inputSchema=INPUT_SCHEMA,
outputSchema=OUTPUT_SCHEMA,
)

tool = AdkMcpTool(mcp_tool=mcp_tool, mcp_session_manager=None)
declaration = tool._get_declaration()

flag = os.environ.get("ADK_ENABLE_JSON_SCHEMA_FOR_FUNC_DECL", "")
print(f"ADK_ENABLE_JSON_SCHEMA_FOR_FUNC_DECL = {flag}")
print(f"declaration.response is set: {declaration.response is not None}")
print(f"declaration.response_json_schema is set: {declaration.response_json_schema is not None}")

payload = _function_declaration_to_tool_param(declaration)
print("\nPayload LiteLlm sends to the model:")
print(json.dumps(payload, indent=2))

print(f"\noutput schema present in payload: {'success' in json.dumps(payload)}")
```

**How often has this issue occurred?:**

- Always (100%)

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.