> ## Documentation Index
> Fetch the complete documentation index at: https://hobbyist-e43fa225.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure a custom code interpreter for agents

> Learn how to configure a custom MCP-based code interpreter for Foundry Agent Service by using Azure Container Apps Dynamic Sessions.

export const ZonePivot = ({group, options = [], defaultValue, label = "Choose an experience"}) => {
  const values = options.map(option => option.id);
  const optionKey = options.map(option => `${option.id}:${option.title}`).join("|");
  const [activePivot, setActivePivot] = useState(defaultValue || values[0]);
  const slugify = value => value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
  const resolvePivot = () => {
    if (typeof window === "undefined") return defaultValue || values[0];
    const params = new URLSearchParams(window.location.search);
    const requested = params.get("pivots");
    if (requested) {
      const requestedIds = requested.split(",").map(value => value.trim()).filter(Boolean);
      const match = requestedIds.find(id => values.includes(id));
      if (match) return match;
    }
    const hash = window.location.hash.replace(/^#/, "");
    if (hash) {
      const match = options.find(option => option.id === hash || slugify(option.title) === hash);
      if (match) return match.id;
    }
    try {
      const stored = window.localStorage.getItem(`foundry-zone-pivot:${group}`);
      if (values.includes(stored)) return stored;
    } catch {
      return defaultValue || values[0];
    }
    return defaultValue || values[0];
  };
  const publishPivotChange = value => {
    if (typeof window === "undefined") return;
    window.dispatchEvent(new CustomEvent("foundry-zone-pivot-change", {
      detail: {
        group,
        value
      }
    }));
  };
  const syncTableOfContents = () => {
    if (typeof window === "undefined") return;
    window.requestAnimationFrame(() => {
      const toc = document.getElementById("table-of-contents-content");
      if (!toc) return;
      const links = Array.from(toc.querySelectorAll('a[href^="#"]'));
      for (const link of links) {
        const item = link.closest("li");
        const rawId = link.getAttribute("href")?.slice(1);
        if (!item || !rawId) continue;
        let id = rawId;
        try {
          id = decodeURIComponent(rawId);
        } catch {}
        item.style.display = document.getElementById(id) ? "" : "none";
      }
    });
  };
  useEffect(() => {
    const resolvedPivot = resolvePivot();
    setActivePivot(resolvedPivot);
    publishPivotChange(resolvedPivot);
    window.setTimeout(syncTableOfContents, 0);
  }, [group, defaultValue, values.join("|"), optionKey]);
  const selectPivot = value => {
    setActivePivot(value);
    if (typeof window !== "undefined") {
      try {
        window.localStorage.setItem(`foundry-zone-pivot:${group}`, value);
      } catch {}
      const url = new URL(window.location.href);
      const current = url.searchParams.get("pivots");
      const preserved = current ? current.split(",").map(id => id.trim()).filter(id => id && !values.includes(id)) : [];
      url.searchParams.set("pivots", [...preserved, value].join(","));
      window.history.replaceState(null, "", `${url.pathname}${url.search}${url.hash}`);
    }
    publishPivotChange(value);
    window.setTimeout(syncTableOfContents, 0);
  };
  if (options.length < 2) return null;
  return <div className="not-prose my-6 border-b border-slate-200 pb-3 dark:border-slate-800">
      <div className="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-500 dark:text-slate-400">
        {label}
      </div>
      <div className="flex flex-wrap gap-2" role="tablist" aria-label={label}>
        {options.map(option => {
    const selected = option.id === activePivot;
    return <button key={option.id} type="button" role="tab" aria-selected={selected} onClick={() => selectPivot(option.id)} className={`rounded-md border px-3 py-1.5 text-sm font-medium transition ${selected ? "border-slate-900 bg-slate-900 text-white shadow-sm dark:border-slate-100 dark:bg-slate-100 dark:text-slate-950" : "border-slate-200 bg-white text-slate-700 hover:border-slate-400 hover:text-slate-950 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-200 dark:hover:border-slate-500"}`}>
              {option.title}
            </button>;
  })}
      </div>
    </div>;
};

export const ZoneContent = ({group, value, options = [], values = [], defaultValue, children}) => {
  const optionKey = options.map(option => `${option.id}:${option.title}`).join("|");
  const [activePivot, setActivePivot] = useState(defaultValue || values[0]);
  const slugify = value => value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
  const resolvePivot = () => {
    if (typeof window === "undefined") return defaultValue || values[0];
    const params = new URLSearchParams(window.location.search);
    const requested = params.get("pivots");
    if (requested) {
      const requestedIds = requested.split(",").map(value => value.trim()).filter(Boolean);
      const match = requestedIds.find(id => values.includes(id));
      if (match) return match;
    }
    const hash = window.location.hash.replace(/^#/, "");
    if (hash) {
      const match = options.find(option => option.id === hash || slugify(option.title) === hash);
      if (match) return match.id;
    }
    try {
      const stored = window.localStorage.getItem(`foundry-zone-pivot:${group}`);
      if (values.includes(stored)) return stored;
    } catch {
      return defaultValue || values[0];
    }
    return defaultValue || values[0];
  };
  useEffect(() => {
    setActivePivot(resolvePivot());
  }, [group, defaultValue, values.join("|"), optionKey]);
  useEffect(() => {
    const onPivotChange = event => {
      if (event.detail?.group === group && values.includes(event.detail.value)) {
        setActivePivot(event.detail.value);
      }
    };
    window.addEventListener("foundry-zone-pivot-change", onPivotChange);
    return () => window.removeEventListener("foundry-zone-pivot-change", onPivotChange);
  }, [group, values.join("|")]);
  if (activePivot !== value) return null;
  return <>{children}</>;
};

<Info>
  Items marked (preview) in this article are currently in public preview. This preview is provided without a service-level agreement, and we don't recommend it for production workloads. Certain features might not be supported or might have constrained capabilities. For more information, see [Supplemental Terms of Use for Microsoft Azure Previews](https://azure.microsoft.com/support/legal/preview-supplemental-terms/).
</Info>

A custom code interpreter gives you full control over the runtime environment for agent-generated Python code. You can configure custom Python packages, compute resources, and [Azure Container Apps environment](https://learn.microsoft.com/azure/container-apps/environment) settings. The code interpreter container exposes a Model Context Protocol (MCP) server.

Use a custom code interpreter when the built-in [Code Interpreter tool for agents](/toolboxes/code-interpreter) doesn't meet your requirements—for example, when you need specific Python packages, custom container images, or dedicated compute resources.

For more information about MCP and how agents connect to MCP tools, see [Connect to Model Context Protocol servers (preview)](/toolboxes/model-context-protocol).

<Tip>
  Consider adding this tool using a [toolbox](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/toolbox). By using a toolbox, you are able to reuse the tool across agents and runtimes, as well as centralizing credential management, versioning, and policy enforcement through a managed MCP endpoint. See the [toolbox quickstart](https://learn.microsoft.com/azure/foundry/agents/quickstarts/quickstart-toolbox-agent).
</Tip>

## Prerequisites

* [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) version 2.60.0 or later.
* Python 3.12 or later for the maintained sample project.
* (Optional) [uv](https://docs.astral.sh/uv/getting-started/installation/) for faster Python package management.
* An Azure subscription and resource group with the following role assignments:
  * [Foundry User](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-user) on the Foundry project for configuring and running the agent after provisioning.

<Info />

> The Foundry RBAC roles were recently renamed. **Foundry User**, **Foundry Owner**, **Foundry Account Owner**, and **Foundry Project Manager** were previously named Azure AI User, Azure AI Owner, Azure AI Account Owner, and Azure AI Project Manager. You might still see the previous names in some places while the rename rolls out. The role IDs and core permissions are unchanged by the rename.

* [Foundry Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles/ai-machine-learning#azure-ai-owner) on the target resource group only while the sample deployment creates the Foundry resources and project connection.
* [Container Apps ManagedEnvironment Contributor](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles/containers#container-apps-managedenvironments-contributor) on the target resource group only while the sample deployment creates the Container Apps environment.

Activate the provisioning roles just in time through Microsoft Entra Privileged Identity Management (PIM), and deactivate them after deployment. Day-to-day agent developers and runtime users don't need these provisioning roles.

* A Microsoft Foundry SDK. See the [quickstart](/get-started/get-started-code) for installation.
* A region supported by both Foundry Agent Service and Azure Container Apps Dynamic Sessions. See [Azure Container Apps Dynamic Sessions regions](https://learn.microsoft.com/azure/container-apps/sessions#regions).

## Usage support

This article uses the Azure CLI and a runnable sample project.

The following table shows SDK and setup support.

| Microsoft Foundry support | Python SDK | C# SDK | JavaScript SDK | Java SDK | REST API | Basic agent setup | Standard agent setup |
| ------------------------- | ---------- | ------ | -------------- | -------- | -------- | ----------------- | -------------------- |
| ✔️                        | ✔️         | ✔️     | ✔️             | ✔️       | ✔️       | -                 | ✔️                   |

For the latest SDK and API support for agents tools, see [Best practices for using tools in Microsoft Foundry Agent Service](/agents/tool-best-practice).

## SDK support

The custom code interpreter uses the MCP tool type. Any SDK that supports MCP tools can create a custom code interpreter agent. The .NET SDK is currently in preview. For the infrastructure provisioning steps (Azure CLI, Bicep), see [Create an agent with custom code interpreter](#create-an-agent-with-custom-code-interpreter).

## Before you begin

This procedure provisions Azure infrastructure, including Azure Container Apps resources. Review your organization's Azure cost and governance requirements before deploying.

## Create an agent with custom code interpreter

The following steps show how to provision the infrastructure and create an agent that uses a custom code interpreter MCP server. The infrastructure setup applies to all languages. Language-specific code samples follow.

### Register the preview feature

Register the MCP server feature for Azure Container Apps Dynamic Sessions:

```console theme={null}
az feature register --namespace Microsoft.App --name SessionPoolsSupportMCP
az provider register -n Microsoft.App
```

### Get the sample code

Clone the [sample code in the GitHub repo](https://github.com/microsoft-foundry/foundry-samples) and navigate to the `samples/python/prompt-agents/code-interpreter-custom` folder in your terminal.

### Provision the infrastructure

The maintained direct-agent sample stores the session pool MCP endpoint in the project connection. Toolbox definitions also require the endpoint as `server_url`. Add this output to the cloned `infra.bicep` file:

```bicep theme={null}
output MCP_SERVER_URL string = sessionPool.properties.mcpServerSettings.mcpServerEndpoint
```

Don't use `poolManagementEndpoint`. That value is the Dynamic Sessions management endpoint, not the MCP server endpoint.

To provision the infrastructure, run the following command by using the Azure CLI (`az`):

```console theme={null}
az deployment group create \
    --name custom-code-interpreter \
    --subscription <your_subscription> \
    --resource-group <your_resource_group> \
    --template-file ./infra.bicep
```

<Note>
  Deployment can take up to one hour, depending on the number of standby instances you request. The dynamic session pool allocation is the longest step.
</Note>

### Configure and run the agent

Copy the `.env.sample` file from the repository to `.env`. Map the Bicep deployment outputs to the matching environment variables:

| Bicep output                     | Environment variable             | Used for                                                                   |
| -------------------------------- | -------------------------------- | -------------------------------------------------------------------------- |
| `AZURE_AI_PROJECT_ENDPOINT`      | `AZURE_AI_PROJECT_ENDPOINT`      | Foundry project endpoint.                                                  |
| `AZURE_AI_CONNECTION_ID`         | `AZURE_AI_CONNECTION_ID`         | Project connection whose target is the custom code interpreter MCP server. |
| `MCP_SERVER_URL`                 | `MCP_SERVER_URL`                 | Session pool MCP endpoint required by toolbox definitions.                 |
| `AZURE_AI_MODEL_DEPLOYMENT_NAME` | `AZURE_AI_MODEL_DEPLOYMENT_NAME` | Agent model deployment.                                                    |

The inline examples use `PROJECT_ENDPOINT` for `AZURE_AI_PROJECT_ENDPOINT` and `MCP_CONNECTION_ID` for `AZURE_AI_CONNECTION_ID`. The maintained direct-agent sample resolves the MCP target through the project connection and uses `https://localhost` as a required placeholder URL. For a toolbox, set `MCP_SERVER_URL` to the `mcpServerEndpoint` output because `MCPToolboxTool` requires `server_url` or `connector_id` even when you also provide a project connection.

Install the Python dependencies and run the maintained sample with one of these command pairs:

```bash theme={null}
uv sync
uv run ./main.py
```

Or create a virtual environment and install the checked-in requirements:

```bash theme={null}
python -m venv .venv
./.venv/bin/pip install -r requirements.txt
./.venv/bin/python ./main.py
```

<ZonePivot group="csharp__java__python__rest__typescript" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} defaultValue="python" />

<ZoneContent group="csharp__java__python__rest__typescript" value="python" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} values={["python", "csharp", "typescript", "java", "rest"]} defaultValue="python">
  ### Code example

  The following Python sample shows how to create an agent with a custom code interpreter MCP tool:

  ```python theme={null}
  from azure.identity import DefaultAzureCredential
  from azure.ai.projects import AIProjectClient
  from azure.ai.projects.models import MCPTool, MCPToolboxTool, PromptAgentDefinition

  # Format: "https://resource_name.ai.azure.com/api/projects/project_name"
  PROJECT_ENDPOINT = "your_project_endpoint"
  MCP_SERVER_URL = "https://your-mcp-server-url"
  # Optional: set to your project connection ID if your MCP server requires authentication
  MCP_CONNECTION_ID = "your-mcp-connection-id"

  # Create clients to call Foundry API
  project = AIProjectClient(
      endpoint=PROJECT_ENDPOINT,
      credential=DefaultAzureCredential(),
  )
  openai = project.get_openai_client()

  # Add the custom code interpreter MCP server to a toolbox. Using a toolbox is the
  # recommended way to give agents tools: you curate tools once and reuse the toolbox
  # across agents. See /azure/foundry/agents/concepts/toolbox-overview
  toolbox = project.toolboxes.create_version(
      name="custom-code-interpreter-toolbox",
      description="Toolbox with the custom code interpreter MCP server",
      tools=[
          MCPToolboxTool(
              server_label="custom-code-interpreter",
              server_url=MCP_SERVER_URL,
              project_connection_id=MCP_CONNECTION_ID,
          )
      ],
  )

  # The toolbox exposes an MCP-compatible endpoint.
  TOOLBOX_MCP_URL = (
      f"{PROJECT_ENDPOINT}/toolboxes/{toolbox.name}"
      f"/versions/{toolbox.version}/mcp?api-version=v1"
  )

  # Create a remote-tool project connection that points at the toolbox endpoint.
  # Use a user Entra token so the caller's identity is passed through
  # (audience https://ai.azure.com). Create the connection once, for example with
  # the Azure Developer CLI:
  #
  #    azd ai connection create custom-code-interpreter-toolbox-conn \
  #      --kind remote-tool \
  #      --target "<TOOLBOX_MCP_URL>" \
  #      --auth-type user-entra-token \
  #      --audience https://ai.azure.com
  TOOLBOX_CONNECTION_NAME = "custom-code-interpreter-toolbox-conn"

  # Create an agent that uses the toolbox as an MCP tool
  agent = project.agents.create_version(
      agent_name="CustomCodeInterpreterAgent",
      definition=PromptAgentDefinition(
          model="gpt-5-mini",
          instructions="You are a helpful assistant that can run Python code to analyze data and solve problems.",
          tools=[
              MCPTool(
                  server_label="toolbox",
                  server_url=TOOLBOX_MCP_URL,
                  require_approval="never",
                  project_connection_id=TOOLBOX_CONNECTION_NAME,
              )
          ],
      ),
      description="Agent with custom code interpreter for data analysis.",
  )
  print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")

  # Test the agent with a simple calculation
  response = openai.responses.create(
      input="Calculate the factorial of 10 using Python.",
      extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
  )
  print(f"Response: {response.output_text}")

  # Clean up
  project.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
  project.toolboxes.delete_toolbox_version(
    toolbox_name=toolbox.name,
    version=toolbox.version,
  )
  print("Agent deleted")
  ```

  ### Expected output

  When you run the sample, you see output similar to:

  ```console theme={null}
  Agent created (id: agent-xxxxxxxxxxxx, name: CustomCodeInterpreterAgent, version: 1)
  Response: The factorial of 10 is 3,628,800. I calculated this using Python's math.factorial() function.
  Agent deleted
  ```

  ### Use a hosted agent

  This sample uses `FoundryChatClient` from the Microsoft Agent Framework and connects to the toolbox MCP endpoint using `FoundryToolbox`.

  ```python theme={null}
  import asyncio

  from agent_framework import Agent
  from agent_framework.foundry import FoundryChatClient, FoundryToolbox
  from azure.identity import AzureCliCredential
  from azure.ai.projects import AIProjectClient
  from azure.ai.projects.models import MCPToolboxTool

  PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"
  MCP_SERVER_URL = "https://your-mcp-server-url"
  # Optional: set to your project connection ID if your MCP server requires authentication
  MCP_CONNECTION_ID = "your-mcp-connection-id"

  async def main() -> None:
      credential = AzureCliCredential()

      # 1. Create the custom code interpreter MCP tool and add it to a toolbox. Using a toolbox is the
      #    recommended way to give agents tools: curate tools once and reuse the
      #    toolbox across agents. See /azure/foundry/agents/concepts/toolbox-overview
      project = AIProjectClient(endpoint=PROJECT_ENDPOINT, credential=credential)
      toolbox = project.toolboxes.create_version(
          name="custom-code-interpreter-toolbox",
          description="Toolbox with the custom code interpreter MCP server",
          tools=[
              MCPToolboxTool(
                  server_label="custom-code-interpreter",
                  server_url=MCP_SERVER_URL,
                  project_connection_id=MCP_CONNECTION_ID,
              )
          ],
      )

      # 2. The toolbox exposes an MCP-compatible endpoint.
      TOOLBOX_MCP_URL = (
          f"{PROJECT_ENDPOINT}/toolboxes/{toolbox.name}"
          f"/versions/{toolbox.version}/mcp?api-version=v1"
      )

      # 3. Attach the toolbox to the hosted agent as an MCP tool.
  , timeout=120.0)
      toolbox_tool = FoundryToolbox(credential, url=TOOLBOX_MCP_URL)

  agent = Agent(
          client=FoundryChatClient(credential=credential),
          instructions="You are a helpful assistant that can run Python code to analyze data and solve problems.",
          tools=[toolbox_tool],
      )

      result = await agent.run("Calculate the factorial of 10 using Python.")
      print(result.text)

      project.toolboxes.delete_toolbox_version(
        toolbox_name=toolbox.name,
        version=toolbox.version,
      )

  if __name__ == "__main__":
      asyncio.run(main())
  ```
</ZoneContent>

<ZoneContent group="csharp__java__python__rest__typescript" value="csharp" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} values={["python", "csharp", "typescript", "java", "rest"]} defaultValue="python">
  ### Code example

  The following C# sample shows how to create an agent with a custom code interpreter MCP tool. For more information about working with MCP tools in .NET, see the [MCP tool sample](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/ai/Azure.AI.Extensions.OpenAI/samples/Sample19_MCP.md) in the Azure SDK for .NET repository on GitHub.

  ```csharp theme={null}
  using System;
  using Azure.AI.Projects;
  using Azure.AI.Extensions.OpenAI;
  using Azure.Identity;

  // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
  var projectEndpoint = "your_project_endpoint";
  var mcpServerUrl = "https://your-mcp-server-url";
  // Optional: set to your project connection ID if your MCP server requires authentication
  var mcpConnectionId = "your-mcp-connection-id";

  // Create project client to call Foundry API
  AIProjectClient projectClient = new(
      endpoint: new Uri(projectEndpoint),
      tokenProvider: new DefaultAzureCredential());

  // Add the custom code interpreter MCP server to a toolbox. Using a toolbox is the
  // recommended way to give agents tools. See /azure/foundry/agents/concepts/toolbox-overview
  // Code runs in a sandboxed Azure Container Apps session.
  McpTool customCodeInterpreter = ResponseTool.CreateMcpTool(
      serverLabel: "custom-code-interpreter",
      serverUri: new Uri(mcpServerUrl));
  customCodeInterpreter.ProjectConnectionId = mcpConnectionId;

  ToolboxVersion toolboxVersion = projectClient.AgentAdministrationClient
      .GetAgentToolboxes().CreateToolboxVersion(
          toolboxName: "custom-code-interpreter-toolbox",
          tools: [ProjectsAgentTool.AsProjectTool(customCodeInterpreter)],
          description: "Toolbox with the custom code interpreter MCP server");

  // The toolbox exposes an MCP-compatible endpoint.
  var toolboxMcpUrl = new Uri(
      $"{projectEndpoint}/toolboxes/{toolboxVersion.Name}" +
      $"/versions/{toolboxVersion.Version}/mcp?api-version=v1");

  // Create a remote-tool project connection that points at the toolbox endpoint.
  // Use a user Entra token so the caller's identity is passed through
  // (audience https://ai.azure.com). Create the connection once, for example
  // with the Azure Developer CLI:
  //
  //    azd ai connection create custom-code-interpreter-toolbox-conn \
  //      --kind remote-tool \
  //      --target "<toolboxMcpUrl>" \
  //      --auth-type user-entra-token \
  //      --audience https://ai.azure.com
  var toolboxConnectionName = "custom-code-interpreter-toolbox-conn";

  McpTool toolboxTool = ResponseTool.CreateMcpTool(
      serverLabel: "toolbox",
      serverUri: toolboxMcpUrl,
      toolCallApprovalPolicy: new McpToolCallApprovalPolicy(
          GlobalMcpToolCallApprovalPolicy.NeverRequireApproval));
  toolboxTool.ProjectConnectionId = toolboxConnectionName;

  DeclarativeAgentDefinition agentDefinition = new(model: "gpt-5-mini")
  {
      Instructions = "You are a helpful assistant that can run Python code to analyze data and solve problems.",
      Tools = { toolboxTool }
  };

  AgentVersion agent = projectClient.AgentAdministrationClient.CreateAgentVersion(
      agentName: "CustomCodeInterpreterAgent",
      options: new(agentDefinition));

  Console.WriteLine($"Agent created: {agent.Name} (version {agent.Version})");

  // Create a response using the agent
  ProjectResponsesClient responseClient = projectClient.ProjectOpenAIClient.GetProjectResponsesClientForAgent(agent.Name);

  ResponseResult response = responseClient.CreateResponse(
      new([ResponseItem.CreateUserMessageItem("Calculate the factorial of 10 using Python.")]));

  Console.WriteLine(response.GetOutputText());

  // Clean up
  projectClient.AgentAdministrationClient.DeleteAgentVersion(
      agentName: agent.Name,
      agentVersion: agent.Version);
  Console.WriteLine("Agent deleted");
  ```

  Delete the toolbox version after the agent no longer references it. See [Delete a toolbox version](/toolboxes/toolbox#delete-a-version) for the verified .NET call.

  ### Expected output

  ```console theme={null}
  Agent created: CustomCodeInterpreterAgent (version 1)
  The factorial of 10 is 3,628,800.
  Agent deleted
  ```

  ### Use a hosted agent

  This sample uses the Microsoft Agent Framework `AddFoundryToolboxes` integration to connect the hosted agent to the toolbox.

  ```csharp theme={null}
  using System;
  using Azure.AI.AgentServer.Responses;
  using Azure.AI.AgentServer.Responses.Models;
  using Azure.AI.OpenAI;
  using Azure.AI.Projects;
  using Azure.AI.Extensions.OpenAI;
  using Azure.Identity;
  using Microsoft.Agents.AI;
  using Microsoft.Agents.AI.Foundry.Hosting;
  using Microsoft.Extensions.DependencyInjection;
  using OpenAI.Chat;

  const string AgentInstructions = "You are a helpful assistant that can run Python code to analyze data and solve problems.";
  const string AgentName = "CustomCodeInterpreterAgent";

  string projectEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
      ?? "https://<account>.services.ai.azure.com/api/projects/<project>";
  string openAiEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
      ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
  string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5-mini";
  string mcpServerUrl = "https://your-mcp-server-url";
  string mcpConnectionId = "your-mcp-connection-id";

  DefaultAzureCredential credential = new();

  // 1. Create the custom code interpreter MCP tool and add it to a toolbox. Using a toolbox is the
  //    recommended way to give agents tools. See /azure/foundry/agents/concepts/toolbox-overview
  AIProjectClient projectClient = new(
      endpoint: new Uri(projectEndpoint),
      tokenProvider: credential);
  McpTool customCodeInterpreter = ResponseTool.CreateMcpTool(
      serverLabel: "custom-code-interpreter",
      serverUri: new Uri(mcpServerUrl));
  customCodeInterpreter.ProjectConnectionId = mcpConnectionId;
  ToolboxVersion toolboxVersion = projectClient.AgentAdministrationClient
      .GetAgentToolboxes().CreateToolboxVersion(
          toolboxName: "custom-code-interpreter-toolbox",
          tools: [ProjectsAgentTool.AsProjectTool(customCodeInterpreter)],
          description: "Toolbox with the custom code interpreter MCP server");

  // Create the hosted agent and register the toolbox integration.
  AIAgent agent = projectClient.AsAIAgent(
      model: deploymentName,
      instructions: "You are a helpful assistant with access to the toolbox tools.",
      name: "hosted-toolbox-agent");

  var builder = WebApplication.CreateBuilder(args);
  builder.Services.AddFoundryResponses(agent);
  builder.Services.AddFoundryToolboxes(credential, toolboxVersion.Name);

  var app = builder.Build();
  app.MapFoundryResponses();
  app.Run();
  ```
</ZoneContent>

<ZoneContent group="csharp__java__python__rest__typescript" value="typescript" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} values={["python", "csharp", "typescript", "java", "rest"]} defaultValue="python">
  ### Code example

  The following TypeScript sample shows how to create an agent with a custom code interpreter MCP tool. For a JavaScript version, see the [MCP tool sample](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/ai/ai-projects/samples/v2/javascript/agents/tools/agentMcp.js) in the Azure SDK for JavaScript repository on GitHub.

  ```typescript theme={null}
  import { DefaultAzureCredential } from "@azure/identity";
  import { AIProjectClient } from "@azure/ai-projects";

  // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
  const PROJECT_ENDPOINT = "your_project_endpoint";
  const MCP_SERVER_URL = "https://your-mcp-server-url";

  export async function main(): Promise<void> {
    // Create clients to call Foundry API
    const project = new AIProjectClient(PROJECT_ENDPOINT, new DefaultAzureCredential());
    const openai = project.getOpenAIClient();

    // Add the custom code interpreter MCP server to a toolbox. Using a toolbox is
    // the recommended way to give agents tools. Code runs in a sandboxed Azure
    // Container Apps session, so the tool uses require_approval: "never".
    // See /azure/foundry/agents/concepts/toolbox-overview
    const toolbox = await project.toolboxes.createVersion(
      "custom-code-interpreter-toolbox",
      [
        {
          type: "mcp",
          server_label: "custom-code-interpreter",
          server_url: MCP_SERVER_URL,
          require_approval: "never",
        },
      ],
      { description: "Toolbox with the custom code interpreter MCP server" },
    );

    // The toolbox exposes an MCP-compatible endpoint.
    const toolboxMcpUrl =
      `${PROJECT_ENDPOINT}/toolboxes/${toolbox.name}` +
      `/versions/${toolbox.version}/mcp?api-version=v1`;

    // Create a remote-tool project connection that points at the toolbox endpoint.
    // Use a user Entra token so the caller's identity is passed through
    // (audience https://ai.azure.com). Create the connection once, for example
    // with the Azure Developer CLI:
    //
    //    azd ai connection create custom-code-interpreter-toolbox-conn \
    //      --kind remote-tool \
    //      --target "<toolboxMcpUrl>" \
    //      --auth-type user-entra-token \
    //      --audience https://ai.azure.com
    const toolboxConnectionName = "custom-code-interpreter-toolbox-conn";

    // Create an agent that uses the toolbox as an MCP tool
    const agent = await project.agents.createVersion("CustomCodeInterpreterAgent", {
      kind: "prompt",
      model: "gpt-5-mini",
      instructions:
        "You are a helpful assistant that can run Python code to analyze data and solve problems.",
      tools: [
        {
          type: "mcp",
          server_label: "toolbox",
          server_url: toolboxMcpUrl,
          require_approval: "never",
          project_connection_id: toolboxConnectionName,
        },
      ],
    });
    console.log(`Agent created (name: ${agent.name}, version: ${agent.version})`);

    // Send a request to the agent
    const response = await openai.responses.create(
      {
        input: "Calculate the factorial of 10 using Python.",
      },
      {
        body: { agent_reference: { name: agent.name, type: "agent_reference" } },
      },
    );
    console.log(`Response: ${response.output_text}`);

    // Clean up
    await project.agents.deleteVersion(agent.name, agent.version);
    await project.toolboxes.deleteVersion(toolbox.name, toolbox.version);
    console.log("Agent deleted");
  }

  main().catch((err) => {
    console.error("The sample encountered an error:", err);
  });
  ```

  ### Expected output

  ```console theme={null}
  Agent created (name: CustomCodeInterpreterAgent, version: 1)
  Response: The factorial of 10 is 3,628,800. I calculated this using Python's math.factorial() function.
  Agent deleted
  ```
</ZoneContent>

<ZoneContent group="csharp__java__python__rest__typescript" value="java" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} values={["python", "csharp", "typescript", "java", "rest"]} defaultValue="python">
  <Tip>
    **Recommended:** For most agents, add tools through a [toolbox](/get-started/toolbox-overview) and attach the toolbox to your agent as an MCP tool. The Java SDK doesn't yet expose a toolbox creation API, so create the toolbox by using the Python, REST API, C#, or TypeScript example, or the [Foundry portal](/toolboxes/toolbox), and then reference its MCP endpoint from your Java agent as an `McpTool`. The following example attaches the toolbox MCP endpoint that contains the custom code interpreter to the agent.
  </Tip>

  Add the dependency to your `pom.xml`:

  ```xml theme={null}
  <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-ai-agents</artifactId>
      <version>2.4.0</version>
  </dependency>
  ```

  ### Code example

  ```java theme={null}
  import com.azure.ai.agents.AgentsClient;
  import com.azure.ai.agents.AgentsClientBuilder;
  import com.azure.ai.agents.ResponsesClient;
  import com.azure.ai.agents.models.AgentReference;
  import com.azure.ai.agents.models.AgentVersionDetails;
  import com.azure.ai.agents.models.AzureCreateResponseOptions;
  import com.azure.ai.agents.models.McpTool;
  import com.azure.ai.agents.models.PromptAgentDefinition;
  import com.azure.identity.DefaultAzureCredentialBuilder;
  import com.openai.models.responses.Response;
  import com.openai.models.responses.ResponseCreateParams;

  import java.util.Collections;

  public class CustomCodeInterpreterExample {
      public static void main(String[] args) {
          // Format: "https://resource_name.ai.azure.com/api/projects/project_name"
          String projectEndpoint = "your_project_endpoint";
          String toolboxMcpUrl = projectEndpoint + "/toolboxes/custom-code-interpreter-toolbox/versions/1/mcp?api-version=v1";
          // Set to the remote-tool project connection that points at the toolbox MCP endpoint.
          String toolboxConnectionId = "custom-code-interpreter-toolbox-conn";

          // Create clients to call Foundry API
          AgentsClientBuilder builder = new AgentsClientBuilder()
              .credential(new DefaultAzureCredentialBuilder().build())
              .endpoint(projectEndpoint);

          AgentsClient agentsClient = builder.buildAgentsClient();
          ResponsesClient responsesClient = builder.buildResponsesClient();

          // Attach the toolbox MCP endpoint as an MCP tool.
          // Uses require_approval: "never" because code runs in a sandboxed Container Apps session.
          McpTool toolboxTool = new McpTool("toolbox")
              .setServerUrl(toolboxMcpUrl)
              .setProjectConnectionId(toolboxConnectionId)
              .setRequireApproval("never");

          PromptAgentDefinition agentDefinition = new PromptAgentDefinition("gpt-5-mini")
              .setInstructions("You are a helpful assistant that can run Python code to analyze data and solve problems.")
              .setTools(Collections.singletonList(toolboxTool));

          AgentVersionDetails agent = agentsClient.createAgentVersion(
              "CustomCodeInterpreterAgent", agentDefinition);
          System.out.printf("Agent created: %s (version %s)%n", agent.getName(), agent.getVersion());

          // Create a response
          AgentReference agentReference = new AgentReference(agent.getName())
              .setVersion(agent.getVersion());

          Response response = responsesClient.createAzureResponse(
              new AzureCreateResponseOptions().setAgentReference(agentReference),
              ResponseCreateParams.builder()
                  .input("Calculate the factorial of 10 using Python."));

          System.out.println("Response: " + response.output());

          // Clean up
          agentsClient.deleteAgentVersion(agent.getName(), agent.getVersion());
          System.out.println("Agent deleted");
      }
  }
  ```

  ### Expected output

  ```console theme={null}
  Agent created: CustomCodeInterpreterAgent (version 1)
  Response: The factorial of 10 is 3,628,800.
  Agent deleted
  ```
</ZoneContent>

<ZoneContent group="csharp__java__python__rest__typescript" value="rest" options={[{"id": "python", "title": "Python"}, {"id": "csharp", "title": "C#"}, {"id": "typescript", "title": "TypeScript"}, {"id": "java", "title": "Java"}, {"id": "rest", "title": "REST"}]} values={["python", "csharp", "typescript", "java", "rest"]} defaultValue="python">
  ### Prerequisites

  Set these environment variables:

  * `FOUNDRY_PROJECT_ENDPOINT`: Your project endpoint URL.
  * `AGENT_TOKEN`: A bearer token for Foundry.

  Get an access token:

  ```bash theme={null}
  export AGENT_TOKEN=$(az account get-access-token --scope "https://ai.azure.com/.default" --query accessToken -o tsv)
  ```

  ### Code example

  #### Create a toolbox with the custom code interpreter

  Add the custom code interpreter by creating a toolbox. Then, attach the toolbox to your agent as an MCP tool. For more information, see [What is a toolbox?](/get-started/toolbox-overview)

  ```bash theme={null}
  curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/toolboxes/custom-code-interpreter-toolbox/versions?api-version=v1" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $AGENT_TOKEN" \
    -d '{
      "description": "Toolbox with the custom code interpreter MCP server",
      "tools": [
        {
          "type": "mcp",
          "server_label": "custom-code-interpreter",
          "server_url": "<MCP_SERVER_URL>",
          "project_connection_id": "<MCP_PROJECT_CONNECTION_ID>",
          "require_approval": "never"
        }
      ]
    }'
  ```

  The toolbox exposes an MCP-compatible endpoint at `$FOUNDRY_PROJECT_ENDPOINT/toolboxes/custom-code-interpreter-toolbox/versions/<version>/mcp?api-version=v1`, where `<version>` is the version returned by the previous call.

  #### Create a remote-tool connection to the toolbox

  Create a remote-tool project connection that points to the toolbox endpoint. Use a user Entra token so the caller's identity is passed through (audience `https://ai.azure.com`):

  ```bash theme={null}
  azd ai connection create custom-code-interpreter-toolbox-conn \
    --kind remote-tool \
    --target "$FOUNDRY_PROJECT_ENDPOINT/toolboxes/custom-code-interpreter-toolbox/versions/<version>/mcp?api-version=v1" \
    --auth-type user-entra-token \
    --audience https://ai.azure.com
  ```

  #### Create an agent that uses the toolbox

  ```bash theme={null}
  curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/agents?api-version=v1" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $AGENT_TOKEN" \
    -d '{
      "name": "CustomCodeInterpreterAgent",
      "definition": {
        "kind": "prompt",
        "model": "<MODEL_DEPLOYMENT>",
        "instructions": "You are a helpful assistant that can run Python code to analyze data and solve problems.",
        "tools": [
          {
            "type": "mcp",
            "server_label": "toolbox",
            "server_url": "'$FOUNDRY_PROJECT_ENDPOINT'/toolboxes/custom-code-interpreter-toolbox/versions/<version>/mcp?api-version=v1",
            "require_approval": "never",
            "project_connection_id": "custom-code-interpreter-toolbox-conn"
          }
        ]
      }
    }'
  ```

  #### Create a response

  ```bash theme={null}
  curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $AGENT_TOKEN" \
    -d '{
      "agent_reference": {"type": "agent_reference", "name": "CustomCodeInterpreterAgent"},
      "input": "Calculate the factorial of 10 using Python."
    }'
  ```

  #### Clean up

  ```bash theme={null}
  curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/agents/CustomCodeInterpreterAgent?api-version=v1" \
    -H "Authorization: Bearer $AGENT_TOKEN"

  curl -X DELETE \
    "$FOUNDRY_PROJECT_ENDPOINT/toolboxes/custom-code-interpreter-toolbox/versions/<version>?api-version=v1" \
    -H "Authorization: Bearer $AGENT_TOKEN"
  ```

  ### Expected output

  ```json theme={null}
  {
    "id": "resp_xxxxxxxxxxxx",
    "output": [
      {
        "type": "message",
        "role": "assistant",
        "content": [
          {
            "type": "output_text",
            "text": "The factorial of 10 is 3,628,800."
          }
        ]
      }
    ]
  }
  ```
</ZoneContent>

## Verify your setup

After you've provisioned the infrastructure and run the sample:

1. Confirm the Azure deployment completed successfully.
2. Confirm the sample connects using the values in your `.env` file.
3. In Microsoft Foundry, verify your agent calls the tool using tracing. For more information, see [Best practices for using tools in Microsoft Foundry Agent Service](/agents/tool-best-practice).

## Troubleshooting

| Issue                                         | Likely cause                                                                                    | Resolution                                                                                                                                                                                                                                                                                  |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Feature registration is still pending         | The `az feature register` command returns `Registering` state.                                  | Wait for registration to complete (can take 15-30 minutes). Check status with `az feature show --namespace Microsoft.App --name SessionPoolsSupportMCP`. Then run `az provider register -n Microsoft.App` again.                                                                            |
| Deployment fails with permission error        | Missing required role assignments.                                                              | For infrastructure deployment, activate **Foundry Owner** and **Container Apps ManagedEnvironment Contributor** on the target resource group through Microsoft Entra PIM. Deactivate them after deployment. For agent operations, confirm you have **Foundry User** on the Foundry project. |
| Deployment fails with region error            | The selected region doesn't support Azure Container Apps Dynamic Sessions.                      | Try a different region. See [Azure Container Apps regions](https://learn.microsoft.com/azure/container-apps/overview#regions) for supported regions.                                                                                                                                        |
| Agent doesn't call the tool                   | The MCP connection isn't configured correctly, or the agent instructions don't prompt tool use. | Use tracing in Microsoft Foundry to confirm tool invocation. Verify the `MCP_SERVER_URL` matches your deployed Container Apps endpoint. See [Best practices](/agents/tool-best-practice).                                                                                                   |
| MCP server connection timeout                 | The Container Apps session pool isn't running or has no standby instances.                      | Check the session pool status in the Azure portal. Increase `standbyInstanceCount` in your Bicep template if needed.                                                                                                                                                                        |
| Code execution fails in container             | Missing Python packages in the custom container.                                                | Update your container image to include required packages. Rebuild and redeploy the container.                                                                                                                                                                                               |
| Authentication error connecting to MCP server | The project connection credentials are invalid or expired.                                      | Regenerate the connection credentials and update the `.env` file. Verify the `MCP_PROJECT_CONNECTION_ID` format.                                                                                                                                                                            |

## Limitations

The APIs don't directly support file input or output, or the use of file stores. To get data in and out, you must use URLs, such as data URLs for small files and Azure Blob Service shared access signature (SAS) URLs for large files.

## Security

Treat generated code and its dependencies as untrusted. Use an approved base image and package allow list, run with the minimum required compute and permissions, and restrict outbound network access to required destinations. Don't mount sensitive data or production credentials into the session.

If you use SAS URLs to pass data in or out of the runtime:

* Use short-lived SAS tokens.
* Don't log SAS URLs or store them in source control.
* Scope permissions to the minimum required (for example, read-only or write-only).

## Clean up

To stop billing for provisioned resources, delete the resources created by the sample deployment. If you used a dedicated resource group for this article, delete the resource group.

## Related content

* [Connect to Model Context Protocol servers (preview)](/toolboxes/model-context-protocol)
* [Azure Container Apps Dynamic Sessions](https://learn.microsoft.com/azure/container-apps/sessions)
* [Code Interpreter tool for agents](/toolboxes/code-interpreter)
