Auto-Generated API Docs

Write handler files. Your app gets OpenAPI, MCP, and federation specs automatically.

Every app running on Qbix Server gets machine-readable API docs published at well-known URLs. No annotations required — though docblocks make the docs richer. Add a handler file, the specs update on the next request.

How it works

From handler file to published spec

The server walks your handlers/ directory tree. Each PHP file becomes an API endpoint. The path maps to the event name:

handlers/
  chat/
    join.php        →  event: "chat/join"
    message.php     →  event: "chat/message"
  users/
    login.php       →  event: "users/login"
    profile/
      get.php       →  event: "users/profile/get"

For each handler file, the server extracts:

1. Event name        ← from the file path (chat/join.php → "chat/join")
2. Description       ← from the file's docblock (/** ... */) or first // comment
3. Parameters        ← from @param tags in the docblock
4. Return type       ← from @return tags
5. Tags/categories   ← from the directory structure (chat/*, users/*)

This information is published at three well-known URLs, all generated from the same scan.

Supported comment formats

The parser supports three formats. Use whichever your codebase already uses — they can coexist in the same project.

PHPDoc (standard PHP):

/**
 * Send a chat message to a room.
 *
 * Broadcasts to all room members except the sender.
 *
 * @param string $text The message content
 * @param string $room The room to send to
 * @param ?string $name Display name (optional, nullable)
 * @return array {id: int, broadcast: bool}
 * @throws InvalidArgumentException If text is empty
 */

YUIDoc / Qbix style (used throughout the Qbix Platform):

/**
 * Send a chat message to a room.
 *
 * @param {String} text The message content
 * @param {String} room The room to send to
 * @param {String} [name] Optional — display name
 * @param {String} [format=text] Optional with default
 * @return {Object} The broadcast result
 */

YUIDoc alternate (name before type):

/**
 * @param text {String} The message content
 * @param [name] {String} Optional display name
 */

Plain // comments (no docblock at all):

// Send a chat message to a room
function chat_message(&$params, &$result) {
    // ...
}

The first // comment line becomes the summary. No parameter docs, but the handler still appears in the spec with its event name.

All recognized tags
TagFormatsMaps to
@param@param type $name desc (PHPDoc)
@param {Type} name desc (YUIDoc)
@param {Type} [name] desc (optional)
@param {Type} [name=default] (default)
@param name {Type} desc (alternate)
@param $name desc (bare)
OpenAPI requestBody schema properties
@return / @returns@return type desc (PHPDoc)
@return {Type} desc (YUIDoc/JSDoc)
Response schema
@throws / @throwSame as @returnError responses
@method@method GETHTTP method hint
@deprecated@deprecatedOpenAPI deprecated flag
@private / @internal@privateExcluded from specs entirely
@access private@access privateExcluded from specs

Nullable types: Both ?string and string|null are detected and mark the parameter as optional.

Array types: array<string> and string[] map to JSON Schema "type": "array".

Type mapping: string, int/integer, float/double/number, bool/boolean, array, object, mixed.

What the spec looks like (without any docblocks)

Even with zero comments, every handler file appears in the spec:

// handlers/chat/message.php — no docblock at all
function chat_message(&$params, &$result) {
    $room = $params['room'];
    Q_Socket::broadcast(['message', $params['data']]);
}

Generates this OpenAPI path:

{
  "/Q/event/chat/message": {
    "post": {
      "summary": "chat/message",
      "operationId": "chat_message",
      "tags": ["chat"],
      "requestBody": { "content": { "application/json": {
        "schema": { "type": "object" }
      }}}
    }
  }
}

Add a // Send a chat message at the top and the summary changes. Add a docblock with @param tags and the schema fills in. The more you document, the richer the spec — but it works from zero.

Three specs from one scan

/.well-known/openapi.json — OpenAPI 3.1

Standard API spec. Works with every tool in the ecosystem:

ToolHow to use
PostmanImport → paste URL → complete collection with all your endpoints
Swagger UIPoint the explorer at it → interactive try-it-out docs
RedocFeed it the URL → polished static reference
InsomniaImport → OpenAPI → all requests pre-configured
Code generatorsopenapi-generator → typed client SDKs in any language

The spec includes built-in server endpoints (/Q/health, /Q/event, /Q/stats) alongside your app’s handlers. Endpoints are tagged by directory — chat/* handlers get the “chat” tag, users/* get “users”.

/.well-known/mcp.json — MCP for AI tools

Each handler becomes an MCP tool that AI assistants can call directly:

{
    "tools": [
        {"name": "health", "description": "Check server health and uptime"},
        {"name": "chat_join", "description": "Send a user into a chat room"},
        {"name": "chat_message", "description": "Send a chat message to a room"},
        {"name": "users_login", "description": "Handle user login"}
    ]
}

Claude, GPT, Cursor, or any MCP-compatible tool can discover your handlers, read their parameter schemas, and call them — no glue code, no adapters, no manual tool definitions. Descriptions come from your docblocks; parameters from @param tags.

/.well-known/qbix.json — Federation manifest

Other Qbix servers use this for federation — pin the fingerprint, discover endpoints, forward events:

{
    "server": "Qbix Server",
    "version": "1.1.0",
    "fingerprint": "4af468e461fc2022...",
    "endpoints": {
        "event": "/Q/event",
        "health": "/Q/health",
        "openapi": "/.well-known/openapi.json",
        "mcp": "/.well-known/mcp.json",
        "websocket": "/Q/ws"
    },
    "plugins": [{"name": "Users", "version": "1.0"}]
}

What this means for your app

You write a handler file. The server publishes it as an OpenAPI endpoint, an MCP tool, and a federation target. Postman can import your API. AI assistants can call it. Other Qbix servers can forward events to it. Three audiences, zero configuration.