ExpLint API documentation

ExpLint lints A/B test specs against the rules your team writes, over two surfaces that do the same work. The MCP server puts the linter inside your assistant, and the REST API hands the same calls to a script or an agent that sends HTTP.

The MCP server exposes four tools: one that returns this documentation as markdown, one for projects, one for the rules inside them, and one that lints a spec against those rules.

Install#

The server is a remote MCP endpoint at https://explint.com/mcp. Claude, ChatGPT, Grok Bot, Cursor, and Gemini all connect to it.

Sign in#

A client that handles OAuth needs nothing beyond the URL. The first call opens a browser window where you sign in and choose the organization the connection works in, and every call after that acts inside the organization you picked.

An assistant that cannot run that flow sends an API key instead, as the header Authorization: Bearer <api key>. You create keys on the MCP page of the ExpLint workspace, and revoking one there stops it working on the next call.

Tools#

Two of the four tools name what to do with an operation string and carry that operation's arguments in the field named after it, so a call with operation: "create" fills create and leaves the rest out. The project tool answers create, update, archive, restore, remove, and list, where remove archives the project because projects are never deleted, and the rule tool answers create, update, remove, and list. explint__lint takes its arguments directly, and explint__docs takes no arguments and answers with the full documentation as markdown. No call names an organization, because the credential decides which one every call works in.

Projects are named by name on explint__project and by projectSlug on the other two, matched inside the organization ignoring case, so any casing of the name or the slug reaches the same project.

explint__docs#

Return the full documentation of how to use the MCP server as one markdown document, covering how to connect and sign in, every tool with its arguments and answer shapes, how listings page, and what each refusal means. The tool takes no arguments, reads and writes nothing in the organization, and never spends a lint request, so an assistant can call it at the start of a session and again whenever the shape of another tool needs checking.

explint__docs

{}

explint__project#

Create, rename, archive, restore, and list the organization's projects. Archiving keeps the project, its rules, and its lint history in place and only takes the project out of the working list, so the reporting that already credits it keeps its name, and restoring brings it back.

ArgumentWhat it carries
operationRequired. One of create, update, archive, restore, remove, or list.
createname for the new project.
updatename for the project to rename and newName for what to rename it to, which regenerates its slug with it.
archivename for the project to archive.
restorename for the archived project to restore.
removename for the project to archive, kept for older callers because projects are never deleted.
listslug to keep only projects whose slug holds that text, includeArchived to bring archived projects back into the listing, limit for how many rows one answer carries, and cursor to continue a listing.
explint__project

{
  "operation": "create",
  "create": { "name": "Checkout cross-sell" }
}

explint__rule#

Create, change, remove, and list the rules inside a project. A rule carries a key such as hypothesis/names-metric, a title, an instruction written in plain English that the linter judges the spec against, a severity of error or warning, and a switch for whether it is on. The category before the slash is how the workspace groups a project's rules, and a rule is found by its key matched ignoring case.

ArgumentWhat it carries
operationRequired. One of create, update, remove, or list.
createprojectSlug, ruleKey, ruleTitle, and ruleInstruction, plus optional severity (error or warning, error by default) and enabled (on by default).
updateprojectSlug and ruleKey to name the rule, plus any of ruleTitle, newRuleKey, ruleInstruction, severity, and enabled to change.
removeprojectSlug and ruleKey to name the rule to remove.
listprojectSlug, plus optional ruleKey to keep only rules whose key holds that text, limit, and cursor.
explint__rule

{
  "operation": "create",
  "create": {
    "projectSlug": "checkout-cross-sell",
    "ruleKey": "hypothesis/names-metric",
    "ruleTitle": "Names the metric",
    "ruleInstruction":
      "The hypothesis names the metric it expects to move."
  }
}

explint__lint#

Lint a spec against every rule the project has switched on.

ArgumentWhat it carries
projectSlugRequired. The project to lint against, by name or slug matched ignoring case.
contentThe spec itself as markdown, HTML, or plain text, judged against the project's rules. An image embedded in it as base64 is dropped before it is judged, and content beyond the acceptable size comes back as an error.

A lint, end to end#

One lint through every surface: the explint__lint tool call beside the same request over REST, written for curl, JavaScript, and Python.

Every rule lands in exactly one of errors, warnings, or passed, by the severity its rule carries, and each list comes back sorted by key. An entry carries the rule's title, key, description, and probability, the chance the model gave the content of satisfying the rule, together with the rule's bad_example and good_example where the rule carries them, each a short excerpt showing what a break looks like and what passing looks like, so an assistant can act on a break without a second call. A rule passes at a probability of 0.8 or more. quality_score is the share of the rules that passed, rounded to three decimals.

REST API#

Every tool above is also a REST call, so a script or an agent that sends HTTP can do the same work. The API lives at https://explint.com/api and takes an API key as the header Authorization: Bearer <api key>, created on the MCP page of the ExpLint workspace. The key decides which organization every call works in, so no call names one.

Nine endpoints cover the work the three tools do:

A project is named in the path by name or slug, matched inside the organization ignoring case the way the tools match it. A rule is named by its key, and a key may hold slashes, so percent-encode it on the way in: hypothesis%2Fnames-metric and hypothesis/names-metric both reach the same rule.

Listings page through their rows the way the tools do: limit carries from 1 to 100 rows and 25 when it is left out, slug and ruleKey narrow a listing to the rows holding that text, and the nextCursor an answer returns is what the next call passes as cursor until it comes back null.

A lint takes the spec as content and answers the same shape explint__lint returns. An image embedded in the content as base64 is dropped before it is judged, content beyond the acceptable size comes back as an error, and a lint no model answered comes back as the linter being unable to answer.

A refusal answers {"error": "<message>"} under a status that says what kind it is:

StatusWhat it answers
400A request to fix.
401A missing or invalid API key.
402A balance spent on linting.
403The Default project refusing removal.
404No such endpoint, project, or rule.
405A path called with the wrong method.
409A project name or rule key already taken.
502A lint the linter could not answer.

The whole surface is published as an OpenAPI document at https://explint.com/openapi.json, which is how an agent learns every path, argument, and answer in one fetch.

Also served as markdown, llms.txt, and the ExpLint OpenAPI document in YAML.