diff --git a/.changeset/smart-items-open.md b/.changeset/smart-items-open.md
new file mode 100644
index 0000000000..8a19135fd7
--- /dev/null
+++ b/.changeset/smart-items-open.md
@@ -0,0 +1,5 @@
+---
+"shadcn": minor
+---
+
+add mcp support for codex
diff --git a/apps/v4/content/docs/(root)/mcp.mdx b/apps/v4/content/docs/(root)/mcp.mdx
index 017fc8cd7b..4db6420715 100644
--- a/apps/v4/content/docs/(root)/mcp.mdx
+++ b/apps/v4/content/docs/(root)/mcp.mdx
@@ -28,6 +28,7 @@ Select your MCP client and follow the instructions to configure the shadcn MCP s
Claude Code
Cursor
VS Code
+ Codex
**Run the following command** in your project:
@@ -69,6 +70,31 @@ Select your MCP client and follow the instructions to configure the shadcn MCP s
- Create a contact form using components from the shadcn registry
+
+
+
+ **Note:** The `shadcn` CLI cannot automatically update `~/.codex/config.toml`.
+ You'll need to add the configuration manually for Codex.
+
+
+ **Run the following command** in your project:
+ ```bash
+ npx shadcn@latest mcp init --client codex
+ ```
+
+ **Then, add the following configuration** to `~/.codex/config.toml`:
+ ```toml
+ [mcp_servers.shadcn]
+ command = "npx"
+ args = ["shadcn@latest", "mcp"]
+ ```
+
+ **Restart Codex** and try the following prompts:
+ - Show me all available components in the shadcn registry
+ - Add the button, dialog and card components to my project
+ - Create a contact form using components from the shadcn registry
+
+
---
@@ -169,6 +195,23 @@ After adding the configuration, open `.vscode/mcp.json` and click **Start** next
See the [VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more details.
+### Codex
+
+
+ **Note:** The `shadcn` CLI cannot automatically update `~/.codex/config.toml`.
+ You'll need to add the configuration manually.
+
+
+To configure MCP in Codex, add the shadcn server to `~/.codex/config.toml`:
+
+```toml title="~/.codex/config.toml" showLineNumbers
+[mcp_servers.shadcn]
+command = "npx"
+args = ["shadcn@latest", "mcp"]
+```
+
+After adding the configuration, restart Codex to load the MCP server.
+
---
## Configuring Registries
diff --git a/apps/v4/content/docs/registry/mcp.mdx b/apps/v4/content/docs/registry/mcp.mdx
index 0a3c40dee1..850a6d68b4 100644
--- a/apps/v4/content/docs/registry/mcp.mdx
+++ b/apps/v4/content/docs/registry/mcp.mdx
@@ -26,6 +26,7 @@ Ask your registry consumers to configure your registry in their `components.json
Claude Code
Cursor
VS Code
+ Codex
**Configure your registry** in your `components.json` file:
@@ -93,6 +94,30 @@ Ask your registry consumers to configure your registry in their `components.json
- Create a landing page using items from the acme registry
+
+
+ **Configure your registry** in your `components.json` file:
+
+ ```json title="components.json" showLineNumbers
+ {
+ "registries": {
+ "@acme": "https://acme.com/r/{name}.json"
+ }
+ }
+ ```
+
+ **Add the following configuration** to `~/.codex/config.toml`:
+ ```toml
+ [mcp_servers.shadcn]
+ command = "npx"
+ args = ["shadcn@latest", "mcp"]
+ ```
+
+ **Restart Codex** and try the following prompts:
+ - Show me the components in the acme registry
+ - Create a landing page using items from the acme registry
+
+
You can read more about the MCP server in the [MCP documentation](/docs/mcp).
diff --git a/packages/shadcn/src/commands/mcp.ts b/packages/shadcn/src/commands/mcp.ts
index 230794fc56..7c576e4e34 100644
--- a/packages/shadcn/src/commands/mcp.ts
+++ b/packages/shadcn/src/commands/mcp.ts
@@ -5,6 +5,7 @@ import { loadEnvFiles } from "@/src/utils/env-loader"
import { getConfig } from "@/src/utils/get-config"
import { getPackageManager } from "@/src/utils/get-package-manager"
import { handleError } from "@/src/utils/handle-error"
+import { highlighter } from "@/src/utils/highlighter"
import { logger } from "@/src/utils/logger"
import { spinner } from "@/src/utils/spinner"
import { updateDependencies } from "@/src/utils/updaters/update-dependencies"
@@ -58,6 +59,15 @@ const CLIENTS = [
},
},
},
+ {
+ name: "codex",
+ label: "Codex",
+ configPath: ".codex/config.toml",
+ config: `[mcp_servers.shadcn]
+command = "npx"
+args = ["shadcn@${SHADCN_MCP_VERSION}", "mcp"]
+`,
+ },
] as const
const DEPENDENCIES = [`shadcn@${SHADCN_MCP_VERSION}`]
@@ -82,7 +92,7 @@ export const mcp = new Command()
})
const mcpInitOptionsSchema = z.object({
- client: z.enum(["claude", "cursor", "vscode"]),
+ client: z.enum(["claude", "cursor", "vscode", "codex"]),
cwd: z.string(),
})
@@ -125,11 +135,52 @@ mcp
cwd,
})
+ const config = await getConfig(options.cwd)
+
+ if (options.client === "codex") {
+ if (config) {
+ await updateDependencies([], DEPENDENCIES, config, {
+ silent: false,
+ })
+ } else {
+ const packageManager = await getPackageManager(options.cwd)
+ const installCommand = packageManager === "npm" ? "install" : "add"
+ const devFlag = packageManager === "npm" ? "--save-dev" : "-D"
+
+ const installSpinner = spinner("Installing dependencies...").start()
+ await execa(
+ packageManager,
+ [installCommand, devFlag, ...DEPENDENCIES],
+ {
+ cwd: options.cwd,
+ }
+ )
+ installSpinner.succeed("Installing dependencies.")
+ }
+
+ logger.break()
+ logger.log("To configure the shadcn MCP server in Codex:")
+ logger.break()
+ logger.log(
+ `1. Open or create the file ${highlighter.info(
+ "~/.codex/config.toml"
+ )}`
+ )
+ logger.log("2. Add the following configuration:")
+ logger.log()
+ logger.info(`[mcp_servers.shadcn]
+command = "npx"
+args = ["shadcn@${SHADCN_MCP_VERSION}", "mcp"]`)
+ logger.break()
+ logger.info("3. Restart Codex to load the MCP server")
+ logger.break()
+ process.exit(0)
+ }
+
const configSpinner = spinner("Configuring MCP server...").start()
const configPath = await runMcpInit(options)
configSpinner.succeed("Configuring MCP server.")
- const config = await getConfig(options.cwd)
if (config) {
await updateDependencies([], DEPENDENCIES, config, {
silent: false,
@@ -173,7 +224,10 @@ async function runMcpInit(options: z.infer) {
}
const configPath = path.join(cwd, clientInfo.configPath)
+ const dir = path.dirname(configPath)
+ await fsExtra.ensureDir(dir)
+ // Handle JSON format.
let existingConfig = {}
try {
const content = await fs.readFile(configPath, "utf-8")
@@ -186,8 +240,6 @@ async function runMcpInit(options: z.infer) {
{ arrayMerge: overwriteMerge }
)
- const dir = path.dirname(configPath)
- await fsExtra.ensureDir(dir)
await fs.writeFile(
configPath,
JSON.stringify(mergedConfig, null, 2) + "\n",