Skip to content

feat(tools): add cueapi_fire_cue for firing existing cues#7

Closed
mikemolinet wants to merge 1 commit intocueapi:mainfrom
mikemolinet:add-fire-cue-tool
Closed

feat(tools): add cueapi_fire_cue for firing existing cues#7
mikemolinet wants to merge 1 commit intocueapi:mainfrom
mikemolinet:add-fire-cue-tool

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Adds a cueapi_fire_cue MCP tool that wraps the existing POST /v1/cues/{id}/fire endpoint, with optional payload_override and merge_strategy ('replace' | 'merge').

The current 8-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:

  1. Ad-hoc one-shot triggers — fire a cue immediately rather than scheduling a new one.
  2. Using cues as a lightweight messaging channel between agents — carrying { message, instruction, task, reply_cue_id } in payload_override is a common pattern for agent-to-agent coordination via existing cues; this turns it into a typed MCP tool instead of forcing the agent to fall back to raw HTTP via shell.

The endpoint already exists and is used by the CLI today, so no backend changes are needed — this is purely an MCP wrapper.

Changes

File Change
src/tools.ts +27 LoC: fireCueSchema (Zod) + cueapi_fire_cue tool definition
tests/tools.test.ts +50 LoC: 3 HTTP-contract tests mirroring the existing cueapi_pause_cue / cueapi_resume_cue pattern (empty fire, with payload_override + merge_strategy, url-encoded cue_id)
README.md Add row to "Tools exposed" table + changelog entry
package.json Bump 0.2.00.3.0 (minor — additive new feature)

Tool shape

cueapi_fire_cue({
  cue_id: 'cue_...',
  payload_override?: { message, instruction, task, reply_cue_id, routing, from, ... },
  merge_strategy?: 'replace' | 'merge'  // default 'replace'
})

Tests

npm test — all 48 tests pass (was 45 before, +3 new fire_cue HTTP-contract tests).

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

 Test Files  4 passed (4)
      Tests  48 passed (48)

npm run build — clean.

Notes

  • Test pattern intentionally mirrors the existing cueapi_pause_cue / cueapi_resume_cue HTTP-contract test block, which exists for the same reason (pin the handler's HTTP behavior so a regression to a wrong path/method is caught at CI rather than runtime).
  • Tool description text explicitly mentions both use cases (one-shot trigger AND agent-to-agent messaging) so MCP-host agents discover the right pattern from the tool surface alone.
  • Considered also adding cueapi_get_execution (single-execution lookup; currently only list_executions exists) as a companion add for the "did my fire land" follow-up path. Held back to keep this PR focused; happy to do it as a follow-up if you'd like.

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>
govindkavaturi-art added a commit that referenced this pull request May 1, 2026
* feat(tools): add cueapi_fire_cue for firing existing cues

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>

* fix: correct merge_strategy default + soften tool description

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>

---------

Co-authored-by: mikemolinet <mike@vector.build>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Gk <gk@Gks-MacBook-Pro.local>
@govindkavaturi-art
Copy link
Copy Markdown
Member

Superseded by #9 (merged at 23:04:57Z, commit 70866004).

Same feature, plus three review fixes applied as a follow-up commit:

  1. Fixed merge_strategy default mismatch — schema said 'replace' but API default is 'merge'.
  2. Softened tool description away from "agent-to-agent messaging" framing (that's what the v1 messaging primitive in cueapi/cueapi#457/#458 is designed to replace; this MCP tool is honest as just "fire an existing cue").
  3. Added two missing test cases (merge_strategy='merge' explicit, and the omit-strategy contract pinning).

Tests: 50/50 pass (was 48). Thanks Mike — feature was clean, the only friction was the default-doc mismatch and the framing.

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