# OpenWork MCP Gateway Architecture: How api.openworklabs.com/mcp/agent Routes AI Agent Requests

> Discover the OpenWork MCP gateway architecture powering api.openworklabs.com/mcp/agent. Learn how this Hono-based server handles AI agent requests and secures communication with JWT authentication.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: architecture
- Published: 2026-08-15

---

**The OpenWork MCP gateway at `api.openworklabs.com/mcp/agent` is a stateless Hono-based HTTP server that authenticates clients via JWT, exposes two core endpoints for capability discovery and execution, and forwards requests to internal microservices.**

The **Model-Control-Plane (MCP)** gateway serves as the public entry point for client-side AI agents interacting with an OpenWork installation. Built with the lightweight **Hono** framework and deployed as the `ee/apps/den-gateway` package, it provides a unified, language-agnostic façade over the platform's modular backend services.

## Core Layers of the MCP Gateway Architecture

The gateway is organized into distinct layers, each with specific responsibilities:

| Layer | Responsibility | Key Files |
|-------|----------------|-----------|
| **HTTP Server** | Boots Node.js, binds Hono app, logs JSON ready-message | [[`server.ts`](https://github.com/different-ai/openwork/blob/main/server.ts)](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-gateway/src/server.ts) |
| **Hono Application** | Registers routes, middleware, delegates to handlers | [[`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts)](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-gateway/src/app.ts) |
| **Environment Config** | Validates runtime settings at startup | [[`env.ts`](https://github.com/different-ai/openwork/blob/main/env.ts)](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-gateway/src/env.ts), [[`load-env.ts`](https://github.com/different-ai/openwork/blob/main/load-env.ts)](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-gateway/src/load-env.ts) |
| **Authentication** | Verifies signed JWTs with capability claims | Inline middleware in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts) |
| **Capability Dispatcher** | Handles `/search_capabilities` and `/execute_capability` | `searchCapabilitiesHandler` and `executeCapabilityHandler` in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts) |
| **Rate Limiting & Telemetry** | Tracks usage, enforces quotas, pushes metrics | Utilities in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts), [`gateway.test.mjs`](https://github.com/different-ai/openwork/blob/dev/ee/apps/den-gateway/test/gateway.test.mjs) |
| **Error Normalization** | Converts exceptions to MCP protocol format | `errorHandler` middleware |

All traffic is served over **HTTPS** (TLS terminated at the deployment layer), and the gateway maintains **no persistent state**—only JWT claims and request-scoped objects.

## The Two Primary MCP Endpoints

The `api.openworklabs.com/mcp/agent` gateway exposes exactly two `POST` endpoints that implement the MCP protocol:

### `/search_capabilities`

Returns a JSON list of capabilities the authenticated client is permitted to invoke. The handler validates the JWT's `capabilities` claim against the platform's registry before responding.

### `/execute_capability`

Forwards the request payload to the appropriate internal service—typically `den-api` for AI operations or plugin backends for custom capabilities—and **streams the result back** to the client.

Both endpoints require a valid JWT in the `Authorization: Bearer <token>` header.

## Authentication Flow

The **JWT-based authentication middleware** in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts) performs three critical checks:

1. **Presence** — Missing header returns `401 Unauthorized`
2. **Signature validity** — Verifies token signed with the shared secret from [`env.ts`](https://github.com/different-ai/openwork/blob/main/env.ts)
3. **Capability claims** — Decodes `client_id`, allowed `capabilities`, and `exp` expiry

Invalid tokens at any step result in immediate `401` responses. Valid tokens populate the request context for downstream handlers.

## How Clients Call the Gateway

```javascript
// Discover available capabilities
const capabilities = await fetch('https://api.openworklabs.com/mcp/agent/search_capabilities', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${myJwt}`
  },
  body: JSON.stringify({ client_id: 'my-client' })
});

// Execute a capability (e.g., OpenAI completion)
const result = await fetch('https://api.openworklabs.com/mcp/agent/execute_capability', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${myJwt}`
  },
  body: JSON.stringify({
    capability: 'openai/completion',
    input: { prompt: 'Write a short poem about sunrise.' }
  })
});

```

The JWT **must include a `capabilities` array** listing permitted operations. The gateway uses this claim for both advertising available functions and authorizing execution requests.

## Internal Service Dependencies

The gateway does not implement capability logic directly. Instead, it **delegates to peer services**:

| Service | Role | Repository Location |
|---------|------|---------------------|
| **`den-api`** | Executes AI operations and plugin code | [`ee/apps/den-api`](https://github.com/different-ai/openwork/tree/dev/ee/apps/den-api) |
| **`den-controller`** | Manages plugin registration, marketplace sync, org policies | [`ee/apps/den-controller`](https://github.com/different-ai/openwork/tree/dev/ee/apps/den-controller) |

This delegation pattern keeps the gateway thin and allows independent versioning of capability implementations.

## Key Source Files

- **[`server.ts`](https://github.com/different-ai/openwork/blob/main/server.ts)** — Entry point that creates the Node.js HTTP server and mounts the Hono app
- **[`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts)** — Core application with route definitions, middleware chain, and handlers
- **[`env.ts`](https://github.com/different-ai/openwork/blob/main/env.ts)** / **[`load-env.ts`](https://github.com/different-ai/openwork/blob/main/load-env.ts)** — Configuration loading with runtime validation
- **`gateway.test.mjs`** — End-to-end tests covering authentication, both endpoints, and rate limiting

## Summary

The **OpenWork MCP gateway architecture** delivers a production-ready agent endpoint through four design principles:

- **Stateless operation** — No session storage, horizontal scaling via JWT claims
- **Minimal surface area** — Just two endpoints for discovery and execution
- **Delegated implementation** — Heavy lifting handled by `den-api` and `den-controller`
- **Protocol-compliant errors** — Standardized error format for downstream agent handling

This structure enables OpenWork to expose a **unified "agent-first" API** while maintaining modularity across the service mesh.

## Frequently Asked Questions

### What framework does the OpenWork MCP gateway use?

The gateway uses **Hono**, a lightweight, edge-ready HTTP framework for Node.js. Hono provides routing, middleware composition, and TypeScript support with minimal overhead. The framework choice keeps cold-start times low and middleware chains readable.

### How does the gateway authenticate incoming requests?

All requests must include a **signed JWT** in the `Authorization: Bearer <token>` header. The authentication middleware in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts) validates the signature using a shared secret, then extracts the `capabilities`, `client_id`, and `exp` claims. Missing or invalid tokens immediately return `401` responses.

### What happens when I call `/execute_capability`?

The `executeCapabilityHandler` function in [`app.ts`](https://github.com/different-ai/openwork/blob/main/app.ts) validates that the requested capability appears in the JWT's allowed list, then **forwards the payload to the appropriate internal service**—typically `den-api` for AI operations. Results stream back through the gateway to the original caller without transformation.

### Is the gateway stateful or stateless?

**Completely stateless.** The gateway stores no session data, no caching layers, and no request history. All authorization data lives in the JWT itself. This design allows horizontal scaling across multiple instances without shared storage or sticky sessions.