fix(mcp): advertise precise object-rooted output schemas - #68
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
mcporter rejects the flicknote MCP server's
tools/listbecause derived output schemas contain terms strict clients cannot parse:note_get'smetadatafield (Option<serde_json::Value>) derives a boolean schema term"metadata": true.note_source'sSourceResultenum derives aoneOfunion without an explicit object root.Earlier coarse fixes (e2fd1b5, #67; and the first commit here) replaced these with
{"type":"object"}, which satisfies strict clients but discards the useful output contract: clients could no longer discover fields, required values, collection shapes, or source-view variants.Fix
Compatibility is fixed at the narrow incompatible parts instead of erasing each schema:
note_get: keep the full generated schema;metadatauses an object-form JSON Schema term that keeps arbitrary JSON (andnullfromOption) representable.note_source: new MCP boundary DTOMcpSourceResult(transparent overSourceResult, serialization unchanged) advertises an object-rooted tagged union with rendered/raw/info variants, each variant's discriminator and required fields, and an object-form term for the arbitrary rawvalue.notes/projectsarray item schemas.output_schemaoverride; schemas now follow MCP boundary DTOs.Tests
mcp_tool_output_schemas_are_strict_client_compatible: every tool's outputSchema has an explicit object root and no boolean schema terms; list tools advertise wrapper + item schemas.mcp_note_get_output_schema_advertises_detail_structure: content/metadata/extractions/sections present and required; metadata is object-form and represents arbitrary JSON incl. null.mcp_note_source_output_schema_advertises_all_views: all three views with discriminators and variant-specific fields.structuredContentstill matches.Verification
cargo test --bin flicknote— 51 tests pass.cargo clippy --workspace --all-targets --all-features -- -D warningsclean.cargo fmt --all --checkclean.flicknote mcp: 25 tools,note_get.metadataobject-form,note_sourceobject-rooted with views rendered/raw/info, zero strict-client violations.