Stu Mason · Folkestone, Kent
One entryMerged PR· StuMason/coolify-mcp· TypeScript

PR #243 merged: fix: validate scheduled-task command length client-side, add error hints

additions
+138
deletions
-3
files changed
5

What

Coolify rejects scheduled-task command values beyond ~250 chars with a bodyless HTTP 500 (Internal Server Error, no validation message) that the MCP previously passed through verbatim. This closes #234, which absorbed item 3 of the now-closed #237.

Upstream evidence for the limit

Checked Coolify's own migrations (gh api repos/coollabsio/coolify/contents/database/migrations). The table is created in database/migrations/2023_12_31_173041_create_scheduled_tasks_table.php:

$table->string('command');

A plain Laravel string() column is varchar(255). I checked every later scheduled-tasks migration (add_timeout_to_scheduled_tasks_table, improve_scheduled_task_executions_tracking, etc.) — none of them touch the command column's type. So the limit is 255, pinned from upstream source, not just the largest empirically-known-good value (247).

This matches the empirical datapoints in the issue: 247 chars OK, ~265+ fails — consistent with a 255-char ceiling (255 itself would still pass; the reporter's smallest failing sample was ~265).

Changes

  1. Client-side validation (src/lib/mcp-server.ts): command in the scheduled_tasks tool shape now has .max(255, '...') with an actionable message. The shape is shared between create and update, so both are covered by one change. Tool description also mentions the limit.
  2. Status-code-aware error hints (src/lib/coolify-client.ts): new pure function errorHint(status, path) appends a short hint to bodyless failures:
    • 500 on a /scheduled-tasks path → command-length limit as a known cause.
    • 401/403 → check COOLIFY_ACCESS_TOKEN validity/scopes.
    • 404 on a uuid-shaped route → uuid may belong to a different resource type (app vs service vs database).
    • Anything else → no hint appended (passthrough unchanged).
  3. Docs: added the gotcha (limit + workaround) to site/concepts/coolify-api-gotchas.md, matching the existing entry style and citing the migration file.

Tests

  • An over-long command is rejected via the tool's zod inputSchema before any HTTP call — asserted that the mocked createApplicationScheduledTask / updateApplicationScheduledTask client methods are never invoked.
  • A 255-char command still validates successfully (boundary case).
  • Unit tests for errorHint covering all three mapped cases and the default (undefined) passthrough.
  • Integration-style test: a real bodyless 500 from createApplicationScheduledTask now surfaces the hint in the thrown error.

npm test (371 tests passing), npm run lint, npx prettier --check ., and npm run build all pass.

Uncertain / worth a second look

  • The 404 "uuid route" heuristic in errorHint is a generic regex (/[\w-]{8,}(\/|$)/) rather than validating true UUID format, since Coolify's uuids aren't RFC4122-shaped. It's intentionally loose per "don't over-engineer" — flagging in case a tighter check is preferred.

Closes #234

🤖 Generated with Claude Code