惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tenable Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
L
LINUX DO - 热门话题
C
Cyber Attacks, Cyber Crime and Cyber Security
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
H
Hacker News: Front Page
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
Scott Helme
Scott Helme
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyberwarzone
Cyberwarzone
Microsoft Security Blog
Microsoft Security Blog
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
Cloudbric
Cloudbric
Simon Willison's Weblog
Simon Willison's Weblog
A
Arctic Wolf
云风的 BLOG
云风的 BLOG
V
Vulnerabilities – Threatpost
Stack Overflow Blog
Stack Overflow Blog
T
Tor Project blog
O
OpenAI News
B
Blog RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
The Exploit Database - CXSecurity.com
MyScale Blog
MyScale Blog
罗磊的独立博客
美团技术团队
博客园 - 聂微东
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
PCI Perspectives
PCI Perspectives
P
Privacy International News Feed
C
Cybersecurity and Infrastructure Security Agency CISA
Recorded Future
Recorded Future
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
Security Archives - TechRepublic
Security Archives - TechRepublic
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Blog — PlanetScale
Blog — PlanetScale

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I Built openapi-mcp-gateway: Multi-Spec OpenAPI-to-MCP With Real OAuth2 In Python
MrOops · 2026-05-10 · via DEV Community

I Built openapi-mcp-gateway: Multi-Spec OpenAPI-to-MCP With Real OAuth2 In Python

This gateway started as a demo. The job was to turn our company's OpenAPI spec into an MCP server so non-technical product folks could try the API through Claude Desktop. The naive version came together quickly.

Then the demo grew. For a customer-support-style agent to be useful, it needed to chain our product API with the internal issue tracker, and both gate access on the user's identity, not a shared service token. The audience was non-technical, so streamable HTTP was the floor. But I did not know what the eventual production client would be, so I wanted stdio and SSE on the same binary as well. And because the spec was actively changing, I needed the MCP layer to track it automatically rather than be hand-maintained.

By the time everything ran stably (multi-API, real per-user OAuth2, all three MCP transports, auto-regenerated from the spec), I had built openapi-mcp-gateway.

It is a Python service that turns OpenAPI specs into MCP servers, mounts as many of them as you want in one process, and does real per-user OAuth2 with token relay. You point it at a YAML and it runs.

Try It

uvx openapi-mcp-gateway --spec https://petstore3.swagger.io/api/v3/openapi.json --name petstore
# MCP server live at http://127.0.0.1:8000/petstore/mcp

Enter fullscreen mode Exit fullscreen mode

Or add it as a dependency:

uv add openapi-mcp-gateway

Enter fullscreen mode Exit fullscreen mode

Connect from Claude Desktop, Cursor, Cline, or any other MCP client. Streamable HTTP, SSE, and stdio are all supported. Python 3.11+.

What The Gateway Actually Does

Three things, each shown in code.

1. Multiple APIs In One Process

Most agent tasks touch more than one API. GitHub for repo lookups, your internal product API for the actual work, an external CRM. Point a single YAML at all of them:

# servers.yml
host: 0.0.0.0
port: 8000
url: http://localhost:8000

servers:
  - name: petstore
    spec: https://petstore3.swagger.io/api/v3/openapi.json

  - name: github
    spec: https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json
    auth:
      type: bearer
      token: ${GITHUB_TOKEN}
    policy:
      allow: ["GET /repos/*", "GET /users/*"]
      deny:  ["GET /repos/*/actions/secrets*"]

  - name: asana
    spec: https://raw.githubusercontent.com/Asana/openapi/master/defs/asana_oas.yaml
    auth:
      type: oauth2
      client_id: ${ASANA_CLIENT_ID}
      client_secret: ${ASANA_CLIENT_SECRET}
      scopes: [openid, email, users:read, workspaces:read]

Enter fullscreen mode Exit fullscreen mode

uvx openapi-mcp-gateway --config servers.yml

Enter fullscreen mode Exit fullscreen mode

Three MCP servers at /petstore/mcp, /github/mcp, /asana/mcp. Each with its own auth. Each independently filterable with policy.allow / policy.deny, so you do not blast every endpoint of every spec at the model.

Visually, this YAML produces:

Multi-API gateway topology: one process, three mount paths, three different auth backends, three different upstream APIs

One process, three mount paths, three different auth backends, three different upstream identities. None of them leak into each other.

2. Real Per-User OAuth2 (Token Relay)

This is the constraint that drove most of the design. When a user opens Claude Desktop and connects to one of the mounted servers:

OAuth2 authorization_code with token relay: gateway as both OAuth Server to MCP client and OAuth Client to upstream API

The gateway plays two roles at once, acting as an OAuth Authorization Server to the MCP client and as an OAuth Client to the upstream API. It mints its own MCP-scoped tokens with their own TTLs and revocation, and keeps a private mapping from those tokens to the upstream tokens.

The result is the part that matters. The MCP client never holds a credential for an API it does not know about, and the upstream API's audit log shows the actual end user.

And because every mounted server has its own auth config, one gateway process can run several different OAuth setups in parallel: Asana OAuth on /asana/mcp, GitHub bearer on /github/mcp, your internal OAuth on /myapp/mcp, all at once. Three different upstream identities, three independent OAuth flows, no cross-talk in the token store, the auth resolver, or the request path. The Asana token issued to one user cannot be confused with the GitHub bearer used to look up a repo. Each (server, user) pair lives in its own namespace.

For service-to-service calls, client_credentials is also supported, with lazy fetch and concurrent-refresh dedup under an asyncio.Lock so N concurrent tool calls hitting the gateway at expiry produce exactly one IdP request. Different shape, different OAuthFlowHandler.

3. FastAPI-Native @mcp_tool

Beyond raw OpenAPI specs, the gateway also takes a live FastAPI app as input. If you already have one, decorate the routes you want exposed:

from fastapi import FastAPI
from openapi_mcp_gateway import Gateway, mcp_tool

app = FastAPI()

@app.get("/items/{item_id}")
@mcp_tool()
def read_item(item_id: int):
    return {"id": item_id}

@app.get("/internal/health")  # not decorated, not exposed
def health():
    return {"ok": True}

Gateway.from_fastapi(app, name="myapp").run()

Enter fullscreen mode Exit fullscreen mode

Tool calls run in-process through httpx.ASGITransport. No localhost roundtrip, no parallel spec, no separate uvicorn. Auth is auto-detected from the app's securitySchemes.

How It Compares To Existing Tools

I did the homework, so you do not have to. As of May 2026, here is the OpenAPI-to-MCP converter landscape (tools whose primary job is "take an OpenAPI spec, produce an MCP server"):

mroops0111/openapi-mcp-gateway fastapi_mcp awslabs/mcp ivo-toby harsha-iiiv ckanthony
Language Python Python Python TS TS (codegen) Go
Input OpenAPI or FastAPI app FastAPI app only OpenAPI OpenAPI OpenAPI OpenAPI
Multi-spec in one process Yes (YAML) No Yes No No No
OAuth2 authorization_code w/ relay Yes Yes Cognito only Yes No No
OAuth2 client_credentials Yes (lazy + lock) Not documented No Yes Yes No
stdio + SSE + Streamable HTTP All three SSE + StrHTTP stdio Partial All three Single port
FastAPI-native decorator Yes Whole-app only No No No No
Pluggable Redis token store Yes No No No No No

Reading guide:

  • If your only input is a FastAPI app, fastapi_mcp is more focused than mine. The in-process ASGI trick is its native idea, and I borrowed it for @mcp_tool.
  • If you need multi-spec on AWS and Cognito is your auth, awslabs/mcp is purpose-built for that.
  • If you want a TypeScript runtime, ivo-toby/mcp-openapi-server is the closest analogue.
  • If you want a generated Node project you control end-to-end, harsha-iiiv/openapi-mcp-generator is the right shape.
  • If you want a Python service you point at a YAML, that hosts several specs at once, that does both OAuth2 flows on real upstream providers (not just Cognito), and that has a decorator for the FastAPI app you probably already have, this gateway is for you.

Concretely, this gateway tends to be the right fit in three situations:

  • Internal agents that have to touch several in-house APIs. Customer support, finance ops, IT helpdesk. The agent needs your product API plus your issue tracker plus maybe your CRM, each with its own auth. One process, several mounts, no inter-service leakage.
  • B2B APIs where actions need to happen as the actual end user. Signing a contract, moving money, closing a ticket on someone's behalf. Anything where the audit log on the upstream side has to show the human, not a shared service account. The token relay handles the per-user identity end to end.
  • Demo or PoC stage with a moving spec. The OpenAPI spec is still evolving, you do not yet know what the production MCP client will be, and you do not want to hand-maintain an MCP server in parallel. Point the gateway at the spec, get all three transports for free, regenerate every time the spec changes.

What Is And Is Not There Yet

Shipping today: OAuth2 authorization_code with token relay, OAuth2 client_credentials with concurrency primitives, multi-server in one process (each with independent auth), FastAPI-native @mcp_tool, operation filtering (allow / deny / marked_only), Redis token store, all three MCP transports.

On the roadmap, in case any of these would unblock you:

  • Flexible OAuth2 scope mapping. Today, upstream scopes pass through to MCP one-to-one. Some setups need to expose only a subset, alias names, or group several upstream scopes under one MCP-side scope. Configurable in YAML, per server.
  • Merging multiple OpenAPI specs into one MCP server. Today one spec produces one mounted server. Some upstream APIs split a single product's docs across several spec files (by tag, by version, by section), and forcing the agent to pick across N mount paths for what is logically one API is awkward. Want a specs: list that the gateway combines into a single MCP server.
  • MCP primitives beyond tools, with per-operation YAML overrides. Today every operation in your spec becomes an MCP tool. MCP also has resources, prompts, and sampling, and not every operation is best modelled as a tool (GET /users/{id} is more naturally a resource than a tool). Want a YAML override per operation, which lets you choose the MCP primitive, rename it, hide it, or reshape its inputs.
  • Dynamic tool exposure (skill-style discovery). For large APIs with hundreds of operations, registering every operation as its own tool blows the agent's context window before the agent has done anything. Want an opt-in mode where the gateway exposes only three meta-tools (list, get, call), and the agent fetches operation details on demand. Same pattern as agent skills.

If any of these are blocking you, please open an issue with the shape of your problem. Concrete use cases drive the design more than my guesses.

Closing

This is a personal open-source side project, not anything I deploy at work. The constraints came from the kinds of agent flows I think about because of my dayjob (a B2B e-signature API), but the gateway itself is independent of that. Sharing it here in case the situations above sound like yours.