diff --git a/app/en/operate/deploy/helm/_meta.tsx b/app/en/operate/deploy/helm/_meta.tsx
new file mode 100644
index 000000000..7948d31e6
--- /dev/null
+++ b/app/en/operate/deploy/helm/_meta.tsx
@@ -0,0 +1,15 @@
+import type { MetaRecord } from "nextra";
+
+export const meta: MetaRecord = {
+ "internal-networking": {
+ title: "Internal networking",
+ },
+ "ipv6-dual-stack": {
+ title: "IPv6 and dual-stack",
+ },
+ "container-registry": {
+ title: "Use a different container registry",
+ },
+};
+
+export default meta;
diff --git a/app/en/operate/deploy/helm/container-registry/page.mdx b/app/en/operate/deploy/helm/container-registry/page.mdx
new file mode 100644
index 000000000..7c8bf79f2
--- /dev/null
+++ b/app/en/operate/deploy/helm/container-registry/page.mdx
@@ -0,0 +1,133 @@
+---
+title: "Use a different container registry"
+description: "Pull the Helm-installed Arcade platform's images from your own registry mirror, including for air-gapped installs"
+---
+
+import { Callout } from "nextra/components";
+
+# Use a different container registry
+
+This guide covers pulling every image the [Helm-installed Arcade platform](/operate/deploy/helm) needs from a registry you run, instead of Docker Hub.
+
+## When you need it
+
+- Your cluster can't reach Docker Hub, or your policy requires images from an approved registry.
+- You run an air-gapped install.
+- You mirror images to avoid Docker Hub rate limits.
+
+## Values overlay
+
+There's no single registry prefix for the whole chart: set each image's repository to its path in your registry. Copy the images at the tags your chart version uses (see the values reference on [Artifact Hub](https://artifacthub.io/packages/helm/arcade/arcade)).
+
+```yaml
+dockerRegistry:
+ enabled: true
+ existingSecret: arcade-registry-pull # a kubernetes.io/dockerconfigjson Secret
+
+engine:
+ image:
+ repository: registry.example.com/arcadedev/engine
+coordinator:
+ image:
+ repository: registry.example.com/arcadedev/coordinator
+dashboard:
+ image:
+ repository: registry.example.com/arcadedev/dashboard
+experienceApi:
+ image:
+ repository: registry.example.com/arcadedev/experience-api
+workerDefaults:
+ image:
+ repository: registry.example.com/arcadedev/worker
+rbac:
+ openfga:
+ image:
+ repository: registry.example.com/arcadedev/openfga
+postgres:
+ image: registry.example.com/postgres:17-alpine
+
+supportImages:
+ busybox:
+ repository: registry.example.com/busybox
+ curl:
+ repository: registry.example.com/curlimages/curl
+ postgres:
+ repository: registry.example.com/postgres
+ tag: 17-alpine
+
+# Only if Arcade Deploy is enabled
+deployments:
+ image:
+ repository: arcadedev/runner
+ registry:
+ server: registry.example.com
+ imagePullSecrets: [arcade-registry-pull]
+```
+
+### Pull credentials
+
+`dockerRegistry` controls the pull Secret on the Arcade pods:
+
+- `dockerRegistry.enabled` (default `true`) adds an `imagePullSecrets` entry to the Arcade component pods (Arcade Engine, coordinator, dashboard, Experience API, OpenFGA, workers, and the chart's Jobs). Leave it on for the private `arcadedev/*` images or a registry that needs credentials.
+- `dockerRegistry.existingSecret` names a Secret you create in the release namespace, of type `kubernetes.io/dockerconfigjson`. This is the usual choice for a mirror.
+- Without `existingSecret`, the chart generates a Secret named `dockerRegistry.secretName` from `dockerRegistry.server`, `dockerRegistry.username`, and `dockerRegistry.token` (a Docker Hub access token).
+
+
+The bundled PostgreSQL and Redis StatefulSets don't get a pull Secret. If your mirror requires authentication, they can't pull from it. Mirror `postgres.image` to a path your nodes can pull without credentials (for example, through node-level registry credentials), or use external PostgreSQL.
+
+The bundled Redis image is fixed at `docker.io/library/redis:8-alpine`; the chart has no value to change it. To avoid pulling it from Docker Hub, configure a node-level mirror for `docker.io` in your container runtime, or use external Redis (`redis.enabled: false`).
+
+
+### Support images
+
+The init containers use `supportImages.busybox` (`generate-env-file`), `supportImages.curl` (`wait-for-workers`, which must be a real curl image), and `supportImages.postgres` (`wait-for-db`, which needs the `psql` client). Each has `repository`, `tag`, and `pullPolicy`. An empty `supportImages.postgres.repository` falls back to `postgres.image`, so a mirrored `postgres.image` already covers it.
+
+### The Arcade Deploy runner image
+
+If you enable [Arcade Deploy](/build/arcade-deploy), the Arcade Engine starts every deployed server from the runner image in the workers namespace:
+
+- The image is `deployments.registry.server` joined with `deployments.image.repository` (default `arcadedev/runner`). With `deployments.registry.server` empty, the repository is used as-is. Its tag is `deployments.image.tag`, or the chart's app version when that's empty.
+- Deployed server pods use the Secrets listed in `deployments.registry.imagePullSecrets`. These Secrets must exist in the workers namespace (`deployments.namespace`), not the release namespace.
+- When `dockerRegistry.enabled` is on and `dockerRegistry.existingSecret` is empty, the chart also adds `dockerRegistry.secretName` to that list. A Secret you name in `dockerRegistry.existingSecret` isn't added, so list it in `deployments.registry.imagePullSecrets` and create a copy in the workers namespace.
+
+## Air-gapped installs
+
+1. Copy every image above, at your chart version's tags, into your registry. Include the Arcade Deploy runner image if you use Arcade Deploy, and any images your workers list overrides.
+2. Copy the chart itself (`oci://public.ecr.aws/s5i6x9d1/charts/arcade`) into an OCI registry you can reach, and install from there.
+3. Create the pull Secret in the release namespace, and in the workers namespace for Arcade Deploy.
+4. Install with the overlay above.
+
+Image pulls are only part of an air-gapped install: the identity provider, OAuth providers, and any MCP server dependencies also need to be reachable from inside your network.
+
+## Verify it
+
+```bash
+# Every image comes from your registry
+kubectl -n arcade get pods -o jsonpath='{range .items[*]}{range .spec.initContainers[*]}{.image}{"\n"}{end}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' | sort -u
+
+# Pods pulled successfully
+kubectl -n arcade get pods
+kubectl -n arcade get events --field-selector reason=Failed
+```
+
+For Arcade Deploy, deploy a test server and run the same image check in the workers namespace (`arcade-workers` by default).
+
+## Common failures
+
+| Symptom | Likely cause and fix |
+| --- | --- |
+| `ImagePullBackOff` on one component | Its `image.repository` still points at Docker Hub, or the tag isn't mirrored. Check the pod's image and mirror the missing tag. |
+| `ImagePullBackOff` on init containers | `supportImages.*` still point at Docker Hub. Override them. |
+| `401` or `unauthorized` pulling PostgreSQL or Redis | The bundled StatefulSets have no pull Secret, and Redis always pulls from Docker Hub. See the warning under [Pull credentials](#pull-credentials). |
+| `401` or `unauthorized` pulling | The pull Secret is missing, in the wrong namespace, or not `kubernetes.io/dockerconfigjson`. Check `dockerRegistry.existingSecret`. |
+| Deployed servers fail to pull the runner image | The Secret isn't in the workers namespace, or isn't listed in `deployments.registry.imagePullSecrets`. |
+| The runner image path is doubled, for example `registry.example.com/registry.example.com/...` | `deployments.image.repository` includes the registry host while `deployments.registry.server` is also set. Set the host in one place. |
+
+## What you own and what the chart handles
+
+| You | The chart |
+| --- | --- |
+| Running the registry, and mirroring each image at the right tag | Using the repository and tag you set for every image |
+| Creating pull Secrets in the release namespace and the workers namespace | Adding `imagePullSecrets` to Arcade pods when `dockerRegistry.enabled` |
+| Mirroring the chart for air-gapped installs | Generating a pull Secret from `dockerRegistry.username` and `dockerRegistry.token` when you don't bring one |
+| Keeping mirrors current on each upgrade | Building the runner image path from `deployments.registry.server` and passing pull Secrets to deployed servers |
diff --git a/app/en/operate/deploy/helm/internal-networking/page.mdx b/app/en/operate/deploy/helm/internal-networking/page.mdx
new file mode 100644
index 000000000..d95dc5a85
--- /dev/null
+++ b/app/en/operate/deploy/helm/internal-networking/page.mdx
@@ -0,0 +1,112 @@
+---
+title: "Internal networking"
+description: "Run a Helm-installed Arcade platform with no public ingress, behind an internal load balancer or Gateway API, and let it reach MCP servers on your internal network"
+---
+
+import { Callout } from "nextra/components";
+
+# Internal networking
+
+This guide covers running the [Helm-installed Arcade platform](/operate/deploy/helm) entirely inside your network: no public ingress, traffic through an internal load balancer or a Gateway API implementation you run, and MCP servers on internal addresses that the Arcade Engine is allowed to reach.
+
+## When you need it
+
+- Arcade must not be reachable from the internet, only from your corporate network or VPN.
+- Your cluster already exposes internal services through a Gateway API implementation or an internal ingress controller.
+- MCP servers or workers that Arcade calls live on private addresses (for example `10.0.0.0/8` or `*.corp.internal`).
+
+## Values overlay
+
+The chart doesn't create a load balancer itself. Every Arcade Service is `ClusterIP` by default (`engine.service.type`, `coordinator.service.type`, `dashboard.service.type`, `experienceApi.service.type`), and traffic enters through routes the chart renders for your own Gateway or ingress controller. Making that entry point internal is a property of the Gateway or ingress controller you attach to.
+
+### Gateway API (recommended)
+
+The chart renders `HTTPRoute`s, never the `Gateway`; you run that. Whenever `gateway.enabled` is `true` and parent refs are set, the chart also renders an AWS Load Balancer Controller `TargetGroupConfiguration` (`gateway.k8s.aws/v1beta1`) per service to set its health check path. It doesn't check whether that CRD is installed, so on a cluster without the AWS Load Balancer Controller (GKE, AKS, on-premises), `helm install` and `helm upgrade` fail with `no matches for kind TargetGroupConfiguration`. Charts up to 1.11.1 behave this way; a future chart release renders it only when the cluster serves the CRD. Point the routes at an internal Gateway, one whose listener is backed by an internal load balancer in your environment:
+
+```yaml
+gateway:
+ enabled: true
+ parentRefs:
+ - name: arcade-internal-gw
+ namespace: gateway-system
+ sectionName: https
+ hostname: arcade.corp.example.com
+ protocol: https
+
+ingress:
+ enabled: false
+```
+
+A service's route renders only when it has parentRefs: its own `gateway..parentRefs` if set, otherwise the shared `gateway.parentRefs`. With both empty, that service gets no route. Services get hostnames from `gateway.subdomains.*` (`api`, `coordinator`, `dashboard`, `experienceApi`) under `gateway.hostname`. To attach one service to a different Gateway, set its own `gateway..parentRefs` (`engine`, `coordinator`, `dashboard`, `experienceApi`), which replaces the shared list for that service. A service with its own `parentRefs` gets a route even when the shared list is empty. If your controller only serves `v1beta1` routes, set `gateway.apiVersion`.
+
+### Legacy Ingress
+
+The `ingress.*` path is deprecated in favor of `gateway.*`, but still works. Use the private ingress class, the one backed by your internal load balancer:
+
+```yaml
+ingress:
+ enabled: true
+ type: private
+ privateIngressClass: nginx-internal
+ hostname: arcade.corp.example.com
+ privateAnnotations:
+ cert-manager.io/cluster-issuer: selfsigned-ca-issuer
+ nginx.ingress.kubernetes.io/ssl-redirect: "true"
+```
+
+`ingress.type: private` (the default) selects `ingress.privateIngressClass` and `ingress.privateAnnotations`. With `ingress.selfSignedIssuer.enabled` (on by default), the chart also creates a self-signed ClusterIssuer named by `ingress.selfSignedIssuer.name`; replace it with your internal CA's issuer if you have one.
+
+### Let the Arcade Engine reach internal MCP servers
+
+By default the Arcade Engine refuses to dial private and internal addresses from user-created worker and MCP server URLs. List the destinations it may reach in `engine.ssrfAllowlist`:
+
+```yaml
+engine:
+ ssrfAllowlist:
+ - https://tools.corp.example.com:8443 # exact scheme + host [+ port]
+ - "*.corp.internal" # any subdomain of the suffix
+ - 10.20.0.0/16 # CIDR or bare IP, matched against the dialed IP
+```
+
+An empty list (the default) keeps the private-address block. `"*"` turns the check off for every destination; avoid it outside evaluation. Two related lists use the same entry shapes: `engine.authSsrfAllowlist` for tenant-created OAuth provider endpoints (empty by default), and `engine.pluginSsrfAllowlist` for plugin webhook hooks.
+
+
+`engine.pluginSsrfAllowlist` defaults to `["*"]`, so plugin hooks can reach any internal address, cloud metadata included. On an internal network, narrow it to the hook endpoints you use, or set it to `[]` if no hook needs an internal address.
+
+
+### Trust your internal proxy's forwarded headers
+
+If TLS ends at your load balancer or Gateway, the coordinator needs to trust its `X-Forwarded-*` headers to build `https://` sign-in redirects. Set `coordinator.proxyHeaders.forwardedAllowIps` to the pod or Service CIDR of your ingress controller or Gateway data plane (comma-separated); the default trusts only `127.0.0.1`.
+
+## Verify it
+
+```bash
+# Routes attached to your Gateway, and accepted by it
+kubectl -n arcade get httproute
+kubectl -n arcade describe httproute
+
+# No public ingress or LoadBalancer Services from the chart
+kubectl -n arcade get ingress,svc
+```
+
+Then, from a machine inside your network, open the dashboard hostname and sign in. From outside the network, the hostname shouldn't resolve or connect.
+
+## Common failures
+
+| Symptom | Likely cause and fix |
+| --- | --- |
+| No `HTTPRoute` for a service | `gateway.enabled` is `false`, or neither `gateway.parentRefs` nor that service's `gateway..parentRefs` is set. |
+| Routes exist but don't serve traffic | The Gateway doesn't accept them. Check the route's `status.parents` conditions, the listener's `sectionName`, and whether the Gateway allows routes from the release namespace. |
+| Sign-in redirects to `http://` or loops | TLS ends upstream and the coordinator doesn't trust the proxy. Set `coordinator.proxyHeaders.forwardedAllowIps`. |
+| A worker or MCP server on a private address fails to connect | The Arcade Engine's private-address block refused it. Add the host, wildcard, or CIDR to `engine.ssrfAllowlist`. For an OAuth provider endpoint, use `engine.authSsrfAllowlist`. |
+| Connections to an allowed internal address still time out with `networkPolicy.enabled: true` | The chart's egress policy for Arcade pods doesn't include that range. Add it to `networkPolicy.egressCIDRs`. |
+
+## What you own and what the chart handles
+
+| You | The chart |
+| --- | --- |
+| The `Gateway` or ingress controller, and the internal load balancer behind it | `HTTPRoute`s (or Ingress resources) for each Arcade service |
+| Internal DNS records for the hostnames | `ClusterIP` Services for every component |
+| TLS certificates or the issuer for your internal CA | A self-signed ClusterIssuer when `ingress.selfSignedIssuer.enabled` |
+| Firewalls and network reachability between your network and the cluster | The Arcade Engine's private-address block and the allowlists you configure |
+| Choosing which internal destinations Arcade may reach | Optional NetworkPolicies for Arcade pods (`networkPolicy.*`) |
diff --git a/app/en/operate/deploy/helm/ipv6-dual-stack/page.mdx b/app/en/operate/deploy/helm/ipv6-dual-stack/page.mdx
new file mode 100644
index 000000000..16ea2448b
--- /dev/null
+++ b/app/en/operate/deploy/helm/ipv6-dual-stack/page.mdx
@@ -0,0 +1,78 @@
+---
+title: "IPv6 and dual-stack"
+description: "Run the Helm-installed Arcade platform on a dual-stack Kubernetes cluster, and what doesn't support IPv6 yet"
+---
+
+import { Callout } from "nextra/components";
+
+# IPv6 and dual-stack
+
+This guide covers running the [Helm-installed Arcade platform](/operate/deploy/helm) on a dual-stack Kubernetes cluster, and lists the parts that still assume IPv4.
+
+
+Dual-stack is the supported way to serve Arcade over IPv6. IPv6-only clusters aren't supported: several parts of the chart and the Arcade Engine still use IPv4-only addresses (see [What doesn't support IPv6](#what-doesnt-support-ipv6)).
+
+
+## When you need it
+
+- Your cluster is dual-stack and clients reach Arcade over IPv6.
+- Your network policy requires Services to expose both an IPv4 and an IPv6 ClusterIP.
+
+## Values overlay
+
+```yaml
+global:
+ bindAddress: "::"
+ ipFamilyPolicy: PreferDualStack
+ ipFamilies: [IPv4, IPv6]
+```
+
+You usually need both halves:
+
+- `global.bindAddress` sets the address the HTTP servers of the Arcade Engine, coordinator, Experience API, and workers listen on. The dashboard and OpenFGA don't read it; the dashboard already listens on both IPv4 and IPv6. The default `0.0.0.0` listens on IPv4 only. `::` listens on IPv6 and, on Linux, also accepts IPv4 through IPv4-mapped addresses. Brackets are stripped, so `[::]` works too.
+- `global.ipFamilyPolicy` and `global.ipFamilies` set `spec.ipFamilyPolicy` and `spec.ipFamilies` on the Arcade Engine, coordinator, dashboard, Experience API, OpenFGA, worker, and worker-peers Services. The bundled PostgreSQL and Redis Services ignore them and stay on the cluster's default family; the bundled PostgreSQL Service is headless, so it has no ClusterIP at all. `ipFamilyPolicy` takes `SingleStack`, `PreferDualStack`, or `RequireDualStack`. The first entry in `ipFamilies` picks the Service's primary ClusterIP. If you leave both unset, Services get your cluster's default, usually IPv4 single-stack.
+
+`PreferDualStack` falls back to a single family on a cluster that isn't dual-stack. Use `RequireDualStack` if you'd rather the install fail there.
+
+If you enable `networkPolicy.enabled`, `networkPolicy.egressCIDRs` takes IPv6 ranges as well as IPv4 ranges; add the IPv6 ranges Arcade pods need to reach.
+
+## Verify it
+
+```bash
+# Each Arcade Service lists both families and two ClusterIPs (bundled PostgreSQL and Redis stay single-stack)
+kubectl -n arcade get svc -o custom-columns=NAME:.metadata.name,FAMILIES:.spec.ipFamilies,IPS:.spec.clusterIPs
+
+# Pods have an IPv6 address
+kubectl -n arcade get pods -o wide
+```
+
+Then reach the Arcade Engine's IPv6 ClusterIP from a pod in the cluster, for example `curl -g "http://[]:9099/v1/health"`.
+
+## Common failures
+
+| Symptom | Likely cause and fix |
+| --- | --- |
+| Services have an IPv6 ClusterIP, but IPv6 connections are refused | `global.bindAddress` is still `0.0.0.0`. Set it to `::`. |
+| Services stay single-stack | `global.ipFamilyPolicy` is unset or `SingleStack`, or the cluster isn't dual-stack. Set `PreferDualStack`, and check the cluster's Service CIDRs. |
+| `RequireDualStack` Services fail to create | The cluster has no IPv6 Service CIDR. Enable dual-stack on the cluster, or use `PreferDualStack`. |
+| Deployed MCP servers can't reach an IPv6-only destination | Expected: their default egress allows public IPv4 only. See below. |
+
+## What doesn't support IPv6
+
+These parts are IPv4-only today. Plan around them, especially for [Arcade Deploy](/build/arcade-deploy):
+
+- **Deployed MCP servers' outbound traffic.** The NetworkPolicy the Arcade Engine applies to each deployed server allows public egress only to `0.0.0.0/0`, minus private and cluster ranges. There's no IPv6 equivalent, so deployed servers get no IPv6 egress by default. Each `deployments.egressAllowlist` entry becomes its own NetworkPolicy rule, so an IPv6 range listed there may open egress to it, but that path isn't tested.
+- **The private ranges deployed servers are blocked from** are IPv4 (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `100.64.0.0/10`, `169.254.0.0/16`). Don't put IPv6 ranges in `deployments.network.clusterCIDRs`: they're added as exceptions to the IPv4 `0.0.0.0/0` rule.
+- **External DNS for deployed servers.** With `deployments.network.dns.mode: external`, `deployments.network.dns.nameservers` must be public IPv4 addresses. The Arcade Engine refuses to start with an IPv6 nameserver.
+- **Deployed servers' Services** don't set `ipFamilyPolicy` or `ipFamilies`, so they get the cluster's default family. `global.ipFamilyPolicy` doesn't apply to them.
+
+The Arcade Engine's private-address block (for worker, MCP server, and OAuth URLs) does cover IPv6: it blocks `::1`, `::`, `fe80::/10`, `fc00::/7`, and `ff00::/8` alongside the IPv4 private ranges. IPv6 CIDRs and addresses work in `engine.ssrfAllowlist`.
+
+## What you own and what the chart handles
+
+| You | The chart |
+| --- | --- |
+| A dual-stack cluster: pod and Service CIDRs for both families, and a CNI that routes IPv6 | Bind address for Arcade pods (`global.bindAddress`) |
+| IPv6 load balancing, DNS `AAAA` records, and your Gateway or ingress listeners | `ipFamilyPolicy` and `ipFamilies` on the Arcade Engine, coordinator, dashboard, Experience API, OpenFGA, worker, and worker-peers Services (not bundled PostgreSQL/Redis or subcharts) |
+| IPv6 reachability of the bundled PostgreSQL and Redis, or external data stores | IPv6 ranges you list in `networkPolicy.egressCIDRs` |
+| Keeping Arcade Deploy egress needs on IPv4 until IPv6 is supported | |
diff --git a/public/llms.txt b/public/llms.txt
index 9dbeba352..5910249d7 100644
--- a/public/llms.txt
+++ b/public/llms.txt
@@ -1,4 +1,4 @@
-
+
# Arcade
@@ -142,6 +142,8 @@ Arcade docs serve two audiences. Start with the path that matches your goal:
- [Hybrid MCP servers](https://docs.arcade.dev/en/operate/deploy/on-prem): This documentation page explains how to set up a hybrid MCP server that runs on your own infrastructure while connecting to Arcade Cloud, allowing you to access private resources and keep sensitive data within your network. You'll learn how to run an MCP server with HTTP transport, create a secure tunnel to expose it publicly, register it in Arcade, and test it using the Arcade Playground.
- [Identity](https://docs.arcade.dev/en/operate/identity): This page explains how to configure user authentication for Arcade gateways and manage identity providers that connect end users to your system. It provides access to resources for setting up user sources, configuring authentication providers, and implementing secure authentication in production environments.
- [In Custom Applications](https://docs.arcade.dev/en/build/tool-calling/custom-apps): This documentation teaches developers how to integrate Arcade tools into custom applications by managing user authentication, checking authorization status, and retrieving tool definitions programmatically. It provides guides for building tool-calling interfaces that handle these core requirements.
+- [Internal networking](https://docs.arcade.dev/en/operate/deploy/helm/internal-networking): This guide explains how to deploy the Helm-installed Arcade platform entirely within your internal network without public internet access, using an internal load balancer or Gateway API for traffic routing and allowing the Arcade Engine to reach MCP servers on private addresses. It covers configuration for Gateway API (recommended) and legacy Ingress setups, managing SSRF allowlists to permit internal server connections, and trusting forwarded headers from internal proxies.
+- [IPv6 and dual-stack](https://docs.arcade.dev/en/operate/deploy/helm/ipv6-dual-stack): This guide explains how to run the Helm-installed Arcade platform on a dual-stack Kubernetes cluster by configuring bind addresses and IP family policies, while documenting which components don't yet support IPv6. It provides configuration values, verification steps, troubleshooting for common issues, and lists the IPv4-only limitations users need to work around, particularly for deployed MCP servers.
- [Mastra](https://docs.arcade.dev/en/get-started/agent-frameworks/mastra): This documentation page guides users in building a TypeScript AI agent using the Mastra framework, enabling interaction with Gmail and Slack through Arcade tools. Users will learn to create an agent capable of reading emails, sending messages, and summarizing emails for Slack,
- [MCP Gateways](https://docs.arcade.dev/en/operate/governance/mcp-gateways): MCP Gateways allow you to combine tools from multiple MCP servers into a single endpoint, enabling centralized management and simplified access for agents, applications, and IDEs. You can create gateways through a dashboard or AI assistant, configure authentication methods, and connect any MCP client that supports Streamable HTTP transport to access the federated tools.
- [Microsoft Entra ID](https://docs.arcade.dev/en/operate/identity/user-sources/microsoft-entra-id): This documentation page guides users through configuring Microsoft Entra ID as a user source for MCP Gateways, allowing employees with Microsoft work or school accounts to sign in. It provides step-by-step instructions for registering an app in the Microsoft Entra admin center, including creating a client secret and granting the necessary OIDC permissions, which are then used to create the user source in Arcade.
@@ -177,6 +179,7 @@ Arcade docs serve two audiences. Start with the path that matches your goal:
- [Tools](https://docs.arcade.dev/en/resources/tools): This documentation page provides an overview of Arcade's ecosystem for AI tools, enabling users to explore a catalog of pre-built integrations, create custom tools, and contribute their own tools to the community. It outlines the benefits of using Arcade tools, such as built
- [Types of Tools](https://docs.arcade.dev/en/build/create-tools/improve/types-of-tools): Arcade offers two types of tools—Optimized and Unoptimized—that differ in their design approach but work identically through the same interface. Optimized tools are carefully designed to match AI chat interfaces and improve reliability by handling complex workflows automatically, while Unoptimized tools mirror original HTTP endpoints and require more careful evaluation before production use. Both types can be used seamlessly together in Arcade's Dashboard and SDK clients.
- [Understanding `Context` and tools](https://docs.arcade.dev/en/build/create-tools/tool-basics/runtime-data-access): The `Context` class provides tools with access to both runtime capabilities and tool-specific data, such as OAuth tokens, secrets, and user information, as well as features like logging, LLM sampling, user elicitation, and progress reporting. This guide explains how to use the `Context` object that is automatically passed to tools by the MCP server to securely access authentication credentials and leverage runtime features during tool execution.
+- [Use a different container registry](https://docs.arcade.dev/en/operate/deploy/helm/container-registry): This guide explains how to configure a Helm-installed Arcade platform to pull container images from your own registry instead of Docker Hub, which is necessary for air-gapped environments, policy compliance, or to avoid rate limits. It covers setting up image repository paths, configuring pull credentials through Kubernetes Secrets, handling support images and the Arcade Deploy runner image, and provides step-by-step instructions for air-gapped installations.
- [Use Arcade in Claude Code](https://docs.arcade.dev/en/get-started/mcp-clients/claude-code): This documentation page guides users on how to connect Claude Code to an Arcade MCP Gateway using the Arcade Headers authentication mode. It outlines the prerequisites for setup, including creating an Arcade account, obtaining an API key, and creating an Arcade MCP Gateway, and provides step-by-step instructions for adding the gateway as a remote HTTP MCP server in Claude Code.
- [Use Arcade in Claude Desktop](https://docs.arcade.dev/en/get-started/mcp-clients/claude-desktop): This documentation page guides users on how to connect Claude Desktop to an Arcade MCP Gateway, detailing the necessary prerequisites and step-by-step instructions for setting up a custom connector. It emphasizes the importance of configuring the correct authentication settings and provides visual aids to facilitate the
- [Use Arcade in Cursor](https://docs.arcade.dev/en/get-started/mcp-clients/cursor): This documentation page provides a step-by-step guide for connecting Cursor to an Arcade MCP Gateway, enabling users to utilize Arcade tools effectively. It outlines the prerequisites for setup, including creating an Arcade account and obtaining an API key, and offers instructions for configuring Cursor