Skip to content

Add Kody job update and delete capabilities - #331

Merged
kentcdodds merged 4 commits into
mainfrom
cursor/kody-job-capabilities-29b0
May 2, 2026
Merged

kentcdodds merged 4 commits into
mainfrom
cursor/kody-job-capabilities-29b0

Conversation

@kentcdodds

@kentcdodds kentcdodds commented May 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add job_update and job_delete to the jobs capability domain and registry metadata
  • reuse the existing jobs service mutations so user scoping, vector updates, and alarm sync stay consistent
  • document and test the new job mutation flows for discovery and supported behavior

Behavior

  • job_delete hard-deletes a scheduled job by id for the signed-in user
  • job_update supports safe mutable fields only: name, code, params, schedule, timezone, enabled, and kill_switch_enabled
  • jobs remain user-scoped by id, so another user receives the same not-found behavior as job_get / job_list
  • job_list and job_get already reflect disabled and kill-switched state, so no separate deletion tombstone was introduced

Intentionally unsupported

  • MCP job_update does not expose internal source reassignment or publish metadata fields such as sourceId, publishedCommit, or repoCheckPolicy
  • mutation is by job id only; duplicate job names are not used as selectors

Validation

  • npm run test -- packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts packages/worker/src/jobs/service.node.test.ts
  • npm run test -- packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
  • npm run test -- packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
  • npm run typecheck
  • npm run build
  • npm run format:check -- docs/use/execute.md docs/use/first-steps.md docs/use/packages.md packages/worker/src/mcp/capabilities/jobs/job-delete.ts packages/worker/src/mcp/capabilities/jobs/job-update.ts packages/worker/src/mcp/capabilities/jobs/shared.ts packages/worker/src/mcp/capabilities/jobs/domain.ts packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts packages/worker/src/jobs/service.node.test.ts packages/worker/src/mcp/jobs-embed.ts packages/worker/src/mcp/server-instructions.ts

Notes

  • follow-up review fix: docs now explicitly mention renaming and kill-switch toggling in job_update
  • follow-up review fix: capability tests now cover once-schedule input mapping from run_at to runAt
  • follow-up review fix: auth-negative tests now cover job_schedule_once alongside job_schedule, job_update, job_delete, and job_run_now
  • I did not act on the generic CodeRabbit docstring-coverage warning because it is repo-wide/non-specific and not a validated jobs-domain defect for this PR
  • npm run lint -- ... exits successfully in this repo but still reports unrelated pre-existing warnings from untouched files, so I did not treat those as blockers for this jobs-scoped change.
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Add ability to update scheduled jobs (schedule, timezone, enabled state, params, or code) and to delete jobs by id.
  • Documentation

    • Clarified guides and examples for scheduling, one-off runs, updating, deleting, and triggering jobs.
  • Tests

    • Added tests covering update/delete flows, authorization, validation, and mapping of one-off schedules.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented May 2, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds MCP job-mutation capabilities: job_update (modify safe mutable fields of an existing scheduled job) and job_delete (remove a scheduled job by id). Changes include Zod schemas, resolver helpers, service wiring, MCP capability definitions, tests, domain registration, usage/instruction text, and docs.

Changes

Job Update & Delete Capabilities

Layer / File(s) Summary
Data Shapes & Schemas
packages/worker/src/mcp/capabilities/jobs/shared.ts
Adds jobUpdateInputSchema (optional mutable fields, .refine() requiring ≥1 field), jobDeleteInputSchema, jobDeleteOutputSchema, and exported types JobUpdateCapabilityInput / JobDeleteCapabilityInput.
Request → Service Mapping
packages/worker/src/mcp/capabilities/jobs/shared.ts
Adds resolveJobUpdateBody() to map MCP input to JobUpdateInput (handles kill_switch_enabled → killSwitchEnabled, one-off schedule run_at → runAt, and null → reset semantics).
Core Handlers
packages/worker/src/mcp/capabilities/jobs/shared.ts
Adds updateJobFromArgs() and deleteJobFromArgs() that call jobs service (updateJob, deleteJob), emit scheduler events (job_updated, job_deleted), and return standardized MCP outputs.
Capability Definitions
packages/worker/src/mcp/capabilities/jobs/job-update.ts, packages/worker/src/mcp/capabilities/jobs/job-delete.ts
Defines job_update and job_delete MCP capabilities (metadata, schemas) whose handlers delegate to the shared handlers.
Domain Registration
packages/worker/src/mcp/capabilities/jobs/domain.ts
Extends jobsDomain keywords (update, delete, disable, enable) and adds jobUpdateCapability and jobDeleteCapability to the capabilities array.
Usage & Instructions
packages/worker/src/mcp/jobs-embed.ts, packages/worker/src/mcp/server-instructions.ts
Expands job usage string and base MCP server instructions to document job_update (list of safe mutable fields) and job_delete.
MCP Handler Tests
packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
Adds tests for job_update and job_delete end-to-end: mocks updateJob/deleteJob, asserts service payload mapping (including one-off schedule mapping), verifies auth gating and rejection when no mutable fields provided, and updates domain capability assertions.
Service Tests
packages/worker/src/jobs/service.node.test.ts
Adds tests for service-layer authorization (non-owner rejects for update/delete), updateJob behavior (clears params when null, updates timezone, disables job), and validation (reject empty/whitespace code).
User Documentation
docs/use/execute.md, docs/use/first-steps.md, docs/use/packages.md
Documents codemode.job_update(...) and codemode.job_delete(...), clarifies job_schedule vs job_schedule_once, and documents job_run_now usage for debugging/ad hoc runs.

Sequence Diagram

sequenceDiagram
    participant Client as MCP Client
    participant MCP as MCP Handler (job_update / job_delete)
    participant Validator as Zod Validator
    participant JobsSvc as Jobs Service
    participant DB as Database
    participant Logger as Scheduler Logger

    Client->>MCP: invoke job_update / job_delete (env, callerContext, args)
    MCP->>Validator: validate & normalize input
    alt validation fails
        Validator-->>MCP: error
        MCP-->>Client: reject (schema / mutable-field error)
    else
        Validator-->>MCP: parsed args
        MCP->>JobsSvc: call updateJob() / deleteJob() with mapped payload
        alt auth/access denied
            JobsSvc-->>MCP: Job not found / access denied
            MCP-->>Client: reject "Job <id> was not found."
        else
            JobsSvc->>DB: mutate / delete job record
            DB-->>JobsSvc: result
            JobsSvc-->>MCP: updated / deleted result
            MCP->>Logger: emit job_updated / job_deleted event
            Logger-->>MCP: logged
            MCP-->>Client: mapped MCP output (job view / { job_id, deleted: true })
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nibble code and hop through queues,
Update a cron or prune old news.
With schema-sight and logger's cheer,
Jobs shift and vanish — neat and clear.
Hooray for tidy schedules, friend — a rabbit's muse!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding job update and delete capabilities, which is the core feature across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/kody-job-capabilities-29b0

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds marked this pull request as ready for review May 2, 2026 19:58
@github-actions

github-actions Bot commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-331.kentcdodds.workers.dev

Worker: kody-pr-331
D1: kody-pr-331-db
KV: kody-pr-331-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts (1)

184-204: ⚡ Quick win

Add a job_update test case covering a once-schedule with run_at → runAt transformation.

The existing test exercises a cron schedule (where expression passes through unchanged). No test verifies that a caller-facing run_at inside a once schedule is correctly transformed to runAt in the updateJob body — the same transformation already tested for job_schedule. If the shared transform helper is ever accidentally gated to the create path only, this path would silently break.

🧪 Suggested additional test assertion (inside the existing test or as a new test)
// After the existing cron-schedule test, add a once-schedule variant:
+test('job_update transforms run_at to runAt for once schedules', async () => {
+	resetMocks()
+	const env = {} as Env
+	const callerContext = createMcpCallerContext({
+		baseUrl: 'https://example.com',
+		user: { userId: 'user-123', email: 'user@example.com', displayName: 'User Example' },
+	})
+	mockModule.updateJob.mockResolvedValue({
+		id: 'job-123',
+		name: 'One-off v2',
+		sourceId: null,
+		publishedCommit: null,
+		storageId: 'job:job-123',
+		schedule: { type: 'once', runAt: '2026-05-01T12:00:00.000Z' },
+		scheduleSummary: 'Runs once at 2026-05-01T12:00:00.000Z',
+		timezone: 'UTC',
+		enabled: true,
+		killSwitchEnabled: false,
+		createdAt: '2026-04-20T10:00:00.000Z',
+		updatedAt: '2026-04-20T12:00:00.000Z',
+		nextRunAt: '2026-05-01T12:00:00.000Z',
+		runCount: 0,
+		successCount: 0,
+		errorCount: 0,
+		runHistory: [],
+	})
+
+	await jobUpdateCapability.handler(
+		{ id: 'job-123', schedule: { type: 'once', run_at: '2026-05-01T12:00:00.000Z' } },
+		{ env, callerContext },
+	)
+
+	expect(mockModule.updateJob).toHaveBeenCalledWith(
+		expect.objectContaining({
+			body: expect.objectContaining({
+				schedule: { type: 'once', runAt: '2026-05-01T12:00:00.000Z' },
+			}),
+		}),
+	)
+})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts` around
lines 184 - 204, Add a test asserting that jobUpdateCapability.handler
transforms a caller-provided once schedule's run_at into runAt in the updateJob
payload: call jobUpdateCapability.handler with a schedule.type 'once' and
schedule.run_at set (e.g., ISO string), then assert that the mocked updateJob
(or the outgoing body) receives schedule.runAt with the same value (and no
run_at), ensuring the shared transform used by job_schedule is applied in
jobUpdate as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/use/packages.md`:
- Around line 139-143: The docs currently list job_update capabilities but omit
that it can also change a job's name and its kill-switch state; update the docs
text describing job_update to include "name" and "kill-switch" (or equivalent
enabled/disabled/paused flag) alongside the existing mutable fields (schedule,
timezone, enabled state, params, code), matching the implementation in the jobs
shared capability (see job_update handling in the jobs/shared.ts implementation
around the job_update handler). Ensure the wording clarifies that job_update can
rename a job and toggle the kill-switch immediately, and keep the rest of the
listed editable fields as-is.

---

Nitpick comments:
In `@packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts`:
- Around line 184-204: Add a test asserting that jobUpdateCapability.handler
transforms a caller-provided once schedule's run_at into runAt in the updateJob
payload: call jobUpdateCapability.handler with a schedule.type 'once' and
schedule.run_at set (e.g., ISO string), then assert that the mocked updateJob
(or the outgoing body) receives schedule.runAt with the same value (and no
run_at), ensuring the shared transform used by job_schedule is applied in
jobUpdate as well.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d1a20e3a-1d24-46a2-9df3-145620624bf4

📥 Commits

Reviewing files that changed from the base of the PR and between ce8252d and ba9568a.

📒 Files selected for processing (11)
  • docs/use/execute.md
  • docs/use/first-steps.md
  • docs/use/packages.md
  • packages/worker/src/jobs/service.node.test.ts
  • packages/worker/src/mcp/capabilities/jobs/domain.ts
  • packages/worker/src/mcp/capabilities/jobs/job-delete.ts
  • packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
  • packages/worker/src/mcp/capabilities/jobs/job-update.ts
  • packages/worker/src/mcp/capabilities/jobs/shared.ts
  • packages/worker/src/mcp/jobs-embed.ts
  • packages/worker/src/mcp/server-instructions.ts

Comment thread docs/use/packages.md Outdated
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts (1)

721-780: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Also cover jobScheduleOnceCapability in the auth-negative path.

This test protects jobScheduleCapability, jobUpdateCapability, jobDeleteCapability, and jobRunNowCapability, but the one-off scheduling entrypoint is still untested here. A regression in that path would slip through.

Suggested addition
   await expect(
+    jobScheduleOnceCapability.handler(
+      {
+        code: 'export default async () => ({ ok: true })',
+        run_at: '2026-04-20T18:30:00Z',
+      },
+      {
+        env,
+        callerContext,
+      },
+    ),
   ).rejects.toThrow('Authenticated MCP user is required for this capability.')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts` around
lines 721 - 780, The test is missing the auth-negative check for the one-off
scheduler; add a call to jobScheduleOnceCapability.handler with the same
unauthenticated callerContext and env (e.g., pass a payload similar to
jobScheduleCapability but with schedule: { type: 'once', at: '...' } or
appropriate shape), assert it rejects with 'Authenticated MCP user is required
for this capability.', and add an expectation that mockModule.createJob (or
whichever mock job creation function jobScheduleOnceCapability uses) was not
called; place this alongside the existing rejects.toThrow assertions and the
final mock non-call assertions (referencing jobScheduleOnceCapability,
mockModule.createJob).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts`:
- Around line 721-780: The test is missing the auth-negative check for the
one-off scheduler; add a call to jobScheduleOnceCapability.handler with the same
unauthenticated callerContext and env (e.g., pass a payload similar to
jobScheduleCapability but with schedule: { type: 'once', at: '...' } or
appropriate shape), assert it rejects with 'Authenticated MCP user is required
for this capability.', and add an expectation that mockModule.createJob (or
whichever mock job creation function jobScheduleOnceCapability uses) was not
called; place this alongside the existing rejects.toThrow assertions and the
final mock non-call assertions (referencing jobScheduleOnceCapability,
mockModule.createJob).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 480b19da-2935-49c1-92bc-ab16f31a8437

📥 Commits

Reviewing files that changed from the base of the PR and between ba9568a and a5b15bf.

📒 Files selected for processing (2)
  • docs/use/packages.md
  • packages/worker/src/mcp/capabilities/jobs/job-schedule.node.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/use/packages.md

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds merged commit 4cd68c3 into main May 2, 2026
9 checks passed
@kentcdodds
kentcdodds deleted the cursor/kody-job-capabilities-29b0 branch May 2, 2026 21:12
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