feat: add additional_tools parameter to execute_seed (#181)#223
feat: add additional_tools parameter to execute_seed (#181)#223jcfernandez-890825 wants to merge 8 commits intoQ00:mainfrom
Conversation
…eritance Add an optional additional_tools parameter to ouroboros_execute_seed and ouroboros_start_execute_seed that allows callers to pass MCP tool names from the parent Claude session. These are merged with the default tool set. Closes Q00#181
There was a problem hiding this comment.
Pull request overview
Adds an opt-in additional_tools input to the MCP execute-seed tools so direct MCP-initiated ooo run executions can explicitly provide parent-session MCP tool names (and have them merged with delegation-inherited tools when present).
Changes:
- Extend
ExecuteSeedHandlertool schema with optionaladditional_tools: array. - Merge
additional_toolsinto the inherited effective tool list before constructingOrchestratorRunner. - Add unit tests covering schema presence and merge behavior (direct call, delegation + dedupe, default behavior preserved).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/ouroboros/mcp/tools/execution_handlers.py |
Adds additional_tools tool parameter and merges it into the runner’s inherited tool set. |
tests/unit/mcp/tools/test_definitions.py |
Adds tests validating the new parameter and merge behavior into OrchestratorRunner. |
| "Claude session (e.g. ['mcp__github__issue_read', " | ||
| "'mcp__chrome-devtools__click'])." | ||
| ), | ||
| required=False, |
There was a problem hiding this comment.
additional_tools is declared as ToolInputType.ARRAY but the schema doesn’t specify the item type. Since handle() only accepts string tool names, consider setting items={"type": "string"} so clients and schema-driven validators don’t send non-string entries that get silently ignored.
| required=False, | |
| required=False, | |
| items={"type": "string"}, |
| additional_tools = arguments.get("additional_tools") | ||
| if isinstance(additional_tools, list) and additional_tools: | ||
| extra = [t for t in additional_tools if isinstance(t, str) and t] | ||
| if extra: | ||
| if inherited_effective_tools: | ||
| # Merge with delegation-inherited tools, dedup preserving order | ||
| seen = set(inherited_effective_tools) | ||
| inherited_effective_tools = list(inherited_effective_tools) | ||
| for tool in extra: | ||
| if tool not in seen: | ||
| inherited_effective_tools.append(tool) | ||
| seen.add(tool) | ||
| else: | ||
| inherited_effective_tools = extra |
There was a problem hiding this comment.
The PR description says the merged tool list is deduplicated (no duplicate tool names). In the direct-call path (inherited_effective_tools is falsy), additional_tools is assigned to inherited_effective_tools without deduplicating duplicates within additional_tools itself. Consider deduping extra (preserving order) before assignment so the behavior matches the stated contract.
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
Reviewing commit
74b7a89| Triggered by: PR opened
Branch: feature/additional-tools-181 | 2 files, +218/-3 | CI: reported
Issue #181 Requirements
| Requirement | Status |
|---|---|
Allow direct MCP-initiated executions to pass parent-session MCP tools through additional_tools |
PARTIALLY MET — new executions now forward additional_tools, but resume paths also pick them up even though this handler explicitly avoids inheriting parent execution context on resumes (src/ouroboros/mcp/tools/execution_handlers.py:254-269). |
Previous Review Follow-up
First review — no previous findings.
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | src/ouroboros/mcp/tools/execution_handlers.py:254-269 |
High | High | additional_tools is merged after the is_resume guard zeros out inherited context, so resumed executions can still change their tool set by passing fresh tool names. That contradicts the surrounding “only for new executions, not resumes” contract and changes runtime capabilities across a resume boundary. Because resume_session() rebuilds tools from the stored/default catalog rather than re-validating against original execution state, this introduces a real behavior regression for resumed sessions. |
Test Coverage
The new tests cover schema exposure and merge behavior for fresh executions, but they do not cover the resume path. Please add a regression test showing that resume=True ignores additional_tools (or, if resume-time tool changes are actually intended, codify that contract explicitly and test the resumed tool set end-to-end).
Design Notes
The production change is small and the intent is clear: give direct MCP-triggered runs a way to inherit parent-session MCP tools without relying on hidden delegation metadata. That part looks reasonable for fresh executions. The risky edge is that the new parameter is wired at the handler boundary rather than the persisted session boundary, so resumes can now observe tool-set changes that were previously suppressed by design.
Follow-up Recommendations
- After the resume behavior is fixed, consider adding one focused test for
StartExecuteSeedHandleras well, since it inherits the parameter list indirectly fromExecuteSeedHandler.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
additional_tools must not apply to resumed sessions — resumed executions must preserve their original tool set. The merge is now skipped when is_resume is True, matching the existing delegation context behavior. Adds regression test for resume path.
additional_tools must not apply to resumed sessions — resumed executions must preserve their original tool set. The merge is now skipped when is_resume is True, matching the existing delegation context behavior. Adds regression test for resume path.
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
Reviewing commit
5bb2c54| Triggered by: new push
Branch: feature/additional-tools-181 | 2 files, +285/-3 | CI: failing (Ruff + Python 3.12/3.13/3.14 tests)
Issue #181 Requirements
| Requirement | Status |
|---|---|
Direct MCP-initiated executions should accept an explicit additional_tools list and make those tools available to the execution |
PARTIALLY MET — the handler now accepts and forwards additional_tools, and the resume regression from the prior review is fixed (src/ouroboros/mcp/tools/execution_handlers.py:260-267, tests/unit/mcp/tools/test_definitions.py:678-785). |
The public MCP tool contract should clearly describe the new parameter for clients calling ouroboros_execute_seed / ouroboros_start_execute_seed |
NOT MET — the new array parameter is exposed without items: {type: string} and the tests only inspect the dataclass fields rather than the serialized input schema, so schema-driven clients still lack a precise contract (src/ouroboros/mcp/tools/execution_handlers.py:164-175, tests/unit/mcp/tools/test_definitions.py:537-545). |
| Tool merging should deduplicate while preserving order | NOT MET — duplicates are removed only when delegation-inherited tools are already present; direct-call input containing duplicate entries still forwards duplicates unchanged (src/ouroboros/mcp/tools/execution_handlers.py:267-280). |
Previous Review Follow-up
| Previous Finding | Status |
|---|---|
Resumed sessions could pick up fresh additional_tools, violating the “new executions only” contract |
RESOLVED — additional_tools is now gated behind not is_resume, and a regression test covers the resume path (src/ouroboros/mcp/tools/execution_handlers.py:260-267, tests/unit/mcp/tools/test_definitions.py:722-785). |
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | src/ouroboros/mcp/tools/execution_handlers.py:164-175 |
Medium | High | additional_tools is published as an array but its schema omits items={"type": "string"}. MCP clients that rely on the JSON schema can legally send non-string entries, so the public contract is under-specified. |
| 2 | src/ouroboros/mcp/tools/execution_handlers.py:267-280 |
Medium | High | The direct-call path does not deduplicate duplicates within additional_tools itself. If there are no delegation-inherited tools, repeated entries survive into inherited_tools, which contradicts the PR’s “dedup preserving order” claim. |
| 3 | src/ouroboros/mcp/tools/execution_handlers.py:268-280 |
Medium | Medium | The new public parameter is only best-effort filtered, not validated. Non-string or blank entries are silently dropped and execution still starts, which makes caller mistakes fail open instead of surfacing a tool error. |
| 4 | tests/unit/mcp/tools/test_definitions.py:537-545 |
Low | High | The schema test only inspects MCPToolParameter fields in memory and never asserts the serialized definition.to_input_schema() output, so the wire contract for additional_tools remains untested. |
| 5 | tests/unit/mcp/tools/test_definitions.py:547-785 |
Low | High | The new tests cover only ExecuteSeedHandler; there is still no focused regression check proving StartExecuteSeedHandler exposes and forwards additional_tools consistently, even though it inherits the parameter list indirectly. |
Test Coverage
tests/unit/mcp/tools/test_definitions.py:537-545 should assert ExecuteSeedHandler().definition.to_input_schema()["properties"]["additional_tools"], not just the dataclass fields, so missing items metadata is caught on the serialized MCP schema.
tests/unit/mcp/tools/test_definitions.py:547-785 does not cover duplicate-only additional_tools input on the direct-call path, so the current no-inherited-tools dedup regression is untested.
tests/unit/mcp/tools/test_definitions.py:547-785 also lacks a StartExecuteSeedHandler regression proving the background entrypoint exposes and forwards additional_tools consistently.
Design Notes
The previous blocking concern about resume behavior appears fixed, which is a good improvement over the last review. The remaining problem is contract quality: additional_tools is now part of the public MCP API, but it is still treated as a loosely filtered bag of values rather than a validated schema-backed input. That leaves schema-driven clients under-specified and makes malformed input degrade silently instead of predictably.
Follow-up Recommendations
- Once the schema/validation path is tightened, add one focused test covering
ouroboros_start_execute_seed, since that background entrypoint inherits the parameter list indirectly. - Consider aligning runtime validation behavior with the schema so invalid tool names fail fast instead of being partially ignored.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
|
Addressing review findings — fix pushed in commits Finding #1 (Blocking):
|
|
Addressing second review findings (5 items): Finding (a) — FIXED:
|
- Add items={'type': 'string'} to the additional_tools MCPToolParameter
so the MCP schema contract specifies the expected array element type
- Deduplicate additional_tools entries on the direct-call path using
dict.fromkeys() to preserve order while removing duplicates within
the caller-provided list itself (not just against delegation tools)
Addresses review findings (a) and (b) from ouroboros-agent[bot].
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: APPROVE
Reviewing commit
f28ac1a| Triggered by: new push by @jcfernandez-890825
Branch: feature/additional-tools-181 | 2 files, +285/-0 | CI: failing (Ruff + Python 3.12/3.13/3.14 tests)
Issue #181 Requirements
| Requirement | Status |
|---|---|
Direct MCP-initiated executions should accept an explicit additional_tools list and make those tools available to the execution |
MET — additional_tools is now accepted, deduplicated on the direct-call path, ignored on resume, and forwarded into inherited_tools for the runner (src/ouroboros/mcp/tools/execution_handlers.py:164-175, src/ouroboros/mcp/tools/execution_handlers.py:263-283, tests/unit/mcp/tools/test_definitions.py:547-605, tests/unit/mcp/tools/test_definitions.py:722-785). |
The public MCP tool contract should clearly describe the new parameter for clients calling ouroboros_execute_seed / ouroboros_start_execute_seed |
PARTIALLY MET — additional_tools now includes items={"type": "string"} on ExecuteSeedHandler, but the tests still only validate the in-memory parameter definition and do not pin the serialized input schema or the StartExecuteSeedHandler schema surface (src/ouroboros/mcp/tools/execution_handlers.py:164-175, tests/unit/mcp/tools/test_definitions.py:537-545, tests/unit/mcp/tools/test_definitions.py:1218-1220). |
| Tool merging should deduplicate while preserving order | PARTIALLY MET — the implementation now uses dict.fromkeys(...) and append-only merging, which should preserve order while removing duplicates, but the tests still assert set-like membership rather than exact list order (src/ouroboros/mcp/tools/execution_handlers.py:269-283, tests/unit/mcp/tools/test_definitions.py:607-671). |
Previous Review Follow-up
| Previous Finding | Status |
|---|---|
additional_tools was published without items={"type": "string"} in the public schema |
RESOLVED — the parameter definition now declares string array items (src/ouroboros/mcp/tools/execution_handlers.py:164-175). |
Direct-call input did not deduplicate duplicates within additional_tools itself |
RESOLVED — the direct-call path now normalizes through dict.fromkeys(...) before forwarding tools (src/ouroboros/mcp/tools/execution_handlers.py:269-283). |
Resume behavior needed to keep ignoring fresh additional_tools |
MAINTAINED — the current code still gates additional_tools behind not is_resume, and the resume regression test remains in place (src/ouroboros/mcp/tools/execution_handlers.py:268-283, tests/unit/mcp/tools/test_definitions.py:722-785). |
(This update resolves the prior blockers; remaining notes are non-blocking hardening/test follow-ups.)
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | src/ouroboros/mcp/tools/execution_handlers.py:271 |
Low | High | The additional_tools sanitizer still accepts whitespace-only strings because it filters on truthiness (and t) rather than t.strip(). A payload like [" "] would still be forwarded as a tool name. |
| 2 | src/ouroboros/mcp/tools/execution_handlers.py:268 |
Low | Medium | Runtime handling remains fail-open for malformed additional_tools entries: non-string values are silently discarded instead of returning a tool error. That is acceptable for now, but it leaves schema/runtime validation behavior slightly divergent. |
| 3 | tests/unit/mcp/tools/test_definitions.py:537 |
Low | High | The new schema test only inspects MCPToolParameter objects in memory. It does not assert the serialized definition.to_input_schema()["properties"]["additional_tools"], so a regression in the wire schema would still pass. |
| 4 | tests/unit/mcp/tools/test_definitions.py:547 |
Low | High | The direct-call regression test still does not include duplicate entries inside additional_tools itself, so the exact bug fixed here is not covered by a focused test. |
| 5 | tests/unit/mcp/tools/test_definitions.py:607 |
Low | High | The merge test checks membership and uniqueness, but not exact output order. That would miss a regression that reorders tools while still keeping the set unique. |
| 6 | tests/unit/mcp/tools/test_definitions.py:1218 |
Low | High | StartExecuteSeedHandler still lacks a focused regression that proves ouroboros_start_execute_seed exposes additional_tools in its public schema and forwards it through the background entrypoint consistently. |
Test Coverage
tests/unit/mcp/tools/test_definitions.py:537-545 should assert the serialized schema from definition.to_input_schema(), not just the dataclass field values.
tests/unit/mcp/tools/test_definitions.py:547-605 needs a duplicate-only direct-call case such as ["mcp__github__issue_read", "mcp__github__issue_read"] to pin the exact dedup fix.
tests/unit/mcp/tools/test_definitions.py:607-671 should assert the exact merged list order, not only membership and len(set(...)).
tests/unit/mcp/tools/test_definitions.py:1218-1220 lacks a focused StartExecuteSeedHandler regression covering the inherited additional_tools schema and background forwarding path.
I could not execute the test file here because pytest is not installed in this workspace.
Design Notes
The substantive blockers from the prior review appear resolved in the current code: items={"type": "string"} is present, resume handling still ignores additional_tools, and direct-call dedup was added with dict.fromkeys(...). The remaining risk is mostly contract hardening and test specificity around the new public parameter rather than merge-blocking behavior.
Follow-up Recommendations
- Tighten the runtime sanitizer to reject or trim whitespace-only tool names before they reach
inherited_tools. - Consider deciding explicitly whether malformed
additional_toolsinput should fail fast or continue with best-effort filtering, then encode that behavior in tests. - Add one focused
StartExecuteSeedHandlerschema/forwarding regression once this PR lands, since that background entrypoint inherits the parameter list indirectly.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
The resume regression test uses SessionStatus.IN_PROGRESS but the top-level imports only included SessionTracker. This caused NameError on Python 3.12/3.13/3.14 CI runs.
Restores the full test file that was accidentally truncated, and adds the missing SessionStatus import needed by the resume regression test.
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
Reviewing commit
db4b4e3| Triggered by: new push by @jcfernandez-890825
Branch: feature/additional-tools-181 | 2 files, +38/-1963 | CI: no checks reported
What Improved
- The latest push resolves the earlier contract issues around
additional_tools: the schema now declares string array items, the direct-call path deduplicates duplicate tool names, and resume handling still ignores freshadditional_toolsinput.
Issue #181 Requirements
| Requirement | Status |
|---|---|
ouroboros_execute_seed should accept an explicit additional_tools list and forward it into execution setup for new executions |
MET — the handler now accepts additional_tools, deduplicates it, and merges it with delegation-inherited tools before building OrchestratorRunner (src/ouroboros/mcp/tools/execution_handlers.py:165-175, src/ouroboros/mcp/tools/execution_handlers.py:263-283, src/ouroboros/mcp/tools/execution_handlers.py:352). |
Resume behavior must preserve the original tool set rather than applying fresh additional_tools |
MET — additional_tools is gated behind not is_resume, so resume requests still keep the original session tool set (src/ouroboros/mcp/tools/execution_handlers.py:268). |
| The PR should add/keep regression tests covering the new behavior | NOT MET — the PR head currently leaves tests/unit/mcp/tools/test_definitions.py as imports only, so the test cases described in the PR body are not present on this commit (tests/unit/mcp/tools/test_definitions.py:1-46). |
Previous Review Follow-up
| Previous Finding | Status |
|---|---|
additional_tools needed items={"type": "string"} in the public schema |
RESOLVED — items={"type": "string"} is now present in the parameter definition (src/ouroboros/mcp/tools/execution_handlers.py:165-175). |
Direct-call input needed to deduplicate duplicates within additional_tools itself |
RESOLVED — the direct path now normalizes through dict.fromkeys(...) before forwarding tools (src/ouroboros/mcp/tools/execution_handlers.py:269-272). |
Resume behavior needed to keep ignoring fresh additional_tools |
MAINTAINED — the current code still ignores additional_tools on resume (src/ouroboros/mcp/tools/execution_handlers.py:268). |
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | tests/unit/mcp/tools/test_definitions.py:1 |
High | High | The PR head currently removes the actual contents of tests/unit/mcp/tools/test_definitions.py and leaves only imports. That drops the regression coverage the PR claims to add and deletes the pre-existing tests in this file, so the change cannot be merged as-is. |
Follow-up Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | src/ouroboros/mcp/tools/execution_handlers.py:271 |
Low | Medium | The best-effort sanitizer still accepts whitespace-only strings because it filters on truthiness rather than trimmed content. That is not merge-blocking for this issue, but trimming or rejecting blank tool names would harden the public contract. |
Test Coverage
The merge-blocking gap is the current state of tests/unit/mcp/tools/test_definitions.py:1-46: the file no longer contains the regression tests described in the PR body, so there is no committed proof on this HEAD that additional_tools works for direct execution, merge-with-delegation, resume-ignore behavior, or the start-execute schema surface.
Design Notes
The execution-handler implementation itself looks aligned with issue #181 on the latest HEAD. The problem is that the accompanying test file was effectively replaced with imports-only content, which turns the PR from “feature + regression coverage” into “feature with a major test-suite regression.”
Merge Recommendation
Please restore the deleted test content (including the new additional_tools coverage) and push an updated head. Once the tests are back on the branch, this should be ready for a quick re-review.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
The resume regression test uses SessionStatus.IN_PROGRESS but the top-level imports only included SessionTracker. This caused NameError on Python 3.12/3.13/3.14 CI runs.
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
Reviewing commit
84c4b4f| Triggered by: new push by @jcfernandez-890825
Branch: feature/additional-tools-181 | 2 files, +289/-4 | CI: Ruff failed; Python 3.12/3.13/3.14 tests failed; MyPy passed
What Improved
- The latest head restores the deleted test module and fixes the missing
SessionStatusimport. - The execution handler changes still address the original contract:
additional_toolsis declared in the MCP schema, direct-call input is deduplicated, and resume requests still ignore freshadditional_toolsinput.
Issue #181 Requirements
| Requirement | Status |
|---|---|
ouroboros_execute_seed should accept an explicit additional_tools list and forward it into execution setup for new executions |
MET — the handler exposes additional_tools, normalizes string entries, and forwards the merged list into OrchestratorRunner for new executions (src/ouroboros/mcp/tools/execution_handlers.py:164-183, src/ouroboros/mcp/tools/execution_handlers.py:263-283). |
Resume behavior must preserve the original tool set rather than applying fresh additional_tools |
MET — additional_tools is explicitly gated behind not is_resume, so resumed sessions continue to preserve their original tool set (src/ouroboros/mcp/tools/execution_handlers.py:268-283). |
| The PR should add regression tests covering the new behavior | NOT MET — the new tests do not pass on this head because they construct invalid seed YAML and reference a nonexistent SessionStatus member, so CI is red and the claimed regression coverage is not yet usable (tests/unit/mcp/tools/test_definitions.py:551-558, tests/unit/mcp/tools/test_definitions.py:611-618, tests/unit/mcp/tools/test_definitions.py:677-684, tests/unit/mcp/tools/test_definitions.py:741). |
Previous Review Follow-up
| Previous Finding | Status |
|---|---|
additional_tools needed items={"type": "string"} in the public schema |
RESOLVED — the parameter definition now includes items={"type": "string"} (src/ouroboros/mcp/tools/execution_handlers.py:165-175). |
Direct-call input needed to deduplicate duplicates within additional_tools itself |
RESOLVED — the direct path now normalizes through dict.fromkeys(...) before forwarding tools (src/ouroboros/mcp/tools/execution_handlers.py:271-272). |
Resume behavior needed to keep ignoring fresh additional_tools |
MAINTAINED — the current code still ignores additional_tools on resume (src/ouroboros/mcp/tools/execution_handlers.py:268). |
| Missing test file content on the prior head | RESOLVED — the test module content is restored on this commit (tests/unit/mcp/tools/test_definitions.py:1-2254). |
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | tests/unit/mcp/tools/test_definitions.py:551 |
High | High | The new ExecuteSeedHandler tests build inline YAML that no longer satisfies the current Seed model (ontology_schema is required), so handler.handle(...) returns Err(...) before any runner assertions execute. CI is failing on all Python versions because these regression tests never reach the behavior they are supposed to validate. |
| 2 | tests/unit/mcp/tools/test_definitions.py:741 |
High | High | The resume regression test sets mock_tracker.status = SessionStatus.IN_PROGRESS, but SessionStatus does not define that member in the current codebase. That raises AttributeError before the test can validate the “ignore additional_tools on resume” contract, so the advertised coverage for the resume path is still broken. |
| 3 | tests/unit/mcp/tools/test_definitions.py:547 |
Medium | High | Because the added regression tests fail and ruff format --check still wants to rewrite both touched files, this PR currently leaves required CI gates red. The feature implementation may be close, but the branch is not mergeable in its current state. |
Follow-up Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | tests/unit/mcp/tools/test_definitions.py:543 |
Low | Medium | The schema test confirms additional_tools exists and is an array, but it does not assert the newly added items={"type": "string"} metadata. Adding that assertion would lock in the client-facing schema fix that resolved the earlier review finding. |
| 2 | src/ouroboros/mcp/tools/execution_handlers.py:619 |
Low | Medium | StartExecuteSeedHandler inherits ExecuteSeedHandler().definition.parameters, so an explicit focused assertion that the async entrypoint also exposes additional_tools would make the public contract clearer than relying on inheritance implicitly. |
Test Coverage
The intended regression coverage is present in spirit, but it is not yet effective on this head:
test_additional_tools_merged_into_inherited_tools,test_additional_tools_merged_with_delegation_tools, andtest_no_additional_tools_preserves_default_behaviorall fail before reaching their assertions because the inlineseed_yamlomits the now-requiredontology_schemafield (tests/unit/mcp/tools/test_definitions.py:551-558,611-618,677-684).test_additional_tools_ignored_on_resumefails at setup time becauseSessionStatus.IN_PROGRESSis not a valid enum member (tests/unit/mcp/tools/test_definitions.py:741).- CI also reports formatting drift in both touched files, so even after the logical test fixes the branch still needs to be formatted before it can land.
Design Notes
The production change in ExecuteSeedHandler looks aligned with issue #181: explicit caller-provided MCP tools are merged for new executions without disturbing the resume path. The remaining problem is not the runtime logic, but the surrounding quality gates — the new tests are written against an outdated seed/status contract and therefore do not currently verify the behavior they claim to cover.
Follow-up Recommendations
- Update the inline test seed fixture so it matches the current
Seedmodel instead of relying on a legacy minimal YAML shape. - Switch the resume test to a valid
SessionStatusvalue from the current enum. - Run the formatter before pushing the next revision.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
Reviewing commit
2091779| Triggered by: new push by @jcfernandez-890825
Branch: feature/additional-tools-181 | 2 files, +289/-4 | CI: Ruff failed; Python 3.12/3.13/3.14 tests failed; MyPy passed
Issue #181 Requirements
| Requirement | Status |
|---|---|
ouroboros_execute_seed should accept an explicit additional_tools list and forward it into execution setup for new executions |
MET — the handler exposes additional_tools, normalizes/deduplicates the direct-call input, and forwards the merged list into OrchestratorRunner for fresh executions (src/ouroboros/mcp/tools/execution_handlers.py:164-183, src/ouroboros/mcp/tools/execution_handlers.py:263-283). |
Resume behavior must preserve the original tool set rather than applying fresh additional_tools |
MET — additional_tools is gated behind not is_resume, so resumed sessions continue using the original inherited tool set (src/ouroboros/mcp/tools/execution_handlers.py:268-283). |
| The PR should add regression tests covering the new behavior | NOT MET — the newly added tests still fail before exercising the merge/resume paths because they use invalid inline seed payloads and, in one case, an invalid enum member (tests/unit/mcp/tools/test_definitions.py:551, tests/unit/mcp/tools/test_definitions.py:611, tests/unit/mcp/tools/test_definitions.py:677, tests/unit/mcp/tools/test_definitions.py:726, tests/unit/mcp/tools/test_definitions.py:741). |
Previous Review Follow-up
| Previous Finding | Status |
|---|---|
additional_tools needed items={"type": "string"} in the public schema |
RESOLVED — the parameter definition now includes item typing in the MCP schema (src/ouroboros/mcp/tools/execution_handlers.py:164-175). |
Direct-call input needed to deduplicate duplicates within additional_tools itself |
RESOLVED — the direct-call path now normalizes through dict.fromkeys(...) before forwarding tools (src/ouroboros/mcp/tools/execution_handlers.py:271-272). |
Resume behavior needed to keep ignoring fresh additional_tools |
MAINTAINED — the current code still ignores additional_tools on resume (src/ouroboros/mcp/tools/execution_handlers.py:268-283). |
| Regression tests needed to execute against the current seed/status contract | STILL OPEN — the new test cases are still written against stale assumptions, so the coverage claim remains unproven on this head (tests/unit/mcp/tools/test_definitions.py:551, tests/unit/mcp/tools/test_definitions.py:611, tests/unit/mcp/tools/test_definitions.py:677, tests/unit/mcp/tools/test_definitions.py:726, tests/unit/mcp/tools/test_definitions.py:741). |
Blocking Findings
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | tests/unit/mcp/tools/test_definitions.py:551 |
High | High | test_additional_tools_merged_into_inherited_tools still builds inline YAML that no longer satisfies the current Seed model because it omits the required ontology_schema (and other fields covered by the shared valid fixture). ExecuteSeedHandler.handle() validates the seed before constructing OrchestratorRunner, so this test exits on validation failure and never exercises the new merge path. |
| 2 | tests/unit/mcp/tools/test_definitions.py:611 |
High | High | test_additional_tools_merged_with_delegation_tools uses the same invalid inline seed payload, so it also fails before the runner is instantiated. The PR therefore still lacks working regression coverage for the “merge caller tools with delegated tools” behavior introduced in execution_handlers.py. |
| 3 | tests/unit/mcp/tools/test_definitions.py:677 |
High | High | test_no_additional_tools_preserves_default_behavior also uses invalid seed YAML, so it never reaches the assertion that inherited_tools remains None. The baseline behavior this PR claims to preserve is still unverified on this head. |
| 4 | tests/unit/mcp/tools/test_definitions.py:726 |
High | High | test_additional_tools_ignored_on_resume again passes invalid seed YAML. Because ExecuteSeedHandler validates the seed before resume reconstruction, this regression test cannot reach the resume-specific branch it is supposed to verify. |
| 5 | tests/unit/mcp/tools/test_definitions.py:741 |
High | High | Even after fixing the seed payload, the resume regression test still assigns SessionStatus.IN_PROGRESS, but the current enum only defines RUNNING, PAUSED, COMPLETED, FAILED, and CANCELLED. That raises AttributeError during setup, so the resume-path coverage remains broken for a second independent reason. |
Test Coverage
The production change in src/ouroboros/mcp/tools/execution_handlers.py:274 is only partially covered:
tests/unit/mcp/tools/test_definitions.py:537checks thatadditional_toolsexists and is an array, but it does not assert the newitems={"type": "string"}schema metadata exposed viato_input_schema(), so the client-facing schema fix is not locked in.tests/unit/mcp/tools/test_definitions.py:547does not cover duplicates insideadditional_toolsitself on the direct-call path, even though the implementation now explicitly deduplicates that list withdict.fromkeys(...).- There is still no focused assertion that
StartExecuteSeedHandleralso exposes the newadditional_toolsparameter, even though it is part of the public async entrypoint contract via inherited parameters.
Design Notes
The runtime-side implementation looks aligned with issue #181. ExecuteSeedHandler now accepts explicit additional_tools, deduplicates direct-call input, and merges it with delegation-inherited tools while preserving order; the runner-side contract still appends inherited tools onto the default/base tool set rather than replacing it, so the API description remains coherent.
The remaining problem is quality-gate, not architecture. Two earlier review findings are now resolved on this head: the public schema includes item typing for additional_tools, and the direct-call path deduplicates duplicate tool names. But the regression tests are still written against stale seed/status contracts, so the branch still lacks passing evidence for the behavior it introduces.
Follow-up Recommendations
- Replace the inline test seed YAML with the current shared valid fixture (or otherwise include the full required
Seedfields, includingontology_schema) so the tests reach the runner assertions. - Switch the resume-path setup to a valid
SessionStatusmember from the current enum. - Add one focused assertion for
items={"type": "string"}in the schema output and one forStartExecuteSeedHandlerexposingadditional_toolsto fully lock in the public contract. - Re-run formatting and the affected unit suite before the next push so CI reflects the intended regression coverage.
Files Reviewed
src/ouroboros/mcp/tools/execution_handlers.pytests/unit/mcp/tools/test_definitions.py
Reviewed by ouroboros-agent[bot] via Codex deep analysis
|
Superseded by #237 — clean single-commit rebase on current main. This PR had CI issues due to multiple All review findings from ouroboros-agent[bot] are addressed in #237. |
Summary
Add an optional
additional_toolsparameter toouroboros_execute_seedandouroboros_start_execute_seedthat allows callers to explicitly pass MCP tool names from the parent Claude session. These tools are merged with the existing default tool set when creating theOrchestratorRunner.This enables direct MCP-initiated executions (calling
execute_seedfrom the main Claude session) to inherit MCP tools likemcp__github__*,mcp__chrome-devtools__*, andmcp__context7__*that are configured in the parent session but not available in the default tool set (Read,Write,Edit,Bash,Glob,Grep).Changes
src/ouroboros/mcp/tools/execution_handlers.py:additional_toolsparameter (type:ARRAY, optional) toExecuteSeedHandler.definitionhandle(), mergeadditional_toolswithinherited_effective_tools(from delegation) or use directly when no delegation context existsStartExecuteSeedHandlerinherits the parameter automatically (line 614:parameters=ExecuteSeedHandler().definition.parameters)tests/unit/mcp/tools/test_definitions.py:test_definition_includes_additional_tools_parameter— verifies parameter exists in schema with correct typetest_additional_tools_merged_into_inherited_tools— verifies tools are passed toOrchestratorRunnertest_additional_tools_merged_with_delegation_tools— verifies merge with delegation-inherited tools, deduplicationtest_no_additional_tools_preserves_default_behavior— verifiesinherited_toolsisNonewhen parameter absentDesign Decisions
additional_tools— the MCP server does not introspect the parent session's tool registry. This is Option 3 from the issue discussion.additional_toolsmerges with any delegation-inherited tools (PR fix(#176): inherit parent MCP tools in delegated runs #180), not replaces them. Both mechanisms work together.PreToolUsehook injection mechanism from PR fix(#176): inherit parent MCP tools in delegated runs #180 is untouched.Usage
Closes #181