Spaces:
Sleeping
Sleeping
| """MCP config validator — paste an MCP client config, get back issues. | |
| Validates against the common shape used by Claude Desktop, Cursor, Cline, | |
| Windsurf, and Zed. Doesn't try to BE all of those — just a quick sanity check. | |
| """ | |
| import json | |
| import gradio as gr | |
| REQUIRED_TOP = {"mcpServers"} | |
| SERVER_REQUIRED = {"command"} | |
| SERVER_OPTIONAL = {"args", "env", "cwd", "transport", "url"} | |
| def validate(config_text: str): | |
| if not config_text.strip(): | |
| return "_Paste a config to validate._" | |
| try: | |
| cfg = json.loads(config_text) | |
| except json.JSONDecodeError as e: | |
| return f"❌ **Invalid JSON:** {e.msg} at line {e.lineno}, col {e.colno}" | |
| issues = [] | |
| suggestions = [] | |
| if not isinstance(cfg, dict): | |
| return "❌ Config must be a JSON object at the top level." | |
| if "mcpServers" not in cfg: | |
| issues.append("Missing top-level `mcpServers` key.") | |
| return _format(issues, suggestions, cfg) | |
| servers = cfg["mcpServers"] | |
| if not isinstance(servers, dict): | |
| issues.append("`mcpServers` must be an object mapping server name → server config.") | |
| return _format(issues, suggestions, cfg) | |
| if not servers: | |
| issues.append("`mcpServers` is empty — no servers will be loaded.") | |
| for name, scfg in servers.items(): | |
| if not isinstance(scfg, dict): | |
| issues.append(f"Server `{name}` is not an object.") | |
| continue | |
| # Either command-based (stdio) or url-based (sse/http) — must have one | |
| if "command" not in scfg and "url" not in scfg: | |
| issues.append(f"Server `{name}` has neither `command` (stdio) nor `url` (sse/http).") | |
| if "command" in scfg and "url" in scfg: | |
| suggestions.append(f"Server `{name}` has both `command` and `url`. Most clients use one.") | |
| if "args" in scfg and not isinstance(scfg["args"], list): | |
| issues.append(f"Server `{name}`: `args` must be a list of strings.") | |
| if "env" in scfg and not isinstance(scfg["env"], dict): | |
| issues.append(f"Server `{name}`: `env` must be an object of string→string.") | |
| unknown = set(scfg.keys()) - SERVER_REQUIRED - SERVER_OPTIONAL | |
| if unknown: | |
| suggestions.append(f"Server `{name}` has unknown keys: {sorted(unknown)} (might be client-specific).") | |
| return _format(issues, suggestions, cfg) | |
| def _format(issues, suggestions, cfg): | |
| n_servers = len(cfg.get("mcpServers", {})) if isinstance(cfg.get("mcpServers"), dict) else 0 | |
| rows = [] | |
| if not issues: | |
| rows.append(f"✅ **Looks good** — {n_servers} server(s) configured.") | |
| else: | |
| rows.append(f"❌ **{len(issues)} issue(s):**") | |
| for i in issues: | |
| rows.append(f"- {i}") | |
| if suggestions: | |
| rows.append("") | |
| rows.append("💡 **Suggestions:**") | |
| for s in suggestions: | |
| rows.append(f"- {s}") | |
| return "\n".join(rows) | |
| EXAMPLES = [ | |
| ['{"mcpServers": {"filesystem": {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me"]}}}'], | |
| ['{"mcpServers": {"agentfit": {"command": "npx", "args": ["-y", "@mukundakatta/agentfit-mcp"]}}}'], | |
| ['{"mcpServers": {"broken": {"args": ["only-args"]}}}'], | |
| ['{"mcpServers": {}}'], | |
| ['{}'], | |
| ['not even json'], | |
| ] | |
| with gr.Blocks(title="MCP Config Validator", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| """ | |
| # MCP Config Validator | |
| Paste your MCP client config (Claude Desktop / Cursor / Cline / Windsurf / Zed style) and get a quick sanity check. | |
| Doesn't replace your client's own validator — just catches the common mistakes (missing `command`, wrong types, empty servers map) before you restart the client. | |
| Sample configs from [`mcp-config-examples`](https://huggingface.co/datasets/mukunda1729/mcp-config-examples). | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| txt = gr.Code( | |
| value=json.dumps({ | |
| "mcpServers": { | |
| "filesystem": { | |
| "command": "npx", | |
| "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me"], | |
| } | |
| } | |
| }, indent=2), | |
| language="json", | |
| label="MCP config", | |
| lines=14, | |
| ) | |
| btn = gr.Button("Validate", variant="primary") | |
| out = gr.Markdown() | |
| btn.click(validate, inputs=txt, outputs=out) | |
| gr.Examples(examples=EXAMPLES, inputs=txt) | |
| gr.Markdown( | |
| """ | |
| --- | |
| Part of [The Agent Reliability Stack](https://mukundakatta.github.io/agent-stack/) · MIT licensed | |
| """ | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) | |