# Overview (/docs/agents)

---
title: Overview
description: Your collections, routes and access rules already describe the app. These pages project that description into an MCP server an agent can call and an OpenAPI document a person can read.
kind: guide
package: questpie
---

There is no second model to maintain here. You add a module, name what an agent
may reach, and run codegen. Both surfaces read the same files the admin and the
typed client read.

| Page                                         | What it covers                                                                   |
| -------------------------------------------- | -------------------------------------------------------------------------------- |
| [MCP](/docs/agents/mcp)                      | The Model Context Protocol server from `@questpie/mcp`, and what becomes a tool. |
| [MCP over OAuth 2.1](/docs/agents/mcp-oauth) | How an outside agent signs in as a real person, and what its scopes reach.       |
| [OpenAPI and Scalar](/docs/agents/openapi)   | The OpenAPI 3.1 document and the Scalar reference UI from `@questpie/openapi`.   |

## Two surfaces, two jobs

**OpenAPI describes.** It emits a document covering your collections, globals,
routes, auth and search. The document decides nothing. Listing a path grants no
access to it.

**MCP executes.** An agent calls a tool and the app performs the operation. That
call runs the same `.access()` rules your REST traffic runs.

## Turn both on

The starters already register `openApiModule`. MCP is opt-in, so add it
yourself.

```ts title="src/questpie/server/modules.ts"
import { adminModule } from "@questpie/admin/modules/admin";
import { mcpModule } from "@questpie/mcp/modules/mcp";
import { openApiModule } from "@questpie/openapi";

export default [adminModule, mcpModule, openApiModule] as const;
```

Then say what an agent may reach. Name the collection and name each operation.

```ts title="src/questpie/server/config/mcp.ts"
import { mcpConfig } from "@questpie/mcp";

export default mcpConfig({
	crud: {
		collections: {
			posts: { operations: { list: true, get: true } },
		},
	},
});
```

```bash
questpie generate
```

## What you now serve

Three endpoints, under your handler's base path, `/api` in the starters.

| Endpoint                | What it is                                                            |
| ----------------------- | --------------------------------------------------------------------- |
| `POST /api/mcp`         | The MCP endpoint. It answers 401 without a signed-in caller.          |
| `GET /api/openapi.json` | The OpenAPI 3.1 document, cached and served with an ETag.             |
| `GET /api/docs`         | The [Scalar](https://scalar.com) reference, built from that document. |

An agent connecting as a user who may read posts sees two tools,
`collections.posts.list` and `collections.posts.get`. It sees no other
collection, and it cannot create, update or delete a post.

## Exposure and permission are separate

`config/mcp.ts` decides which tools exist. `.access()` decides whether a call
succeeds. Both have to pass.

### Nothing is exposed until you list it

The tool catalog starts empty. A collection you never named contributes no
tools, whatever its access rules say. Naming the collection is not enough
either. Each operation has to be switched on under `operations`. That is why
`posts: true` on its own still yields nothing.

### The rules you already wrote still run

Every tool call re-checks the collection's `.access()` rules for the calling
session. So does the tool list. A user who may not read `posts` never sees
`collections.posts.list` in the first place.

### OAuth can only subtract

An external agent authenticates over OAuth 2.1 and carries consented scopes.
The scope gate runs beside the access rules, never instead of them. The
effective permission is `scopes ∩ RBAC`, so a scope cannot widen what that user
is allowed to do.

<Callout type="warn" title="stdio is the exception">
	The stdio transport demands explicit authority. Set `stdio.trustedMaintenance`
	and the process runs as `system`, which skips the access checks entirely. See
	[MCP](/docs/agents/mcp).
</Callout>

## What QUESTPIE does not ship

There is no agent runtime here. Provider choice, approvals and what an agent is
allowed to decide belong to the app that owns those concepts. QUESTPIE gives you
the pieces underneath: MCP tools, [jobs](/docs/code/jobs), a
[queue](/docs/infrastructure/queue) and a
[sandbox](/docs/infrastructure/sandbox) for untrusted code.

## Next

**[MCP](/docs/agents/mcp)** covers the surface itself. Every config key, custom
tools, and the transports. [Access control](/docs/schema/access-control) sits
under all of it, because every tool call ends there.
