Skip to content

[MCP] Schema validation fails for tools with multiple discriminated-union/nested-object parameters (e.g. obsidian-mcp-server patch_note, append_to_note) #26277

@r007b34r

Description

@r007b34r

Description

Environment

  • OpenCode: latest (oh-my-opencode v3.17.15)
  • MCP server: obsidian-mcp-server@3.1.5 (cyanheads/obsidian-mcp-server, npm)
  • OS: Windows

Steps to reproduce

  1. Configure obsidian-mcp-server as an MCP server (stdio transport)
  2. Call obsidian_patch_note with valid nested parameters:
    • target: { type: "path", path: "SomeFile.md" }
    • section: { type: "heading", target: "SectionName" }
    • operation: "append"
    • content: "new content"
  3. Call obsidian_append_to_note with:
    • target: { type: "path", path: "SomeFile.md" }
    • section: { type: "heading", target: "SectionName" } (optional)
    • content: "new content"

Expected behavior

Both calls should succeed with properly structured nested parameters matching the server's declared input schema.

Actual behavior

Both calls fail with -32602 Invalid params. The error messages demand flat top-level fields that are actually nested inside discriminated union objects, e.g.:

  • required property 'path' (path is inside target, not top-level)
  • required property 'sectionTargeted' (this is an output field, not an input field)

Which tools are affected

  • obsidian_patch_note — has target (discriminated union) + section (nested object)
  • obsidian_append_to_note — has target (discriminated union) + optional section (nested object)

Which tools work correctly

  • obsidian_replace_in_note — all flat parameters
  • obsidian_write_note — single nested target
  • obsidian_get_note — single nested target
  • obsidian_list_notes — all flat parameters

Hypothesis

OpenCode's host layer is incorrectly flattening Zod discriminated-union schemas when a tool has two or more nested-object parameters, then validating calls against the flattened (incorrect) schema instead of the server's actual schema.

Server schema (for reference)

From obsidian-mcp-server@3.1.5 source (obsidian-patch-note.tool.js):
input: z.object({
target: TargetSchema, // discriminated union: {type:"path",path} | {type:"active"} | {type:"periodic",...}
section: SectionSchema, // nested object: {type: "heading"|"block"|"frontmatter", target: string}
operation: z.enum('append', 'prepend', 'replace'),
content: z.string(),
})

Workaround

Using obsidian_replace_in_note (literal/regex search-replace) in place of obsidian_patch_note and obsidian_append_to_note works correctly.

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Metadata

Metadata

Assignees

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