<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Furkan </title>
    <description>The latest articles on DEV Community by Furkan  (@furkan708).</description>
    <link>https://dev.to/furkan708</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4099603%2F4bb4ed9c-0d63-4420-bff2-de607a5434b2.jpg</url>
      <title>DEV Community: Furkan </title>
      <link>https://dev.to/furkan708</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/furkan708"/>
    <language>en</language>
    <item>
      <title>I connected a real weather API to Claude in 3 commands — and the community broke my tool in the best way</title>
      <dc:creator>Furkan </dc:creator>
      <pubDate>Sat, 29 Aug 2026 00:06:54 +0000</pubDate>
      <link>https://dev.to/furkan708/i-connected-a-real-weather-api-to-claude-in-3-commands-and-the-community-broke-my-tool-in-the-3jid</link>
      <guid>https://dev.to/furkan708/i-connected-a-real-weather-api-to-claude-in-3-commands-and-the-community-broke-my-tool-in-the-3jid</guid>
      <description>&lt;p&gt;How mcpify went from "it works on my examples" to surviving the live api.weather.gov spec — a story in OpenAPI archaeology.&lt;/p&gt;

&lt;p&gt;The problem nobody warns you about&lt;/p&gt;

&lt;p&gt;Every tutorial about connecting Claude (or Cursor, or any agent) to your own REST API ends the same way: "and now you write a custom MCP server."&lt;/p&gt;

&lt;p&gt;If your API has 40 endpoints, that's 40 tool definitions. Parameter schemas. Validation. Error handling. Auth plumbing. And then your API changes next sprint — because real APIs change next sprint — and you do it again.&lt;/p&gt;

&lt;p&gt;Here's the thing though: if your API has an OpenAPI document (Swagger), all the information an MCP server needs already exists. The paths, the parameter types, the required fields, the enums, the descriptions you wrote for humans. Writing a second, hand-maintained version of the same contract is busywork.&lt;/p&gt;

&lt;p&gt;That's why I built mcpify: point it at any OpenAPI 3.x spec — file or URL — and it serves the whole API as an MCP server over stdio. No codegen. No wrapper repo. One command.&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;pipx install mcpify-openapi&lt;/p&gt;

&lt;p&gt;mcpify list &lt;a href="https://api.weather.gov/openapi.json" rel="noopener noreferrer"&gt;https://api.weather.gov/openapi.json&lt;/a&gt; --read-only&lt;br&gt;
mcpify serve &lt;a href="https://api.weather.gov/openapi.json" rel="noopener noreferrer"&gt;https://api.weather.gov/openapi.json&lt;/a&gt; --read-only&lt;br&gt;
That second command wires 69 real tools into any MCP client — every National Weather Service endpoint, with typed parameters and enum'd values the model picks from a list instead of free-typing.&lt;/p&gt;

&lt;p&gt;"It works on my examples" — famous last words&lt;/p&gt;

&lt;p&gt;The first version was honestly naive. I tested it against the usual petstore-style specs and called it done. Then I did something better than writing more examples myself: I published it and let people throw real APIs at it.&lt;/p&gt;

&lt;p&gt;They found the gaps fast:&lt;/p&gt;

&lt;p&gt;$ref'd parameter schemas crashed it. The live weather.gov spec references #/components/schemas/... from its parameters — real-world OpenAPI does this everywhere. My resolver was being handed an empty spec. One line-level bug, every "serious" API dead on arrival.&lt;br&gt;
GET-only isn't side-effect-free. A "read-only mode" that filters by HTTP method happily exposes GET /admin/reset-cache. Oops.&lt;br&gt;
Circular $refs, multipart bodies, server URL variables, relative base URLs, 300KB responses — each one a small landmine that toy specs never step on.&lt;br&gt;
The fix wasn't just patching these — it was building a hostile-spec corpus from published failure studies (there's a great arXiv paper on REST→MCP generation across 18 real APIs — its top-3 failure categories are all base-URL and auth-declaration problems). Every landmine is now a pinned regression test. The weather.gov spec loads in CI on every push. 82 tests total, mypy strict, ruff, CodeQL, Linux + Windows matrices.&lt;/p&gt;

&lt;p&gt;That's the honest version of "production-grade": not a vibe, a checklist you re-run.&lt;/p&gt;

&lt;p&gt;The parts I'm proudest of&lt;/p&gt;

&lt;p&gt;The policy layer. After the GET-mutation feedback, --read-only got teeth:&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;mcpify serve api.json --read-only --deny '/admin' --allow '/search'&lt;br&gt;
--deny hides paths no matter what (so that mutating GET is gone), --allow re-includes read-style POST endpoints (search-with-a-body is a read). Deny always wins — least surprise for whoever configures it.&lt;/p&gt;

&lt;p&gt;Token-friendly scoping. Every tool description eats context tokens on every turn. A 200-endpoint API as 200 tools is how you get billed for a model re-reading a phone book. --tag payments, --include /v1/orders, --exclude /internal keep the surface to what the agent actually needs.&lt;/p&gt;

&lt;p&gt;Secrets stay out of band. --auth-env API_TOKEN --auth-style bearer — the credential lives in the environment, gets injected at call time, and never appears in tool schemas, configs, or logs. The Authorization header param is stripped from advertised schemas so the model can't inject its own.&lt;/p&gt;

&lt;p&gt;One tag = full release. Pushing v1.0.4 ships PyPI + the official MCP Registry (io.github.furkan708/mcpify) + a GitHub Release + a GHCR container image, via OIDC, no stored tokens.&lt;/p&gt;

&lt;p&gt;Try it in 60 seconds&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;h1&gt;
  
  
  zero-install runner (uv):
&lt;/h1&gt;

&lt;p&gt;uvx --from mcpify-openapi mcpify list ./openapi.json --read-only&lt;/p&gt;

&lt;h1&gt;
  
  
  or install:
&lt;/h1&gt;

&lt;p&gt;pipx install mcpify-openapi&lt;/p&gt;

&lt;h1&gt;
  
  
  wire it into Claude Desktop (claude_desktop_config.json):
&lt;/h1&gt;

&lt;p&gt;{&lt;br&gt;
  "mcpServers": {&lt;br&gt;
    "my-api": {&lt;br&gt;
      "command": "mcpify",&lt;br&gt;
      "args": ["serve", "./openapi.json", "--read-only"]&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Or as a container: docker run -i ghcr.io/furkan708/mcpify:latest serve ./spec.json --read-only&lt;/p&gt;

&lt;p&gt;What it deliberately doesn't do&lt;/p&gt;

&lt;p&gt;Spec-less APIs — if there's no OpenAPI document, mcpify has nothing to project. (Garbage-in protection for both of us.)&lt;br&gt;
Retries / rate limiting / circuit breakers — retrying a non-idempotent POST can duplicate side effects; those belong at your gateway, where they're observable. mcpify limits blast radius instead: read-only, deny policies, timeouts, truncated responses.&lt;br&gt;
Webhooks &amp;amp; streaming — MCP-over-stdio is request/response today; remote transports are on the roadmap.&lt;br&gt;
Being upfront about limits is part of the trust contract, same as the tests.&lt;/p&gt;

&lt;p&gt;Repo: github.com/furkan708/mcpify · PyPI: mcpify-openapi · Docs: USAGE · Audit checklist&lt;/p&gt;

&lt;p&gt;If you point it at a real API — your company's internal service, a public one, whatever breaks — I want to hear what blows up. Every crash report so far has made it better, and there's a good-first-issue list if you'd rather build than break.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
