Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Oh My

FreeNot checked

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

GitHubEmbed

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.

npm version CI types license

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 inputSchema that requireds 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/call smoke tests.
  • A --fix that 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

from github.com/didrod205/oh-my-mcp

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-mcp

FAQ

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

Compare 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