@@ -12,6 +12,7 @@ import { server } from '@/src/mcp'
12
12
import { loadEnvFiles } from '@/src/utils/env-loader'
13
13
import { getConfig } from '@/src/utils/get-config'
14
14
import { handleError } from '@/src/utils/handle-error'
15
+ import { highlighter } from '@/src/utils/highlighter'
15
16
import { logger } from '@/src/utils/logger'
16
17
import { spinner } from '@/src/utils/spinner'
17
18
import { updateDependencies } from '@/src/utils/updaters/update-dependencies'
@@ -58,6 +59,15 @@ const CLIENTS = [
58
59
} ,
59
60
} ,
60
61
} ,
62
+ {
63
+ name : 'codex' ,
64
+ label : 'Codex' ,
65
+ configPath : '.codex/config.toml' ,
66
+ config : `[mcp_servers.shadcn_vue]
67
+ command = "npx"
68
+ args = ["shadcn-vue@${ SHADCN_MCP_VERSION } ", "mcp"]
69
+ ` ,
70
+ } ,
61
71
] as const
62
72
63
73
const DEPENDENCIES = [ `shadcn-vue@${ SHADCN_MCP_VERSION } ` ]
@@ -83,7 +93,7 @@ export const mcp = new Command()
83
93
} )
84
94
85
95
const mcpInitOptionsSchema = z . object ( {
86
- client : z . enum ( [ 'claude' , 'cursor' , 'vscode' ] ) ,
96
+ client : z . enum ( [ 'claude' , 'cursor' , 'vscode' , 'codex' ] ) ,
87
97
cwd : z . string ( ) ,
88
98
} )
89
99
@@ -126,11 +136,55 @@ mcp
126
136
cwd,
127
137
} )
128
138
139
+ const config = await getConfig ( options . cwd )
140
+
141
+ if ( options . client === 'codex' ) {
142
+ if ( config ) {
143
+ await updateDependencies ( [ ] , DEPENDENCIES , config , {
144
+ silent : false ,
145
+ } )
146
+ }
147
+ else {
148
+ const packageManager = await detectPackageManager ( options . cwd )
149
+ const installCommand = packageManager ?. name === 'npm' ? 'install' : 'add'
150
+ const devFlag = packageManager ?. name === 'npm' ? '--save-dev' : '-D'
151
+
152
+ const installSpinner = spinner ( 'Installing dependencies...' ) . start ( )
153
+ await x (
154
+ packageManager ?. name || 'npm' ,
155
+ [ installCommand , devFlag , ...DEPENDENCIES ] ,
156
+ {
157
+ nodeOptions : {
158
+ cwd : options . cwd ,
159
+ } ,
160
+ } ,
161
+ )
162
+ installSpinner . succeed ( 'Installing dependencies.' )
163
+ }
164
+
165
+ logger . break ( )
166
+ logger . log ( 'To configure the shadcn-vue MCP server in Codex:' )
167
+ logger . break ( )
168
+ logger . log (
169
+ `1. Open or create the file ${ highlighter . info (
170
+ '~/.codex/config.toml' ,
171
+ ) } `,
172
+ )
173
+ logger . log ( '2. Add the following configuration:' )
174
+ logger . log ( )
175
+ logger . info ( `[mcp_servers.shadcn_vue]
176
+ command = "npx"
177
+ args = ["shadcn-vue@${ SHADCN_MCP_VERSION } ", "mcp"]` )
178
+ logger . break ( )
179
+ logger . info ( '3. Restart Codex to load the MCP server' )
180
+ logger . break ( )
181
+ process . exit ( 0 )
182
+ }
183
+
129
184
const configSpinner = spinner ( 'Configuring MCP server...' ) . start ( )
130
185
const configPath = await runMcpInit ( options )
131
186
configSpinner . succeed ( 'Configuring MCP server.' )
132
187
133
- const config = await getConfig ( options . cwd )
134
188
if ( config ) {
135
189
await updateDependencies ( [ ] , DEPENDENCIES , config , {
136
190
silent : false ,
@@ -178,6 +232,8 @@ async function runMcpInit(options: z.infer<typeof mcpInitOptionsSchema>) {
178
232
}
179
233
180
234
const configPath = path . join ( cwd , clientInfo . configPath )
235
+ const dir = path . dirname ( configPath )
236
+ await fsExtra . ensureDir ( dir )
181
237
182
238
let existingConfig = { }
183
239
try {
@@ -192,8 +248,6 @@ async function runMcpInit(options: z.infer<typeof mcpInitOptionsSchema>) {
192
248
{ arrayMerge : overwriteMerge } ,
193
249
)
194
250
195
- const dir = path . dirname ( configPath )
196
- await fsExtra . ensureDir ( dir )
197
251
await fs . writeFile (
198
252
configPath ,
199
253
`${ JSON . stringify ( mergedConfig , null , 2 ) } \n` ,
0 commit comments