OpenLint MCP
OpenLint MCP is a local, read-only MCP server for linting API documents and inspecting OpenLint rulesets and rules.
Lint OpenAPI (2.0/Swagger, 3.x), AsyncAPI, and Arazzo documents using a configured/default or inline ruleset; returns recognized formats, severity counts, grouped diagnostics, truncation status, and notes.
List configured rulesets, including source, default status, formats, and enabled rule count.
Validate YAML/JSON rulesets without running code, reporting errors and warnings such as inline-ruleset restrictions.
List a ruleset’s rules, filter by format, include filename-based override effects, and optionally show only enabled rules.
Explain a specific rule, including description, message,
givenpaths,thenfunctions, severity, formats, documentation URL, and free-formextensionssuch as agent guidance.Configure rulesets via CLI options or
OPENLINT_RULESET; use built-inoas,asyncapi, andarazzorulesets when none is configured.Support custom functions in configured rulesets, while restricting untrusted inline rulesets.
Do not follow external
$refs by default; report them asinvalid-ref, with optional--allow-external-refssupport and security caveats.Keep all tools read-only, with no code execution or task support.
Provides linting for Swagger/OpenAPI documents, including OpenAPI 2.0 (Swagger) and OpenAPI 3.x, with diagnostics, rule listings, and rule explanations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OpenLint MCP validate my .openlint.yaml ruleset and flag any issues"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openlint-mcp
An MCP server for OpenLint. It lets AI tools such as Claude, Codex and OpenCode lint OpenAPI, AsyncAPI and Arazzo documents, look up rules, and check OpenLint rulesets.
The server runs locally over stdio and builds only on the published @openlint/* npm packages. Design and milestones: docs/v1-plan.md.
Not on npm yet. Releases are published on GitHub until the project moves to the
openlintorganization; it will then be published to npm as@openlint/openlint-mcp.
Tools
All tools are read-only.
Tool | What it does | Status |
| Lists the rulesets the server is configured with | Available |
| Checks a YAML or JSON ruleset without running any code, and warns about anything | Available |
| Lints an OpenAPI, AsyncAPI or Arazzo document | Available |
| Lists a ruleset's rules, optionally for one format (such as | Available |
| Explains one rule, including | Available |
Related MCP server: Spotlight MCP
Install
Requires Node.js ^22.22.1 || >=24.
From a release (recommended)
Each GitHub release includes the built package as openlint-mcp.tgz. Install it globally:
curl -LO https://github.com/miqui/openlint-mcp/releases/latest/download/openlint-mcp.tgz
npm install -g ./openlint-mcp.tgz
openlint-mcp --versionThis installs the
openlint-mcpcommand for your current Node.js. With asdf, runasdf reshim nodejsafterwards.For a specific version, download
releases/download/v<version>/openlint-mcp.tgzinstead ofreleases/latest/download/…. To update, install a newer release the same way.npm 12 may warn that it skipped install scripts for
@openlint/openlint-mcpandfsevents. The package doesn't need them.Why not
npx github:miqui/openlint-mcp? npm 12 refuses git and URL installs by default (itsallow-gitandallow-remotesettings), and a git install has to build the package first. A downloaded tarball installs anywhere.
From source
git clone https://github.com/miqui/openlint-mcp.git
cd openlint-mcp
npm ci
npm run build
npm run smoke # optional: starts the built server over stdio and calls its toolsThen use node /abs/path/to/openlint-mcp/dist/index.js wherever the examples below say openlint-mcp. Run pwd in the clone to get the absolute path.
Configure rulesets
Option | Meaning |
| The default ruleset: a YAML, JSON or JS ruleset file |
| An extra named ruleset. Repeat the option to add more. |
| The default ruleset, when there is no unnamed |
| Let |
Which one is the default: an unnamed
--ruleset, thenOPENLINT_RULESET, then the first named ruleset.Filenames that contain
=:--ruleset team=prod.yamlmeans a ruleset namedteam, loaded fromprod.yaml. To load a file calledteam=prod.yaml, start the path with./or/, as in--ruleset ./team=prod.yaml.No ruleset configured: the server uses the
oas,asyncapiandarazzorulesets from@openlint/openlint-rulesets(recommended rules).Use absolute paths. AI tools usually start MCP servers from a different working directory than your project, so relative paths may not resolve.
Custom functions are supported in configured rulesets (
functions,functionsDir, and JS rulesets).Errors at startup: if a ruleset fails to load, the server prints the error to stderr and exits. Your AI tool will show the server as failed; its MCP logs have the message.
Rulesets that an AI tool passes inline in a tool call are untrusted, so they are restricted:
no custom functions
no
overridesJSONPath (
given,then.field, aliases) only as plain paths, without filter or script expressions (nothing with()extendsonly names a configured ruleset,oas,asyncapi,arazzo, or one of the aliasesspectral:oas,spectral:asyncapi,spectral:arazzo,openlint:openapi,openlint:asyncapiandopenlint:arazzoformatsonly names formats exported by@openlint/openlint-formats
validate_ruleset explains what was refused.
Linting documents
lint_document takes the document as text in content. Optional inputs:
filename, such asopenapi.json, without directories or#,?and%. It is never read from disk. A.jsonname selects the JSON parser (otherwise YAML), and the ruleset'soverridesmatch it as if the document sat next to the ruleset file.ruleset: a name fromlist_rulesets(oroas,asyncapi,arazzo), or an inline YAML/JSON ruleset.severity(error,warn,infoorhint; defaulthint): leaves out less severe diagnostics.limit(default 50), andgroupBy(code, the default, ornone).
It returns:
the
formatsthe ruleset recognized (empty when none)countsper severity, which always cover every resultthe
diagnostics, most severe first, grouped by rule code unlessgroupByisnonetruncated, and anynotes
External $refs (to other files or URLs) aren't followed by default. They're reported as invalid-ref, with a note. --allow-external-refs turns them on; each HTTP request then has a 10-second timeout.
Warning: with
--allow-external-refs, a document from your AI tool can make the server read any local file it has access to, and fetch any URL. Relative refs resolve against the ruleset file's directory (or the working directory). Only use it when you trust the documents.
Looking up rules
list_ruleslists a ruleset's rules, sorted by name: severity, whether it's enabled and recommended, its formats and description.formatkeeps the rules for one kind of document. It accepts names likeoas3.1,OpenAPI 3.1,swagger(OpenAPI 2.0),asyncapi3orarazzo1.0. A version includes rules for its family:oas3.1includes rules for OpenAPI 3.x, andoas3includes rules for every OpenAPI 3 version.enabledOnly(defaulttrue) lists only the ruleslint_documentruns.filename(as forlint_document) includes what the ruleset'soverrideschange for a document of that name, such as rules added for*.jsonfiles.
explain_ruleexplains one rule: its description, message,givenpaths,then(function, field and small function options), severity, formats, documentation link andextensions.
Guidance for agents in your ruleset: core accepts a free-form extensions object on each rule, and explain_rule returns it as written. The convention for agent guidance is extensions.prompt:
rules:
operation-summary:
description: Every operation needs a summary.
given: $.paths[*][*]
then: { field: summary, function: truthy }
extensions:
prompt: Write a short summary in sentence case, under 60 characters, without a trailing period.Use with AI tools
The examples run the openlint-mcp command from a release install. Replace /abs/path/to/.openlint.yaml with your ruleset. The --ruleset … part is optional; without it, the server uses the default rulesets above. If a tool can't find openlint-mcp (desktop apps often don't see your shell's PATH), use the absolute paths shown for Claude Desktop.
Claude Code
Add the server with the claude CLI. Everything after -- is the server's own command line:
claude mcp add openlint -- openlint-mcp --ruleset /abs/path/to/.openlint.yamlChoose where the setting is stored with --scope:
local(default): only you, only this project.project: everyone working on the project. It is written to.mcp.jsonin the project root, for committing. Claude Code asks each person to approve the server the first time.user: only you, in all your projects.
A project-scoped .mcp.json looks like this:
{
"mcpServers": {
"openlint": {
"type": "stdio",
"command": "openlint-mcp",
"args": ["--ruleset", "/abs/path/to/.openlint.yaml"],
"env": {}
}
}
}The paths in a committed .mcp.json must work on every teammate's machine. If your checkouts live in different places, have each person run claude mcp add with the default local scope instead.
To set the ruleset through the environment instead, use -e OPENLINT_RULESET=/abs/path/to/.openlint.yaml before --.
Check it's connected: run claude mcp list, or /mcp inside a Claude Code session.
Docs: Claude Code MCP.
Claude Desktop
Open Settings → Developer → Edit Config. That opens claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Desktop apps often don't see the PATH from your shell, especially with version managers like nvm or asdf, so give absolute paths to Node.js and to the server. Print them with:
node -p process.execPath # Node.js
echo "$(npm root -g)/@openlint/openlint-mcp/dist/index.js" # the server, from a release installThen add the server:
{
"mcpServers": {
"openlint": {
"command": "/abs/path/to/node",
"args": ["/abs/path/to/@openlint/openlint-mcp/dist/index.js", "--ruleset", "/abs/path/to/.openlint.yaml"]
}
}
}From source, the server is
/abs/path/to/openlint-mcp/dist/index.jsin your clone.On Windows, escape backslashes in JSON paths:
"C:\\Users\\you\\AppData\\Roaming\\npm\\node_modules\\@openlint\\openlint-mcp\\dist\\index.js".Restart: quit Claude Desktop completely and start it again.
If it doesn't connect, check the logs. On macOS they're at
~/Library/Logs/Claude/mcp-server-openlint.log.
Docs: Connect to local MCP servers.
Codex
Add the server with the codex CLI. The CLI, the IDE extension and the ChatGPT desktop app share this configuration:
codex mcp add openlint -- openlint-mcp --ruleset /abs/path/to/.openlint.yamlThis writes to ~/.codex/config.toml. You can also edit that file directly:
[mcp_servers.openlint]
command = "openlint-mcp"
args = ["--ruleset", "/abs/path/to/.openlint.yaml"]
# Optional, instead of --ruleset:
# [mcp_servers.openlint.env]
# OPENLINT_RULESET = "/abs/path/to/.openlint.yaml"Environment variable from the CLI:
codex mcp add openlint --env OPENLINT_RULESET=/abs/path/to/.openlint.yaml -- openlint-mcp.Per project: a
.codex/config.tomlin a trusted project can hold the same table.
Check it's connected: run codex mcp list, or /mcp inside the Codex TUI.
Docs: Codex MCP.
OpenCode
Add the server with the opencode CLI. Without --global, it goes into the project's configuration:
opencode mcp add openlint -- openlint-mcp --ruleset /abs/path/to/.openlint.yamlIn some older versions, opencode mcp add doesn't take a name and command, and asks for them instead. Enter openlint as the name, choose a local server, and give the same command.
Or edit opencode.json (or opencode.jsonc) in the project root, or ~/.config/opencode/opencode.json for all projects. The format in OpenCode's current docs (V2) puts servers under mcp.servers:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"servers": {
"openlint": {
"type": "local",
"command": ["openlint-mcp", "--ruleset", "/abs/path/to/.openlint.yaml"],
// Optional, instead of --ruleset:
// "environment": { "OPENLINT_RULESET": "/abs/path/to/.openlint.yaml" }
},
},
},
}Older versions (V1) put servers directly under mcp, and use enabled:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"openlint": {
"type": "local",
"command": ["openlint-mcp", "--ruleset", "/abs/path/to/.openlint.yaml"],
"enabled": true,
},
},
}If you're not sure which format your version uses, opencode mcp add writes the right one.
Check it's connected: run opencode mcp list, or /mcps inside OpenCode.
Docs: OpenCode MCP servers.
Try it
Once the server is connected, ask your AI tool things like:
"Which OpenLint rulesets are configured?"
"Lint
openapi.yamlwith OpenLint and fix the errors.""Which OpenLint rules apply to OpenAPI 3.1, and what does
operation-tagscheck?""Write an OpenLint ruleset that requires
info.contactin OpenAPI 3.1 documents, and validate it withvalidate_ruleset."
Development
npm ci
npm run lint # Prettier, ESLint and type-check
npm test # Vitest
npm run build # TypeScript 7 → dist/
npm run smoke # the built server over stdioCommit messages and PR titles follow conventional commits, as in OpenLint's CONTRIBUTING.md.
License
Available Tools
5 toolsexplain_ruleExplain ruleARead-only
Explains one rule: what it checks (description, message, given, then), its severity and formats, a documentation link, and extensions, free-form data the ruleset attached to the rule, such as guidance for fixing it (extensions.prompt).
Inputs: rule (required), ruleset, filename. Returns: name, then, given, enabled, +7 more
lint_documentLint documentARead-only
Lints an OpenAPI (2.0/Swagger, 3.x), AsyncAPI or Arazzo document with an OpenLint ruleset. Pass the document text as content. counts cover every result, whatever severity and limit are; diagnostics are sorted most severe first, then by code, and grouped by code unless groupBy is "none". formats lists the formats the ruleset recognized; empty means none. External $refs to files and URLs are not followed; they are reported as invalid-ref.
Inputs: content (required), limit, groupBy, ruleset, +2 more. Returns: notes, counts, formats, truncated, +1 more
list_rulesList rulesARead-only
Lists a ruleset's rules, sorted by name. format keeps the rules that apply to documents of that format: oas3.1 includes rules for OpenAPI 3.1 and 3.x; oas3 includes rules for every OpenAPI 3 version. Rules that overrides in the ruleset add or turn off for a document are included when filename matches them. Use explain_rule for one rule in detail.
Inputs: format, ruleset, filename, enabledOnly. Returns: rules
list_rulesetsList rulesetsARead-only
Lists the rulesets this server is configured with. Pass a name as the ruleset argument of other tools; when ruleset is omitted, the default ruleset is used. ruleCount counts the rules that are enabled.
Inputs: no named parameters. Returns: rulesets
validate_rulesetValidate rulesetARead-only
Checks a YAML or JSON OpenLint ruleset without running any code. valid means the ruleset is well formed. warnings list what lint_document would refuse when the ruleset is passed inline (custom functions, or extending files, URLs or packages); such rulesets can still be configured on the server with --ruleset. JavaScript rulesets are not supported.
Inputs: content (required). Returns: valid, errors, warnings
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 5 tools
Each tool has a clearly distinct role: validating rulesets, listing rulesets, linting documents, listing rules, and explaining a single rule. The boundaries between listing versus explaining rules and validating versus linting are explicit in the descriptions. No pair of tools appears interchangeable.
All tools follow a consistent snake_case verb_noun pattern: validate_ruleset, list_rulesets, lint_document, list_rules, explain_rule. The convention is predictable and easy to scan.
Five tools is well scoped for a focused OpenLint server covering ruleset validation, ruleset discovery, linting, rule listing, and rule explanation. Each tool earns its place without obvious redundancy.
The surface covers the core linting workflow from ruleset validation through document linting and rule inspection. Minor gaps remain, such as no direct tool for resolving or inspecting external $refs and no explicit server configuration/default-ruleset inspection beyond list_rulesets.
Maintenance
Related MCP Connectors
Deterministic validation for AI-generated artifacts: JSON Schema, OpenAPI response, SQL syntax.
Scores how well AI agents will use your API, 0-100, from its OpenAPI spec. Free and read-only.
Checks AI-written code against your rules as it is written, and keeps a record of what it found.
Detect breaking changes, generate changelogs, diff, and validate OpenAPI specs.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to browse, read, compare, and validate OpenAPI contracts for providers and consumers.1MIT
- AlicenseAqualityBmaintenanceEnables AI agents to lint API artifacts (OpenAPI, AsyncAPI, Arazzo) and manage rulesets conversationally via the Model Context Protocol.4Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with OpenAPI documents for analysis, validation, and management through structured interfaces.376 npm3ISC
- AlicenseAqualityDmaintenanceEnables AI clients to validate OpenAPI specs, compare versions, detect breaking changes, and generate changelogs.4MIT