Skip to content

fix: mcp tool converter sending none values#180

Merged
NicoleMGomes merged 11 commits into
mainfrom
fix/langchain-tool-converter
Jun 24, 2026
Merged

fix: mcp tool converter sending none values#180
NicoleMGomes merged 11 commits into
mainfrom
fix/langchain-tool-converter

Conversation

@NicoleMGomes

@NicoleMGomes NicoleMGomes commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Disclaimer: Do not include SAP-internal or customer-specific information in this PR (e.g. internal system URLs, customer names, tenant IDs, or confidential configurations). This is a public repository.

Description

Fixes mcp_tool_to_langchain in the Agent Gateway converter so that optional MCP tool parameters are no longer forwarded to call_mcp_tool as None values, and adds an omit_none configuration option to control this behaviour.

Root cause: Optional fields in the generated Pydantic args_schema were typed as str | None with a plain None default. LangChain passes all schema fields — including optional ones the LLM did not supply — to the tool's run closure as keyword arguments. This caused call_mcp_tool to receive explicit None for every optional parameter, which breaks downstream MCP tool invocations that distinguish between an absent parameter and a null one.

Changes:

  • Optional fields are now typed as str | None with Field(default=None) so Pydantic accepts None from LangChain's validation layer, while the field is still not in required.
  • The run closure strips None values from kwargs before forwarding to call_tool (controlled by the new omit_none flag).
  • New keyword-only parameter omit_none: bool = True on mcp_tool_to_langchain — set to False to forward None values explicitly to the MCP server.
  • Test suite refactored: shared _make_tool() fixture removes duplication; new TestMcpToolToLangchainInvocation class covers end-to-end LangChain tool invocation including the omit_none=False path.
  • Removed stale # ty: ignore comments from tests/adms/unit/test_client.py and tests/destination/unit/test_client.py that caused ty type-check pre-commit failures.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Dependency update

How to Test

  1. Install the package: uv sync
  2. Run the converter unit tests:
    uv run pytest tests/agentgateway/unit/test_converters.py -v
    
  3. Verify the default behaviour (None omitted):
    import asyncio
    from unittest.mock import AsyncMock
    from sap_cloud_sdk.agentgateway import MCPTool
    from sap_cloud_sdk.agentgateway.converters import mcp_tool_to_langchain
    
    tool = MCPTool(
        name="get_supplier_bid", server_name="ariba",
        description="Gets supplier bids",
        input_schema={
            "type": "object", "required": ["eventid"],
            "properties": {"eventid": {"type": "string"}, "showdeclinedreason": {"type": "string"}},
        },
        url="https://example.com/mcp",
    )
    call_tool = AsyncMock(return_value="ok")
    lc_tool = mcp_tool_to_langchain(tool, call_tool, lambda: "token")
    asyncio.run(lc_tool.arun({"eventid": "E001"}))
    assert "showdeclinedreason" not in call_tool.call_args.kwargs  # omitted, not None
  4. Verify omit_none=False forwards None explicitly:
    call_tool2 = AsyncMock(return_value="ok")
    lc_tool2 = mcp_tool_to_langchain(tool, call_tool2, lambda: "token", omit_none=False)
    asyncio.run(lc_tool2.arun({"eventid": "E001", "showdeclinedreason": None}))
    assert call_tool2.call_args.kwargs["showdeclinedreason"] is None  # forwarded as None
  5. Run the full pre-commit suite: uvx pre-commit run --all-files

Checklist

  • I have read the Contributing Guidelines
  • I have verified that my changes solve the issue
  • I have added/updated automated tests to cover my changes
  • All tests pass locally
  • I have verified that my code follows the Code Guidelines
  • I have updated documentation (if applicable)
  • I have added type hints for all public APIs
  • My code does not contain sensitive information (credentials, tokens, etc.)
  • I have followed Conventional Commits for commit messages

Additional Notes

omit_none is keyword-only (declared after *) to prevent positional misuse. The default True preserves existing behaviour — no changes needed for current callers.

@NicoleMGomes NicoleMGomes force-pushed the fix/langchain-tool-converter branch from 85daa74 to 9c31104 Compare June 23, 2026 06:46
@NicoleMGomes NicoleMGomes marked this pull request as ready for review June 23, 2026 06:46
@NicoleMGomes NicoleMGomes requested a review from a team as a code owner June 23, 2026 06:46
@NicoleMGomes NicoleMGomes force-pushed the fix/langchain-tool-converter branch 2 times, most recently from 98461bf to 4303453 Compare June 24, 2026 06:39
@NicoleMGomes NicoleMGomes dismissed cassiofariasmachado’s stale review June 24, 2026 11:35

The merge-base changed after approval.

@NicoleMGomes NicoleMGomes force-pushed the fix/langchain-tool-converter branch from 91b6245 to 08d7c41 Compare June 24, 2026 11:35
@NicoleMGomes NicoleMGomes merged commit 101492b into main Jun 24, 2026
11 checks passed
@NicoleMGomes NicoleMGomes deleted the fix/langchain-tool-converter branch June 24, 2026 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants