toolschema

package
v0.44.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package toolschema translates the JSON Schema documents that upstream MCP servers attach to their tools into the 2020-12 dialect.

Neither the servers nor the clients involved are misbehaving, and that is why the fix belongs here. The MCP 2026-07-28 spec's "JSON Schema Usage" section lets a schema declare any dialect, requires implementations to support only 2020-12, and tells them to handle an unsupported dialect by returning an error saying so -- which is exactly what the rejecting clients do. Servers built on the MCP TypeScript SDK declare draft-07 for every tool, because its zod converter defaults to that target. Both halves are conformant and the combination does not work, so the gateway in the middle reconciles them.

That section postdates the revision this gateway negotiates (the vendored go-sdk tops out at 2025-06-18, whose basic/index.mdx says nothing normative about dialects), so it is cited as the ecosystem's settled reading of a rule that was always implicit, not as a requirement binding the current wire version. The breakage it describes is happening today either way.

Translation is deliberately narrow. Normalize only acts on a schema that explicitly declares draft-04, draft-06 or draft-07; a schema with no $schema is already 2020-12 by the spec's default and is returned untouched rather than guessed at. Where a construct has no faithful 2020-12 equivalent the whole schema is returned unchanged, so the caller's fallback is the verbatim passthrough that predates this package rather than a plausible-looking lie.

Input must be a JSON-decoded document, as every schema on the MCP wire is: containers are map[string]any and []any, and the values inside them are JSON scalars.

Normalize never mutates its input. On the TRANSLATING path it deep-copies the containers it returns, so the result aliases none of the input. On every other path -- no dialect declared, a dialect it does not translate, or a refusal -- it returns the input value itself, which therefore does alias. That is the point: those paths are meant to hand back exactly what the server sent, and it is what this package did before it existed. Two caveats on the copying path: a container of some other Go type is copied by reference, and JSON scalars are immutable and shared. Neither matters while nothing in the gateway writes through a tool schema, which nothing does.

Index

Constants

View Source
const Dialect202012 = "https://json-schema.org/draft/2020-12/schema"

Dialect202012 is the 2020-12 dialect URI, which MCP treats as the default.

Variables

This section is empty.

Functions

This section is empty.

Types

type Result

type Result struct {
	// Changed is true when the returned schema differs from the input.
	Changed bool
	// Skipped is true when the schema declared a translatable dialect but held
	// a construct with no faithful 2020-12 equivalent, so it was returned
	// unchanged. Reason says which.
	Skipped bool
	// UnsupportedDialect is true when the schema declared a dialect that is
	// neither 2020-12 nor one this package translates, so it was returned
	// unchanged. Such a schema is still rejected by a 2020-12-only client, and a
	// caller sizing the affected surface has to be able to see it -- otherwise
	// "nothing to report" and "affected but beyond our reach" look identical.
	UnsupportedDialect bool
	// Reason explains a Skipped result. Empty otherwise.
	Reason string
}

Result reports what Normalize did to a schema.

func Normalize

func Normalize(schema any) (any, Result)

Normalize returns a 2020-12 equivalent of schema.

It never mutates schema or anything reachable from it: MCP tool schemas are shared by reference with the upstream client session's cached tool list, and discovery runs concurrently across servers.

A schema that declares no dialect, declares 2020-12, or declares a dialect this package does not translate is returned as-is.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL