Skip to content

auditlogs_by_account_id: zod validation fails on actor.context == "api" (new value from Cloudflare API) #352

@hamiltonmascioli

Description

@hamiltonmascioli

Client Information

  • LLM Client: Claude Code CLI
  • MCP Server: https://auditlogs.mcp.cloudflare.com/mcp
  • Using MCP Remote?: No (remote HTTP MCP)
  • Prompt: Weekly SOC 2 continuous-monitoring checkpoint — query audit logs for a 7-day window

Describe the bug

auditlogs_by_account_id returns 13 zod validation errors and no data for a 7-day window on a low-activity account. The response schema for actor.context is declared as:

// apps/auditlogs/src/tools/auditlogs.tools.ts:9
export const actorContexts = z.enum(['api_key', 'api_token', 'dash', 'oauth', 'origin_ca_key'])

…but the live Cloudflare Audit Log API is now returning actor.context = "api" for many entries (appears to indicate a generic API-driven change, distinct from api_key / api_token). Every entry with this value fails validation, which causes the whole response to be rejected — even though the entries themselves are legitimate.

Error (trimmed — 13 identical errors at different result indices)

{
  "received": "api",
  "code": "invalid_enum_value",
  "options": ["api_key", "api_token", "dash", "oauth", "origin_ca_key"],
  "path": ["result", 2, "actor", "context"],
  "message": "Invalid enum value. Expected 'api_key' | 'api_token' | 'dash' | 'oauth' | 'origin_ca_key', received 'api'"
}

To reproduce

  1. Connect to https://auditlogs.mcp.cloudflare.com/mcp
  2. Call auditlogs_by_account_id with any 7-day window that contains API-driven activity:
    {
      "since": "2026-04-10",
      "before": "2026-04-17",
      "limit": 100
    }
  3. All entries where the platform returns actor.context = "api" fail the enum check; the tool returns no data.

Expected behavior

The tool returns the audit log entries. The response schema should accept "api" as a valid actor.context value (or relax actorContexts to z.string() since Cloudflare's API evolves and the current enum is already incomplete).

Proposed fix (one-line change)

In apps/auditlogs/src/tools/auditlogs.tools.ts:9:

-export const actorContexts = z.enum(['api_key', 'api_token', 'dash', 'oauth', 'origin_ca_key'])
+export const actorContexts = z.enum(['api', 'api_key', 'api_token', 'dash', 'oauth', 'origin_ca_key'])

A more defensive alternative would be to drop the enum entirely on the response side and keep it only on the query filter side (auditLogsQuerySchema.actor_context), since Cloudflare's response surface clearly isn't a closed set.

Additional context

  • Same class of bug as auditlogs_by_account_id returns "Expected object, received array" #270 (also open, also an over-strict response schema — resource.response array vs object). Both point to the response schema being written too tightly against a particular snapshot of the Cloudflare API.
  • The underlying Cloudflare API call succeeds (HTTP 200 upstream); only the MCP-side response validation fails.
  • accounts_list works fine on the same MCP session, so this is specific to the response schema in auditlogs.tools.ts, not auth or transport.
  • This is currently blocking a SOC 2 Type II continuous-monitoring control; happy to test a fix against our account if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions