Skip to content

HTTP Runner Protocol

The MTHDS Protocol is the minimal HTTP contract every MTHDS runner implements. Any server that serves these five routes with the shapes defined here is an MTHDS-compliant runner. A runner is just a runner: it executes methods, validates bundles, and reports what models it can route to and what version it is. It keeps no run store and owns no user, billing, or catalog concepts.

The normative artifact is the OpenAPI document: mthds-protocol.openapi.yaml. This page walks through it in prose, then renders it route by route — every parameter, request body, and response schema — in the route reference below. Where prose and YAML disagree, the YAML wins.

The five routes

Method Path Purpose
POST /execute Execute a method synchronously; the full output comes back in the response.
POST /start Start a method asynchronously; returns its pipeline_run_id immediately (202). Completion delivery is implementation-defined.
POST /validate Parse, validate, and dry-run an MTHDS bundle.
GET /models The models this runner can route to. Optional ?type= filter (llm · extract · img_gen · search).
GET /version Always public. Protocol and runner versions — the handshake clients use for feature detection.

All errors are RFC 7807 application/problem+json documents. Auth is implementation-defined: a bearer-token slot is reserved, and anonymous access is allowed for self-hosted runners.

Base URL and versioning

Protocol paths are version-agnostic. The version segment belongs to the server base URL, chosen by the implementation:

http://localhost:8081/v1/execute
https://api.example.com/v1/execute

The protocol itself is versioned by this standard (protocol_version in /version); each implementation versions its own mount point. A client written against the protocol composes {base_url}/{path} and never inspects the base URL's structure.

Executing a method

POST /execute is blocking: the response carries the method's full output. The request body is a RunRequest:

{
  "pipe_code": "analyze_contract",
  "mthds_contents": ["domain = \"legal\"\n..."],
  "inputs": {
    "contract": { "concept": "Document", "content": { "file_path": "..." } }
  }
}

At least one of pipe_code / mthds_contents is required. If mthds_contents is provided without pipe_code, the first bundle must declare a main_pipe. Optional fields: output_name, output_multiplicity, dynamic_output_concept_ref.

The 200 response is a RunResultExecute — the completed run, holding two base fields: pipeline_run_id (mandatory, server-generated and authoritative) and pipe_output (the method's serialized output; always present — a completed run has output). Anything more an implementation returns — a run state, timestamps, output naming, anything else — is an extension field (see Extension policy), declared and documented by that implementation.

The protocol sets no time limit on /execute; deployments cap it at their proxy layer. For long-running methods prefer /start. Implementations MAY answer 202 + RunResultStart (just the run id, no output yet) with a Location header pointing at an implementation-defined status resource when they cannot hold the connection open (RFC 9110 asynchronous pattern). Simple runners never emit 202; clients that cannot handle it should use /start.

Starting a method asynchronously

POST /start accepts the same RunRequest body as /execute — the protocol declares no start-only request fields. Anything an implementation accepts on top (a client-supplied run identifier, anything else) is an extension arg (see Extension policy), defined and documented by that implementation.

The response is 202 + RunResultStart — just the authoritative server-generated pipeline_run_id (plus any implementation extension fields). A started run has no output yet.

No run store, no completion channel

The protocol mandates no run store, and it defines no completion channel for /start: how a caller learns that an asynchronous run finished — webhooks, polling routes, anything else — is implementation-defined and outside the protocol (see Extension policy). A bare runner is not required to answer "what happened to run X?" after the fact. Clients written against the protocol alone must rely on /execute's response.

Validating a bundle

POST /validate takes mthds_contents (always an array, even for a single file) and an optional allow_signatures flag (default false — strict; when true, the validation sweep tolerates unimplemented pipe signatures by minting a mock). A valid bundle returns 200 — the status IS the verdict; the protocol declares no body fields, and implementations MAY include their own artifacts (parsed structures, graphs, anything else) as additional properties. An invalid bundle is a 422 problem.

Discovery

GET /models returns the runner's model deck — the models it can route to ({name, type} entries), optionally filtered by category. Implementations may add their own routing metadata (aliases, fallback chains, anything else) as additional properties.

GET /version is always public (no auth). It returns protocol_version (required) and an optional runner_version — implementations may add their own identification on top:

{
  "protocol_version": "0.6.0",
  "runner_version": "2.3.0"
}

Clients use /version as the handshake: it reports the protocol and runner versions, and any additional properties let clients detect vendor extensions before relying on them.

Extension policy

Implementations may extend the surface — extra routes, extra optional request properties, extra response properties — but must not change the meaning or shape of the protocol routes. Both sides of the wire are extension-open: request bodies accept implementation-defined args, and the protocol's response schemas declare only the base fields (additionalProperties allowed). A client written against the MTHDS Protocol runs unmodified against any compliant runner; a vendor's superset may accept and return more, but never diverges on the surface defined here.

Conformance

An implementation claiming conformance states it as: implements MTHDS Protocol v0.1. Conformance means: the five routes exist with the request/response shapes of mthds-protocol.openapi.yaml, errors are RFC 7807 problems, and /version is public.

Route reference

Everything below is rendered at build time from the normative OpenAPI document — do not edit it by hand; edit mthds-protocol.openapi.yaml.

Servers

Description URL
Example — a self-hosted runner. The version segment belongs to the server base URL; protocol paths are version-agnostic. http://localhost:8081/v1
Example — a hosted, protocol-compliant superset. https://api.example.com/v1

run


POST /execute

Execute a method synchronously and return its full output.

Description

Blocking. The protocol sets no time limit; deployments cap it at their proxy layer. For long-running methods prefer /start. Implementations MAY return 202 + RunResultStart (id only) with a Location header pointing at an implementation-defined status resource when they cannot hold the connection open for the full execution (RFC 9110 asynchronous pattern); clients that cannot handle 202 should use /start instead.

Input parameters

Parameter In Type Default Nullable Description
bearer header string N/A No Token semantics are implementation-defined.

Request body

{
    "pipe_code": "string",
    "mthds_contents": [
        "string"
    ],
    "inputs": {},
    "output_name": "string",
    "output_multiplicity": null,
    "dynamic_output_concept_ref": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "type": "object",
    "description": "At least one of pipe_code / mthds_contents is required (enforced by the anyOf rule below). If mthds_contents is provided without pipe_code, the first bundle must declare a main_pipe. Extension-open: implementations MAY accept extra top-level properties (extension args).\n",
    "additionalProperties": true,
    "anyOf": [
        {
            "required": [
                "pipe_code"
            ],
            "properties": {
                "pipe_code": {
                    "type": "string",
                    "minLength": 1
                }
            }
        },
        {
            "required": [
                "mthds_contents"
            ],
            "properties": {
                "mthds_contents": {
                    "type": "array",
                    "minItems": 1
                }
            }
        }
    ],
    "properties": {
        "pipe_code": {
            "type": [
                "string",
                "null"
            ],
            "description": "Code of the pipe to execute (a pipe already registered, or one defined in mthds_contents)."
        },
        "mthds_contents": {
            "type": [
                "array",
                "null"
            ],
            "minItems": 1,
            "items": {
                "type": "string"
            },
            "description": "MTHDS bundle contents to load (always an array, even for a single file; never empty). Implementations bound count and per-file size."
        },
        "inputs": {
            "type": [
                "object",
                "null"
            ],
            "description": "Method inputs: map of input name to { concept, content }. Content shapes follow the concept's structure; content validation is deliberately loose here and strict inside the runtime.",
            "additionalProperties": {
                "type": "object",
                "required": [
                    "concept",
                    "content"
                ],
                "properties": {
                    "concept": {
                        "type": "string"
                    },
                    "content": {}
                }
            }
        },
        "output_name": {
            "type": [
                "string",
                "null"
            ],
            "description": "Name of the output slot to return as the main output."
        },
        "output_multiplicity": {
            "oneOf": [
                {
                    "type": "boolean"
                },
                {
                    "type": "integer"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Output multiplicity override (false/true or an explicit count)."
        },
        "dynamic_output_concept_ref": {
            "type": [
                "string",
                "null"
            ],
            "description": "Override for the dynamic output concept reference."
        }
    }
}

Responses

{
    "pipeline_run_id": "string",
    "pipe_output": {}
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "POST /execute 200 — the completed run. Two base fields: the server-generated authoritative pipeline_run_id and the method's pipe_output (always present — a completed run has output). Extension-open: anything more an implementation returns (a run state, timestamps, output naming) is an extension on top.\n",
    "additionalProperties": true,
    "required": [
        "pipeline_run_id",
        "pipe_output"
    ],
    "properties": {
        "pipeline_run_id": {
            "type": "string",
            "description": "The run identifier — server-generated and authoritative."
        },
        "pipe_output": {
            "description": "The method's serialized output (working memory of serialized stuffs).",
            "type": "object"
        }
    }
}

{
    "pipeline_run_id": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "POST /start 202 (and the optional /execute 202 degrade) — the started run's authoritative pipeline_run_id, nothing else. A started run has no output yet; how it is delivered later (polling, callbacks, anything else) is implementation-defined and outside the protocol. Extension-open.\n",
    "additionalProperties": true,
    "required": [
        "pipeline_run_id"
    ],
    "properties": {
        "pipeline_run_id": {
            "type": "string",
            "description": "The run identifier — server-generated and authoritative."
        }
    }
}

Response headers

Name Description Schema
Location Implementation-defined status resource for this run. string

Refer to the common response description: ValidationProblem.

Refer to the common response description: Problem.


POST /start

Start a method asynchronously; returns its pipeline_run_id immediately.

Description

Asynchronous. Returns 202 + RunResultStart immediately (pipeline_run_id only); the runner keeps no run store, and how completion is later delivered (callbacks, polling, anything else) is implementation-defined and outside the protocol. The returned pipeline_run_id is always authoritative (server-generated).

Input parameters

Parameter In Type Default Nullable Description
bearer header string N/A No Token semantics are implementation-defined.

Request body

{
    "pipe_code": "string",
    "mthds_contents": [
        "string"
    ],
    "inputs": {},
    "output_name": "string",
    "output_multiplicity": null,
    "dynamic_output_concept_ref": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "type": "object",
    "description": "At least one of pipe_code / mthds_contents is required (enforced by the anyOf rule below). If mthds_contents is provided without pipe_code, the first bundle must declare a main_pipe. Extension-open: implementations MAY accept extra top-level properties (extension args).\n",
    "additionalProperties": true,
    "anyOf": [
        {
            "required": [
                "pipe_code"
            ],
            "properties": {
                "pipe_code": {
                    "type": "string",
                    "minLength": 1
                }
            }
        },
        {
            "required": [
                "mthds_contents"
            ],
            "properties": {
                "mthds_contents": {
                    "type": "array",
                    "minItems": 1
                }
            }
        }
    ],
    "properties": {
        "pipe_code": {
            "type": [
                "string",
                "null"
            ],
            "description": "Code of the pipe to execute (a pipe already registered, or one defined in mthds_contents)."
        },
        "mthds_contents": {
            "type": [
                "array",
                "null"
            ],
            "minItems": 1,
            "items": {
                "type": "string"
            },
            "description": "MTHDS bundle contents to load (always an array, even for a single file; never empty). Implementations bound count and per-file size."
        },
        "inputs": {
            "type": [
                "object",
                "null"
            ],
            "description": "Method inputs: map of input name to { concept, content }. Content shapes follow the concept's structure; content validation is deliberately loose here and strict inside the runtime.",
            "additionalProperties": {
                "type": "object",
                "required": [
                    "concept",
                    "content"
                ],
                "properties": {
                    "concept": {
                        "type": "string"
                    },
                    "content": {}
                }
            }
        },
        "output_name": {
            "type": [
                "string",
                "null"
            ],
            "description": "Name of the output slot to return as the main output."
        },
        "output_multiplicity": {
            "oneOf": [
                {
                    "type": "boolean"
                },
                {
                    "type": "integer"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Output multiplicity override (false/true or an explicit count)."
        },
        "dynamic_output_concept_ref": {
            "type": [
                "string",
                "null"
            ],
            "description": "Override for the dynamic output concept reference."
        }
    }
}

Responses

{
    "pipeline_run_id": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "POST /start 202 (and the optional /execute 202 degrade) — the started run's authoritative pipeline_run_id, nothing else. A started run has no output yet; how it is delivered later (polling, callbacks, anything else) is implementation-defined and outside the protocol. Extension-open.\n",
    "additionalProperties": true,
    "required": [
        "pipeline_run_id"
    ],
    "properties": {
        "pipeline_run_id": {
            "type": "string",
            "description": "The run identifier — server-generated and authoritative."
        }
    }
}

Refer to the common response description: ValidationProblem.

Refer to the common response description: Problem.

validate


POST /validate

Parse, validate, and dry-run an MTHDS bundle.

Input parameters

Parameter In Type Default Nullable Description
bearer header string N/A No Token semantics are implementation-defined.

Request body

{
    "mthds_contents": [
        "string"
    ],
    "allow_signatures": true
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "type": "object",
    "required": [
        "mthds_contents"
    ],
    "properties": {
        "mthds_contents": {
            "type": "array",
            "minItems": 1,
            "items": {
                "type": "string"
            },
            "description": "MTHDS contents to load (always an array, even for a single file)."
        },
        "allow_signatures": {
            "type": "boolean",
            "default": false,
            "description": "When true, the validation sweep tolerates unimplemented pipe signatures (signatures dry-run by minting a mock). Strict by default."
        }
    }
}

Responses

Schema of the response body
{
    "type": "object",
    "description": "Returned only when the bundle is valid; failures are RFC 7807 problems. The 200 status IS the verdict — the protocol declares no body fields. Implementations MAY include their own artifacts (parsed structures, graphs, anything else) as additional properties.\n",
    "additionalProperties": true
}

Refer to the common response description: ValidationProblem.

Refer to the common response description: Problem.

discovery


GET /models

The model deck available on this runner.

Input parameters

Parameter In Type Default Nullable Description
bearer header string N/A No Token semantics are implementation-defined.
type query string No Filter the deck by model category.

Responses

{
    "models": [
        {
            "name": "string",
            "type": "llm"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "The models this runner can route to. Implementations MAY add their own routing metadata (aliases, fallback chains, anything else) as additional properties — on the deck and on each model entry.\n",
    "additionalProperties": true,
    "properties": {
        "models": {
            "type": "array",
            "items": {
                "type": "object",
                "additionalProperties": true,
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "llm",
                            "extract",
                            "img_gen",
                            "search"
                        ]
                    }
                }
            }
        }
    }
}

Refer to the common response description: Problem.


GET /version

Protocol and runner versions.

Responses

{
    "protocol_version": "string",
    "runner_version": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "The handshake. The protocol defines protocol_version (required) plus an optional runner_version; implementations MAY add their own identification (a name, an underlying runtime version, anything else) as additional properties.\n",
    "required": [
        "protocol_version"
    ],
    "additionalProperties": true,
    "properties": {
        "protocol_version": {
            "type": "string",
            "description": "MTHDS Protocol version implemented."
        },
        "runner_version": {
            "type": [
                "string",
                "null"
            ],
            "description": "Version of the runner serving this protocol (optional)."
        }
    }
}

Refer to the common response description: Problem.


Schemas

ModelDeck

Name Type Description
models Array<Properties: name, type>

Problem

Name Type Description
detail string
instance string
status integer
title string
type string(uri)

RunRequest

Name Type Description
dynamic_output_concept_ref string | null Override for the dynamic output concept reference.
inputs Method inputs: map of input name to { concept, content }. Content shapes follow the concept's structure; content validation is deliberately loose here and strict inside the runtime.
mthds_contents Array<string> MTHDS bundle contents to load (always an array, even for a single file; never empty). Implementations bound count and per-file size.
output_multiplicity Output multiplicity override (false/true or an explicit count).
output_name string | null Name of the output slot to return as the main output.
pipe_code string | null Code of the pipe to execute (a pipe already registered, or one defined in mthds_contents).

RunResultExecute

Name Type Description
pipe_output The method's serialized output (working memory of serialized stuffs).
pipeline_run_id string The run identifier — server-generated and authoritative.

RunResultStart

Name Type Description
pipeline_run_id string The run identifier — server-generated and authoritative.

ValidateRequest

Name Type Description
allow_signatures boolean When true, the validation sweep tolerates unimplemented pipe signatures (signatures dry-run by minting a mock). Strict by default.
mthds_contents Array<string> MTHDS contents to load (always an array, even for a single file).

ValidationReport

VersionInfo

Name Type Description
protocol_version string MTHDS Protocol version implemented.
runner_version string | null Version of the runner serving this protocol (optional).

Common responses

This section describes common responses that are reused across operations.

Problem

RFC 7807 problem document.

{
    "type": "string",
    "title": "string",
    "status": 0,
    "detail": "string",
    "instance": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "RFC 7807.",
    "properties": {
        "type": {
            "type": "string",
            "format": "uri"
        },
        "title": {
            "type": "string"
        },
        "status": {
            "type": "integer"
        },
        "detail": {
            "type": "string"
        },
        "instance": {
            "type": "string"
        }
    }
}

ValidationProblem

The request or bundle failed validation (RFC 7807).

{
    "type": "string",
    "title": "string",
    "status": 0,
    "detail": "string",
    "instance": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "description": "RFC 7807.",
    "properties": {
        "type": {
            "type": "string",
            "format": "uri"
        },
        "title": {
            "type": "string"
        },
        "status": {
            "type": "integer"
        },
        "detail": {
            "type": "string"
        },
        "instance": {
            "type": "string"
        }
    }
}

Security schemes

Name Type Scheme Description
bearer http bearer Token semantics are implementation-defined.

Tags

Name Description
run Execute methods, synchronously or asynchronously.
validate Static + dry-run validation of MTHDS bundles.
discovery What this runner is and what it can route to.