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

# Feature Provisioning

> How to provision which MCP features a gateway exposes in MCP Manager: for each server, choose to allow all, allow only those that match conditions, or block all tools (and the same for resources and prompts), preview a server's live tools using an identity, pin a tool by its name, title, or description so unreviewed changes stop passing the gateway, and filter or gate tools by their MCP annotations — read-only, destructive, idempotent, and open world.

When you add a server to a [gateway](/mcp-gateway-concepts/mcp-gateways), you decide exactly which of its tools, prompts, and resources the gateway exposes to clients. That decision is **feature provisioning**, and it's how you apply least privilege in practice — exposing the handful of tools a job actually needs instead of a server's entire surface. The filtering is enforced entirely by the gateway, so it works for **every** server — including one whose vendor offers no tool-level enable/disable controls of its own. What you can block is never limited by the upstream server's settings. This page is the how-to; for why it matters and the security model behind it (including the defense against tool poisoning and rug pulls), see [Feature Governance](/security/feature-governance). For a guided walkthrough that provisions a trimmed toolset on a new gateway, see [Build a team gateway](/tutorials/team-gateway).

<Note>
  Provisioning features on a server is gated by the **Manage feature provisioning settings** capability. If you don't see provisioning controls on a server within a gateway, your role doesn't have it — capabilities are assigned per role and fully configurable, so access depends on the capability, not on any fixed role name. See the [capabilities reference](/deployment/rbac-and-roles/capabilities).
</Note>

## The three provisioning modes

For each server on a gateway, and **independently for tools, prompts, and resources**, you pick one of three schemes from a dropdown:

* **Allowing all** (shown as *Allowing all tools*, *Allowing all resources*, or *Allowing all prompts*) — every capability of that type passes through. This is the scheme a server gets when you first assign it to a gateway.
* **Allow if conditions are met** — only capabilities matching an explicit allowlist pass; everything else is hidden and uncallable. This is least privilege in practice.
* **Blocking all** (shown as *Blocking all tools*, and so on) — no capability of that type is exposed.

<Note>
  A gateway starts out with no servers, so it exposes nothing. When you **assign** a server, each of its feature types defaults to **Allowing all** — for a simple setup, every tool, prompt, and resource the server offers passes straight through, so you aren't forced to curate before the gateway is useful.

  Narrowing a type is a deliberate switch, and that switch is **fail-closed by design**: change a type to **Allow if conditions are met** and it exposes **zero** capabilities until you add allowlist entries. Anything you haven't explicitly allowed — including a tool the server adds or renames later — stays hidden and uncallable.
</Note>

MCP Manager filters by allowlist only: there is no "allow everything except these" denylist mode, and that's deliberate — see [Why an allowlist, not a denylist](/security/feature-governance#why-an-allowlist-not-a-denylist) for the reasoning.

## Preview a server's tools with an identity

To choose which tools to allow, MCP Manager shows you the server's **live feature list**. Because a server can return a different set of tools to different identities, you first pick an **identity to preview against** — your own, or a shared one. MCP Manager fetches the tools that identity can see, so you select from the real, current list rather than guessing. (Picking the identity to preview is also where you set the server's [identity scheme](/features/identity-controls) — per-user or shared.)

## Provision the tools you want

<Steps>
  <Step title="Open the server on the gateway">
    From [Gateways](https://app.mcpmanager.ai/settings/gateways), open a gateway and select the assigned server you want to provision.
  </Step>

  <Step title="Pick an identity to preview">
    Choose the identity scheme and select an identity to preview the server's live tools, so the allowlist is built from the actual current capabilities.
  </Step>

  <Step title="Choose Allow if conditions are met for tools">
    Set the tools scheme to **Allow if conditions are met**. The moment you switch away from **Allowing all**, the list drops to zero exposed tools — nothing passes until you add an entry.
  </Step>

  <Step title="Add each tool you want">
    Browse the previewed tool list and add the specific tools to expose. Each one you add becomes an allowlist entry.
  </Step>

  <Step title="Choose which fields must match">
    For each added tool, choose which of its fields the gateway must match to let it through — its **name**, **title**, and/or **description**. See [Pinning a tool by its metadata](#pinning-a-tool-by-its-metadata) below.
  </Step>

  <Step title="Set prompts and resources, then save">
    Set the prompts and resources schemes to **Blocking all** (or **Allow if conditions are met**) depending on what this gateway needs, then save.
  </Step>
</Steps>

## Pinning a tool by its metadata

Each allowed tool is admitted only if it matches the fields you chose, exactly. How tightly you pin is a deliberate trade-off:

* **Match on name only** to tolerate the vendor improving a tool's description over time.
* **Match on name and description** to freeze exactly the wording you reviewed — so if the description later changes, the tool **no longer matches and is dropped** rather than reaching the model with new, unreviewed text.

That second option is the control that neutralizes **rug pulls** and **tool poisoning**: you approve a specific version of a tool's metadata, and anything that doesn't match what you approved stops passing the gateway. The full reasoning is in [Feature Governance](/security/feature-governance#a-defense-against-tool-poisoning-and-rug-pulls).

## Filter and gate by tool type

MCP tools can carry **annotations** — behavioral hints the upstream server attaches to a tool, such as whether it only reads data or might delete it. MCP Manager surfaces those hints as a tool's **tool type** and lets you use them in two ways: to **filter** the lists you provision from, and to **gate** an allowlist condition.

Every tool's annotations appear in a **Tool type** column on the Available, Provisioned, and Conditions tabs. Each reported annotation shows as an icon — its **-off** variant when the value is `false` — and annotations the server didn't report are left out. Hover any icon for a tooltip stating that annotation's value, such as *Read-only is true*. The four hints are independent — a tool can be read-only and open-world at once — so each renders on its own.

<Warning>
  Tool type comes from the MCP server and is **not validated by MCP Manager** — the filter dropdown says exactly that. Treat it as a way to triage and organize tools, **not** as a security control. Read [What each annotation means, and how far to trust it](#what-each-annotation-means-and-how-far-to-trust-it) before you depend on it.
</Warning>

### Filter the list by tool type

On the **Available**, **Provisioned**, and **Conditions** tabs, open **Filter by tool type** to narrow which rows are shown. The dropdown has one section per annotation — **Read-only**, **Destructive**, **Idempotent**, and **Open world** — and within each you can check **is true**, **is false**, and/or **is unknown**. **Select all** and **Deselect all** toggle every box at once.

* The checks are combined with **OR**, across every section: a row is shown if it matches **any** box you've checked. With nothing checked, everything is shown — the trigger reads "Filter by tool type"; check one box and it reads "Filtering by 1 annotation", more than one and it reads "Filtering by *N* annotations".
* **is unknown** matches tools whose server didn't report that annotation — a state distinct from `true` or `false`.
* The same filter sits on all three tabs and shares one selection: it narrows the **Available** and **Provisioned** lists of tools, and on the **Conditions** tab it narrows the allowlist rules to those that gate on the annotations you've checked.
* The filter composes with the search box, so you can stack a *Destructive is true* filter on top of a name search to scan, say, every delete-style tool on a large server.
* Filtering applies to **tools only**. Prompts and resources don't carry these hints, so the control doesn't appear for them.

Filtering only changes what you see while provisioning; on its own it doesn't change what the gateway exposes. To make a tool-type rule actually gate traffic, add it to the allowlist as a condition.

### Gate an allowlist on tool type

A **condition** is an allowlist entry that admits tools by a rule rather than by naming a single tool — it lives on the **Conditions** tab next to the tools you've pinned by name. When you add one, you can constrain it on annotations alongside name, title, and description. Each annotation offers **is true**, **is false**, **is unknown**, or **No value** — and **No value** is the default, meaning "don't constrain on this annotation."

A single condition combines its constraints with **AND**: a tool matches only if it satisfies *every* field you set. So *Read-only is true* on its own admits every tool the server marks read-only, without your naming each one; add *Open world is false* to the same condition and it narrows to tools that are both read-only **and** closed-world.

The allowlist as a whole combines its entries with **OR**: a tool is exposed if it matches **any** entry — any tool pinned by name, or any condition. That lets you pair a broad rule ("all read-only tools") with specific pins ("plus these three write tools I reviewed") on the same server. The filter and a condition use opposite logic by design: the filter casts a wide net with **OR** so you can eyeball several types at once, while a condition tightens with **AND** so one rule can be precise.

**is unknown** in a condition gates to tools whose server didn't report that hint — a way to single out or quarantine unannotated tools, distinct from `true` or `false`. Identical conditions are de-duplicated, so adding the same rule twice is a no-op. However you build it, a condition is enforced like any other allowlist entry: non-matching tools are filtered out of what clients see, and a direct call to one is blocked — see [What clients see, and how it's logged](#what-clients-see-and-how-its-logged).

<Warning>
  A tool-type condition gates on what the server **says about itself**, so it is only as trustworthy as that server. Never let *Read-only is true* be your sole defense against a destructive tool from a server you don't control — pair it with name and description [pinning](#pinning-a-tool-by-its-metadata).
</Warning>

### What each annotation means, and how far to trust it

The four annotations come straight from the [Model Context Protocol tool specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools). When a server sets one to `true`, it means:

| Annotation      | What `true` asserts                                                                                                                                             | MCP field         |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| **Read-only**   | The tool does not modify its environment.                                                                                                                       | `readOnlyHint`    |
| **Destructive** | The tool may perform destructive updates to its environment; `false` means it performs only additive updates. Meaningful only when the tool is *not* read-only. | `destructiveHint` |
| **Idempotent**  | Calling the tool repeatedly with the same arguments has no additional effect beyond the first call.                                                             | `idempotentHint`  |
| **Open world**  | The tool may interact with an "open world" of external entities — a web-search tool, say; `false` means its domain is closed, like a memory tool.               | `openWorldHint`   |

A tool shows **unknown** for any annotation its server didn't report. MCP Manager surfaces that gap honestly rather than guessing — which is worth knowing, because it differs from the MCP spec's own defaults: the spec assumes an *unannotated* tool is the riskier case (not read-only, potentially destructive, not idempotent, and open-world). An "unknown" in MCP Manager is therefore an absence of information, not a claim of safety.

<Warning>
  **Annotations are hints, not guarantees — and not a security boundary.** The MCP specification is explicit that these properties "are not guaranteed to provide a faithful description of tool behavior," and that a client "should never make tool use decisions based on annotations received from untrusted servers." A malicious or buggy server can advertise `readOnlyHint: true` on a tool that quietly deletes data; MCP Manager passes the values through unvalidated and labels them as such.

  So rely on tool type to **triage and organize** — surfacing likely-destructive tools for review, or trimming a long list to the read-only ones. For an *enforceable* control, rely on [name and description pinning](#pinning-a-tool-by-its-metadata) and the [feature-governance model](/security/feature-governance), which gate on the metadata you actually reviewed rather than on what the server asserts about itself.
</Warning>

## Turn off prompts and resources you don't need

Tools aren't the only feature type a server can expose. If a gateway doesn't need a server's prompts or resources, set those types to **Block all** to remove them entirely — fewer features means less context, lower cost, and a smaller surface.

## What clients see, and how it's logged

<Note>
  Provisioning changes take effect **immediately**. A change to a server's scheme or allowlist is enforced on the next request from any connected client — there's no separate publish or deploy step, and no staged draft that batches changes for later release. Remove a capability and it stops passing at once; add one and it becomes reachable right away.
</Note>

Clients connecting to the gateway see **one unified, filtered toolset**, each tool namespaced by its server — only the capabilities you provisioned. Provisioning decisions are recorded in your [logs](/features/viewing-logs): a capability removed from a list because it didn't match the allowlist is logged as `gateway_feature_filtered`, and a direct call to a disallowed capability is logged as `gateway_feature_blocked`. That lets you confirm what a gateway exposes and catch the moment a previously-passing tool stops matching — for example, when an upstream server renames or rewrites it.

## Further reading

<CardGroup cols={2}>
  <Card title="Feature Governance" icon="list-check" href="/security/feature-governance">
    The security model behind provisioning — least privilege, and the defense against tool poisoning and rug pulls.
  </Card>

  <Card title="Curating exposed tools" icon="network-wired" href="/mcp-gateway-concepts/mcp-gateways#curating-which-tools-are-exposed">
    How a gateway presents one filtered, namespaced toolset across many servers.
  </Card>

  <Card title="Identity Controls" icon="id-card" href="/features/identity-controls">
    Choosing the per-server identity you preview and provision against.
  </Card>

  <Card title="Viewing Logs" icon="rectangle-list" href="/features/viewing-logs">
    The `gateway_feature_filtered` and `gateway_feature_blocked` log types.
  </Card>
</CardGroup>
