Skip to content

feat(tools): add cueapi_fire_cue (supersedes #7 with review fixes)#9

Merged
govindkavaturi-art merged 2 commits intomainfrom
add-fire-cue-tool
May 1, 2026
Merged

feat(tools): add cueapi_fire_cue (supersedes #7 with review fixes)#9
govindkavaturi-art merged 2 commits intomainfrom
add-fire-cue-tool

Conversation

@govindkavaturi-art
Copy link
Copy Markdown
Member

Supersedes #7. Same feature (Mike's cueapi_fire_cue MCP tool wrapping POST /v1/cues/{id}/fire) plus three review fixes applied as a follow-up commit:

  1. Fixed default merge_strategy mismatch — schema described default as 'replace', but the API's Pydantic default in app/schemas/cue.py is 'merge'. Reordered enum + corrected description.
  2. Softened tool description — dropped the "messaging channel between agents" framing (that pattern is what the v1 messaging primitive in cueapi/cueapi#457/#458 is designed to replace). Reframed to "fire an existing cue" — what the tool actually does.
  3. Filled test gap — added two cases: merge_strategy='merge' explicitly passed, and payload_override without merge_strategy (pins the contract that the handler omits the field, leaving server's Pydantic default to apply).

Diff vs PR #7

Change File
Reorder enum + fix description src/tools.ts
Soften tool description src/tools.ts
Tighten changelog wording README.md
Add merge + omit-strategy tests tests/tools.test.ts

Everything else is identical to #7.

Tests

$ npm test
 ✓ tests/pkce.test.ts (8 tests)
 ✓ tests/tools.test.ts (14 tests)
 ✓ tests/oauth-flow.test.ts (13 tests)
 ✓ tests/token-store.test.ts (15 tests)

 Test Files  4 passed (4)
      Tests  50 passed (50)   (was 48 in #7; +2 from new fire_cue cases)

npm run build — clean.

🤖 Generated with Claude Code

mikemolinet and others added 2 commits May 1, 2026 15:54
Adds an MCP tool that wraps the existing POST /v1/cues/{id}/fire
endpoint, with optional payload_override and merge_strategy. The
existing tool surface covers create / list / get / pause / resume /
delete / list_executions / report_outcome — but not "fire an existing
cue right now," which is the primitive an agent needs for ad-hoc
one-shot triggers and for using cues as a lightweight messaging
channel between agents (carrying { message, instruction, task,
reply_cue_id } in payload_override).

Without this tool, MCP-host agents had to fall back to raw HTTP via
shell to invoke this endpoint, which is awkward and unguided.

- src/tools.ts: +27 LoC (Zod schema + tool definition)
- tests/tools.test.ts: +50 LoC (3 HTTP-contract tests mirroring the
  existing pause/resume pattern: empty-fire, payload_override + merge,
  url-encoded cue_id)
- README.md: add row to "Tools exposed" table + changelog entry
- package.json: bump 0.2.0 → 0.3.0

No backend changes — POST /v1/cues/{id}/fire already exists and is
used by the CLI today. All 48 tests pass (was 45).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small fixes from review of #7 before merge:

1. Default merge_strategy bug
   The MCP tool's schema description claimed "Default 'replace'", but
   the API's Pydantic default in app/schemas/cue.py is 'merge'. An
   agent reading the tool description would expect "no merge_strategy
   passed → replace semantics" when the actual server-side behavior is
   merge — silently wrong defaults that would surface hours later as
   "why did my override leave fields from the cue's stored payload".
   Reordered enum to ["merge", "replace"] (default-first) and fixed the
   description to match the server's contract.

2. Tool description framing
   Reframed away from "messaging channel between agents" toward what
   the tool actually does: fire an existing cue, optionally with
   per-fire dynamic data. The agent-to-agent messaging pattern via
   cue payload metadata is the failure-mode the v1 messaging primitive
   spec (PRs #457/#458 in cueapi/cueapi) is designed to replace; this
   MCP tool should be honest about being the "fire a cue" primitive,
   not the "messaging" workaround.

3. Test coverage gap
   The original 3 tests only exercised merge_strategy='replace' and
   the empty-body case. Added two:
     - merge_strategy='merge' explicitly passed (pins the most common
       real-world case — swap a few fields, keep the rest)
     - payload_override without merge_strategy (pins the contract that
       the handler omits the field rather than forcing a client-side
       default that would override server's Pydantic default)

Tests: 50/50 pass (was 48/48; +2 new). Build clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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