← Back to Skills Marketplace
lrg913427-dot

Api Bridge

by lrg913427-dot · GitHub ↗ · v2.0.0 · MIT-0
cross-platform ✓ Security Clean
43
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install gavin-api-bridge
Description
Generate API integrations from OpenAPI/Swagger specs. Auto-create MCP servers, API clients, and webhook handlers. Use when user wants to connect to a REST AP...
README (SKILL.md)

API Bridge

Generate API integrations from OpenAPI/Swagger specs — MCP servers, API clients, and webhook handlers.

When to Use

Activate this skill when the user:

  • Says "connect to this API", "integrate with X", "build an API client"
  • Wants to create an MCP server for a REST API
  • Has an OpenAPI/Swagger spec and wants code generated
  • Needs a webhook handler for API events
  • Wants to scaffold an API integration quickly
  • Mentions "API key", "REST endpoint", or "webhook"

What This Skill Does

When a user wants to connect to an API, this skill:

  1. Finds or fetches the OpenAPI/Swagger spec
  2. Generates a working MCP server or API client
  3. Handles auth (API key, OAuth2, Bearer token)
  4. Includes error handling, rate limiting, and retries
  5. Produces ready-to-use code

Quick Start

From OpenAPI Spec URL

# Fetch the spec
curl -s https://api.example.com/openapi.json > /tmp/api-spec.json

# Generate MCP server
# (Use the steps below)

From Existing API Documentation

If no OpenAPI spec exists, create one from the API docs:

  1. Identify base URL and endpoints
  2. Create a minimal OpenAPI 3.0 spec
  3. Generate the integration

Step 1: Parse the Spec

import json

with open('api-spec.json') as f:
    spec = json.load(f)

info = spec.get('info', {})
base_url = spec.get('servers', [{}])[0].get('url', '')
paths = spec.get('paths', {})

print(f"API: {info.get('title')}")
print(f"Version: {info.get('version')}")
print(f"Base URL: {base_url}")
print(f"Endpoints: {len(paths)}")

# List all endpoints
for path, methods in paths.items():
    for method in methods:
        if method in ['get', 'post', 'put', 'patch', 'delete']:
            print(f"  {method.upper()} {path}")

Step 2: Generate MCP Server (Python)

# mcp_server.py - Generated from OpenAPI spec
import os
import json
import httpx
from mcp.server import Server
from mcp.types import Tool, TextContent

app = Server("api-name")

BASE_URL = "https://api.example.com"
API_KEY = os.environ.get("API_KEY", "")

@app.tool()
async def list_items(limit: int = 10) -> str:
    """List items from the API."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{BASE_URL}/items",
            headers={"Authorization": f"Bearer {API_KEY}"},
            params={"limit": limit},
        )
        resp.raise_for_status()
        return json.dumps(resp.json(), indent=2)

@app.tool()
async def get_item(item_id: str) -> str:
    """Get a single item by ID."""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{BASE_URL}/items/{item_id}",
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        resp.raise_for_status()
        return json.dumps(resp.json(), indent=2)

@app.tool()
async def create_item(name: str, description: str = "") -> str:
    """Create a new item."""
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{BASE_URL}/items",
            headers={"Authorization": f"Bearer {API_KEY}"},
            json={"name": name, "description": description},
        )
        resp.raise_for_status()
        return json.dumps(resp.json(), indent=2)

Step 3: Add Rate Limiting

import asyncio
from collections import deque
import time

class RateLimiter:
    def __init__(self, max_requests: int = 100, window: int = 60):
        self.max_requests = max_requests
        self.window = window
        self.timestamps = deque()

    async def acquire(self):
        now = time.time()
        while self.timestamps and now - self.timestamps[0] > self.window:
            self.timestamps.popleft()

        if len(self.timestamps) >= self.max_requests:
            wait = self.window - (now - self.timestamps[0])
            await asyncio.sleep(wait)

        self.timestamps.append(time.time())

rate_limiter = RateLimiter(max_requests=100, window=60)

Step 4: Add Retry Logic

import httpx
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=1, max=10),
)
async def api_request(method: str, path: str, **kwargs) -> dict:
    """Make an API request with retry logic."""
    async with httpx.AsyncClient() as client:
        resp = await client.request(
            method,
            f"{BASE_URL}{path}",
            headers={"Authorization": f"Bearer {API_KEY}"},
            **kwargs,
        )
        resp.raise_for_status()
        return resp.json()

Generate Python API Client

"""API client generated from OpenAPI spec."""

import httpx
from typing import Optional, Dict, Any


class APIClient:
    def __init__(self, base_url: str, api_key: str = ""):
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self._client = httpx.AsyncClient(
            base_url=self.base_url,
            headers={
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
            },
            timeout=30.0,
        )

    async def close(self):
        await self._client.aclose()

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        await self.close()

    async def _request(
        self,
        method: str,
        path: str,
        params: Optional[Dict] = None,
        json: Optional[Dict] = None,
    ) -> Any:
        resp = await self._client.request(method, path, params=params, json=json)
        resp.raise_for_status()
        return resp.json()

    # Generated methods from OpenAPI spec
    async def list_items(self, limit: int = 10) -> list:
        return await self._request("GET", "/items", params={"limit": limit})

    async def get_item(self, item_id: str) -> dict:
        return await self._request("GET", f"/items/{item_id}")

    async def create_item(self, name: str, **kwargs) -> dict:
        return await self._request("POST", "/items", json={"name": name, **kwargs})

    async def update_item(self, item_id: str, **kwargs) -> dict:
        return await self._request("PATCH", f"/items/{item_id}", json=kwargs)

    async def delete_item(self, item_id: str) -> None:
        await self._request("DELETE", f"/items/{item_id}")

Generate Webhook Handler

"""Webhook handler for API events."""

from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib

app = FastAPI()
WEBHOOK_SECRET = os.environ.get("WEBHOOK_SECRET", "")

@app.post("/webhook")
async def handle_webhook(request: Request):
    # Verify signature
    body = await request.body()
    signature = request.headers.get("X-Signature", "")

    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        body,
        hashlib.sha256,
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        raise HTTPException(status_code=401, detail="Invalid signature")

    payload = await request.json()
    event_type = payload.get("event_type")

    if event_type == "item.created":
        await handle_item_created(payload)
    elif event_type == "item.updated":
        await handle_item_updated(payload)
    elif event_type == "item.deleted":
        await handle_item_deleted(payload)

    return {"status": "ok"}

Common API Patterns

OAuth2 Flow

async def get_oauth_token(
    client_id: str,
    client_secret: str,
    token_url: str,
) -> str:
    """Get OAuth2 access token."""
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            token_url,
            data={
                "grant_type": "client_credentials",
                "client_id": client_id,
                "client_secret": client_secret,
            },
        )
        resp.raise_for_status()
        return resp.json()["access_token"]

Pagination

async def list_all_items(api_client) -> list:
    """List all items with automatic pagination."""
    all_items = []
    cursor = None

    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor

        result = await api_client._request("GET", "/items", params=params)
        all_items.extend(result["data"])

        cursor = result.get("next_cursor")
        if not cursor:
            break

    return all_items

File Upload

async def upload_file(api_client, file_path: str) -> dict:
    """Upload a file to the API."""
    async with httpx.AsyncClient() as client:
        with open(file_path, "rb") as f:
            resp = await client.post(
                f"{api_client.base_url}/files",
                headers={"Authorization": f"Bearer {api_client.api_key}"},
                files={"file": (file_path, f, "application/octet-stream")},
            )
            resp.raise_for_status()
            return resp.json()

OpenAPI Spec Sources

Common places to find OpenAPI specs:

API Spec URL
GitHub https://api.github.com/openapi.json
Stripe https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json
Twilio https://github.com/twilio/twilio-oai/blob/main/spec/yaml/twilio_api_v2010.yaml
OpenAI https://github.com/openai/openai-openapi/blob/main/openapi.yaml
Notion https://github.com/makenotion/notion-sdk-js/blob/main/api-openapi.yml

Or search: site:github.com "openapi" OR "swagger" "api-name"

Pitfalls

  • Spec version — Check if it's OpenAPI 2.0 (Swagger) or 3.0+ (different format)
  • Auth types — API key vs Bearer token vs OAuth2 vs Basic auth (check spec's securitySchemes)
  • Rate limits — Always implement rate limiting; check API docs for limits
  • Pagination — Different APIs use different patterns (cursor, offset, page, link header)
  • Content types — Some APIs use application/x-www-form-urlencoded instead of JSON
  • Webhook verification — Always verify signatures; don't trust raw payloads
  • Error handling — Check API docs for error codes and retry-after headers

Verification

After generating the integration:

  1. Test with a simple GET request (list endpoint)
  2. Verify auth works (check response code)
  3. Test error handling (invalid ID, missing auth)
  4. Check rate limiting (exceed limit, verify backoff)
  5. Test pagination (if applicable)
Usage Guidance
This skill appears safe to install as an instruction-only scaffolding helper. Before running generated code, review the endpoints it exposes, use low-privilege credentials, avoid enabling unnecessary write/delete actions, and add authentication or webhook signature checks for any generated server.
Capability Analysis
Type: OpenClaw Skill Name: gavin-api-bridge Version: 2.0.0 The skill bundle provides boilerplate code and instructions for generating API integrations, MCP servers, and webhook handlers from OpenAPI specifications. The code snippets in SKILL.md follow standard practices for API clients, including environment variable usage for secrets, rate limiting, and signature verification for webhooks, with no evidence of malicious intent or data exfiltration.
Capability Tags
cryptorequires-oauth-tokenrequires-sensitive-credentials
Capability Assessment
Purpose & Capability
The stated purpose matches the documented behavior: generating OpenAPI/Swagger-based MCP servers, API clients, and webhook handlers. Users should note that the generated tools can make live API calls, including write operations.
Instruction Scope
The examples are user-directed scaffolding instructions rather than automatic execution, but they include generic generated tools that may perform authenticated API requests. Generated endpoints should be reviewed before use.
Install Mechanism
No install spec, binaries, helper code, or package dependencies are provided; the artifact set is instruction-only and the static scan had no code to analyze.
Credentials
API keys, OAuth tokens, and bearer tokens are expected for this kind of integration, but the registry requirements do not declare required credentials or environment variables. This appears under-declared rather than hidden.
Persistence & Privilege
No autorun, background persistence, protected-path writes, or post-install execution are shown. Generated MCP servers or webhook handlers would run only if the user deploys them.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install gavin-api-bridge
  3. After installation, invoke the skill by name or use /gavin-api-bridge
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v2.0.0
Major upgrade: Automated generation of MCP servers, API clients, and webhook handlers from OpenAPI/Swagger specs. - Generates ready-to-use MCP server code, Python API clients, and secure webhook handlers. - Handles authentication (API key, OAuth2, Bearer token), rate limiting, and retries out-of-the-box. - Works from both existing OpenAPI/Swagger specs or minimal specs created from API docs. - Clear guidance for users on when and how to activate or use the skill. - Designed for fast, robust scaffolding of REST API integrations.
Metadata
Slug gavin-api-bridge
Version 2.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Api Bridge?

Generate API integrations from OpenAPI/Swagger specs. Auto-create MCP servers, API clients, and webhook handlers. Use when user wants to connect to a REST AP... It is an AI Agent Skill for Claude Code / OpenClaw, with 43 downloads so far.

How do I install Api Bridge?

Run "/install gavin-api-bridge" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Api Bridge free?

Yes, Api Bridge is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Api Bridge support?

Api Bridge is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Api Bridge?

It is built and maintained by lrg913427-dot (@lrg913427-dot); the current version is v2.0.0.

💬 Comments