kervan.yaml reference

A kervan.yaml file declares an MCP server whose tools are HTTP requests. This page lists every field, generated from the spec’s JSON Schema.

Where this fits: Build with YAML. The reference for every field; HTTP tools and the pages after it explain how the fields work together.

On this page

A complete example

examples/spec/kervan.yaml
specVersion: 1
name: open-meteo
version: 0.1.0
description: Weather and city lookup backed by the public Open-Meteo APIs (no API key needed).

defaults:
  http: { timeoutMs: 8000, maxResponseBytes: 262144 }
  rateLimit: { perMinute: 30, concurrency: 5 }

tools:
  - name: search_city
    title: Search city
    description: Finds up to 5 places by name and returns their coordinates.
    annotations: { readOnlyHint: true }
    input:
      type: object
      properties:
        name: { type: string, minLength: 2, maxLength: 100, description: "City name, e.g. Ankara" }
      required: [name]
    http:
      url: https://geocoding-api.open-meteo.com/v1/search
      query: { name: "{{input.name}}", count: 5, language: en, format: json }
    output:
      # Only the fields the model needs; never the whole API response.
      select: "results[].{name: name, country: country, latitude: latitude, longitude: longitude}"

  - name: get_current_weather
    title: Current weather
    description: Current temperature (°C), wind speed (km/h) and WMO weather code at a coordinate.
    annotations: { readOnlyHint: true }
    input:
      type: object
      properties:
        latitude: { type: number, minimum: -90, maximum: 90 }
        longitude: { type: number, minimum: -180, maximum: 180 }
      required: [latitude, longitude]
    http:
      url: https://api.open-meteo.com/v1/forecast
      query:
        latitude: "{{input.latitude}}"
        longitude: "{{input.longitude}}"
        current: temperature_2m,wind_speed_10m,weather_code
    output:
      select: "{temperatureC: current.temperature_2m, windKmh: current.wind_speed_10m, weatherCode: current.weather_code}"
      schema:
        type: object
        properties:
          temperatureC: { type: number }
          windKmh: { type: number }
          weatherCode: { type: integer }
        required: [temperatureC, windKmh, weatherCode]

Two things to know before the table:

  • specVersion is always 1. A breaking change of the format would become specVersion: 2.
  • Unknown fields are errors, and every error names the file, line and column, for example kervan.yaml:12:5 tools[0].http.url: The URL's host and port cannot be templated.

Fields

tools[].output has two forms: select (with an optional schema), or raw: true. Both are listed below. tools[].input and output.schema are ordinary JSON Schema (2020-12); their limits are in input and output.

Generated from the editor schema, Kervan spec (https://getkervan.dev/schema/v1.json), when this site was built.

FieldTypeDescription and limits
defaultsobject
defaults.httpobjectDefaults for every tool’s HTTP request.
defaults.http.allowInsecureHttpbooleanAllow plain http:// URLs. Off by default: requests, answers and any secrets would travel unencrypted.
defaults.http.followRedirectsintegerHow many redirects to follow (default 0). Each hop is checked again; secret headers are dropped when the host changes.
at least 0; at most 5
defaults.http.maxOutputCharsintegerLongest tool output sent to the model; longer output is cut.
at least 1; at most 1e+06
defaults.http.maxResponseBytesintegerLargest response body accepted, after decompression.
at least 1; at most 5.24288e+07
defaults.http.timeoutMsintegerRequest timeout in milliseconds (connect and response).
at least 100; at most 120000
defaults.rateLimitobjectPer-tool limits on outgoing calls (defaults: 60 per minute, 10 at once).
defaults.rateLimit.concurrencyintegerat least 1; at most 1000
defaults.rateLimit.perMinuteintegerat least 1; at most 100000
descriptionstring
name
required
string1+ characters; up to 128 characters
secretsarray of string or objectSecrets this spec may use as {{secrets.NAME}}: a name, or { name, hosts } to allow sending it only to those hosts. Only declared names are resolved.
up to 100 items; a name: pattern ^[A-Z][A-Z0-9_]{0,127}$
secrets[].hosts
required
array of stringThe only hosts this secret may be sent to, as host or host:port (port 443 when omitted), matched exactly (no subdomains or wildcards), e.g. api.example.com or api.example.com:8443.
1+ items; up to 32 items; each: pattern ^(?:[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.?|\[[0-9A-Fa-f:.]+\])(?::\d{1,5})?$
secrets[].name
required
stringpattern ^[A-Z][A-Z0-9_]{0,127}$
specVersion
required
1 (constant)
tools
required
array of object1+ items; up to 200 items
tools[].annotationsobject
tools[].annotations.destructiveHintboolean
tools[].annotations.idempotentHintboolean
tools[].annotations.openWorldHintboolean
tools[].annotations.readOnlyHintboolean
tools[].annotations.titlestring
tools[].description
required
stringWhat the tool does; the model’s main guidance.
1+ characters
tools[].http
required
objectThe HTTP request this tool makes.
tools[].http.allowInsecureHttpboolean
tools[].http.bodyany JSON valueJSON request body. String values may contain templates.
tools[].http.followRedirectsintegerHow many redirects to follow (default 0). Each hop is checked again; secret headers are dropped when the host changes.
at least 0; at most 5
tools[].http.headersmap of string or number or booleanRequest headers. Names are literal; values may contain templates.
tools[].http.maxResponseBytesintegerLargest response body accepted, after decompression.
at least 1; at most 5.24288e+07
tools[].http.methodstringone of GET, POST, PUT, PATCH, DELETE; default GET
tools[].http.querymap of string or number or boolean or array of string or number or booleanQuery parameters. Values may contain templates.
tools[].http.timeoutMsintegerRequest timeout in milliseconds (connect and response).
at least 100; at most 120000
tools[].http.url
required
stringRequest URL. Scheme, host and port must be literal; {{input.x}} and {{secrets.X}} may appear in the path. Put templated query parameters under query.
1+ characters
tools[].inputmapJSON Schema of the arguments; must have type: object.
tools[].name
required
stringTool name: 1-128 of A-Z a-z 0-9 _ - .
pattern ^[A-Za-z0-9_.-]{1,128}$
tools[].output
required
objectHow the response becomes the tool result: select (JMESPath) or raw: true.
tools[].output.maxOutputCharsintegerLongest tool output sent to the model; longer output is cut.
at least 1; at most 1e+06
tools[].output.schemamapJSON Schema of the selected value. When set, the tool returns structured content.
tools[].output.select
required
stringJMESPath expression that picks and reshapes the fields the model sees, e.g. {temp: main.temp}. External API output is untrusted; select only what is needed.
1+ characters; up to 1000 characters
tools[].output.maxOutputCharsintegerLongest tool output sent to the model; longer output is cut.
at least 1; at most 1e+06
tools[].output.raw
required
true (constant)Return the response body as text (cut to maxOutputChars) instead of selecting fields. Prefer select.
tools[].rateLimitobjectPer-tool limits on outgoing calls (defaults: 60 per minute, 10 at once).
tools[].rateLimit.concurrencyintegerat least 1; at most 1000
tools[].rateLimit.perMinuteintegerat least 1; at most 100000
tools[].titlestring
version
required
string1+ characters; up to 64 characters

Templates

Only two kinds of placeholders exist, {{input.field}} (nested: {{input.user.id}}) and {{secrets.NAME}}. There is no logic, no filter and no expression; anything else is a load error, and \{{ writes a literal {{. Each value is encoded for where it goes: see HTTP tools.

Editor support

The schema in the table above ships in @kervan/spec-runtime as schema/kervan.schema.json. With the YAML extension of VS Code, point the file at it:

yaml
# yaml-language-server: $schema=./node_modules/@kervan/spec-runtime/schema/kervan.schema.json

The schema’s $id, https://getkervan.dev/schema/v1.json, is also where this site serves the same file. Loading a spec never fetches anything: validation always uses the copy in the package.