Skip to content

mcpb clean silently drops unknown nested manifest keys (loose .passthrough() is top-level only) #264

@aosmcleod

Description

@aosmcleod

Summary

mcpb clean (via cleanMcpb) silently deletes unknown keys nested inside author, server, server.mcp_config, etc. from a user's manifest. The loose schemas exist to preserve unrecognised data while cleaning, but .passthrough() is applied only to the top-level object, so nested z.object() schemas strip unknown keys, and cleanMcpb writes the pruned object back to disk.

Mechanism

Zod's .passthrough() only affects the object it's called on. In src/schemas_loose/*.ts only the root object has .passthrough(); nested schemas (McpServerConfigSchema, McpbManifestAuthorSchema, McpbManifestServerSchema, McpbManifestRepositorySchema, …) are plain z.object() and strip unknowns. cleanMcpb (src/node/validate.ts:437-445) rewrites the manifest with result.data, so nested extras are lost.

Reproduction (executed)

A 0.4 manifest with top_level_unknown, author.twitter, server.custom_server_field, server.mcp_config.extra_exec_opt, run through the loose parse:

  • top_level_unknown kept: true
  • author.twitter kept: false
  • server.custom_server_field kept: false
  • server.mcp_config.extra_exec_opt kept: false

So mcpb clean silently discards nested custom fields the author put in their manifest.

Suggested fix

Add .passthrough() to the nested loose object schemas that should preserve data, across all schemas_loose/*.ts (McpServerConfigSchema, McpbManifestAuthorSchema, McpbManifestServerSchema, McpbManifestRepositorySchema, …). 0.3/0.4 already added .passthrough() to the localization/icon loose sub-schemas — the server/author/mcp_config ones were missed.

Environment: current main (70fe3b3).

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