Input and output

The input schema is what the model must send; the output section is what it gets back. Both are deliberate in Kervan.

Where this fits: Build with YAML. Between the HTTP request and the select expression.

On this page

Input: the arguments

input is a JSON Schema of type object. Clients list it as the tool’s inputSchema, and every call is validated against it before any request is made: invalid arguments come back to the model as a tool error it can read and fix, and no request is sent.

yaml
input:
  type: object
  properties:
    latitude: { type: number, minimum: -90, maximum: 90 }
    longitude: { type: number, minimum: -180, maximum: 180 }
    units: { type: string, enum: [metric, imperial] }
  required: [latitude, longitude]

Arguments reach the request only through templates ({{input.latitude}}), each encoded for its place; see HTTP tools.

Output: what the model sees

An API response is untrusted input for the model: it can be large, and it can carry instructions (prompt injection). A spec tool therefore has to choose:

  • select: a JMESPath expression that picks and reshapes the fields the model needs (required unless raw is set);
  • raw: true: the response body as text, for the cases where the whole body is the point.
yaml
output:
  select: "{temperatureC: current.temperature_2m, windKmh: current.wind_speed_10m}"
  schema:
    type: object
    properties:
      temperatureC: { type: number }
      windKmh: { type: number }
    required: [temperatureC, windKmh]
  • With schema, the selected value becomes the result’s structuredContent (validated against the schema) as well as text. Clients see the schema as the tool’s outputSchema.
  • Output is cut at maxOutputChars (20,000 characters by default).
  • Secret values are redacted from the response before select runs, so an expression cannot reshape or probe a secret an API echoed.

The quickstart’s example shows a real result:

tools/call request (recorded)
{
  "id": 4,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/protocolVersion": "2026-07-28"
    },
    "arguments": {
      "latitude": 39.92,
      "longitude": 32.85
    },
    "name": "get_current_weather"
  }
}
tools/call result, October 8, 2026
{
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "open-meteo",
      "version": "0.1.0"
    }
  },
  "content": [
    {
      "text": "{\"temperatureC\":21.1,\"windKmh\":5.9,\"weatherCode\":2}",
      "type": "text"
    }
  ],
  "resultType": "complete",
  "structuredContent": {
    "temperatureC": 21.1,
    "weatherCode": 2,
    "windKmh": 5.9
  }
}

Schemas in a spec

input and output.schema are JSON Schema 2020-12. Only same-document $refs (#/...) are allowed, so nothing is ever fetched; $id and dynamic references are refused. Schemas are limited to 32 levels, 2,000 nodes, 64 anyOf/oneOf/allOf keywords, 64 KiB and 512-character patterns.