# Core concepts

> Organisations own MCP servers. Servers carry policies and grants. Every proxy request is evaluated against policy before reaching the upstream.

Canonical: https://policylayer.com/docs/core-concepts

PolicyLayer has a small operating model:

```text
Organisation
  └─ Server
       ├─ Policies
       └─ Grants
```

An MCP client connects to the PolicyLayer proxy, not directly to the upstream MCP server. The client authenticates with a grant token. PolicyLayer resolves the grant, evaluates the attached policy, and only forwards the request when the policy allows it.

## Organisations and roles

An organisation owns its servers, policies, grants, members, and logs.

Team members sign in to the dashboard and receive an organisation role:

- **`admin`** sets up servers, upstream authentication, grants, members, and audit access.
- **`policy_manager`** writes policies and attaches them to existing grants, without access to upstream credentials or grant tokens.
- **`viewer`** reads servers, policy names, grant labels, and proxy logs.

Roles control dashboard access only. MCP clients authenticate with grant tokens, not dashboard user sessions. See [Roles](/docs/roles) for the full matrix.

## Servers

A server is one upstream MCP target. It has:

- **Name.** A dashboard label such as `prod-stripe`, `github`, or `linear`.
- **Upstream URL.** The real HTTP MCP endpoint.
- **Proxy URL.** The PolicyLayer URL clients connect to, shaped like `https://proxy.policylayer.com/mcp/<server-uuid>/`.
- **Upstream authentication.** OAuth tokens or static headers that PolicyLayer injects when forwarding allowed requests.

The server UUID in the proxy URL is part of enforcement. A grant belongs to exactly one server, and the proxy rejects requests where the path UUID does not match the grant's server.

PolicyLayer does not forward the client's `Authorization` header upstream. That header is consumed as the PolicyLayer grant token. If the upstream needs credentials, configure OAuth or static headers on the server. See [Upstream authentication](/docs/upstream-authentication).

## Policies

A policy is a named ruleset on one server. It decides which tools a grant can use.

One server can have many policies:

- `stripe-readonly`
- `stripe-low-cap-refunds`
- `stripe-admin`

Several grants can share the same policy, and a grant can switch from one policy to another without changing its token.

Policies can:

- allow or deny tools by default;
- hide tools from streamable HTTP `tools/list` responses;
- require argument conditions before a tool call is allowed;
- deny calls when argument conditions match;
- apply quota limits by grant, policy, server, or global scope.

Body edits create immutable policy versions. Renaming a policy is metadata-only. Logs record the policy version that decided a call, so past decisions remain attributable after edits.

## Grants

A grant is a labelled bearer token for one MCP client, developer machine, or automation.

Each grant has:

- **Label.** A human-readable name such as `alice-laptop`, `ci-runner`, or `support-agent`.
- **Token.** The secret sent by the MCP client as `Authorization: Bearer <grant-token>`.
- **Server.** The one server this grant can reach.
- **Policy.** The policy attached to the grant, or no policy.

A grant with no policy denies every tool call until a policy is attached.

Only `admin` can mint, rotate, reveal, or revoke grant tokens. `policy_manager` can attach or detach policies on existing grants, but cannot reveal token material.

Grants are not users. Removing someone from the organisation removes dashboard access, but it does not automatically revoke grants they minted. Review personal and CI grants during offboarding.

## Request flow

For each proxy request:

```text
Client ──HTTP──▶ PolicyLayer proxy ──HTTP──▶ Upstream MCP server
                       │
                       ├─ Authenticate the bearer token to a grant
                       ├─ Check the grant belongs to the URL's server UUID
                       ├─ Resolve the policy attached to the grant
                       ├─ Evaluate the requested tool call
                       ├─ Reserve quota counters
                       ├─ Forward with configured upstream credentials
                       ├─ Stream the response back
                       └─ Roll back counters if the upstream errors
```

The proxy supports MCP streamable HTTP and the older legacy SSE transport. Stdio MCPs are not supported directly; expose a stdio MCP as HTTP and register that URL.

## Evaluation

Each `tools/call` runs through the same order:

1. **Hide.** Hidden tools are denied.
2. **Default.** Under `default: deny`, unlisted tools are denied.
3. **Require.** Required predicates must match.
4. **Deny-if.** Matching deny predicates block the call.
5. **Limits.** PolicyLayer reserves quota counters before forwarding.

The first denial wins. If the policy allows the call, the proxy forwards it with the server's configured upstream credentials. If the upstream later errors, quota reservations from that call roll back.

## Logs

Proxy logs attribute calls to a grant, policy version, decision, and upstream result without storing argument values. The separate admin audit log records state-changing dashboard actions such as server creation, grant minting, OAuth connection, and role changes.
