11'use client'
22
3- import type { ReactNode } from 'react'
43import { GitHubConnectionCard } from '@/components/github-connection-card'
54import { GoogleDriveConnectionCard } from '@/components/google-drive-connection-card'
65import { GitLabConnectionCard } from '@/components/gitlab-connection-card'
76import { JiraConnectionCard } from '@/components/jira-connection-card'
8- import { MCPCredentialCard } from '@/components/mcp-credential-card'
97import { PageHeader } from '@/components/page-header'
108import { useIntegrationsStatus } from '@/services/queries/use-integrations'
119import { Loader2 } from 'lucide-react'
1210
13- type FieldDefinition = {
14- name : string
15- label : string
16- type : 'text' | 'password'
17- placeholder ?: string
18- helpText ?: string
19- }
20-
21- type MCPCredentialServer = {
22- displayName : string
23- description : string
24- iconBg ?: string
25- icon ?: ReactNode
26- fields : FieldDefinition [ ]
27- }
28-
29- /**
30- * MCP servers that require user-provided credentials.
31- * Platform-wide no-auth servers (context7, deepwiki, webfetch) are not shown
32- * here — they belong at the project scope, not user-scoped integrations.
33- */
34- const MCP_CREDENTIAL_SERVERS : Record < string , MCPCredentialServer > = {
35- 'mcp-atlassian' : {
36- displayName : 'Jira (MCP)' ,
37- description :
38- 'Provide Jira credentials for the MCP Atlassian server used in agentic sessions' ,
39- iconBg : 'bg-blue-600' ,
40- icon : (
41- < svg className = "w-8 h-8 text-white" fill = "currentColor" viewBox = "0 0 24 24" aria-hidden = "true" >
42- < path d = "M11.571 11.513H0a5.218 5.218 0 0 0 5.232 5.215h2.13v2.057A5.215 5.215 0 0 0 12.575 24V12.518a1.005 1.005 0 0 0-1.005-1.005zm5.723-5.756H5.736a5.215 5.215 0 0 0 5.215 5.214h2.129v2.058a5.218 5.218 0 0 0 5.215 5.214V6.758a1.001 1.001 0 0 0-1.001-1.001zM23.013 0H11.455a5.215 5.215 0 0 0 5.215 5.215h2.129v2.057A5.215 5.215 0 0 0 24 12.483V1.005A1.001 1.001 0 0 0 23.013 0z" />
43- </ svg >
44- ) ,
45- fields : [
46- {
47- name : 'jira_url' ,
48- label : 'Jira URL' ,
49- type : 'text' ,
50- placeholder : 'https://issues.redhat.com' ,
51- } ,
52- {
53- name : 'jira_email' ,
54- label : 'Email' ,
55- type : 'text' ,
56- placeholder : 'you@example.com' ,
57- } ,
58- {
59- name : 'jira_api_token' ,
60- label : 'API Token' ,
61- type : 'password' ,
62- placeholder : 'Your Jira API token' ,
63- helpText : 'Create a token in Jira > Profile > Personal Access Tokens' ,
64- } ,
65- ] ,
66- } ,
67- }
68-
6911type Props = { appSlug ?: string }
7012
7113export default function IntegrationsClient ( { appSlug } : Props ) {
7214 const { data : integrations , isLoading, refetch } = useIntegrationsStatus ( )
7315
74- // Merge known credential servers with any additional servers that have stored credentials
75- const mcpServerNames = new Set < string > ( Object . keys ( MCP_CREDENTIAL_SERVERS ) )
76- if ( integrations ?. mcpServers ) {
77- for ( const name of Object . keys ( integrations . mcpServers ) ) {
78- mcpServerNames . add ( name )
79- }
80- }
81-
8216 return (
8317 < div className = "min-h-screen bg-background" >
8418 { /* Sticky header */ }
@@ -99,70 +33,27 @@ export default function IntegrationsClient({ appSlug }: Props) {
9933 < Loader2 className = "h-8 w-8 animate-spin text-muted-foreground" />
10034 </ div >
10135 ) : (
102- < >
103- < div className = "grid grid-cols-1 md:grid-cols-2 gap-6" >
104- < GitHubConnectionCard
105- appSlug = { appSlug }
106- showManageButton = { true }
107- status = { integrations ?. github }
108- onRefresh = { refetch }
109- />
110- < GoogleDriveConnectionCard
111- showManageButton = { true }
112- status = { integrations ?. google }
113- onRefresh = { refetch }
114- />
115- < GitLabConnectionCard
116- status = { integrations ?. gitlab }
117- onRefresh = { refetch }
118- />
119- < JiraConnectionCard
120- status = { integrations ?. jira }
121- onRefresh = { refetch }
122- />
123- </ div >
124-
125- { /* MCP Servers section — only credential-based servers (user-scoped) */ }
126- { mcpServerNames . size > 0 && (
127- < div className = "mt-8" >
128- < h2 className = "text-lg font-semibold text-foreground mb-4" > MCP Servers</ h2 >
129- < div className = "grid grid-cols-1 md:grid-cols-2 gap-6" >
130- { [ ...mcpServerNames ] . map ( ( name ) => {
131- const entry = MCP_CREDENTIAL_SERVERS [ name ]
132- const serverStatus = integrations ?. mcpServers ?. [ name ]
133- return (
134- < MCPCredentialCard
135- key = { name }
136- serverName = { name }
137- displayName = { entry ?. displayName ?? name }
138- icon = { entry ?. icon }
139- iconBg = { entry ?. iconBg }
140- description = {
141- entry ?. description ?? `Credentials for the ${ name } MCP server`
142- }
143- fields = {
144- entry ?. fields ?? [
145- {
146- name : 'api_key' ,
147- label : 'API Key' ,
148- type : 'password' as const ,
149- placeholder : 'Enter API key' ,
150- } ,
151- ]
152- }
153- status = {
154- serverStatus
155- ? { connected : serverStatus . connected , serverName : name }
156- : { connected : false , serverName : name }
157- }
158- onRefresh = { refetch }
159- />
160- )
161- } ) }
162- </ div >
163- </ div >
164- ) }
165- </ >
36+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-6" >
37+ < GitHubConnectionCard
38+ appSlug = { appSlug }
39+ showManageButton = { true }
40+ status = { integrations ?. github }
41+ onRefresh = { refetch }
42+ />
43+ < GoogleDriveConnectionCard
44+ showManageButton = { true }
45+ status = { integrations ?. google }
46+ onRefresh = { refetch }
47+ />
48+ < GitLabConnectionCard
49+ status = { integrations ?. gitlab }
50+ onRefresh = { refetch }
51+ />
52+ < JiraConnectionCard
53+ status = { integrations ?. jira }
54+ onRefresh = { refetch }
55+ />
56+ </ div >
16657 ) }
16758 </ div >
16859 </ div >
0 commit comments