Skip to content

MCP Config & Schema Validator

Paste an MCP client config to see why a server won't load, or a server's tool definitions to check them against the specification: wrong keys, arguments in the command, invalid JSON Schema, bad tool names and header annotations. Each problem has its line and column; safe ones get a fix.

Runs locally in your browser

Input

15 lines · 315 characters
{
  "mcpServers": {
    "filesystem": {
      "command": "npx -y @modelcontextprotocol/server-filesystem /Users/me/projects"
    },
    "github": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"
      }
    }
  }
}

Output

When a problem has a safe fix, the config with it appears here.

What the MCP validator finds

The validator does two jobs. Under Client config it reads an AI client's MCP config the way the client does and lists what would stop a server from loading: servers under a key the client never reads, a command line packed into the command field, a value of the wrong type, a placeholder in another client's syntax, a token written out in full. Under Tool schemas it checks the tools an MCP server lists against the specification: the fields a tool needs, its inputSchema and outputSchema as JSON Schema, the naming rules and the x-mcp-header annotation. Each problem points at its line and column, and for the common mistakes the output shows your input with the fix applied.

It knows the configs of Claude Desktop, Claude Code, Cursor, VS Code, Devin (formerly Windsurf) and OpenAI Codex, including JSON with comments and Codex's TOML, and the tool definitions of MCP revisions 2026-07-28 and 2025-11-25.

How to check an MCP config or tool schemas

  1. Choose Client config for a client's config file, or Tool schemas for the tools a server lists.
  2. Paste the config or the tools, or open the file: claude_desktop_config.json, .mcp.json, mcp.json, mcp_config.json or config.toml for a config; a tool, a list of tools or a tools/list response for tool schemas.
  3. Choose the client under Client, or leave Auto-detect on. For tools, choose the revision your server follows under Revision.
  4. Read the problems, errors first. Select one to jump to its place in the input.
  5. Where the output shows a fixed version, copy it or download it, and use it in place of your file or your server's definitions.
  6. Restart the client, or reload its MCP servers, so it reads the change.

Examples

VS Code's key in Claude Desktop's file

Input

{
  "servers": {
    "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/Documents"] }
  }
}

Output

Line 2, column 3: Claude Desktop reads servers from mcpServers, not servers. Rename servers to mcpServers: servers is VS Code's key. (MCP_WRONG_TOP_LEVEL_KEY)
A whole command line in Cursor's command field

Input

{
  "mcpServers": {
    "git": { "command": "uvx mcp-server-git --repository /Users/me/code/app" }
  }
}

Output

Line 3, column 25: The command includes its arguments. Put uvx in command and each argument in args; the client runs the command as one program name. (MCP_COMMAND_HAS_ARGS)
A misspelt type and an undefined parameter in a tool

Input

{
  "name": "get_weather",
  "description": "Get the current weather for a city.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "city": { "type": "strng" }
    },
    "required": ["city", "units"]
  }
}

Output

Line 7, column 25: In the inputSchema of get_weather, properties.city.type is "strng", which isn't a JSON Schema type. The types are string, number, integer, boolean, object, array and null; a list of them takes any of those. (MCP_JSON_SCHEMA_INVALID)
Line 9, column 26: In the inputSchema of get_weather, required names "units", which properties leaves out. Add it to properties with its type and description, or remove it from required: a model can't fill in a parameter it doesn't see. (MCP_REQUIRED_NOT_IN_PROPERTIES)

Why a client skips a server

Most configs that fail to load have one of a few mistakes:

  • The servers are under the wrong key. VS Code reads servers; the other JSON clients read mcpServers; Codex wants [mcp_servers.<name>] tables. Snippets copied from a README sometimes have no key at all, and VS Code's older settings.json kept them inside mcp.
  • The command holds its arguments. A client starts the command as one program, so "npx -y package" looks for a program with spaces in its name. The program goes in command, everything after it in args.
  • npx waits for an answer. Without -y, npx asks before it downloads a package, and nobody is there to reply.
  • A value has the wrong type. Arguments and environment values are strings: 8080 without quotes is a number. VS Code alone takes numbers in env.
  • The client reads the entry differently. Claude Code treats a server without type as local, so a url alone isn't enough there, and VS Code needs type on every server.

Which client a config is for

Codex's TOML and VS Code's servers key give their client away. Claude Desktop, Claude Code, Cursor and Devin all use mcpServers, so the validator looks for what only one of them documents: envFile or ${env:NAME} for Cursor, ${NAME} or headersHelper for Claude Code, transport or disabled for Devin. A config with plain local servers fits all four, and the validator then checks only what they share and says so. Choose the client under Client to check everything, including the fields, placeholders and comments that client reads.

Fields each client documents

The server fields each client documents
ClientLocal serverRemote serverComments
Claude Desktopcommand, args, envNot in this filePlain JSON
Claude Codetype, command, args, env, timeout, alwaysLoadtype, url, headers, headersHelper, oauth, timeout, alwaysLoadPlain JSON
Cursortype, command, args, env, envFiletype, url, headers, authNot described
VS Codetype, command, args, cwd, env, envFile, dev, sandboxEnabled, sandboxtype, url, headers, oauth, devRead
Devin Desktop (formerly Windsurf)command, args, env, disabledurl, transport, headers, oauthClientId, oauthClientSecret, oauthResource, disabledNot described
OpenAI Codexcommand, args, env, env_vars, cwd, experimental_environment, startup_timeout_sec, tool_timeout_sec, enabled, required, enabled_tools, disabled_tools, default_tools_approval_mode, toolsurl, auth, bearer_token_env_var, http_headers, env_http_headers, http_headers_helper, scopes, oauth, startup_timeout_sec, tool_timeout_sec, enabled, required, enabled_tools, disabled_tools, default_tools_approval_mode, toolsTOML: # comments

A field outside this list is not always an error, since clients add settings over time, but a misspelt one is silently ignored: enviroment instead of env leaves the server without its variables. The validator lists such fields as warnings. Comments are fine in VS Code's mcp.json; Claude Desktop's and Claude Code's documentation shows only plain JSON, and Cursor's and Devin's shows comments in examples without describing them.

Placeholders and secrets

A placeholder works only in the syntax its client replaces; in any other, the server receives the text itself. Claude Code reads ${NAME} and ${NAME:-default}, Cursor and VS Code read ${env:NAME}, and VS Code also reads ${input:id} once the id is defined under inputs. Codex reads variables through env_vars, bearer_token_env_var and env_http_headers. Claude Desktop replaces nothing, and Devin only in its OAuth fields.

Values that look like keys or tokens, found by their name or by a known key format, are listed with the way the client keeps them out of the file. The config never leaves your browser.

What a tool definition needs

A tool is an object with a name and an inputSchema; title, description, outputSchema, annotations and icons are optional. Clients call the tool by its name, and the specification asks for 1 to 128 letters, digits, _, - and ., unique within the server: get_weather or admin.tools.list, not get weather. The model reads the description to decide when to call the tool, so the validator flags one that is missing or only a word or two. A tool written for a model API, with input_schema or parameters, needs its schema renamed to inputSchema.

Tool schemas and JSON Schema

Tool arguments are always one JSON object, so an inputSchema needs "type": "object" at its top, even for a tool without parameters: { "type": "object", "additionalProperties": false } takes only an empty object. Schemas are JSON Schema 2020-12 unless their $schema names another dialect. The validator checks 2020-12 and draft-07 schemas against their official meta-schemas, so a misspelt type, a required that isn't a list or a pattern that isn't a valid regular expression shows up at its place. It also flags a name in required that properties leaves out, since the model never sees what to put there.

Header parameters with x-mcp-header

Since 2026-07-28, a parameter's schema can carry x-mcp-header to send its value as an HTTP header, Mcp-Param-{name}, on Streamable HTTP, so a gateway can route a call without reading its body. A client must leave out a tool whose annotation breaks the rules: the name is an HTTP token without spaces, different from the tool's other header names ignoring case, on a string, integer or boolean parameter reached from the top through properties alone, not inside items, anyOf or $defs. Header values travel in the open, so keep keys, tokens and personal data out of them.

Which MCP revision to choose

Choose the revision your server's SDK implements. 2026-07-28 made every tools/list result carry resultType, ttlMs and cacheScope, added x-mcp-header, moved tasks and the tools' execution field into an extension, and let an outputSchema be any JSON Schema. Under 2025-11-25 an outputSchema is an object schema with "type": "object", like an inputSchema, and each schema under properties is an object rather than true or false.

Suggested fixes

A few mistakes have a fix the validator can make without guessing. In a config, a wrong root key is renamed, servers written at the top are put inside the client's key, and a command line is split into command and args, with -y added for npx. In tool schemas, an inputSchema without a type gets "type": "object", and so does an outputSchema under 2025-11-25. The output shows the whole input with these changes, in its own indentation and with its comments; your input stays as it is. Other problems need a decision, such as which value a secret should come from, so they are listed with a hint instead. Codex's TOML gets hints only.

Options

Options
OptionValuesDefaultWhen to change it
ClientAuto-detect, Claude Desktop, Claude Code, Cursor, VS Code, Devin (Windsurf), CodexAuto-detectClient config: the client whose rules apply. Auto-detect tells it from the config where it can, and remembers your last choice.
Revision2026-07-28 (latest), 2025-11-252026-07-28 (latest)Tool schemas: the MCP specification revision the tools are checked against.

Common errors and fixes

Common errors and how to fix them
CodeWhat it meansHow to fix it
MCP_WRONG_TOP_LEVEL_KEYErrorThe servers are under a key the client doesn't read, at the top of the file without a key, or in VS Code's settings.json section.Use the fixed config, or move the servers under mcpServers (servers for VS Code).
MCP_CLIENT_UNDETECTEDWarningThe config fits several clients, so only the rules they share were checked.Choose the client under Client.
MCP_MISSING_COMMAND_OR_URLErrorA local server has no command or a remote one no url; in Claude Code, a url without a type counts as local.Add the command, the url, or "type": "http" for Claude Code.
MCP_COMMAND_AND_URLErrorA server has both a command and a url.Delete one of them: a command makes the server local, a url makes it remote.
MCP_COMMAND_HAS_ARGSWarningThe command field holds the whole command line.Use the fixed config, or keep the program in command and the rest in args.
MCP_NPX_MISSING_YWarningnpx would ask for confirmation before downloading the package.Add -y as the first argument.
MCP_ARGS_NOT_STRINGSErrorargs is not a list, or holds a number, true or an object.Write each argument as a string in quotes, as in ["--port", "8080"].
MCP_ENV_NOT_STRINGErrorAn environment value isn't a string; only VS Code takes numbers and null.Put the value in quotes.
MCP_INVALID_FIELDErrorA field has the wrong type or value, VS Code's type is missing, or an ${input:} id isn't defined.Follow the hint: the problem names what the client expects.
MCP_UNKNOWN_FIELDWarningThe client's documentation doesn't name this field for this kind of server; often a typo.Check the spelling against the fields table above.
MCP_INVALID_URLErrorThe url isn't an http:// or https:// address.Copy the endpoint again from the server's documentation.
MCP_INSECURE_URLWarningThe url sends requests with http:// to another computer, without encryption.Use https://, unless the server is on a network you trust.
MCP_SSE_DEPRECATEDWarningThe server uses SSE, which MCP replaced with Streamable HTTP.Switch to the server's Streamable HTTP endpoint, often /mcp.
MCP_PLACEHOLDER_UNSUPPORTEDWarningA placeholder is in a syntax this client doesn't replace.Write it the way the hint shows, or put the value in another way the client reads.
MCP_PLAINTEXT_SECRETWarningA key or token is written into the file.Read it from the environment or an input, as the hint shows for your client.
MCP_JSONC_NOT_SUPPORTEDWarningThe file has comments or trailing commas, and the client's documentation shows plain JSON.Remove the comment or the comma.
MCP_INVALID_SERVER_NAMEErrorThe server's name has characters some clients or commands refuse, or Claude Code keeps it for itself.Rename it with letters, numbers, - and _.
MCP_TRANSPORT_UNSUPPORTEDWarningThe client's file doesn't take this kind of server: Claude Desktop starts local servers only.Add a remote server to Claude Desktop as a custom connector.
MCP_TOML_SYNTAXErrorCodex's config.toml can't be read.Fix the line shown: a missing quote, bracket or =, or a table written twice.
MCP_IMPORT_UNRECOGNIZEDErrorThe input is in another format than the client's, or isn't a tool, a list of tools or a tools/list response.Paste the client's own file, or the server's tools as JSON.
MCP_TOOL_SCHEMA_INVALIDErrorA tool, or the tools/list result around it, doesn't match the revision's schema: a missing name or inputSchema, a value of the wrong type.Follow the hint; for a result of an older server, choose its revision under Revision.
MCP_SCHEMA_ROOT_NOT_OBJECTErrorAn inputSchema has no type or another type than object; under 2025-11-25, an outputSchema too.Use the fixed tools, or put "type": "object" at the top of the schema.
MCP_JSON_SCHEMA_INVALIDErrorThe inputSchema or outputSchema breaks its JSON Schema meta-schema, or is nested too deep to check.Correct the keyword at the place shown, as the hint describes.
MCP_SCHEMA_DIALECT_UNSUPPORTEDWarningThe schema's $schema names a dialect other than 2020-12 or draft-07, so the validator doesn't check it.Remove $schema to use 2020-12, MCP's default, or write the official URI of the dialect.
MCP_TOOL_NAME_INVALIDWarningThe tool's name is empty, longer than 128 characters, or has a character beyond letters, digits, _, - and .Rename the tool, as the hint suggests.
MCP_TOOL_DESCRIPTION_MISSINGWarningThe tool has no description, or one of a word or two.Describe what the tool does and when the model should call it.
MCP_REQUIRED_NOT_IN_PROPERTIESWarningrequired names a parameter that properties doesn't define.Define the parameter, or remove its name from required.
MCP_DUPLICATE_TOOL_NAMEErrorTwo tools in the list have the same name.Rename one of them, or remove the copy.
MCP_HEADER_MAPPING_INVALIDWarningAn x-mcp-header breaks the 2026-07-28 rules, or would send a secret as a header.Correct the header name or the parameter's type, or remove the annotation.
JSON_DUPLICATE_KEYErrorThe same key appears twice in one object, such as one server name written twice.Keep one of them: the client reads only the last.
JSON_NUMBER_PRECISIONNoteA number in a tool schema has more digits than a JavaScript number keeps, so the checks compare the nearest one.Nothing to fix for the check; your text stays as written.

Privacy

MCP Config & Schema Validator runs entirely in your browser. What you type, paste or open is processed on your device: it is not sent to Toolzami, and Toolzami does not store it. Only the options you choose are remembered, in this browser.

Frequently asked questions

Why doesn't my MCP server show up after I edit the config?

Usually the client can't read the entry: the servers sit under the wrong key, the file has a syntax error, the command holds its arguments, or npx waits for a confirmation nobody gives. The validator points at each of these. After fixing the file, restart the client or reload its MCP servers.

Can an MCP config file have comments?

VS Code reads its mcp.json as JSON with comments. Claude Desktop's and Claude Code's documentation shows plain JSON only, so leave comments and trailing commas out of their files. Cursor's and Devin's documentation shows comments in some examples without saying whether they are read.

Why does my MCP server receive ${env:API_KEY} instead of the key?

The client doesn't replace that syntax, so the server gets the text as written. Claude Code reads ${API_KEY}, Cursor and VS Code ${env:API_KEY}, and Codex reads variables through env_vars; Claude Desktop and Devin replace none. The validator names the form your client reads.

Does an MCP tool's inputSchema need "type": "object"?

Yes. Tool arguments are always one JSON object, and the specification's Tool definition asks for "type": "object" at the top of inputSchema, even for a tool without parameters. Clients and model APIs may reject a tool without it. Under Tool schemas the validator flags the missing type and adds it in the fixed output.

Which JSON Schema version do MCP tool schemas use?

JSON Schema 2020-12, unless a schema's $schema names another dialect. Every client must support 2020-12, and draft-07 schemas are common too. The validator checks both against their official meta-schemas and flags any other dialect, which a client may refuse.

Last updated