@@ -15,18 +15,31 @@ interface EnvironmentVariable {
1515 visible_to_users? : boolean
1616}
1717
18+ interface ArgumentSchema {
19+ name: string
20+ type? : string
21+ description? : string
22+ placeholder? : string
23+ required? : boolean
24+ locked? : boolean
25+ default_team_locked? : boolean
26+ }
27+
1828interface ServerData {
1929 id: string
2030 name: string
2131 description? : string
2232 author_name? : string
2333 category_id? : string
34+ team_args_schema? : string | ArgumentSchema []
2435 team_env_schema? : string | EnvironmentVariable []
36+ user_args_schema? : string | ArgumentSchema []
2537 user_env_schema? : string | EnvironmentVariable []
2638 [key : string ]: unknown
2739}
2840
2941const modelValue = defineModel <{
42+ team_args: string []
3043 team_env: Record <string , string >
3144 user_env: Record <string , string >
3245}>({ required: true })
@@ -55,17 +68,43 @@ const parseEnvSchema = (schema: string | EnvironmentVariable[] | undefined): Env
5568 }
5669}
5770
71+ const parseArgsSchema = (schema : string | ArgumentSchema [] | undefined ): ArgumentSchema [] => {
72+ if (! schema ) return []
73+
74+ try {
75+ const parsed = typeof schema === ' string' ? JSON .parse (schema ) : schema
76+ return Array .isArray (parsed ) ? parsed : []
77+ } catch (error ) {
78+ console .error (' Error parsing arguments schema:' , error )
79+ return []
80+ }
81+ }
82+
83+ const teamArgsSchema = computed (() => parseArgsSchema (props .serverData ?.team_args_schema ))
5884const teamEnvSchema = computed (() => parseEnvSchema (props .serverData ?.team_env_schema ))
85+ const userArgsSchema = computed (() => parseArgsSchema (props .serverData ?.user_args_schema ))
5986const userEnvSchema = computed (() => parseEnvSchema (props .serverData ?.user_env_schema ))
6087
88+ const hasTeamArgs = computed (() => teamArgsSchema .value .length > 0 )
6189const hasTeamEnvVars = computed (() => teamEnvSchema .value .length > 0 )
90+ const hasUserArgs = computed (() => userArgsSchema .value .length > 0 )
6291const hasUserEnvVars = computed (() => userEnvSchema .value .length > 0 )
63- const hasAnyEnvVars = computed (() => hasTeamEnvVars .value || hasUserEnvVars .value )
92+ const hasUserConfiguration = computed (() => hasUserArgs .value || hasUserEnvVars .value )
93+ const hasAnyConfiguration = computed (() => hasTeamArgs .value || hasTeamEnvVars .value || hasUserConfiguration .value )
6494
65- const validateTeamEnvVars = () => {
95+ const validateConfiguration = () => {
6696 const missingFields: string [] = []
6797 let isValid = true
6898
99+ // Validate team arguments
100+ teamArgsSchema .value .forEach ((arg , index ) => {
101+ if (arg .required && ! modelValue .value .team_args [index ]?.trim ()) {
102+ missingFields .push (arg .name )
103+ isValid = false
104+ }
105+ })
106+
107+ // Validate team environment variables
69108 teamEnvSchema .value .forEach ((envVar ) => {
70109 if (envVar .required && ! modelValue .value .team_env [envVar .name ]?.trim ()) {
71110 missingFields .push (envVar .name )
@@ -77,18 +116,29 @@ const validateTeamEnvVars = () => {
77116 return isValid
78117}
79118
119+ watch (() => modelValue .value .team_args , () => {
120+ validateConfiguration ()
121+ }, { deep: true })
122+
80123watch (() => modelValue .value .team_env , () => {
81- validateTeamEnvVars ()
124+ validateConfiguration ()
82125}, { deep: true })
83126
84127watch (() => props .serverData , (newData ) => {
85128 if (newData ) {
129+ const newTeamArgs: string [] = []
86130 const newTeamEnv: Record <string , string > = {}
87131 const newUserEnv: Record <string , string > = {}
88132
133+ const argsSchema = parseArgsSchema (newData .team_args_schema )
89134 const teamSchema = parseEnvSchema (newData .team_env_schema )
90135 const userSchema = parseEnvSchema (newData .user_env_schema )
91136
137+ // Initialize team arguments array
138+ argsSchema .forEach ((arg , index ) => {
139+ newTeamArgs [index ] = modelValue .value .team_args ?.[index ] || ' '
140+ })
141+
92142 teamSchema .forEach ((env ) => {
93143 newTeamEnv [env .name ] = modelValue .value .team_env ?.[env .name ] || ' '
94144 })
@@ -98,11 +148,12 @@ watch(() => props.serverData, (newData) => {
98148 })
99149
100150 modelValue .value = {
151+ team_args: newTeamArgs ,
101152 team_env: newTeamEnv ,
102153 user_env: newUserEnv
103154 }
104155
105- validateTeamEnvVars ()
156+ validateConfiguration ()
106157 }
107158}, { immediate: true })
108159
@@ -135,7 +186,57 @@ const isTextarea = (envVar: EnvironmentVariable) => {
135186 :show-details-button =" false"
136187 />
137188
138- <div v-if =" hasAnyEnvVars" class =" space-y-8" >
189+ <div v-if =" hasAnyConfiguration" class =" space-y-8" >
190+ <!-- Team Arguments Section -->
191+ <div v-if =" hasTeamArgs" class =" bg-blue-50 p-4" >
192+ <div class =" mb-4" >
193+ <h3 class =" text-lg font-medium text-gray-900" >
194+ {{ t('mcpInstallations.teamConfiguration.sections.teamArgs.title') }}
195+ </h3 >
196+ <span class =" text-sm text-gray-500" >
197+ {{ teamArgsSchema.length }} {{ teamArgsSchema.length === 1 ? t('mcpInstallations.teamConfiguration.sections.teamArgs.counter.single') : t('mcpInstallations.teamConfiguration.sections.teamArgs.counter.plural') }}
198+ </span >
199+ </div >
200+ <p class =" text-sm text-gray-600 mb-6" >
201+ {{ t('mcpInstallations.teamConfiguration.sections.teamArgs.description') }}
202+ </p >
203+
204+ <div class =" space-y-4" >
205+ <div v-for =" (arg, index) in teamArgsSchema" :key =" `arg_${index}`" class =" space-y-2" >
206+ <div class =" flex items-center gap-2" >
207+ <Label :for =" `team_arg_${index}`" class =" flex items-center gap-2" >
208+ {{ arg.name }}
209+ <span v-if =" arg.required" class =" text-xs text-gray-500" >
210+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.required') }}
211+ </span >
212+ <span v-else class =" text-xs text-gray-500" >
213+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.optional') }}
214+ </span >
215+ </Label >
216+ </div >
217+
218+ <div v-if =" arg.description" class =" text-sm text-gray-600" >
219+ {{ arg.description }}
220+ </div >
221+
222+ <div class =" relative" >
223+ <Input
224+ :id =" `team_arg_${index}`"
225+ type =" text"
226+ v-model =" modelValue.team_args[index]"
227+ :placeholder =" arg.placeholder || t('mcpInstallations.teamConfiguration.editModal.form.placeholders.enterValue')"
228+ :required =" arg.required"
229+ />
230+ </div >
231+
232+ <div v-if =" arg.type" class =" text-xs text-gray-500" >
233+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.typeLabel') }} <code class =" bg-gray-100 px-1 rounded" >{{ arg.type }}</code >
234+ </div >
235+ </div >
236+ </div >
237+ </div >
238+
239+ <!-- Team Environment Variables Section -->
139240 <div v-if =" hasTeamEnvVars" class =" bg-gray-50 p-4" >
140241 <div class =" mb-4" >
141242 <h3 class =" text-lg font-medium text-gray-900" >
@@ -197,13 +298,14 @@ const isTextarea = (envVar: EnvironmentVariable) => {
197298 </div >
198299 </div >
199300
200- <div v-if =" hasUserEnvVars" class =" bg-gray-50 p-4" >
301+ <!-- User Configuration Section -->
302+ <div v-if =" hasUserConfiguration" class =" bg-gray-50 p-4" >
201303 <div class =" mb-4" >
202304 <h3 class =" text-lg font-medium text-gray-900" >
203- {{ t('mcpInstallations.teamConfiguration.sections.userEnv .title') }}
305+ {{ t('mcpInstallations.teamConfiguration.sections.userConfig .title') }}
204306 </h3 >
205307 <span class =" text-sm text-gray-500" >
206- {{ userEnvSchema.length }} {{ userEnvSchema.length === 1 ? t('mcpInstallations.teamConfiguration.sections.teamEnv .counter.single') : t('mcpInstallations.teamConfiguration.sections.teamEnv .counter.plural') }}
308+ {{ (userArgsSchema.length + userEnvSchema.length) }} {{ (userArgsSchema.length + userEnvSchema.length) === 1 ? t('mcpInstallations.teamConfiguration.sections.userConfig .counter.single') : t('mcpInstallations.teamConfiguration.sections.userConfig .counter.plural') }}
207309 </span >
208310 </div >
209311
@@ -215,24 +317,57 @@ const isTextarea = (envVar: EnvironmentVariable) => {
215317 </div >
216318
217319 <div class =" space-y-4" >
218- <div v-for =" envVar in userEnvSchema" :key =" envVar.name" class =" bg-white p-4" >
219- <div class =" flex items-center gap-2 mb-2" >
220- <span class =" font-medium text-gray-900 font-mono" >{{ envVar.name }}</span >
221- <span v-if =" envVar.required" class =" text-xs text-gray-500" >
222- {{ t('mcpInstallations.teamConfiguration.userEnvDetails.required') }}
223- </span >
224- <span v-else class =" text-xs text-gray-500" >
225- {{ t('mcpInstallations.teamConfiguration.userEnvDetails.optional') }}
226- </span >
227- </div >
320+ <!-- User Arguments -->
321+ <div v-if =" hasUserArgs" class =" space-y-3" >
322+ <h4 class =" text-sm font-semibold text-gray-900 border-b border-gray-200 pb-2" >
323+ {{ t('mcpInstallations.teamConfiguration.sections.userArgs.title') }}
324+ </h4 >
325+ <div v-for =" (arg, index) in userArgsSchema" :key =" `user_arg_${index}`" class =" bg-white p-4 rounded-lg border" >
326+ <div class =" flex items-center gap-2 mb-2" >
327+ <span class =" font-medium text-gray-900 font-mono" >{{ arg.name }}</span >
328+ <span v-if =" arg.required" class =" text-xs text-gray-500" >
329+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.required') }}
330+ </span >
331+ <span v-else class =" text-xs text-gray-500" >
332+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.optional') }}
333+ </span >
334+ </div >
228335
229- <div v-if =" envVar.description" class =" text-sm text-gray-600 mb-2" >
230- {{ envVar.description }}
336+ <div v-if =" arg.description" class =" text-sm text-gray-600 mb-2" >
337+ {{ arg.description }}
338+ </div >
339+
340+ <div class =" flex items-center gap-4 text-xs text-gray-500" >
341+ <span >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.typeLabel') }} <code class =" bg-gray-100 px-1 rounded" >{{ arg.type || 'string' }}</code ></span >
342+ <span v-if =" arg.placeholder" >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.placeholderLabel') }} "{{ arg.placeholder }}"</span >
343+ </div >
231344 </div >
345+ </div >
346+
347+ <!-- User Environment Variables -->
348+ <div v-if =" hasUserEnvVars" class =" space-y-3" >
349+ <h4 class =" text-sm font-semibold text-gray-900 border-b border-gray-200 pb-2" >
350+ {{ t('mcpInstallations.teamConfiguration.sections.userEnv.title') }}
351+ </h4 >
352+ <div v-for =" envVar in userEnvSchema" :key =" envVar.name" class =" bg-white p-4 rounded-lg border" >
353+ <div class =" flex items-center gap-2 mb-2" >
354+ <span class =" font-medium text-gray-900 font-mono" >{{ envVar.name }}</span >
355+ <span v-if =" envVar.required" class =" text-xs text-gray-500" >
356+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.required') }}
357+ </span >
358+ <span v-else class =" text-xs text-gray-500" >
359+ {{ t('mcpInstallations.teamConfiguration.userEnvDetails.optional') }}
360+ </span >
361+ </div >
362+
363+ <div v-if =" envVar.description" class =" text-sm text-gray-600 mb-2" >
364+ {{ envVar.description }}
365+ </div >
232366
233- <div class =" flex items-center gap-4 text-xs text-gray-500" >
234- <span >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.typeLabel') }} <code class =" bg-gray-100 px-1 rounded" >{{ envVar.type || 'string' }}</code ></span >
235- <span v-if =" envVar.placeholder" >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.placeholderLabel') }} "{{ envVar.placeholder }}"</span >
367+ <div class =" flex items-center gap-4 text-xs text-gray-500" >
368+ <span >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.typeLabel') }} <code class =" bg-gray-100 px-1 rounded" >{{ envVar.type || 'string' }}</code ></span >
369+ <span v-if =" envVar.placeholder" >{{ t('mcpInstallations.teamConfiguration.userEnvDetails.placeholderLabel') }} "{{ envVar.placeholder }}"</span >
370+ </div >
236371 </div >
237372 </div >
238373 </div >
0 commit comments