OpenAPI ⇢ Hyperia Server

Automatically wrap any REST/HTTP service described by an OpenAPI 3.0 / 3.1 spec and expose it as a fully‑featured Hyperia MCP server—no hand‑rolled glue code required.

Added in v2.0 (major revamp v2.2) – point Hyperia at your .json, hand it an httpx.AsyncClient, and receive tools/resources/prompts ready for LLMs.


1 Quick Start

import httpx, asyncio
from hyperia import Hyperia

spec = "https://api.example.com/openapi.json"  # or dict loaded from file
spec = httpx.get(spec).json()

api = httpx.AsyncClient(base_url="https://api.example.com")

mcp = Hyperia.from_openapi(
    openapi_spec = spec,
    client       = api,
    name         = "ExampleAPI",  # optional, appears in roots
    timeout      = 8.0,            # secs per request
)

if __name__ == "__main__":
    mcp.run(transport="streamable-http", port=9000)

Hyperia parses the spec, builds Tools for mutating endpoints, Resources/Templates for GET routes, and wires a response mapper that converts JSON → TextContent automatically.


2 Mapping Rules

HTTP Method
Path Params
Component
Example

GET

none

Resource

GET /statsresource://stats

GET

present

ResourceTemplate

GET /users/{id}users://{id}

any other (POST, PUT, PATCH, DELETE, …)

n/a

Tool

POST /loginlogin

This is implemented via a priority‑ordered RouteMap list.

from hyperia.server.openapi import RouteMap, RouteType

custom = [
    # Treat *any* /analytics/* GET as a Tool (force call instead of read)
    RouteMap(methods=["GET"], pattern=r"^/analytics/.*", route_type=RouteType.TOOL)
]

mcp = Hyperia.from_openapi(spec, api, route_maps=custom)

all_routes_as_tools=True is a convenience flag that sets one catch‑all map; use when building agent backends that only need actions.


3 Request Construction

Hyperia uses the path templating, parameter schema, and requestBody definitions from the spec to build the outbound HTTP request.

3.1 Query Params Filtering

  • None or empty strings are omitted to avoid ?max=&sort= noise.

  • Boolean false is still sent (flag=false).

await cli.call_tool("search", {"q": "gpu", "page": None})
# → GET /search?q=gpu

3.2 Path Params Validation

Required placeholders must be non‑null; else ValueError.

3.3 Request Bodies

  • JSON – dict/list sent via json=

  • multipart/form‑data – files or nested models (OpenAPI encoding) supported

  • application/x‑www‑form‑urlencoded – auto encoded

If the spec marks a request body as optional you may omit it.


4 Response Mapping

Response Content-Type

Mapped MCP Content

application/json

TextContent with JSON string

text/*

TextContent

image/*

ImageContent

other / binary

BlobResourceContents

Hyperia strips unknown fields and honours schema.examples when generating the description shown to LLMs.


5 Advanced Options

5.1 Global Timeout

mcp = Hyperia.from_openapi(spec, api, timeout=5)

Applies to every outbound HTTP call; per‑tool override coming in v2.5.

5.2 Auth Injection

Because you provide the httpx.AsyncClient, you control headers, OAuth middleware, mTLS, or cookies there. Example Bearer token refresher:

class TokenAuth(httpx.Auth):
    async def async_auth_flow(self, req):
        req.headers["Authorization"] = f"Bearer {await get_token()}"
        yield req

api = httpx.AsyncClient(base_url=url, auth=TokenAuth())
mcp = Hyperia.from_openapi(spec, api)

5.3 Server Prefix

Pass route_prefix="/v2" if your OpenAPI paths are rooted differently than the runtime base URL.


6 Validation & Error Propagation

HTTP 4xx/5xx are translated into MCP errors so the client can handle gracefully. Response body (up to 2 KB) is forwarded in ToolError unless redact_errors=True.


7 Complete Walkthrough – PetStore

import httpx, asyncio
from hyperia import Hyperia
from pathlib import Path

spec = Path("petstore.yaml").read_text()  # local file ok; yaml or json
spec = yaml.safe_load(spec)
client = httpx.AsyncClient(base_url="https://petstore.example.com/api")

mcp = Hyperia.from_openapi(spec, client, name="PetStore")

async def demo():
    tools = await mcp.get_tools()
    print("Tools:", list(tools))

    # Call generated tool
    async with httpx.AsyncClient() as aio_cli:
        petstore_cli = Client(mcp)
        async with petstore_cli:
            res = await petstore_cli.call_tool("createPet", {"name": "Fido", "tag": "dog"})
            print(res[0].text)

asyncio.run(demo())

8 Limitations & Roadmap

  • OAuth 2.1 / OpenID helpers planned → auto‑generate auth flows for client apps.

  • Async Streaming – OpenAPI text/event‑stream responses currently buffered, streaming proxy slated for v2.6.

  • Enum to Literal – generation uses raw enums; future versions will convert to Python Literal for tighter schemas.


9 Troubleshooting

Problem
Cause
Remedy

ValueError: Missing required path parameters

Called tool without all placeholders

Provide all path args

404 on every request

Wrong base_url vs path prefix

Use route_prefix

Spec contains $ref but Hyperia raises KeyError

Circular $ref or unsupported JSON‑Pointer

Flatten spec or open GitHub issue

Last updated