MCP Config Validator

Paste an mcpServers config to validate it. Checks the transport shape, catches common mistakes and flags hard-coded secrets. Free, runs in your browser.

Advertisement

Lint an mcpServers config before your client silently ignores it

MCP clients are unhelpfully quiet about broken configuration. A missing comma, a server with neither a command nor a url, a httpUrl key where url was meant — and the server simply does not appear. No error, no toast, no log entry you would think to look for. You restart the client, the tool list is unchanged, and you start suspecting the server itself.

This validator turns that silence into a list. Paste your config, and it parses the JSON, checks the structure a client actually requires, classifies each server's transport, and scans the environment variables and headers for credentials you probably did not mean to commit. Results appear live as you type, split into errors that will stop the config working and warnings that will not. It runs entirely in your browser — nothing is uploaded, which is the only responsible way to lint a file that by nature contains tokens.

Every check it performs

The checks are worth listing precisely, because knowing what a linter does not look at is as useful as knowing what it does.

CheckSeverityFires when
JSON parsesErrorThe text is not valid JSON. Reports the parser's message plus a line hint.
Root is an objectErrorThe top level is an array, a scalar, or null.
Servers key presentErrorNeither mcpServers nor servers exists at the root.
Servers value is an objectErrorThe servers key holds an array or a scalar instead of a name-to-config map.
Servers map non-emptyWarningThe object exists but defines nothing.
Each server is an objectErrorA server name maps to a string, array or null.
Exactly one transportErrorA server has neither command nor url, or has both.
Misnamed URL keyErrorNo url, but one of httpUrl, serverUrl, endpoint, uri or href is present. Names the key and the fix.
command is a non-empty stringErrorThe key exists but holds an empty string or a non-string.
args is an arrayErrorargs is present but is not an array.
args holds only stringsWarningAn array element is a number, boolean or object.
env / headers are objectsErrorEither is present but is an array, scalar or null.
url is a non-empty stringErrorThe key exists but is empty or not a string.
url is absolute http(s)WarningIt does not begin with http:// or https://.
Plain HTTP off-localhostWarninghttp:// to anything other than localhost or 127.0.0.1.
Recognised remote transportWarningA type or transport value that is not http, sse, streamable-http or streamableHttp.
Hard-coded secretsWarningSee the section below.

A config is reported as valid when there are zero errors. Warnings alone give you a "Valid (with warnings)" badge — they are things worth fixing, not things that will stop the client loading the file.

Both keys accepted, deliberately

The validator accepts mcpServers (Claude Code, Claude Desktop, Cursor) or servers (VS Code), checking for mcpServers first. Everything downstream is identical, and findings are labelled with whichever key you actually used, so the field path in a message reads servers.my-server.args or mcpServers.my-server.args to match your file.

It does not, however, tell you that you used the wrong one for your client. A file with servers validates cleanly even if you are about to paste it into Claude. The structural check is client-agnostic; picking the right key for the right client is a step earlier, and the MCP server config generator emits the correct dialect for each.

The transport check, which catches most real failures

An MCP server is either local, launched as a process and spoken to over stdio, or remote, reached over HTTP. In config terms that means command or url — exactly one. The validator treats both violations as errors:

  • Neither. The client has no idea how to reach the server, so it skips it. This is what a half-finished entry looks like, and it is completely silent in most clients.
  • Both. Usually the residue of converting a local server to a hosted one and leaving the old command behind. Which one wins is client-dependent, so it may work on your machine and not a colleague's.

The misnamed-key check is the same failure with a friendlier cause. If there is no command and no url but there is an endpoint or an httpUrl, the tool assumes you meant a remote server and tells you to rename the key rather than just reporting an absence. Remote MCP servers use url.

Secret scanning

The scanner walks every string value inside each server's env and headers objects and flags two different things.

Values that look like real credentials. These are matched against a fixed set of patterns:

Pattern nameRecognises
OpenAI / Anthropic style keyAn sk- prefix followed by 16 or more identifier characters
GitHub tokenghp_, gho_, ghu_, ghs_ or ghr_ plus 20 or more alphanumerics
AWS access key idAKIA followed by 16 uppercase alphanumerics
Google API keyAIza followed by 30 or more identifier characters
Slack tokenxoxb-, xoxa-, xoxp-, xoxr- or xoxs- plus 10 or more characters
Bearer tokenThe word Bearer followed by 16 or more token characters
JWTAn eyJ-prefixed three-segment dotted token
Long high-entropy stringA whole value of 32 or more base64-style characters

Key names that suggest a credential. Separately, the name is matched against terms including token, secret, api_key, apikey, password, auth, authorization, access_key, private_key, client_secret, bearer, credential and session_key. If the name looks sensitive and the value is a literal, you get a warning even when the value matches none of the patterns above — an internal token with no recognisable prefix is still a token.

Both checks skip anything that is obviously a placeholder, so the tool stays quiet about the things it should. Recognised as placeholders: an empty value, shell-style indirection such as ${API_KEY} or $API_KEY, Windows-style %API_KEY%, angle-bracket stand-ins, plain booleans, null, bare numbers, and any value containing words like your, example, placeholder, changeme, here, todo, replace or a run of x's. Every warning includes the suggested rewrite in ${VARIABLE} form with the name upper-cased and non-alphanumerics turned into underscores.

Reading the output

Findings are grouped with errors first, each showing a field path such as mcpServers.remote-docs.url, an approximate line number, and a message that names the fix rather than restating the rule. The Copy report button produces a plain-text summary — a status line with the server count or the error and warning totals, then one line per finding in [SEVERITY] field (line N): message form. That format exists to be pasted into a ticket or a message to whoever owns the config.

The Load example button fills the box with a two-server config that deliberately contains both an sk- style key in env and a GitHub token in an Authorization header, so you can see the secret scanner fire without pasting anything of your own.

What it deliberately does not do

  • It does not connect to anything. A clean report means the file is well-formed, not that the server runs. The command may not exist, the package may not install, the URL may 404.
  • It only reads JSON. Codex CLI's config.toml will fail at the parse step. The error message says so explicitly rather than leaving you guessing.
  • Comments are a parse error. Validation uses a strict JSON parser, so a VS Code mcp.json containing // comments — which the editor itself tolerates — will be reported as invalid. Strip the comments before pasting.
  • Line numbers are approximate. They are found by locating the first occurrence of the quoted key in the raw text, so with a key repeated across several servers the number may point at the first one rather than the offending one. Treat it as a hint, and rely on the field path for precision.
  • Client-specific keys are not validated. Fields outside the ones listed above are ignored rather than flagged, so a client extension will not produce a false error — and a typo in one will not produce a true one.
  • The type value is only checked on remote servers. A type alongside a command is not examined.
  • Nothing is checked for security beyond hard-coded secrets. Whether a server should have the access it has is a separate review.

A debugging order that works

  • Paste the file here and clear every error. Structural problems are the cause of most silent failures.
  • Confirm the top-level key matches the client you are targeting — servers for VS Code, mcpServers for the others.
  • Fully restart the client. Most read the config once at startup, and an edit made while running does nothing.
  • For a stdio server, run the exact command and args in a terminal yourself. Clients spawn processes without your interactive shell's PATH, so a command that works for you may not be found by the client; an absolute path settles it.
  • For a remote server, request the url with the same headers and check the status code before blaming the client.
  • Only then work through the warnings — particularly the secret ones, before the file reaches a repository.

Reading a JSON parse error

When the parse fails, the tool reports the parser's own message together with a line hint derived from the character position in that message. The messages are terse but they are predictable, and a handful of causes account for nearly all of them.

What you seeWhat it usually means
Unexpected token at a position mid-fileA missing or extra comma, most often after the last entry in an object.
Unexpected end of JSON inputAn unclosed brace — usually the outermost one, after pasting an inner block on its own.
Unexpected token in a comment line// or /* */ in the file. Strict JSON has no comments.
Unexpected token near a quotation markSmart quotes from a document or chat client instead of straight ASCII quotes.
Bad escape in a stringA Windows path with single backslashes. Each one must be doubled inside a JSON string.
An error on line 1 of a file that looks fineTOML pasted into a JSON validator — the message says so explicitly.

Because the parse is all-or-nothing, a single syntax error suppresses every structural and secret finding in the file. Fix the JSON first, then re-read the report: the second pass is usually where the real problems appear.

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results.
MCP Config Validator - Lint mcpServers | InventiveHQ