UAT: MCPToolAdapter.register_tools() infers resource slots but never wires them into domain Tool objects — resource binding for MCP tools is dead code #2946

Open
opened 2026-04-05 02:54:17 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/mcp-adapter-resource-slot-wiring
  • Commit Message: fix(mcp): wire inferred resource slots into domain Tool objects in MCPToolAdapter
  • Milestone: v3.8.0
  • Parent Epic: #399

Background

The spec requires that MCP tools are registered in the Tool Registry with "extended capability metadata," including resource bindings that allow actors to use resource binding when invoking MCP tools. The MCPToolAdapter.infer_resource_slots() method correctly infers resource slots from MCP tool parameter schemas (e.g. file_path → file slot, directory → directory slot, repo_path → repository slot). However, the inferred slots are never wired into the domain Tool objects stored in the registry, making the entire resource slot inference pipeline dead code.

Additionally, a key name mismatch exists between register_tools() (which stores slots under source_metadata["resource_slots"]) and ToolRegistry.find_tools_for_resource() (which reads from source_metadata["resource_bindings"]), meaning MCP tools can never be discovered via resource-based lookup.

Current Behavior

In src/cleveragents/mcp/adapter.py, register_tools():

  1. Correctly calls self.infer_resource_slots(desc.name, desc.input_schema) to infer resource slots
  2. Converts them to slot_dicts (list of dicts with name, resource_type, access, binding)
  3. Stores them in source_metadata["resource_slots"] on the ToolSpec

However, a TODO comment in the code (referencing issue #882) explicitly acknowledges that nothing downstream reads source_metadata["resource_slots"]:

# TODO(#882): resource_slots are stored in source_metadata but
# nothing downstream reads them yet.  The ToolRegistry persists
# resource bindings via domain Tool.resource_slots, and the DB
# migration (c1_001) stores them in tool_resource_bindings.
# A follow-up ticket should wire inferred slots into the domain
# Tool objects so the registry and DB actually consume them.

As a result:

  • domain Tool.resource_slots is never populated from MCP tool inference
  • The database table tool_resource_bindings is never populated for MCP tools
  • ToolRegistry.find_tools_for_resource() reads source_metadata["resource_bindings"] but the key stored is "resource_slots" — a key name mismatch that guarantees MCP tools are never returned

Steps to reproduce:

  1. Create an MCP adapter with a tool that has file_path in its schema
  2. Register the tool with register_tools(registry, "mcp-fs")
  3. Call registry.find_tools_for_resource("file", type_registry)
  4. Observe: returns empty list (should return the MCP tool)

Affected code locations:

  • src/cleveragents/mcp/adapter.pyregister_tools(): stores slots under "resource_slots" key
  • src/cleveragents/tool/registry.pyfind_tools_for_resource(): reads from "resource_bindings" key

Expected Behavior

Per the specification, MCP tools registered via MCPToolAdapter.register_tools() must:

  1. Have their inferred resource slots wired into the domain Tool.resource_slots field
  2. Have their resource bindings persisted to the tool_resource_bindings database table
  3. Be discoverable via ToolRegistry.find_tools_for_resource() when a matching resource type is queried
  4. Use a consistent key name ("resource_bindings") across both register_tools() and find_tools_for_resource()

Subtasks

  • Audit MCPToolAdapter.register_tools() in src/cleveragents/mcp/adapter.py to understand the full slot inference → ToolSpecTool pipeline
  • Fix the key name mismatch: rename source_metadata["resource_slots"] to source_metadata["resource_bindings"] in register_tools() (or update find_tools_for_resource() to read the correct key — whichever is canonical per spec)
  • Wire the inferred slot_dicts into the domain Tool.resource_slots field when constructing/registering the Tool object in the registry
  • Ensure tool_resource_bindings DB rows are created for MCP tools during register_tools() (or verify the registry handles this automatically once Tool.resource_slots is populated)
  • Remove the TODO comment referencing #882 once the wiring is complete
  • Write Behave unit tests (in features/) covering:
    • register_tools() with a schema containing file_pathTool.resource_slots contains a file slot
    • register_tools() with a schema containing repo_pathTool.resource_slots contains a repository slot
    • find_tools_for_resource("file", ...) returns the MCP tool after registration
  • Write Robot Framework integration test (in robot/) verifying end-to-end resource binding for a registered MCP tool
  • Run nox to confirm all quality gates pass

Definition of Done

  • MCPToolAdapter.register_tools() correctly populates domain Tool.resource_slots from inferred resource slots
  • ToolRegistry.find_tools_for_resource() returns MCP tools when queried with a matching resource type
  • The source_metadata key name is consistent between register_tools() and find_tools_for_resource()
  • tool_resource_bindings DB rows are created for MCP tools upon registration
  • The TODO comment referencing #882 is removed from adapter.py
  • All Behave unit tests pass (nox -e unit_tests)
  • All Robot Framework integration tests pass (nox -e integration_tests)
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Metadata - **Branch**: `fix/mcp-adapter-resource-slot-wiring` - **Commit Message**: `fix(mcp): wire inferred resource slots into domain Tool objects in MCPToolAdapter` - **Milestone**: v3.8.0 - **Parent Epic**: #399 ## Background The spec requires that MCP tools are registered in the Tool Registry with "extended capability metadata," including resource bindings that allow actors to use resource binding when invoking MCP tools. The `MCPToolAdapter.infer_resource_slots()` method correctly infers resource slots from MCP tool parameter schemas (e.g. `file_path` → file slot, `directory` → directory slot, `repo_path` → repository slot). However, the inferred slots are never wired into the domain `Tool` objects stored in the registry, making the entire resource slot inference pipeline dead code. Additionally, a key name mismatch exists between `register_tools()` (which stores slots under `source_metadata["resource_slots"]`) and `ToolRegistry.find_tools_for_resource()` (which reads from `source_metadata["resource_bindings"]`), meaning MCP tools can never be discovered via resource-based lookup. ## Current Behavior In `src/cleveragents/mcp/adapter.py`, `register_tools()`: 1. Correctly calls `self.infer_resource_slots(desc.name, desc.input_schema)` to infer resource slots 2. Converts them to `slot_dicts` (list of dicts with `name`, `resource_type`, `access`, `binding`) 3. Stores them in `source_metadata["resource_slots"]` on the `ToolSpec` However, a TODO comment in the code (referencing issue #882) explicitly acknowledges that nothing downstream reads `source_metadata["resource_slots"]`: ```python # TODO(#882): resource_slots are stored in source_metadata but # nothing downstream reads them yet. The ToolRegistry persists # resource bindings via domain Tool.resource_slots, and the DB # migration (c1_001) stores them in tool_resource_bindings. # A follow-up ticket should wire inferred slots into the domain # Tool objects so the registry and DB actually consume them. ``` As a result: - `domain Tool.resource_slots` is never populated from MCP tool inference - The database table `tool_resource_bindings` is never populated for MCP tools - `ToolRegistry.find_tools_for_resource()` reads `source_metadata["resource_bindings"]` but the key stored is `"resource_slots"` — a key name mismatch that guarantees MCP tools are never returned **Steps to reproduce:** 1. Create an MCP adapter with a tool that has `file_path` in its schema 2. Register the tool with `register_tools(registry, "mcp-fs")` 3. Call `registry.find_tools_for_resource("file", type_registry)` 4. Observe: returns empty list (should return the MCP tool) **Affected code locations:** - `src/cleveragents/mcp/adapter.py` — `register_tools()`: stores slots under `"resource_slots"` key - `src/cleveragents/tool/registry.py` — `find_tools_for_resource()`: reads from `"resource_bindings"` key ## Expected Behavior Per the specification, MCP tools registered via `MCPToolAdapter.register_tools()` must: 1. Have their inferred resource slots wired into the domain `Tool.resource_slots` field 2. Have their resource bindings persisted to the `tool_resource_bindings` database table 3. Be discoverable via `ToolRegistry.find_tools_for_resource()` when a matching resource type is queried 4. Use a consistent key name (`"resource_bindings"`) across both `register_tools()` and `find_tools_for_resource()` ## Subtasks - [ ] Audit `MCPToolAdapter.register_tools()` in `src/cleveragents/mcp/adapter.py` to understand the full slot inference → `ToolSpec` → `Tool` pipeline - [ ] Fix the key name mismatch: rename `source_metadata["resource_slots"]` to `source_metadata["resource_bindings"]` in `register_tools()` (or update `find_tools_for_resource()` to read the correct key — whichever is canonical per spec) - [ ] Wire the inferred `slot_dicts` into the domain `Tool.resource_slots` field when constructing/registering the `Tool` object in the registry - [ ] Ensure `tool_resource_bindings` DB rows are created for MCP tools during `register_tools()` (or verify the registry handles this automatically once `Tool.resource_slots` is populated) - [ ] Remove the TODO comment referencing #882 once the wiring is complete - [ ] Write Behave unit tests (in `features/`) covering: - `register_tools()` with a schema containing `file_path` → `Tool.resource_slots` contains a file slot - `register_tools()` with a schema containing `repo_path` → `Tool.resource_slots` contains a repository slot - `find_tools_for_resource("file", ...)` returns the MCP tool after registration - [ ] Write Robot Framework integration test (in `robot/`) verifying end-to-end resource binding for a registered MCP tool - [ ] Run `nox` to confirm all quality gates pass ## Definition of Done - [ ] `MCPToolAdapter.register_tools()` correctly populates `domain Tool.resource_slots` from inferred resource slots - [ ] `ToolRegistry.find_tools_for_resource()` returns MCP tools when queried with a matching resource type - [ ] The `source_metadata` key name is consistent between `register_tools()` and `find_tools_for_resource()` - [ ] `tool_resource_bindings` DB rows are created for MCP tools upon registration - [ ] The TODO comment referencing #882 is removed from `adapter.py` - [ ] All Behave unit tests pass (`nox -e unit_tests`) - [ ] All Robot Framework integration tests pass (`nox -e integration_tests`) - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.8.0 milestone 2026-04-05 02:54:22 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Confirmed
  • MoSCoW: Should Have

Valid finding verified during batch triage.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Confirmed - **MoSCoW**: Should Have Valid finding verified during batch triage. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#399 Epic: Post-MVP Server & Clients
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2946
No description provided.