Skip to content

Commit ca7e44c

Browse files
authored
Merge pull request #97 from smart-mcp-proxy/fix/web-ui-delete-server
Fix: Web UI delete server functionality and add comprehensive tests
2 parents 968a8e1 + a5806ca commit ca7e44c

File tree

4 files changed

+365
-1
lines changed

4 files changed

+365
-1
lines changed

frontend/src/components/ServerCard.vue

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,44 @@
103103
>
104104
Details
105105
</router-link>
106+
107+
<button
108+
@click="showDeleteConfirmation = true"
109+
:disabled="loading"
110+
class="btn btn-sm btn-error"
111+
>
112+
Delete
113+
</button>
114+
</div>
115+
</div>
116+
117+
<!-- Delete Confirmation Modal -->
118+
<div v-if="showDeleteConfirmation" class="modal modal-open">
119+
<div class="modal-box">
120+
<h3 class="font-bold text-lg mb-4">Delete Server</h3>
121+
<p class="mb-4">
122+
Are you sure you want to delete the server <strong>{{ server.name }}</strong>?
123+
</p>
124+
<p class="text-sm text-base-content/70 mb-6">
125+
This action cannot be undone. The server will be removed from your configuration.
126+
</p>
127+
<div class="modal-action">
128+
<button
129+
@click="showDeleteConfirmation = false"
130+
:disabled="loading"
131+
class="btn btn-outline"
132+
>
133+
Cancel
134+
</button>
135+
<button
136+
@click="confirmDelete"
137+
:disabled="loading"
138+
class="btn btn-error"
139+
>
140+
<span v-if="loading" class="loading loading-spinner loading-xs"></span>
141+
Delete Server
142+
</button>
143+
</div>
106144
</div>
107145
</div>
108146
</div>
@@ -123,6 +161,7 @@ const props = defineProps<Props>()
123161
const serversStore = useServersStore()
124162
const systemStore = useSystemStore()
125163
const loading = ref(false)
164+
const showDeleteConfirmation = ref(false)
126165
127166
const needsOAuth = computed(() => {
128167
// Check if server requires OAuth authentication
@@ -236,4 +275,25 @@ async function unquarantine() {
236275
loading.value = false
237276
}
238277
}
278+
279+
async function confirmDelete() {
280+
loading.value = true
281+
try {
282+
await serversStore.deleteServer(props.server.name)
283+
systemStore.addToast({
284+
type: 'success',
285+
title: 'Server Deleted',
286+
message: `${props.server.name} has been deleted successfully`,
287+
})
288+
showDeleteConfirmation.value = false
289+
} catch (error) {
290+
systemStore.addToast({
291+
type: 'error',
292+
title: 'Delete Failed',
293+
message: error instanceof Error ? error.message : 'Unknown error',
294+
})
295+
} finally {
296+
loading.value = false
297+
}
298+
}
239299
</script>

frontend/src/services/api.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ class APIService {
237237
})
238238
}
239239

240+
async deleteServer(serverName: string): Promise<APIResponse> {
241+
return this.callTool('upstream_servers', {
242+
operation: 'remove',
243+
name: serverName
244+
})
245+
}
246+
240247
async getServerTools(serverName: string): Promise<APIResponse<{ tools: Tool[] }>> {
241248
return this.request<{ tools: Tool[] }>(`/api/v1/servers/${encodeURIComponent(serverName)}/tools`)
242249
}

frontend/src/stores/servers.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ export const useServersStore = defineStore('servers', () => {
3939
try {
4040
const response = await api.getServers()
4141
if (response.success && response.data) {
42-
servers.value = response.data.servers
42+
// Sort servers alphabetically by name to match tray menu order
43+
servers.value = response.data.servers.sort((a, b) =>
44+
a.name.localeCompare(b.name)
45+
)
4346
} else {
4447
loading.value.error = response.error || 'Failed to fetch servers'
4548
}
@@ -188,6 +191,22 @@ export const useServersStore = defineStore('servers', () => {
188191
}
189192
}
190193

194+
async function deleteServer(serverName: string) {
195+
try {
196+
const response = await api.deleteServer(serverName)
197+
if (response.success) {
198+
// Remove server from local state
199+
servers.value = servers.value.filter(s => s.name !== serverName)
200+
return true
201+
} else {
202+
throw new Error(response.error || 'Failed to delete server')
203+
}
204+
} catch (error) {
205+
console.error('Failed to delete server:', error)
206+
throw error
207+
}
208+
}
209+
191210
function updateServerStatus(statusUpdate: any) {
192211
// Update servers based on real-time status updates
193212
if (statusUpdate.upstream_stats) {
@@ -265,6 +284,7 @@ export const useServersStore = defineStore('servers', () => {
265284
triggerOAuthLogin,
266285
quarantineServer,
267286
unquarantineServer,
287+
deleteServer,
268288
updateServerStatus,
269289
getServerByName,
270290
addServer,

0 commit comments

Comments
 (0)