Skip to content

[go-fan] Go Module Review: google/jsonschema-go #35160

@github-actions

Description

@github-actions

🐹 Go Fan Report: google/jsonschema-go

Module Overview

github.com/google/jsonschema-go v0.4.3 is Google's official Go library for JSON Schema. It does three things: infer schemas from Go types (For[T]), construct/resolve schemas, and validate JSON values against them. It has zero non-stdlib dependencies and supports both draft-07 and draft 2020-12. The library is the data-shape contract for every MCP tool we expose.

Current Usage in gh-aw

  • Production files: 3 (pkg/cli/mcp_schema.go, pkg/cli/mcp_tools_privileged.go, pkg/cli/mcp_tools_readonly.go).
  • Test files: 3 in pkg/cli/.
  • Indirect dependency: pkg/cli/mcp_argument_validation.go parses jsonschema-go's unexpected additional properties [...] error string via regex to power fuzzy-matched parameter suggestions.
  • Key APIs used: jsonschema.For[T](), *Schema.Properties[...].Default = json.RawMessage(...), schema.Resolve() + resolved.Validate() (tests only).
  • Tags consumed: json:"..." for property names + optionality, jsonschema:"..." for descriptions.

Four MCP tools register their input schemas via the project's GenerateSchema[T]() helper: logs, audit, audit-diff, compile. The logs and compile tools additionally inject elicitation defaults (SEP-1024) via AddSchemaDefault.

Research Findings

Recent Updates

  • 794ce5e (2026-05-22) — resolve default through $ref unless default exists at same level (Add more security notes #69).
  • 8c4ab4f (2026-04-17) — infer: support maps with non-string keys (Fix default permissions typo #70).
  • 8bd5742 (2025-12-19) — improved anyOf error messages.
  • eb36139 (2025-12-11) — PropertyOrder added; For populates it automatically from struct field order.
  • 5c63758 (2025-12-05) — ApplyDefaults no longer supported on structs.

Best Practices Observed in the Library

  • Use jsonschema: tag for descriptions — required for LLM-friendly tool schemas.
  • For custom JSON-shape Go types, prefer ForOptions.TypeSchemas over post-hoc mutation of the result schema.
  • For complex schemas with $ref, call Resolve() once and then Validate() repeatedly — the resolved form caches $ref lookups.
  • PropertyOrder is now intrinsic to struct-inferred schemas; do not rely on map ordering elsewhere.

Improvement Opportunities

🏃 Quick Wins

  • AddSchemaDefault silently swallows misspelled property names (pkg/cli/mcp_schema.go:60). It logs and returns nil, so AddSchemaDefault(s, "timeoutt", 1) is a no-op that nobody notices. Returning an error for unknown property names would catch typos at the registerXTool call site, where the existing code already checks err.
  • Lock the jsonschema-go validator error format into a test. mcp_argument_validation.go:114 regex-matches the literal phrase unexpected additional properties [...] produced by jsonschema/validate.go:509. A small test that runs a real validation through the library and feeds the resulting error into extractUnknownParams would catch any future rephrasing on upgrade.

✨ Feature Opportunities

  • Use ForOptions.TypeSchemas for project-specific type mappings. Today the codebase only uses For[T](nil). A TypeSchemas entry for time.Duration (currently inferred as an int64 of nanoseconds) could emit a string with format: duration — far more usable for an LLM filling in a tool arg.
  • Consider ForOptions.IgnoreInvalidTypes: true for tool-arg structs, so a future field whose type is incompatible with JSON Schema does not crash MCP registration but just gets skipped with a log line.
  • Take advantage of PropertyOrder for stable golden tests. v0.4.0+ already preserves struct field order; tests that compare serialized schemas can now rely on it deterministically across Go versions.

📐 Best Practice Alignment

  • Centralize default-injection. pkg/cli/mcp_tools_privileged.go:58-65 and pkg/cli/mcp_tools_readonly.go:98 repeat the same AddSchemaDefault(...); if err != nil { mcpLog.Printf(...) } pattern. A small applyDefaults(schema, map[string]any{...}) helper would shrink the call sites and make defaults declarative.
  • Document the two-library split. pkg/cli/* uses jsonschema-go (via the MCP SDK); pkg/parser/* and pkg/workflow/* use santhosh-tekuri/jsonschema/v6. The split is intentional and reasonable, but a one-line comment near each schema compiler would prevent a future contributor from "unifying" them.

🔧 General Improvements

  • Wrap schema-generation failures with context. pkg/cli/mcp_tools_privileged.go:52 does return err after logging. A fmt.Errorf("generate logs schema: %w", err) would make stack traces self-explanatory if a tool-arg struct grows an incompatible field.
  • Cache generated schemas behind sync.OnceValue. Not a perf concern (registration runs once), but slightly cleaner if the same arg type ever appears in multiple registrars.

Recommendations

Prioritized:

  1. (low-risk, high-signal) Make AddSchemaDefault return an error for unknown property names.
  2. (low-risk, low-cost) Add a regression test against the live unexpected additional properties error string from jsonschema-go.
  3. (small refactor) Extract an applyDefaults helper to reduce repetition across the three registrars.
  4. (forward-looking) Consider ForOptions.TypeSchemas for time.Duration and any other custom-format type that lands in a tool arg.

Next Steps

  • Open a small PR implementing items 1 and 2 above — both are isolated changes in pkg/cli/mcp_schema.go and a new test in pkg/cli/mcp_argument_validation_test.go.
  • Audit each tool's arg struct for fields whose JSON Schema representation would benefit from TypeSchemas.

Generated by Go Fan
Module summary saved to: scratchpad/mods/google-jsonschema-go.md

References:

Generated by 🐹 Go Fan · opus47 8.8M ·

  • expires on May 28, 2026, 9:02 AM UTC

Metadata

Metadata

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