ConfigStdioCard.vue
1 <script setup lang="ts"> 2 import { McpMetadataStdio } from '@/types/mcp' 3 import { reactive, ref } from 'vue' 4 import { useStdioStore } from '@/renderer/store/stdio' 5 import { getRawServers } from '@/renderer/store/mcp' 6 7 import McpEditPage from '@/renderer/components/pages/McpEditPage.vue' 8 9 import MarkdownCard from '@/renderer/components/common/MarkdownCard.vue' 10 11 const stdioStore = useStdioStore() 12 13 const editDialog = ref(false) 14 15 const show = ref(false) 16 17 const showPassword = reactive<Record<string, boolean>>({}) 18 19 const props = defineProps({ 20 modelValue: { 21 type: Object as () => McpMetadataStdio, 22 required: true 23 } 24 }) 25 26 const { modelValue: metadata } = props 27 28 function formattedValue(value: string[], sep: string) { 29 if (Array.isArray(value)) { 30 return value.join(sep) 31 } else { 32 return value 33 } 34 } 35 36 const editConfig = () => { 37 editDialog.value = true 38 } 39 </script> 40 41 <template> 42 <v-card :title="$t('mcp.stdio')"> 43 <template v-if="metadata.description?.implementation" #subtitle> 44 {{ metadata.description?.implementation.title ?? metadata.description?.implementation.name }} 45 </template> 46 <template v-if="metadata.description?.implementation.version" #append> 47 <v-chip size="small" class="font-weight-bold" color="primary">{{ 48 metadata.description.implementation.version 49 }}</v-chip> 50 </template> 51 <v-divider></v-divider> 52 <v-card-text> 53 <div v-for="(value, key) in metadata.config" :key="key" class="ma-2"> 54 <div v-if="key === 'command'"> 55 <v-text-field 56 prepend-icon="mdi-application-outline" 57 :model-value="value" 58 density="compact" 59 variant="outlined" 60 readonly 61 hide-details 62 ></v-text-field> 63 </div> 64 <div v-else-if="key === 'args'"> 65 <v-divider class="mt-4"></v-divider> 66 <v-textarea 67 class="mt-4" 68 prepend-icon="mdi-application-brackets-outline" 69 :model-value="formattedValue(value as string[], ' \n')" 70 density="compact" 71 variant="outlined" 72 readonly 73 rows="1" 74 auto-grow 75 ></v-textarea> 76 <v-text-field 77 prepend-icon="mdi-application-export" 78 :model-value="metadata.config['command'] + ' ' + formattedValue(value as string[], ' ')" 79 density="compact" 80 variant="outlined" 81 readonly 82 hide-details 83 ></v-text-field> 84 </div> 85 <div v-else-if="key === 'env'"> 86 <v-divider class="mt-4"></v-divider> 87 88 <v-text-field 89 v-for="(envValue, envKey) in value as Record<string, string>" 90 :key="envKey" 91 class="mt-4" 92 prepend-icon="mdi-application-braces-outline" 93 :type="showPassword[envKey] ? 'text' : 'password'" 94 density="compact" 95 variant="outlined" 96 :append-inner-icon="showPassword[envKey] ? 'mdi-eye-off' : 'mdi-eye'" 97 :label="envKey" 98 :model-value="envValue" 99 readonly 100 hide-details 101 @click:append-inner="showPassword[envKey] = !showPassword[envKey]" 102 > 103 </v-text-field> 104 </div> 105 <div v-else> 106 <v-divider class="mt-4"></v-divider> 107 <v-text-field 108 class="mt-4" 109 prepend-icon="mdi-cog-outline" 110 :model-value="value" 111 density="compact" 112 variant="outlined" 113 readonly 114 hide-details 115 ></v-text-field> 116 </div> 117 </div> 118 </v-card-text> 119 <v-divider></v-divider> 120 <v-card-actions> 121 <v-btn 122 v-if="metadata.description?.instructions" 123 :icon="show ? 'mdi-chevron-up' : 'mdi-chevron-down'" 124 @click="show = !show" 125 ></v-btn> 126 <v-spacer> </v-spacer> 127 <v-btn 128 v-if="metadata.name in (getRawServers() ?? {})" 129 v-tooltip:top="$t('general.reset')" 130 icon="mdi-refresh" 131 rounded="lg" 132 color="error" 133 @click="stdioStore.deleteConfig(metadata.name)" 134 > 135 </v-btn> 136 <v-btn 137 v-else 138 v-tooltip:top="$t('general.delete')" 139 icon="mdi-delete-outline" 140 rounded="lg" 141 color="error" 142 @click="stdioStore.deleteConfig(metadata.name)" 143 > 144 </v-btn> 145 146 <v-btn 147 v-tooltip:top="$t('general.edit')" 148 icon="mdi-lead-pencil" 149 rounded="lg" 150 color="primary" 151 @click="editConfig" 152 > 153 </v-btn> 154 </v-card-actions> 155 <v-expand-transition v-if="metadata.description?.instructions"> 156 <div v-show="show"> 157 <v-divider></v-divider> 158 <v-card-text class="mx-2"> 159 <MarkdownCard :model-value="metadata.description.instructions"></MarkdownCard 160 ></v-card-text> 161 </div> 162 </v-expand-transition> 163 </v-card> 164 <McpEditPage v-model="editDialog" v-model:name="metadata.name"></McpEditPage> 165 </template>