You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 3c34860
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: agents/cli/README.md
+67-3Lines changed: 67 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,6 +60,7 @@ claude: {}
60
60
| `dex.tls.ca_file`, `dex.tls.server_name` | none | An `https` `dex.server` only. A PEM file of root CAs to trust as well, and the name the certificate must match. `DEX_TLS_CA_FILE` and `DEX_TLS_SERVER_NAME` override them. |
61
61
| `connectors.mcp` | `auto` | The connectors MCP server. `auto` uses the one `dexcli dev` provides. Otherwise an `http` or `https` URL on `127.0.0.1`, `localhost`, or `[::1]`. See URLs below. |
62
62
| `connectors.enabled` | every authorized connection | Which connections, and which of their operations, the agent may call. See below. |
63
+
| `mcp_servers` | `{}` | Remote MCP servers whose tools the agent may call, by name, over Streamable HTTP. See Remote MCP servers below. |
63
64
| `approval.always` | `[]` | Tool names, as the agent sees them, whose every call waits for approval. This adds to what the connectors and local tools already require. |
64
65
| `workspace` | `~/dex-agent-workspace`; for `dex-agents-pi`, the directory the command starts in | The only directory the local file tools use, and the working directory of shell commands. |
65
66
| `local_tools.files` | `true` | Read, write, list, and search files in `workspace`. Reads run at once; writes wait for approval. |
@@ -85,7 +86,8 @@ boundary. As in Pi, they run without approval unless `approval.always` names
85
86
them; see [its README](typescript/pi/README.md#tools-and-approvals).
86
87
87
88
Do not put secrets in the file. Provider keys come from the environment.
88
-
Connector credentials stay in the connections you authorize in Dex Web. The
89
+
Connector credentials stay in the connections you authorize in Dex Web.
90
+
Remote MCP server headers take their secrets from environment variables. The
89
91
schema rejects user info in URLs, but it cannot check the harness sections,
90
92
which each harness command defines.
91
93
@@ -173,6 +175,66 @@ letter or a digit, and an acronym stays one word, so `listStoryIDs` is
173
175
Two entries must not cover the same connection, so `slack` and `slack/work`
174
176
cannot appear together. An empty list gives the agent no connector tools.
175
177
178
+
### Remote MCP servers
179
+
180
+
`mcp_servers`adds the tools of MCP servers that are not Dex connectors, such
181
+
as a team's own tool server. Each key is the server's name, and each server
182
+
speaks the Streamable HTTP transport. Stateless servers work: every request
183
+
opens its own connection and protocol session.
184
+
185
+
```yaml
186
+
mcp_servers:
187
+
studio:
188
+
url: https://mcp.example.com/mcp
189
+
headers:
190
+
Authorization: "Bearer ${STUDIO_API_KEY}"
191
+
local-notes:
192
+
url: http://127.0.0.1:9000/mcp
193
+
trust_tool_annotations: true
194
+
```
195
+
196
+
| Field | Default | Meaning |
197
+
| --- | --- | --- |
198
+
| name (the key) | | 1 to 32 ASCII letters, digits, `_`, or `-`, starting with a letter. |
199
+
| `url` | required | The server's endpoint: `https`, or `http` on `localhost`, `127.0.0.0/8`, or `[::1]` (`insecure_mcp_server_url`). No user info or fragment. It follows the URL rules of `dex.server` and is used as written. |
200
+
| `headers` | `{}` | HTTP headers sent with every request to the server. |
201
+
| `trust_tool_annotations` | `false` | Whether the server's `readOnlyHint` and `idempotentHint` annotations, and the effects it declares under the Dex MCP conventions, pick each tool's effect. |
202
+
203
+
The agent sees each tool as `<server name>__<tool name>`, such as
204
+
`studio__search_assets`, and `approval.always` names it that way. With
205
+
`trust_tool_annotations: false`, every call waits for approval and runs at
206
+
most once. With `true`, a tool the server marks read-only or idempotent runs
207
+
without approval, unless `approval.always` names it, and may be retried; set
208
+
it only for a server whose hints you trust. `dex-agents-pi` and
209
+
`dex-agents-deepagents`still make every call that is not a read wait for
210
+
approval, as they do for connector tools.
211
+
212
+
Secrets belong in environment variables, never in the file. In a header
213
+
value, each `${NAME}` is replaced by the value of the environment variable
214
+
`NAME`when the command starts. `NAME` has ASCII letters, digits, and `_`, and
215
+
does not start with a digit. Any other `$` stays as written. The value is used
216
+
exactly as set, never trimmed or expanded again. `DEX_API_KEY`, `DEX_CREDENTIAL`, and `DEX_CREDENTIAL_FILE` count as not set,
217
+
so a Dex credential never reaches another server. A variable that is not set
218
+
or is empty stops the command with exit code 2 and a message that names it,
219
+
such as
220
+
`mcp_servers.studio.headers.Authorization needs the environment variable STUDIO_API_KEY, which is not set or is empty.`
221
+
A value outside printable ASCII stops it the same way. A header value may
222
+
also be literal text, but a literal secret then sits in the file: use a
223
+
`${NAME}` reference for every secret. Only the Worker expands the values. The command never prints, logs, or stores them:
224
+
the effective configuration, the session, and the log file keep the text as
225
+
written. Error text that a server sends back, such as an HTTP 401 body or a
226
+
tool error, is redacted on a best-effort basis: each header value, each of its
227
+
parts between spaces, `=`, `:`, `,`, or `;`, and each variable value of at
228
+
least 8 characters becomes `[redacted]` in the log file, the terminal, tool
229
+
output, and errors. Other content the server returns, such as progress and
230
+
task status messages and tool descriptions, is not covered, so give a token
231
+
only to servers you trust with it. A Worker that runs a stored call checks it against its own
232
+
configuration: for a server whose annotations it does not trust, the call must
233
+
have had approval and a single-attempt effect, or it fails unsent.
234
+
235
+
A server that cannot be listed offers no tools until it answers again; the
236
+
log file has the error. Session settings cannot change `mcp_servers`.
237
+
176
238
### Images
177
239
178
240
In the chat, `/image <path>` attaches an image file to your next message. A
@@ -242,7 +304,7 @@ session in Dex Web can edit its settings.
242
304
243
305
Other top-level keys are ignored, so the settings can also hold keys that
244
306
other readers use. This includes `dex`, `workspace`, `system_prompt_file`,
245
-
`media`, and the harness sections, which belong to the file only. The command reports each
307
+
`media`, `mcp_servers`, and the harness sections, which belong to the file only. The command reports each
246
308
ignored key as a warning, but the turn still runs. Inside a known field, an
247
309
unknown key is an error, so `connectors.mcp` fails.
248
310
@@ -257,7 +319,9 @@ cases every CLI core runs: YAML parsing, valid and invalid files with the
257
319
expected effective configuration or error, session settings with the
258
320
expected turn configuration and warnings, or error, and, in `dex_connection`,
259
321
files and environments with the expected Dex connection settings, or the
260
-
setting to fix and its exact message. Its `error_codes`,
322
+
setting to fix and its exact message, and, in `mcp_servers`, files and
323
+
environments with the expected remote MCP servers and their expanded headers,
324
+
or the setting to fix and its exact message. Its `error_codes`,
261
325
`warnings`, and `check_order` fields define how errors and warnings are
Copy file name to clipboardExpand all lines: agents/cli/config.schema.json
+44Lines changed: 44 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -222,6 +222,17 @@
222
222
}
223
223
}
224
224
},
225
+
"mcp_servers": {
226
+
"type": "object",
227
+
"default": {},
228
+
"description": "Remote MCP servers whose tools the agent may call over the Streamable HTTP transport, by server name: 1 to 32 ASCII letters, digits, underscores, or hyphens, starting with a letter. The agent sees each tool as <server name>__<tool name>, and approval.always names it that way. Every call waits for approval unless trust_tool_annotations lets the server's hints mark the tool a read or an idempotent write. Keep secrets out of this file: a header value can take them from environment variables with ${NAME} references, which the Worker expands when the command starts. Session settings cannot change it: they ignore an mcp_servers key with a warning.",
"description": "The server's Streamable HTTP endpoint: an https URL, or an http URL on localhost, 127.0.0.0/8, or [::1], without user info or a fragment. The host rules and the CLI core checks are those of dex.server. The URL is used as written, never expanded, so it must not hold a secret."
501
+
},
502
+
"headers": {
503
+
"type": "object",
504
+
"default": {},
505
+
"description": "HTTP headers sent with every request to the server, such as Authorization, by header name: 1 to 256 HTTP token characters. A value is printable ASCII. Each ${NAME} in it is replaced by the value of the environment variable NAME when the command starts; NAME has ASCII letters, digits, and underscores and does not start with a digit. A variable that is not set, is empty, or holds anything but printable ASCII stops the command. Any other $ stays as written. A value may be literal; put each secret in a ${NAME} reference instead. The command never prints, logs, or stores the expanded values.",
"description": "A header value: printable ASCII, where ${ always starts a ${NAME} reference."
511
+
}
512
+
},
513
+
"additionalProperties": false
514
+
},
515
+
"trust_tool_annotations": {
516
+
"type": "boolean",
517
+
"default": false,
518
+
"description": "Whether the server's readOnlyHint and idempotentHint annotations, and the effects it declares by the Dex MCP conventions, pick each tool's effect. false: every call of the server's tools waits for approval and runs at most once. true: a tool the server marks read-only or idempotent runs without approval, unless approval.always names it, and may be retried. Set it only for a server whose hints you trust."
Copy file name to clipboardExpand all lines: agents/cli/python/core/README.md
+30-1Lines changed: 30 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -438,6 +438,35 @@ read, and caches them for the harness:
438
438
Connectors page, `<Dex Web URL>/v1/connectors`, and opens it only in an
439
439
interactive terminal.
440
440
441
+
## Remote MCP server tools
442
+
443
+
`McpServersToolSource` offers the tools of the configuration's
444
+
`mcp_servers` through `McpToolSource`, over Streamable HTTP. The agent sees
445
+
each tool as `<server name>__<tool name>`. Its `source_name` is
446
+
`mcp_servers`, and the command registers it even without servers, so it
447
+
refuses a stored call of a server this Worker does not configure.
448
+
449
+
-`resolve_mcp_servers(config, os.environ)` expands each `${NAME}` in a
450
+
header value when the command starts. A variable that is not set, is
451
+
empty, or is not printable ASCII raises `McpServerSettingsError`, whose
452
+
message names the setting and the variable, never the value; the command
453
+
prints it and exits with code 2. The Worker host does the same.
454
+
- Each call adds the turn's `approval.always`. The tool Step checks it again
455
+
on the Worker that runs it and refuses a call that had no approval but now
456
+
needs one. For a server whose annotations that Worker does not trust, it
457
+
also refuses, unsent, a call without approval or with a retried effect.
458
+
- The source replaces each header value, each part of it between whitespace,
459
+
`=`, `:`, `,`, or `;`, and each value of `mcp_server_secret_texts`, of at
460
+
least 8 characters, with `[redacted]` in errors, tool output, and the log
461
+
file. This is best-effort for error text only: progress and task status
462
+
messages and tool descriptions are not redacted. The log filter covers the
463
+
root logger's handlers that exist when the Worker connects the servers.
464
+
- A listing that no server answers offers no remote tools and prints one
465
+
line, `MCP server tools are unavailable for now; each turn tries again.
466
+
See <logfile> for the error.`, until a server answers again. The error
467
+
goes to the log file. The command lists every server once at startup, so a
468
+
harness whose tool set is fixed at build gets the tools that answered then.
469
+
441
470
## Local tools
442
471
443
472
The local tool source offers these tools in their own Dex tool Steps. Paths
@@ -646,7 +675,7 @@ harness may replace only `FILES` and `SHELL`.
646
675
|`workspace: Path`| The absolute workspace, which exists. |
647
676
|`instructions: str \| None`|`system_prompt`, else the text of `system_prompt_file`, else `None` for the harness default. |
648
677
|`harness_options: Mapping[str, Any]`| The harness's own section, `{}` by default. |
649
-
|`tool_sources: Sequence[ToolSource]`| The connector and local tool sources, which apply each turn's settings themselves. Offer all of them. |
678
+
|`tool_sources: Sequence[ToolSource]`| The connector, remote MCP server, and local tool sources, which apply each turn's settings themselves. Offer all of them. |
650
679
|`media_store: MediaStore \| None`| The media store of `media.store`, holding the images of `/image` and of connector tool results. Pass it to an adapter that takes one, such as `media_store=context.media_store`. The CLI core always sets it; it is `None` only in a context a test builds without one. |
651
680
|`resolve_turn(session_settings) -> ResolvedTurn`| A turn's narrowed configuration with its `model`, `instructions`, and `reasoning_effort`. Raises `ConfigError` for rejected settings. |
652
681
|`resolve_tool_step_permissions(call=None) -> ResolvedTurn`| The permissions a replacement tool's own Step applies: this Worker's file narrowed by the session settings recorded for the call's turn. Pass the `DeferredToolExecution` from a runner, or nothing from a built-in loop function tool. Raises `RuntimeError` without a call outside a tool Step and a model call. |
0 commit comments