@@ -30,6 +30,9 @@ import {
3030 installCcwMcp ,
3131 uninstallCcwMcp ,
3232 updateCcwConfig ,
33+ installCcwMcpToCodex ,
34+ uninstallCcwMcpFromCodex ,
35+ updateCcwConfigForCodex ,
3336} from '@/lib/api' ;
3437import { mcpServersKeys } from '@/hooks' ;
3538import { useQueryClient } from '@tanstack/react-query' ;
@@ -77,6 +80,8 @@ export interface CcwToolsMcpCardProps {
7780 onUpdateConfig : ( config : Partial < CcwConfig > ) => void ;
7881 /** Callback when install/uninstall is triggered */
7982 onInstall : ( ) => void ;
83+ /** Installation target: Claude or Codex */
84+ target ?: 'claude' | 'codex' ;
8085}
8186
8287// ========== Constants ==========
@@ -105,6 +110,7 @@ export function CcwToolsMcpCard({
105110 onToggleTool,
106111 onUpdateConfig,
107112 onInstall,
113+ target = 'claude' ,
108114} : CcwToolsMcpCardProps ) {
109115 const { formatMessage } = useIntl ( ) ;
110116 const queryClient = useQueryClient ( ) ;
@@ -117,22 +123,36 @@ export function CcwToolsMcpCard({
117123 const [ isExpanded , setIsExpanded ] = useState ( false ) ;
118124 const [ installScope , setInstallScope ] = useState < 'global' | 'project' > ( 'global' ) ;
119125
126+ const isCodex = target === 'codex' ;
127+
120128 // Mutations for install/uninstall
121129 const installMutation = useMutation ( {
122- mutationFn : ( params : { scope : 'global' | 'project' ; projectPath ?: string } ) =>
123- installCcwMcp ( params . scope , params . projectPath ) ,
130+ mutationFn : isCodex
131+ ? ( ) => installCcwMcpToCodex ( )
132+ : ( params : { scope : 'global' | 'project' ; projectPath ?: string } ) =>
133+ installCcwMcp ( params . scope , params . projectPath ) ,
124134 onSuccess : ( ) => {
125- queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
126- queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfig' ] } ) ;
135+ if ( isCodex ) {
136+ queryClient . invalidateQueries ( { queryKey : [ 'codexMcpServers' ] } ) ;
137+ queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfigCodex' ] } ) ;
138+ } else {
139+ queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
140+ queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfig' ] } ) ;
141+ }
127142 onInstall ( ) ;
128143 } ,
129144 } ) ;
130145
131146 const uninstallMutation = useMutation ( {
132- mutationFn : uninstallCcwMcp ,
147+ mutationFn : isCodex ? uninstallCcwMcpFromCodex : uninstallCcwMcp ,
133148 onSuccess : ( ) => {
134- queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
135- queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfig' ] } ) ;
149+ if ( isCodex ) {
150+ queryClient . invalidateQueries ( { queryKey : [ 'codexMcpServers' ] } ) ;
151+ queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfigCodex' ] } ) ;
152+ } else {
153+ queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
154+ queryClient . invalidateQueries ( { queryKey : [ 'ccwMcpConfig' ] } ) ;
155+ }
136156 onInstall ( ) ;
137157 } ,
138158 onError : ( error ) => {
@@ -141,9 +161,13 @@ export function CcwToolsMcpCard({
141161 } ) ;
142162
143163 const updateConfigMutation = useMutation ( {
144- mutationFn : updateCcwConfig ,
164+ mutationFn : isCodex ? updateCcwConfigForCodex : updateCcwConfig ,
145165 onSuccess : ( ) => {
146- queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
166+ if ( isCodex ) {
167+ queryClient . invalidateQueries ( { queryKey : [ 'codexMcpServers' ] } ) ;
168+ } else {
169+ queryClient . invalidateQueries ( { queryKey : mcpServersKeys . all } ) ;
170+ }
147171 } ,
148172 } ) ;
149173
@@ -170,10 +194,14 @@ export function CcwToolsMcpCard({
170194 } ;
171195
172196 const handleInstallClick = ( ) => {
173- installMutation . mutate ( {
174- scope : installScope ,
175- projectPath : installScope === 'project' ? currentProjectPath : undefined ,
176- } ) ;
197+ if ( isCodex ) {
198+ ( installMutation as any ) . mutate ( undefined ) ;
199+ } else {
200+ ( installMutation as any ) . mutate ( {
201+ scope : installScope ,
202+ projectPath : installScope === 'project' ? currentProjectPath : undefined ,
203+ } ) ;
204+ }
177205 } ;
178206
179207 const handleUninstallClick = ( ) => {
@@ -213,6 +241,11 @@ export function CcwToolsMcpCard({
213241 < Badge variant = { isInstalled ? 'default' : 'secondary' } className = "text-xs" >
214242 { isInstalled ? formatMessage ( { id : 'mcp.ccw.status.installed' } ) : formatMessage ( { id : 'mcp.ccw.status.notInstalled' } ) }
215243 </ Badge >
244+ { isCodex && (
245+ < Badge variant = "outline" className = "text-xs text-blue-500" >
246+ Codex
247+ </ Badge >
248+ ) }
216249 { isInstalled && (
217250 < Badge variant = "outline" className = "text-xs text-info" >
218251 { formatMessage ( { id : 'mcp.ccw.status.special' } ) }
@@ -388,8 +421,8 @@ export function CcwToolsMcpCard({
388421
389422 { /* Install/Uninstall Button */ }
390423 < div className = "pt-3 border-t border-border space-y-3" >
391- { /* Scope Selection */ }
392- { ! isInstalled && (
424+ { /* Scope Selection - Claude only (Codex is always global) */ }
425+ { ! isInstalled && ! isCodex && (
393426 < div className = "space-y-2" >
394427 < p className = "text-xs font-medium text-muted-foreground uppercase" >
395428 { formatMessage ( { id : 'mcp.scope' } ) }
@@ -422,6 +455,12 @@ export function CcwToolsMcpCard({
422455 </ div >
423456 </ div >
424457 ) }
458+ { /* Codex note */ }
459+ { isCodex && ! isInstalled && (
460+ < p className = "text-xs text-muted-foreground" >
461+ { formatMessage ( { id : 'mcp.ccw.codexNote' } ) }
462+ </ p >
463+ ) }
425464 { ! isInstalled ? (
426465 < Button
427466 onClick = { handleInstallClick }
@@ -430,7 +469,7 @@ export function CcwToolsMcpCard({
430469 >
431470 { isPending
432471 ? formatMessage ( { id : 'mcp.ccw.actions.installing' } )
433- : formatMessage ( { id : 'mcp.ccw.actions.install' } )
472+ : formatMessage ( { id : isCodex ? 'mcp.ccw.actions.installCodex' : 'mcp.ccw.actions.install' } )
434473 }
435474 </ Button >
436475 ) : (
0 commit comments