mirror of
https://github.com/hansjone/netxops.git
synced 2026-10-20 03:51:01 +08:00
Netx tools: load from netx remote /mcp, add per-tool toggles
- Drop the TypeScript netx tool implementations and the hard-coded TOOLS_BY_GROUP list; register netx__* tools from the server's tools/list (group from _meta.netx.group) and forward tools/call. - Thin Streamable HTTP client on standard fetch (fetchImpl injectable); cached catalog when netx is unreachable, refresh to reconnect. - disabledTools (deny list; new server tools follow their group) and readOnlyOnly (only readOnlyHint=true tools), re-registered live. - Settings card: per-group expandable tool rows with switches and a write marker; skills append a disabled-tools note. - Toggles only control model visibility; netx enforces security. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2def53e7c7
commit
2ef3a43c63
38 changed files with 5049 additions and 17029 deletions
116
test/mcp-test-catalog.mjs
Normal file
116
test/mcp-test-catalog.mjs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* Seed the process-local MCP catalog for registration / publication tests.
|
||||
*/
|
||||
|
||||
import { publishNetxConnection } from '../src/netx/runtime.ts'
|
||||
|
||||
const STORE_KEY = Symbol.for('dsh-netxops.mcp-catalog-store')
|
||||
|
||||
/** Classic ops catalog size (matches historical TOOLS_BY_GROUP.ops.length). */
|
||||
export const OPS_TOOL_NAMES = Object.freeze([
|
||||
'queryNmsAlarms',
|
||||
'aggregateNmsAlarms',
|
||||
'runNmsDiagnostics',
|
||||
'queryNmsNeInventory',
|
||||
'getNmsNe',
|
||||
'queryNmsAlarmsRaw',
|
||||
'aggregateNmsAlarmsRaw',
|
||||
'listNmsAlarmFields',
|
||||
'sqlQueryNms',
|
||||
'listManagedNe',
|
||||
'getManagedNe',
|
||||
'execManagedNe',
|
||||
'getNeExecJob',
|
||||
'listCliTargets',
|
||||
'findTopologyPaths',
|
||||
])
|
||||
|
||||
export const TOPOLOGY_TOOL_NAMES = Object.freeze([
|
||||
'getTopologyTree',
|
||||
'getTopologyView',
|
||||
'createTopologyFolder',
|
||||
'addTopologyViewNodes',
|
||||
'removeTopologyViewNodes',
|
||||
'copyTopologyViewNodes',
|
||||
'updateTopologyViewPositions',
|
||||
'projectTopologyNeighbors',
|
||||
'queryTopologyFabricNodes',
|
||||
'classifyTopologyFabricNodes',
|
||||
'queryTopologyNeighborhood',
|
||||
'queryTopologyEdges',
|
||||
'layoutTopologyView',
|
||||
'suggestSinkHubs',
|
||||
'analyzeTopologyViewLayout',
|
||||
])
|
||||
|
||||
export const BIZ_MONITOR_TOOL_NAMES = Object.freeze([
|
||||
'listBizMonitors',
|
||||
'listBizMonitorBatches',
|
||||
'getBizMonitorContext',
|
||||
'getBizMonitorBoard',
|
||||
'listBizMonitorReds',
|
||||
'getBizMonitorDiffs',
|
||||
'getBizCollectBatch',
|
||||
'getBizCollectCommandRaw',
|
||||
])
|
||||
|
||||
const WRITE_OPS = new Set(['execManagedNe'])
|
||||
const WRITE_TOPOLOGY = new Set([
|
||||
'createTopologyFolder',
|
||||
'addTopologyViewNodes',
|
||||
'removeTopologyViewNodes',
|
||||
'copyTopologyViewNodes',
|
||||
'updateTopologyViewPositions',
|
||||
'projectTopologyNeighbors',
|
||||
'classifyTopologyFabricNodes',
|
||||
'layoutTopologyView',
|
||||
])
|
||||
|
||||
function descriptor(name, group) {
|
||||
const write = (group === 'ops' && WRITE_OPS.has(name))
|
||||
|| (group === 'topology' && WRITE_TOPOLOGY.has(name))
|
||||
return {
|
||||
name,
|
||||
description: name,
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
readOnlyHint: !write,
|
||||
group,
|
||||
}
|
||||
}
|
||||
|
||||
export function fullCatalog() {
|
||||
return [
|
||||
...OPS_TOOL_NAMES.map((name) => descriptor(name, 'ops')),
|
||||
...TOPOLOGY_TOOL_NAMES.map((name) => descriptor(name, 'topology')),
|
||||
...BIZ_MONITOR_TOOL_NAMES.map((name) => descriptor(name, 'bizMonitor')),
|
||||
]
|
||||
}
|
||||
|
||||
/** Install a frozen catalog into the shared Symbol.for store (no network). */
|
||||
export function seedMcpCatalog(tools = fullCatalog()) {
|
||||
const root = globalThis
|
||||
const store = {
|
||||
state: {
|
||||
phase: 'connected',
|
||||
mcpUrl: 'http://127.0.0.1:8890/mcp',
|
||||
tools: Object.freeze([...tools]),
|
||||
error: '',
|
||||
listedAt: new Date().toISOString(),
|
||||
fromCache: false,
|
||||
},
|
||||
listeners: new Set(),
|
||||
generation: 1,
|
||||
}
|
||||
root[STORE_KEY] = store
|
||||
return store.state
|
||||
}
|
||||
|
||||
export function clearMcpCatalogSeed() {
|
||||
delete globalThis[STORE_KEY]
|
||||
}
|
||||
|
||||
/** Convenience: seed catalog + publish a connection snapshot. */
|
||||
export function publishWithCatalog(connection) {
|
||||
seedMcpCatalog()
|
||||
publishNetxConnection(connection)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue