@huanlin/dsh-plugin-mcp-manager 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +24 -11
  2. package/lib/index.js +1229 -268
  3. package/lib/index.mjs +147 -13
  4. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -6,15 +6,121 @@ window.__ModuleLoader__.load({
6
6
  let react = require("react");
7
7
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
+ //#region src/client/locales.ts
10
+ /** Locale namespace id (matches the package basename; DSH locale namespace convention). */
11
+ const NS = "dsh-plugin-mcp-manager";
12
+ /** English dictionary. */
13
+ const en = {
14
+ heading: "MCP Servers",
15
+ introBefore: "Manage MCP server connections. Each server is mounted by the official",
16
+ introMid: "and tools are registered under",
17
+ introAfter: "Config writes to the profile patch and applies live via HMR.",
18
+ envWarning: "⚠ env / headers are stored as plaintext in the profile cordis.patch.yml (same shape as the official examples). Do not put long-lived secrets here. Disabling a server keeps its config; the loader skips mounting and tools stay unregistered (invisible to the model).",
19
+ loading: "Loading…",
20
+ empty: "No MCP servers yet. Click \"Add server\" to create one.",
21
+ addServer: "+ Add server",
22
+ addTitle: "Add server",
23
+ transport: "Transport",
24
+ serverNameLabel: "serverName (tool namespace, must be unique)",
25
+ serverNamePlaceholder: "github",
26
+ commandLabel: "command",
27
+ commandPlaceholder: "npx",
28
+ argsLabel: "args (one per line)",
29
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
30
+ envLabel: "env (one key=value per line, stored as plaintext)",
31
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
32
+ cwdLabel: "cwd (optional)",
33
+ urlLabel: "url",
34
+ urlPlaceholder: "https://mcp.example.com/mcp",
35
+ headersLabel: "headers (one key=value per line, stored as plaintext)",
36
+ headersPlaceholder: "Authorization=Bearer xxx",
37
+ timeoutLabel: "toolCallTimeoutMs",
38
+ cancel: "Cancel",
39
+ save: "Save",
40
+ add: "Add",
41
+ edit: "Edit",
42
+ enable: "Enable",
43
+ disable: "Disable",
44
+ delete: "Delete",
45
+ tools: "Tools",
46
+ collapse: "Collapse",
47
+ noTools: "(no registered tools — server not connected or not synced)",
48
+ statusDisabled: "Disabled",
49
+ statusConnecting: "Connecting…",
50
+ statusDisconnected: "Not connected",
51
+ toolCount: "{count} tools"
52
+ };
53
+ /** Chinese dictionary. */
54
+ const zh = {
55
+ heading: "MCP 服务器",
56
+ introBefore: "管理 MCP 服务器连接。每台服务器由官方",
57
+ introMid: "挂载,工具以",
58
+ introAfter: "命名注册。配置写入 profile patch,HMR 实时生效。",
59
+ envWarning: "⚠ env / headers 以明文存入 profile cordis.patch.yml(与官方示例同形态)。勿放长期密钥。禁用服务器不会删除配置,loader 跳过挂载,工具不注册(模型不可见)。",
60
+ loading: "加载中…",
61
+ empty: "尚无 MCP 服务器。点击「新增」添加。",
62
+ addServer: "+ 新增服务器",
63
+ addTitle: "新增服务器",
64
+ transport: "传输方式",
65
+ serverNameLabel: "serverName(工具命名空间,唯一)",
66
+ serverNamePlaceholder: "github",
67
+ commandLabel: "command",
68
+ commandPlaceholder: "npx",
69
+ argsLabel: "args(每行一个)",
70
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
71
+ envLabel: "env(每行 key=value,明文存储)",
72
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
73
+ cwdLabel: "cwd(可空)",
74
+ urlLabel: "url",
75
+ urlPlaceholder: "https://mcp.example.com/mcp",
76
+ headersLabel: "headers(每行 key=value,明文存储)",
77
+ headersPlaceholder: "Authorization=Bearer xxx",
78
+ timeoutLabel: "toolCallTimeoutMs",
79
+ cancel: "取消",
80
+ save: "保存",
81
+ add: "添加",
82
+ edit: "编辑",
83
+ enable: "启用",
84
+ disable: "禁用",
85
+ delete: "删除",
86
+ tools: "工具",
87
+ collapse: "收起",
88
+ noTools: "(无已注册工具——服务器未连接或未同步)",
89
+ statusDisabled: "已禁用",
90
+ statusConnecting: "连接中…",
91
+ statusDisconnected: "未连接",
92
+ toolCount: "{count} 工具"
93
+ };
94
+ /**
95
+ * Build a translate function over one bundled dictionary. Interpolates
96
+ * `{name}` params so a missing param leaves the placeholder in place.
97
+ * @param dict - the dictionary to read from.
98
+ * @returns a keyed translate function.
99
+ */
100
+ function makeT(dict) {
101
+ return (key, params) => {
102
+ const template = dict[key];
103
+ if (params === void 0) return template;
104
+ return template.replace(/\{(\w+)\}/g, (match, name) => params[name] === void 0 ? match : String(params[name]));
105
+ };
106
+ }
107
+ //#endregion
9
108
  //#region src/client/Panel.tsx
10
109
  /**
11
110
  * MCP 管理面板(UI 对齐官方「模型」设置页设计语言):
12
111
  * - 服务器列表:serverName + 传输标识 + 端点摘要 + 状态 Pill(connected/
13
- * disconnected)+ 工具数;行内操作:编辑 / 删除
112
+ * disconnected/disabled)+ 工具数;行内操作:编辑 / 禁用|启用 / 删除
14
113
  * - 新增/编辑表单:transport 切换(stdio ↔ streamable-http 字段组联动);
15
- * serverName/command/args/env/url/headers/超时
114
+ * serverName/command/args/env/url/headers/超时;**内联渲染**——编辑既有
115
+ * 服务器时表单展开在对应卡片下方,新增时作为顶部独立卡片
16
116
  * - 工具浏览:点击服务器展开其 mcp__ 工具列表(名称 + 描述),只读
117
+ * - 禁用:entry-level `disabled: true` 字段(config 保留,loader 跳过挂载,
118
+ * 工具不注册→模型不可见),与删除语义分离
17
119
  * 全部 token 走 --dsw-alias-*;零 CSS 依赖(inline 样式)。
120
+ *
121
+ * 文案走 DSH locale(`dsh-plugin-mcp-manager` 命名空间):slot 渲染器绑定
122
+ * 语言座位 `t`(跟随 DSH zh/en,better-locale 覆盖生效时优先覆盖文本);
123
+ * `makeT(zh)` 是 slot 系统外的直挂回退(测试/快速挂载)。
18
124
  */
19
125
  const sectionStyle = {
20
126
  display: "flex",
@@ -176,8 +282,191 @@ window.__ModuleLoader__.load({
176
282
  }
177
283
  return out;
178
284
  }
179
- /** 设置页面板主体。 */
180
- function McpPanel() {
285
+ function ServerEditor(props) {
286
+ const { config: c, isEdit, busy, envText, headersText, t } = props;
287
+ const isStdio = c.transport === "stdio";
288
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
289
+ style: editorStyle,
290
+ children: [
291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
292
+ style: fieldStyle,
293
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
294
+ style: fieldLabelStyle,
295
+ children: t("transport")
296
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
297
+ style: {
298
+ display: "flex",
299
+ gap: 8
300
+ },
301
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
302
+ onClick: () => props.onSwitchTransport("stdio"),
303
+ disabled: busy,
304
+ children: isStdio ? "✓ stdio" : "stdio"
305
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
306
+ onClick: () => props.onSwitchTransport("streamable-http"),
307
+ disabled: busy,
308
+ children: !isStdio ? "✓ streamable-http" : "streamable-http"
309
+ })]
310
+ })]
311
+ }),
312
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
313
+ style: fieldStyle,
314
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
315
+ style: fieldLabelStyle,
316
+ children: t("serverNameLabel")
317
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
318
+ value: c.serverName,
319
+ onChange: (e) => props.onConfigChange({
320
+ ...c,
321
+ serverName: e.target.value
322
+ }),
323
+ disabled: busy,
324
+ placeholder: t("serverNamePlaceholder")
325
+ })]
326
+ }),
327
+ isStdio ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
328
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
329
+ style: fieldStyle,
330
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
331
+ style: fieldLabelStyle,
332
+ children: t("commandLabel")
333
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
334
+ value: c.command ?? "",
335
+ onChange: (e) => props.onConfigChange({
336
+ ...c,
337
+ command: e.target.value
338
+ }),
339
+ disabled: busy,
340
+ placeholder: t("commandPlaceholder")
341
+ })]
342
+ }),
343
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
344
+ style: fieldStyle,
345
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
346
+ style: fieldLabelStyle,
347
+ children: t("argsLabel")
348
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
349
+ value: (c.args ?? []).join("\n"),
350
+ onChange: (e) => props.onConfigChange({
351
+ ...c,
352
+ args: e.target.value.split("\n")
353
+ }),
354
+ disabled: busy,
355
+ rows: 3,
356
+ style: {
357
+ fontSize: 12,
358
+ fontFamily: "ui-monospace, monospace",
359
+ borderRadius: 8,
360
+ border: "1px solid var(--dsw-alias-border-l2)",
361
+ padding: "8px 10px"
362
+ },
363
+ placeholder: t("argsPlaceholder")
364
+ })]
365
+ }),
366
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
367
+ style: fieldStyle,
368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
369
+ style: fieldLabelStyle,
370
+ children: t("envLabel")
371
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
372
+ value: envText,
373
+ onChange: (e) => props.onEnvTextChange(e.target.value),
374
+ disabled: busy,
375
+ rows: 3,
376
+ style: {
377
+ fontSize: 12,
378
+ fontFamily: "ui-monospace, monospace",
379
+ borderRadius: 8,
380
+ border: "1px solid var(--dsw-alias-border-l2)",
381
+ padding: "8px 10px"
382
+ },
383
+ placeholder: t("envPlaceholder")
384
+ })]
385
+ }),
386
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
387
+ style: fieldStyle,
388
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
389
+ style: fieldLabelStyle,
390
+ children: t("cwdLabel")
391
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
392
+ value: c.cwd ?? "",
393
+ onChange: (e) => props.onConfigChange({
394
+ ...c,
395
+ cwd: e.target.value
396
+ }),
397
+ disabled: busy,
398
+ placeholder: ""
399
+ })]
400
+ })
401
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
402
+ style: fieldStyle,
403
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
404
+ style: fieldLabelStyle,
405
+ children: t("urlLabel")
406
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
407
+ value: c.url ?? "",
408
+ onChange: (e) => props.onConfigChange({
409
+ ...c,
410
+ url: e.target.value
411
+ }),
412
+ disabled: busy,
413
+ placeholder: t("urlPlaceholder")
414
+ })]
415
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
416
+ style: fieldStyle,
417
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
418
+ style: fieldLabelStyle,
419
+ children: t("headersLabel")
420
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
421
+ value: headersText,
422
+ onChange: (e) => props.onHeadersTextChange(e.target.value),
423
+ disabled: busy,
424
+ rows: 3,
425
+ style: {
426
+ fontSize: 12,
427
+ fontFamily: "ui-monospace, monospace",
428
+ borderRadius: 8,
429
+ border: "1px solid var(--dsw-alias-border-l2)",
430
+ padding: "8px 10px"
431
+ },
432
+ placeholder: t("headersPlaceholder")
433
+ })]
434
+ })] }),
435
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
436
+ style: fieldStyle,
437
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
438
+ style: fieldLabelStyle,
439
+ children: t("timeoutLabel")
440
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
441
+ type: "number",
442
+ value: String(c.toolCallTimeoutMs ?? 6e4),
443
+ onChange: (e) => props.onConfigChange({
444
+ ...c,
445
+ toolCallTimeoutMs: Number(e.target.value) || 6e4
446
+ }),
447
+ disabled: busy
448
+ })]
449
+ }),
450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
451
+ style: editorActionsStyle,
452
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
453
+ onClick: props.onCancel,
454
+ disabled: busy,
455
+ children: t("cancel")
456
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
457
+ onClick: props.onSave,
458
+ disabled: busy,
459
+ children: isEdit ? t("save") : t("add")
460
+ })]
461
+ })
462
+ ]
463
+ });
464
+ }
465
+ /**
466
+ * 设置页面板主体。`t` 是 slot 系统绑定 locale 座位后的翻译函数(跟随 DSH
467
+ * zh/en + better-locale 覆盖);缺省回退到 zh 字典,供 slot 外直挂使用。
468
+ */
469
+ function McpPanel({ t = makeT(zh) }) {
181
470
  const [servers, setServers] = (0, react.useState)([]);
182
471
  const [toolGroups, setToolGroups] = (0, react.useState)({});
183
472
  const [error, setError] = (0, react.useState)(void 0);
@@ -226,7 +515,7 @@ window.__ModuleLoader__.load({
226
515
  setHeadersText("");
227
516
  setError(void 0);
228
517
  }, []);
229
- /** 打开编辑表单。 */
518
+ /** 打开编辑表单(内联到对应卡片下方)。 */
230
519
  const startEdit = (0, react.useCallback)((row) => {
231
520
  setEditing({
232
521
  id: row.id,
@@ -281,6 +570,25 @@ window.__ModuleLoader__.load({
281
570
  try {
282
571
  const body = await (await fetch(`/api/mcp-manager/servers/${encodeURIComponent(id)}`, { method: "DELETE" })).json();
283
572
  if (body.ok !== true) throw new Error(body.message ?? "delete failed");
573
+ if (editing?.id === id) setEditing(void 0);
574
+ await refresh();
575
+ } catch (caught) {
576
+ setError(caught instanceof Error ? caught.message : String(caught));
577
+ } finally {
578
+ setBusy(false);
579
+ }
580
+ }, [refresh, editing]);
581
+ /** 禁用/启用(不删除配置)。 */
582
+ const toggleDisabled = (0, react.useCallback)(async (row) => {
583
+ setBusy(true);
584
+ setError(void 0);
585
+ try {
586
+ const body = await (await fetch(`/api/mcp-manager/servers/${encodeURIComponent(row.id)}`, {
587
+ method: "PATCH",
588
+ headers: { "content-type": "application/json" },
589
+ body: JSON.stringify({ disabled: !row.disabled })
590
+ })).json();
591
+ if (body.ok !== true) throw new Error(body.message ?? "toggle failed");
284
592
  await refresh();
285
593
  } catch (caught) {
286
594
  setError(caught instanceof Error ? caught.message : String(caught));
@@ -297,28 +605,30 @@ window.__ModuleLoader__.load({
297
605
  return next;
298
606
  });
299
607
  }, []);
300
- const c = editing?.config;
301
- const isStdio = c?.transport === "stdio";
302
608
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
303
609
  style: sectionStyle,
304
610
  children: [
305
611
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
306
612
  style: titleStyle,
307
- children: "MCP 服务器"
613
+ children: t("heading")
308
614
  }),
309
615
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
310
616
  style: introStyle,
311
617
  children: [
312
- "管理 MCP 服务器连接。每台服务器由官方 ",
618
+ t("introBefore"),
619
+ " ",
313
620
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: "@deepseek-ai/dsh-mcp-client" }),
314
- " 挂载, 工具以 ",
621
+ " ",
622
+ t("introMid"),
623
+ " ",
315
624
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: "mcp__<serverName>__*" }),
316
- " 命名注册。配置写入 profile patch,HMR 实时生效。"
625
+ " ",
626
+ t("introAfter")
317
627
  ]
318
628
  }),
319
629
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
320
630
  style: warnStyle,
321
- children: "⚠ env / headers 以明文存入 profile cordis.patch.yml(与官方示例同形态)。勿放长期密钥。"
631
+ children: t("envWarning")
322
632
  }),
323
633
  error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
324
634
  style: errorStyle,
@@ -326,293 +636,944 @@ window.__ModuleLoader__.load({
326
636
  }),
327
637
  loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
328
638
  style: introStyle,
329
- children: "加载中…"
639
+ children: t("loading")
330
640
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
331
641
  style: rowsStyle,
332
- children: [servers.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
333
- style: rowCardStyle,
334
- children: [
335
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
642
+ children: [
643
+ editing !== void 0 && editing.id.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
644
+ style: rowCardStyle,
645
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
336
646
  style: rowHeadStyle,
337
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
647
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
338
648
  style: identityStyle,
339
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
649
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
340
650
  style: nameStyle,
341
- children: row.config.serverName
342
- }), row.status === "connected" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
343
- active: true,
344
- children: [row.toolCount, " 工具"]
345
- }) : row.status === "connecting" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, { children: "连接中…" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, { children: "未连接" })]
346
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
347
- style: actionsStyle,
348
- children: [
349
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
350
- onClick: () => toggleExpand(row.id),
351
- disabled: busy,
352
- children: expanded.has(row.id) ? "收起" : "工具"
353
- }),
354
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
355
- onClick: () => startEdit(row),
356
- disabled: busy,
357
- children: "编辑"
358
- }),
359
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
360
- onClick: () => void remove(row.id),
361
- disabled: busy,
362
- children: "删除"
363
- })
364
- ]
365
- })]
366
- }),
367
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
368
- style: metaStyle,
369
- children: [
370
- row.transport,
371
- " · ",
372
- row.endpoint,
373
- " · id: ",
374
- row.id
375
- ]
376
- }),
377
- expanded.has(row.id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
378
- style: toolListStyle,
379
- children: (toolGroups[row.config.serverName] ?? []).length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
380
- style: toolRowStyle,
381
- children: "(无已注册工具——服务器未连接或未同步)"
382
- }) : toolGroups[row.config.serverName].map((t) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
383
- style: toolRowStyle,
384
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
385
- style: toolNameStyle,
386
- children: t.rawName
387
- }), t.description !== void 0 && t.description.length > 0 ? ` — ${t.description}` : ""]
388
- }, t.name))
389
- })
390
- ]
391
- }, row.id)), servers.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
392
- style: introStyle,
393
- children: "尚无 MCP 服务器。点击「新增」添加。"
394
- })]
395
- }),
396
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
397
- style: editorActionsStyle,
398
- children: editing === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
399
- onClick: startAdd,
400
- disabled: busy,
401
- children: "+ 新增服务器"
402
- })
403
- }),
404
- editing !== void 0 && c !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
405
- style: editorStyle,
406
- children: [
407
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
408
- style: fieldStyle,
409
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
410
- style: fieldLabelStyle,
411
- children: "传输方式"
412
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
413
- style: {
414
- display: "flex",
415
- gap: 8
416
- },
417
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
418
- onClick: () => switchTransport("stdio"),
419
- disabled: busy,
420
- children: isStdio ? "✓ stdio" : "stdio"
421
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
422
- onClick: () => switchTransport("streamable-http"),
423
- disabled: busy,
424
- children: !isStdio ? "✓ streamable-http" : "streamable-http"
425
- })]
426
- })]
427
- }),
428
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
429
- style: fieldStyle,
430
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
431
- style: fieldLabelStyle,
432
- children: "serverName(工具命名空间,唯一)"
433
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
434
- value: c.serverName,
435
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
436
- ...p,
437
- config: {
438
- ...p.config,
439
- serverName: e.target.value
440
- }
651
+ children: t("addTitle")
652
+ })
653
+ })
654
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ServerEditor, {
655
+ config: editing.config,
656
+ isEdit: false,
657
+ busy,
658
+ envText,
659
+ headersText,
660
+ t,
661
+ onConfigChange: (next) => setEditing((prev) => prev === void 0 ? prev : {
662
+ ...prev,
663
+ config: next
441
664
  }),
442
- disabled: busy,
443
- placeholder: "github"
665
+ onEnvTextChange: setEnvText,
666
+ onHeadersTextChange: setHeadersText,
667
+ onSwitchTransport: switchTransport,
668
+ onSave: () => void save(),
669
+ onCancel: () => setEditing(void 0)
444
670
  })]
445
671
  }),
446
- isStdio ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
447
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
448
- style: fieldStyle,
449
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
450
- style: fieldLabelStyle,
451
- children: "command"
452
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
453
- value: c.command ?? "",
454
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
455
- ...p,
456
- config: {
457
- ...p.config,
458
- command: e.target.value
459
- }
672
+ servers.map((row) => {
673
+ const isEditingThis = editing?.id === row.id;
674
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
675
+ style: {
676
+ ...rowCardStyle,
677
+ opacity: row.disabled ? .6 : 1
678
+ },
679
+ children: [
680
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
681
+ style: rowHeadStyle,
682
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
683
+ style: identityStyle,
684
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
685
+ style: nameStyle,
686
+ children: row.config.serverName
687
+ }), row.disabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, { children: t("statusDisabled") }) : row.status === "connected" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
688
+ active: true,
689
+ children: t("toolCount", { count: row.toolCount })
690
+ }) : row.status === "connecting" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, { children: t("statusConnecting") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, { children: t("statusDisconnected") })]
691
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
692
+ style: actionsStyle,
693
+ children: [
694
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
695
+ onClick: () => toggleExpand(row.id),
696
+ disabled: busy || row.disabled,
697
+ children: expanded.has(row.id) ? t("collapse") : t("tools")
698
+ }),
699
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
700
+ onClick: () => startEdit(row),
701
+ disabled: busy || isEditingThis,
702
+ children: t("edit")
703
+ }),
704
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
705
+ onClick: () => void toggleDisabled(row),
706
+ disabled: busy || isEditingThis,
707
+ children: row.disabled ? t("enable") : t("disable")
708
+ }),
709
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
710
+ onClick: () => void remove(row.id),
711
+ disabled: busy || isEditingThis,
712
+ children: t("delete")
713
+ })
714
+ ]
715
+ })]
460
716
  }),
461
- disabled: busy,
462
- placeholder: "npx"
463
- })]
464
- }),
465
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
466
- style: fieldStyle,
467
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
468
- style: fieldLabelStyle,
469
- children: "args(每行一个)"
470
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
471
- value: (c.args ?? []).join("\n"),
472
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
473
- ...p,
474
- config: {
475
- ...p.config,
476
- args: e.target.value.split("\n")
477
- }
717
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
718
+ style: metaStyle,
719
+ children: [
720
+ row.transport,
721
+ " · ",
722
+ row.endpoint,
723
+ " · id: ",
724
+ row.id
725
+ ]
478
726
  }),
479
- disabled: busy,
480
- rows: 3,
481
- style: {
482
- fontSize: 12,
483
- fontFamily: "ui-monospace, monospace",
484
- borderRadius: 8,
485
- border: "1px solid var(--dsw-alias-border-l2)",
486
- padding: "8px 10px"
487
- },
488
- placeholder: "-y\n@modelcontextprotocol/server-github"
489
- })]
490
- }),
491
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
492
- style: fieldStyle,
493
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
494
- style: fieldLabelStyle,
495
- children: "env(每行 key=value,明文存储)"
496
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
497
- value: envText,
498
- onChange: (e) => setEnvText(e.target.value),
499
- disabled: busy,
500
- rows: 3,
501
- style: {
502
- fontSize: 12,
503
- fontFamily: "ui-monospace, monospace",
504
- borderRadius: 8,
505
- border: "1px solid var(--dsw-alias-border-l2)",
506
- padding: "8px 10px"
507
- },
508
- placeholder: "GITHUB_TOKEN=ghp_xxx"
509
- })]
510
- }),
511
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
512
- style: fieldStyle,
513
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
514
- style: fieldLabelStyle,
515
- children: "cwd(可空)"
516
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
517
- value: c.cwd ?? "",
518
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
519
- ...p,
520
- config: {
521
- ...p.config,
522
- cwd: e.target.value
523
- }
727
+ expanded.has(row.id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
728
+ style: toolListStyle,
729
+ children: (toolGroups[row.config.serverName] ?? []).length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
730
+ style: toolRowStyle,
731
+ children: t("noTools")
732
+ }) : toolGroups[row.config.serverName].map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
733
+ style: toolRowStyle,
734
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
735
+ style: toolNameStyle,
736
+ children: tool.rawName
737
+ }), tool.description !== void 0 && tool.description.length > 0 ? ` — ${tool.description}` : ""]
738
+ }, tool.name))
524
739
  }),
525
- disabled: busy,
526
- placeholder: ""
527
- })]
528
- })
529
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
530
- style: fieldStyle,
531
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
532
- style: fieldLabelStyle,
533
- children: "url"
534
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
535
- value: c.url ?? "",
536
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
537
- ...p,
538
- config: {
539
- ...p.config,
540
- url: e.target.value
541
- }
542
- }),
543
- disabled: busy,
544
- placeholder: "https://mcp.example.com/mcp"
545
- })]
546
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
547
- style: fieldStyle,
548
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
549
- style: fieldLabelStyle,
550
- children: "headers(每行 key=value,明文存储)"
551
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
552
- value: headersText,
553
- onChange: (e) => setHeadersText(e.target.value),
554
- disabled: busy,
555
- rows: 3,
556
- style: {
557
- fontSize: 12,
558
- fontFamily: "ui-monospace, monospace",
559
- borderRadius: 8,
560
- border: "1px solid var(--dsw-alias-border-l2)",
561
- padding: "8px 10px"
562
- },
563
- placeholder: "Authorization=Bearer xxx"
564
- })]
565
- })] }),
566
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
567
- style: fieldStyle,
568
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
569
- style: fieldLabelStyle,
570
- children: "toolCallTimeoutMs"
571
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
572
- type: "number",
573
- value: String(c.toolCallTimeoutMs ?? 6e4),
574
- onChange: (e) => setEditing((p) => p === void 0 ? p : {
575
- ...p,
576
- config: {
577
- ...p.config,
578
- toolCallTimeoutMs: Number(e.target.value) || 6e4
579
- }
580
- }),
581
- disabled: busy
582
- })]
740
+ isEditingThis && editing !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ServerEditor, {
741
+ config: editing.config,
742
+ isEdit: true,
743
+ busy,
744
+ envText,
745
+ headersText,
746
+ t,
747
+ onConfigChange: (next) => setEditing((prev) => prev === void 0 ? prev : {
748
+ ...prev,
749
+ config: next
750
+ }),
751
+ onEnvTextChange: setEnvText,
752
+ onHeadersTextChange: setHeadersText,
753
+ onSwitchTransport: switchTransport,
754
+ onSave: () => void save(),
755
+ onCancel: () => setEditing(void 0)
756
+ })
757
+ ]
758
+ }, row.id);
583
759
  }),
584
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
585
- style: editorActionsStyle,
586
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
587
- onClick: () => setEditing(void 0),
588
- disabled: busy,
589
- children: "取消"
590
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
591
- onClick: () => void save(),
592
- disabled: busy,
593
- children: editing.id.length > 0 ? "保存" : "添加"
594
- })]
760
+ servers.length === 0 && editing === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
761
+ style: introStyle,
762
+ children: t("empty")
595
763
  })
596
764
  ]
765
+ }),
766
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
767
+ style: editorActionsStyle,
768
+ children: editing === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
769
+ onClick: startAdd,
770
+ disabled: busy,
771
+ children: t("addServer")
772
+ })
597
773
  })
598
774
  ]
599
775
  });
600
776
  }
601
777
  //#endregion
778
+ //#region src/client/dictionaries.ts
779
+ /** All override-language dictionaries for the `NS` namespace. */
780
+ const dicts = {
781
+ ja: {
782
+ heading: "MCP サーバー",
783
+ introBefore: "MCP サーバー接続を管理します。各サーバーは公式の",
784
+ introMid: "によってマウントされ、ツールは",
785
+ introAfter: "として登録されます。設定は profile patch に書き込まれ、HMR で即時反映されます。",
786
+ envWarning: "⚠ env / headers は profile cordis.patch.yml に平文で保存されます(公式サンプルと同じ形式)。長期の秘密鍵は置かないでください。サーバーを無効化しても設定は削除されず、loader がマウントをスキップしてツールは登録されません(モデルから見えなくなります)。",
787
+ loading: "読み込み中…",
788
+ empty: "MCP サーバーはまだありません。「サーバーを追加」で作成してください。",
789
+ addServer: "+ サーバーを追加",
790
+ addTitle: "サーバーを追加",
791
+ transport: "転送方式",
792
+ serverNameLabel: "serverName(ツール名前空間、一意である必要があります)",
793
+ serverNamePlaceholder: "github",
794
+ commandLabel: "command",
795
+ commandPlaceholder: "npx",
796
+ argsLabel: "args(1 行に 1 つ)",
797
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
798
+ envLabel: "env(1 行に 1 つの key=value、平文で保存)",
799
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
800
+ cwdLabel: "cwd(省略可)",
801
+ urlLabel: "url",
802
+ urlPlaceholder: "https://mcp.example.com/mcp",
803
+ headersLabel: "headers(1 行に 1 つの key=value、平文で保存)",
804
+ headersPlaceholder: "Authorization=Bearer xxx",
805
+ timeoutLabel: "toolCallTimeoutMs",
806
+ cancel: "キャンセル",
807
+ save: "保存",
808
+ add: "追加",
809
+ edit: "編集",
810
+ enable: "有効化",
811
+ disable: "無効化",
812
+ delete: "削除",
813
+ tools: "ツール",
814
+ collapse: "折りたたむ",
815
+ noTools: "(登録済みツールなし——サーバーが未接続または未同期です)",
816
+ statusDisabled: "無効",
817
+ statusConnecting: "接続中…",
818
+ statusDisconnected: "未接続",
819
+ toolCount: "{count} ツール"
820
+ },
821
+ de: {
822
+ heading: "MCP-Server",
823
+ introBefore: "MCP-Serververbindungen verwalten. Jeder Server wird von der offiziellen",
824
+ introMid: "gemountet, wobei Tools unter",
825
+ introAfter: "registriert werden. Die Konfiguration wird in den Profile-Patch geschrieben und per HMR sofort wirksam.",
826
+ envWarning: "⚠ env / headers werden im Profile cordis.patch.yml im Klartext gespeichert (wie in den offiziellen Beispielen). Keine langlebigen Geheimnisse hier ablegen. Das Deaktivieren eines Servers löscht die Konfiguration nicht; der Loader überspringt das Mounten und Tools bleiben unregistriert (für das Modell unsichtbar).",
827
+ loading: "Wird geladen…",
828
+ empty: "Noch keine MCP-Server. Klicke auf „Server hinzufügen”, um einen anzulegen.",
829
+ addServer: "+ Server hinzufügen",
830
+ addTitle: "Server hinzufügen",
831
+ transport: "Transport",
832
+ serverNameLabel: "serverName (Tool-Namespace, muss eindeutig sein)",
833
+ serverNamePlaceholder: "github",
834
+ commandLabel: "command",
835
+ commandPlaceholder: "npx",
836
+ argsLabel: "args (eines pro Zeile)",
837
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
838
+ envLabel: "env (ein key=value pro Zeile, im Klartext gespeichert)",
839
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
840
+ cwdLabel: "cwd (optional)",
841
+ urlLabel: "url",
842
+ urlPlaceholder: "https://mcp.example.com/mcp",
843
+ headersLabel: "headers (ein key=value pro Zeile, im Klartext gespeichert)",
844
+ headersPlaceholder: "Authorization=Bearer xxx",
845
+ timeoutLabel: "toolCallTimeoutMs",
846
+ cancel: "Abbrechen",
847
+ save: "Speichern",
848
+ add: "Hinzufügen",
849
+ edit: "Bearbeiten",
850
+ enable: "Aktivieren",
851
+ disable: "Deaktivieren",
852
+ delete: "Löschen",
853
+ tools: "Tools",
854
+ collapse: "Einklappen",
855
+ noTools: "(keine registrierten Tools — Server nicht verbunden oder nicht synchronisiert)",
856
+ statusDisabled: "Deaktiviert",
857
+ statusConnecting: "Verbinde…",
858
+ statusDisconnected: "Nicht verbunden",
859
+ toolCount: "{count} Tools"
860
+ },
861
+ fr: {
862
+ heading: "Serveurs MCP",
863
+ introBefore: "Gérez les connexions aux serveurs MCP. Chaque serveur est monté par le",
864
+ introMid: "officiel, et les outils sont enregistrés sous",
865
+ introAfter: "La configuration est écrite dans le patch du profil et appliquée en direct via HMR.",
866
+ envWarning: "⚠ env / headers sont stockés en clair dans le cordis.patch.yml du profil (comme les exemples officiels). N'y placez pas de secrets durables. Désactiver un serveur conserve sa configuration ; le loader ignore le montage et les outils restent non enregistrés (invisibles pour le modèle).",
867
+ loading: "Chargement…",
868
+ empty: "Aucun serveur MCP pour le moment. Cliquez sur « Ajouter un serveur » pour en créer un.",
869
+ addServer: "+ Ajouter un serveur",
870
+ addTitle: "Ajouter un serveur",
871
+ transport: "Transport",
872
+ serverNameLabel: "serverName (espace de noms des outils, doit être unique)",
873
+ serverNamePlaceholder: "github",
874
+ commandLabel: "command",
875
+ commandPlaceholder: "npx",
876
+ argsLabel: "args (un par ligne)",
877
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
878
+ envLabel: "env (un key=value par ligne, stocké en clair)",
879
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
880
+ cwdLabel: "cwd (optionnel)",
881
+ urlLabel: "url",
882
+ urlPlaceholder: "https://mcp.example.com/mcp",
883
+ headersLabel: "headers (un key=value par ligne, stocké en clair)",
884
+ headersPlaceholder: "Authorization=Bearer xxx",
885
+ timeoutLabel: "toolCallTimeoutMs",
886
+ cancel: "Annuler",
887
+ save: "Enregistrer",
888
+ add: "Ajouter",
889
+ edit: "Modifier",
890
+ enable: "Activer",
891
+ disable: "Désactiver",
892
+ delete: "Supprimer",
893
+ tools: "Outils",
894
+ collapse: "Réduire",
895
+ noTools: "(aucun outil enregistré — serveur non connecté ou non synchronisé)",
896
+ statusDisabled: "Désactivé",
897
+ statusConnecting: "Connexion…",
898
+ statusDisconnected: "Non connecté",
899
+ toolCount: "{count} outils"
900
+ },
901
+ pt: {
902
+ heading: "Servidores MCP",
903
+ introBefore: "Gerencie as conexões dos servidores MCP. Cada servidor é montado pelo",
904
+ introMid: "oficial, e as ferramentas são registradas sob",
905
+ introAfter: "A configuração é gravada no patch do perfil e aplicada ao vivo via HMR.",
906
+ envWarning: "⚠ env / headers são armazenados em texto puro no cordis.patch.yml do perfil (mesmo formato dos exemplos oficiais). Não coloque segredos de longo prazo aqui. Desativar um servidor mantém a configuração; o loader pula a montagem e as ferramentas permanecem não registradas (invisíveis para o modelo).",
907
+ loading: "Carregando…",
908
+ empty: "Ainda não há servidores MCP. Clique em \"Adicionar servidor\" para criar um.",
909
+ addServer: "+ Adicionar servidor",
910
+ addTitle: "Adicionar servidor",
911
+ transport: "Transporte",
912
+ serverNameLabel: "serverName (namespace de ferramentas, deve ser único)",
913
+ serverNamePlaceholder: "github",
914
+ commandLabel: "command",
915
+ commandPlaceholder: "npx",
916
+ argsLabel: "args (um por linha)",
917
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
918
+ envLabel: "env (um key=value por linha, armazenado em texto puro)",
919
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
920
+ cwdLabel: "cwd (opcional)",
921
+ urlLabel: "url",
922
+ urlPlaceholder: "https://mcp.example.com/mcp",
923
+ headersLabel: "headers (um key=value por linha, armazenado em texto puro)",
924
+ headersPlaceholder: "Authorization=Bearer xxx",
925
+ timeoutLabel: "toolCallTimeoutMs",
926
+ cancel: "Cancelar",
927
+ save: "Salvar",
928
+ add: "Adicionar",
929
+ edit: "Editar",
930
+ enable: "Ativar",
931
+ disable: "Desativar",
932
+ delete: "Excluir",
933
+ tools: "Ferramentas",
934
+ collapse: "Recolher",
935
+ noTools: "(nenhuma ferramenta registrada — servidor não conectado ou não sincronizado)",
936
+ statusDisabled: "Desativado",
937
+ statusConnecting: "Conectando…",
938
+ statusDisconnected: "Não conectado",
939
+ toolCount: "{count} ferramentas"
940
+ },
941
+ ko: {
942
+ heading: "MCP 서버",
943
+ introBefore: "MCP 서버 연결을 관리합니다. 각 서버는 공식",
944
+ introMid: "에 의해 마운트되며, 도구는",
945
+ introAfter: "로 등록됩니다. 설정은 profile patch에 기록되어 HMR로 즉시 적용됩니다.",
946
+ envWarning: "⚠ env / headers는 profile cordis.patch.yml에 평문으로 저장됩니다(공식 예제와 동일한 형태). 장기 보관할 비밀 키는 넣지 마세요. 서버를 비활성화해도 설정은 삭제되지 않으며, loader가 마운트를 건너뛰어 도구가 등록되지 않습니다(모델에 보이지 않음).",
947
+ loading: "불러오는 중…",
948
+ empty: "아직 MCP 서버가 없습니다. \"서버 추가\"를 클릭하여 생성하세요.",
949
+ addServer: "+ 서버 추가",
950
+ addTitle: "서버 추가",
951
+ transport: "전송 방식",
952
+ serverNameLabel: "serverName(도구 네임스페이스, 고유해야 함)",
953
+ serverNamePlaceholder: "github",
954
+ commandLabel: "command",
955
+ commandPlaceholder: "npx",
956
+ argsLabel: "args(줄마다 하나)",
957
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
958
+ envLabel: "env(줄마다 key=value 하나씩, 평문 저장)",
959
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
960
+ cwdLabel: "cwd(선택)",
961
+ urlLabel: "url",
962
+ urlPlaceholder: "https://mcp.example.com/mcp",
963
+ headersLabel: "headers(줄마다 key=value 하나씩, 평문 저장)",
964
+ headersPlaceholder: "Authorization=Bearer xxx",
965
+ timeoutLabel: "toolCallTimeoutMs",
966
+ cancel: "취소",
967
+ save: "저장",
968
+ add: "추가",
969
+ edit: "편집",
970
+ enable: "활성화",
971
+ disable: "비활성화",
972
+ delete: "삭제",
973
+ tools: "도구",
974
+ collapse: "접기",
975
+ noTools: "(등록된 도구 없음 — 서버가 연결되지 않았거나 동기화되지 않음)",
976
+ statusDisabled: "비활성화됨",
977
+ statusConnecting: "연결 중…",
978
+ statusDisconnected: "연결 안 됨",
979
+ toolCount: "도구 {count}개"
980
+ },
981
+ ar: {
982
+ heading: "خوادم MCP",
983
+ introBefore: "إدارة اتصالات خوادم MCP. يتم تركيب كل خادم بواسطة",
984
+ introMid: "الرسمي، ويتم تسجيل الأدوات تحت",
985
+ introAfter: "تُكتب الإعدادات في تصحيح ملف التعريف (profile patch) وتُطبَّق فورًا عبر HMR.",
986
+ envWarning: "⚠ تُخزَّن env / headers كنص صريح في cordis.patch.yml لملف التعريف (بنفس شكل الأمثلة الرسمية). لا تضع أسرارًا طويلة الأمد هنا. تعطيل خادم يحتفظ بإعداداته؛ يتخطى المحمّل التركيب وتبقى الأدوات غير مسجلة (غير مرئية للنموذج).",
987
+ loading: "جارٍ التحميل…",
988
+ empty: "لا توجد خوادم MCP بعد. انقر فوق «إضافة خادم» لإنشاء واحد.",
989
+ addServer: "+ إضافة خادم",
990
+ addTitle: "إضافة خادم",
991
+ transport: "النقل",
992
+ serverNameLabel: "serverName (مساحة أسماء الأدوات، يجب أن يكون فريدًا)",
993
+ serverNamePlaceholder: "github",
994
+ commandLabel: "command",
995
+ commandPlaceholder: "npx",
996
+ argsLabel: "args (واحد لكل سطر)",
997
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
998
+ envLabel: "env (key=value واحد لكل سطر، مخزَّن كنص صريح)",
999
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1000
+ cwdLabel: "cwd (اختياري)",
1001
+ urlLabel: "url",
1002
+ urlPlaceholder: "https://mcp.example.com/mcp",
1003
+ headersLabel: "headers (key=value واحد لكل سطر، مخزَّن كنص صريح)",
1004
+ headersPlaceholder: "Authorization=Bearer xxx",
1005
+ timeoutLabel: "toolCallTimeoutMs",
1006
+ cancel: "إلغاء",
1007
+ save: "حفظ",
1008
+ add: "إضافة",
1009
+ edit: "تعديل",
1010
+ enable: "تفعيل",
1011
+ disable: "تعطيل",
1012
+ delete: "حذف",
1013
+ tools: "الأدوات",
1014
+ collapse: "طي",
1015
+ noTools: "(لا أدوات مسجلة — الخادم غير متصل أو غير متزامن)",
1016
+ statusDisabled: "معطَّل",
1017
+ statusConnecting: "جارٍ الاتصال…",
1018
+ statusDisconnected: "غير متصل",
1019
+ toolCount: "{count} أدوات"
1020
+ },
1021
+ hi: {
1022
+ heading: "MCP सर्वर",
1023
+ introBefore: "MCP सर्वर कनेक्शन प्रबंधित करें। प्रत्येक सर्वर आधिकारिक",
1024
+ introMid: "द्वारा माउंट किया जाता है, और टूल",
1025
+ introAfter: "के अंतर्गत पंजीकृत होते हैं। कॉन्फ़िग profile patch में लिखा जाता है और HMR के माध्यम से तुरंत लागू होता है।",
1026
+ envWarning: "⚠ env / headers profile cordis.patch.yml में सादे पाठ में संग्रहीत होते हैं (आधिकारिक उदाहरणों के समान रूप)। यहाँ दीर्घकालिक रहस्य न रखें। सर्वर को अक्षम करने से उसका कॉन्फ़िग बना रहता है; loader माउंटिंग छोड़ देता है और टूल पंजीकृत नहीं रहते (मॉडल को दिखाई नहीं देते)।",
1027
+ loading: "लोड हो रहा है…",
1028
+ empty: "अभी कोई MCP सर्वर नहीं है। बनाने के लिए \"सर्वर जोड़ें\" पर क्लिक करें।",
1029
+ addServer: "+ सर्वर जोड़ें",
1030
+ addTitle: "सर्वर जोड़ें",
1031
+ transport: "ट्रांसपोर्ट",
1032
+ serverNameLabel: "serverName (टूल नेमस्पेस, अद्वितीय होना चाहिए)",
1033
+ serverNamePlaceholder: "github",
1034
+ commandLabel: "command",
1035
+ commandPlaceholder: "npx",
1036
+ argsLabel: "args (प्रति पंक्ति एक)",
1037
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1038
+ envLabel: "env (प्रति पंक्ति एक key=value, सादे पाठ में संग्रहीत)",
1039
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1040
+ cwdLabel: "cwd (वैकल्पिक)",
1041
+ urlLabel: "url",
1042
+ urlPlaceholder: "https://mcp.example.com/mcp",
1043
+ headersLabel: "headers (प्रति पंक्ति एक key=value, सादे पाठ में संग्रहीत)",
1044
+ headersPlaceholder: "Authorization=Bearer xxx",
1045
+ timeoutLabel: "toolCallTimeoutMs",
1046
+ cancel: "रद्द करें",
1047
+ save: "सहेजें",
1048
+ add: "जोड़ें",
1049
+ edit: "संपादित करें",
1050
+ enable: "सक्षम करें",
1051
+ disable: "अक्षम करें",
1052
+ delete: "हटाएँ",
1053
+ tools: "टूल",
1054
+ collapse: "संक्षिप्त करें",
1055
+ noTools: "(कोई पंजीकृत टूल नहीं — सर्वर कनेक्ट नहीं है या सिंक नहीं हुआ)",
1056
+ statusDisabled: "अक्षम",
1057
+ statusConnecting: "कनेक्ट हो रहा है…",
1058
+ statusDisconnected: "कनेक्ट नहीं है",
1059
+ toolCount: "{count} टूल"
1060
+ },
1061
+ id: {
1062
+ heading: "Server MCP",
1063
+ introBefore: "Kelola koneksi server MCP. Setiap server dipasang oleh",
1064
+ introMid: "resmi, dan alat didaftarkan di bawah",
1065
+ introAfter: "Konfigurasi ditulis ke patch profil dan langsung berlaku melalui HMR.",
1066
+ envWarning: "⚠ env / headers disimpan sebagai teks biasa di cordis.patch.yml profil (sama seperti contoh resmi). Jangan taruh rahasia jangka panjang di sini. Menonaktifkan server tetap menyimpan konfigurasinya; loader melewati pemasangan dan alat tidak terdaftar (tidak terlihat oleh model).",
1067
+ loading: "Memuat…",
1068
+ empty: "Belum ada server MCP. Klik \"Tambahkan server\" untuk membuatnya.",
1069
+ addServer: "+ Tambahkan server",
1070
+ addTitle: "Tambahkan server",
1071
+ transport: "Transport",
1072
+ serverNameLabel: "serverName (namespace alat, harus unik)",
1073
+ serverNamePlaceholder: "github",
1074
+ commandLabel: "command",
1075
+ commandPlaceholder: "npx",
1076
+ argsLabel: "args (satu per baris)",
1077
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1078
+ envLabel: "env (satu key=value per baris, disimpan sebagai teks biasa)",
1079
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1080
+ cwdLabel: "cwd (opsional)",
1081
+ urlLabel: "url",
1082
+ urlPlaceholder: "https://mcp.example.com/mcp",
1083
+ headersLabel: "headers (satu key=value per baris, disimpan sebagai teks biasa)",
1084
+ headersPlaceholder: "Authorization=Bearer xxx",
1085
+ timeoutLabel: "toolCallTimeoutMs",
1086
+ cancel: "Batal",
1087
+ save: "Simpan",
1088
+ add: "Tambah",
1089
+ edit: "Edit",
1090
+ enable: "Aktifkan",
1091
+ disable: "Nonaktifkan",
1092
+ delete: "Hapus",
1093
+ tools: "Alat",
1094
+ collapse: "Ciutkan",
1095
+ noTools: "(tidak ada alat terdaftar — server tidak terhubung atau belum tersinkron)",
1096
+ statusDisabled: "Nonaktif",
1097
+ statusConnecting: "Menghubungkan…",
1098
+ statusDisconnected: "Tidak terhubung",
1099
+ toolCount: "{count} alat"
1100
+ },
1101
+ tr: {
1102
+ heading: "MCP Sunucuları",
1103
+ introBefore: "MCP sunucu bağlantılarını yönetin. Her sunucu resmi",
1104
+ introMid: "tarafından bağlanır ve araçlar",
1105
+ introAfter: "ile kaydedilir. Yapılandırma profil yamasına yazılır ve HMR ile anında uygulanır.",
1106
+ envWarning: "⚠ env / headers, profil cordis.patch.yml dosyasında düz metin olarak saklanır (resmi örneklerle aynı biçim). Buraya uzun ömürlü sırlar koymayın. Bir sunucuyu devre dışı bırakmak yapılandırmasını korur; yükleyici bağlamayı atlar ve araçlar kayıtsız kalır (model tarafından görülemez).",
1107
+ loading: "Yükleniyor…",
1108
+ empty: "Henüz MCP sunucusu yok. Oluşturmak için \"Sunucu ekle\"ye tıklayın.",
1109
+ addServer: "+ Sunucu ekle",
1110
+ addTitle: "Sunucu ekle",
1111
+ transport: "Aktarım",
1112
+ serverNameLabel: "serverName (araç ad alanı, benzersiz olmalı)",
1113
+ serverNamePlaceholder: "github",
1114
+ commandLabel: "command",
1115
+ commandPlaceholder: "npx",
1116
+ argsLabel: "args (satır başına bir)",
1117
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1118
+ envLabel: "env (satır başına bir key=value, düz metin olarak saklanır)",
1119
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1120
+ cwdLabel: "cwd (isteğe bağlı)",
1121
+ urlLabel: "url",
1122
+ urlPlaceholder: "https://mcp.example.com/mcp",
1123
+ headersLabel: "headers (satır başına bir key=value, düz metin olarak saklanır)",
1124
+ headersPlaceholder: "Authorization=Bearer xxx",
1125
+ timeoutLabel: "toolCallTimeoutMs",
1126
+ cancel: "İptal",
1127
+ save: "Kaydet",
1128
+ add: "Ekle",
1129
+ edit: "Düzenle",
1130
+ enable: "Etkinleştir",
1131
+ disable: "Devre dışı bırak",
1132
+ delete: "Sil",
1133
+ tools: "Araçlar",
1134
+ collapse: "Daralt",
1135
+ noTools: "(kayıtlı araç yok — sunucu bağlı değil veya eşitlenmemiş)",
1136
+ statusDisabled: "Devre dışı",
1137
+ statusConnecting: "Bağlanıyor…",
1138
+ statusDisconnected: "Bağlı değil",
1139
+ toolCount: "{count} araç"
1140
+ },
1141
+ vi: {
1142
+ heading: "Máy chủ MCP",
1143
+ introBefore: "Quản lý kết nối máy chủ MCP. Mỗi máy chủ được gắn bởi",
1144
+ introMid: "chính thức, và các công cụ được đăng ký dưới",
1145
+ introAfter: "Cấu hình được ghi vào profile patch và áp dụng trực tiếp qua HMR.",
1146
+ envWarning: "⚠ env / headers được lưu dưới dạng văn bản thô trong cordis.patch.yml của profile (giống các ví dụ chính thức). Không đặt bí mật dài hạn ở đây. Vô hiệu hóa máy chủ vẫn giữ cấu hình; loader bỏ qua việc gắn và các công cụ không được đăng ký (không hiển thị với mô hình).",
1147
+ loading: "Đang tải…",
1148
+ empty: "Chưa có máy chủ MCP nào. Nhấp \"Thêm máy chủ\" để tạo.",
1149
+ addServer: "+ Thêm máy chủ",
1150
+ addTitle: "Thêm máy chủ",
1151
+ transport: "Giao thức truyền",
1152
+ serverNameLabel: "serverName (không gian tên công cụ, phải là duy nhất)",
1153
+ serverNamePlaceholder: "github",
1154
+ commandLabel: "command",
1155
+ commandPlaceholder: "npx",
1156
+ argsLabel: "args (mỗi dòng một)",
1157
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1158
+ envLabel: "env (mỗi dòng một key=value, lưu dạng văn bản thô)",
1159
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1160
+ cwdLabel: "cwd (tùy chọn)",
1161
+ urlLabel: "url",
1162
+ urlPlaceholder: "https://mcp.example.com/mcp",
1163
+ headersLabel: "headers (mỗi dòng một key=value, lưu dạng văn bản thô)",
1164
+ headersPlaceholder: "Authorization=Bearer xxx",
1165
+ timeoutLabel: "toolCallTimeoutMs",
1166
+ cancel: "Hủy",
1167
+ save: "Lưu",
1168
+ add: "Thêm",
1169
+ edit: "Sửa",
1170
+ enable: "Bật",
1171
+ disable: "Tắt",
1172
+ delete: "Xóa",
1173
+ tools: "Công cụ",
1174
+ collapse: "Thu gọn",
1175
+ noTools: "(không có công cụ nào được đăng ký — máy chủ chưa kết nối hoặc chưa đồng bộ)",
1176
+ statusDisabled: "Đã tắt",
1177
+ statusConnecting: "Đang kết nối…",
1178
+ statusDisconnected: "Chưa kết nối",
1179
+ toolCount: "{count} công cụ"
1180
+ },
1181
+ th: {
1182
+ heading: "เซิร์ฟเวอร์ MCP",
1183
+ introBefore: "จัดการการเชื่อมต่อเซิร์ฟเวอร์ MCP เซิร์ฟเวอร์แต่ละตัวถูกเมานต์โดย",
1184
+ introMid: "อย่างเป็นทางการ และเครื่องมือลงทะเบียนภายใต้",
1185
+ introAfter: "การกำหนดค่าถูกเขียนลงใน profile patch และนำไปใช้ทันทีผ่าน HMR",
1186
+ envWarning: "⚠ env / headers ถูกจัดเก็บเป็นข้อความธรรมดาใน cordis.patch.yml ของโปรไฟล์ (รูปแบบเดียวกับตัวอย่างทางการ) อย่าใส่ความลับระยะยาวที่นี่ การปิดใช้งานเซิร์ฟเวอร์ยังคงเก็บการกำหนดค่าไว้ loader จะข้ามการเมานต์และเครื่องมือจะไม่ลงทะเบียน (มองไม่เห็นโดยโมเดล)",
1187
+ loading: "กำลังโหลด…",
1188
+ empty: "ยังไม่มีเซิร์ฟเวอร์ MCP คลิก \"เพิ่มเซิร์ฟเวอร์\" เพื่อสร้าง",
1189
+ addServer: "+ เพิ่มเซิร์ฟเวอร์",
1190
+ addTitle: "เพิ่มเซิร์ฟเวอร์",
1191
+ transport: "โปรโตคอลการส่ง",
1192
+ serverNameLabel: "serverName (เนมสเปซของเครื่องมือ ต้องไม่ซ้ำกัน)",
1193
+ serverNamePlaceholder: "github",
1194
+ commandLabel: "command",
1195
+ commandPlaceholder: "npx",
1196
+ argsLabel: "args (หนึ่งรายการต่อบรรทัด)",
1197
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1198
+ envLabel: "env (หนึ่ง key=value ต่อบรรทัด จัดเก็บเป็นข้อความธรรมดา)",
1199
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1200
+ cwdLabel: "cwd (ไม่บังคับ)",
1201
+ urlLabel: "url",
1202
+ urlPlaceholder: "https://mcp.example.com/mcp",
1203
+ headersLabel: "headers (หนึ่ง key=value ต่อบรรทัด จัดเก็บเป็นข้อความธรรมดา)",
1204
+ headersPlaceholder: "Authorization=Bearer xxx",
1205
+ timeoutLabel: "toolCallTimeoutMs",
1206
+ cancel: "ยกเลิก",
1207
+ save: "บันทึก",
1208
+ add: "เพิ่ม",
1209
+ edit: "แก้ไข",
1210
+ enable: "เปิดใช้งาน",
1211
+ disable: "ปิดใช้งาน",
1212
+ delete: "ลบ",
1213
+ tools: "เครื่องมือ",
1214
+ collapse: "ย่อ",
1215
+ noTools: "(ไม่มีเครื่องมือที่ลงทะเบียน — เซิร์ฟเวอร์ไม่ได้เชื่อมต่อหรือยังไม่ซิงค์)",
1216
+ statusDisabled: "ปิดใช้งาน",
1217
+ statusConnecting: "กำลังเชื่อมต่อ…",
1218
+ statusDisconnected: "ยังไม่เชื่อมต่อ",
1219
+ toolCount: "{count} เครื่องมือ"
1220
+ },
1221
+ ru: {
1222
+ heading: "Серверы MCP",
1223
+ introBefore: "Управление подключениями к серверам MCP. Каждый сервер монтируется официальным",
1224
+ introMid: "а инструменты регистрируются с префиксом",
1225
+ introAfter: "Конфигурация записывается в patch профиля и применяется мгновенно через HMR.",
1226
+ envWarning: "⚠ env / headers хранятся в открытом виде в profile cordis.patch.yml (как в официальных примерах). Не помещайте сюда долгоживущие секреты. Отключение сервера сохраняет его конфигурацию; загрузчик пропускает монтирование, и инструменты не регистрируются (невидимы для модели).",
1227
+ loading: "Загрузка…",
1228
+ empty: "Серверов MCP пока нет. Нажмите «Добавить сервер», чтобы создать.",
1229
+ addServer: "+ Добавить сервер",
1230
+ addTitle: "Добавить сервер",
1231
+ transport: "Транспорт",
1232
+ serverNameLabel: "serverName (пространство имён инструментов, должно быть уникальным)",
1233
+ serverNamePlaceholder: "github",
1234
+ commandLabel: "command",
1235
+ commandPlaceholder: "npx",
1236
+ argsLabel: "args (по одному в строке)",
1237
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1238
+ envLabel: "env (по одному key=value в строке, хранится в открытом виде)",
1239
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1240
+ cwdLabel: "cwd (необязательно)",
1241
+ urlLabel: "url",
1242
+ urlPlaceholder: "https://mcp.example.com/mcp",
1243
+ headersLabel: "headers (по одному key=value в строке, хранится в открытом виде)",
1244
+ headersPlaceholder: "Authorization=Bearer xxx",
1245
+ timeoutLabel: "toolCallTimeoutMs",
1246
+ cancel: "Отмена",
1247
+ save: "Сохранить",
1248
+ add: "Добавить",
1249
+ edit: "Изменить",
1250
+ enable: "Включить",
1251
+ disable: "Отключить",
1252
+ delete: "Удалить",
1253
+ tools: "Инструменты",
1254
+ collapse: "Свернуть",
1255
+ noTools: "(нет зарегистрированных инструментов — сервер не подключён или не синхронизирован)",
1256
+ statusDisabled: "Отключено",
1257
+ statusConnecting: "Подключение…",
1258
+ statusDisconnected: "Не подключено",
1259
+ toolCount: "{count} инструментов"
1260
+ },
1261
+ it: {
1262
+ heading: "Server MCP",
1263
+ introBefore: "Gestisci le connessioni ai server MCP. Ogni server è montato dall’",
1264
+ introMid: "ufficiale, e gli strumenti sono registrati sotto",
1265
+ introAfter: "La configurazione viene scritta nel patch del profilo e applicata al volo tramite HMR.",
1266
+ envWarning: "⚠ env / headers sono memorizzati in chiaro nel cordis.patch.yml del profilo (come negli esempi ufficiali). Non inserire segreti a lungo termine. Disabilitare un server conserva la sua configurazione; il loader salta il montaggio e gli strumenti restano non registrati (invisibili al modello).",
1267
+ loading: "Caricamento…",
1268
+ empty: "Nessun server MCP per ora. Fai clic su \"Aggiungi server\" per crearne uno.",
1269
+ addServer: "+ Aggiungi server",
1270
+ addTitle: "Aggiungi server",
1271
+ transport: "Trasporto",
1272
+ serverNameLabel: "serverName (namespace strumenti, deve essere univoco)",
1273
+ serverNamePlaceholder: "github",
1274
+ commandLabel: "command",
1275
+ commandPlaceholder: "npx",
1276
+ argsLabel: "args (uno per riga)",
1277
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1278
+ envLabel: "env (un key=value per riga, memorizzato in chiaro)",
1279
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1280
+ cwdLabel: "cwd (facoltativo)",
1281
+ urlLabel: "url",
1282
+ urlPlaceholder: "https://mcp.example.com/mcp",
1283
+ headersLabel: "headers (un key=value per riga, memorizzato in chiaro)",
1284
+ headersPlaceholder: "Authorization=Bearer xxx",
1285
+ timeoutLabel: "toolCallTimeoutMs",
1286
+ cancel: "Annulla",
1287
+ save: "Salva",
1288
+ add: "Aggiungi",
1289
+ edit: "Modifica",
1290
+ enable: "Abilita",
1291
+ disable: "Disabilita",
1292
+ delete: "Elimina",
1293
+ tools: "Strumenti",
1294
+ collapse: "Comprimi",
1295
+ noTools: "(nessuno strumento registrato — server non connesso o non sincronizzato)",
1296
+ statusDisabled: "Disabilitato",
1297
+ statusConnecting: "Connessione…",
1298
+ statusDisconnected: "Non connesso",
1299
+ toolCount: "{count} strumenti"
1300
+ },
1301
+ nl: {
1302
+ heading: "MCP-servers",
1303
+ introBefore: "Beheer MCP-serververbindingen. Elke server wordt gemount door de officiële",
1304
+ introMid: "en tools worden geregistreerd onder",
1305
+ introAfter: "De configuratie wordt naar de profile-patch geschreven en direct toegepast via HMR.",
1306
+ envWarning: "⚠ env / headers worden als platte tekst opgeslagen in profile cordis.patch.yml (zelfde vorm als de officiële voorbeelden). Zet hier geen langdurige geheimen neer. Een server uitschakelen behoudt de configuratie; de loader slaat het mounten over en tools blijven ongeregistreerd (onzichtbaar voor het model).",
1307
+ loading: "Laden…",
1308
+ empty: "Nog geen MCP-servers. Klik op \"Server toevoegen\" om er een te maken.",
1309
+ addServer: "+ Server toevoegen",
1310
+ addTitle: "Server toevoegen",
1311
+ transport: "Transport",
1312
+ serverNameLabel: "serverName (tool-naamruimte, moet uniek zijn)",
1313
+ serverNamePlaceholder: "github",
1314
+ commandLabel: "command",
1315
+ commandPlaceholder: "npx",
1316
+ argsLabel: "args (één per regel)",
1317
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1318
+ envLabel: "env (één key=value per regel, als platte tekst opgeslagen)",
1319
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1320
+ cwdLabel: "cwd (optioneel)",
1321
+ urlLabel: "url",
1322
+ urlPlaceholder: "https://mcp.example.com/mcp",
1323
+ headersLabel: "headers (één key=value per regel, als platte tekst opgeslagen)",
1324
+ headersPlaceholder: "Authorization=Bearer xxx",
1325
+ timeoutLabel: "toolCallTimeoutMs",
1326
+ cancel: "Annuleren",
1327
+ save: "Opslaan",
1328
+ add: "Toevoegen",
1329
+ edit: "Bewerken",
1330
+ enable: "Inschakelen",
1331
+ disable: "Uitschakelen",
1332
+ delete: "Verwijderen",
1333
+ tools: "Tools",
1334
+ collapse: "Inklappen",
1335
+ noTools: "(geen geregistreerde tools — server niet verbonden of niet gesynchroniseerd)",
1336
+ statusDisabled: "Uitgeschakeld",
1337
+ statusConnecting: "Verbinden…",
1338
+ statusDisconnected: "Niet verbonden",
1339
+ toolCount: "{count} tools"
1340
+ },
1341
+ sv: {
1342
+ heading: "MCP-servrar",
1343
+ introBefore: "Hantera MCP-serveranslutningar. Varje server monteras av den officiella",
1344
+ introMid: "och verktyg registreras under",
1345
+ introAfter: "Konfigurationen skrivs till profilpatchen och tillämpas direkt via HMR.",
1346
+ envWarning: "⚠ env / headers lagras i klartext i profilens cordis.patch.yml (samma form som de officiella exemplen). Lägg inte långlivade hemligheter här. Att inaktivera en server behåller konfigurationen; lastaren hoppar över monteringen och verktygen förblir oregistrerade (osynliga för modellen).",
1347
+ loading: "Läser in…",
1348
+ empty: "Inga MCP-servrar ännu. Klicka på \"Lägg till server\" för att skapa en.",
1349
+ addServer: "+ Lägg till server",
1350
+ addTitle: "Lägg till server",
1351
+ transport: "Transport",
1352
+ serverNameLabel: "serverName (verktygsnamnrymd, måste vara unik)",
1353
+ serverNamePlaceholder: "github",
1354
+ commandLabel: "command",
1355
+ commandPlaceholder: "npx",
1356
+ argsLabel: "args (en per rad)",
1357
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1358
+ envLabel: "env (en key=value per rad, lagrad i klartext)",
1359
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1360
+ cwdLabel: "cwd (valfritt)",
1361
+ urlLabel: "url",
1362
+ urlPlaceholder: "https://mcp.example.com/mcp",
1363
+ headersLabel: "headers (en key=value per rad, lagrad i klartext)",
1364
+ headersPlaceholder: "Authorization=Bearer xxx",
1365
+ timeoutLabel: "toolCallTimeoutMs",
1366
+ cancel: "Avbryt",
1367
+ save: "Spara",
1368
+ add: "Lägg till",
1369
+ edit: "Redigera",
1370
+ enable: "Aktivera",
1371
+ disable: "Inaktivera",
1372
+ delete: "Ta bort",
1373
+ tools: "Verktyg",
1374
+ collapse: "Fäll ihop",
1375
+ noTools: "(inga registrerade verktyg — servern inte ansluten eller inte synkroniserad)",
1376
+ statusDisabled: "Inaktiverad",
1377
+ statusConnecting: "Ansluter…",
1378
+ statusDisconnected: "Inte ansluten",
1379
+ toolCount: "{count} verktyg"
1380
+ },
1381
+ pl: {
1382
+ heading: "Serwery MCP",
1383
+ introBefore: "Zarządzaj połączeniami serwerów MCP. Każdy serwer jest montowany przez oficjalny",
1384
+ introMid: "a narzędzia są rejestrowane pod",
1385
+ introAfter: "Konfiguracja jest zapisywana do poprawki profilu i stosowana na żywo przez HMR.",
1386
+ envWarning: "⚠ env / headers są przechowywane w postaci zwykłego tekstu w pliku cordis.patch.yml profilu (tak jak w oficjalnych przykładach). Nie umieszczaj tu długoterminowych sekretów. Wyłączenie serwera zachowuje jego konfigurację; loader pomija montowanie, a narzędzia pozostają niezarejestrowane (niewidoczne dla modelu).",
1387
+ loading: "Wczytywanie…",
1388
+ empty: "Nie ma jeszcze serwerów MCP. Kliknij „Dodaj serwer”, aby utworzyć.",
1389
+ addServer: "+ Dodaj serwer",
1390
+ addTitle: "Dodaj serwer",
1391
+ transport: "Transport",
1392
+ serverNameLabel: "serverName (przestrzeń nazw narzędzi, musi być unikalna)",
1393
+ serverNamePlaceholder: "github",
1394
+ commandLabel: "command",
1395
+ commandPlaceholder: "npx",
1396
+ argsLabel: "args (jedno w wierszu)",
1397
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1398
+ envLabel: "env (jedno key=value w wierszu, przechowywane w postaci zwykłego tekstu)",
1399
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1400
+ cwdLabel: "cwd (opcjonalnie)",
1401
+ urlLabel: "url",
1402
+ urlPlaceholder: "https://mcp.example.com/mcp",
1403
+ headersLabel: "headers (jedno key=value w wierszu, przechowywane w postaci zwykłego tekstu)",
1404
+ headersPlaceholder: "Authorization=Bearer xxx",
1405
+ timeoutLabel: "toolCallTimeoutMs",
1406
+ cancel: "Anuluj",
1407
+ save: "Zapisz",
1408
+ add: "Dodaj",
1409
+ edit: "Edytuj",
1410
+ enable: "Włącz",
1411
+ disable: "Wyłącz",
1412
+ delete: "Usuń",
1413
+ tools: "Narzędzia",
1414
+ collapse: "Zwiń",
1415
+ noTools: "(brak zarejestrowanych narzędzi — serwer niepołączony lub niezsynchronizowany)",
1416
+ statusDisabled: "Wyłączony",
1417
+ statusConnecting: "Łączenie…",
1418
+ statusDisconnected: "Niepołączony",
1419
+ toolCount: "{count} narzędzi"
1420
+ },
1421
+ "zh-HK": {
1422
+ heading: "MCP 伺服器",
1423
+ introBefore: "管理 MCP 伺服器連線。每台伺服器由官方",
1424
+ introMid: "掛載,工具以",
1425
+ introAfter: "命名註冊。設定寫入 profile patch,HMR 即時生效。",
1426
+ envWarning: "⚠ env / headers 以明文存入 profile cordis.patch.yml(與官方範例同形態)。勿放長期密鑰。停用伺服器不會刪除設定,loader 跳過掛載,工具不會註冊(模型不可見)。",
1427
+ loading: "載入中…",
1428
+ empty: "尚無 MCP 伺服器。點擊「新增」新增一個。",
1429
+ addServer: "+ 新增伺服器",
1430
+ addTitle: "新增伺服器",
1431
+ transport: "傳輸方式",
1432
+ serverNameLabel: "serverName(工具命名空間,唯一)",
1433
+ serverNamePlaceholder: "github",
1434
+ commandLabel: "command",
1435
+ commandPlaceholder: "npx",
1436
+ argsLabel: "args(每行一個)",
1437
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1438
+ envLabel: "env(每行 key=value,明文儲存)",
1439
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1440
+ cwdLabel: "cwd(可空)",
1441
+ urlLabel: "url",
1442
+ urlPlaceholder: "https://mcp.example.com/mcp",
1443
+ headersLabel: "headers(每行 key=value,明文儲存)",
1444
+ headersPlaceholder: "Authorization=Bearer xxx",
1445
+ timeoutLabel: "toolCallTimeoutMs",
1446
+ cancel: "取消",
1447
+ save: "儲存",
1448
+ add: "新增",
1449
+ edit: "編輯",
1450
+ enable: "啟用",
1451
+ disable: "停用",
1452
+ delete: "刪除",
1453
+ tools: "工具",
1454
+ collapse: "收起",
1455
+ noTools: "(無已註冊工具——伺服器未連線或未同步)",
1456
+ statusDisabled: "已停用",
1457
+ statusConnecting: "連線中…",
1458
+ statusDisconnected: "未連線",
1459
+ toolCount: "{count} 個工具"
1460
+ },
1461
+ "zh-TW": {
1462
+ heading: "MCP 伺服器",
1463
+ introBefore: "管理 MCP 伺服器連線。每台伺服器由官方",
1464
+ introMid: "掛載,工具以",
1465
+ introAfter: "命名註冊。設定寫入 profile patch,HMR 即時生效。",
1466
+ envWarning: "⚠ env / headers 以明文存入 profile cordis.patch.yml(與官方範例同形態)。請勿放置長期密鑰。停用伺服器不會刪除設定,loader 會跳過掛載,工具不會註冊(模型看不到)。",
1467
+ loading: "載入中…",
1468
+ empty: "尚無 MCP 伺服器。點選「新增」建立一個。",
1469
+ addServer: "+ 新增伺服器",
1470
+ addTitle: "新增伺服器",
1471
+ transport: "傳輸方式",
1472
+ serverNameLabel: "serverName(工具命名空間,唯一)",
1473
+ serverNamePlaceholder: "github",
1474
+ commandLabel: "command",
1475
+ commandPlaceholder: "npx",
1476
+ argsLabel: "args(每行一個)",
1477
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1478
+ envLabel: "env(每行 key=value,明文儲存)",
1479
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1480
+ cwdLabel: "cwd(可留空)",
1481
+ urlLabel: "url",
1482
+ urlPlaceholder: "https://mcp.example.com/mcp",
1483
+ headersLabel: "headers(每行 key=value,明文儲存)",
1484
+ headersPlaceholder: "Authorization=Bearer xxx",
1485
+ timeoutLabel: "toolCallTimeoutMs",
1486
+ cancel: "取消",
1487
+ save: "儲存",
1488
+ add: "新增",
1489
+ edit: "編輯",
1490
+ enable: "啟用",
1491
+ disable: "停用",
1492
+ delete: "刪除",
1493
+ tools: "工具",
1494
+ collapse: "收起",
1495
+ noTools: "(無已註冊工具——伺服器未連線或未同步)",
1496
+ statusDisabled: "已停用",
1497
+ statusConnecting: "連線中…",
1498
+ statusDisconnected: "未連線",
1499
+ toolCount: "{count} 個工具"
1500
+ },
1501
+ "zh-MO": {
1502
+ heading: "MCP 伺服器",
1503
+ introBefore: "管理 MCP 伺服器連線。每台伺服器由官方",
1504
+ introMid: "掛載,工具以",
1505
+ introAfter: "命名註冊。設定寫入 profile patch,HMR 即時生效。",
1506
+ envWarning: "⚠ env / headers 以明文存入 profile cordis.patch.yml(與官方範例同形態)。勿放置長期密鑰。停用伺服器不會刪除設定,loader 跳過掛載,工具不註冊(模型不可見)。",
1507
+ loading: "載入中…",
1508
+ empty: "尚無 MCP 伺服器。點擊「新增」新增一個。",
1509
+ addServer: "+ 新增伺服器",
1510
+ addTitle: "新增伺服器",
1511
+ transport: "傳輸方式",
1512
+ serverNameLabel: "serverName(工具命名空間,唯一)",
1513
+ serverNamePlaceholder: "github",
1514
+ commandLabel: "command",
1515
+ commandPlaceholder: "npx",
1516
+ argsLabel: "args(每行一個)",
1517
+ argsPlaceholder: "-y\n@modelcontextprotocol/server-github",
1518
+ envLabel: "env(每行 key=value,明文儲存)",
1519
+ envPlaceholder: "GITHUB_TOKEN=ghp_xxx",
1520
+ cwdLabel: "cwd(可空)",
1521
+ urlLabel: "url",
1522
+ urlPlaceholder: "https://mcp.example.com/mcp",
1523
+ headersLabel: "headers(每行 key=value,明文儲存)",
1524
+ headersPlaceholder: "Authorization=Bearer xxx",
1525
+ timeoutLabel: "toolCallTimeoutMs",
1526
+ cancel: "取消",
1527
+ save: "儲存",
1528
+ add: "新增",
1529
+ edit: "編輯",
1530
+ enable: "啟用",
1531
+ disable: "停用",
1532
+ delete: "刪除",
1533
+ tools: "工具",
1534
+ collapse: "收起",
1535
+ noTools: "(無已註冊工具——伺服器未連線或未同步)",
1536
+ statusDisabled: "已停用",
1537
+ statusConnecting: "連線中…",
1538
+ statusDisconnected: "未連線",
1539
+ toolCount: "{count} 個工具"
1540
+ }
1541
+ };
1542
+ //#endregion
602
1543
  //#region src/client/index.ts
603
1544
  /** Cordis 插件名。 */
604
1545
  const name = "dsh-mcp-manager-client";
605
- /** 需要 slots(settings.section 插槽)。 */
606
- const inject = ["slots"];
1546
+ /** 需要 slots(settings.section 插槽)+ locale(面板文案 zh/en)。 */
1547
+ const inject = ["slots", "locale"];
607
1548
  /** 注册设置页「MCP」面板。 */
608
1549
  function apply(ctx) {
1550
+ ctx.effect(() => ctx.locale.register(NS, {
1551
+ zh,
1552
+ en
1553
+ }), "dsh-plugin-mcp-manager: own copy namespace");
609
1554
  ctx.slots.inject("settings.section", () => ctx.slots.register({
610
1555
  name: "settings.section",
611
1556
  id: "dsh-mcp-manager",
612
1557
  order: 61,
613
1558
  label: () => "MCP",
1559
+ locale: NS,
614
1560
  inject: () => ({})
615
1561
  }, McpPanel));
1562
+ ctx.effect(() => {
1563
+ let dispose;
1564
+ const sync = () => {
1565
+ dispose?.();
1566
+ dispose = void 0;
1567
+ const store = ctx.get("betterLocale");
1568
+ if (store !== void 0) dispose = store.register(NS, dicts);
1569
+ };
1570
+ sync();
1571
+ const unsubscribe = ctx.locale.subscribe(sync);
1572
+ return () => {
1573
+ unsubscribe();
1574
+ dispose?.();
1575
+ };
1576
+ }, "dsh-plugin-mcp-manager: better-locale override dicts");
616
1577
  }
617
1578
  //#endregion
618
1579
  exports.apply = apply;