diff --git a/app/en/get-started/_meta.tsx b/app/en/get-started/_meta.tsx
index 93c4fc3af..589f4674e 100644
--- a/app/en/get-started/_meta.tsx
+++ b/app/en/get-started/_meta.tsx
@@ -2,6 +2,7 @@ import type { MetaRecord } from "nextra";
export const meta: MetaRecord = {
"about-arcade": "About Arcade",
+ "agent-plugin": "Agent Plugin",
setup: "Setup",
quickstarts: "Quickstarts",
"agent-frameworks": "Agent Frameworks",
diff --git a/app/en/get-started/agent-plugin/_meta.tsx b/app/en/get-started/agent-plugin/_meta.tsx
new file mode 100644
index 000000000..490a07d94
--- /dev/null
+++ b/app/en/get-started/agent-plugin/_meta.tsx
@@ -0,0 +1,12 @@
+import type { MetaRecord } from "nextra";
+
+export const meta: MetaRecord = {
+ index: {
+ title: "Install",
+ },
+ "whats-included": {
+ title: "What's included",
+ },
+};
+
+export default meta;
diff --git a/app/en/get-started/agent-plugin/page.mdx b/app/en/get-started/agent-plugin/page.mdx
new file mode 100644
index 000000000..af738b88b
--- /dev/null
+++ b/app/en/get-started/agent-plugin/page.mdx
@@ -0,0 +1,208 @@
+---
+title: "Install the Arcade agent plugin"
+description: "Install Arcade in Cursor, Claude Code, VS Code, GitHub Copilot CLI, Codex, or Claude Desktop. Your agent gets tools for every app you connect, with browser sign-in and no API keys."
+---
+
+import { Callout, Tabs } from "nextra/components";
+import { SignupLink } from "@/app/_components/analytics";
+
+# Install the Arcade agent plugin
+
+This guide is for agent developers installing Arcade in their own coding agent or desktop client. Personal installs use Arcade's hosted gateway without creating API keys or configuring a gateway.
+
+
+
+
+Install the Arcade agent plugin in a supported client and connect to its hosted gateway.
+
+
+
+
+
+- A [supported client](/get-started/agent-plugin/whats-included#client-support): Cursor, Claude Code, VS Code, GitHub Copilot CLI, Codex, or Claude Desktop
+- An Arcade account
+- For Claude Code, Claude Cowork, Cursor CLI, and GitHub Copilot CLI: [Node.js](https://nodejs.org/) on the PATH of the host that launches their routing hooks. Those hooks run `node`. Cursor IDE and Cloud Agents, VS Code, Codex, and Claude Desktop Chat do not need Node.js.
+
+
+
+
+
+## Install
+
+
+ The cross-client `npx plugins add` command does not finish every client
+ install. Use the client-native steps below so the gateway and every supported
+ plugin component load together. The install commands below use the plugin
+ repository and are not pinned to a release.
+
+
+
+
+
+Requires [Claude Code 2.1.292 or later](https://code.claude.com/docs/en/discover-plugins#add-and-install-from-your-shell).
+
+1. Install Arcade:
+
+ ```bash
+ claude plugin install arcade --marketplace {{ARCADE_PLUGIN_REPO}}
+ ```
+
+2. Run `/reload-plugins` if Claude Code is already open.
+3. Run `/arcade:try-arcade` to start.
+
+
+Earlier Claude Code versions
+
+Add the marketplace, then install the plugin:
+
+```bash
+claude plugin marketplace add {{ARCADE_PLUGIN_REPO}}
+claude plugin install arcade@arcade
+```
+
+Run `/reload-plugins` if Claude Code is already open.
+
+
+
+
+
+
+1. Add the Arcade marketplace and install the plugin:
+
+ ```bash
+ codex plugin marketplace add {{ARCADE_PLUGIN_REPO}}
+ codex plugin add arcade@arcade
+ ```
+
+2. Start a new Codex session or ChatGPT desktop chat.
+3. Open `/plugins` and confirm **arcade** is installed and enabled.
+4. Confirm the **arcade** MCP server is connected.
+5. Choose `@Arcade` or invoke `$arcade:try-arcade` to start.
+
+
+
+
+**Local installation**
+
+For an individual plan, or a Teams or Enterprise plan with **Allow Local Plugin Imports** enabled:
+
+1. Clone the plugin into Cursor's local plugin directory:
+
+ ```bash
+ git clone https://github.com/{{ARCADE_PLUGIN_REPO}} ~/.cursor/plugins/local/arcade-plugin
+ ```
+
+2. Run **Developer: Reload Window**.
+3. Open **Customize** and confirm the two Arcade skills, `arcade-operator`, rule, and MCP server are present.
+4. Run `/try-arcade` to start.
+
+Keep the clone inside `~/.cursor/plugins/local/`. Cursor ignores symlinks to folders outside that directory.
+
+To update the plugin later:
+
+1. Run `git pull` in `~/.cursor/plugins/local/arcade-plugin`.
+2. Run **Developer: Reload Window**.
+
+**Team marketplace alternative**
+
+Enterprise turns **Allow Local Plugin Imports** off by default. When it is off, Cursor ignores `~/.cursor/plugins/local`. Use a team marketplace:
+
+1. An admin opens **Dashboard → Plugins & MCPs → Team Marketplaces → Add Marketplace → Import from Repo** and pastes `https://github.com/{{ARCADE_PLUGIN_REPO}}`.
+2. Each person opens **Customize**, finds **Arcade**, and selects **Install**.
+
+
+
+
+1. Open the Command Palette and select **Chat: Install Plugin From Source**.
+2. Paste the repository URL:
+
+ ```text
+ https://github.com/{{ARCADE_PLUGIN_REPO}}
+ ```
+
+3. Turn on `chat.plugins.enabled` if needed, then reload VS Code.
+4. Confirm **Arcade** appears under **Agent Plugins → Installed**.
+5. Run **MCP: List Servers**, select **arcade**, and choose **Start Server**.
+6. Sign in when prompted, then return to VS Code and continue the original task.
+7. Run `/arcade:try-arcade` to start.
+
+
+
+
+1. Install with Copilot CLI's plugin command:
+
+ ```bash
+ copilot plugin install {{ARCADE_PLUGIN_REPO}}
+ ```
+
+2. Restart the session or run `/restart`.
+3. Run `/try-arcade` to start.
+
+
+
+
+Requires a [paid Claude plan](https://support.claude.com/en/articles/13837440-use-plugins-in-claude). On Team or Enterprise, your organization must allow this marketplace.
+
+1. Open **Customize → Plugins → Add → Add marketplace → Add from a repository**.
+2. Paste `{{ARCADE_PLUGIN_REPO}}`.
+3. Add **Arcade** from the marketplace.
+4. Open **Arcade → Connectors**, then add and connect **arcade** if it is not connected. Sign in to Arcade when prompted.
+5. Start a new conversation and ask "What can Arcade do?"
+
+On Team or Enterprise, an Owner may need to [add the connector for your organization](https://claude.com/docs/plugins/overview#bundled-connectors) before you can connect it with your account.
+
+Use this flow for Desktop Chat and Cowork. [Installing from the Claude Code command line does not add the plugin to your Claude account](https://claude.com/docs/plugins/overview#find-the-plugin-in-each-app).
+
+
+
+
+Your client must support remote HTTP MCP servers and browser sign-in. This connection includes tools only; it does not install the plugin's skills, subagent, or commands.
+
+1. Add an HTTP MCP server with this URL in your client's MCP settings:
+
+ ```text
+ {{ARCADE_PLUGIN_GATEWAY_URL}}
+ ```
+
+2. Sign in to Arcade in the browser when prompted, then return to your client.
+
+
+
+
+## Install the ChatGPT ZIP
+
+This path requires a ChatGPT account with plugin upload access. For a managed workspace, an eligible owner or admin uploads the plugin; members install it from their workspace's plugin directory.
+
+1. Open [Arcade's official plugin releases](https://github.com/ArcadeAI/arcade-plugin/releases) in your browser.
+2. Expand **Assets** on a release that includes the ChatGPT plugin and download `arcade-chatgpt-{VERSION}.zip`. Do not use GitHub's **Source code (zip)** download. If the ChatGPT ZIP is absent, that release does not include it.
+3. Keep the file compressed. On iPhone, Safari downloads appear in **Files → Browse → iCloud Drive → Downloads**, unless you chose another download location. On Android, find the file in Chrome's **Downloads** or your Files app.
+4. Open [ChatGPT on the web](https://chatgpt.com) in the account and workspace where you want to install Arcade. Use the plugin upload option available to your account and select the downloaded ZIP. For eligible workspace owners and admins, the path is **Admin console → your workspace → Plugins → Add → Upload plugin**.
+5. Select **Install plugin** if prompted, then connect Arcade and sign in when prompted.
+
+If you don't see an upload option, check your account's access or ask your workspace admin. Uploading a ZIP to an ordinary chat does not install it. This installation flow is separate from submitting a plugin for public publication.
+
+**Using a phone:** OpenAI documents plugin-directory installation in the mobile apps, but does not document ZIP upload in those apps or guarantee it in a mobile browser. Use ChatGPT web on a computer if the upload control is unavailable on your phone. After a workspace admin makes Arcade available, install it from that workspace's plugin directory in the mobile app.
+
+Upload availability and where a plugin can run are separate. Plugins marked **Desktop only** require the ChatGPT desktop app.
+
+See [OpenAI's plugin installation guide](https://help.openai.com/en/articles/20001256-plugins-in-chatgpt), [Apple's download instructions](https://support.apple.com/en-us/102440), and [Chrome's Android download instructions](https://support.google.com/chrome/answer/95759?co=GENIE.Platform%3DAndroid&hl=en-GB).
+
+## Sign in
+
+Arcade separates [gateway sign-in from app authorization](/learn/server-level-vs-tool-level-auth):
+
+1. **Into the gateway.** Your client asks you to sign in when it first connects. Sign in to Arcade in the browser so your client can connect to the gateway.
+2. **Into each app.** When a task needs an app, your agent gives you a browser sign-in link for the required permissions. After approval, Arcade stores the authorization. You may need to reconnect if the connection expires or a later task needs additional permissions.
+
+After you finish in the browser, return to your agent and continue the original task. Arcade does not resume it for you.
+
+You never give your agent an API key or a password for either layer. To check or manage connections, ask your agent to "Check my Arcade connection," "Show my connected apps," or "Connect Google." You can connect an app before you need it. Clients that support Arcade commands also provide [command shortcuts](/get-started/agent-plugin/whats-included#commands).
+
+Arcade uses the app connections authorized for your signed-in identity. Authorize only the accounts you intend the agent to use.
+
+## Next steps
+
+- [What's included](/get-started/agent-plugin/whats-included): plugin components and client support
+- [Connect to MCP clients](/get-started/mcp-clients): configure a client against a gateway you control
+- [Integrations catalog](/resources/integrations): every app and toolkit Arcade supports
+- [Agentic development](/get-started/setup/connect-arcade-docs): point your agent at these docs with `llms.txt`
diff --git a/app/en/get-started/agent-plugin/whats-included/page.mdx b/app/en/get-started/agent-plugin/whats-included/page.mdx
new file mode 100644
index 000000000..6061821ad
--- /dev/null
+++ b/app/en/get-started/agent-plugin/whats-included/page.mdx
@@ -0,0 +1,144 @@
+---
+title: "What's included"
+description: "Components bundled with the Arcade agent plugin and support across clients."
+---
+
+import { Code, Table } from "nextra/components";
+
+# What's included
+
+For agent developers using the Arcade plugin, the package includes a connection to Arcade's hosted MCP gateway, two skills, three command shortcuts, and the `arcade-operator` subagent.
+
+## MCP server
+
+The plugin registers an MCP server named `arcade` at `{{ARCADE_PLUGIN_GATEWAY_URL}}`. The gateway provides tools for email, calendar, chat, issues, docs, and other apps.
+
+## Skills
+
+- [`try-arcade`](https://github.com/ArcadeAI/arcade-plugin/blob/v0.3.0/skills/try-arcade/SKILL.md) guides tool selection, app sign-in, and tasks across connected apps.
+- [`scale-arcade`](https://github.com/ArcadeAI/arcade-plugin/blob/v0.3.0/skills/scale-arcade/SKILL.md) guides gateway, tool selection, and end-user identity decisions for a proven workflow.
+
+Skills load when relevant to your request. In Codex and the ChatGPT local runtime, choose `@Arcade` or invoke `$arcade:try-arcade` or `$arcade:scale-arcade`. Codex does not expose these skills as slash commands.
+
+## Subagent
+
+The `arcade-operator` subagent executes app tasks in a separate context and returns the outcome. The `try-arcade` skill delegates to it when the client exposes `arcade-operator`.
+
+The plugin's subagent is [not supported in every client](#client-support).
+
+## Client support
+
+**Every plugin install includes the Arcade MCP server and both skills.** The clients below load those components. Subagent and command support varies by client.
+
+
+
+
+ Client
+ Subagent
+ Commands
+
+
+
+
+ Cursor IDE and Cloud Agents
+ Yes
+ 3 (IDE: plugin page, not / menu)
+
+
+ Cursor CLI
+ Yes
+ 3
+
+
+ Claude Code
CLI and desktop Code tab
+ Yes
+ 3 (/arcade: prefix)
+
+
+ Claude Cowork
No session-start text
+ Yes
+ 3 (/arcade: prefix)
+
+
+ GitHub Copilot CLI
+ Yes
+ None
+
+
+ VS Code (Copilot sessions)
Session and subagent hooks
+ Yes
+ None
+
+
+ Codex / ChatGPT (local)
No lifecycle hooks.
+ No
+ None
+
+
+ Claude Desktop Chat
+ No
+ None
+
+
+
+
+
+Routing details by client
+
+- **Cursor IDE and Cloud Agents:** the always-apply rule provides routing guidance; plugin hooks do not run.
+- **Cursor CLI:** only the session hook runs; the always-apply rule does not load.
+- **Claude Code:** the session, prompt, and subagent hooks run.
+- **Claude Cowork:** prompt and subagent hooks run, but session-start text does not reach the main conversation.
+- **GitHub Copilot CLI:** session and subagent hooks run; prompt-hook output from configuration files does not reach the model.
+- **VS Code:** in VS Code's Copilot sessions, Arcade adds routing guidance when a session or subagent starts.
+- **Codex:** does not run Agent Plugins lifecycle hooks yet.
+- **Claude Desktop Chat:** loads neither the rule nor hooks.
+
+
+
+## Commands
+
+Claude Code and Cowork namespace the commands as `/arcade:arcade-status`, `/arcade:arcade-connect`, and `/arcade:arcade-apps`.
+
+### `/arcade-status`
+
+Reports whether the gateway is reachable, whether you have signed in, and which apps you have authorized.
+
+### `/arcade-connect `
+
+Authorizes an app on demand, so you are not interrupted mid-task.
+
+### `/arcade-apps`
+
+Lists the apps you have connected and lets you disconnect one.
+
+## Rule and hooks
+
+The rule and hooks tell your agent when to use Arcade for app tasks.
+
+The [Agent Plugins](https://agent-plugins.org) 1.0 specification makes only skills and MCP servers portable. Commands, subagents, hooks, and editor rules require client-specific support.
+
+## How Arcade chooses a connection
+
+Arcade prefers the plugin's gateway. If it cannot complete a task for a reason other than sign-in or permission denial, your agent may use another already-authorized connection within the task you approved. It checks the intended app account before using another Arcade gateway. Sign-in and permission failures require your attention. The agent does not switch connections to get around them. The plugin instructs your agent to confirm the action and destination before changing something in an app.
+
+`arcade-operator` falls back only to another authorized Arcade gateway. Fallback to any other tool belongs to the parent agent.
+
+## Privacy
+
+The released plugin turns client-side usage telemetry off in code. No environment setting turns collection on. Requests you make through Arcade still go to its hosted gateway and the apps you authorize. See [Arcade's privacy policy](https://www.arcade.dev/privacy-policy).
+
+## Example requests
+
+- "Send a summary of tomorrow's calendar events to me on Slack."
+- "Read my Granola notes from last week, check them against Linear, and file anything I promised that is not a ticket yet. Wait for me before creating anything."
+- "Find unread mail that needs a reply. Look the sender up in HubSpot if you can, draft a response, and Slack me the draft before sending."
+- "Pull my open GitHub pull requests, my Linear issues, and tomorrow's calendar. Write a standup update and send it to me on Slack."
+- "Search my Drive and Notion for the product spec my team uses, then drop a one-paragraph summary in Slack."
+
+Or ask "What can Arcade do?" and pick a workflow from the answer.
+
+## Next steps
+
+- [Install the Arcade agent plugin](/get-started/agent-plugin): client-native setup and gateway sign-in
+- [Integrations catalog](/resources/integrations): supported apps and toolkits
diff --git a/app/en/get-started/mcp-clients/claude-code/page.mdx b/app/en/get-started/mcp-clients/claude-code/page.mdx
index fcfe7080b..73a553cb5 100644
--- a/app/en/get-started/mcp-clients/claude-code/page.mdx
+++ b/app/en/get-started/mcp-clients/claude-code/page.mdx
@@ -3,6 +3,13 @@ import { SignupLink } from "@/app/_components/analytics";
# Use Arcade in Claude Code
+
+ **Setting Arcade up for yourself?** The [Arcade agent plugin](/get-started/agent-plugin)
+ installs through Claude's plugin marketplace, needs no API key, and signs you
+ in to each app in the browser. This guide is for pointing Claude Code at a
+ gateway you control, with your own tool list and your own end-user identities.
+
+
@@ -44,4 +51,3 @@ claude mcp list
Open Claude Code in your project and ask it to use one of the tools from your gateway.
-
diff --git a/app/en/get-started/mcp-clients/claude-desktop/page.mdx b/app/en/get-started/mcp-clients/claude-desktop/page.mdx
index 9deda727c..b45c6afd1 100644
--- a/app/en/get-started/mcp-clients/claude-desktop/page.mdx
+++ b/app/en/get-started/mcp-clients/claude-desktop/page.mdx
@@ -36,6 +36,14 @@ export const STEP_7_LIGHT_HEIGHT = 2450;
# Use Arcade in Claude Desktop
+
+ **Setting Arcade up for yourself?** Install [the Arcade agent
+ plugin](/get-started/agent-plugin), which needs no API key and
+ authorizes each app in the browser. This guide is for pointing Claude Desktop
+ at a gateway you control, with your own tool list and your own end-user
+ identities.
+
+
diff --git a/app/en/get-started/mcp-clients/cursor/page.mdx b/app/en/get-started/mcp-clients/cursor/page.mdx
index 9e852f132..1fc47e4c3 100644
--- a/app/en/get-started/mcp-clients/cursor/page.mdx
+++ b/app/en/get-started/mcp-clients/cursor/page.mdx
@@ -8,6 +8,13 @@ import { SignupLink } from "@/app/_components/analytics";
# Use Arcade in Cursor
+
+ **Setting Arcade up for yourself?** The [Arcade agent plugin](/get-started/agent-plugin)
+ installs from GitHub through Cursor's plugin flow, needs no API key, and signs
+ you in to each app in the browser. This guide is for pointing Cursor at a
+ gateway you control, with your own tool list and your own end-user identities.
+
+
Cursor is an MCP client. Point it at an Arcade [MCP Gateway](/operate/governance/mcp-gateways) URL over the Streamable HTTP transport and Cursor's agent can call any tool you selected on that gateway — GitHub, Linear, Gmail, Slack, or any other toolkit from the [Arcade integrations catalog](/resources/integrations), plus tools from your own [custom MCP servers](/build/create-tools/tool-basics/build-mcp-server).
diff --git a/app/en/get-started/mcp-clients/github-copilot/page.mdx b/app/en/get-started/mcp-clients/github-copilot/page.mdx
index 7d73779ee..85ceaecc2 100644
--- a/app/en/get-started/mcp-clients/github-copilot/page.mdx
+++ b/app/en/get-started/mcp-clients/github-copilot/page.mdx
@@ -20,6 +20,13 @@ export const VISUAL_STUDIO_STEP_6_HEIGHT = 360;
# Use Arcade in GitHub Copilot
+
+ **Setting Arcade up for yourself?** The [Arcade agent plugin](/get-started/agent-plugin)
+ installs with Copilot CLI's plugin command, needs no API key, and signs you in
+ to each app in the browser. This guide is for pointing Copilot at a gateway
+ you control, with your own tool list and your own end-user identities.
+
+
diff --git a/app/en/get-started/mcp-clients/page.mdx b/app/en/get-started/mcp-clients/page.mdx
index f9e3177b8..c5623b5ef 100644
--- a/app/en/get-started/mcp-clients/page.mdx
+++ b/app/en/get-started/mcp-clients/page.mdx
@@ -9,6 +9,10 @@ import { MCPClientGrid } from "./mcp-client-grid";
You can connect [Arcade MCP servers](/resources/integrations) to MCP-compatible clients and development environments to unlock powerful flows for your agents.
-Every supported MCP client — Cursor, Claude Desktop, Claude Code, VS Code, GitHub Copilot, and Copilot Studio — connects to an Arcade [MCP Gateway](/operate/governance/mcp-gateways) over the Streamable HTTP transport. The gateway decides which tools the client can call: pick from Arcade-hosted toolkits (GitHub, Linear, Gmail, Slack, Google Calendar, Notion, Jira, Confluence, and dozens more in the [integrations catalog](/resources/integrations)), from [remote MCP servers](/operate/governance/remote-mcp-servers) you registered, and from your own [custom MCP servers](/build/create-tools/tool-basics/build-mcp-server) hosted with [Arcade Deploy](/build/arcade-deploy).
+Every supported MCP client, including Cursor, Claude Desktop, Claude Code, VS Code, GitHub Copilot, and Copilot Studio, connects to an Arcade [MCP Gateway](/operate/governance/mcp-gateways) over the Streamable HTTP transport. The gateway decides which tools the client can call: pick from Arcade-hosted toolkits (GitHub, Linear, Gmail, Slack, Google Calendar, Notion, Jira, Confluence, and dozens more in the [integrations catalog](/resources/integrations)), from [remote MCP servers](/operate/governance/remote-mcp-servers) you registered, and from your own [custom MCP servers](/build/create-tools/tool-basics/build-mcp-server) hosted with [Arcade Deploy](/build/arcade-deploy).
+
+## Setting Arcade up for yourself?
+
+These guides assume you want your own gateway, with a tool list and end-user identities you control. If you are setting Arcade up for your own work, the [Arcade agent plugin](/get-started/agent-plugin) is faster: install it through your client's plugin flow, skip the API key, and sign in to each app in the browser.
diff --git a/app/en/get-started/mcp-clients/visual-studio-code/page.mdx b/app/en/get-started/mcp-clients/visual-studio-code/page.mdx
index 1957a3d50..dff90afb6 100644
--- a/app/en/get-started/mcp-clients/visual-studio-code/page.mdx
+++ b/app/en/get-started/mcp-clients/visual-studio-code/page.mdx
@@ -5,6 +5,13 @@ import { SignupLink } from "@/app/_components/analytics";
In this guide, you'll learn how to connect Visual Studio Code to an Arcade MCP Gateway.
+
+ **Setting Arcade up for yourself?** The [Arcade agent plugin](/get-started/agent-plugin)
+ installs from source through the Command Palette, needs no API key, and signs
+ you in to each app in the browser. This guide is for pointing VS Code at a
+ gateway you control, with your own tool list and your own end-user identities.
+
+
**Production end users with their own identities?** If your end users already sign in to Entra ID, Okta, Auth0, Clerk, or another OIDC provider, configure a [User Source](/operate/identity/user-sources) on your gateway. Arcade redirects each end user to your identity provider on sign-in and identifies them by an OIDC subject claim.
@@ -62,4 +69,4 @@ Note: if you are using the Arcade Header auth mode for your MCP Gateway, you wil
}
```
-You will not see the authentication prompts when you start the MCP Server in Visual Studio Code because the API Key is passed directly.
+You will not see the authentication prompts when you start the MCP Server in Visual Studio Code because the config passes the API key directly.
diff --git a/lib/agent-plugin.ts b/lib/agent-plugin.ts
new file mode 100644
index 000000000..49346c987
--- /dev/null
+++ b/lib/agent-plugin.ts
@@ -0,0 +1,13 @@
+/**
+ * Every install surface for the Arcade agent plugin resolves from the values
+ * here. Swapping these constants updates the prose, the copyable commands, and
+ * the one-click install links together.
+ *
+ * MDX pages reach these through `{{TOKEN}}` placeholders — see
+ * `lib/remark-substitute.ts` for the token list.
+ */
+export const AGENT_PLUGIN_ENGINE_PUBLIC_URL = "https://api.arcade.dev";
+export const AGENT_PLUGIN_GATEWAY_SLUG = "arcade";
+export const AGENT_PLUGIN_GATEWAY_URL = `${AGENT_PLUGIN_ENGINE_PUBLIC_URL}/mcp/${AGENT_PLUGIN_GATEWAY_SLUG}`;
+
+export const AGENT_PLUGIN_REPO = "ArcadeAI/arcade-plugin";
diff --git a/lib/remark-substitute.ts b/lib/remark-substitute.ts
new file mode 100644
index 000000000..ab71fb90d
--- /dev/null
+++ b/lib/remark-substitute.ts
@@ -0,0 +1,60 @@
+import type { Root } from "mdast";
+import { visit } from "unist-util-visit";
+import { AGENT_PLUGIN_GATEWAY_URL, AGENT_PLUGIN_REPO } from "./agent-plugin";
+
+/**
+ * Tokens an MDX page can write as `{{NAME}}`. Prose, inline code, fenced code
+ * blocks, and link targets all resolve them, which is why pages use these
+ * instead of importing the constants directly — a fenced code block cannot
+ * interpolate JavaScript.
+ */
+export const substitutions: Record = {
+ ARCADE_PLUGIN_GATEWAY_URL: AGENT_PLUGIN_GATEWAY_URL,
+ ARCADE_PLUGIN_REPO: AGENT_PLUGIN_REPO,
+};
+
+/**
+ * Unknown tokens are left alone. Auth provider reference pages already write
+ * OAuth placeholders such as `{{client_id}}`, and those have to survive to the
+ * rendered page.
+ */
+export function applySubstitutions(value: string): string {
+ let result = value;
+ for (const [token, replacement] of Object.entries(substitutions)) {
+ result = result.split(`{{${token}}}`).join(replacement);
+ }
+ return result;
+}
+
+/**
+ * The shape of a VFile that this plugin touches. Declared here so the plugin
+ * does not depend on `vfile` directly.
+ */
+type SourceFile = { value?: unknown };
+
+export function remarkSubstitute() {
+ return (tree: Root, file: SourceFile) => {
+ // Nextra exports the untouched source string alongside the AST, and that
+ // copy is what feeds the "copy page" button and the markdown the site
+ // serves to agents. Substitute there too, or those readers get the raw
+ // token.
+ if (typeof file.value === "string") {
+ file.value = applySubstitutions(file.value);
+ }
+
+ visit(tree, (node) => {
+ if (
+ node.type === "text" ||
+ node.type === "inlineCode" ||
+ node.type === "code"
+ ) {
+ node.value = applySubstitutions(node.value);
+ return;
+ }
+
+ if (node.type === "link" || node.type === "definition") {
+ node.url = applySubstitutions(node.url);
+ }
+ });
+ };
+}
diff --git a/next.config.ts b/next.config.ts
index c6a53a2a5..e9da6d70c 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -2,6 +2,7 @@ import type { NextConfig } from "next";
import nextra from "nextra";
import { withLlmsTxt } from "./lib/next-plugin-llmstxt";
import { remarkGlossary } from "./lib/remark-glossary";
+import { remarkSubstitute } from "./lib/remark-substitute";
import { stripMarkdownFromSwcPageExtensions } from "./lib/swc-page-extensions";
import { redirects } from "./redirects";
@@ -16,6 +17,7 @@ const withNextra = nextra({
remarkGlossary,
{ glossaryPath: "./app/en/resources/glossary/page.mdx" },
],
+ remarkSubstitute,
],
},
});
diff --git a/public/llms.txt b/public/llms.txt
index 9dbeba352..05f73486c 100644
--- a/public/llms.txt
+++ b/public/llms.txt
@@ -142,6 +142,7 @@ 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.
+- [Install the Arcade agent plugin](https://docs.arcade.dev/en/get-started/agent-plugin): Install Arcade in Cursor, Claude Code, VS Code, GitHub Copilot CLI, Codex, or Claude Desktop. Your agent gets tools for every app you connect, with browser sign-in and no API keys.
- [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.
@@ -188,6 +189,7 @@ Arcade docs serve two audiences. Start with the path that matches your goal:
- [User Sources](https://docs.arcade.dev/en/operate/identity/user-sources): A User Source connects an MCP Gateway to your OIDC identity provider, allowing end users to sign in with their existing identities instead of requiring Arcade to manage them separately. This documentation guides you through registering an OAuth client with your identity provider and creating a User Source in Arcade to enable production authentication for your gateways.
- [User-facing agents](https://docs.arcade.dev/en/build/user-facing-agents): This documentation guides agent developers on building and deploying agents that operate on behalf of end users with proper authorization and authentication. It provides resources for implementing secure authentication in production environments and integrating user authorization into tool-calling workflows.
- [What are tools?](https://docs.arcade.dev/en/build/tool-calling): This documentation page explains what tools are in the context of language models and how Arcade enables tool calling—the ability for AI models to interact with external systems and APIs to accomplish tasks beyond text generation. It covers the use cases for tool calling, how it works, the authorization challenges Arcade solves, and introduces Tool Augmented Generation (TAG) as a flexible alternative to retrieval-based approaches.
+- [What's included](https://docs.arcade.dev/en/get-started/agent-plugin/whats-included): The Arcade MCP server and skills, subagent and command support by client, and routing and authorization boundaries.
- [Why evaluate tools?](https://docs.arcade.dev/en/build/create-tools/evaluate-tools/why-evaluate): Tool evaluations ensure AI models use your tools correctly in production by measuring whether the model selects the right tools and provides accurate parameters before deployment. Without evaluation, models risk misinterpreting user intents, providing incorrect arguments, or skipping necessary tool calls, which Arcade's evaluation framework helps prevent by comparing actual tool calls against expected ones and scoring them based on tool selection and parameter accuracy.
- [Windows environment setup](https://docs.arcade.dev/en/get-started/setup/windows-environment): This documentation page provides step-by-step instructions for setting up the Arcade CLI on Windows, emphasizing the use of the `uv` package manager while offering fallback options with `pip`. It includes prerequisites, installation methods, validation steps, and troubleshooting tips to ensure
diff --git a/redirects.ts b/redirects.ts
index c602ed79d..f8172aa0e 100644
--- a/redirects.ts
+++ b/redirects.ts
@@ -16,6 +16,27 @@ export type Redirect = {
};
export const redirects: Redirect[] = [
+ // Retired agent-plugin guides.
+ {
+ source: "/:locale/get-started/agent-plugin/tools-only",
+ destination: "/:locale/get-started/agent-plugin",
+ permanent: true,
+ },
+ {
+ source: "/:locale/get-started/agent-plugin/tools-only/claude-desktop",
+ destination: "/:locale/get-started/agent-plugin",
+ permanent: true,
+ },
+ {
+ source: "/:locale/get-started/agent-plugin/tools-only/any-mcp-client",
+ destination: "/:locale/get-started/mcp-clients",
+ permanent: true,
+ },
+ {
+ source: "/:locale/get-started/agent-plugin/team-rollout",
+ destination: "/:locale/operate/governance/mcp-gateways",
+ permanent: true,
+ },
// The toolkit-page breadcrumb links "Resources" -> /resources, which has
// no index page. Send it to the integrations registry instead of 404ing.
{
@@ -1170,4 +1191,14 @@ export const redirects: Redirect[] = [
destination: "/:locale/build",
permanent: true,
},
+ {
+ source: "/:locale/get-started/agent-plugin/any-mcp-client",
+ destination: "/:locale/get-started/mcp-clients",
+ permanent: true,
+ },
+ {
+ source: "/:locale/get-started/agent-plugin/claude-desktop",
+ destination: "/:locale/get-started/agent-plugin",
+ permanent: true,
+ },
];
diff --git a/styles/config/vocabularies/Arcade/accept.txt b/styles/config/vocabularies/Arcade/accept.txt
index b8ee8f233..83516eeaa 100644
--- a/styles/config/vocabularies/Arcade/accept.txt
+++ b/styles/config/vocabularies/Arcade/accept.txt
@@ -13,6 +13,7 @@ Entra ID
Stytch
Connected App
Connected Apps
+Claude Desktop
LLM
SDK
API
diff --git a/tests/broken-link-check.test.ts b/tests/broken-link-check.test.ts
index 593a89eac..d505e97da 100644
--- a/tests/broken-link-check.test.ts
+++ b/tests/broken-link-check.test.ts
@@ -3,6 +3,7 @@ import { join } from "node:path";
import fg from "fast-glob";
import { scanURLs, validateFiles } from "next-validate-link";
import { expect, test } from "vitest";
+import { applySubstitutions } from "@/lib/remark-substitute";
import {
INTEGRATION_CATEGORIES,
normalizeToolkitId,
@@ -256,7 +257,15 @@ test(
return false;
};
- const found = await validateFiles(await fg("app/**/*.{md,mdx}"), {
+ // Pages write `{{TOKEN}}` placeholders for values that live in one place in
+ // the codebase, so resolve them before validating or the checker sees the
+ // literal token as a relative path.
+ const files = (await fg("app/**/*.{md,mdx}")).map((path) => ({
+ path,
+ content: applySubstitutions(readFileSync(path, "utf-8")),
+ }));
+
+ const found = await validateFiles(files, {
scanned,
whitelist,
});
diff --git a/tests/mdx-page-metadata.test.ts b/tests/mdx-page-metadata.test.ts
index ec5378946..c9d182ca9 100644
--- a/tests/mdx-page-metadata.test.ts
+++ b/tests/mdx-page-metadata.test.ts
@@ -2,6 +2,8 @@ import { existsSync, readFileSync } from "node:fs";
import { readdir } from "node:fs/promises";
import { join, relative } from "node:path";
import type { NextConfig } from "next";
+import { createElement } from "react";
+import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, test } from "vitest";
import { stripMarkdownFromSwcPageExtensions } from "../lib/swc-page-extensions";
@@ -228,7 +230,10 @@ describe("MDX pages", () => {
}
const renderedTitle =
readFileSync(html, "utf8").match(HTML_TITLE_RE)?.[1] ?? "";
- if (!renderedTitle.includes(frontmatterTitle)) {
+ const escapedTitle = renderToStaticMarkup(
+ createElement("title", null, frontmatterTitle)
+ ).match(HTML_TITLE_RE)?.[1];
+ if (!(escapedTitle && renderedTitle.includes(escapedTitle))) {
mismatches.push(
`${relative(process.cwd(), page)}: expected "${frontmatterTitle}" in "${renderedTitle}"`
);
diff --git a/tests/remark-substitute.test.ts b/tests/remark-substitute.test.ts
new file mode 100644
index 000000000..5be6e3dc5
--- /dev/null
+++ b/tests/remark-substitute.test.ts
@@ -0,0 +1,82 @@
+import type { Code, Link, Paragraph, Root, Text } from "mdast";
+import { describe, expect, it } from "vitest";
+import { AGENT_PLUGIN_GATEWAY_URL } from "@/lib/agent-plugin";
+import { applySubstitutions, remarkSubstitute } from "@/lib/remark-substitute";
+
+const substitute = remarkSubstitute();
+
+describe("applySubstitutions", () => {
+ it("replaces a known token", () => {
+ expect(applySubstitutions("Paste {{ARCADE_PLUGIN_GATEWAY_URL}}")).toBe(
+ `Paste ${AGENT_PLUGIN_GATEWAY_URL}`
+ );
+ });
+
+ it("replaces every occurrence of a token", () => {
+ const result = applySubstitutions(
+ "{{ARCADE_PLUGIN_REPO}} and {{ARCADE_PLUGIN_REPO}}"
+ );
+ expect(result).toBe("ArcadeAI/arcade-plugin and ArcadeAI/arcade-plugin");
+ });
+
+ it("leaves unknown tokens alone so OAuth placeholders survive", () => {
+ expect(applySubstitutions('client_id: "{{client_id}}"')).toBe(
+ 'client_id: "{{client_id}}"'
+ );
+ });
+});
+
+describe("remarkSubstitute", () => {
+ it("substitutes in the raw source Nextra exports for copy-page and agents", () => {
+ const file = {
+ value: "Paste {{ARCADE_PLUGIN_GATEWAY_URL}} as an MCP server.",
+ };
+ const tree: Root = { type: "root", children: [] };
+
+ substitute(tree, file);
+
+ expect(file.value).toBe(
+ `Paste ${AGENT_PLUGIN_GATEWAY_URL} as an MCP server.`
+ );
+ });
+
+ it("substitutes inside fenced code blocks", () => {
+ const code: Code = {
+ type: "code",
+ lang: "text",
+ value: "{{ARCADE_PLUGIN_GATEWAY_URL}}",
+ };
+ const tree: Root = { type: "root", children: [code] };
+
+ substitute(tree, {});
+
+ expect(code.value).toBe(AGENT_PLUGIN_GATEWAY_URL);
+ });
+
+ it("substitutes inside link targets", () => {
+ const link: Link = {
+ type: "link",
+ url: "{{ARCADE_PLUGIN_GATEWAY_URL}}",
+ children: [],
+ };
+ const paragraph: Paragraph = { type: "paragraph", children: [link] };
+ const tree: Root = { type: "root", children: [paragraph] };
+
+ substitute(tree, {});
+
+ expect(link.url).toBe(AGENT_PLUGIN_GATEWAY_URL);
+ });
+
+ it("substitutes inside prose", () => {
+ const text: Text = {
+ type: "text",
+ value: "Install {{ARCADE_PLUGIN_REPO}} to start.",
+ };
+ const paragraph: Paragraph = { type: "paragraph", children: [text] };
+ const tree: Root = { type: "root", children: [paragraph] };
+
+ substitute(tree, {});
+
+ expect(text.value).toBe("Install ArcadeAI/arcade-plugin to start.");
+ });
+});