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

Closed as not planned

Description

@r007b34r

Description

Environment

  • OpenCode: latest (oh-my-opencode v3.17.15)
  • MCP server: [email protected] (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 [email protected] 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

Activity

  1. cyanheads commented on May 8, 2026

    @cyanheads

    Hi there, maintainer of obsidian-mcp-server here — wanted to share a few findings that might help narrow this down.

    Schema dump. Here's the actual inputSchema the server emits for obsidian_patch_note (descriptions and a couple of optional fields elided for brevity), in case it's useful for comparison against what opencode is validating against:

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "target": {
          "oneOf": [
            {"type": "object", "properties": {"type": {"type": "string", "const": "path"}, "path": {"type": "string", "minLength": 1}}, "required": ["type", "path"]},
            {"type": "object", "properties": {"type": {"type": "string", "const": "active"}}, "required": ["type"]},
            {"type": "object", "properties": {"type": {"type": "string", "const": "periodic"}, "period": {"type": "string", "enum": ["daily","weekly","monthly","quarterly","yearly"]}}, "required": ["type", "period"]}
          ]
        },
        "section": {"type": "object", "properties": {"type": {"type": "string", "enum": ["heading","block","frontmatter"]}, "target": {"type": "string", "minLength": 1}}, "required": ["type", "target"]},
        "operation": {"type": "string", "enum": ["append","prepend","replace"]},
        "content": {"type": "string"}
      },
      "required": ["target", "section", "operation", "content"]
    }

    It's standard JSON Schema — oneOf with a const discriminator and nested properties. Both shapes are core features in draft-07 and JSON Schema 2020-12 (the MCP spec default when no $schema is set).

    One detail that might point at the cause. The reporter mentions a required property 'sectionTargeted' error for obsidian_append_to_note. That field only exists in the tool's outputSchema, not its input — so the validator may be reading from the wrong schema (or a merged one) for tools with multiple nested-object parameters. That lines up with @r007b34r's flattening hypothesis.

    Happy to provide full schema dumps for any of the affected tools or help test a fix against the live server.

  2. github-actions commented on Jul 9, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions