Skip to content

Commit d16879a

Browse files
committed
feat: Implement session management and SSE handling
- Add SessionManager class for managing user sessions with features like session creation, cleanup, and activity tracking. - Introduce SSEHandler class to establish Server-Sent Events (SSE) connections and manage communication with clients. - Update index.ts to register new MCP command. - Modify config types to accommodate new MCP server configurations. - Enhance MCP types with installation management and server configuration details. - Create StateComparator utility for comparing expected server states with actual running processes. - Implement ToolDiscoveryManager for discovering tools from MCP servers, including error handling and caching mechanisms.
1 parent 582d7b0 commit d16879a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+7568
-212
lines changed

package-lock.json

Lines changed: 310 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/backend/api-spec.json

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16771,20 +16771,52 @@
1677116771
}
1677216772
]
1677316773
},
16774+
"homepage_url": {
16775+
"anyOf": [
16776+
{
16777+
"type": "string"
16778+
},
16779+
{
16780+
"type": "null"
16781+
}
16782+
]
16783+
},
16784+
"author_name": {
16785+
"anyOf": [
16786+
{
16787+
"type": "string"
16788+
},
16789+
{
16790+
"type": "null"
16791+
}
16792+
]
16793+
},
16794+
"language": {
16795+
"type": "string"
16796+
},
1677416797
"runtime": {
1677516798
"type": "string"
1677616799
},
16777-
"installation_methods": {
16800+
"status": {
16801+
"type": "string"
16802+
},
16803+
"tags": {
1677816804
"type": "array",
1677916805
"items": {}
1678016806
},
1678116807
"environment_variables": {
1678216808
"type": "array",
1678316809
"items": {}
1678416810
},
16785-
"default_config": {
16811+
"installation_methods": {
16812+
"type": "array",
16813+
"items": {}
16814+
},
16815+
"category_id": {
1678616816
"anyOf": [
16787-
{},
16817+
{
16818+
"type": "string"
16819+
},
1678816820
{
1678916821
"type": "null"
1679016822
}
@@ -16796,10 +16828,15 @@
1679616828
"name",
1679716829
"description",
1679816830
"github_url",
16831+
"homepage_url",
16832+
"author_name",
16833+
"language",
1679916834
"runtime",
16800-
"installation_methods",
16835+
"status",
16836+
"tags",
1680116837
"environment_variables",
16802-
"default_config"
16838+
"installation_methods",
16839+
"category_id"
1680316840
],
1680416841
"additionalProperties": false
1680516842
}

services/backend/api-spec.yaml

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11315,27 +11315,47 @@ paths:
1131511315
anyOf:
1131611316
- type: string
1131711317
- type: "null"
11318+
homepage_url:
11319+
anyOf:
11320+
- type: string
11321+
- type: "null"
11322+
author_name:
11323+
anyOf:
11324+
- type: string
11325+
- type: "null"
11326+
language:
11327+
type: string
1131811328
runtime:
1131911329
type: string
11320-
installation_methods:
11330+
status:
11331+
type: string
11332+
tags:
1132111333
type: array
1132211334
items: {}
1132311335
environment_variables:
1132411336
type: array
1132511337
items: {}
11326-
default_config:
11338+
installation_methods:
11339+
type: array
11340+
items: {}
11341+
category_id:
1132711342
anyOf:
11328-
- {}
11343+
- type: string
1132911344
- type: "null"
1133011345
required:
1133111346
- id
1133211347
- name
1133311348
- description
1133411349
- github_url
11350+
- homepage_url
11351+
- author_name
11352+
- language
1133511353
- runtime
11336-
- installation_methods
11354+
- status
11355+
- tags
1133711356
- environment_variables
11338-
- default_config
11357+
- installation_methods
11358+
- category_id
1133911359
additionalProperties: false
1134011360
required:
1134111361
- id

services/backend/src/routes/mcp/installations/list.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@ const installationSchema = z.object({
2323
name: z.string(),
2424
description: z.string(),
2525
github_url: z.string().nullable(),
26+
homepage_url: z.string().nullable(),
27+
author_name: z.string().nullable(),
28+
language: z.string(),
2629
runtime: z.string(),
27-
installation_methods: z.array(z.any()),
30+
status: z.string(),
31+
tags: z.array(z.any()),
2832
environment_variables: z.array(z.any()),
29-
default_config: z.any().nullable()
33+
installation_methods: z.array(z.any()),
34+
category_id: z.string().nullable()
3035
}).optional()
3136
});
3237

services/backend/src/services/mcpInstallationService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export class McpInstallationService {
9595
status: row.server.status,
9696
tags: this.parseJsonField(row.server.tags, []),
9797
environment_variables: this.parseJsonField(row.server.environment_variables, []),
98+
installation_methods: this.parseJsonField(row.server.installation_methods, []),
9899
category_id: row.server.category_id
99100
} : undefined
100101
}));

services/backend/tests/unit/routes/teams.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ describe('Teams Route', () => {
163163
schema: expect.objectContaining({
164164
tags: ['Teams'],
165165
summary: 'Get current user teams',
166-
security: [{ cookieAuth: [] }],
166+
security: [{ cookieAuth: [] }, { bearerAuth: [] }],
167167
}),
168168
}),
169169
expect.any(Function)
@@ -1100,7 +1100,7 @@ describe('Teams Route', () => {
11001100
expect(options.schema).toBeDefined();
11011101
expect(options.schema.tags).toEqual(['Teams']);
11021102
expect(options.schema.summary).toBe('Get current user teams');
1103-
expect(options.schema.security).toEqual([{ cookieAuth: [] }]);
1103+
expect(options.schema.security).toEqual([{ cookieAuth: [] }, { bearerAuth: [] }]);
11041104
expect(options.schema.response).toBeDefined();
11051105
expect(options.schema.response[200]).toBeDefined();
11061106
expect(options.schema.response[401]).toBeDefined();

services/frontend/CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## <small>0.21.1 (2025-07-27)</small>
4+
5+
* remove scoped commit implementation documentation ([8311fc8](https://github.com/deploystackio/deploystack/commit/8311fc89c5c7c6ca4944c0f7040275e00d5170b9))
6+
* release v0.21.0 ([0a01e3c](https://github.com/deploystackio/deploystack/commit/0a01e3c2e90ba7cc415211bb0f76ba4e0bd11087))
7+
* update README links for better formatting ([ba15434](https://github.com/deploystackio/deploystack/commit/ba15434bd65f371d9ad39576a56a923a9040f74e))
8+
* implement scoped commit message guidelines and templates ([a6839b8](https://github.com/deploystackio/deploystack/commit/a6839b880248a35a213cfb44f19ec29c0b9553cc))
9+
* update README with new links and SVG assets ([704799c](https://github.com/deploystackio/deploystack/commit/704799c34ef1d67824b5a1911d14ae148b0f4b15))
10+
* implement OAuth consent page and service integration ([1df0813](https://github.com/deploystackio/deploystack/commit/1df0813afb893d33690a02cf395f100edbe839cb))
11+
12+
## 0.21.0 (2025-07-27)
13+
14+
* update README links for better formatting ([ba15434](https://github.com/deploystackio/deploystack/commit/ba15434bd65f371d9ad39576a56a923a9040f74e))
15+
* implement scoped commit message guidelines and templates ([a6839b8](https://github.com/deploystackio/deploystack/commit/a6839b880248a35a213cfb44f19ec29c0b9553cc))
16+
* update README with new links and SVG assets ([704799c](https://github.com/deploystackio/deploystack/commit/704799c34ef1d67824b5a1911d14ae148b0f4b15))
17+
* implement OAuth consent page and service integration ([1df0813](https://github.com/deploystackio/deploystack/commit/1df0813afb893d33690a02cf395f100edbe839cb))
18+
* remove scoped commit implementation documentation ([8311fc8](https://github.com/deploystackio/deploystack/commit/8311fc89c5c7c6ca4944c0f7040275e00d5170b9))
19+
320
## <small>0.20.1 (2025-07-26)</small>
421

522
* bump @libsql/client from 0.15.9 to 0.15.10 ([908efef](https://github.com/deploystackio/deploystack/commit/908efefe920ad03cd859e17c9df9a2e52493e99b))

services/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@deploystack/frontend",
3-
"version": "0.20.1",
3+
"version": "0.21.1",
44
"private": true,
55
"type": "module",
66
"scripts": {

services/frontend/src/components/mcp-server/installation/DangerZone.vue

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { ref } from 'vue'
33
import { useI18n } from 'vue-i18n'
44
import { useRouter } from 'vue-router'
5+
import { toast } from 'vue-sonner'
56
import { Button } from '@/components/ui/button'
67
import {
78
AlertDialog,
@@ -80,21 +81,25 @@ async function handleUninstall() {
8081
// Close modal
8182
showUninstallModal.value = false
8283
83-
// Store success notification for persistence across navigation
84-
const message = t('mcpInstallations.notifications.uninstallSuccess')
85-
86-
// Use event bus storage to persist notification across navigation
87-
eventBus.setState('pending_notification', {
88-
message,
89-
type: 'success',
90-
timestamp: Date.now()
84+
// Show success toast
85+
toast.success(t('mcpInstallations.notifications.uninstallSuccess'), {
86+
description: t('mcpInstallations.removal.notifications.success')
9187
})
9288
89+
// Emit event for other components to update
90+
eventBus.emit('mcp-installations-updated')
91+
9392
// Navigate back to MCP servers list
9493
router.push('/mcp-server')
9594
9695
} catch (err) {
97-
error.value = err instanceof Error ? err.message : 'Unknown error occurred'
96+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'
97+
error.value = errorMessage
98+
99+
// Show error toast
100+
toast.error(t('mcpInstallations.removal.notifications.genericError', { error: errorMessage }), {
101+
description: t('mcpInstallations.details.dangerZone.uninstall.modal.warning')
102+
})
98103
} finally {
99104
isUninstalling.value = false
100105
}

services/frontend/src/components/mcp-server/wizard/McpServerInstallWizard.vue

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n'
55
import { useRoute } from 'vue-router'
66
import { Button } from '@/components/ui/button'
77
import { ProgressBars } from '@/components/ui/progress-bars'
8-
import { Alert, AlertDescription } from '@/components/ui/alert'
8+
import { toast } from 'vue-sonner'
99
import { Server, Settings, Cloud, Loader2 } from 'lucide-vue-next'
1010
import { McpInstallationService } from '@/services/mcpInstallationService'
1111
import { TeamService } from '@/services/teamService'
@@ -108,7 +108,7 @@ const handleStepClick = (step: any, index: number) => {
108108
// State
109109
const currentStep = ref(0)
110110
const isSubmitting = ref(false)
111-
const submitError = ref<string | null>(null)
111+
112112
const environmentValidation = ref({
113113
isValid: true,
114114
missingFields: [] as string[]
@@ -166,6 +166,17 @@ const nextStep = () => {
166166
// Mark environment step as touched when user tries to proceed from it
167167
if (currentStep.value === 1) {
168168
environmentStepTouched.value = true
169+
170+
// Check validation before proceeding
171+
if (!environmentValidation.value.isValid) {
172+
// Show error toast for missing required fields
173+
if (environmentValidation.value.missingFields.length > 0) {
174+
toast.error(t('mcpInstallations.wizard.environment.missingRequiredFields'), {
175+
description: environmentValidation.value.missingFields.join(', ')
176+
})
177+
}
178+
return
179+
}
169180
}
170181
171182
if (canGoNext.value) {
@@ -223,15 +234,16 @@ const initializeTeamContext = async () => {
223234
}
224235
} catch (error) {
225236
console.error('Error initializing team context:', error)
226-
submitError.value = 'Failed to initialize team context. Please refresh the page.'
237+
toast.error('Failed to initialize team context', {
238+
description: 'Please refresh the page and try again.'
239+
})
227240
}
228241
}
229242
230243
// Form submission
231244
const submitInstallation = async () => {
232245
try {
233246
isSubmitting.value = true
234-
submitError.value = null
235247
236248
// Ensure we have a team ID
237249
if (!currentTeamId.value) {
@@ -259,7 +271,10 @@ const submitInstallation = async () => {
259271
}
260272
261273
} catch (error) {
262-
submitError.value = error instanceof Error ? error.message : 'Failed to submit installation'
274+
const errorMessage = error instanceof Error ? error.message : 'Failed to submit installation'
275+
toast.error(t('mcpInstallations.notifications.installError', { error: errorMessage }), {
276+
description: t('mcpInstallations.wizard.environment.helpText')
277+
})
263278
} finally {
264279
isSubmitting.value = false
265280
}
@@ -326,7 +341,9 @@ const handleQueryParameters = async () => {
326341
}
327342
} catch (error) {
328343
console.error('Error loading server from query parameters:', error)
329-
submitError.value = 'Failed to load the selected server. Please try again.'
344+
toast.error(t('mcpInstallations.wizard.server.errorTitle'), {
345+
description: 'Failed to load the specified server. Please try again.'
346+
})
330347
}
331348
}
332349
}
@@ -346,7 +363,7 @@ onMounted(async () => {
346363
environment: { user_environment_variables: {} },
347364
platform: { installation_type: 'local' }
348365
}
349-
submitError.value = null
366+
350367
})
351368
})
352369
</script>
@@ -363,19 +380,7 @@ onMounted(async () => {
363380
@step-click="handleStepClick"
364381
/>
365382

366-
<!-- Error Message -->
367-
<Alert v-if="submitError" variant="destructive">
368-
<AlertDescription>
369-
{{ submitError }}
370-
</AlertDescription>
371-
</Alert>
372-
373-
<!-- Validation Error for Environment Variables (only show after user tries to proceed) -->
374-
<Alert v-if="currentStep === 1 && environmentStepTouched && !environmentValidation.isValid && environmentValidation.missingFields.length > 0" variant="destructive">
375-
<AlertDescription>
376-
{{ t('mcpInstallations.wizard.environment.missingRequiredFields') }}: {{ environmentValidation.missingFields.join(', ') }}
377-
</AlertDescription>
378-
</Alert>
383+
379384

380385
<!-- Step Content -->
381386
<div>

0 commit comments

Comments
 (0)