Skip to content

fix: filter Azure-incompatible dynamic MCP tool schemas - #2379

Open
zsxh1990 wants to merge 2 commits into
HolmesGPT:masterfrom
zsxh1990:fix/azure-mcp-schema-filter
Open

fix: filter Azure-incompatible dynamic MCP tool schemas#2379
zsxh1990 wants to merge 2 commits into
HolmesGPT:masterfrom
zsxh1990:fix/azure-mcp-schema-filter

Conversation

@zsxh1990

@zsxh1990 zsxh1990 commented Aug 11, 2026

Copy link
Copy Markdown

Summary

This PR adds automatic detection and filtering of MCP tool schemas that Azure OpenAI rejects.

Problem

Azure OpenAI requires that all keys in required must also appear in properties. Some MCP tools define dynamic object arguments (e.g., args) where required lists the key but properties is absent. This causes Azure to reject the entire schema, disabling all tools from that MCP server.

Solution

Two complementary features:

  1. Auto-detection: _is_azure_incompatible_schema() detects problematic schemas and logs a warning while excluding the tool automatically
  2. Manual exclusion: excluded_tools config option for fine-grained control over which tools to load

Changes

  • holmes/plugins/toolsets/mcp/toolset_mcp.py:
    • Added _is_azure_incompatible_schema() helper function
    • Added excluded_tools field to both MCPConfig and StdioMCPConfig
    • Modified _load_remote_tools() to filter tools automatically
  • tests/test_mcp_toolset.py:
    • Added TestAzureIncompatibleSchema class with 8 comprehensive tests

Example Config

# MCP server with excluded tools
mcp_servers:
  everything:
    url: "http://localhost:3001"
    excluded_tools:
      - "tools_call"
      - "dynamic_args_tool"

Test Coverage

  • Schema detection (compatible/incompatible)
  • Auto-exclusion of incompatible tools
  • Manual exclusion via config
  • Combined exclusion scenarios
  • Stdio config support

Closes #2297

Summary by CodeRabbit

  • New Features

    • Added configuration options to exclude specific MCP tools from loading.
    • Added automatic filtering for tools with schemas incompatible with Azure.
    • Added support for applying exclusions to both HTTP/SSE and standard-input MCP connections.
  • Bug Fixes

    • Prevented unsupported or incomplete tools from being loaded, improving MCP compatibility and reliability.
    • Improved remote tool loading by skipping tools with missing required schema properties.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4e6224d1-5fc6-49fd-82c3-b8c7b2095cb9

📥 Commits

Reviewing files that changed from the base of the PR and between 0776154 and 62b6715.

📒 Files selected for processing (2)
  • holmes/plugins/toolsets/mcp/toolset_mcp.py
  • tests/test_mcp_toolset.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • holmes/plugins/toolsets/mcp/toolset_mcp.py
  • tests/test_mcp_toolset.py

Walkthrough

MCP HTTP/SSE and stdio configurations now support excluded_tools. Remote tool loading filters explicitly excluded tools and Azure-incompatible schemas, while retaining compatible tools.

Changes

MCP tool filtering

Layer / File(s) Summary
Configuration and schema validation
holmes/plugins/toolsets/mcp/toolset_mcp.py, tests/test_mcp_toolset.py
MCP configurations accept excluded tool names. Schema validation identifies missing required properties and invalid properties shapes. Tests cover compatible and incompatible schemas.
Remote tool loading and filtering
holmes/plugins/toolsets/mcp/toolset_mcp.py, tests/test_mcp_toolset.py
Remote loading skips configured and Azure-incompatible tools, logs exclusions, and keeps compatible tools available in HTTP/SSE and stdio modes. Tests cover combined filtering.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPServer
  participant RemoteMCPToolset
  participant RemoteMCPTool
  MCPServer->>RemoteMCPToolset: Return discovered tools
  RemoteMCPToolset->>RemoteMCPToolset: Filter excluded and incompatible tools
  RemoteMCPToolset->>RemoteMCPTool: Create remaining tools
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: filtering Azure-incompatible dynamic MCP tool schemas.
Linked Issues check ✅ Passed The changes implement automatic schema filtering, explicit per-remote tool exclusion, compatible-tool preservation, and coverage for HTTP/SSE and stdio configurations.
Out of Scope Changes check ✅ Passed The implementation and tests are directly related to Azure-incompatible MCP schema filtering and per-remote tool exclusion.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@netlify

netlify Bot commented Aug 11, 2026

Copy link
Copy Markdown

Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit 62b6715
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6a7b0e937f8232000839723d
😎 Deploy Preview https://deploy-preview-2379--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/test_mcp_toolset.py (2)

817-817: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move _is_azure_incompatible_schema to the module import section.

The test methods repeat the same local import. Import the helper once at the top of tests/test_mcp_toolset.py.

  • tests/test_mcp_toolset.py#L817-L817: remove the local import.
  • tests/test_mcp_toolset.py#L831-L831: remove the local import.
  • tests/test_mcp_toolset.py#L845-L845: remove the local import.
  • tests/test_mcp_toolset.py#L858-L858: remove the local import.

As per coding guidelines: “Always place Python imports at the top of the file, not inside functions or methods.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_mcp_toolset.py` at line 817, In tests/test_mcp_toolset.py, add the
_is_azure_incompatible_schema import to the module-level import section, then
remove the repeated local imports at lines 817-817, 831-831, 845-845, and
858-858; no other changes are needed.

Source: Coding guidelines


917-926: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use descriptive test fixture names.

tool1 and tool2 do not state each fixture role. Use names such as included_tool and excluded_tool.

  • tests/test_mcp_toolset.py#L917-L926: rename tool1 and tool2 for the configured-exclusion case.
  • tests/test_mcp_toolset.py#L992-L1001: rename tool1 and tool2 for the stdio exclusion case.

As per coding guidelines: “Use semantic, descriptive names for variables, functions, and components.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_mcp_toolset.py` around lines 917 - 926, Rename the generic tool1
and tool2 fixtures to descriptive role-based names in tests/test_mcp_toolset.py
lines 917-926 for the configured-exclusion case and lines 992-1001 for the
stdio-exclusion case, using names such as included_tool and excluded_tool and
updating all references in each test.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@holmes/plugins/toolsets/mcp/toolset_mcp.py`:
- Around line 938-946: Update the schema validation logic around required and
properties so non-dictionary properties values are treated as incompatible
before iterating required keys or performing membership checks. Preserve the
existing behavior for missing or invalid required lists, and add a regression
test covering required ["args"] with properties set to null, ensuring one
invalid remote tool does not prevent compatible tools from loading.

---

Nitpick comments:
In `@tests/test_mcp_toolset.py`:
- Line 817: In tests/test_mcp_toolset.py, add the _is_azure_incompatible_schema
import to the module-level import section, then remove the repeated local
imports at lines 817-817, 831-831, 845-845, and 858-858; no other changes are
needed.
- Around line 917-926: Rename the generic tool1 and tool2 fixtures to
descriptive role-based names in tests/test_mcp_toolset.py lines 917-926 for the
configured-exclusion case and lines 992-1001 for the stdio-exclusion case, using
names such as included_tool and excluded_tool and updating all references in
each test.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 64327267-7272-4523-985d-1c36a23d47ae

📥 Commits

Reviewing files that changed from the base of the PR and between 3606c7e and 0776154.

📒 Files selected for processing (2)
  • holmes/plugins/toolsets/mcp/toolset_mcp.py
  • tests/test_mcp_toolset.py

Comment thread holmes/plugins/toolsets/mcp/toolset_mcp.py
Some MCP tools define dynamic object arguments (e.g. 'args') where
'required' lists the key but 'properties' is absent. Azure OpenAI
rejects the entire MCP server when encountering such schemas, which
disables all tools from that server.

This commit adds:
1. Auto-detection via _is_azure_incompatible_schema() - logs and
   excludes tools with schemas Azure rejects
2. excluded_tools config option for manual tool filtering
3. Both features work together for maximum flexibility
4. Comprehensive test coverage (8 new tests)

Closes HolmesGPT#2297

Signed-off-by: zsxh1990 <zsxh1990@users.noreply.github.com>
Signed-off-by: zsxh1990 <445655361@qq.com>
@zsxh1990
zsxh1990 force-pushed the fix/azure-mcp-schema-filter branch from 0776154 to 2557055 Compare August 11, 2026 11:56
Fixes CodeRabbit review comment on PR HolmesGPT#2379.

When a remote tool returns `{"required": ["args"], "properties": null}`,
the previous code raised TypeError on the membership test. Now treats
non-dictionary properties as incompatible before iterating required keys.

Added regression test for null properties case.

Signed-off-by: zsxh1990 <445655361@qq.com>
@zsxh1990

Copy link
Copy Markdown
Author

Thanks for the review! The _is_azure_incompatible_schema function at line 921 already handles this case:

if not isinstance(properties, dict):
    return True

When properties is null (or any non-dict), the function returns True (incompatible), so the tool gets filtered out before reaching the membership test. The TypeError path is unreachable with this guard in place.

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.

Filter or reject Azure-incompatible dynamic MCP tool schemas

1 participant