cloudflare / cloudflare/mcp-server-cloudflare

`query_worker_observability` fails to parse cron-triggered Worker events (`$workers.outcome` is absent)

Open Beginner friendly
#435 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
4.2k
Forks
514
Avg merge
1d 21h
Merged PRs (30d)
2

Description

### Summary

The observability MCP server (`https://observability.mcp.cloudflare.com/mcp`) cannot return any cron-triggered Worker event. Its response schema requires `$workers.outcome` to be a string, but the underlying Cloudflare telemetry API omits that field entirely for `eventType: "cron"` events. The tool therefore rejects valid data returned by the very API it wraps, and cron/scheduled Worker invocations become unqueryable through MCP.

### Reproduce

Any Worker with a `[triggers] crons` schedule and observability enabled. Call `query_worker_observability`:

```json
{
"view": "events",
"queryId": "repro",
"limit": 20,
"dry": false,
"parameters": {
"datasets": ["cloudflare-workers"],
"filters": [
{ "key": "$metadata.service", "operation": "eq", "type": "string", "value": "" },
{ "key": "$metadata.origin", "operation": "eq", "type": "string", "value": "cron" }
]
},
"timeframe": { "reference": "", "offset": "-24h" }
}
```

### Actual

```
Error analyzing worker logs: [
{
"code": "invalid_union",
"errors": [[{ "expected": "string", "code": "invalid_type",
"path": ["outcome"],
"message": "Invalid input: expected string, received undefined" }]],
"path": ["result", "events", "events", 0, "$workers"],
"message": "Invalid input"
},
...
]
```

Note the error names `events[0]`, `events[2]`, etc. — the events **were** retrieved; only deserialization fails.

### Expected

The cron events are returned, as they are via the REST API.

### Root cause

`POST /accounts/{account_id}/workers/observability/telemetry/query` returns different `$workers` shapes by event type. Same Worker, same account, same timeframe:

| eventType | `$workers` keys | `outcome` |
| --- | --- | --- |
| `cron` | `truncated, event, scriptName, eventType, scriptVersion, executionModel, requestId` | **absent** |
| `fetch` | `event, truncated, scriptName, outcome, eventType, executionModel, scriptVersion, requestId, cpuTimeMs, wallTimeMs` | `"ok"` |

Cron events also omit `cpuTimeMs` and `wallTimeMs`.

The MCP layer's zod schema for `$workers` requires `outcome`, so every cron event fails validation. The REST endpoint returns these same events without complaint, which is the workaround (see below).

### Suggested fix

Make `outcome` optional in the `$workers` schema (and likely `cpuTimeMs` / `wallTimeMs` too), or discriminate the schema on `eventType`.

### Impact

Cron-triggered Workers cannot be observed through MCP at all. This matters for scheduled jobs, where the log line emitted by the `scheduled()` handler is often the only record that the job ran and what it decided — there is no request/response to inspect, and `wrangler tail` only shows live traffic, so a missed window is unrecoverable.

### Secondary note

`$metadata.origin` for cron-triggered events is `"cron"`, not `"scheduled"`. Filtering on `"scheduled"` returns an empty array rather than an error, which is indistinguishable from "the cron never fired" — a misleading result when debugging a scheduled job. Worth documenting in the tool description alongside the existing `$metadata.origin` guidance.

### Workaround

Query the REST API directly; it returns the events correctly:

```
POST /accounts/{account_id}/workers/observability/telemetry/query
{
"queryId": "…", "view": "events", "limit": 25, "dry": false,
"parameters": {
"datasets": ["cloudflare-workers"],
"filters": [
{ "id": "1", "key": "$metadata.service", "operation": "eq", "type": "string", "value": "" },
{ "id": "2", "key": "$metadata.origin", "operation": "eq", "type": "string", "value": "cron" }
],
"calculations": [], "groupBys": [], "havings": []
},
"timeframe": { "from": , "to": }
}
```

(The REST endpoint wants numeric epoch-ms `from`/`to` and `id` on each filter; the MCP tool accepts ISO strings and omits `id`.)

Contributor guide

Open the contributing guide

Research direction

Start at the query_worker_observability entry point and locate the Zod schema that validates the $workers event object. Reproduce with the supplied cron-events query, then verify that events without outcome, cpuTimeMs, or wallTimeMs are accepted and returned; also check the tool description's guidance for the cron origin value.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, observability
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.