Quickback Docs

AI Agent Readiness

Every Quickback Worker ships agent-discovery files and an auto-generated MCP server. Let Claude, ChatGPT, Cursor, and Perplexity find and call your API out of the box.

Every compiled Quickback Worker advertises itself to AI agents and MCP clients — no user wiring required. One config flag controls the whole discovery surface.

What the compiler generates

When agents is enabled (the default), the Worker serves:

RouteWhat it is
GET /robots.txtAI-bot policy with the Cloudflare Content Signals preamble and explicit Allow: rules for GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot, Applebot-Extended, Bytespider, MistralAI, Cohere, DuckAssist.
GET /llms.txtAgent-facing summary of the API — project name, authentication, resource list, endpoint conventions — derived from your own config.
GET /.well-known/oauth-protected-resourceRFC 9728 metadata declaring this Worker as a protected resource.
GET /.well-known/oauth-authorization-serverRFC 8414 metadata pointing at the sign-in and token endpoints.
GET /.well-known/api-catalogRFC 9727 catalog linking at /openapi.json.
GET /.well-known/mcp.jsonMCP Server Card — discoverable metadata for the MCP server below.
POST /mcpAuto-generated MCP-over-HTTP server. One tool per OpenAPI operation, JWT auth forwarded through the same middleware as the REST API.

Default behavior

quickback.config.ts
import { defineConfig } from '@quickback/compiler';

export default defineConfig({
  name: 'my-api',
  // …
  // agents: true is the default — no need to write it.
});

Run quickback compile and every endpoint above ships in the Worker.

Opting out

quickback.config.ts
export default defineConfig({
  // …
  agents: false,  // disables everything
});

Fine-grained control

Pass an object to toggle individual surfaces:

quickback.config.ts
export default defineConfig({
  // …
  agents: {
    robotsTxt: true,        // default
    llmsTxt: true,          // default
    mcp: true,              // default
    oauthDiscovery: true,   // default
    apiCatalog: true,       // default
    allowAiCrawlers: true,  // default — flip to false to Disallow in robots.txt
  },
});

The MCP server

Tools

Every operation in your generated OpenAPI spec becomes one MCP tool. The tool name is the operation's operationId (e.g. listCustomers, createInvoice, sendInvoice). Each tool's inputSchema is a flat JSON Schema combining path params, query params, and the request body.

tools/call re-enters the same Hono app via app.request(...) — so every existing middleware runs exactly as it would for a direct REST call: authentication, firewall, access control, guards, masking. No bypass.

Access-filtered tools/list

tools/list only returns tools the calling identity could actually invoke. Each generated tool entry carries the operation's access metadata (roles, userRole, or / and combinators) and tools/list filters against ctx before responding:

  • Unauthenticated callers see only tools whose access declares the PUBLIC pseudo-role, or operations that have no security requirement at all (e.g. sign-in / sign-up).
  • Authenticated callers see tools whose role gate intersects their ctx.roles or ctx.userRole. Admin-only endpoints don't appear for non-admins.
  • Function-form access (escape hatch) is opaque at list time — surfaced to any authenticated caller, then evaluated for real on tools/call.
  • Record predicates are dropped from the list-time check (no record yet) and applied normally on the actual call.

This is recon-mitigation, not a security boundary. Hiding a tool from the list never weakens the underlying gate — tools/call still runs the full middleware chain and rejects unauthorized invocations the same way a direct REST call would.

The unauthenticated GET /mcp discovery payload returns server info only; it does not enumerate tool names. Inventory is exclusively available via the access-filtered tools/list.

Authentication

MCP clients pass their credentials through the standard Authorization: Bearer <jwt> header. The generated MCP handler forwards the header verbatim into the internal request, and the same JWT middleware that guards /api/v1/* validates it.

Mint a JWT from an authenticated session:

curl -X POST https://my-api.example.com/api/v1/token \
  -H "Cookie: better-auth.session_token=..." \
  -H "Content-Type: application/json"

Connecting clients

Claude Desktop — add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "my-api": {
      "url": "https://my-api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer <jwt>"
      }
    }
  }
}

Cursor — use the same config shape under .cursor/mcp.json.

Quick sanity check with curl:

# List available tools
curl -X POST https://my-api.example.com/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# Call a tool
curl -X POST https://my-api.example.com/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"listCustomers","arguments":{"limit":10}}}'

Transport

The server speaks the Streamable HTTP MCP transport — JSON-RPC 2.0 over POST. A plain GET /mcp returns the server info document for sanity checks.

The MCP route does not emit its own CORS headers. The Worker's existing cors() middleware applies uniformly, so browser-origin access is governed by the same allowlist as the rest of the API (auth.trustedOrigins + the deploy origin). Server-to-server clients (Claude Desktop, Cursor, MCP Inspector) connect with a Bearer token and don't need browser CORS at all. If you want a browser-based MCP client (ChatGPT, Claude.ai) to connect cross-origin, add its origin to auth.trustedOrigins like any other web client.

Verification

After you deploy, scan both the REST and MCP surfaces:

# Agent-readiness scan (external)
open https://isitagentready.com/?url=https://my-api.example.com

# MCP Inspector (official tool)
npx @modelcontextprotocol/inspector https://my-api.example.com/mcp

On this page