Skip to content

Commit 45bd18b

Browse files
author
Lasim
committed
feat(frontend): ensure fresh data loading in edit mode
1 parent 41987b5 commit 45bd18b

File tree

5 files changed

+111
-42
lines changed

5 files changed

+111
-42
lines changed

services/frontend/src/components/admin/mcp-catalog/McpServerEditFormWizard.vue

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,18 @@ const submitError = ref<string | null>(null)
167167
const isFetchingGitHub = ref(false)
168168
const githubFetchError = ref<string | null>(null)
169169
170-
// Initialize storage with form data for edit mode - BUT PRESERVE USER EDITS
170+
// Initialize storage with form data for edit mode - FORCE FRESH DATA LOADING
171171
const initializeStorageWithData = (data: McpServerFormData) => {
172-
// Initialize all storage keys that the storage-first components expect
172+
// Always overwrite storage with fresh data in edit mode
173+
// This ensures we load fresh data from database, not old corrupted cache
173174
eventBus.setState('edit_basic_data', data.basic)
174175
eventBus.setState('edit_repository_data', data.repository)
175176
eventBus.setState('edit_technical_data', data.technical)
176177
177-
// CRITICAL: Only initialize configuration_schema if user hasn't made edits yet
178-
const existingConfigSchema = eventBus.getState('edit_configuration_schema')
179-
if (data.configuration_schema && !existingConfigSchema) {
180-
// Only set if no existing edits
178+
// FORCE FRESH CONFIGURATION SCHEMA - always overwrite in edit mode
179+
if (data.configuration_schema) {
181180
eventBus.setState('edit_configuration_schema', data.configuration_schema)
182181
}
183-
// If existingConfigSchema exists, DON'T overwrite it - keep user's edits!
184182
185183
// Initialize Claude Desktop config if available
186184
if (data.technical.installation_methods && data.technical.installation_methods.length > 0) {

services/frontend/src/components/admin/mcp-catalog/TechnicalStep.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const isUpdatingFromStorage = ref(false)
6161
// Load data from storage
6262
const loadFromStorage = () => {
6363
const storedData = eventBus.getState<TechnicalFormData>(STORAGE_KEY)
64-
64+
6565
if (storedData) {
6666
localData.value = { ...localData.value, ...storedData }
6767
} else if (props.formData?.technical) {
@@ -312,7 +312,7 @@ watch(jsonInput, (newValue) => {
312312
eventBus.emit('technical-env-vars-updated', {
313313
envVars: validation.envVars || []
314314
})
315-
315+
316316
// ALSO store in persistent storage for ConfigurationSchemaStep to load later
317317
eventBus.setState('technical_extracted_env_vars_edit', validation.envVars || [])
318318
@@ -329,7 +329,7 @@ watch(jsonInput, (newValue) => {
329329
env: serverConfig.env || {}
330330
}]
331331
332-
// Update the technical form data
332+
// Update installation_methods
333333
updateField('installation_methods', installationMethods)
334334
335335
// Also update the capabilities section with environment variables
@@ -396,6 +396,7 @@ const handleStepChanged = (data: { from: number; to: number; stepKey: string })
396396
loadLatestConfigFromStorage()
397397
}, 50)
398398
}
399+
399400
}
400401
401402
// Computed properties

services/frontend/src/components/admin/mcp-catalog/steps/ConfigurationSchemaStepAdd.vue

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,63 @@ const typeOptions = [
178178
{ value: 'boolean', label: computed(() => t('mcpCatalog.form.configurationSchema.dataTypes.boolean')) },
179179
]
180180
181-
// Smart default logic
182-
const isStaticTemplateArg = (arg: string): boolean => {
183-
return arg.startsWith('-') || arg.includes('@modelcontextprotocol')
181+
// Placeholder detection for team-configurable values (still needed for env vars)
182+
const isPlaceholderValue = (value: string): boolean => {
183+
const placeholderPatterns = [
184+
/^YOUR_[A-Z_]+$/, // YOUR_API_KEY, YOUR_TOKEN
185+
/^[A-Z_]+_KEY$/, // API_KEY, ACCESS_KEY
186+
/^[A-Z_]+_TOKEN$/, // AUTH_TOKEN, ACCESS_TOKEN
187+
/^[A-Z_]+_SECRET$/, // CLIENT_SECRET, API_SECRET
188+
/^<[^>]+>$/, // <API_KEY>, <YOUR_TOKEN>
189+
/^\{[^}]+\}$/, // {API_KEY}, {YOUR_TOKEN}
190+
/^\$\{[^}]+\}$/, // ${API_KEY}, ${YOUR_TOKEN}
191+
/^REPLACE_WITH_/, // REPLACE_WITH_YOUR_KEY
192+
/^CHANGE_ME/, // CHANGE_ME, CHANGE_ME_API_KEY
193+
]
194+
return placeholderPatterns.some(pattern => pattern.test(value))
195+
}
196+
197+
// Simple args parsing - first 2 are template, rest are team configurable
198+
const parseArgsIntelligently = (rawArgs: string[]): ConfigItem[] => {
199+
const items: ConfigItem[] = []
200+
201+
rawArgs.forEach((arg, index) => {
202+
// Skip if arg is undefined
203+
if (!arg) return
204+
205+
// First 2 arguments are always template (static)
206+
if (index < 2) {
207+
items.push({
208+
id: `template_arg_${index}`,
209+
type: 'arg',
210+
category: 'template',
211+
name: arg,
212+
value: arg,
213+
description: `Static argument: ${arg}`,
214+
dataType: 'string',
215+
required: true,
216+
locked: true,
217+
default_team_locked: false,
218+
})
219+
}
220+
// All other arguments are team configurable
221+
else {
222+
items.push({
223+
id: `team_arg_${index}`,
224+
type: 'arg',
225+
category: 'team',
226+
name: arg,
227+
value: undefined,
228+
description: `Team-configurable argument: ${arg}`,
229+
dataType: 'string',
230+
required: true,
231+
locked: false,
232+
default_team_locked: true,
233+
})
234+
}
235+
})
236+
237+
return items
184238
}
185239
186240
// Parse and categorize items from Claude Desktop config
@@ -193,38 +247,29 @@ const parseFromClaudeConfig = () => {
193247
194248
const items: ConfigItem[] = []
195249
196-
// Process args
250+
// Process args with intelligent parsing
197251
const rawArgs = serverConfig.args || []
198-
rawArgs.forEach((arg, index) => {
199-
items.push({
200-
id: `arg_${index}`,
201-
type: 'arg',
202-
category: isStaticTemplateArg(arg) ? 'template' : 'user',
203-
name: `arg_${index}`,
204-
value: arg,
205-
description: '',
206-
dataType: 'string',
207-
required: true,
208-
locked: false,
209-
default_team_locked: false,
210-
})
211-
})
252+
const argItems = parseArgsIntelligently(rawArgs)
253+
items.push(...argItems)
212254
213255
// Process envs
214256
const rawEnvs = serverConfig.env || {}
215257
Object.entries(rawEnvs).forEach(([key, value]) => {
258+
const isPlaceholder = isPlaceholderValue(value)
216259
items.push({
217260
id: `env_${key}`,
218261
type: 'env',
219-
category: 'team',
262+
category: isPlaceholder ? 'team' : 'user',
220263
name: key,
221264
value: value,
222-
description: '',
265+
description: isPlaceholder
266+
? `Team-configurable environment variable (placeholder: ${value})`
267+
: `User-configurable environment variable`,
223268
dataType: 'string',
224269
required: true,
225270
locked: false,
226-
default_team_locked: true,
227-
visible_to_users: false,
271+
default_team_locked: isPlaceholder,
272+
visible_to_users: !isPlaceholder,
228273
})
229274
})
230275

services/frontend/src/components/admin/mcp-catalog/steps/ConfigurationSchemaStepEdit.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,45 +164,46 @@ const typeOptions = [
164164
{ value: 'boolean', label: computed(() => t('mcpCatalog.form.configurationSchema.dataTypes.boolean')) },
165165
]
166166
167+
167168
// Load data from existing schema in storage
168169
const loadFromStorageSchema = () => {
169170
const storedSchema = eventBus.getState<ConfigurationSchema>(STORAGE_KEY)
170171
if (!storedSchema) return
171172
172173
const items: ConfigItem[] = []
173174
174-
// Convert template args
175+
// Convert template args - these should display the actual argument values
175176
;(storedSchema.template_args || []).forEach((arg, index) => {
176177
items.push({
177178
id: `template_arg_${index}`,
178179
type: 'arg',
179180
category: 'template',
180181
name: arg.value, // Use the actual value as the name
181182
value: arg.value, // Keep value for reference
182-
description: arg.description || '',
183+
description: arg.description || `Static argument: ${arg.value}`,
183184
dataType: 'string',
184185
required: true,
185186
locked: arg.locked,
186187
default_team_locked: false,
187188
})
188189
})
189190
190-
// Convert team args schema
191+
// Convert team args schema - these should display the actual argument values
191192
;(storedSchema.team_args_schema || []).forEach((arg, index) => {
192193
items.push({
193194
id: `team_arg_${index}`,
194195
type: 'arg',
195196
category: 'team',
196-
name: arg.name,
197-
description: arg.description || '',
197+
name: arg.name, // This should be the actual argument value like "@upstash/context7-mcp"
198+
description: arg.description || `Team-configurable argument: ${arg.name}`,
198199
dataType: arg.type || 'string',
199200
required: arg.required || false,
200201
locked: arg.locked || false,
201202
default_team_locked: arg.default_team_locked || false,
202203
})
203204
})
204205
205-
// Convert user args schema
206+
// Convert user args schema (these are manually added, not from original parsing)
206207
;(storedSchema.user_args_schema || []).forEach((arg, index) => {
207208
items.push({
208209
id: `user_arg_${index}`,
@@ -568,7 +569,6 @@ onUnmounted(() => {
568569

569570
<template>
570571
<div class="space-y-6">
571-
572572
<!-- Arguments Section -->
573573
<div class="space-y-4">
574574
<div>

services/frontend/src/views/admin/mcp-server-catalog/edit/[id].vue

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,38 @@ const goToCatalog = () => {
4141
router.push('/admin/mcp-server-catalog')
4242
}
4343
44+
// Clear all edit-related storage to ensure fresh data loading
45+
const clearEditStorage = () => {
46+
// Clear all edit-related storage keys
47+
const editStorageKeys = [
48+
'edit_basic_data',
49+
'edit_repository_data',
50+
'edit_technical_data',
51+
'edit_configuration_schema',
52+
'edit_claude_config',
53+
'technical_extracted_env_vars_edit',
54+
'mcp_edit_drafts'
55+
]
56+
57+
editStorageKeys.forEach(key => {
58+
eventBus.clearState(key)
59+
})
60+
61+
// Also clear localStorage directly to ensure complete cleanup
62+
editStorageKeys.forEach(key => {
63+
localStorage.removeItem(key)
64+
})
65+
}
66+
4467
// Load server data
4568
const loadServerData = async () => {
4669
try {
4770
isLoading.value = true
4871
isRetrying.value = true
4972
loadError.value = null
5073
74+
clearEditStorage()
75+
5176
const server = await McpCatalogService.getServerById(serverId)
5277
serverData.value = server
5378
@@ -64,7 +89,7 @@ const loadServerData = async () => {
6489
}
6590
6691
// Helper function to parse JSON fields with proper error handling
67-
92+
6893
const parseJsonField = (fieldValue: any, defaultValue: any) => {
6994
if (!fieldValue || fieldValue === '' || (typeof fieldValue === 'string' && fieldValue.trim() === '')) {
7095
return defaultValue
@@ -83,7 +108,7 @@ const parseJsonField = (fieldValue: any, defaultValue: any) => {
83108
// Convert server data to form data format
84109
const convertServerToFormData = (server: McpServer): Partial<McpServerFormData> => {
85110
// Convert installation methods to new format
86-
111+
87112
const convertedInstallationMethods = (server.installation_methods || []).map((method: any) => {
88113
// Handle old format: {type, command, description}
89114
if (method.type && method.command && !method.client) {
@@ -107,7 +132,7 @@ const convertServerToFormData = (server: McpServer): Partial<McpServerFormData>
107132
args: method.args || [],
108133
env: method.env || {}
109134
}
110-
135+
111136
}).filter((method: any) =>
112137
// Filter out git clone template entries and any invalid entries
113138
method.command &&

0 commit comments

Comments
 (0)