Skip to content

Commit fb83787

Browse files
docs(site): document two-level MCP permission model (#742)
1 parent 37e4a14 commit fb83787

1 file changed

Lines changed: 53 additions & 6 deletions

File tree

  • site/src/content/docs/reference

site/src/content/docs/reference/mcp.mdx

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,57 @@ mcp-servers:
5656

5757
**Common (both types):**
5858
- `enabled:` - Whether this MCP server is active (default: `true`). Set to `false` to temporarily disable an entry without removing it from the front matter.
59-
- `allowed:` - Array of tool names the agent is permitted to call (required for security)
59+
- `allowed:` - Array of tool names the agent is permitted to call from this server (required for security). See [Two-Level Permission Model](#two-level-permission-model) for how this interacts with Copilot CLI's `--allow-tool`.
6060
- `env:` - Environment variables for the MCP server process. Use `""` (empty string) for passthrough from the pipeline environment.
6161

62+
## Two-Level Permission Model
63+
64+
MCP security operates at **two distinct layers**, both of which must grant permission for an agent to successfully call an MCP tool:
65+
66+
### Layer 1: Copilot CLI Server Access (`--allow-tool <server-name>`)
67+
68+
The Copilot CLI controls which MCP servers the agent can *access* via `--allow-tool` flags. The compiler automatically generates these flags for:
69+
70+
- **Built-in extensions** — `github`, `safeoutputs`, and `azure-devops` (when configured via `tools.azure-devops`)
71+
- **User-defined MCP servers** — any server in `mcp-servers:` with a `container:` or `url:` backing
72+
73+
For example, if you define an `azure-devops` server in `mcp-servers:`, the compiled pipeline includes:
74+
75+
```bash
76+
copilot --allow-tool azure-devops ...
77+
```
78+
79+
This grants the agent permission to *connect to the server*. Without this flag, the agent cannot communicate with the server at all, regardless of the `allowed:` list.
80+
81+
**When is `--allow-tool` automatic?**
82+
- **Restricted bash mode** (explicit `bash: [...]` list) — the compiler emits individual `--allow-tool` flags for each server.
83+
- **Wildcard bash mode** (omitted `bash:` or `bash: [":*"]`) — the compiler emits `--allow-all-tools` instead, which grants access to all servers and tools without individual flags.
84+
85+
### Layer 2: MCPG Tool-Level Filtering (`allowed: [...]`)
86+
87+
The MCP Gateway (MCPG) enforces the `allowed:` list for each server. Even if the agent has `--allow-tool azure-devops` permission, it can only call tools explicitly listed in the server's `allowed:` array.
88+
89+
```yaml
90+
mcp-servers:
91+
azure-devops:
92+
container: "node:20-slim"
93+
entrypoint: "npx"
94+
entrypoint-args: ["-y", "@azure-devops/mcp", "myorg"]
95+
allowed:
96+
- core_list_projects # ✅ Agent can call this
97+
- wit_get_work_item # ✅ Agent can call this
98+
# wit_update_work_item ❌ Not in allowed list → MCPG blocks
99+
```
100+
101+
If the agent attempts to call `wit_update_work_item`, MCPG rejects the request even though the agent has `--allow-tool azure-devops`.
102+
103+
### Why Two Layers?
104+
105+
- **CLI layer (`--allow-tool`)** — coarse-grained server access control; prevents agents from discovering or connecting to servers they shouldn't use.
106+
- **MCPG layer (`allowed:`)** — fine-grained tool access control; allows servers to expose many tools while agents only get a safe subset.
107+
108+
This defense-in-depth model ensures agents can only call the exact tools you intended, with no accidental privilege escalation.
109+
62110
## Environment Variable Passthrough
63111

64112
MCP containers may need secrets from the pipeline (e.g., ADO tokens). The `env:` field supports passthrough:
@@ -94,8 +142,7 @@ network:
94142

95143
## Security Notes
96144

97-
1. **Allow-listing**: Only tools explicitly listed in `allowed:` are accessible to agents
98-
2. **Containerization**: Stdio MCP servers run as isolated Docker containers (per MCPG spec §3.2.1)
99-
3. **Environment Isolation**: MCP containers are spawned by MCPG with only the configured environment variables
100-
4. **MCPG Gateway**: All MCP traffic flows through the MCP Gateway which enforces tool-level filtering
101-
5. **Network Isolation**: MCP containers run within the same AWF-isolated network. Users must explicitly allow external domains via `network.allowed`
145+
1. **Two-level allow-listing**: Both `--allow-tool <server>` (CLI layer) and `allowed:` (MCPG layer) must grant permission for a tool call to succeed. See [Two-Level Permission Model](#two-level-permission-model) for details.
146+
2. **Containerization**: Stdio MCP servers run as isolated Docker containers (per MCPG spec §3.2.1).
147+
3. **Environment Isolation**: MCP containers are spawned by MCPG with only the configured environment variables.
148+
4. **Network Isolation**: MCP containers run within the same AWF-isolated network. Users must explicitly allow external domains via `network.allowed`.

0 commit comments

Comments
 (0)