Hosted mock APIs from OpenAPI, TypeScript or Postman: realistic data, errors and latency on demand.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Optional. Bearer la_… (Loutre API token) to list and manage your account's mocks; without it, mocks are created anonymously.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Add a conditional response to a route: when the request matches the conditions (query, header, path param, body field), the mock answers with this status, body and latency. Rules are evaluated in order, the first match wins; x-loutre-* headers keep priority.
Subdomain of the mock, e.g. "brisk-otter"
Every condition must hold
Route identifier, lowercase method: "get:/users/{id}"
JSON body of the response
Human-readable label of the rule
Owner token received at creation (not needed when the account is connected with an API token)
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
claude mcp add --transport http loutre https://api.loutre.app/mcp
Headers
Authorization (optional, not in the config above): Optional. Bearer la_… (Loutre API token) to list and manage your account's mocks; without it, mocks are created anonymously.Add a conditional response to a route: when the request matches the conditions (query, header, path param, body field), the mock answers with this status, body and latency. Rules are evaluated in order, the first match wins; x-loutre-* headers keep priority.
| Argument | Type | Description |
|---|---|---|
| body | any | JSON body of the response |
| name | string | Human-readable label of the rule |
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| when* | object | Every condition must hold |
| route* | string | Route identifier, lowercase method: "get:/users/{id}" |
| status | integer | |
| latencyMs | number | |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"route",
"when"
],
"properties": {
"body": {
"description": "JSON body of the response"
},
"name": {
"type": "string",
"maxLength": 60,
"description": "Human-readable label of the rule"
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"when": {
"type": "object",
"properties": {
"body": {
"type": "object",
"description": "Expected JSON body fields, by dotted path (customer.email)",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"param": {
"type": "object",
"description": "Expected path parameters ({id})",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"query": {
"type": "object",
"description": "Expected query parameters",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"header": {
"type": "object",
"description": "Expected headers",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
}
},
"description": "Every condition must hold",
"additionalProperties": false
},
"route": {
"type": "string",
"description": "Route identifier, lowercase method: \"get:/users/{id}\""
},
"status": {
"type": "integer",
"maximum": 599,
"minimum": 100
},
"latencyMs": {
"type": "number",
"maximum": 30000,
"minimum": 0
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Call a route of the mock like an HTTP client would and return the status, the x-loutre-* headers and the body. The headers x-loutre-status, x-loutre-delay, x-loutre-count, x-loutre-message and x-loutre-seed are honoured; latency is not awaited, it is reported in delayMs. Writes (POST, PUT, PATCH, DELETE) are persisted when persistent state is on. For a GraphQL mock, POST to its GraphQL path with the body { "query": "…", "variables": { … } }; mutations are persisted the same way.
| Argument | Type | Description |
|---|---|---|
| body | any | JSON body for POST, PUT, PATCH |
| path* | string | Path with its query string: "/users/42?expand=orders" |
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| method* | string | |
| headers | object | Request headers, including x-loutre-* |
| accessKey | string | Access key (lk_…) of a private mock you do not own |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"method",
"path"
],
"properties": {
"body": {
"description": "JSON body for POST, PUT, PATCH"
},
"path": {
"type": "string",
"minLength": 1,
"description": "Path with its query string: \"/users/42?expand=orders\""
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"method": {
"enum": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"HEAD",
"OPTIONS",
"QUERY"
],
"type": "string",
"default": "GET"
},
"headers": {
"type": "object",
"description": "Request headers, including x-loutre-*",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"accessKey": {
"type": "string",
"description": "Access key (lk_…) of a private mock you do not own"
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Empty the mock's request log.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Remove every conditional rule of a route.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| route* | string | Route identifier, lowercase method: "get:/users/{id}" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"route"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"route": {
"type": "string",
"description": "Route identifier, lowercase method: \"get:/users/{id}\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Create a hosted mock from an OpenAPI 3.0/3.1 or Swagger 2.0 document (YAML or JSON), from TypeScript types (interfaces, types, enums: CRUD routes derived, or a route map type keyed like "GET /users") or from a Postman v2 collection, an Insomnia export (v4 JSON or v5 YAML), a Bruno collection (JSON export, or .bru files one after the other), a HAR file (headers and cookies are dropped, data is generated), a json-server db.json (records served as they are), curl commands, or a GraphQL schema (SDL or introspection JSON; Pro plan: queries, mutations and introspection answered on POST /graphql). OpenAPI 3.2 is read too. Give the document in `spec`, or its public address in `url` (then the mock re-reads it every six hours and follows changes). Returns the URL, the route list and an ownerToken to keep for later changes. Data is realistic and coherent, generated once. Without an account the mock lives seven days.
| Argument | Type | Description |
|---|---|---|
| url | string | Public URL of the document, instead of spec |
| auto | boolean | With url: re-read every six hours (default true) |
| seed | string | Data seed, for reproducible data sets |
| slug | string | Desired subdomain (Pro plan) |
| spec | string | The full document, verbatim: OpenAPI, Swagger, TypeScript types, a Postman, Insomnia or Bruno collection, a HAR file, a db.json or curl commands |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "Public URL of the document, instead of spec"
},
"auto": {
"type": "boolean",
"description": "With url: re-read every six hours (default true)"
},
"seed": {
"type": "string",
"maxLength": 64,
"description": "Data seed, for reproducible data sets"
},
"slug": {
"type": "string",
"maxLength": 63,
"description": "Desired subdomain (Pro plan)"
},
"spec": {
"type": "string",
"minLength": 1,
"description": "The full document, verbatim: OpenAPI, Swagger, TypeScript types, a Postman, Insomnia or Bruno collection, a HAR file, a db.json or curl commands"
}
},
"additionalProperties": false
}Permanently delete a mock and its kept schema.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Details of a mock: routes with identifiers, behaviour, lock, sample generated bodies per route.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}The latest requests received by the mock, most recent first: method, path, query, status, headers and body as received (body cut at 8 KB), where the answer came from, latency. Each entry has an id for replay_request.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| limit | integer | |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}List the connected account's mocks (API token required), with their URL, routes and expiry.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {},
"additionalProperties": false
}Generate a new data set (new seed), for the whole mock or for one route and the routes sharing its collection. A full new set forgets persisted writes.
| Argument | Type | Description |
|---|---|---|
| seed | string | |
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| routeId | string | Route identifier, lowercase method: "get:/users/{id}" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"seed": {
"type": "string",
"maxLength": 64
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"routeId": {
"type": "string",
"description": "Route identifier, lowercase method: \"get:/users/{id}\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Replay a request from the log exactly as it was received (same method, path, headers and body) against the mock as it is now, and return the answer. Useful after changing a rule, a body or a scenario.
| Argument | Type | Description |
|---|---|---|
| id* | string | Entry id from get_requests |
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Entry id from get_requests"
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Forget persisted writes (POST, PUT, PATCH, DELETE): the generated collections come back as they were.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Lock a mock with a token (private) and/or restrict the allowed browser origins. Pro plan.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| origins | any | Allowed origins (https://app.example.com); null to allow all |
| private | boolean | |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"origins": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"description": "Allowed origins (https://app.example.com); null to allow all"
},
"private": {
"type": "boolean"
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Change a mock's behaviour: default status, latency, jitter, error rate, persistent writes, and per route status, latency, hand-written bodies, rules. Merge semantics: missing keys are kept, null clears.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| patch* | object | Same fields as PATCH /mocks/:slug/behavior: a missing key is kept, null clears |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"patch"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"patch": {
"type": "object",
"properties": {
"proxy": {
"type": [
"string",
"null"
],
"description": "Base URL of a real backend: routes the schema does not describe are forwarded there; null removes"
},
"jitter": {
"anyOf": [
{
"type": "number",
"maximum": 1,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Random latency variation (0.3 = ± 30 %)"
},
"routes": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "object",
"properties": {
"rules": {
"anyOf": [
{
"type": "array",
"items": {}
},
{
"type": "null"
}
],
"description": "Conditional rules (see add_rule); the list replaces the existing one"
},
"bodies": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
{
"type": "null"
}
],
"description": "Status → hand-written JSON body; null removes"
},
"status": {
"anyOf": [
{
"type": "integer",
"maximum": 599,
"minimum": 100
},
{
"type": "null"
}
]
},
"errorRate": {
"anyOf": [
{
"type": "number",
"maximum": 1,
"minimum": 0
},
{
"type": "null"
}
]
},
"latencyMs": {
"anyOf": [
{
"type": "number",
"maximum": 30000,
"minimum": 0
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
{
"type": "null"
}
],
"description": "Settings per route identifier"
},
"status": {
"anyOf": [
{
"type": "integer",
"maximum": 599,
"minimum": 100
},
{
"type": "null"
}
],
"description": "Forced status for the whole mock; null to remove"
},
"stateful": {
"type": [
"boolean",
"null"
],
"description": "Persistent writes (true by default)"
},
"errorRate": {
"anyOf": [
{
"type": "number",
"maximum": 1,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Share of requests that return an error"
},
"latencyMs": {
"anyOf": [
{
"type": "number",
"maximum": 30000,
"minimum": 0
},
{
"type": "null"
}
]
},
"scenarios": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{},
{
"type": "null"
}
]
}
},
{
"type": "null"
}
],
"description": "Named bundles of settings (same fields as this patch minus scenarios and proxy), applied per request with the x-loutre-scenario header or with activeScenario; null removes"
},
"graphqlPath": {
"type": [
"string",
"null"
],
"description": "GraphQL mocks only: the path the endpoint answers on, /graphql by default (e.g. /api/graphql); null restores /graphql"
},
"activeScenario": {
"type": [
"string",
"null"
],
"description": "Scenario applied to every request without an x-loutre-scenario header; null deactivates"
}
},
"description": "Same fields as PATCH /mocks/:slug/behavior: a missing key is kept, null clears",
"additionalProperties": false
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Serve the mock under the account's own hostname (Pro): declares it at Cloudflare and returns the CNAME to create (hostname → target) plus the current status; call again without hostname to re-check, or with hostname null to remove it.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| hostname | any | e.g. mock.acme.com; null removes; omitted re-checks the status |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"hostname": {
"anyOf": [
{
"type": "string",
"maxLength": 253
},
{
"type": "null"
}
],
"description": "e.g. mock.acme.com; null removes; omitted re-checks the status"
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Set the JSON body a route returns for a given status (hand-written response); a null body restores the generated response.
| Argument | Type | Description |
|---|---|---|
| body* | any | JSON body, or null to go back to the generated response |
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| route* | string | Route identifier, lowercase method: "get:/users/{id}" |
| status* | integer | |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug",
"route",
"status",
"body"
],
"properties": {
"body": {
"description": "JSON body, or null to go back to the generated response"
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"route": {
"type": "string",
"description": "Route identifier, lowercase method: \"get:/users/{id}\""
},
"status": {
"type": "integer",
"maximum": 599,
"minimum": 100
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}Re-read the schema at the mock's source URL now and update the mock if it changed (routes, fields; settings kept, persisted writes forgotten). force regenerates even when the document is unchanged.
| Argument | Type | Description |
|---|---|---|
| slug* | string | Subdomain of the mock, e.g. "brisk-otter" |
| force | boolean | |
| ownerToken | string | Owner token received at creation (not needed when the account is connected with an API token) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"pattern": "^[a-z0-9-]{1,63}$",
"description": "Subdomain of the mock, e.g. \"brisk-otter\""
},
"force": {
"type": "boolean"
},
"ownerToken": {
"type": "string",
"description": "Owner token received at creation (not needed when the account is connected with an API token)"
}
},
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 2, 2026.
No readOnlyHint / destructiveHint annotations, so clients can't tell a read from a write without asking.
Fix: Add annotations to each tool, e.g. { readOnlyHint: true } for tools that only read.