Oh My
FreeNot checkedLint your MCP server before a model chokes on it. Checks MCP tool definitions — names that break function-calling, weak descriptions, invalid input schemas, and
About
Lint your MCP server before a model chokes on it. Checks MCP tool definitions — names that break function-calling, weak descriptions, invalid input schemas, and the context budget your toolset eats every request — from a tools/list JSON or by speaking the protocol to a live server over stdio. Local, no API key.
README
oh-my-mcp
Lint your MCP server before a model chokes on it.
npx oh-my-mcp --cmd "node your-server.js"
Everyone's shipping MCP servers. And the tool definitions are full of silent footguns the protocol won't catch for you:
- a tool name with a space or a dot — which breaks function-calling the moment a client maps it to an OpenAI-style function name,
- a description the model can't act on ("search") or a param with no description — so the model picks the wrong tool or fills the wrong args,
- an
inputSchemathatrequireds a property it never defines, - and the one nobody measures: how much of the model's context window your whole toolset eats on every single request.
oh-my-mcp reads your tool definitions — from a tools/list JSON or by speaking
the protocol to a live server over stdio — and grades them. Local,
deterministic, no API key.
$ npx oh-my-mcp --cmd "node weather-server.js"
● oh-my-mcp · weather-server v1.0.0 (live, MCP 2025-06-18)
Server-wide
✗ Duplicate tool name "list_items" (2 tools share it) — the model can't address them.
· Your 6 tool definitions cost ~157 tokens of context on every single request.
B get weather 83/100 · ~28 tok
✗ Name "get weather" has characters that break function-calling. → Use only [a-zA-Z0-9_-].
! Param "location" has no description — the model leans on these to fill arguments.
B search_database 83/100
✗ inputSchema problem at inputSchema.required: requires "query", which is not in properties
…
30/100 (F) 4 errors · 4 warnings · ~157 ctx tokens
Three ways to point it at your tools
# 1. a live server — spawn it and run the MCP handshake, then lint what it serves
npx oh-my-mcp --cmd "node server.js"
npx oh-my-mcp --cmd "npx -y @some/mcp-server"
# 2. every server in your MCP client config (claude_desktop_config.json / mcp.json)
npx oh-my-mcp --servers ~/Library/Application\ Support/Claude/claude_desktop_config.json
# 3. a tools/list JSON you already have
npx oh-my-mcp tools.json
some-server | npx oh-my-mcp --stdin
In live mode it runs the real initialize → tools/list handshake and also checks
the protocol itself (missing serverInfo, protocolVersion, malformed
tools/list). Non-JSON log lines on stdout are ignored; a silent server times out
instead of hanging.
What it checks
| Group | Examples |
|---|---|
| Breaks tool-calling | names outside [a-zA-Z0-9_-] or >64 chars, duplicate names, readOnlyHint on a tool whose name screams mutation |
| The model can't use it well | missing/one-word descriptions, params with no description, mixed snake/camel naming |
| Input schema | not a valid JSON Schema, required referencing a missing property, params with no type, non-object top level |
| Wastes context | the total token cost of your toolset on every request; individual over-long descriptions |
| Protocol (live) | missing serverInfo/protocolVersion, no tools capability, malformed tools/list |
Every finding rolls up into a per-tool and overall 0–100 score (A–F) you can gate in CI.
Install
npx oh-my-mcp --cmd "node server.js" # no install
npm i -g oh-my-mcp # the bin is also `omm`
Node ≥ 18. The lint core is dependency-free and browser-safe.
Gate it in CI
oh-my-mcp exits non-zero on any error (or below --min-score), so a bad tool
definition can't ship:
# .github/workflows/ci.yml
- run: npx oh-my-mcp --cmd "node dist/server.js" --min-score 80
oh-my-mcp tools.json --json report.json # machine-readable
oh-my-mcp tools.json --md report.md # paste into a PR
Library API
The lint engine is pure (browser-safe), so you can lint a pasted tools/list:
import { extractTools, analyze, DEFAULT_CONFIG } from "oh-my-mcp";
const report = analyze(extractTools(toolsListResult), DEFAULT_CONFIG, { label: "my-server", mode: "file" });
console.log(report.score, report.tools[0].findings);
Roadmap
- 🌐 Web playground — paste a
tools/list, see the report (the core already runs in a browser). - Resources & prompts (not just tools), and
tools/callsmoke tests. - A
--fixthat rewrites names/schemas where it safely can. - More client configs auto-discovered (Cursor, VS Code, Windsurf).
💖 Sponsor
Free, MIT, built in spare time. If it caught a tool def before a model did:
- ⭐ Star the repo — so the next person building an MCP server finds it.
- 🍋 Sponsor via Lemon Squeezy — one-time or recurring.
License
MIT © oh-my-mcp contributors
Installing Oh My
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/didrod205/oh-my-mcpFAQ
Is Oh My MCP free?
Yes, Oh My MCP is free — one-click install via Unyly at no cost.
Does Oh My need an API key?
No, Oh My runs without API keys or environment variables.
Is Oh My hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Oh My in Claude Desktop, Claude Code or Cursor?
Open Oh My on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare Oh My with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
