mcp-vertex-check

command
v1.41.0 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 17 Imported by: 0

README

mcp-vertex-check

Validates the published tool schemas against the subset of JSON Schema that Vertex AI can parse — and therefore against what Gemini Enterprise will accept when it loads "custom actions". It answers "would Gemini load these tools?" locally, instead of through a customer retrying a connector.

go run ./cmd/mcp-vertex-check              # what a Gemini client gets; must be clean
go run ./cmd/mcp-vertex-check -published   # the raw published surface; will not be clean
go run ./cmd/mcp-vertex-check -warn        # include warnings
go run ./cmd/mcp-vertex-check -input-only  # inputSchema only
go run ./cmd/mcp-vertex-check -json        # machine-readable
go run ./cmd/mcp-vertex-check -tools=captured.json   # a saved body, checked as it stands

The default checks what a Gemini client is served, not what the server publishes — that is the surface which has to be clean, and the published one cannot be (see below). Exit status is 1 when anything is reported and 2 on a usage error, so the default mode works as a CI gate.

Why this is not the same as "the schema is valid"

Vertex models a tool schema as a protobuf message, not as JSON Schema. Its Schema message is a declared subset of OpenAPI 3.0.3 (google/cloud/aiplatform/v1/openapi.proto), so a document can be perfectly valid JSON Schema and still be unparseable there. Two consequences carry most of the weight:

  • type is a single enum field with members string, number, integer, boolean, array, object. There is no NULL, and a list cannot be parsed at all — Gemini clients report Proto field is not repeating, cannot start list.
  • Any keyword outside the message's fields is an unknown field. examples (JSON Schema 2020-12, plural) is not one of them; the message has singular example.

Note this is the opposite of OpenAPI 3.1+, which adopted JSON Schema 2020-12 and made ["string","null"] the sanctioned nullable form. Chasing the newest spec moves away from what Vertex accepts.

Severities

  • error — contradicts the Schema message, so it cannot be parsed.
  • warn — permitted by the message but reported rejected by Gemini clients, or outside the documented value set. additionalProperties as a schema rather than a boolean is the clearest case: the field is a Value, so the proto allows it, but Gemini answers Expected boolean, received object (gemini-cli #13694, closed as not planned). many-tools is another: at most 128 function declarations reach the model per request, but Gemini Enterprise imports a connector's actions and enables them individually, so a longer list does not stop them loading.

Output schemas are checked, and that is deliberate

Vertex's FunctionDeclaration carries Schema response = 4 alongside parameters, and Gemini clients do validate an MCP tool's outputSchema. Pass -input-only to scope a run to what a tools/list caller sends, but a clean -input-only run does not mean Gemini will load the tools.

Two surfaces, and only one of them passes

The output schemas cannot be fixed the way the input ones were: their nulls are real wire values (twapi.Date encodes as null when unset), so removing them would publish a schema every response violates.

So a Gemini client is served a rewritten copy instead — helpers.VertexTools, wired to wantsVertexSchemas in pkg/config — and that copy is what the default mode checks:

go run ./cmd/mcp-vertex-check              # the copy a Gemini client gets: clean
go run ./cmd/mcp-vertex-check -published   # the raw surface: 602 errors, and must be

TestVertexVariantIsClean is the gate, and TestPublishedSurfaceStillCarriesOutputSchemaNulls stops it passing vacuously — if the published surface ever becomes Vertex-safe on its own, the variant is no longer needed.

Adding a rule

Rules live in vertex.go, driven by vertexFields, vertexTypes and documentedFormats. Take a new rule from the proto or from a reproducible client error, and put it at SeverityError only when the proto says it cannot parse — a guess at error turns this tool into noise. vertex_test.go drives each rule from one table.

TestVertexVariantIsClean gates the variant in CI. The published surface is deliberately not gated: it cannot pass while its output schemas carry real nulls.

Documentation

Overview

Command mcp-vertex-check validates the published tool schemas against the subset of JSON Schema that Vertex AI — and therefore Gemini Enterprise — can parse. It answers "would Gemini load these tools?" locally, instead of through a customer retrying a connector.

The rules come from the Vertex Schema message (google/cloud/aiplatform/v1/openapi.proto): see vertex.go. Errors contradict that definition and cannot be parsed; warnings are permitted by it but have been reported rejected by Gemini clients.

By default it checks what a Gemini client is actually served — the rewritten copy from helpers.VertexTools — because that is the surface that has to be clean. The published surface cannot be: its output schemas declare real nulls.

Usage:

go run ./cmd/mcp-vertex-check                     # what a Gemini client gets; must be clean
go run ./cmd/mcp-vertex-check -published          # the raw published surface; will not be clean
go run ./cmd/mcp-vertex-check -warn               # include warnings
go run ./cmd/mcp-vertex-check -input-only         # ignore output schemas
go run ./cmd/mcp-vertex-check -json               # machine-readable
go run ./cmd/mcp-vertex-check -tools=live.json    # a captured tools/list result, as-is

It exits non-zero when anything is reported, so the default mode works as a CI gate.

Jump to

Keyboard shortcuts

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