> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kavachos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway

> An auth proxy that sits in front of any API or MCP server, enforcing auth, permissions, rate limiting, and audit without changing upstream code.

## What the gateway does

The KavachOS Gateway is a standalone HTTP reverse proxy. Every request to your API or MCP server passes through it first. The gateway:

* Validates Bearer tokens against a KavachOS instance
* Checks agent permissions before forwarding
* Enforces global and per-route rate limits
* Records an audit trail for every request
* Handles CORS preflight
* Strips or forwards the Authorization header depending on your config

The upstream service sees only clean, authenticated traffic. No SDK changes required on the upstream side.

## When to use it

Use the gateway when you want to add auth to something that doesn't have it. Common cases:

* A local tool server or MCP server that accepts unauthenticated connections
* A third-party API you're exposing to agents
* A service you can't modify but need to wrap with auth
* Staging environments where you want to restrict access

If you own the upstream service and can add the KavachOS SDK directly, that's more flexible. The gateway is best when you can't or don't want to touch upstream code.

## Quick start

The fastest path is the one-liner:

```bash theme={"system"}
npx @kavachos/gateway --upstream http://localhost:8080
```

This starts a gateway on port 3000 that proxies all traffic to `http://localhost:8080`. Requests without a valid KavachOS Bearer token are rejected with 401.

Check the health endpoint to confirm it's running:

```bash theme={"system"}
curl http://localhost:3000/_kavach/health
# {"status":"ok","upstream":"http://localhost:8080","timestamp":"..."}
```

## Configuration

### CLI flags

```bash theme={"system"}
npx @kavachos/gateway \
  --upstream http://localhost:8080 \
  --port 4000 \
  --database ./kavach.db \
  --config gateway.json \
  --strip-auth \
  --no-audit
```

| Flag           | Default    | Description                                         |
| -------------- | ---------- | --------------------------------------------------- |
| `--upstream`   | required   | URL of the upstream service                         |
| `--port`       | `3000`     | Port the gateway listens on                         |
| `--database`   | `:memory:` | SQLite database path for KavachOS                   |
| `--config`     | ,          | Path to a `gateway.json` config file                |
| `--strip-auth` | false      | Remove the `Authorization` header before forwarding |
| `--no-audit`   | false      | Disable audit trail recording                       |

### gateway.json

For more control, put your config in a JSON file and pass it with `--config`:

```json theme={"system"}
{
  "upstream": "http://localhost:8080",
  "audit": true,
  "stripAuthHeader": false,
  "cors": {
    "origins": ["https://app.example.com"],
    "methods": ["GET", "POST", "PUT", "DELETE"],
    "credentials": true
  },
  "rateLimit": {
    "windowMs": 60000,
    "max": 100
  },
  "policies": [
    {
      "path": "/health",
      "public": true
    },
    {
      "path": "/api/read/**",
      "method": "GET",
      "requiredPermissions": [
        { "resource": "api", "actions": ["read"] }
      ]
    },
    {
      "path": "/api/**",
      "requiredPermissions": [
        { "resource": "api", "actions": ["read", "write"] }
      ],
      "rateLimit": {
        "windowMs": 60000,
        "max": 20
      }
    }
  ]
}
```

### Embedded mode

Use the gateway inside your own Node.js application without starting a separate process:

```typescript theme={"system"}
import { createKavach } from 'kavachos';
import { createGateway } from '@kavachos/gateway';

const kavach = await createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
});

const gateway = createGateway({
  upstream: 'http://localhost:8080',
  kavach,
  audit: true,
  cors: { origins: '*' },
  rateLimit: { windowMs: 60_000, max: 100 },
  policies: [
    { path: '/_health', public: true },
    {
      path: '/api/**',
      requiredPermissions: [{ resource: 'api', actions: ['read'] }],
    },
  ],
});

// Start a standalone server
await gateway.listen(3000);

// Or use it as a handler in your existing server framework
// (pass it a Web API Request, get back a Response)
const response = await gateway.handleRequest(request);
```

## Policy rules

Policies are matched in order. The first policy whose `path` pattern and `method` (if set) match the incoming request wins.

```typescript theme={"system"}
interface GatewayPolicy {
  path: string;              // glob pattern, e.g. '/api/*', '/tools/**'
  method?: string | string[]; // 'GET', ['GET', 'POST'], etc.
  public?: boolean;          // skip auth entirely
  requireAuth?: boolean;     // default true
  requiredPermissions?: Array<{
    resource: string;
    actions: string[];
  }>;
  rateLimit?: {
    windowMs: number;
    max: number;
  };
}
```

### Glob patterns

Patterns use standard glob syntax via [micromatch](https://github.com/micromatch/micromatch):

| Pattern   | Matches                                       |
| --------- | --------------------------------------------- |
| `/api/*`  | `/api/users`, `/api/items` (one level)        |
| `/api/**` | `/api/users`, `/api/v2/users/123` (any depth) |
| `/health` | `/health` exactly                             |
| `/**`     | everything                                    |

### Auth flow per request

1. Check if the path is `/_kavach/health`, serve locally, no upstream
2. Handle CORS preflight if `cors` is configured
3. Match the request against policies (path + method)
4. If the matched policy is `public: true` or `requireAuth: false`, skip auth
5. Otherwise extract the `Authorization: Bearer <token>` header
6. Validate the token against KavachOS, reject with 401 if invalid
7. Check global rate limit (keyed by agent ID or IP), reject with 429 if exceeded
8. Check policy-level rate limit, reject with 429 if exceeded
9. Check `requiredPermissions` if any, reject with 403 if insufficient
10. Proxy the request to the upstream
11. Record an audit entry if `audit: true`
12. Return the upstream response with CORS headers merged in

## Integration with MCP servers

The gateway works well in front of MCP tool servers. Agents that have been issued KavachOS tokens can call tools through the gateway, with permissions enforced per-route:

```json theme={"system"}
{
  "upstream": "http://localhost:3001",
  "policies": [
    {
      "path": "/tools/read-file",
      "method": "POST",
      "requiredPermissions": [
        { "resource": "filesystem", "actions": ["read"] }
      ]
    },
    {
      "path": "/tools/write-file",
      "method": "POST",
      "requiredPermissions": [
        { "resource": "filesystem", "actions": ["write"] }
      ]
    },
    {
      "path": "/tools/**",
      "requiredPermissions": [
        { "resource": "mcp", "actions": ["call"] }
      ]
    }
  ]
}
```

## Standalone vs embedded

|            | Standalone (CLI)           | Embedded                        |
| ---------- | -------------------------- | ------------------------------- |
| Setup      | `npx @kavachos/gateway`    | `createGateway(config)`         |
| Process    | Separate process           | In-process                      |
| Framework  | None required              | Works with any framework        |
| Hot reload | Restart required           | Your app's reload               |
| Use case   | Quick wrap, Docker sidecar | Full control, custom middleware |

In Docker, the standalone mode works as a sidecar:

```dockerfile theme={"system"}
# Start your API
CMD ["node", "server.js"]

# Or start the gateway in front of it
CMD ["npx", "@kavachos/gateway", "--upstream", "http://localhost:8080", "--port", "3000", "--database", "/data/kavach.db"]
```

## Configuration reference

<ParamField path="upstream" type="string">URL of the upstream service to proxy to</ParamField>
<ParamField path="basePath" type="string" default="&#x22;/&#x22;">Base path prefix. Default: "/"</ParamField>
<ParamField path="kavach" type="Kavach">KavachOS instance created with createKavach()</ParamField>
<ParamField path="policies" type="GatewayPolicy[]">Array of path-based access policies</ParamField>
<ParamField path="cors" type="CorsConfig">CORS configuration</ParamField>
<ParamField path="rateLimit" type="{ windowMs: number; max: number }">Global rate limit applied to all requests</ParamField>
<ParamField path="audit" type="boolean" default="true">Record an audit entry for every request. Default: true</ParamField>
<ParamField path="stripAuthHeader" type="boolean" default="false">Remove the Authorization header before forwarding to upstream. Default: false</ParamField>

<Info>
  Rate limits are tracked in memory. If you run multiple gateway instances, each tracks limits independently. For distributed rate limiting, wrap the gateway with an external store or use a single gateway instance.
</Info>
