# SyntaxChecker MCP — instructions for AI assistants This document is intended for an AI assistant (Claude, etc.) that needs to install, configure and use the `syntaxchecker` MCP server. ## What it is `syntaxchecker` is an MCP server that exposes a single tool, `check_syntax`, capable of validating files in JSON, JSON5, JSONC, XML, HTML, YAML, TOML, INI, CSV/TSV, HCL, Markdown, `.env`, Java Properties, Protobuf, GraphQL, Dockerfile, jq, the programming languages Go, TypeScript/JavaScript (incl. JSX/TSX), Shell/Bash, Lua and Starlark, and SQL (MySQL, PostgreSQL/ANSI, SQLite, SQL Server, Oracle). Use it when the user asks you to **verify the syntax** of a code/configuration file, or when you have just produced a file and want to confirm its validity before delivering it. The programming-language checks are **parse-only** (no type-checking, no name/import resolution). ## When to use it USE `check_syntax` when: - The user explicitly asks to validate/check a file's syntax. - You have just written or edited a JSON/JSON5/JSONC/XML/HTML/YAML/TOML/INI/CSV/HCL/Markdown/`.env`/Properties/Protobuf/GraphQL/Dockerfile/jq/Go/TypeScript/JavaScript/Shell/Lua/Starlark/SQL file and want to verify it before considering the task complete. - You are debugging a parsing error in one of these formats. USE `check_syntax` with `schema` when: - You need to validate a JSON or YAML file against a JSON Schema (structure, required fields, types, constraints) — pass the schema's path in `schema`. - You need to validate an XML file against a DTD — pass the DTD's path in `schema`. DO NOT use it for: - Semantic validation (e.g. "does this SQL do the right thing?", type errors, undefined variables) — the tool checks syntax/parsing only. - XSD/RelaxNG validation for XML — not supported (XML supports DTD only; JSON/YAML support JSON Schema). - Languages not listed (Python, Java, C/C++, Rust, etc.). ## Installation ### 1. Build the binaries From the repo root, with Go 1.22+: ``` mage build ``` Produces: - `dist/syntax-checker(.exe)` — validation CLI. - `dist/syntaxchecker-mcp(.exe)` — MCP server (stdio transport). If Mage is not installed: ``` go build -o dist/syntax-checker.exe ./apps/checker go build -o dist/syntaxchecker-mcp.exe ./apps/mcp-server ``` ### 2. MCP client configuration #### Claude Desktop / Claude Code File: `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS). ```json { "mcpServers": { "syntaxchecker": { "command": "C:\\absolute\\path\\dist\\syntaxchecker-mcp.exe", "env": { "CHECKER_BIN": "C:\\absolute\\path\\dist\\syntax-checker.exe" } } } } ``` `CHECKER_BIN` is optional if both binaries live in the same folder: the server looks for `syntax-checker(.exe)` next to itself and then on `PATH`. Restart the MCP client after editing the config. #### VS Code (MCP extension) Same JSON shape under the `mcpServers` key in the extension configuration. #### OpenCode File: `~/.config/opencode/opencode.json` (Linux/macOS) or `%APPDATA%\opencode\opencode.json` (Windows). ```json { "mcp": { "syntaxchecker": { "type": "local", "command": ["C:\\absolute\\path\\dist\\syntaxchecker-mcp.exe"], "environment": { "CHECKER_BIN": "C:\\absolute\\path\\dist\\syntax-checker.exe" }, "enabled": true } } } ``` Restart OpenCode after editing the config. #### Installed via winget (portable) When SyntaxChecker is installed with `winget install Parresia.SyntaxChecker` (portable zip package), winget registers two PATH aliases — `syntax-checker` and `syntaxchecker-mcp` — so you no longer need absolute paths. In every config above, replace the absolute `...\dist\syntaxchecker-mcp.exe` with just the alias name, and drop `CHECKER_BIN` entirely (the server finds `syntax-checker` on `PATH` automatically). Claude Code, in one command: ```powershell claude mcp add syntaxchecker syntaxchecker-mcp # current project claude mcp add --scope user syntaxchecker syntaxchecker-mcp # all projects ``` Or the equivalent JSON for any client: ```json { "mcpServers": { "syntaxchecker": { "command": "syntaxchecker-mcp" } } } ``` > Open a new shell after the winget install so the updated `PATH` is picked up. > The reference docs (`for-ia.md`, `for-agent.md`, `README.md`) ship inside the > same zip, next to the executables. ### 3. Verify the installation In the client, call the tool against a sample file: ``` check_syntax(file_path="C:/path/SyntaxChecker/test-samples/json/config.json") ``` Expected: `{"valid": true, ...}`. ## Using the tool ### Signature ``` check_syntax(file_path: string, type?: string, schema?: string, strict?: boolean) ``` ### Parameters - **`file_path`** (required) — path to the file. Absolute or relative to the server's working directory. Prefer absolute paths to avoid ambiguity. - **`type`** (optional) — forces the type. If omitted, the checker auto-detects from the extension (`.json`, `.json5`, `.jsonc`, `.xml`, `.html`/`.htm`, `.yml`/`.yaml`, `.toml`, `.ini`/`.cfg`, `.csv`, `.tsv`, `.hcl`/`.tf`, `.md`/`.markdown`, `.env`, `.properties`, `.proto`, `.graphql`/`.gql`, `.jq`, `.go`, `.ts`, `.tsx`, `.js`/`.mjs`/`.cjs`, `.jsx`, `.lua`, `.sh`/`.bash`, `.star`/`.bzl`, `.sql`) or, by file name, for Dockerfiles (`Dockerfile`, `Containerfile`, `*.dockerfile`) and Bazel (`BUILD.bazel`, `WORKSPACE.bazel`). - **Important for `.sql`**: auto-detect does NOT know which dialect to use. For SQL files **you must always pass `type`** with the correct dialect, otherwise the checker fails or uses an unwanted default. - **Bazel `BUILD`/`WORKSPACE` without extension** are not auto-detected: pass `type="starlark"`. - Valid values: `json`, `json5`, `jsonc`, `xml`, `html`, `yaml`, `toml`, `ini`, `csv`, `tsv`, `hcl`, `markdown`, `env`, `properties`, `proto`, `graphql` (alias `gql`), `dockerfile`, `jq`, `go` (alias `golang`), `ts` (alias `typescript`), `tsx`, `js` (alias `javascript`), `jsx`, `lua`, `shell` (alias `bash`, `sh`), `starlark` (alias `bzl`), `sql:mysql`, `sql:postgres` (alias `sql:postgresql`), `sql:ansi`, `sql:sqlite`, `sql:mssql` (alias `sql:tsql`), `sql:oracle` (alias `sql:plsql`). - **`schema`** (optional) — for `json`/`yaml`, a JSON Schema (drafts up to 2020-12, including draft-07); for `xml`, a DTD. Passing it for any other type returns an error (XSD/RelaxNG are not supported). JSON Schema violations are reported by instance location (a JSON pointer like `/items/0/name`); DTD violations carry the offending element/attribute name. - **`format` is annotation-only** (e.g. `email`, `date` are NOT enforced); structural keywords (`type`, `required`, `enum`, `pattern`, ranges, `oneOf`, `$ref`, …) ARE enforced. Do not assume a malformed email fails validation. - **`strict`** (optional, bool) — enables stricter checks. Known effects: - JSON: detects duplicate keys (otherwise silently ignored by the standard parser). - CSV/TSV: enforces a consistent field count across rows (ragged rows are tolerated without it) and rejects lazy quoting. - HTML: enforces XHTML-style balanced/nested tags (without it, the tolerant HTML5 parse accepts almost anything). - YAML: rejects application-specific custom tags (e.g. `!Point`); anchors/aliases and standard tags stay valid. - Other formats: no effect for now, but passing `true` is harmless. ### Call examples ``` check_syntax(file_path="/abs/path/config.json") check_syntax(file_path="/abs/path/config.json", strict=true) check_syntax(file_path="/abs/path/config.json", schema="/abs/path/schema.json") check_syntax(file_path="/abs/path/query.sql", type="sql:mysql") check_syntax(file_path="/abs/path/migration.sql", type="sql:postgres") check_syntax(file_path="/abs/path/deploy.yaml") check_syntax(file_path="/abs/path/deploy.yaml", schema="/abs/path/schema.json") ``` ### Response Structured content with this shape: ```json { "file": "/abs/path/config.json", "type": "json", "valid": false, "errors": [ { "line": 5, "column": 12, "message": "invalid character '}' looking for ..." } ] } ``` - `valid: true` → file is syntactically correct. `errors` absent or empty. - `valid: false` → at least one error. Every `errors[i]` always has `message`; `line`/`column` may be missing. JSON, JSON5, TOML, CSV/TSV, HCL, HTML (strict), GraphQL, Protobuf, jq, Go, TypeScript/JavaScript, Shell, Lua and Starlark report both `line` and `column`; YAML, XML and Dockerfile report `line` only; `.env`, INI, Properties, Markdown and DTD violations may report neither. ## How to interpret results 1. If `valid: true`: the file is well-formed. This does NOT mean "correct at the logic/schema level" — only that the parser accepts it. 2. If `valid: false`: - Report errors to the user mentioning **file, line, column and message** (`file_path:line:column`). - If you generated the file yourself, **fix it** before returning it to the user. - For SQL: if the error looks inconsistent, double-check that you passed the right `type`. A construct valid in PostgreSQL may be invalid in MySQL. ## Common errors and troubleshooting - **Tool not available in the client**: the server did not start. Check the `command` path, restart the client, and make sure `syntaxchecker-mcp.exe` exists. - **"checker binary not found"**: the server cannot locate `syntax-checker(.exe)`. Set `CHECKER_BIN` or place it in the same folder as `syntaxchecker-mcp.exe`. - **All SQL validations fail in odd ways**: you probably omitted `type` and auto-detect picked an unsuitable dialect. Pass the explicit dialect. - **First `sql:postgres` call is slow (~700 ms)**: normal. That is the WASM module init, once per process. ## Best practices - Always pass **absolute paths**. - For SQL, always pass an **explicit `type`**. - For JSON with sensitive configuration (e.g. config keys that must not repeat), pass **`strict=true`**. - When the user has a JSON Schema (or asks to validate structure/required fields, not just syntax) for a JSON/YAML file, pass **`schema`** with its path. - After generating a file for the user, validate before delivering. If invalid, fix and re-validate — do not hand over a broken file. - Do not call the tool on large binary or non-textual files: respond sensibly.