mcpsmith 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. mcpsmith-0.1.0/.claude-plugin/marketplace.json +17 -0
  2. mcpsmith-0.1.0/.claude-plugin/plugin.json +31 -0
  3. mcpsmith-0.1.0/.github/workflows/ci.yml +22 -0
  4. mcpsmith-0.1.0/.github/workflows/publish.yml +51 -0
  5. mcpsmith-0.1.0/.gitignore +9 -0
  6. mcpsmith-0.1.0/AGENTS.md +49 -0
  7. mcpsmith-0.1.0/LICENSE +21 -0
  8. mcpsmith-0.1.0/PKG-INFO +193 -0
  9. mcpsmith-0.1.0/README.md +163 -0
  10. mcpsmith-0.1.0/docs/design.md +144 -0
  11. mcpsmith-0.1.0/pyproject.toml +60 -0
  12. mcpsmith-0.1.0/server.json +30 -0
  13. mcpsmith-0.1.0/skills/build-mcp-server/SKILL.md +108 -0
  14. mcpsmith-0.1.0/skills/design-mcp-tools/SKILL.md +67 -0
  15. mcpsmith-0.1.0/src/mcpsmith/__init__.py +3 -0
  16. mcpsmith-0.1.0/src/mcpsmith/capture.py +49 -0
  17. mcpsmith-0.1.0/src/mcpsmith/check.py +87 -0
  18. mcpsmith-0.1.0/src/mcpsmith/cli.py +245 -0
  19. mcpsmith-0.1.0/src/mcpsmith/codegen.py +514 -0
  20. mcpsmith-0.1.0/src/mcpsmith/design/__init__.py +18 -0
  21. mcpsmith-0.1.0/src/mcpsmith/design/_digest.py +135 -0
  22. mcpsmith-0.1.0/src/mcpsmith/design/_draft.py +238 -0
  23. mcpsmith-0.1.0/src/mcpsmith/design/_validate.py +195 -0
  24. mcpsmith-0.1.0/src/mcpsmith/design/guide.md +115 -0
  25. mcpsmith-0.1.0/src/mcpsmith/design/llm.py +169 -0
  26. mcpsmith-0.1.0/src/mcpsmith/importers/__init__.py +34 -0
  27. mcpsmith-0.1.0/src/mcpsmith/importers/har.py +436 -0
  28. mcpsmith-0.1.0/src/mcpsmith/importers/openapi.py +279 -0
  29. mcpsmith-0.1.0/src/mcpsmith/model.py +301 -0
  30. mcpsmith-0.1.0/src/mcpsmith/runtime/__init__.py +7 -0
  31. mcpsmith-0.1.0/src/mcpsmith/runtime/http.py +343 -0
  32. mcpsmith-0.1.0/src/mcpsmith/runtime/server.py +79 -0
  33. mcpsmith-0.1.0/src/mcpsmith/runtime/shape.py +55 -0
  34. mcpsmith-0.1.0/src/mcpsmith/server.py +171 -0
  35. mcpsmith-0.1.0/src/mcpsmith/templates/ci.yml +21 -0
  36. mcpsmith-0.1.0/src/mcpsmith/templates/conftest.py.tmpl +46 -0
  37. mcpsmith-0.1.0/src/mcpsmith/templates/gitignore +8 -0
  38. mcpsmith-0.1.0/src/mcpsmith/templates/publish.yml +51 -0
  39. mcpsmith-0.1.0/tests/conftest.py +6 -0
  40. mcpsmith-0.1.0/tests/fixtures/har/shop.har +169 -0
  41. mcpsmith-0.1.0/tests/fixtures/openapi/petstore2.yaml +115 -0
  42. mcpsmith-0.1.0/tests/fixtures/openapi/petstore3.json +1 -0
  43. mcpsmith-0.1.0/tests/fixtures/openapi/tasks31.json +101 -0
  44. mcpsmith-0.1.0/tests/test_cli.py +150 -0
  45. mcpsmith-0.1.0/tests/test_codegen.py +324 -0
  46. mcpsmith-0.1.0/tests/test_design.py +389 -0
  47. mcpsmith-0.1.0/tests/test_importers.py +383 -0
  48. mcpsmith-0.1.0/tests/test_runtime.py +275 -0
  49. mcpsmith-0.1.0/uv.lock +1513 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "mcpsmith",
3
+ "description": "Build curated, tested MCP servers from an OpenAPI file or a recorded website session.",
4
+ "owner": {
5
+ "name": "Sepehr Radmard",
6
+ "email": "sepehrr80@gmail.com",
7
+ "url": "https://github.com/sepehr071"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "mcpsmith",
12
+ "source": "./",
13
+ "description": "Skills and an MCP server that guide your coding agent from an OpenAPI file or HAR to a tested MCP server project.",
14
+ "category": "development"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "mcpsmith",
3
+ "displayName": "mcpsmith",
4
+ "version": "0.1.0",
5
+ "description": "Turn an OpenAPI file or a recorded website session into a curated, tested MCP server. Skills and an MCP server for your coding agent.",
6
+ "author": {
7
+ "name": "Sepehr Radmard",
8
+ "email": "sepehrr80@gmail.com",
9
+ "url": "https://github.com/sepehr071"
10
+ },
11
+ "homepage": "https://github.com/sepehr071/mcpsmith",
12
+ "repository": "https://github.com/sepehr071/mcpsmith",
13
+ "license": "MIT",
14
+ "keywords": [
15
+ "mcp",
16
+ "openapi",
17
+ "har",
18
+ "code-generation",
19
+ "mcp-server",
20
+ "agents"
21
+ ],
22
+ "mcpServers": {
23
+ "mcpsmith": {
24
+ "command": "uvx",
25
+ "args": [
26
+ "mcpsmith@0.1.0",
27
+ "mcp"
28
+ ]
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python: ["3.10", "3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ - uses: astral-sh/setup-uv@v10.2.0
17
+ with:
18
+ python-version: ${{ matrix.python }}
19
+ - run: uv sync --locked
20
+ - run: uv run ruff check .
21
+ - run: uv run ruff format --check .
22
+ - run: uv run pytest -q
@@ -0,0 +1,51 @@
1
+ name: Publish
2
+
3
+ # Tag a release (git tag v0.1.0 && git push --tags) after bumping the version in
4
+ # pyproject.toml and server.json.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ jobs:
10
+ pypi:
11
+ runs-on: ubuntu-latest
12
+ environment: pypi
13
+ permissions:
14
+ id-token: write # PyPI trusted publishing
15
+ contents: write # GitHub Release
16
+ steps:
17
+ - uses: actions/checkout@v7
18
+ - uses: astral-sh/setup-uv@v10.2.0
19
+ - name: Check versions match the tag
20
+ run: |
21
+ TAG=${GITHUB_REF_NAME#v}
22
+ grep -q "^version = \"$TAG\"" pyproject.toml
23
+ test "$(jq -r .version server.json)" = "$TAG"
24
+ test "$(jq -r '.packages[0].version' server.json)" = "$TAG"
25
+ - run: uv sync --locked && uv run pytest -q
26
+ - run: uv build
27
+ - uses: pypa/gh-action-pypi-publish@release/v1
28
+ - run: gh release create "$GITHUB_REF_NAME" dist/* --generate-notes --title "$GITHUB_REF_NAME"
29
+ env:
30
+ GH_TOKEN: ${{ github.token }}
31
+
32
+ mcp-registry:
33
+ needs: pypi
34
+ runs-on: ubuntu-latest
35
+ permissions:
36
+ id-token: write # MCP Registry login via GitHub OIDC
37
+ contents: read
38
+ steps:
39
+ - uses: actions/checkout@v7
40
+ - name: Wait for PyPI to serve the new version
41
+ run: |
42
+ for i in $(seq 1 30); do
43
+ curl -sf "https://pypi.org/pypi/mcpsmith/${GITHUB_REF_NAME#v}/json" >/dev/null && exit 0
44
+ sleep 10
45
+ done
46
+ exit 1
47
+ - name: Install mcp-publisher
48
+ run: |
49
+ curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.1/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
50
+ - run: ./mcp-publisher login github-oidc
51
+ - run: ./mcp-publisher publish
@@ -0,0 +1,9 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.egg-info/
4
+ dist/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .mcpsmith/
8
+ *.har
9
+ !tests/fixtures/har/*.har
@@ -0,0 +1,49 @@
1
+ # mcpsmith
2
+
3
+ Python framework that turns an OpenAPI/Swagger file or a recorded website session (HAR) into a curated, tested MCP server project. An LLM designs the tools: you (the coding agent) edit `plan.yaml`, or `mcpsmith design --provider ...` calls an LLM API. Generated projects use `mcpsmith.runtime` and include tests, CI, a PyPI/MCP Registry publish workflow, `server.json` and a Claude Code plugin.
4
+
5
+ ## Workflow
6
+
7
+ Ask the user which tasks the server should support, then:
8
+
9
+ 1. Website only: `mcpsmith capture <url> -o site.har --host <host>` (user browses, closes the browser), or use a DevTools HAR export.
10
+ 2. `mcpsmith inspect <openapi-or-har path|url>` writes `.mcpsmith/source.json` and `.mcpsmith/digest.md`.
11
+ 3. Read `.mcpsmith/digest.md` and the output of `mcpsmith guide` (tool-design rules).
12
+ 4. `mcpsmith draft` writes a heuristic `.mcpsmith/plan.yaml`.
13
+ 5. Redesign `plan.yaml` yourself: merge or drop endpoints, plain arg names, one-sentence first lines, compact `output.fields`, `example` per tool, `instructions`.
14
+ 6. `mcpsmith validate` (exit 1 on errors).
15
+ 7. `mcpsmith generate -o <dir>`, then `cd <dir> && uv run pytest`.
16
+ 8. `mcpsmith check <dir>` calls every tool live: errors, output size, empty fields. Confirm with the user before it runs non-GET tools.
17
+ 9. Edit the plan and `generate --force` to iterate. Hand edits to `server.py` are overwritten by regenerating.
18
+ 10. Publish: PyPI trusted publisher (workflow `publish.yml`, environment `pypi`), bump `version` in `pyproject.toml` and `server.json`, tag `v*`.
19
+
20
+ Without a shell, use the MCP tools below (`smith_guide`, `smith_inspect`, `smith_draft`, `smith_validate`, `smith_generate`, `smith_check`; paths absolute).
21
+
22
+ ## Skills
23
+
24
+ - `skills/build-mcp-server/SKILL.md`: the full workflow above.
25
+ - `skills/design-mcp-tools/SKILL.md`: checklist for designing or reviewing tools, and how to measure output size.
26
+
27
+ Codex, Cursor, Gemini CLI and others: read these files directly; they are plain Markdown.
28
+
29
+ ## MCP server config
30
+
31
+ ```json
32
+ {"mcpServers": {"mcpsmith": {"command": "uvx", "args": ["mcpsmith", "mcp"]}}}
33
+ ```
34
+
35
+ Claude Code: `claude mcp add mcpsmith -- uvx mcpsmith mcp`, or `/plugin marketplace add sepehr071/mcpsmith` then `/plugin install mcpsmith@mcpsmith`.
36
+
37
+ ## Contributing
38
+
39
+ ```
40
+ uv sync
41
+ uv run pytest # live tests are skipped; run them with -m live
42
+ uv run ruff check .
43
+ uv run ruff format .
44
+ ```
45
+
46
+ - Layout: `src/mcpsmith/` (`model.py` is the data contract: `Source`, `Plan`; `importers/`, `design/`, `codegen/`, `runtime/`, `check.py`, `cli.py`); design notes in `docs/design.md`.
47
+ - Do not rename `model.py` fields without checking every stage that reads them.
48
+ - `mcpsmith.runtime` is imported by every generated server: keep it small and backward compatible.
49
+ - Ruff: line length 120, Python 3.10+.
mcpsmith-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sepehr Radmard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,193 @@
1
+ Metadata-Version: 2.5
2
+ Name: mcpsmith
3
+ Version: 0.1.0
4
+ Summary: Turn an OpenAPI file or a recorded website session into a curated, tested MCP server, with an LLM designing the tools.
5
+ Project-URL: Homepage, https://github.com/sepehr071/mcpsmith
6
+ Project-URL: Issues, https://github.com/sepehr071/mcpsmith/issues
7
+ Author-email: Sepehr Radmard <sepehrr80@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,code-generation,har,llm,mcp,model-context-protocol,openapi
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Code Generators
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: mcp<3,>=2.2
23
+ Requires-Dist: pyyaml>=6
24
+ Provides-Extra: capture
25
+ Requires-Dist: playwright>=1.45; extra == 'capture'
26
+ Provides-Extra: stealth
27
+ Requires-Dist: curl-cffi>=0.16.3; extra == 'stealth'
28
+ Requires-Dist: httpx-curl-cffi>=0.1.5; extra == 'stealth'
29
+ Description-Content-Type: text/markdown
30
+
31
+ <!-- mcp-name: io.github.sepehr071/mcpsmith -->
32
+
33
+ # mcpsmith
34
+
35
+ Turn an OpenAPI/Swagger file, or a website session you recorded in the browser, into a curated, tested MCP server project. An LLM designs the tools; you get ordinary Python code you own.
36
+
37
+ Most generators mirror every endpoint as a tool and hand the model raw JSON, or stop at an OpenAPI spec or API client. mcpsmith designs a few workflow-level tools with plain argument names, descriptions that say when to call what next, and compact output. The input is an OpenAPI file or a HAR recording, so sites with no public API work too. The output is a server project with tests, CI, a PyPI + MCP Registry publish workflow and a Claude Code plugin.
38
+
39
+ ## Quickstart: OpenAPI
40
+
41
+ ```bash
42
+ uvx mcpsmith inspect https://petstore3.swagger.io/api/v3/openapi.json # .mcpsmith/source.json + digest.md
43
+ uvx mcpsmith draft --name petstore-mcp # heuristic .mcpsmith/plan.yaml, no LLM
44
+ # redesign plan.yaml (your coding agent does this, or use `design`, see below)
45
+ uvx mcpsmith validate
46
+ uvx mcpsmith generate -o petstore-mcp
47
+ cd petstore-mcp && uv run pytest
48
+ uvx mcpsmith check . # call every tool live
49
+ claude mcp add petstore-mcp -- uv run --directory "$PWD" petstore-mcp
50
+ ```
51
+
52
+ A spec read from a local file may only have a relative server URL; `validate` then asks you to set an absolute `base_url` in the plan.
53
+
54
+ ## Quickstart: a website without an API
55
+
56
+ ```bash
57
+ pip install "mcpsmith[capture]" && playwright install chromium
58
+ mcpsmith capture https://example.com -o site.har --host example.com # browse, then close the tab
59
+ mcpsmith inspect site.har --host example.com
60
+ mcpsmith draft --name example-mcp
61
+ # redesign plan.yaml, then validate, generate, check as above
62
+ ```
63
+
64
+ While recording, do each thing you want as a tool: search, open a detail page, paginate, apply a filter. Anything you do not click is not in the capture. `--host` (repeatable) keeps only the hosts you list. A DevTools "Save all as HAR" export works in place of `capture`. The recording browser uses `HTTPS_PROXY` when it is set.
65
+
66
+ A HAR holds everything the browser sent and received, including cookies and your personal data: keep it out of git and delete it after `inspect`. `inspect` scrubs what it keeps: an API key or token becomes an `auth` env var with its value dropped, other secret-looking headers and query params are dropped, and emails, phone numbers, JWTs and values under secret or personal field names are masked in examples and test fixtures. This is pattern-based, so read `tests/fixtures/` before you publish a generated server. If a key is a public one the site sends to every visitor (a search or maps key), you may put it in the tool's `fixed` values.
67
+
68
+ ## Use it from your agent
69
+
70
+ No API key needed: your coding agent is the designer.
71
+
72
+ - Claude Code plugin (skills + MCP server): `/plugin marketplace add sepehr071/mcpsmith`, then `/plugin install mcpsmith@mcpsmith`.
73
+ - MCP server only, any client:
74
+ ```json
75
+ {"mcpServers": {"mcpsmith": {"command": "uvx", "args": ["mcpsmith", "mcp"]}}}
76
+ ```
77
+ Tools: `smith_guide`, `smith_inspect`, `smith_draft`, `smith_validate`, `smith_generate`, `smith_check` (paths absolute).
78
+ - Skills: `skills/build-mcp-server` (the whole workflow) and `skills/design-mcp-tools` (design checklist). `AGENTS.md` points other agents (Codex, Cursor, Gemini CLI) at them.
79
+
80
+ Then ask: "Build an MCP server for this OpenAPI file; users should be able to find pets and check stock."
81
+
82
+ ## Let mcpsmith call an LLM
83
+
84
+ ```bash
85
+ uvx mcpsmith design --goal "find products, compare prices, read reviews" --provider anthropic
86
+ ```
87
+
88
+ Providers: `anthropic` (`ANTHROPIC_API_KEY`), `openai` (`OPENAI_API_KEY`), `openrouter` (`OPENROUTER_API_KEY`), `ollama` (no key). `--model` picks the model; `MCPSMITH_MODEL` and `MCPSMITH_BASE_URL` override the model and endpoint. The result is the same `plan.yaml`; review it before `generate`.
89
+
90
+ ## How it works
91
+
92
+ ```
93
+ openapi.yaml | site.har --inspect--> source.json + digest.md
94
+ --draft----> plan.yaml (heuristic starting point)
95
+ your agent edits plan.yaml, or `design` ------> plan.yaml
96
+ --validate-> issues
97
+ --generate-> <name>/ (server project)
98
+ --check----> live report per tool
99
+ ```
100
+
101
+ `Source` is what the API offers; `Plan` is the server to build; code generation reads the plan plus captured responses for test fixtures. A plan, trimmed:
102
+
103
+ ```yaml
104
+ name: shop-mcp
105
+ description: Search products and compare prices on Example Shop.
106
+ prefix: shop
107
+ base_url: https://example.com/api
108
+ env_prefix: SHOP_MCP
109
+ instructions: Search first, then fetch details with the id. Prices are in toman.
110
+ tools:
111
+ - name: shop_search
112
+ title: Search products
113
+ description: Returns matching products with price and stock. Use shop_product for full details.
114
+ endpoint: GET /v2/search
115
+ args:
116
+ - {name: query, type: string, required: true, description: "Search words, e.g. 'laptop'", to: query.q}
117
+ - {name: max_price, type: integer, description: "Upper price limit in toman, e.g. 20000000", to: query.price_max}
118
+ - {name: sort, description: "Result order.", map: {cheapest: price_asc, newest: date_desc}, default: cheapest, to: query.o}
119
+ output:
120
+ root: data.products
121
+ fields: {id: id, title: title_fa, price: price.selling_price, in_stock: stock.available}
122
+ max_items: 10
123
+ example: {query: laptop}
124
+ ```
125
+
126
+ Argument targets (`to:`): `path.<n>`, `query.<n>`, `header.<n>`, `cookie.<n>`, `body`, `body.<a.b.c>`. Output paths use dots, a number indexes a list (`images.0.url`), `[]` maps over a list (`tags[].name`). `map` turns friendly values the model sees into the cryptic ones the API wants.
127
+
128
+ ## What you get
129
+
130
+ ```
131
+ <name>/
132
+ pyproject.toml server.json README.md LICENSE .gitignore mcpsmith.yaml
133
+ src/<package>/server.py # tools, built on mcpsmith.runtime
134
+ tests/ # replay captured responses; one -m live test per tool
135
+ .github/workflows/ # ci.yml, publish.yml (PyPI + MCP Registry)
136
+ .claude-plugin/plugin.json # Claude Code plugin
137
+ skills/<name>/SKILL.md # skill for the generated server
138
+ ```
139
+
140
+ `mcpsmith.yaml` is the plan, so you can regenerate. To publish: add a PyPI trusted publisher (workflow `publish.yml`, environment `pypi`), bump the version in `pyproject.toml` and `server.json`, tag `v*`.
141
+
142
+ ## Runtime features
143
+
144
+ Generated servers import `mcpsmith.runtime`, so a fix there reaches every server on upgrade.
145
+
146
+ - Retries on network errors, timeouts, 429 and 5xx (writes only on 429, so they are never sent twice); `Retry-After` honoured and capped; jitter; concurrency cap.
147
+ - GET response cache, host allowlist, 5 MB body cap.
148
+ - Proxy support: `<P>_PROXY` takes one URL or a comma list (pool). `<P>_BASE_URL` overrides the base URL. System proxy env vars are ignored on purpose.
149
+ - Chrome TLS fingerprint for sites that block plain clients: `pip install "mcpsmith[stealth]"` and `impersonate: true` in the plan. Without the extra it falls back to plain httpx with one warning.
150
+ - Compact output: `shape()` keeps only the planned fields, caps lists (reports the total count), clips long strings, drops nulls.
151
+ - Actionable errors: a 403 suggests setting `<P>_PROXY`, a 401 names the auth env var, 404/429/5xx say what to do next.
152
+ - Auth: bearer, header, query, cookie or basic, read from an env var.
153
+
154
+ ## Drift check
155
+
156
+ `mcpsmith check <project> [--json]` calls every tool with its example arguments and reports errors, output size in characters and output fields that came back empty. Run it nightly in CI to see when an API or site changes. It makes real calls, so tools marked `read_only: false` are skipped unless you pass `--writes`.
157
+
158
+ ## Comparison
159
+
160
+ | | Input | Output | Tool design | Response shaping | Drift check | Open source |
161
+ |---|---|---|---|---|---|---|
162
+ | mcpsmith | OpenAPI, HAR | Python MCP project | LLM-designed plan | per-tool root/fields/max_items | `mcpsmith check` | yes |
163
+ | FastMCP `from_openapi` | OpenAPI | runtime proxy | one tool per endpoint; manual route maps / transforms | raw JSON | no | yes |
164
+ | openapi-mcp-generator | OpenAPI | TypeScript server | one tool per endpoint; `x-mcp` to pick | raw JSON | no | yes |
165
+ | Speakeasy / Gram | OpenAPI | TypeScript or hosted | manual toolsets | experimental | no | Gram yes |
166
+ | Stainless | OpenAPI | npm package | code mode (search + execute) | n/a | no | no |
167
+ | mitmproxy2swagger, har-to-openapi | HAR / traffic | OpenAPI spec | none | none | no | yes |
168
+ | Integuru, reverse-api-engineer | HAR / browsing | API client code, not MCP | none | none | no | yes |
169
+ | Supergood, Wire | site walkthrough | hosted API / MCP | managed | managed | vendor claims | no |
170
+
171
+ Compiled from each project's public docs in October 2026; check them before relying on a cell. FastMCP's own docs say curated servers clearly beat auto-converted ones.
172
+
173
+ ## Limitations
174
+
175
+ - No browser per call: JS challenges and captchas are out of scope. Sites that need them will fail at `check`.
176
+ - A tool maps to one request. Multi-call workflow tools need hand edits to the generated `server.py`, and regenerating overwrites them.
177
+ - The generated project is Python only.
178
+ - A HAR only contains what you did while recording; unrecorded features are not in the plan.
179
+ - Request bodies are sent as JSON; endpoints that only accept `application/x-www-form-urlencoded` or multipart need a hand edit.
180
+ - The plan is trusted input: its text ends up in server instructions and the skill, and `mcpsmith check` runs the generated code. Review a plan written by an LLM from third-party content before you generate and publish it.
181
+ - Alpha (0.1).
182
+
183
+ ## Develop
184
+
185
+ ```bash
186
+ uv sync
187
+ uv run pytest
188
+ uv run ruff check .
189
+ ```
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,163 @@
1
+ <!-- mcp-name: io.github.sepehr071/mcpsmith -->
2
+
3
+ # mcpsmith
4
+
5
+ Turn an OpenAPI/Swagger file, or a website session you recorded in the browser, into a curated, tested MCP server project. An LLM designs the tools; you get ordinary Python code you own.
6
+
7
+ Most generators mirror every endpoint as a tool and hand the model raw JSON, or stop at an OpenAPI spec or API client. mcpsmith designs a few workflow-level tools with plain argument names, descriptions that say when to call what next, and compact output. The input is an OpenAPI file or a HAR recording, so sites with no public API work too. The output is a server project with tests, CI, a PyPI + MCP Registry publish workflow and a Claude Code plugin.
8
+
9
+ ## Quickstart: OpenAPI
10
+
11
+ ```bash
12
+ uvx mcpsmith inspect https://petstore3.swagger.io/api/v3/openapi.json # .mcpsmith/source.json + digest.md
13
+ uvx mcpsmith draft --name petstore-mcp # heuristic .mcpsmith/plan.yaml, no LLM
14
+ # redesign plan.yaml (your coding agent does this, or use `design`, see below)
15
+ uvx mcpsmith validate
16
+ uvx mcpsmith generate -o petstore-mcp
17
+ cd petstore-mcp && uv run pytest
18
+ uvx mcpsmith check . # call every tool live
19
+ claude mcp add petstore-mcp -- uv run --directory "$PWD" petstore-mcp
20
+ ```
21
+
22
+ A spec read from a local file may only have a relative server URL; `validate` then asks you to set an absolute `base_url` in the plan.
23
+
24
+ ## Quickstart: a website without an API
25
+
26
+ ```bash
27
+ pip install "mcpsmith[capture]" && playwright install chromium
28
+ mcpsmith capture https://example.com -o site.har --host example.com # browse, then close the tab
29
+ mcpsmith inspect site.har --host example.com
30
+ mcpsmith draft --name example-mcp
31
+ # redesign plan.yaml, then validate, generate, check as above
32
+ ```
33
+
34
+ While recording, do each thing you want as a tool: search, open a detail page, paginate, apply a filter. Anything you do not click is not in the capture. `--host` (repeatable) keeps only the hosts you list. A DevTools "Save all as HAR" export works in place of `capture`. The recording browser uses `HTTPS_PROXY` when it is set.
35
+
36
+ A HAR holds everything the browser sent and received, including cookies and your personal data: keep it out of git and delete it after `inspect`. `inspect` scrubs what it keeps: an API key or token becomes an `auth` env var with its value dropped, other secret-looking headers and query params are dropped, and emails, phone numbers, JWTs and values under secret or personal field names are masked in examples and test fixtures. This is pattern-based, so read `tests/fixtures/` before you publish a generated server. If a key is a public one the site sends to every visitor (a search or maps key), you may put it in the tool's `fixed` values.
37
+
38
+ ## Use it from your agent
39
+
40
+ No API key needed: your coding agent is the designer.
41
+
42
+ - Claude Code plugin (skills + MCP server): `/plugin marketplace add sepehr071/mcpsmith`, then `/plugin install mcpsmith@mcpsmith`.
43
+ - MCP server only, any client:
44
+ ```json
45
+ {"mcpServers": {"mcpsmith": {"command": "uvx", "args": ["mcpsmith", "mcp"]}}}
46
+ ```
47
+ Tools: `smith_guide`, `smith_inspect`, `smith_draft`, `smith_validate`, `smith_generate`, `smith_check` (paths absolute).
48
+ - Skills: `skills/build-mcp-server` (the whole workflow) and `skills/design-mcp-tools` (design checklist). `AGENTS.md` points other agents (Codex, Cursor, Gemini CLI) at them.
49
+
50
+ Then ask: "Build an MCP server for this OpenAPI file; users should be able to find pets and check stock."
51
+
52
+ ## Let mcpsmith call an LLM
53
+
54
+ ```bash
55
+ uvx mcpsmith design --goal "find products, compare prices, read reviews" --provider anthropic
56
+ ```
57
+
58
+ Providers: `anthropic` (`ANTHROPIC_API_KEY`), `openai` (`OPENAI_API_KEY`), `openrouter` (`OPENROUTER_API_KEY`), `ollama` (no key). `--model` picks the model; `MCPSMITH_MODEL` and `MCPSMITH_BASE_URL` override the model and endpoint. The result is the same `plan.yaml`; review it before `generate`.
59
+
60
+ ## How it works
61
+
62
+ ```
63
+ openapi.yaml | site.har --inspect--> source.json + digest.md
64
+ --draft----> plan.yaml (heuristic starting point)
65
+ your agent edits plan.yaml, or `design` ------> plan.yaml
66
+ --validate-> issues
67
+ --generate-> <name>/ (server project)
68
+ --check----> live report per tool
69
+ ```
70
+
71
+ `Source` is what the API offers; `Plan` is the server to build; code generation reads the plan plus captured responses for test fixtures. A plan, trimmed:
72
+
73
+ ```yaml
74
+ name: shop-mcp
75
+ description: Search products and compare prices on Example Shop.
76
+ prefix: shop
77
+ base_url: https://example.com/api
78
+ env_prefix: SHOP_MCP
79
+ instructions: Search first, then fetch details with the id. Prices are in toman.
80
+ tools:
81
+ - name: shop_search
82
+ title: Search products
83
+ description: Returns matching products with price and stock. Use shop_product for full details.
84
+ endpoint: GET /v2/search
85
+ args:
86
+ - {name: query, type: string, required: true, description: "Search words, e.g. 'laptop'", to: query.q}
87
+ - {name: max_price, type: integer, description: "Upper price limit in toman, e.g. 20000000", to: query.price_max}
88
+ - {name: sort, description: "Result order.", map: {cheapest: price_asc, newest: date_desc}, default: cheapest, to: query.o}
89
+ output:
90
+ root: data.products
91
+ fields: {id: id, title: title_fa, price: price.selling_price, in_stock: stock.available}
92
+ max_items: 10
93
+ example: {query: laptop}
94
+ ```
95
+
96
+ Argument targets (`to:`): `path.<n>`, `query.<n>`, `header.<n>`, `cookie.<n>`, `body`, `body.<a.b.c>`. Output paths use dots, a number indexes a list (`images.0.url`), `[]` maps over a list (`tags[].name`). `map` turns friendly values the model sees into the cryptic ones the API wants.
97
+
98
+ ## What you get
99
+
100
+ ```
101
+ <name>/
102
+ pyproject.toml server.json README.md LICENSE .gitignore mcpsmith.yaml
103
+ src/<package>/server.py # tools, built on mcpsmith.runtime
104
+ tests/ # replay captured responses; one -m live test per tool
105
+ .github/workflows/ # ci.yml, publish.yml (PyPI + MCP Registry)
106
+ .claude-plugin/plugin.json # Claude Code plugin
107
+ skills/<name>/SKILL.md # skill for the generated server
108
+ ```
109
+
110
+ `mcpsmith.yaml` is the plan, so you can regenerate. To publish: add a PyPI trusted publisher (workflow `publish.yml`, environment `pypi`), bump the version in `pyproject.toml` and `server.json`, tag `v*`.
111
+
112
+ ## Runtime features
113
+
114
+ Generated servers import `mcpsmith.runtime`, so a fix there reaches every server on upgrade.
115
+
116
+ - Retries on network errors, timeouts, 429 and 5xx (writes only on 429, so they are never sent twice); `Retry-After` honoured and capped; jitter; concurrency cap.
117
+ - GET response cache, host allowlist, 5 MB body cap.
118
+ - Proxy support: `<P>_PROXY` takes one URL or a comma list (pool). `<P>_BASE_URL` overrides the base URL. System proxy env vars are ignored on purpose.
119
+ - Chrome TLS fingerprint for sites that block plain clients: `pip install "mcpsmith[stealth]"` and `impersonate: true` in the plan. Without the extra it falls back to plain httpx with one warning.
120
+ - Compact output: `shape()` keeps only the planned fields, caps lists (reports the total count), clips long strings, drops nulls.
121
+ - Actionable errors: a 403 suggests setting `<P>_PROXY`, a 401 names the auth env var, 404/429/5xx say what to do next.
122
+ - Auth: bearer, header, query, cookie or basic, read from an env var.
123
+
124
+ ## Drift check
125
+
126
+ `mcpsmith check <project> [--json]` calls every tool with its example arguments and reports errors, output size in characters and output fields that came back empty. Run it nightly in CI to see when an API or site changes. It makes real calls, so tools marked `read_only: false` are skipped unless you pass `--writes`.
127
+
128
+ ## Comparison
129
+
130
+ | | Input | Output | Tool design | Response shaping | Drift check | Open source |
131
+ |---|---|---|---|---|---|---|
132
+ | mcpsmith | OpenAPI, HAR | Python MCP project | LLM-designed plan | per-tool root/fields/max_items | `mcpsmith check` | yes |
133
+ | FastMCP `from_openapi` | OpenAPI | runtime proxy | one tool per endpoint; manual route maps / transforms | raw JSON | no | yes |
134
+ | openapi-mcp-generator | OpenAPI | TypeScript server | one tool per endpoint; `x-mcp` to pick | raw JSON | no | yes |
135
+ | Speakeasy / Gram | OpenAPI | TypeScript or hosted | manual toolsets | experimental | no | Gram yes |
136
+ | Stainless | OpenAPI | npm package | code mode (search + execute) | n/a | no | no |
137
+ | mitmproxy2swagger, har-to-openapi | HAR / traffic | OpenAPI spec | none | none | no | yes |
138
+ | Integuru, reverse-api-engineer | HAR / browsing | API client code, not MCP | none | none | no | yes |
139
+ | Supergood, Wire | site walkthrough | hosted API / MCP | managed | managed | vendor claims | no |
140
+
141
+ Compiled from each project's public docs in October 2026; check them before relying on a cell. FastMCP's own docs say curated servers clearly beat auto-converted ones.
142
+
143
+ ## Limitations
144
+
145
+ - No browser per call: JS challenges and captchas are out of scope. Sites that need them will fail at `check`.
146
+ - A tool maps to one request. Multi-call workflow tools need hand edits to the generated `server.py`, and regenerating overwrites them.
147
+ - The generated project is Python only.
148
+ - A HAR only contains what you did while recording; unrecorded features are not in the plan.
149
+ - Request bodies are sent as JSON; endpoints that only accept `application/x-www-form-urlencoded` or multipart need a hand edit.
150
+ - The plan is trusted input: its text ends up in server instructions and the skill, and `mcpsmith check` runs the generated code. Review a plan written by an LLM from third-party content before you generate and publish it.
151
+ - Alpha (0.1).
152
+
153
+ ## Develop
154
+
155
+ ```bash
156
+ uv sync
157
+ uv run pytest
158
+ uv run ruff check .
159
+ ```
160
+
161
+ ## License
162
+
163
+ MIT