Skip to content

Conversation

@peteski22
Copy link
Contributor

@peteski22 peteski22 commented Nov 13, 2025

  • Add check_health parameter to filter tools by server health status
  • Defaults to True for best performance and JavaScript SDK parity
  • Add _get_healthy_servers() helper method for batch health checking
  • Silently skip unhealthy servers (timeout, unreachable, unknown)
  • Add comprehensive unit tests for health filtering scenarios
  • Update existing tests to mock server_health
  • Update README with health filtering examples
  • Maintains full backward compatibility via check_health=False option

Summary by CodeRabbit

  • New Features

    • Tools retrieval now filters to healthy servers by default; unhealthy servers are skipped. Option added to disable health filtering and to request specific servers when fetching tools.
  • Documentation

    • Updated public API docs and examples to show the new parameters, default healthy-server behaviour and how to override it.
  • Tests

    • Added and expanded tests and a fixture covering healthy/unhealthy servers, server selection, disabling checks and health-check error scenarios.

@peteski22 peteski22 requested a review from daavoo November 13, 2025 22:35
@peteski22 peteski22 added enhancement New feature or request sdk labels Nov 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Walkthrough

agent_tools gained parameters servers: list[str] | None = None and keyword-only check_health: bool = True. When check_health is true (default), provided or discovered servers are filtered to those with health "ok" via a new _get_healthy_servers; README, tests, and a new test fixture were updated.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updated examples and API entry to show `agent_tools(self, servers: list[str]
Health filtering implementation
src/mcpd/mcpd_client.py
Changed agent_tools signature to accept servers and keyword-only check_health: bool = True; added private _get_healthy_servers(self, server_names: list[str]) -> list[str]; when check_health is true, only servers with health "ok" are used; missing or unhealthy servers are skipped during tool retrieval; error handling adjusted.
Tests and fixtures
tests/unit/test_mcpd_client.py, tests/conftest.py
Added tools_side_effect fixture in tests/conftest.py for per-server tool mocks; expanded unit tests in tests/unit/test_mcpd_client.py to cover health-aware behaviour, check_health=False, empty/nonexistent server lists, combined server/health scenarios, and health-check exceptions.

Possibly related PRs

Suggested labels

documentation

Suggested reviewers

  • daavoo

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarises the main change: adding health filtering capability to the agent_tools() method, which is the primary focus across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch peteski22/agent-tools-health-filtering

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61a7987 and c43896d.

📒 Files selected for processing (4)
  • README.md (2 hunks)
  • src/mcpd/mcpd_client.py (4 hunks)
  • tests/conftest.py (2 hunks)
  • tests/unit/test_mcpd_client.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/mcpd/mcpd_client.py (2)
src/mcpd/exceptions.py (2)
  • ServerNotFoundError (105-132)
  • ServerUnhealthyError (135-167)
src/mcpd/function_builder.py (1)
  • create_function_from_schema (119-207)
tests/unit/test_mcpd_client.py (2)
src/mcpd/mcpd_client.py (3)
  • McpdClient (56-884)
  • agent_tools (370-467)
  • servers (216-263)
tests/conftest.py (3)
  • client (52-53)
  • tools_side_effect (62-83)
  • side_effect (78-79)
🔇 Additional comments (5)
README.md (1)

93-104: agent_tools documentation now matches the health-aware API

The Agentic Usage examples and the API section correctly describe agent_tools(servers: list[str] | None = None, *, check_health: bool = True), including the default healthy-only behaviour and the check_health=False escape hatch. This keeps docs, implementation, and tests aligned.

Also applies to: 148-148

src/mcpd/mcpd_client.py (1)

370-399: Health-aware agent_tools implementation is consistent and well-scoped

The updated agent_tools API and implementation look solid:

  • check_health is keyword-only with a sensible default, avoiding positional boolean traps.
  • When check_health=True, _get_healthy_servers is called first, so /tools is only queried for servers with an ok status, matching the docstring and README.
  • _get_healthy_servers handles empty input efficiently, relies on server_health() once, and reuses HealthStatus.is_healthy so health semantics stay centralised.
  • Non-existent and unhealthy servers are silently skipped as documented, while health-check failures and tool-definition errors propagate rather than being swallowed, which is also enforced by the tests.

I don’t see correctness or robustness issues in this flow.

Also applies to: 446-467, 469-496

tests/unit/test_mcpd_client.py (2)

129-181: agent_tools tests thoroughly cover server selection and basic health filtering

The tests around agent_tools (default behaviour, explicit single/multiple servers, nonexistent servers, empty server lists, and omission of the servers parameter) correctly exercise:

  • Use of servers() vs explicit server lists.
  • Per-server tool retrieval via the tools_side_effect factory.
  • That no unnecessary calls are made when servers=[].

These give good confidence that server selection and tool wrapping behave as intended.

Also applies to: 211-237, 238-347


268-347: Health-filtering and failure-mode tests capture the important edge cases

The added tests for health-aware behaviour:

  • Verify that only healthy servers contribute tools by default, including when mixing healthy and unhealthy servers.
  • Confirm that check_health=False skips health checks entirely, regardless of configured servers.
  • Check that when all servers are unhealthy, agent_tools returns an empty list without creating any functions.
  • Ensure that an exception from server_health propagates out of agent_tools rather than being converted into an empty result.

This suite accurately encodes the intended semantics and guards against regressions in the health-filtering path.

Also applies to: 348-395

tests/conftest.py (1)

1-1: tools_side_effect fixture cleanly standardises tools() mocking

The tools_side_effect fixture is a neat, type-annotated factory for per-server tools() mocks, with sensible defaults for missing servers. It keeps the agent-tools tests concise and consistent and matches the real tools(server_name=...) shape.

Also applies to: 61-83

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unit/test_mcpd_client.py (1)

203-227: Add missing server_health mock to prevent implicit HTTP calls

The two tests at lines 203–227 are missing the @patch.object(McpdClient, "server_health") decorator that all similar tests in this file include. Since agent_tools() defaults to check_health=True, both tests will invoke _get_healthy_servers(), which calls the unmocked server_health() method and triggers real HTTP requests.

This contradicts the established pattern used in every other agent_tools test (test_agent_tools, test_agent_tools_filter_by_single_server, test_agent_tools_filter_by_multiple_servers, etc.), all of which properly mock server_health.

Apply either fix suggested:

  • Add @patch.object(McpdClient, "server_health") to both tests and set mock_health.return_value = {} (consistent with existing tests); or
  • Call client.agent_tools(servers=["nonexistent"], check_health=False) and client.agent_tools(servers=[], check_health=False) respectively.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afcb2b9 and 69c1089.

📒 Files selected for processing (3)
  • README.md (1 hunks)
  • src/mcpd/mcpd_client.py (5 hunks)
  • tests/unit/test_mcpd_client.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/unit/test_mcpd_client.py (2)
src/mcpd/mcpd_client.py (3)
  • McpdClient (56-882)
  • agent_tools (370-466)
  • servers (216-263)
tests/conftest.py (1)
  • client (51-52)
🪛 Ruff (0.14.4)
src/mcpd/mcpd_client.py

370-370: Boolean-typed positional argument in function definition

(FBT001)


370-370: Boolean default positional argument in function definition

(FBT002)


483-483: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (1)
tests/unit/test_mcpd_client.py (1)

129-151: Health-filtering tests look solid and cover key scenarios

The new tests around agent_tools and health (filters_by_health_default, no_health_check_when_disabled, all_servers_unhealthy, combined server/health filtering, and health-check exception) give good coverage of the intended behaviours, including the “exception ⇒ empty result” path.

This will make future changes to the health logic much safer.

Also applies to: 152-201, 252-362

- Add check_health parameter to filter tools by server health status
- Defaults to True for best performance and JavaScript SDK parity
- Add _get_healthy_servers() helper method for batch health checking
- Silently skip unhealthy servers (timeout, unreachable, unknown)
- Add comprehensive unit tests for health filtering scenarios
- Update existing tests to mock server_health
- Update README with health filtering examples
- Maintains full backward compatibility via check_health=False option
@peteski22 peteski22 force-pushed the peteski22/agent-tools-health-filtering branch from 69c1089 to 8d1257c Compare November 14, 2025 13:34
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/mcpd/mcpd_client.py (1)

405-411: Update docstring to remove ServerNotFoundError from Raises section

The docstring (line 409) documents ServerNotFoundError as a raised exception, but the implementation (line 459) catches and silently ignores both ServerNotFoundError and ServerUnhealthyError. Remove ServerNotFoundError: If a server becomes unavailable during tool retrieval. from the Raises: section, as this behaviour is already documented in the Args: section (line 389: "Non-existent server names are silently ignored").

♻️ Duplicate comments (1)
README.md (1)

93-104: Examples align with health‑filtering semantics; API bullet still misses keyword‑only marker

The “Agentic Usage” examples for agent_tools now correctly demonstrate default health filtering, servers=[...], and check_health=False, which matches the current implementation.

In the API section, the bullet uses:

client.agent_tools(servers: list[str] | None = None, check_health: bool = True) -> list[Callable]

The actual signature is keyword‑only for check_health (..., *, check_health: bool = True, ...). For accuracy and to encourage clearer call sites, consider reflecting that in the docs:

client.agent_tools(servers: list[str] | None = None, *, check_health: bool = True) -> list[Callable]

Also applies to: 148-148

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69c1089 and 8d1257c.

📒 Files selected for processing (4)
  • README.md (2 hunks)
  • src/mcpd/mcpd_client.py (4 hunks)
  • tests/conftest.py (1 hunks)
  • tests/unit/test_mcpd_client.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/mcpd/mcpd_client.py (2)
src/mcpd/exceptions.py (2)
  • ServerNotFoundError (105-132)
  • ServerUnhealthyError (135-167)
src/mcpd/function_builder.py (1)
  • create_function_from_schema (119-207)
tests/unit/test_mcpd_client.py (2)
src/mcpd/mcpd_client.py (2)
  • agent_tools (370-467)
  • servers (216-263)
tests/conftest.py (3)
  • client (51-52)
  • tools_side_effect (61-82)
  • side_effect (77-78)
🪛 Ruff (0.14.4)
tests/conftest.py

76-76: Missing return type annotation for private function _create_side_effect

(ANN202)


77-77: Missing return type annotation for private function side_effect

(ANN202)

tests/unit/test_mcpd_client.py

228-228: Unused method argument: mock_tools

(ARG002)

🔇 Additional comments (2)
src/mcpd/mcpd_client.py (1)

370-467: Health‑first agent_tools flow and helper structure look solid

The refactored agent_tools now derives the server list, applies _get_healthy_servers when check_health=True, and only then fetches tools per server, which matches the documented/default health‑filtering semantics and avoids calling /tools on servers already known to be unhealthy. Reusing HealthStatus.is_healthy inside _get_healthy_servers keeps status logic centralised. Overall, the control flow and error handling here look correct and coherent with the tests and README.

Also applies to: 469-493

tests/unit/test_mcpd_client.py (1)

129-207: Health‑aware agent_tools test coverage is comprehensive and well factored

The updated tests around agent_tools cover the key behaviours: default health filtering, explicit servers=[...], the no‑servers case, disabling health checks, all‑unhealthy servers, combining server and health filters, and exception propagation from server_health. Using the tools_side_effect fixture keeps per‑server tool data clear and reduces duplication. This suite gives good confidence in the new health‑filtering logic.

Also applies to: 238-390

@peteski22 peteski22 force-pushed the peteski22/agent-tools-health-filtering branch from 831e3b1 to 594c8a8 Compare November 14, 2025 15:22
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d1257c and 594c8a8.

📒 Files selected for processing (4)
  • README.md (2 hunks)
  • src/mcpd/mcpd_client.py (4 hunks)
  • tests/conftest.py (2 hunks)
  • tests/unit/test_mcpd_client.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/mcpd/mcpd_client.py (2)
src/mcpd/exceptions.py (2)
  • ServerNotFoundError (105-132)
  • ServerUnhealthyError (135-167)
src/mcpd/function_builder.py (1)
  • create_function_from_schema (119-207)
tests/unit/test_mcpd_client.py (2)
src/mcpd/mcpd_client.py (3)
  • McpdClient (56-880)
  • agent_tools (370-466)
  • servers (216-263)
tests/conftest.py (3)
  • client (52-53)
  • tools_side_effect (62-83)
  • side_effect (78-79)
🔇 Additional comments (6)
src/mcpd/mcpd_client.py (1)

370-467: Health-aware agent_tools implementation looks consistent and robust

The new signature, default check_health=True, and the flow of “discover servers → optionally filter via _get_healthy_servers → fetch tools per server with targeted exception handling” align well with the docstring, README, and tests. Using a keyword-only boolean and delegating health logic to _get_healthy_servers keeps the API clear and avoids boolean-trap issues; the per-server try/except for ServerNotFoundError/ServerUnhealthyError is a sensible resilience choice.

tests/conftest.py (1)

1-1: tools_side_effect fixture cleanly abstracts per-server tools mocking

The new fixture neatly packages the tools() side-effect pattern with clear typing and documentation, and keeps tests aligned with the real tools(server_name=...) -> list[dict] shape. This improves readability and reuse across the agent-tools tests.

Also applies to: 61-83

tests/unit/test_mcpd_client.py (3)

129-268: Comprehensive coverage for default and server-filtered agent_tools paths

The tests around test_agent_tools, single/multiple server filtering, explicit empty server list, and omitted servers parameter collectively exercise the main success paths for agent_tools, including interaction with server_health and create_function_from_schema. Using the shared tools_side_effect keeps the mocked tools() contract realistic and the expectations (counts and arguments) match the implementation.


269-348: Health-filtering behaviour and check-health toggle are well exercised

The tests for default health filtering, disabling health checks, and the “all servers unhealthy” case accurately capture the intended semantics: only healthy servers contribute tools when check_health=True, and server_health is completely bypassed when check_health=False. Assertions on call counts (mock_health.assert_not_called, mock_create.assert_not_called) make these guarantees explicit and future-proof.


349-395: Edge cases for mixed health and health-check failures are handled correctly

The combined server/health filtering and test_agent_tools_health_check_exception ensure that:

  • Only the intersection of requested and healthy servers is used, and unhealthy ones are skipped.
  • Exceptions from server_health (via _get_healthy_servers) propagate rather than being silently swallowed.

This aligns with the documented contract that McpdError (or other exceptions from health retrieval) will bubble out when health checking is enabled.

README.md (1)

93-104: agent_tools documentation now matches the implementation and tests

The updated Agentic Usage examples and API bullet correctly reflect the new signature and default health-filtering semantics (servers plus keyword-only check_health, healthy-only by default, check_health=False to include all servers). This keeps users’ expectations aligned with the actual runtime behaviour.

Also applies to: 148-148

@peteski22 peteski22 force-pushed the peteski22/agent-tools-health-filtering branch from 594c8a8 to 61a7987 Compare November 14, 2025 15:34
@peteski22 peteski22 force-pushed the peteski22/agent-tools-health-filtering branch from 61a7987 to c43896d Compare November 19, 2025 11:32
Copy link
Member

@aittalam aittalam left a comment

Choose a reason for hiding this comment

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

Thanks @peteski22 !
I have left one comment but it's more to test my own understanding... 😅 Your changes LGTM, especially knowing that follow-up PRs are already planned 🙏

@peteski22 peteski22 merged commit c874895 into main Nov 19, 2025
8 checks passed
@peteski22 peteski22 deleted the peteski22/agent-tools-health-filtering branch November 19, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request sdk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants