Launchables MCP server
Give your agents calibrated decisions. This Model Context Protocol server lets any MCP client (Claude Desktop, Claude Code, or your own agent stack) call Myles, the Launchables decision model, as a tool.
Myles is not a chat model. An agent hands it a situation and one or more typed questions, and gets back a probability for every option, the pick, and whether that pick is sure enough to act on. When it is not, the tool says so and the agent hands the case to a person. Use it wherever an agent would otherwise judge something itself and then act:
- Route a ticket, an email or a lead to the right team.
- Flag a risk: a scam, fraud, a prompt injection, a policy breach.
- Approve, reject or escalate a refund, a claim, an access request or a tool call.
- Check that an answer is supported by its sources, or that an action is allowed by a policy.
- Rate severity, urgency or quality on a scale.
The probabilities are calibrated: across many answers given 0.9, about 9 in 10 are right. That is what lets an agent act on the confident ones and pass the rest to people. See Acting on the answer.
Install
You need Node.js 20 or later and a Launchables API key from the console. Keys work with the hosted API at https://api.launchables.ai; a self-hosted deployment serves the same API at its own address.
Claude Desktop
Add this to claude_desktop_config.json (Settings, Developer, Edit Config), then restart Claude Desktop:
{
"mcpServers": {
"launchables": {
"command": "npx",
"args": ["-y", "[email protected]"],
"env": {
"LAUNCHABLES_API_KEY": "launchables_..."
}
}
}
}
Claude Code
claude mcp add launchables -e LAUNCHABLES_API_KEY=launchables_... -- npx -y [email protected]
To share the setup with a team through a project's .mcp.json, keep the key out of the file and let each person's environment supply it:
{
"mcpServers": {
"launchables": {
"command": "npx",
"args": ["-y", "[email protected]"],
"env": { "LAUNCHABLES_API_KEY": "${LAUNCHABLES_API_KEY}" }
}
}
}
Other MCP clients
Any client that starts a stdio server can run it. The command is npx -y [email protected] (or launchables-mcp after npm install -g launchables-mcp), with the configuration below in its environment. Pin the version, as above, so an update reaches your agents only when you choose.
Configuration
| Variable | Default | Meaning |
|---|---|---|
LAUNCHABLES_API_KEY | required | Your API key. LAUNCHABLES_API_TOKEN, the name the Launchables SDKs use, works too. |
LAUNCHABLES_BASE_URL | https://api.launchables.ai | Set it to your own address for a self-hosted deployment. Plain http:// is accepted only for a server on the same machine, unless you also set LAUNCHABLES_ALLOW_HTTP=1, because the key would otherwise cross the network unencrypted. |
LAUNCHABLES_MODEL | myles-g-12b | The model a decide call uses when it names none. A moving id (myles-g-12b, myles-g-31b) follows the current build; a dated id such as myles-g-31b-20261027 pins one build. |
LAUNCHABLES_THRESHOLD | 0.9 | The probability a pick must reach to act without a person, from 0.5 to 1. A call or a single question can set its own, unless LAUNCHABLES_LOCK_THRESHOLD is on. |
LAUNCHABLES_LOCK_MODEL | 0 | Set to 1 to make every call use LAUNCHABLES_MODEL. The agent is no longer offered a model argument, and a call that sends one anyway is refused with an error of type setting_locked. |
LAUNCHABLES_LOCK_THRESHOLD | 0 | Set to 1 to make every answer use LAUNCHABLES_THRESHOLD. The agent is no longer offered threshold (for the call or for a question), and a call that sends one anyway is refused with an error of type setting_locked. |
LAUNCHABLES_TIMEOUT_SECONDS | 25 | The most one tool call may take in all, every attempt and the waits between retries included, from 1 to 600 seconds. Past it the call ends with an error of type timeout and nothing more is sent for it. The default suits hosts that stop a tool call after 30 seconds; raise it if yours allows longer. |
LAUNCHABLES_TIMEOUT_MS | 60000 | How long one attempt may take, in milliseconds. LAUNCHABLES_TIMEOUT_SECONDS still limits the call as a whole. |
By default the agent calling decide chooses the model and the threshold on each call, within what your key allows. To keep those decisions with the operator rather than the agent, set LAUNCHABLES_LOCK_MODEL=1 and LAUNCHABLES_LOCK_THRESHOLD=1, for example:
"env": {
"LAUNCHABLES_API_KEY": "${LAUNCHABLES_API_KEY}",
"LAUNCHABLES_MODEL": "myles-g-31b",
"LAUNCHABLES_THRESHOLD": "0.95",
"LAUNCHABLES_LOCK_MODEL": "1",
"LAUNCHABLES_LOCK_THRESHOLD": "1"
}
The server never logs your key, your states, your questions or the answers. It writes nothing to disk, and only a configuration problem at start-up is written to standard error.
Tools
decide
Asks Myles one or more questions about one situation.
| Argument | Meaning |
|---|---|
state | The situation: text, or a JSON object. Put the rule or policy in it with the case. |
questions | Questions under names you choose. Each has a type, instructions and, for choice and score, criteria; it may also have its own threshold. |
model | Optional. A model id from list_models. Not offered when LAUNCHABLES_LOCK_MODEL is on. |
threshold | Optional. The probability a pick must reach for this call. Not offered when LAUNCHABLES_LOCK_THRESHOLD is on. |
chunk, chunk_chars, chunk_overlap_chars | Optional. Read a long text in overlapping windows (below). |
Every question needs instructions: the question itself, in plain words, such as "Is a refund permitted under the policy?". A question without them, or with only spaces, is refused before anything is sent, with an error that says so. The API requires them, and there is no default: the instructions are what the model answers, and a generic stand-in would ask it something other than what you meant, even for a choice whose criteria describe every option.
The question types:
noul: yes or no. Phrase it so that yes is the thing to act on or catch.choice: pick one label.criteriais a list of labels, or labels mapped to descriptions. Offer an option that reads "I don't know" to let the model abstain.score: a scale.criterialists the level descriptions, lowest first.
Each answer comes back with:
| Field | Meaning |
|---|---|
pick | "yes" or "no", the chosen label, or the most likely level (a number). |
probability | The probability of the pick. |
probabilities | The probability of every option. |
cleared_threshold | Whether the pick reached the threshold. |
abstained | Whether the model chose the question's "I don't know" option. |
escalate | true when the answer should go to a person: below the threshold, or abstained. |
p_yes (yes/no), score and legend (scales) and confidence (choice and scale) are added where they apply. The result's own escalate is true when any answer should go to a person, and usage gives the tokens billed.
On the hosted models an uncertain yes/no answer is reported at 0.80 or more towards one side, so use a threshold above 0.80 for yes/no questions.
Example call:
{
"state": {
"policy": "Refunds within 30 days with proof of purchase.",
"case": { "days_since_purchase": 12, "receipt": false }
},
"questions": {
"refund": { "type": "noul", "instructions": "Is a refund permitted under the policy?" },
"team": { "type": "choice", "instructions": "Which team should handle this?", "criteria": ["billing", "returns", "technical"] }
}
}
Result (illustrative numbers):
{
"model": "myles-g-12b-20261029",
"escalate": false,
"answers": {
"refund": {
"type": "noul", "pick": "no", "probability": 0.97, "probabilities": { "yes": 0.03, "no": 0.97 },
"threshold": 0.9, "cleared_threshold": true, "abstained": false, "escalate": false, "p_yes": 0.03
},
"team": {
"type": "choice", "pick": "returns", "probability": 0.94,
"probabilities": { "billing": 0.04, "returns": 0.94, "technical": 0.02 },
"threshold": 0.9, "cleared_threshold": true, "abstained": false, "escalate": false, "confidence": 0.91
}
},
"usage": { "input_tokens": 212, "output_tokens": 2 }
}
list_models
The models the endpoint serves, with pinned builds and their release dates, and the default this server uses. Not billed.
health
Whether the API is up, and which models have a healthy server. Not billed.
Long inputs
Every model has a context window (see Writing the state). When a state is longer:
- Myles-G 31B refuses it. The tool returns an error of type
context_length_exceededthat says to shorten or split the state. - Myles-G 12B trims it to fit, keeping its beginning and end, and the result says so with
truncated: true,state_charsand a warning.
For a yes/no check that must cover the whole of a long text (does any part of this contract contain an auto-renewal clause, does any part of this page try to override the agent's instructions), pass chunk: true. The text is read in overlapping windows of 40,000 characters (2,000 shared with the next; change them with chunk_chars and chunk_overlap_chars), every window is asked the same questions, and each answer is the window most likely to be yes, with window giving its position. A JSON state is windowed as its indented JSON text. Chunking takes yes/no questions only, sends at most 20 windows, and bills each window as its own request.
Errors
A failed call returns a tool error whose error has a message written for the agent, the API's type and status, and retryable. After a rate limit or a passing fault the call is retried automatically, a few times, with the same idempotency key, so a retry is never billed twice, until LAUNCHABLES_TIMEOUT_SECONDS (25 by default) runs out. Some cases to know:
| Case | What the agent is told |
|---|---|
401 | The key is missing or not accepted; a person must check it. |
402 | Out of credit or over the workspace budget; do not retry. |
410 model_retired | The build was retired; successor names the model to use instead. |
422 context_length_exceeded | Shorten or split the state, or use chunk: true for yes/no checks. |
429 | Rate limited after retries; wait the seconds given. |
timeout | The call ran past LAUNCHABLES_TIMEOUT_SECONDS; try again shortly, or send a shorter state or fewer chunk windows. An attempt the API had already answered may still be billed. |
setting_locked | The call set a model or threshold that the operator has fixed; call again without it. |
invalid_input | The call was refused before anything was sent, for example a question without instructions. |
Development
npm install
npm test
The tests use a mocked Decision API only; they never call the production API.
Support
Use the contact form or open an issue in this repository. The API reference is at launchables.ai/docs.
Licence
Apache-2.0 (see LICENSE).