@xxxyz/dsh-mcp-manager 2.2.2 → 2.2.4

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.
package/README.md CHANGED
@@ -17,11 +17,12 @@
17
17
  [![GitHub](https://img.shields.io/badge/GitHub-xxxyz%2FDeepSeekHarness--MCP--Manager-181717?logo=github)](https://github.com/xxxyz/DeepSeekHarness-MCP-Manager)
18
18
  [![dsh.market](https://img.shields.io/badge/dsh.market-%E2%9C%93-3fb950)](https://dsh.market)
19
19
  [![awesome-dsh-plugin](https://img.shields.io/badge/awesome--dsh--plugin-%E5%B7%B2%E6%94%B6%E5%BD%95-3fb950)](https://awesome-dsh-plugin.com)
20
+ [![dsh-suite](https://img.shields.io/badge/featured%20on-dsh--suite-4d6bfe)](https://whyihaveyou.github.io/dsh-suite/)
20
21
 
21
22
  </div>
22
23
 
23
24
  <div align="center">
24
- 🛒 已收录于 <a href="https://dsh.market"><b>dsh.market</b></a> <a href="https://awesome-dsh-plugin.com"><b>awesome-dsh-plugin.com</b></a> 官方插件列表(<a href="https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/2078"><b>PR #2078</b></a> 已合并)
25
+ 🛒 已收录于 <a href="https://dsh.market"><b>dsh.market</b></a> · <a href="https://awesome-dsh-plugin.com"><b>awesome-dsh-plugin.com</b></a> · <a href="https://whyihaveyou.github.io/dsh-suite/"><b>dsh-suite</b></a>
25
26
  </div>
26
27
 
27
28
  <div align="center">
package/README_EN.md CHANGED
@@ -18,11 +18,12 @@
18
18
  [![GitHub](https://img.shields.io/badge/GitHub-xxxyz%2FDeepSeekHarness--MCP--Manager-181717?logo=github)](https://github.com/xxxyz/DeepSeekHarness-MCP-Manager)
19
19
  [![dsh.market](https://img.shields.io/badge/dsh.market-%E2%9C%93-3fb950)](https://dsh.market)
20
20
  [![awesome-dsh-plugin](https://img.shields.io/badge/awesome--dsh--plugin-listed-3fb950)](https://awesome-dsh-plugin.com)
21
+ [![dsh-suite](https://img.shields.io/badge/featured%20on-dsh--suite-4d6bfe)](https://whyihaveyou.github.io/dsh-suite/)
21
22
 
22
23
  </div>
23
24
 
24
25
  <div align="center">
25
- 🛒 Listed on <a href="https://dsh.market"><b>dsh.market</b></a> and the <a href="https://awesome-dsh-plugin.com"><b>awesome-dsh-plugin.com</b></a> official plugin list (<a href="https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/2078"><b>PR #2078</b></a> merged)
26
+ 🛒 Listed on <a href="https://dsh.market"><b>dsh.market</b></a> · <a href="https://awesome-dsh-plugin.com"><b>awesome-dsh-plugin.com</b></a> · <a href="https://whyihaveyou.github.io/dsh-suite/"><b>dsh-suite</b></a>
26
27
  </div>
27
28
 
28
29
  <div align="center">
package/lib/client.js CHANGED
@@ -17,25 +17,25 @@ const factory = (require) => {
17
17
  '.mcpm-msg.err{background:rgba(248,81,73,.15);border:1px solid rgba(248,81,73,.4)}' +
18
18
  '.mcpm-msg.info{background:rgba(88,166,255,.15);border:1px solid rgba(88,166,255,.5)}' +
19
19
  '.mcpm-path{font-family:monospace;font-size:11px;opacity:.7;word-break:break-all}' +
20
- '.mcpm-btn{font-size:12px;padding:3px 10px;border-radius:5px;border:1px solid rgba(128,128,128,.5);background:transparent;color:inherit;cursor:pointer;white-space:nowrap}' +
20
+ '.mcpm-btn{font-size:12px;padding:3px 10px;border-radius:5px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));background:transparent;color:inherit;cursor:pointer;white-space:nowrap}' +
21
21
  '.mcpm-btn:disabled{opacity:.5;cursor:default}' +
22
22
  '.mcpm-btn.primary{border-color:rgba(88,166,255,.7)}' +
23
23
  '.mcpm-btn.danger{border-color:rgba(248,81,73,.7)}' +
24
- '.mcpm-backup{display:flex;flex-direction:column;gap:8px;border:1px dashed rgba(128,128,128,.45);border-radius:8px;padding:10px 12px}' +
24
+ '.mcpm-backup{display:flex;flex-direction:column;gap:8px;border:1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,.45));border-radius:8px;padding:10px 12px}' +
25
25
  '.mcpm-backup .row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}' +
26
- '.mcpm-json{width:100%;box-sizing:border-box;font-family:monospace;font-size:11px;min-height:70px;background:transparent;color:inherit;border:1px solid rgba(128,128,128,.4);border-radius:5px;padding:6px;white-space:pre;overflow:auto}' +
26
+ '.mcpm-json{width:100%;box-sizing:border-box;font-family:monospace;font-size:11px;min-height:70px;background:transparent;color:inherit;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.4));border-radius:5px;padding:6px;white-space:pre;overflow:auto}' +
27
27
  '.mcpm-report{font-family:monospace;font-size:11px;opacity:.85;word-break:break-all}' +
28
28
  '.mcpm-warn{font-size:11px;color:rgba(248,81,73,.95)}' +
29
- '.mcpm-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 12px;border:1px solid rgba(128,128,128,.35);border-radius:8px;padding:12px}' +
29
+ '.mcpm-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 12px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));border-radius:8px;padding:12px}' +
30
30
  '.mcpm-form h3{margin:0;grid-column:1/-1;font-size:13px}' +
31
31
  '.mcpm-form label{display:flex;flex-direction:column;gap:3px;font-size:12px}' +
32
32
  '.mcpm-form .full{grid-column:1/-1}' +
33
- '.mcpm-form input,.mcpm-form select,.mcpm-form textarea{font-size:12px;padding:4px 6px;border-radius:5px;border:1px solid rgba(128,128,128,.5);background:transparent;color:inherit}' +
33
+ '.mcpm-form input,.mcpm-form select,.mcpm-form textarea{font-size:12px;padding:4px 6px;border-radius:5px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));background:transparent;color:inherit}' +
34
34
  '.mcpm-form textarea{font-family:monospace;resize:vertical;min-height:44px}' +
35
- '.mcpm-row{border:1px solid rgba(128,128,128,.35);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:8px}' +
35
+ '.mcpm-row{border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:8px}' +
36
36
  '.mcpm-row-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}' +
37
37
  '.mcpm-name{font-weight:600}' +
38
- '.mcpm-chip{font-size:11px;padding:1px 8px;border-radius:999px;border:1px solid rgba(128,128,128,.5);white-space:nowrap}' +
38
+ '.mcpm-chip{font-size:11px;padding:1px 8px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));white-space:nowrap}' +
39
39
  '.mcpm-chip.on{background:rgba(46,160,67,.18);border-color:rgba(46,160,67,.55)}' +
40
40
  '.mcpm-chip.off{background:rgba(128,128,128,.15)}' +
41
41
  '.mcpm-chip.live{background:rgba(88,166,255,.15);border-color:rgba(88,166,255,.5)}' +
@@ -43,17 +43,27 @@ const factory = (require) => {
43
43
  '.mcpm-chip.warn{background:rgba(219,154,4,.18);border-color:rgba(219,154,4,.6)}' +
44
44
  '.mcpm-row-actions{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}' +
45
45
  '.mcpm-detail{font-family:monospace;font-size:11px;opacity:.75;word-break:break-all}' +
46
- '.mcpm-mask{position:fixed;inset:0;background:transparent;display:flex;align-items:center;justify-content:center;z-index:99999}' +
47
- '.mcpm-dialog{background:color-mix(in srgb, currentColor 8%, transparent);backdrop-filter:blur(14px) saturate(1.2);border:1px solid rgba(128,128,128,.5);border-radius:10px;padding:16px 18px;min-width:300px;max-width:440px;box-shadow:0 10px 34px rgba(0,0,0,.35);color:inherit}' +
46
+ '.mcpm-mask{position:fixed;inset:0;background:var(--dsw-alias-bg-mask-drop);display:flex;align-items:center;justify-content:center;z-index:99999}' +
47
+ '.mcpm-dialog{background:var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-base, #fff));border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));border-radius:10px;padding:16px 18px;min-width:300px;max-width:440px;box-shadow:0 10px 34px rgba(0,0,0,.35);color:inherit}' +
48
48
  '.mcpm-dialog-title{font-size:14px;font-weight:600;margin-bottom:8px}' +
49
49
  '.mcpm-dialog-body{font-size:12px;opacity:.88;line-height:1.7;margin-bottom:16px;word-break:break-all}' +
50
50
  '.mcpm-dialog-actions{display:flex;justify-content:flex-end;gap:8px}' +
51
- '.skm-search{font-size:12px;padding:5px 8px;border-radius:6px;border:1px solid rgba(128,128,128,.5);background:transparent;color:inherit;width:100%;box-sizing:border-box}' +
52
- '.skm-group-title{font-size:12px;font-weight:600;opacity:.85;margin-top:4px;padding-bottom:2px;border-bottom:1px solid rgba(128,128,128,.25)}' +
51
+ '.skm-search{font-size:12px;padding:5px 8px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));background:transparent;color:inherit;width:100%;box-sizing:border-box}' +
52
+ '.skm-group-title{font-size:12px;font-weight:600;opacity:.85;margin-top:4px;padding-bottom:2px;border-bottom:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.25))}' +
53
53
  '.skm-provider-title{font-size:12px;font-weight:600;cursor:pointer;user-select:none;margin-top:4px;opacity:.9}' +
54
54
  '.mcpm-version{margin-left:8px;font-size:11px;font-weight:500;opacity:.55;letter-spacing:.3px;vertical-align:middle}' +
55
55
  '.mcpm-token{display:flex;align-items:center;gap:8px;font-size:12px;opacity:.85}' +
56
- '.mcpm-token input{font-size:12px;padding:3px 6px;border-radius:5px;border:1px solid rgba(128,128,128,.5);background:transparent;color:inherit;flex:1;max-width:260px}'
56
+ '.mcpm-token input{font-size:12px;padding:3px 6px;border-radius:5px;border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.5));background:transparent;color:inherit;flex:1;max-width:260px}' +
57
+ '.mcpm-dialog-tools{max-width:560px;max-height:70vh;display:flex;flex-direction:column}' +
58
+ '.mcpm-dialog-tools .mcpm-dialog-body{flex:1;min-height:0;overflow:auto;margin-bottom:12px}' +
59
+ '.mcpm-tools-list{display:flex;flex-direction:column;gap:8px;padding-right:4px}' +
60
+ '.mcpm-tool{border:1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.3));border-radius:6px;padding:8px 10px}' +
61
+ '.mcpm-tool-name{font-family:monospace;font-size:12px;font-weight:600;word-break:break-all}' +
62
+ '.mcpm-tool-params{display:flex;flex-direction:column;gap:2px;margin-top:6px;padding-top:6px;border-top:1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,.3))}' +
63
+ '.mcpm-tool-param{display:flex;gap:8px;font-size:11px;align-items:baseline}' +
64
+ '.mcpm-tool-param-key{font-family:monospace;font-weight:600;min-width:80px;word-break:break-all}' +
65
+ '.mcpm-tool-param-type{opacity:.6;min-width:60px}' +
66
+ '.mcpm-tool-param-desc{opacity:.8;flex:1;word-break:break-all}'
57
67
 
58
68
  function ensureCss() {
59
69
  if (typeof document === 'undefined') return
@@ -136,6 +146,9 @@ const factory = (require) => {
136
146
  const [backup, setBackup] = React.useState(null)
137
147
  const [importText, setImportText] = React.useState('')
138
148
  const [confirmRow, setConfirmRow] = React.useState(null)
149
+ const [toolPreview, setToolPreview] = React.useState(null)
150
+ const [toolPreviewErr, setToolPreviewErr] = React.useState(null)
151
+ const [toolPreviewBusy, setToolPreviewBusy] = React.useState(false)
139
152
 
140
153
  const refresh = () => {
141
154
  apiCall('mcpm-list', {}).then((res) => {
@@ -221,6 +234,15 @@ const factory = (require) => {
221
234
  setConfirmRow(null)
222
235
  if (row) run('mcpm-remove', { id: row.id, level: row.level }, row.id + ':remove')
223
236
  }
237
+ const openToolPreview = (row) => {
238
+ setToolPreviewErr(null)
239
+ setToolPreviewBusy(true)
240
+ setToolPreview({ serverName: row.serverName, tools: [] })
241
+ apiCall('mcpm-tools', { serverName: row.serverName }).then((res) => {
242
+ if (res && res.ok) { setToolPreview({ serverName: row.serverName, tools: (res.tools) || [] }) }
243
+ else setToolPreviewErr((res && res.error) || '加载工具失败')
244
+ }).catch((e) => setToolPreviewErr(String((e && e.message) || e))).then(() => setToolPreviewBusy(false))
245
+ }
224
246
 
225
247
  const rows = state.rows || []
226
248
  const maskKv = (obj) => {
@@ -321,6 +343,7 @@ const factory = (require) => {
321
343
  (row.headers ? 'headers: ' + maskKv(row.headers) + ' ' : '') + (row.env ? 'env: ' + Object.keys(row.env).map((k) => k + ': ****').join(' ') : '')),
322
344
  React.createElement('div', { className: 'mcpm-row-actions' },
323
345
  row.level !== 'loader' && React.createElement('button', { className: 'mcpm-btn', disabled: rowsLocked, onClick: () => openEdit(row) }, '编辑'),
346
+ typeof row.toolCount === 'number' && row.toolCount > 0 && React.createElement('button', { className: 'mcpm-btn', disabled: toolPreviewBusy, onClick: () => openToolPreview(row) }, '工具 (' + row.toolCount + ')'),
324
347
  React.createElement('button', { className: 'mcpm-btn', disabled: rowsLocked, onClick: () => toggleRow(row) }, row.disabled ? '启用' : '禁用'),
325
348
  React.createElement('button', { className: 'mcpm-btn', disabled: rowsLocked, onClick: () => restartRow(row) }, '重启'),
326
349
  row.level !== 'loader' && React.createElement('button', { className: 'mcpm-btn danger', disabled: rowsLocked, onClick: () => removeRow(row) }, '删除')))),
@@ -331,7 +354,32 @@ const factory = (require) => {
331
354
  '确定要删除“' + confirmRow.serverName + '”吗?\n删除后该服务的配置将从补丁文件中移除,相关工具立即下线,此操作不可撤销。'),
332
355
  React.createElement('div', { className: 'mcpm-dialog-actions' },
333
356
  React.createElement('button', { className: 'mcpm-btn', onClick: () => setConfirmRow(null) }, '取消'),
334
- React.createElement('button', { className: 'mcpm-btn danger', onClick: confirmDelete }, '删除'))))
357
+ React.createElement('button', { className: 'mcpm-btn danger', onClick: confirmDelete }, '删除')))),
358
+ toolPreview && React.createElement('div', { className: 'mcpm-mask', onClick: () => setToolPreview(null) },
359
+ React.createElement('div', { className: 'mcpm-dialog mcpm-dialog-tools', onClick: (ev) => ev.stopPropagation() },
360
+ React.createElement('div', { className: 'mcpm-dialog-title' }, '工具预览:' + toolPreview.serverName + '(' + (toolPreviewBusy ? '加载中…' : (toolPreview.tools || []).length + ' 个工具') + ')'),
361
+ React.createElement('div', { className: 'mcpm-dialog-body' },
362
+ toolPreviewErr
363
+ ? React.createElement('div', { className: 'mcpm-warn' }, '⚠ ' + toolPreviewErr)
364
+ : toolPreviewBusy
365
+ ? React.createElement('div', { className: 'mcpm-sub' }, '正在获取工具列表…')
366
+ : (toolPreview.tools || []).length === 0
367
+ ? React.createElement('div', { className: 'mcpm-sub' }, '该服务暂无已注册工具' + (toolPreview.emptyHint || ''))
368
+ : React.createElement('div', { className: 'mcpm-tools-list' },
369
+ (toolPreview.tools || []).map((t) =>
370
+ React.createElement('div', { className: 'mcpm-tool' },
371
+ React.createElement('div', { className: 'mcpm-tool-name' }, t.name),
372
+ React.createElement('div', { className: 'mcpm-sub' }, t.description || '(无描述)'),
373
+ (t.parameters && t.parameters.length > 0) &&
374
+ React.createElement('div', { className: 'mcpm-tool-params' },
375
+ t.parameters.map((p) =>
376
+ React.createElement('div', { className: 'mcpm-tool-param' },
377
+ React.createElement('span', { className: 'mcpm-tool-param-key' },
378
+ p.key + (p.required ? ' *' : '')),
379
+ React.createElement('span', { className: 'mcpm-tool-param-type' }, p.type || 'any'),
380
+ React.createElement('span', { className: 'mcpm-tool-param-desc' }, p.description || '')))))))),
381
+ React.createElement('div', { className: 'mcpm-dialog-actions' },
382
+ React.createElement('button', { className: 'mcpm-btn', onClick: () => setToolPreview(null) }, '关闭'))))
335
383
  )
336
384
  }
337
385
 
package/lib/index.js CHANGED
@@ -844,6 +844,56 @@ export default {
844
844
  async function pluginVersion() {
845
845
  return { ok: true, version: PKG_VERSION };
846
846
  }
847
+ // Tool preview for one MCP server: project the model-facing schemas down to
848
+ // a name + description + parameter-summary list. The registry prefixes every
849
+ // MCP tool with `mcp__<serverName>__`; we filter on that and strip the prefix
850
+ // for display. Only the direct `properties` of the parameters object are
851
+ // summarized — nested object/array children are omitted (one level is enough
852
+ // for a preview, keeps the dialog readable).
853
+ async function mcpmTools(args) {
854
+ const serverName = String(args && args.serverName || '').trim();
855
+ if (!serverName)
856
+ return { ok: false, error: 'serverName 不能为空' };
857
+ const prefix = 'mcp__' + serverName + '__';
858
+ let schemas = [];
859
+ try {
860
+ schemas = await tools.schemas();
861
+ }
862
+ catch (e) {
863
+ return { ok: false, error: message(e) };
864
+ }
865
+ const toolsList = [];
866
+ for (const s of schemas) {
867
+ const fullName = String(s && s.name || '');
868
+ if (!fullName.startsWith(prefix))
869
+ continue;
870
+ const params = [];
871
+ const props = s.parameters && typeof s.parameters === 'object' ? s.parameters.properties : null;
872
+ const requiredSet = new Set();
873
+ if (s.parameters && Array.isArray(s.parameters.required)) {
874
+ for (const k of s.parameters.required)
875
+ if (typeof k === 'string')
876
+ requiredSet.add(k);
877
+ }
878
+ if (props && typeof props === 'object') {
879
+ for (const [key, spec] of Object.entries(props)) {
880
+ const ps = (spec && typeof spec === 'object') ? spec : {};
881
+ params.push({
882
+ key,
883
+ required: requiredSet.has(key),
884
+ type: typeof ps.type === 'string' ? ps.type : 'any',
885
+ ...(typeof ps.description === 'string' ? { description: ps.description } : {}),
886
+ });
887
+ }
888
+ }
889
+ toolsList.push({
890
+ name: fullName.slice(prefix.length),
891
+ description: typeof s.description === 'string' ? s.description : '',
892
+ parameters: params,
893
+ });
894
+ }
895
+ return { ok: true, tools: toolsList };
896
+ }
847
897
  async function mcpmList() {
848
898
  const p = await ensurePaths();
849
899
  const rows = [];
@@ -1195,6 +1245,7 @@ export default {
1195
1245
  const handlers = {
1196
1246
  'plugin-version': pluginVersion,
1197
1247
  'mcpm-list': mcpmList,
1248
+ 'mcpm-tools': mcpmTools,
1198
1249
  'mcpm-add': mcpmAdd,
1199
1250
  'mcpm-edit': mcpmEdit,
1200
1251
  'mcpm-set-enabled': mcpmSetEnabled,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xxxyz/dsh-mcp-manager",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "DSH-standard MCP manager plugin: Settings UI + HTTP API + model-facing mcp_manager_* tools. Install with one command: dsh plugin --profile web add @xxxyz/dsh-mcp-manager@latest",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
package/show.png CHANGED
Binary file