Mcp Ai — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp Ai (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
mcpgen is a command-line tool that takes a URL — either an API documentation page or a regular website — and automatically generates a working MCP server for it. You run one command, point it at a URL, and get back a folder with a Python server you can plug into Claude.
MCP (Model Context Protocol) is how AI assistants connect to external tools and services. If you want Claude to be able to call a specific API or interact with a website, you need an MCP server that wraps it. Writing those servers by hand is repetitive: you read the docs, figure out which endpoints matter, write boilerplate FastMCP code, set up authentication, and write tests. That takes hours per service.
mcpgen automates that whole process. You give it the URL you would have read manually, and it does the reading, the design decisions, and the code generation for you. It handles two distinct cases:
https://pokeapi.co/docs/v2) — it reads the docs and generates an MCP server that makes HTTP calls using httpxhttps://twitter.com) — it generates an MCP server that uses Playwright browser automation to interact with the UI directlyThe second case is where it becomes genuinely useful. Most services either have no public API, have a paid API, or have an API that lags behind what you can do through the actual website. Browser automation fills that gap.
The pipeline has four stages:
server.py, requirements.txt, .env.example, a README.md, and smoke testsResults from steps 1 and 2 are cached locally so you can tweak generation or try a different model without re-crawling and re-paying for LLM tokens.
You need accounts and API keys for:
You need Python 3.11 or higher. The project uses uv for package management but pip works fine too.
Clone the repo and install in a virtual environment:
git clone https://github.com/your-repo/mcpgen
cd mcpgen
python -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
pip install -e .For UI mode (browser automation), you also need the Playwright browser binaries:
pip install playwright
playwright install chromiumCreate a .env file in the project root. At minimum you need Firecrawl and one LLM provider:
# Required for crawling
FIRECRAWL_API_KEY=fc-your_key_here
# Pick at least one LLM provider
ANTHROPIC_API_KEY=sk-ant-your_key_here
OPENAI_API_KEY=sk-your_key_here
GOOGLE_API_KEY=your_key_hereYou do not need all three LLM providers. If you only have an Anthropic key, just set that one and pick Claude from the model menu when you run mcpgen.
mcpgen https://pokeapi.co/docs/v2This will:
./pokeapi-mcp/The output folder looks like this:
pokeapi-mcp/
server.py # the MCP server — this is what you run
requirements.txt # fastmcp, httpx, python-dotenv
.env.example # shows which env vars the server needs
README.md # setup instructions specific to this server
tests/
__init__.py
test_tools.py # smoke tests with httpx mocked outmcpgen [URL] [OPTIONS]
Arguments:
URL The page to generate an MCP server for
Options:
--model, -m TEXT LiteLLM model string (skips the interactive menu)
Examples: claude-sonnet-4-6, claude-opus-4-7, openai/gpt-5.5
--mode TEXT auto, api_docs, or ui [default: auto]
--out, -o PATH Output directory [default: {site_name}-mcp]
--dry-run Print the discovered tools without generating code
--no-cache Ignore cached crawl and tool spec, start fresh
--cache-only Skip crawl and analysis, regenerate code from cacheThe --dry-run flag is useful for checking what tools mcpgen would create before spending tokens on code generation. The --cache-only flag is useful when you are happy with the tool spec but want to try a different model for code generation.
When you run mcpgen without --model, it shows a menu:
Which AI model to use?
1. claude-sonnet-4-6 (Recommended)
2. claude-opus-4-7 (Most capable)
3. openai/gpt-5.5
4. gemini/gemini-3.1-pro-preview
5. Enter model name manuallyYou can also pass any LiteLLM-supported model string directly:
mcpgen https://example.com/api/docs --model claude-opus-4-7
mcpgen https://example.com/api/docs --model openai/gpt-5.5Note: GPT-5.5 is a reasoning model and does not accept a temperature parameter. mcpgen handles this automatically.
By default mcpgen looks at the URL to decide whether to generate an API client or a browser automation server. URLs containing segments like /docs, /api, /reference, /developers are treated as API documentation. Everything else is treated as a UI target.
You can override this:
# Force API mode even if the URL looks like a regular site
mcpgen https://some-site.com/endpoints --mode api_docs
# Force UI/browser mode
mcpgen https://some-site.com --mode uiFor API mode, the generated server.py follows these patterns:
httpx for HTTP calls, not requestsresp.raise_for_status() before processing any response_compact() helper that truncates lists to 10 items and strings to 300 characters, so the LLM context does not get floodedRuntimeError immediately on python server.py if required environment variables are missing, instead of failing silently on the first tool calllimit: int = 10 parameterFor UI mode, the generated server.py:
playwright.sync_api.sync_playwright for browser automationheadless=True by default (set MCPGEN_HEADLESS=false to see the browser){"status": "success", "data": ..., "url": page.url} — never raw page contentfinally: browser.close(), so a missing selector does not crash the serverTool descriptions follow a specific formula designed to help the LLM pick the right tool:
"[ACTION] [OBJECT] — use this when [TRIGGER]. Do not use this to [DISAMBIGUATION]."For example: "Retrieves a Pokemon's data — use this when you know the Pokemon's name or ID. Do not use this to list all available Pokemon."
After generating a server, you can add it to Claude Code with one command (shown at the end of the generation output):
claude mcp add pokeapi -- python /absolute/path/to/pokeapi-mcp/server.pyFind your MCP config JSON file (claude_desktop_config.json on Desktop, or your Cursor settings) and add an entry:
{
"mcpServers": {
"pokeapi": {
"command": "python",
"args": ["/absolute/path/to/pokeapi-mcp/server.py"]
}
}
}The server reads its environment variables from the .env file in its own directory, so credentials stay with the server rather than in the MCP config.
pytestThe test suite covers the analyzer, generator, writer, and crawler modules. All tests mock external calls (LiteLLM, Firecrawl, httpx) so you do not need live API keys to run them.
pytest -v # verbose output
pytest tests/test_writer.py # run a specific moduleSingle-page crawl only. mcpgen scrapes one URL. Many API documentation sites spread their reference across dozens of pages. For example, the Stripe API docs have separate pages for each resource type. mcpgen will only see whatever is on the specific URL you give it. For deep coverage of multi-page docs, you need to run it multiple times on different URLs or point it at a single-page reference if one exists.
Generated selectors may be wrong. For UI mode, the LLM has to guess the CSS selectors or test IDs for page elements it has never seen. It uses heuristics from the page text. These selectors will often be wrong or break when the site updates. Expect to manually correct selectors in the generated server.py before it works reliably. The generated code at least gives you the correct structure so you only need to fix the selectors, not rewrite the whole thing.
No session management. Each tool call in UI mode opens a fresh browser, navigates, acts, and closes. There is no persistent login session. If a site requires authentication, the generated server will need manual additions to handle cookies or local storage.
Rate limits are not handled. The generated API servers do not include retry logic or rate limit backoff. If an API returns 429, raise_for_status() will propagate the exception.
Context quality depends on the page. If the documentation page you give it is poorly structured, has a lot of irrelevant content, or uses formats that Firecrawl cannot parse well (some SPAs, heavy JavaScript), the tool spec will be incomplete or inaccurate.
The project structure:
mcpgen/
cli.py # Typer CLI entry point and pipeline orchestration
crawler.py # Firecrawl integration and URL classification
analyzer.py # LLM call that produces a ToolSpec from Markdown
generator.py # LLM call that produces server.py code from ToolSpec
writer.py # Writes the output folder (server.py, README, tests, etc.)
cache.py # JSON file cache for crawl results and tool specs
models.py # TypedDict definitions (ToolSpec, Tool, ToolParam)
prompts/
analyze.md # System prompt for the analysis LLM call
generate_api.md # System prompt for API server code generation
generate_ui.md # System prompt for UI/Playwright server code generation
tests/
test_analyzer.py
test_crawler.py
test_generator.py
test_writer.pyThe prompts directory is where the quality of generated output is determined. If you want to improve the generated servers, the system prompts are the place to start.
Dependencies are managed through pyproject.toml. To add a new dependency:
# Edit pyproject.toml, then reinstall
pip install -e .~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.