Schema Version: 2025-10-09 (date-based). Increment (add a new date) only when changing validation semantics or adding/removing fields. Older versions remain acceptable unless explicitly deprecated.
This document describes the lightweight schema shapes supported by the validator in mcp/manager.go.
The validator accepts two shapes for a schema (any):
- Direct map: top-level is a map of property name -> property schema
- JSON Schema–like: top-level object with
propertiesmap and optionalrequiredarray
It normalizes both into a common in-memory form (ArgSchemaProperty) and validates arguments accordingly.
We use a simple date-based version string (YYYY-MM-DD). Each time we introduce a backward-incompatible change (e.g. start enforcing a new constraint that could fail existing payloads, or rename/remove a field), we:
- Bump the version constant in code.
- Add a new entry to the Changelog section below describing the change and migration notes.
- (Optional) Support the prior version for a grace period by keeping permissive parsing logic.
Minor, purely additive, backward-compatible enhancements (e.g. recognizing a new field but not enforcing it) do not require a version bump—still document them in the Changelog as “additive”.
Clients MAY send a top-level field schemaVersion (string) alongside the schema object; if omitted we assume the latest version and apply the most permissive interpretation available. Future server logic can branch based on this field for phased rollouts.
- type: string | integer | float | number | boolean | enum | array
- required: boolean (per-field). Alternatively, use top-level
required: ["field1", "field2"]in JSON Schema–like shape. - description: string (informational; not validated, but strongly recommended). Use full sentences; first sentence should be a concise summary. Can be surfaced in UI/help.
- isArray: boolean (for direct-map shape). When true, the argument must be an array (slice). The element type is taken from
typeunlessitems.typeis specified. - items: object (JSON Schema–like). Allows specifying
type,minLength,maxLength,minimum,maximum, andenumfor array elements. - minLength / maxLength: integers (applies to strings; also to each array element if present via
itemsor when usingisArray+type: "string"). - minimum / maximum: numbers (applies to integer/float/number; also to each array element if present via
itemsor when usingisArray+ numeric type). - enum: array of allowed values (each element of the argument must be one of these values). For arrays, each element is checked.
Notes:
- Numbers from JSON typically decode as
float64in Go; the validator accepts common numeric types (int, floats) for numeric checks. - If
type: "array"anditems.typeis provided, it is used as the element type. IfisArray: trueis used with a non-arraytype, that non-arraytypeis treated as the element type. enumvalues are compared by string form to provide leniency across JSON-decoded numeric/string representations.
Top-level is the properties map:
Validation behavior:
qmust be a string with length between 3 and 64 inclusivelimitmust be an integer between 1 and 100 inclusivetagsmust be an array of strings, each with length >= 2scoresmust be an array of numbers, each between 0 and 1 inclusivemodemust be one of: "fast", "accurate"
Top-level contains properties and optional required:
{
"properties": {
"q": { "type": "string", "minLength": 3, "maxLength": 64 },
"limit": { "type": "integer", "minimum": 1, "maximum": 100 },
"tags": {
"type": "array",
"items": { "type": "string", "minLength": 2 }
},
"scores": {
"type": "array",
"items": { "type": "number", "minimum": 0, "maximum": 1 }
},
"mode": { "type": "enum", "enum": ["fast", "accurate"] }
},
"required": ["q"]
}Same validation semantics as the direct map example.
{
"properties": {
"levels": {
"type": "array",
"items": { "type": "integer" },
"enum": [1, 2, 3]
}
}
}- Each value in
levelsmust be one of 1, 2, or 3.
{
"properties": {
"names": {
"type": "string",
"isArray": true,
"minLength": 1,
"maxLength": 20
},
"thresholds": {
"type": "float",
"isArray": true,
"minimum": 0.1,
"maximum": 0.9
}
},
"required": ["names"]
}| Version | Type | Change |
|---|---|---|
| 2025-10-09 | Initial | Established base fields: type, required, description, isArray, items, minLength, maxLength, minimum, maximum, enum. Added optional schemaVersion field support (ignored if absent). |
- Pattern (regex), format, nested objects, oneOf/anyOf/allOf.
- Distinguishing between integer vs. floating-point at the JSON level (we accept Go ints and floats for numeric constraints).
Validator returns human-friendly errors like:
missing required argument 'q'argument 'tags' must be an arrayargument 'q' string length must be >= 3argument 'limit' value must be <= 100argument 'mode' must be one of the enum values
- Prefer the JSON Schema–like shape when your schema is already JSON Schema or generated—use
type: "array"+itemsfor arrays. - For simple cases, the direct map shape is concise and easy to hand-write.
- Always specify
items.typefor arrays (or useisArray: true+type: "...") so element validation is precise.
Good descriptions improve UX and tooling. Recommended style:
- First sentence: high-level purpose (≤80 chars).
- Optional detail sentences: constraints, examples, domain semantics.
- Avoid leaking internal system names; focus on user intent.
Examples:
- "Primary search query string. Minimum length 3 characters." (string)
- "Confidence thresholds applied per model stage (0.0 – 1.0)." (float array)
- "Execution mode; choose fast for lower latency or accurate for higher quality." (enum)
- pattern (regex) enforcement for strings
- object / nested schema support
- default values application (currently not applied)
- deprecations via a
deprecated: trueflag - range validation for array length (minItems / maxItems)
This document reflects what ParseArgSchema and ValidateArgs in mcp/manager.go support for schema version 2025-10-09. Enhancements can be added incrementally; only breaking changes require a new version date.
{ "q": { "type": "string", "required": true, "minLength": 3, "maxLength": 64 }, "limit": { "type": "integer", "minimum": 1, "maximum": 100 }, "tags": { "type": "string", "isArray": true, "minLength": 2 }, "scores": { "type": "float", "isArray": true, "minimum": 0, "maximum": 1 }, "mode": { "type": "enum", "enum": ["fast", "accurate"] } }