self-hosted-sandboxes-custom-tools changedmanaged-agents/self-hosted-sandboxes-custom-tools
Nearest release: v2.1.312, published under an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+18added
Lines−18removed
From line
22
where the diff opens
First seen
2 Oct 2026
this site's first read of the page
Recorded edits12to this page, all time
The whole hunk
from line 22, old and new numbered
/
from line 22
2222
2323<Steps>
2424 <Step title="Declare the tool on the agent">
25 Add a `custom` entry to the agent's `tools` whose `name` matches the tool your worker registers. See [Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools) for the full declaration shape.
25 Add a `custom` entry to the agent’s `tools` whose `name` matches the tool your worker registers. See [Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools) for the full declaration shape.
2626
2727 ```json
2828 {
from line 41
4141 </Step>
4242
4343 <Step title="Register the implementation with the worker">
44 Pass the tool through the worker's `tools` (go: `ToolsFunc`) factory (see [`EnvironmentWorker`](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#environment-worker)), alongside the built-in toolset:
44 Pass the tool through the worker’s `tools` (go: `ToolsFunc`) factory (see [`EnvironmentWorker`](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#environment-worker)), alongside the built-in toolset:
4545
4646 <CodeGroup exclude="shell, csharp, java, php, ruby">
4747 ```python Python
from line 110
110110 ```
111111
112112 <CodeGroupItem language="C#">
113 The C# SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session's event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
113 The C# SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session’s event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
114114 </CodeGroupItem>
115115
116116 ```go Go
from line 175
175175 ```
176176
177177 <CodeGroupItem language="Java">
178 The Java SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session's event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
178 The Java SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session’s event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
179179 </CodeGroupItem>
180180
181181 <CodeGroupItem language="PHP">
182 The PHP SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session's event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
182 The PHP SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session’s event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
183183 </CodeGroupItem>
184184
185185 <CodeGroupItem language="Ruby">
186 The Ruby SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session's event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
186 The Ruby SDK does not have `EnvironmentWorker`. To answer custom tool calls from your own code, send each result on the session’s event stream, as in [Return a custom tool result](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#return-a-custom-tool-result).
187187 </CodeGroupItem>
188188 </CodeGroup>
189189 </Step>
from line 193
193193
194194## Wrap an MCP server as custom tools
195195
196The [MCP connector](https://platform.claude.com/docs/en/managed-agents/mcp-connector) connects to MCP servers from Anthropic's side. A server must therefore expose an HTTP endpoint that Anthropic can reach, directly or through an [MCP tunnel](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview).
196The [MCP connector](https://platform.claude.com/docs/en/managed-agents/mcp-connector) connects to MCP servers from Anthropic’s side. A server must therefore expose an HTTP endpoint that Anthropic can reach, directly or through an [MCP tunnel](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview).
197197
198To use a server that only your network can reach, make the worker the MCP client instead and declare the server's tools as custom tools. The MCP server needs no inbound connectivity from outside your network. Anthropic receives the tool definitions you declare on the agent, each call's input, and the result your worker posts back.
198To use a server that only your network can reach, make the worker the MCP client instead and declare the server’s tools as custom tools. The MCP server needs no inbound connectivity from outside your network. Anthropic receives the tool definitions you declare on the agent, each call’s input, and the result your worker posts back.
199199
200200At runtime the model calls a wrapped tool like any other custom tool:
201201
2022021. The agent emits an `agent.custom_tool_use` event.
2032032. The worker, inside your sandbox, forwards the call over its open MCP session to the server on your network.
2043. The worker posts the server's response as the `user.custom_tool_result`.
2043. The worker posts the server’s response as the `user.custom_tool_result`.
205205
206206### Install an MCP SDK
207207
208The SDK's [Client-side MCP helpers](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#client-side-mcp-helpers) convert the server's tools into the runnable tools the worker accepts. Install an MCP SDK alongside the Anthropic SDK: `pip install "anthropic[mcp]" "mcp>=1.24"` (typescript: `npm install @modelcontextprotocol/sdk`; go: `go get github.com/modelcontextprotocol/go-sdk`; csharp: `dotnet add package ModelContextProtocol`; java: `com.anthropic:anthropic-java-mcp`; php: `composer require mcp/sdk`; ruby: `bundle add mcp faraday event_stream_parser`).
208The SDK’s [Client-side MCP helpers](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#client-side-mcp-helpers) convert the server’s tools into the runnable tools the worker accepts. Install an MCP SDK alongside the Anthropic SDK: `pip install "anthropic[mcp]" "mcp>=1.24"` (typescript: `npm install @modelcontextprotocol/sdk`; go: `go get github.com/modelcontextprotocol/go-sdk`; csharp: `dotnet add package ModelContextProtocol`; java: `com.anthropic:anthropic-java-mcp`; php: `composer require mcp/sdk`; ruby: `bundle add mcp faraday event_stream_parser`).
209209
210210The examples connect without authentication. To send credentials, configure the `http_client` (typescript: `requestInit`; go: `HTTPClient`; csharp: `AdditionalHeaders`; java: `.customizeRequest()`; php, ruby: `headers`) you hand to the MCP transport.
211211
from line 212
212212### Declare and serve the tools
213213
214214<Steps>
215 <Step title="Declare the server's tools on the agent">
216 List the MCP server's tools and declare each one as a `custom` tool. The MCP `name`, `description`, and `inputSchema` map one to one onto the custom tool's fields. If the server paginates its tool list, declare every page; the worker must list the same pages.
215 <Step title="Declare the server’s tools on the agent">
216 List the MCP server’s tools and declare each one as a `custom` tool. The MCP `name`, `description`, and `inputSchema` map one to one onto the custom tool’s fields. If the server paginates its tool list, declare every page; the worker must list the same pages.
217217
218218 <CodeGroup exclude="shell">
219219 ```python Python
from line 759
759759
760760### Tools are declared, not discovered at runtime
761761
762The worker lists the MCP server's tools once at startup and cannot add tools to a running session. When the server's tools change:
762The worker lists the MCP server’s tools once at startup and cannot add tools to a running session. When the server’s tools change:
763763
7647641. Declare them again, on the agent or on an idle session through [Updating the agent configuration](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-agent-configuration).
7657652. Restart the worker.
from line 766
766766
767767### Declarations must fit the Managed Agents API
768768
769The MCP helpers keep the server's names and descriptions, and most schemas pass through unchanged. Rename, trim, or inline where a declaration breaks one of these rules:
769The MCP helpers keep the server’s names and descriptions, and most schemas pass through unchanged. Rename, trim, or inline where a declaration breaks one of these rules:
770770
771771| Field | Rule |
772772| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
from line 773
773773| `name` | Unique per agent. Letters, digits, underscores, and hyphens, 1–128 characters. Cannot match a built-in agent tool such as `bash` or `read`, or use the reserved `mcp__` prefix or `ant__` prefix. |
774774| `description` | Required and non-empty. |
775775| `input_schema` | Accepts the JSON Schema keywords MCP servers commonly emit, such as `additionalProperties` and `title`. Rejects reference keywords such as `$ref` anywhere, and top-level `oneOf`, `anyOf`, and `allOf`. Property names use letters, digits, underscores, dots, and hyphens, 1–64 characters. |
776| The agent's `tools` array | At most 256 entries. Each wrapped tool is one entry, and the built-in toolset is one more. |
776| The agent’s `tools` array | At most 256 entries. Each wrapped tool is one entry, and the built-in toolset is one more. |
777777
778778Two cases need extra work:
779779
780* **Two servers expose the same tool name:** Define the wrapper yourself under a prefixed name and have it call the server's original tool name.
780* **Two servers expose the same tool name:** Define the wrapper yourself under a prefixed name and have it call the server’s original tool name.
781781* **A generator such as Pydantic factors schemas into `$defs`:** Inline those schemas before you declare the tool.
782782
783783### Tool failures surface as error tool results
from line 788
788788
789789### Wrap only servers you operate or trust
790790
791A wrapped tool's name, description, and results enter the model's context like any other tool's. They are untrusted input that can influence what the agent does with its other tools, including `bash` on the worker host. Declare only the tools you intend the agent to use.
791A wrapped tool’s name, description, and results enter the model’s context like any other tool’s. They are untrusted input that can influence what the agent does with its other tools, including `bash` on the worker host. Declare only the tools you intend the agent to use.
792792
793793### Permission policies do not apply
794794
No line in this hunk matches that.