Skip to content
Salyro
Tool

mcp.json validator

Check an MCP configuration for Claude Code or Claude Desktop — missing fields, bad types and names, unsafe URLs, duplicates, and credentials in the clear.

What it does

Paste a .mcp.json, a ~/.claude.json or a claude_desktop_config.json, and say which client it is for. Each finding names its line and its path, such as $.mcpServers.search.url, and what to change.

This is about your MCP client's configuration. It is not Salyro's MCP Expose, where a gateway is the server, or MCP Connect, where a gateway is the client.

What it checks

From Claude Code's MCP page:

  • A url with no type. Claude Code reads an entry with no type as a stdio server, and skips this one. Add "type": "http", "sse" or "ws".
  • A type the page does not name. The page names stdio, http (or streamable-http), sse and ws.
  • Server names: a name Claude Code's commands reject (anything but letters, numbers, hyphens and underscores), and the names of Claude Code's own built-in servers, such as computer-use, which it skips.
  • Hidden whitespace at either end of command, url, an argument, or a value or name in env or headers. It is often a pasted newline, and Claude Code uses the value as written.
  • SSE, which the page calls deprecated.

And from what any client needs:

  • a stdio server with no command, a remote server with no url, and fields that belong to the other kind;
  • values that are not strings, such as a port number in args;
  • a server name given twice. JSON keeps only the last one, silently;
  • the address: a URL that is not a URL (named, never repeated, since it may hold a password), a scheme that does not fit the transport, http to anything but your own machine, and a user name, password or key inside the URL, however the URL writes it.

Credentials

A credential written in the clear, in env, in headers, in an argument or in the URL, is an error. It is recognised the way Salyro's own log redactor recognises one, and by names such as API_KEY, TOKEN or Authorization. A ${VARIABLE} reference is fine. Under a credential's name, a ${VARIABLE:-default} with a default is not: the default is used whenever the variable is unset, so it is written in the clear.

A credential is also found by where it sits: the value after --api-key, a --token= or -e API_KEY= argument, the password in curl -u user:password, a --header "X-Api-Key: …", a URL's user information or its api_key= parameter, anything under a secret name (a number, a list, an object), or a header inside headersHelper. It is judged as the client will read it, with JSON escapes decoded.

For Claude Code, the tool then shows the same text with every credential moved to a ${VARIABLE}, and lists the variables to set. No page read here says Claude Desktop expands a ${VARIABLE}, so for it the tool does not suggest one. A link never holds a credential. It holds only the file's structure: server names, transports, commands, flags, package names and each address's scheme and host, with every value of env and headers as a ${VARIABLE} and every other value a placeholder. A flag keeps its name, never its value, and a name with a slash is kept only as a scoped package or an image with its registry's host. So a shared link shows the findings about structure, such as a missing type, but not those about a value it leaves out. Text that is not JSON is not put in a link. "Share settings only" leaves the file out.

What it does not know

  • A credential nothing marks. One with no known shape and no credential's name, such as a random segment in an address's path, is not recognised on the page. A link never holds it, because a link keeps only an address's scheme and host.
  • Cursor, VS Code and Windsurf. Their pages could not be read when this tool was built, so their rules are unknown.
  • Whether a server works: the tool reads the file. It does not start or reach any server.

Sources

The rules quote Claude Code's MCP page on code.claude.com, recorded as Reference Data with the date it was read.

Where the numbers come from

  • Facts about models and providers that are not in that catalogue carry their own source and the date they were checked, and are shown as unknown where no reliable source exists.