Skip to content

Commit 3c7fccf

Browse files
committed
feat(servers): Phase 4 — Wire entry points
Autonomous decisions: - Plus icon for guided custom, FileJson for manifest — distinguishes panel vs full JSON editor at a glance - Reused P2 customServerPanelSpace state — already wired; no rename to customServerPanelOpen Signed-off-by: crimsonsunset <jsangio1@gmail.com>
1 parent c87c337 commit 3c7fccf

4 files changed

Lines changed: 40 additions & 50 deletions

File tree

apps/desktop/src/components/ConfigEditorModal.tsx

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useToast, ToastContainer } from '@mcpmux/ui';
88
import USER_SPACE_CONFIG_SCHEMA from '../../../../schemas/user-space.schema.json';
99
import { RequestServerCTA } from './Contribute';
1010
import { MonacoJsonEditor } from './monaco-json-editor.component';
11+
import { CustomServerPanel } from '@/features/servers/CustomServerPanel';
1112

1213
const EDITOR_MOUNT_TIMEOUT_MS = 10_000;
1314

@@ -23,39 +24,6 @@ type SpaceConfigJson = {
2324
[key: string]: unknown;
2425
};
2526

26-
const CUSTOM_SERVER_BASE_KEY = 'custom-server';
27-
28-
function nextCustomServerKey(servers: Record<string, unknown>): string {
29-
let suffix = 1;
30-
31-
while (true) {
32-
const key = suffix === 1 ? CUSTOM_SERVER_BASE_KEY : CUSTOM_SERVER_BASE_KEY + '-' + suffix;
33-
if (!(key in servers)) {
34-
return key;
35-
}
36-
suffix += 1;
37-
}
38-
}
39-
40-
function addCustomServerDraft(config: SpaceConfigJson): SpaceConfigJson {
41-
const mcpServers = { ...(config.mcpServers ?? {}) };
42-
const key = nextCustomServerKey(mcpServers);
43-
const suffix =
44-
key === CUSTOM_SERVER_BASE_KEY ? '' : ' ' + key.replace(CUSTOM_SERVER_BASE_KEY + '-', '');
45-
46-
mcpServers[key] = {
47-
name: 'New Custom Server' + suffix,
48-
command: '',
49-
args: [],
50-
env: {},
51-
};
52-
53-
return {
54-
...config,
55-
mcpServers,
56-
};
57-
}
58-
5927
export function ConfigEditorModal({
6028
spaceId,
6129
spaceName,
@@ -72,6 +40,7 @@ export function ConfigEditorModal({
7240
const [editorReady, setEditorReady] = useState(false);
7341
const [editorMounted, setEditorMounted] = useState(false);
7442
const [editorLoadFailed, setEditorLoadFailed] = useState(false);
43+
const [showCustomServerPanel, setShowCustomServerPanel] = useState(false);
7544
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
7645
const { toasts, success, error: showError } = useToast();
7746

@@ -185,19 +154,12 @@ export function ConfigEditorModal({
185154
editorRef.current?.getAction('actions.find')?.run();
186155
}, []);
187156

157+
/**
158+
* Open the guided custom-server panel docked over this manifest editor.
159+
*/
188160
const handleInsertCustomServer = useCallback(() => {
189-
try {
190-
const parsed = JSON.parse(content || '{"mcpServers":{}}') as SpaceConfigJson;
191-
setContent(JSON.stringify(addCustomServerDraft(parsed), null, 2));
192-
setIsValidJson(true);
193-
setError(null);
194-
} catch (e) {
195-
const message = e instanceof Error ? e.message : String(e);
196-
setIsValidJson(false);
197-
setError(t('configEditorModal.validation.invalidJson', { message }));
198-
showError(t('configEditorModal.toast.invalidJsonTitle'), message);
199-
}
200-
}, [content, showError, t]);
161+
setShowCustomServerPanel(true);
162+
}, []);
201163

202164
// Configure Monaco before mount to set up JSON schema validation
203165
const handleEditorBeforeMount = (monaco: Monaco) => {
@@ -434,6 +396,17 @@ export function ConfigEditorModal({
434396
)}
435397
</div>
436398
</div>
399+
400+
{showCustomServerPanel && (
401+
<CustomServerPanel
402+
spaceId={spaceId}
403+
spaceName={spaceName}
404+
onClose={() => setShowCustomServerPanel(false)}
405+
onSaved={() => {
406+
void loadConfig();
407+
}}
408+
/>
409+
)}
437410
</>
438411
);
439412
}

apps/desktop/src/features/servers/AddServerMenu.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import {
1111
interface AddServerMenuProps {
1212
/** Opens the Discover page to browse the community server registry. */
1313
onDiscover: () => void;
14-
/** Opens the Space JSON editor to add a custom server definition. */
14+
/** Opens the guided custom-server panel (Form / JSON). */
1515
onCustom: () => void;
16+
/** Opens the full-space JSON manifest editor. */
17+
onViewManifest: () => void;
1618
}
1719

1820
/**
19-
* Dropdown for the two ways to add MCP servers: registry discover vs custom JSON.
21+
* Dropdown for adding MCP servers: registry discover, guided custom setup, or full manifest.
2022
*/
21-
export function AddServerMenu({ onDiscover, onCustom }: AddServerMenuProps) {
23+
export function AddServerMenu({ onDiscover, onCustom, onViewManifest }: AddServerMenuProps) {
2224
const { t } = useTranslation('servers');
2325

2426
return (
@@ -39,12 +41,19 @@ export function AddServerMenu({ onDiscover, onCustom }: AddServerMenuProps) {
3941
data-testid="add-server-option-discover"
4042
/>
4143
<DropdownMenuItem
42-
icon={FileJson}
44+
icon={Plus}
4345
label={t('addMenu.custom')}
4446
description={t('addMenu.customDesc')}
4547
onSelect={onCustom}
4648
data-testid="add-server-option-custom"
4749
/>
50+
<DropdownMenuItem
51+
icon={FileJson}
52+
label={t('addMenu.viewManifest')}
53+
description={t('addMenu.viewManifestDesc')}
54+
onSelect={onViewManifest}
55+
data-testid="add-server-option-view-manifest"
56+
/>
4857
</DropdownMenuContent>
4958
</DropdownMenu>
5059
);

apps/desktop/src/features/servers/ServersPage.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,9 @@ export function ServersPage() {
16701670
onCustom={() =>
16711671
setCustomServerPanelSpace({ id: viewSpace.id, name: viewSpace.name })
16721672
}
1673+
onViewManifest={() =>
1674+
setEditConfigSpace({ id: viewSpace.id, name: viewSpace.name })
1675+
}
16731676
/>
16741677
</div>
16751678
)}
@@ -1712,6 +1715,9 @@ export function ServersPage() {
17121715
onCustom={() =>
17131716
setCustomServerPanelSpace({ id: viewSpace.id, name: viewSpace.name })
17141717
}
1718+
onViewManifest={() =>
1719+
setEditConfigSpace({ id: viewSpace.id, name: viewSpace.name })
1720+
}
17151721
/>
17161722
</div>
17171723
)}

apps/desktop/src/locales/en/servers.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@
189189
"discover": "Discover from registry",
190190
"discoverDesc": "Browse the community catalog — install with guided setup, OAuth, and credential fields.",
191191
"custom": "Add custom server",
192-
"customDesc": "Edit your Space JSON config for local CLIs, private servers, or anything not in the registry."
192+
"customDesc": "Guided setup for local CLIs, private servers, or anything not in the registry.",
193+
"viewManifest": "View full server manifest",
194+
"viewManifestDesc": "Edit the entire Space JSON file — all servers, metadata, and raw config."
193195
},
194196
"filters": {
195197
"appliedTitle": "Applied filters",

0 commit comments

Comments
 (0)