Developers
Build Myrmigo into your own agent.
Before your agent acts on a travel site, it can ask Myrmigo how that task is done there: the official page, which company services the booking, what to have ready and where the person takes over. The reference server is live, anonymous and read-only. It needs no sign-up and no API key.
MCP serverlive · no key
https://mcp.myrmigo.com/mcpStreamable HTTP. Three read-only tools: check_booking_change_cancel_refund, find_official_booking_site and check_flight_compensation (EU261/UK261 check).
RESTlive · anonymous · JSON
POST https://mcp.myrmigo.com/v1/referenceAnswer format: JSON Schema · API: OpenAPI 3.1
Pick a path
- A model provider calls Myrmigo for you: the Claude API or OpenAI’s hosted MCP tool. The server is public, so their servers can reach it.
- An MCP client in your own process: LangChain, LangGraph, or the OpenAI Agents SDK’s local client.
- A framework that only starts local servers: the npm proxy,
npx -y myrmigo-mcp. - Plain HTTP: the same answer as JSON over REST.
Using Myrmigo in an app such as Claude, Cursor or VS Code instead? See Connect.
Claude API
Anthropic’s servers call Myrmigo for you through the Messages API MCP connector. You need both halves: the server in mcp_servers and an mcp_toolset entry in tools. We have tried the connector with these two fields; the code around them comes from Anthropic’s documentation.
TypeScript (@anthropic-ai/sdk)not tested yet
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic(); // reads ANTHROPIC_API_KEY
const response = await anthropic.beta.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1000,
messages: [{ role: 'user', content: 'My Blue Star ferry was booked on Ferryhopper. How do I change the date?' }],
mcp_servers: [{ type: 'url', url: 'https://mcp.myrmigo.com/mcp', name: 'myrmigo' }], // no authorization_token: it is anonymous
tools: [{ type: 'mcp_toolset', mcp_server_name: 'myrmigo' }],
betas: ['mcp-client-2025-11-20'],
});
for (const block of response.content) {
if (block.type === 'mcp_tool_use') console.log('asked Myrmigo:', block.input);
else if (block.type === 'mcp_tool_result') console.log('Myrmigo answered', block.is_error ? '(error)' : '');
else if (block.type === 'text') console.log(block.text);
}From Anthropic: MCP connector, checked 2026-09-26. We haven’t run it yet.
Python (anthropic)not tested yet
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1000,
messages=[{"role": "user", "content": "How do I check in online for my Aegean flight?"}],
mcp_servers=[{"type": "url", "url": "https://mcp.myrmigo.com/mcp", "name": "myrmigo"}],
tools=[{"type": "mcp_toolset", "mcp_server_name": "myrmigo"}],
betas=["mcp-client-2025-11-20"],
)
for block in response.content:
if block.type == "text":
print(block.text)From Anthropic: MCP connector, checked 2026-09-26. We haven’t run it yet.
curlnot tested yet
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mcp-client-2025-11-20" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 1000,
"messages": [{ "role": "user", "content": "How do I check in online for my Aegean flight?" }],
"mcp_servers": [{ "type": "url", "url": "https://mcp.myrmigo.com/mcp", "name": "myrmigo" }],
"tools": [{ "type": "mcp_toolset", "mcp_server_name": "myrmigo" }]
}'From Anthropic: MCP connector, checked 2026-09-26. We haven’t run it yet.
- The answer comes back as mcp_tool_use and mcp_tool_result blocks between the text blocks.
- The connector uses the server’s tools only, not its instructions.
- With the newer beta header mcp-client-2026-09-15 (tool-list pinning), the response can start with an mcp_tool_listing block. If your code reads content[0], skip those blocks.
OpenAI: Agents SDK and Responses API
HostedMCPTool (hostedMcpTool in JavaScript) and the Responses API’s mcp tool let OpenAI’s servers call Myrmigo. MCPServerStreamableHttp calls it from your own process instead, with any model the SDK supports.
Agents SDK, Python: hosted toolnot tested yet
import asyncio
from agents import Agent, HostedMCPTool, Runner
agent = Agent(
name="Travel assistant",
instructions="Help the user with tasks on their own travel bookings.",
tools=[
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "myrmigo",
"server_url": "https://mcp.myrmigo.com/mcp",
"require_approval": "never",
}
)
],
)
async def main() -> None:
result = await Runner.run(agent, "My Blue Star ferry was booked on Ferryhopper. How do I change the date?")
print(result.final_output)
asyncio.run(main())From OpenAI Agents SDK: MCP, checked 2026-09-26. We haven’t run it yet.
Agents SDK, Python: from your processnot tested yet
import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
async def main() -> None:
async with MCPServerStreamableHttp(
name="myrmigo",
params={"url": "https://mcp.myrmigo.com/mcp", "timeout": 10},
cache_tools_list=True,
) as myrmigo:
agent = Agent(name="Travel assistant", instructions="Help the user with tasks on their own travel bookings.", mcp_servers=[myrmigo])
result = await Runner.run(agent, "How do I check in online for my Aegean flight?")
print(result.final_output)
asyncio.run(main())From OpenAI Agents SDK: MCP, checked 2026-09-26. We haven’t run it yet.
Agents SDK, TypeScriptnot tested yet
import { Agent, hostedMcpTool, run } from '@openai/agents';
const agent = new Agent({
name: 'Travel assistant',
instructions: 'Help the user with tasks on their own travel bookings.',
tools: [hostedMcpTool({ serverLabel: 'myrmigo', serverUrl: 'https://mcp.myrmigo.com/mcp', requireApproval: 'never' })],
});
const result = await run(agent, 'My Blue Star ferry was booked on Ferryhopper. How do I change the date?');
console.log(result.finalOutput);From OpenAI Agents SDK (JS): MCP, checked 2026-09-26. We haven’t run it yet.
Responses API, Pythonnot tested yet
from openai import OpenAI
client = OpenAI() # reads OPENAI_API_KEY
resp = client.responses.create(
model="gpt-6-astra",
tools=[
{
"type": "mcp",
"server_label": "myrmigo",
"server_description": "Travel booking reference: change, cancel and refund rules, official booking sites, EU261/UK261 flight compensation checks",
"server_url": "https://mcp.myrmigo.com/mcp",
"require_approval": "never",
},
],
input="How do I check in online for my Aegean flight?",
)
print(resp.output_text) # resp.output also holds mcp_list_tools and mcp_call itemsFrom OpenAI: MCP servers in the Responses API, checked 2026-09-26. We haven’t run it yet.
- Myrmigo’s tools are read-only, so require_approval "never" is a reasonable setting. It is your choice: leave it out and your code approves each call.
LangChain and LangGraph
LangChain 1.4 has MCP built in (langchain.mcp, beta). The older langchain-mcp-adapters package was archived on 2026-09-17; its client still works in existing code. In JavaScript, @langchain/mcp-adapters is still the documented way.
Python: langchain[mcp] 1.4 or laternot tested yet
import asyncio
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter
async def main() -> None:
async with MCPAdapter("https://mcp.myrmigo.com/mcp") as adapter: # a URL: Streamable HTTP
tools = await adapter.list_tools()
agent = create_agent("claude-sonnet-5", tools)
result = await agent.ainvoke({"messages": [{"role": "user", "content": "How do I check in online for my Aegean flight?"}]})
print(result["messages"][-1].content)
asyncio.run(main())From LangChain: MCP, checked 2026-09-26. We haven’t run it yet.
Python: langchain-mcp-adapters (archived)not tested yet
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({"myrmigo": {"transport": "http", "url": "https://mcp.myrmigo.com/mcp"}})
tools = await client.get_tools() # inside an async functionFrom LangChain: MCP, checked 2026-09-26. We haven’t run it yet.
TypeScript: @langchain/mcp-adaptersnot tested yet
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
import { createAgent } from 'langchain';
const client = new MultiServerMCPClient({ myrmigo: { transport: 'http', url: 'https://mcp.myrmigo.com/mcp' } });
const tools = await client.getTools();
const agent = createAgent({ model: 'claude-sonnet-5', tools });
const result = await agent.invoke({ messages: [{ role: 'user', content: 'How do I check in online for my Aegean flight?' }] });
console.log(result.messages.at(-1)?.content);From LangChain.js: MCP, checked 2026-09-26. We haven’t run it yet.
- Agents built with create_agent run on LangGraph, so the same tools work in a LangGraph graph.
Browser agents
A browser agent can ask Myrmigo which official page to open and where the person takes over, then act in the browser. Browser Use’s MCP client starts local (stdio) servers only, so it reaches Myrmigo through the npm proxy, or through a small custom action that calls REST.
Browser Use: MCP through the npm proxynot tested yet
import asyncio
from browser_use import Agent, ChatBrowserUse, Tools
from browser_use.mcp.client import MCPClient
async def main() -> None:
tools = Tools()
myrmigo = MCPClient(server_name="myrmigo", command="npx", args=["-y", "myrmigo-mcp"])
await myrmigo.connect()
await myrmigo.register_to_tools(tools) # adds Myrmigo's tools as actions
try:
agent = Agent(
task="Check in online for my Aegean flight. I will enter my passport details myself.",
llm=ChatBrowserUse(),
tools=tools,
)
await agent.run()
finally:
await myrmigo.disconnect()
asyncio.run(main())From Browser Use: custom tools and MCPClient, checked 2026-09-26. We haven’t run it yet.
Browser Use: a custom action over RESTnot tested yet
import asyncio
import json
import urllib.request
from browser_use import ActionResult, BrowserSession, Tools
tools = Tools()
def _reference(task: str, where: str) -> dict:
req = urllib.request.Request(
"https://mcp.myrmigo.com/v1/reference",
data=json.dumps({"task": task, "where": where}).encode(),
headers={"content-type": "application/json"},
)
with urllib.request.urlopen(req, timeout=5) as r:
return json.load(r)
@tools.action("Look up how a task is done on a travel site: official page, who services the booking, what to ask the user, where the user acts")
async def myrmigo_reference(task: str, where: str, browser_session: BrowserSession) -> ActionResult:
answer = await asyncio.to_thread(_reference, task, where)
return ActionResult(extracted_content=answer["card"]) # the answer as text for the modelFrom Browser Use: custom tools and MCPClient, checked 2026-09-26. We haven’t run it yet.
Playwright MCP next to Myrmigo in an MCP hostnot tested yet
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest"
]
},
"myrmigo": {
"command": "npx",
"args": [
"-y",
"myrmigo-mcp"
]
}
}
}From Playwright MCP, checked 2026-09-26. We haven’t run it yet.
- The npm proxy needs Node.js 20 or later and no key. It removes query strings from web addresses before anything is sent.
- An answer’s envelope.allowed_domains lists the hosts the agent navigates on for the task. It is not a network allowlist: don’t pass it to Playwright MCP’s --allowed-origins, which blocks every request to other origins, including the payment form, the bank’s approval page (3-D Secure) and the CAPTCHA that the person completes. If you check where the agent goes, check the pages it opens itself, not the requests and redirects the site makes.
REST
The same answer as JSON, anonymous, no key. These helpers use only the standard library; they set a timeout, turn errors into one exception with a stable code, and handle the question Myrmigo can ask back.
TypeScript: rest-client.tstested
// Myrmigo REST from TypeScript: fetch only, no dependency (Node 18+, Deno, Bun, Workers).
// Anonymous and read-only, no key. The full answer format: https://mcp.myrmigo.com/v1/schema/route.json
// Myrmigo's tests run this file against the server (test/site-developers.test.ts); https://myrmigo.com/developers/ shows it.
/** The fields most integrations read from an answer (format myrmigo.route/1). New fields can appear: ignore unknown ones. */
export type Answer = {
schema: 'myrmigo.route/1';
match: 'exact' | 'likely' | 'question' | 'servicing_question' | 'none' | 'need_site' | 'out_of_scope' | (string & {});
coverage: 'L0' | 'L1' | 'L2' | null;
site: { id: string; name: string; domain: string } | null;
best_route: { type: string; ref: string; label: string } | null;
also_channels?: Array<{ type: string; ref: string; label: string }>;
entry_url: string | null;
ask_user_first: Array<{ name: string; prompt: string }>;
human_only: Array<{ kind: string; note: string }>;
facts: Array<{ topic: string; value: string; source_url: string; quote?: string; as_of: string }>;
question?: { ask_user: string; options: Array<{ label: string; task?: string; booked_via?: string }> };
refusal?: string;
warning?: string;
disclosure?: string; // show it to the user whenever it is present
card: string; // the same answer as text for a model; not a stable format
};
export type Query = { task: string; where?: string; booked_via?: string };
/** A REST error: `code` is stable (invalid_request, rate_limited, …), `message` is one line with the fix. */
export class MyrmigoError extends Error {
readonly status: number;
readonly code: string;
readonly retryAfter: number | undefined;
constructor(status: number, code: string, message: string, retryAfter?: number) {
super(message);
this.status = status;
this.code = code;
this.retryAfter = retryAfter;
}
}
export function myrmigo({ base = 'https://mcp.myrmigo.com', timeoutMs = 5000, fetch: f = fetch } = {}) {
async function call<T>(path: string, init?: RequestInit): Promise<T> {
const res = await f(new URL(path, base), { ...init, signal: AbortSignal.timeout(timeoutMs) });
const body: unknown = await res.json().catch(() => ({}));
if (!res.ok) {
const { error, code } = body as { error?: string; code?: string };
const wait = Number(res.headers.get('retry-after')) || undefined;
throw new MyrmigoError(res.status, code ?? 'unknown', error ?? res.statusText, wait);
}
return body as T;
}
return {
/** POST /v1/reference. `task`: an id from intents() (e.g. "ferry.change") or a short English phrase. */
reference: (q: Query) =>
call<Answer>('/v1/reference', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(q) }),
/** GET /v1/intents: the task ids. */
intents: () => call<{ intents: Array<{ id: string; object: string; action_class: string }> }>('/v1/intents').then((r) => r.intents),
};
}
/** Myrmigo asked back (match question, servicing_question or need_site): build the next query from what the user chose.
* `choice` is one of `answer.question.options`, or the site the user named when there are no options. An option with no
* booked_via and no other task ("Another site or travel agent (name it)"): ask the user which one and pass
* `{ booked_via: name }`. Without a name this sends booked_via "not sure", so Myrmigo answers instead of asking again. */
export function followUp(q: Query, choice: { label?: string; task?: string; booked_via?: string } | { where: string }): Query {
if ('where' in choice) return { ...q, where: choice.where };
const task = choice.task ?? q.task;
const booked_via = choice.booked_via || (task === q.task ? 'not sure' : q.booked_via);
return { ...q, task, ...(booked_via ? { booked_via } : {}) };
}
/** Lines to show the user, from the fields (not from `card`). */
export function summary(a: Answer): string[] {
if (a.refusal) return [a.refusal];
if (a.question) return [a.question.ask_user, ...a.question.options.map((o) => `- ${o.label}`)];
const lines: string[] = [];
if (a.disclosure) lines.push(a.disclosure);
if (a.warning) lines.push(a.warning);
if (a.site) lines.push(`Handled by ${a.site.name} (${a.site.domain})`);
if (a.best_route) lines.push(`Start at ${a.best_route.ref}`);
for (const f of a.facts) lines.push(`${f.value} (as of ${f.as_of}, ${f.source_url})`);
if (a.ask_user_first.length) lines.push(`Have ready: ${a.ask_user_first.map((i) => i.prompt).join('; ')}`);
if (a.human_only.length) lines.push(`You do yourself: ${a.human_only.map((h) => h.kind.replace(/_/g, ' ')).join(', ')}`);
return lines;
}
// Example:
// const m = myrmigo();
// let q: Query = { task: 'ferry.change', where: 'Blue Star' };
// let a = await m.reference(q);
// if (a.question) a = await m.reference(followUp(q, a.question.options[1]!)); // the user booked through Ferryhopper
// console.log(summary(a).join('\n'));Python: rest_client.pytested
"""Myrmigo REST from Python: standard library only (Python 3.9+).
Anonymous and read-only, no key. The full answer format: https://mcp.myrmigo.com/v1/schema/route.json
Myrmigo's tests run this file against the server (test/site-developers.test.ts); https://myrmigo.com/developers/ shows it.
python3 rest_client.py # https://mcp.myrmigo.com
MYRMIGO_BASE=http://localhost:8787 python3 rest_client.py
"""
from __future__ import annotations
import json
import os
import urllib.error
import urllib.request
BASE = os.environ.get("MYRMIGO_BASE", "https://mcp.myrmigo.com")
class MyrmigoError(Exception):
"""A REST error: `code` is stable (invalid_request, rate_limited, ...), the message is one line with the fix."""
def __init__(self, status: int, code: str, message: str, retry_after: int | None = None):
super().__init__(message)
self.status, self.code, self.retry_after = status, code, retry_after
def _call(path: str, body: dict | None = None, timeout: float = 5.0) -> dict:
data = json.dumps(body).encode() if body is not None else None
req = urllib.request.Request(BASE + path, data=data, headers={"content-type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=timeout) as r:
return json.load(r)
except urllib.error.HTTPError as e:
try:
err = json.load(e)
except ValueError:
err = {}
wait = e.headers.get("retry-after")
raise MyrmigoError(e.code, err.get("code", "unknown"), err.get("error", e.reason), int(wait) if wait else None) from None
def reference(task: str, where: str | None = None, booked_via: str | None = None) -> dict:
"""POST /v1/reference. `task`: an id from intents() (e.g. "ferry.change") or a short English phrase."""
q = {"task": task, "where": where, "booked_via": booked_via}
return _call("/v1/reference", {k: v for k, v in q.items() if v is not None})
def intents() -> list[dict]:
"""GET /v1/intents: the task ids."""
return _call("/v1/intents")["intents"]
def follow_up(q: dict, choice: dict) -> dict:
"""Myrmigo asked back (match question, servicing_question or need_site): the next query from what the user chose.
`choice` is one of answer["question"]["options"], or {"where": ...} with the site the user named. An option with no
booked_via and no other task ("Another site or travel agent (name it)"): ask the user which one and pass
{"booked_via": name}. Without a name this sends booked_via "not sure", so Myrmigo answers instead of asking again."""
if "where" in choice:
return {**q, "where": choice["where"]}
task = choice.get("task") or q["task"]
booked_via = choice.get("booked_via") or ("not sure" if task == q["task"] else q.get("booked_via"))
return {**q, "task": task, **({"booked_via": booked_via} if booked_via else {})}
def summary(a: dict) -> list[str]:
"""Lines to show the user, from the fields (not from `card`, which is text for a model and may change)."""
if a.get("refusal"):
return [a["refusal"]]
if a.get("question"):
return [a["question"]["ask_user"]] + ["- " + o["label"] for o in a["question"]["options"]]
lines = []
if a.get("disclosure"): # show it whenever it is present
lines.append(a["disclosure"])
if a.get("warning"):
lines.append(a["warning"])
if a.get("site"):
lines.append(f"Handled by {a['site']['name']} ({a['site']['domain']})")
if a.get("best_route"):
lines.append(f"Start at {a['best_route']['ref']}")
for f in a.get("facts", []):
lines.append(f"{f['value']} (as of {f['as_of']}, {f['source_url']})")
if a.get("ask_user_first"):
lines.append("Have ready: " + "; ".join(i["prompt"] for i in a["ask_user_first"]))
if a.get("human_only"):
lines.append("You do yourself: " + ", ".join(h["kind"].replace("_", " ") for h in a["human_only"]))
return lines
if __name__ == "__main__":
print(len(intents()), "task ids")
q = {"task": "ferry.change", "where": "Blue Star"}
a = reference(**q)
if a.get("question"): # where was it booked? say the user answers "Ferryhopper"
q = follow_up(q, next(o for o in a["question"]["options"] if o["label"] == "Ferryhopper"))
a = reference(**q)
print("\n".join(summary(a)))
try:
reference(None) # no task: a 400 that says what to send
except MyrmigoError as e:
print("error:", e.status, e.code, e)curltested
curl -s https://mcp.myrmigo.com/v1/reference \
-H 'content-type: application/json' \
-d '{"task":"ferry.change","where":"Blue Star","booked_via":"Ferryhopper"}'MCP over curl, for a quick looktested
curl -s https://mcp.myrmigo.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"check_booking_change_cancel_refund","arguments":{"task":"ferry.change","where":"Blue Star","booked_via":"Ferryhopper"}}}'The answer comes as one server-sent event. MCP clients normally initialize a session first.
- Task ids: GET https://mcp.myrmigo.com/v1/intents. Sites: GET https://mcp.myrmigo.com/v1/sites.
- Browser pages and extensions can call GET /v1/intents, /v1/sites, /v1/guides/{site}/{ref}, /v1/schema/route.json, /v1/schema/guide.json, /v1/schema/rights.json and /openapi.json from any origin (CORS, without credentials). Call POST /v1/reference and the other routes from your server.
Flight compensation check (EU261/UK261)
For a delayed, cancelled, overbooked or downgraded flight, the MCP tool check_flight_compensation and POST /v1/rights check the EU and UK air passenger rules (Regulation 261/2004 and its UK version) for that one flight: the verdict with the rule, the amount per passenger, what the airline owes now whatever the verdict, what would change the verdict, where the traveller claims (the airline first, then the national enforcement body, or the UK ADR scheme or the CAA) and the evidence to keep. The rules are versioned by flight date and every rule cites an official source with the day it was read. It is a descriptive check, not legal advice.
REST: POST /v1/rightstested
curl -s https://mcp.myrmigo.com/v1/rights \
-H 'content-type: application/json' \
-d '{"flight_date":"2026-09-26","from":"ATH","to":"PAS","carrier":"A3","event":"cancelled","notice_days":0}'MCP over curl: check_flight_compensationtested
curl -s https://mcp.myrmigo.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"check_flight_compensation","arguments":{"flight_date":"2026-09-26","from":"ATH","to":"PAS","carrier":"A3","event":"cancelled","notice_days":0}}}'- Send facts about the flight only: its scheduled date, the IATA codes of the first departure and the final destination, the airline that operated it, and what happened (with the arrival delay, the notice or the reason when known). There is no field for a name, a booking reference or an e-mail, and nothing sent is stored.
- verdict depends means a fact, a proof or a legal question is open: ask the user the questions in questions (depends_on says which), then call again.
- The traveller files any claim personally, with the airline first. Myrmigo submits nothing and names no claims company.
- Answer format myrmigo.rights/1: https://mcp.myrmigo.com/v1/schema/rights.json. 10 checks per minute and 100 per day per network (or per organisation with a key). POST /v1/rights is not open to browser pages: call it from your server.
Reading the answer
Every answer has the format myrmigo.route/1, described field by field in theJSON Schema and the OpenAPI document.
- Parse the fields, not card. card is the same answer as text for a model, and its wording changes.
- Show disclosure to the user whenever it is present: it is a conflict-of-interest line about that site.
- match says how the request matched a step guide, not whether the site was found. match none with coverage L0 or L1 is a normal reference answer.
- match question, servicing_question or need_site: ask the user question.ask_user (for need_site, which company it was), then call again with the chosen option’s task or booked_via, or with where. If the option has no booked_via (another site or travel agent), send the name the user gives as booked_via, or “not sure”.
- best_route is where to go first; entry_url is the official page where the task starts; human_only lists where the person acts themselves (payment, ID, sign-in).
- Facts carry a date and a source. Guide text is licensed CC BY-SA 4.0: credit Myrmigo. Quotes from sites belong to their owners.
- New fields and enum values can appear. Ignore the ones you don’t know.
- A flight compensation answer (myrmigo.rights/1): verdict depends means ask the user the questions, then call again; amounts come from the rules’ own table; it is not legal advice.
Errors and limits
- Every REST error is JSON: {"error": "…", "code": "…"}. error is one line with the fix; branch on code.
- On 429, wait the seconds in the Retry-After header.
- Calls with a key go to /v1/route and /v1/runs from your server. Keys are issued by Myrmigo; the reference answers need none.
- If Myrmigo can’t be reached, your agent carries on without it.
The codes: invalid_request, unauthorized, forbidden, origin_not_allowed, host_not_allowed, not_found, conflict, gone, payload_too_large, rejected, rate_limited, internal, writes_disabled, unavailable.
Payments, passport and ID details, and logins are always entered by the person, never the agent. Before anything paid or irreversible, the agent stops, shows exactly what will happen and waits for a clear yes.
Connect an appHow it worksTerms of UsePrivacy Policyllms.txt