@pellux/goodvibes-sdk 0.33.26 → 0.33.27
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/dist/contracts/artifacts/operator-contract.json +1090 -4
- package/dist/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-runtime.js +150 -2
- package/dist/platform/daemon/facade-composition.d.ts.map +1 -1
- package/dist/platform/daemon/facade-composition.js +2 -0
- package/dist/platform/daemon/http/mcp-routes.d.ts +13 -0
- package/dist/platform/daemon/http/mcp-routes.d.ts.map +1 -0
- package/dist/platform/daemon/http/mcp-routes.js +128 -0
- package/dist/platform/daemon/http/router.d.ts +2 -0
- package/dist/platform/daemon/http/router.d.ts.map +1 -1
- package/dist/platform/daemon/http/router.js +12 -0
- package/dist/platform/mcp/config.d.ts +27 -0
- package/dist/platform/mcp/config.d.ts.map +1 -1
- package/dist/platform/mcp/config.js +165 -46
- package/dist/platform/mcp/index.d.ts +3 -3
- package/dist/platform/mcp/index.d.ts.map +1 -1
- package/dist/platform/mcp/index.js +1 -1
- package/dist/platform/mcp/mcp-api.d.ts +24 -0
- package/dist/platform/mcp/mcp-api.d.ts.map +1 -1
- package/dist/platform/mcp/mcp-api.js +12 -0
- package/dist/platform/mcp/registry.d.ts +27 -2
- package/dist/platform/mcp/registry.d.ts.map +1 -1
- package/dist/platform/mcp/registry.js +106 -8
- package/dist/platform/version.js +1 -1
- package/package.json +9 -9
|
@@ -1,67 +1,186 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP server configuration — scans multiple locations in precedence order.
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, readFileSync } from 'fs';
|
|
5
|
-
import { join } from 'path';
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
6
|
import { logger } from '../utils/logger.js';
|
|
7
7
|
import { summarizeError } from '../utils/error-display.js';
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
function optionalStringArray(value) {
|
|
12
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === 'string')
|
|
13
|
+
? [...value]
|
|
14
|
+
: undefined;
|
|
15
|
+
}
|
|
16
|
+
function optionalStringRecord(value) {
|
|
17
|
+
if (!isRecord(value))
|
|
18
|
+
return undefined;
|
|
19
|
+
const entries = Object.entries(value).filter((entry) => typeof entry[1] === 'string');
|
|
20
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
21
|
+
}
|
|
22
|
+
function normalizeServerConfig(name, raw) {
|
|
23
|
+
if (typeof raw.command !== 'string' || !raw.command.trim())
|
|
24
|
+
return null;
|
|
25
|
+
return {
|
|
26
|
+
name,
|
|
27
|
+
command: raw.command,
|
|
28
|
+
args: optionalStringArray(raw.args) ?? [],
|
|
29
|
+
env: optionalStringRecord(raw.env),
|
|
30
|
+
role: typeof raw.role === 'string' ? raw.role : undefined,
|
|
31
|
+
trustMode: typeof raw.trustMode === 'string' ? raw.trustMode : undefined,
|
|
32
|
+
allowedPaths: optionalStringArray(raw.allowedPaths),
|
|
33
|
+
allowedHosts: optionalStringArray(raw.allowedHosts),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function getMcpConfigLocations(roots) {
|
|
37
|
+
const cwd = roots.workingDirectory;
|
|
38
|
+
const home = roots.homeDirectory;
|
|
39
|
+
return [
|
|
40
|
+
{
|
|
41
|
+
scope: 'global',
|
|
42
|
+
kind: 'global-xdg',
|
|
43
|
+
path: join(home, '.config', 'mcp', 'mcp.json'),
|
|
44
|
+
writable: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
scope: 'external',
|
|
48
|
+
kind: 'global-dotdir',
|
|
49
|
+
path: join(home, '.mcp', 'mcp.json'),
|
|
50
|
+
writable: false,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
scope: 'external',
|
|
54
|
+
kind: 'claude-desktop',
|
|
55
|
+
path: join(home, '.config', 'claude', 'claude_desktop_config.json'),
|
|
56
|
+
writable: false,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
scope: 'external',
|
|
60
|
+
kind: 'project-mcp',
|
|
61
|
+
path: join(cwd, '.mcp', 'mcp.json'),
|
|
62
|
+
writable: false,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
scope: 'project',
|
|
66
|
+
kind: 'project-goodvibes',
|
|
67
|
+
path: join(cwd, '.goodvibes', 'mcp.json'),
|
|
68
|
+
writable: true,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
function writableMcpConfigLocation(roots, scope) {
|
|
73
|
+
const location = getMcpConfigLocations(roots).find((entry) => entry.scope === scope && entry.writable);
|
|
74
|
+
if (!location)
|
|
75
|
+
throw new Error(`No writable MCP config location is available for scope '${scope}'.`);
|
|
76
|
+
return location;
|
|
77
|
+
}
|
|
78
|
+
function parseMcpServers(raw) {
|
|
79
|
+
if (!isRecord(raw))
|
|
80
|
+
return null;
|
|
81
|
+
if (isRecord(raw.mcpServers)) {
|
|
82
|
+
const servers = [];
|
|
83
|
+
for (const [name, value] of Object.entries(raw.mcpServers)) {
|
|
84
|
+
if (!isRecord(value))
|
|
85
|
+
continue;
|
|
86
|
+
const server = normalizeServerConfig(name, value);
|
|
87
|
+
if (server)
|
|
88
|
+
servers.push(server);
|
|
89
|
+
}
|
|
90
|
+
return servers;
|
|
91
|
+
}
|
|
92
|
+
if (isMcpConfig(raw))
|
|
93
|
+
return raw.servers.map((server) => ({ ...server }));
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
function readMcpConfigAtPath(path) {
|
|
97
|
+
if (!existsSync(path))
|
|
98
|
+
return { servers: [] };
|
|
99
|
+
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
100
|
+
const servers = parseMcpServers(raw);
|
|
101
|
+
return { servers: servers ?? [] };
|
|
102
|
+
}
|
|
103
|
+
function assertServerConfig(server) {
|
|
104
|
+
if (!server.name.trim())
|
|
105
|
+
throw new Error('MCP server name is required.');
|
|
106
|
+
if (server.name.includes(':') || server.name.includes('/')) {
|
|
107
|
+
throw new Error('MCP server name may not contain ":" or "/".');
|
|
108
|
+
}
|
|
109
|
+
if (!server.command.trim())
|
|
110
|
+
throw new Error('MCP server command is required.');
|
|
111
|
+
}
|
|
112
|
+
function writeMcpConfigFile(path, config) {
|
|
113
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
114
|
+
const normalized = {
|
|
115
|
+
servers: config.servers.map((server) => {
|
|
116
|
+
assertServerConfig(server);
|
|
117
|
+
return {
|
|
118
|
+
name: server.name,
|
|
119
|
+
command: server.command,
|
|
120
|
+
...(server.args !== undefined ? { args: [...server.args] } : {}),
|
|
121
|
+
...(server.env !== undefined ? { env: { ...server.env } } : {}),
|
|
122
|
+
...(server.role !== undefined ? { role: server.role } : {}),
|
|
123
|
+
...(server.trustMode !== undefined ? { trustMode: server.trustMode } : {}),
|
|
124
|
+
...(server.allowedPaths !== undefined ? { allowedPaths: [...server.allowedPaths] } : {}),
|
|
125
|
+
...(server.allowedHosts !== undefined ? { allowedHosts: [...server.allowedHosts] } : {}),
|
|
126
|
+
};
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
writeFileSync(path, `${JSON.stringify(normalized, null, 2)}\n`);
|
|
130
|
+
}
|
|
8
131
|
/**
|
|
9
132
|
* loadMcpConfig - Scan multiple locations in precedence order (later wins).
|
|
10
133
|
* Returns merged config from all found files. Returns empty config on failure.
|
|
11
134
|
*/
|
|
12
135
|
export function loadMcpConfig(roots) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const locations =
|
|
17
|
-
join(home, '.config', 'mcp', 'mcp.json'), // global XDG
|
|
18
|
-
join(home, '.mcp', 'mcp.json'), // global dotdir
|
|
19
|
-
join(home, '.config', 'claude', 'claude_desktop_config.json'), // Claude Desktop
|
|
20
|
-
join(cwd, '.mcp', 'mcp.json'), // project-local
|
|
21
|
-
join(cwd, '.goodvibes', 'mcp.json'), // goodvibes project
|
|
22
|
-
];
|
|
23
|
-
const merged = { servers: [] };
|
|
136
|
+
return { servers: loadMcpEffectiveConfig(roots).servers.map((entry) => entry.server) };
|
|
137
|
+
}
|
|
138
|
+
export function loadMcpEffectiveConfig(roots) {
|
|
139
|
+
const locations = getMcpConfigLocations(roots);
|
|
24
140
|
const serversByName = new Map();
|
|
25
|
-
for (const
|
|
141
|
+
for (const location of locations) {
|
|
26
142
|
try {
|
|
27
|
-
if (!existsSync(path))
|
|
28
|
-
continue;
|
|
29
|
-
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
30
|
-
// Handle Claude Desktop format
|
|
31
|
-
if (typeof raw === 'object' && raw !== null && 'mcpServers' in raw) {
|
|
32
|
-
const obj = raw;
|
|
33
|
-
if (typeof obj['mcpServers'] === 'object' && obj['mcpServers'] !== null) {
|
|
34
|
-
for (const [name, srv] of Object.entries(obj['mcpServers'])) {
|
|
35
|
-
const s = srv;
|
|
36
|
-
if (typeof s.command === 'string') {
|
|
37
|
-
serversByName.set(name, {
|
|
38
|
-
name,
|
|
39
|
-
command: s.command,
|
|
40
|
-
args: Array.isArray(s.args) ? s.args.filter((a) => typeof a === 'string') : [],
|
|
41
|
-
env: typeof s.env === 'object' && s.env ? Object.fromEntries(Object.entries(s.env).filter(([, v]) => typeof v === 'string')) : undefined,
|
|
42
|
-
role: typeof s.role === 'string' ? s.role : undefined,
|
|
43
|
-
trustMode: typeof s.trustMode === 'string' ? s.trustMode : undefined,
|
|
44
|
-
allowedPaths: Array.isArray(s.allowedPaths) ? s.allowedPaths.filter((v) => typeof v === 'string') : undefined,
|
|
45
|
-
allowedHosts: Array.isArray(s.allowedHosts) ? s.allowedHosts.filter((v) => typeof v === 'string') : undefined,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
143
|
+
if (!existsSync(location.path))
|
|
50
144
|
continue;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
for (const srv of raw.servers) {
|
|
55
|
-
serversByName.set(srv.name, srv);
|
|
56
|
-
}
|
|
145
|
+
const config = readMcpConfigAtPath(location.path);
|
|
146
|
+
for (const server of config.servers) {
|
|
147
|
+
serversByName.set(server.name, { server, source: location });
|
|
57
148
|
}
|
|
58
149
|
}
|
|
59
150
|
catch (err) {
|
|
60
|
-
logger.warn(`[MCP] Failed to read ${path}`, { error: summarizeError(err) });
|
|
151
|
+
logger.warn(`[MCP] Failed to read ${location.path}`, { error: summarizeError(err) });
|
|
61
152
|
}
|
|
62
153
|
}
|
|
63
|
-
|
|
64
|
-
|
|
154
|
+
return {
|
|
155
|
+
servers: [...serversByName.values()],
|
|
156
|
+
locations,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export function loadWritableMcpConfig(roots, scope) {
|
|
160
|
+
const location = writableMcpConfigLocation(roots, scope);
|
|
161
|
+
return readMcpConfigAtPath(location.path);
|
|
162
|
+
}
|
|
163
|
+
export function upsertMcpServerConfig(roots, scope, server) {
|
|
164
|
+
assertServerConfig(server);
|
|
165
|
+
const location = writableMcpConfigLocation(roots, scope);
|
|
166
|
+
const current = readMcpConfigAtPath(location.path);
|
|
167
|
+
const nextServers = current.servers.filter((entry) => entry.name !== server.name);
|
|
168
|
+
nextServers.push({ ...server });
|
|
169
|
+
nextServers.sort((a, b) => a.name.localeCompare(b.name));
|
|
170
|
+
const config = { servers: nextServers };
|
|
171
|
+
writeMcpConfigFile(location.path, config);
|
|
172
|
+
return { path: location.path, config };
|
|
173
|
+
}
|
|
174
|
+
export function removeMcpServerConfig(roots, scope, serverName) {
|
|
175
|
+
if (!serverName.trim())
|
|
176
|
+
throw new Error('MCP server name is required.');
|
|
177
|
+
const location = writableMcpConfigLocation(roots, scope);
|
|
178
|
+
const current = readMcpConfigAtPath(location.path);
|
|
179
|
+
const config = { servers: current.servers.filter((entry) => entry.name !== serverName) };
|
|
180
|
+
const removed = config.servers.length !== current.servers.length;
|
|
181
|
+
if (removed || existsSync(location.path))
|
|
182
|
+
writeMcpConfigFile(location.path, config);
|
|
183
|
+
return { path: location.path, removed, config };
|
|
65
184
|
}
|
|
66
185
|
/** Type guard for McpConfig (goodvibes format) */
|
|
67
186
|
function isMcpConfig(v) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { McpRegistry } from './registry.js';
|
|
2
|
-
export type { RegisteredTool } from './registry.js';
|
|
2
|
+
export type { McpReloadResult, McpReloadServerResult, RegisteredTool } from './registry.js';
|
|
3
3
|
export { McpClient } from './client.js';
|
|
4
4
|
export { createMcpApi } from './mcp-api.js';
|
|
5
5
|
export type { McpApi, McpApiRegistry, McpSandboxBindingRecord, McpServerRecord, McpServerSecurityRecord, } from './mcp-api.js';
|
|
6
|
-
export { loadMcpConfig } from './config.js';
|
|
7
|
-
export type { McpConfig, McpConfigRoots, McpServerConfig } from './config.js';
|
|
6
|
+
export { getMcpConfigLocations, loadMcpConfig, loadMcpEffectiveConfig, loadWritableMcpConfig, removeMcpServerConfig, upsertMcpServerConfig, } from './config.js';
|
|
7
|
+
export type { McpConfig, McpConfigLocation, McpConfigRoots, McpConfigScope, McpEffectiveConfig, McpServerConfig, McpServerConfigEntry, } from './config.js';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EACV,MAAM,EACN,cAAc,EACd,uBAAuB,EACvB,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { McpRegistry } from './registry.js';
|
|
2
2
|
export { McpClient } from './client.js';
|
|
3
3
|
export { createMcpApi } from './mcp-api.js';
|
|
4
|
-
export { loadMcpConfig } from './config.js';
|
|
4
|
+
export { getMcpConfigLocations, loadMcpConfig, loadMcpEffectiveConfig, loadWritableMcpConfig, removeMcpServerConfig, upsertMcpServerConfig, } from './config.js';
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { RegisteredTool } from './registry.js';
|
|
2
|
+
import type { McpConfigRoots, McpConfigScope, McpEffectiveConfig, McpServerConfig } from './config.js';
|
|
3
|
+
import type { McpReloadResult } from './registry.js';
|
|
2
4
|
import type { McpDecisionRecord, McpServerRole, McpTrustMode, QuarantineReason, SchemaFreshness } from '../runtime/mcp/types.js';
|
|
3
5
|
export interface McpServerRecord {
|
|
4
6
|
readonly name: string;
|
|
@@ -25,6 +27,17 @@ export interface McpSandboxBindingRecord {
|
|
|
25
27
|
readonly startupStatus?: 'verified' | 'planned' | 'failed' | undefined;
|
|
26
28
|
}
|
|
27
29
|
export interface McpApi {
|
|
30
|
+
getEffectiveConfig(roots: McpConfigRoots): McpEffectiveConfig;
|
|
31
|
+
reload(roots: McpConfigRoots): Promise<McpReloadResult>;
|
|
32
|
+
upsertServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverConfig: McpServerConfig): Promise<{
|
|
33
|
+
readonly path: string;
|
|
34
|
+
readonly reload: McpReloadResult;
|
|
35
|
+
}>;
|
|
36
|
+
removeServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverName: string): Promise<{
|
|
37
|
+
readonly path: string;
|
|
38
|
+
readonly removed: boolean;
|
|
39
|
+
readonly reload: McpReloadResult;
|
|
40
|
+
}>;
|
|
28
41
|
listServerNames(): readonly string[];
|
|
29
42
|
listServers(): readonly McpServerRecord[];
|
|
30
43
|
listServerSecurity(): readonly McpServerSecurityRecord[];
|
|
@@ -38,6 +51,17 @@ export interface McpApi {
|
|
|
38
51
|
}
|
|
39
52
|
export interface McpApiRegistry {
|
|
40
53
|
readonly serverNames: readonly string[];
|
|
54
|
+
getEffectiveConfig(roots: McpConfigRoots): McpEffectiveConfig;
|
|
55
|
+
reload(roots: McpConfigRoots): Promise<McpReloadResult>;
|
|
56
|
+
upsertServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverConfig: McpServerConfig): Promise<{
|
|
57
|
+
readonly path: string;
|
|
58
|
+
readonly reload: McpReloadResult;
|
|
59
|
+
}>;
|
|
60
|
+
removeServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverName: string): Promise<{
|
|
61
|
+
readonly path: string;
|
|
62
|
+
readonly removed: boolean;
|
|
63
|
+
readonly reload: McpReloadResult;
|
|
64
|
+
}>;
|
|
41
65
|
listServers(): readonly McpServerRecord[];
|
|
42
66
|
listServerSecurity(): readonly McpServerSecurityRecord[];
|
|
43
67
|
listServerSandboxBindings(): readonly McpSandboxBindingRecord[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-api.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/mcp-api.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"mcp-api.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/mcp-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export function createMcpApi(registry) {
|
|
2
2
|
return {
|
|
3
|
+
getEffectiveConfig(roots) {
|
|
4
|
+
return registry.getEffectiveConfig(roots);
|
|
5
|
+
},
|
|
6
|
+
reload(roots) {
|
|
7
|
+
return registry.reload(roots);
|
|
8
|
+
},
|
|
9
|
+
upsertServerConfig(roots, scope, serverConfig) {
|
|
10
|
+
return registry.upsertServerConfig(roots, scope, serverConfig);
|
|
11
|
+
},
|
|
12
|
+
removeServerConfig(roots, scope, serverName) {
|
|
13
|
+
return registry.removeServerConfig(roots, scope, serverName);
|
|
14
|
+
},
|
|
3
15
|
listServerNames() {
|
|
4
16
|
return registry.serverNames;
|
|
5
17
|
},
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { McpClient } from './client.js';
|
|
2
2
|
import type { McpToolSchema } from './client.js';
|
|
3
|
-
import type { McpServerConfig } from './config.js';
|
|
3
|
+
import type { McpConfigRoots, McpConfigScope, McpEffectiveConfig, McpServerConfig } from './config.js';
|
|
4
4
|
import type { HookDispatcher } from '../hooks/dispatcher.js';
|
|
5
5
|
import type { McpDecisionRecord, QuarantineReason, SchemaFreshness } from '../runtime/mcp/types.js';
|
|
6
6
|
import type { RuntimeEventBus } from '../runtime/events/index.js';
|
|
7
7
|
import type { ConfigManager } from '../config/manager.js';
|
|
8
|
-
import type { McpConfigRoots } from './config.js';
|
|
9
8
|
import { type SandboxSessionRegistry } from '../runtime/sandbox/session-registry.js';
|
|
10
9
|
export interface RegisteredTool {
|
|
11
10
|
/** Fully-qualified tool name: mcp:<server>:<tool> */
|
|
@@ -14,8 +13,21 @@ export interface RegisteredTool {
|
|
|
14
13
|
toolName: string;
|
|
15
14
|
description: string;
|
|
16
15
|
}
|
|
16
|
+
export interface McpReloadServerResult {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly action: 'added' | 'changed' | 'removed' | 'unchanged';
|
|
19
|
+
readonly connected: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface McpReloadResult {
|
|
22
|
+
readonly added: number;
|
|
23
|
+
readonly changed: number;
|
|
24
|
+
readonly removed: number;
|
|
25
|
+
readonly unchanged: number;
|
|
26
|
+
readonly servers: readonly McpReloadServerResult[];
|
|
27
|
+
}
|
|
17
28
|
export declare class McpRegistry {
|
|
18
29
|
private clients;
|
|
30
|
+
private serverConfigs;
|
|
19
31
|
private permissions;
|
|
20
32
|
private freshness;
|
|
21
33
|
private runtimeBus;
|
|
@@ -39,6 +51,18 @@ export declare class McpRegistry {
|
|
|
39
51
|
* Exposed for programmatic use (testing, dynamic registration).
|
|
40
52
|
*/
|
|
41
53
|
connectServer(serverConfig: McpServerConfig): Promise<void>;
|
|
54
|
+
reload(roots: McpConfigRoots): Promise<McpReloadResult>;
|
|
55
|
+
getEffectiveConfig(roots: McpConfigRoots): McpEffectiveConfig;
|
|
56
|
+
upsertServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverConfig: McpServerConfig): Promise<{
|
|
57
|
+
readonly path: string;
|
|
58
|
+
readonly reload: McpReloadResult;
|
|
59
|
+
}>;
|
|
60
|
+
removeServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverName: string): Promise<{
|
|
61
|
+
readonly path: string;
|
|
62
|
+
readonly removed: boolean;
|
|
63
|
+
readonly reload: McpReloadResult;
|
|
64
|
+
}>;
|
|
65
|
+
applyConfig(serverConfigs: readonly McpServerConfig[]): Promise<McpReloadResult>;
|
|
42
66
|
/**
|
|
43
67
|
* listAllTools — Return all registered tools (name + description) from all connected servers.
|
|
44
68
|
* Only loads tool names and descriptions — full schemas are NOT fetched here.
|
|
@@ -58,6 +82,7 @@ export declare class McpRegistry {
|
|
|
58
82
|
* disconnectAll — Stop all connected MCP server processes.
|
|
59
83
|
*/
|
|
60
84
|
disconnectAll(): Promise<void>;
|
|
85
|
+
disconnectServer(serverName: string, reason?: string): Promise<boolean>;
|
|
61
86
|
/**
|
|
62
87
|
* getClient — Get the McpClient for a given server name (for advanced use).
|
|
63
88
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* Tool namespace: mcp:<server-name>:<tool-name>
|
|
9
9
|
*/
|
|
10
10
|
import { logger } from '../utils/logger.js';
|
|
11
|
-
import {
|
|
11
|
+
import { loadMcpEffectiveConfig, removeMcpServerConfig, upsertMcpServerConfig, } from './config.js';
|
|
12
12
|
import { McpClient } from './client.js';
|
|
13
13
|
import { McpPermissionManager } from '../runtime/mcp/permissions.js';
|
|
14
14
|
import { McpSchemaFreshnessTracker } from '../runtime/mcp/schema-freshness.js';
|
|
15
|
-
import { emitMcpConfigured, emitMcpPolicyUpdated, emitMcpSchemaQuarantineApproved, emitMcpSchemaQuarantined, } from '../runtime/emitters/mcp.js';
|
|
15
|
+
import { emitMcpConfigured, emitMcpDisconnected, emitMcpPolicyUpdated, emitMcpSchemaQuarantineApproved, emitMcpSchemaQuarantined, } from '../runtime/emitters/mcp.js';
|
|
16
16
|
import { getSandboxConfigSnapshot } from '../runtime/sandbox/manager.js';
|
|
17
17
|
import {} from '../runtime/sandbox/session-registry.js';
|
|
18
18
|
import { resolveSandboxCommandPlan } from '../runtime/sandbox/backend.js';
|
|
@@ -20,8 +20,12 @@ import { summarizeError } from '../utils/error-display.js';
|
|
|
20
20
|
function compactEnv(env) {
|
|
21
21
|
return Object.fromEntries(Object.entries(env).filter((entry) => typeof entry[1] === 'string'));
|
|
22
22
|
}
|
|
23
|
+
function sameServerConfig(a, b) {
|
|
24
|
+
return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
25
|
+
}
|
|
23
26
|
export class McpRegistry {
|
|
24
27
|
clients = new Map();
|
|
28
|
+
serverConfigs = new Map();
|
|
25
29
|
permissions = new McpPermissionManager();
|
|
26
30
|
freshness = new McpSchemaFreshnessTracker();
|
|
27
31
|
runtimeBus = null;
|
|
@@ -45,16 +49,74 @@ export class McpRegistry {
|
|
|
45
49
|
* Errors on individual servers are logged but do not abort the whole startup.
|
|
46
50
|
*/
|
|
47
51
|
async connectAll(roots) {
|
|
48
|
-
|
|
49
|
-
await Promise.allSettled(mcpConfig.servers.map((serverConfig) => this._connectServer(serverConfig)));
|
|
52
|
+
await this.reload(roots);
|
|
50
53
|
}
|
|
51
54
|
/**
|
|
52
55
|
* connectServer — Connect a single MCP server by config.
|
|
53
56
|
* Exposed for programmatic use (testing, dynamic registration).
|
|
54
57
|
*/
|
|
55
58
|
async connectServer(serverConfig) {
|
|
59
|
+
this.serverConfigs.set(serverConfig.name, serverConfig);
|
|
56
60
|
await this._connectServer(serverConfig);
|
|
57
61
|
}
|
|
62
|
+
async reload(roots) {
|
|
63
|
+
const effective = loadMcpEffectiveConfig(roots);
|
|
64
|
+
return this.applyConfig(effective.servers.map((entry) => entry.server));
|
|
65
|
+
}
|
|
66
|
+
getEffectiveConfig(roots) {
|
|
67
|
+
return loadMcpEffectiveConfig(roots);
|
|
68
|
+
}
|
|
69
|
+
async upsertServerConfig(roots, scope, serverConfig) {
|
|
70
|
+
const written = upsertMcpServerConfig(roots, scope, serverConfig);
|
|
71
|
+
return { path: written.path, reload: await this.reload(roots) };
|
|
72
|
+
}
|
|
73
|
+
async removeServerConfig(roots, scope, serverName) {
|
|
74
|
+
const written = removeMcpServerConfig(roots, scope, serverName);
|
|
75
|
+
return { path: written.path, removed: written.removed, reload: await this.reload(roots) };
|
|
76
|
+
}
|
|
77
|
+
async applyConfig(serverConfigs) {
|
|
78
|
+
const next = new Map(serverConfigs.map((serverConfig) => [serverConfig.name, serverConfig]));
|
|
79
|
+
const results = [];
|
|
80
|
+
let added = 0;
|
|
81
|
+
let changed = 0;
|
|
82
|
+
let removed = 0;
|
|
83
|
+
let unchanged = 0;
|
|
84
|
+
for (const name of [...this.serverConfigs.keys()]) {
|
|
85
|
+
if (next.has(name))
|
|
86
|
+
continue;
|
|
87
|
+
await this.disconnectServer(name, 'config-removed');
|
|
88
|
+
this.serverConfigs.delete(name);
|
|
89
|
+
removed += 1;
|
|
90
|
+
results.push({ name, action: 'removed', connected: false });
|
|
91
|
+
}
|
|
92
|
+
for (const [name, serverConfig] of next) {
|
|
93
|
+
const previous = this.serverConfigs.get(name);
|
|
94
|
+
if (previous && sameServerConfig(previous, serverConfig)) {
|
|
95
|
+
unchanged += 1;
|
|
96
|
+
const client = this.clients.get(name);
|
|
97
|
+
if (!client?.isConnected) {
|
|
98
|
+
await this._connectServer(serverConfig);
|
|
99
|
+
}
|
|
100
|
+
results.push({ name, action: 'unchanged', connected: this.clients.get(name)?.isConnected ?? false });
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (previous) {
|
|
104
|
+
await this.disconnectServer(name, 'config-changed');
|
|
105
|
+
changed += 1;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
added += 1;
|
|
109
|
+
}
|
|
110
|
+
this.serverConfigs.set(name, serverConfig);
|
|
111
|
+
await this._connectServer(serverConfig);
|
|
112
|
+
results.push({
|
|
113
|
+
name,
|
|
114
|
+
action: previous ? 'changed' : 'added',
|
|
115
|
+
connected: this.clients.get(name)?.isConnected ?? false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { added, changed, removed, unchanged, servers: results };
|
|
119
|
+
}
|
|
58
120
|
/**
|
|
59
121
|
* listAllTools — Return all registered tools (name + description) from all connected servers.
|
|
60
122
|
* Only loads tool names and descriptions — full schemas are NOT fetched here.
|
|
@@ -194,6 +256,38 @@ export class McpRegistry {
|
|
|
194
256
|
}
|
|
195
257
|
this.sandboxSessionByServer.clear();
|
|
196
258
|
}
|
|
259
|
+
async disconnectServer(serverName, reason = 'manual') {
|
|
260
|
+
const client = this.clients.get(serverName);
|
|
261
|
+
if (!client)
|
|
262
|
+
return false;
|
|
263
|
+
await client.disconnect();
|
|
264
|
+
this.clients.delete(serverName);
|
|
265
|
+
const sessionId = this.sandboxSessionByServer.get(serverName);
|
|
266
|
+
if (sessionId) {
|
|
267
|
+
this.sandboxSessions.stop(sessionId);
|
|
268
|
+
this.sandboxSessionByServer.delete(serverName);
|
|
269
|
+
}
|
|
270
|
+
if (this.runtimeBus) {
|
|
271
|
+
emitMcpDisconnected(this.runtimeBus, {
|
|
272
|
+
sessionId: 'mcp-registry',
|
|
273
|
+
traceId: `mcp-registry:${serverName}:disconnected`,
|
|
274
|
+
source: 'mcp-registry',
|
|
275
|
+
}, { serverId: serverName, reason, willRetry: false });
|
|
276
|
+
}
|
|
277
|
+
const disconnectedEvent = {
|
|
278
|
+
path: 'Lifecycle:mcp:disconnected',
|
|
279
|
+
phase: 'Lifecycle',
|
|
280
|
+
category: 'mcp',
|
|
281
|
+
specific: 'disconnected',
|
|
282
|
+
sessionId: '',
|
|
283
|
+
timestamp: Date.now(),
|
|
284
|
+
payload: { server: serverName, reason },
|
|
285
|
+
};
|
|
286
|
+
this.hookDispatcher.fire(disconnectedEvent).catch((err) => {
|
|
287
|
+
logger.warn('Lifecycle:mcp:disconnected hook error', { error: summarizeError(err) });
|
|
288
|
+
});
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
197
291
|
/**
|
|
198
292
|
* getClient — Get the McpClient for a given server name (for advanced use).
|
|
199
293
|
*/
|
|
@@ -202,15 +296,15 @@ export class McpRegistry {
|
|
|
202
296
|
}
|
|
203
297
|
/** Connected server names. */
|
|
204
298
|
get serverNames() {
|
|
205
|
-
return Array.from(this.clients.keys());
|
|
299
|
+
return Array.from(new Set([...this.serverConfigs.keys(), ...this.clients.keys()])).sort();
|
|
206
300
|
}
|
|
207
301
|
/**
|
|
208
302
|
* listServers — Return status info for all known servers (connected or not).
|
|
209
303
|
*/
|
|
210
304
|
listServers() {
|
|
211
|
-
return
|
|
305
|
+
return this.serverNames.map((name) => ({
|
|
212
306
|
name,
|
|
213
|
-
connected:
|
|
307
|
+
connected: this.clients.get(name)?.isConnected ?? false,
|
|
214
308
|
}));
|
|
215
309
|
}
|
|
216
310
|
listServerSecurity() {
|
|
@@ -283,10 +377,14 @@ export class McpRegistry {
|
|
|
283
377
|
// ---------------------------------------------------------------------------
|
|
284
378
|
async _connectServer(serverConfig) {
|
|
285
379
|
const { name } = serverConfig;
|
|
286
|
-
|
|
380
|
+
const existing = this.clients.get(name);
|
|
381
|
+
if (existing?.isConnected) {
|
|
287
382
|
logger.info('McpRegistry: server already registered', { name });
|
|
288
383
|
return;
|
|
289
384
|
}
|
|
385
|
+
if (existing) {
|
|
386
|
+
await this.disconnectServer(name, 'reconnect');
|
|
387
|
+
}
|
|
290
388
|
let sandboxSessionId = null;
|
|
291
389
|
let processSpec;
|
|
292
390
|
if (this.sandboxConfigManager) {
|
package/dist/platform/version.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
let version = '0.33.
|
|
3
|
+
let version = '0.33.27';
|
|
4
4
|
try {
|
|
5
5
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', '..', 'package.json'), 'utf-8'));
|
|
6
6
|
version = pkg.version ?? version;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-sdk",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.27",
|
|
4
4
|
"description": "TypeScript SDK for building GoodVibes operator, peer, web, mobile, and daemon-connected apps with typed contracts, auth, realtime events, and transport layers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"goodvibes",
|
|
@@ -449,14 +449,14 @@
|
|
|
449
449
|
"sideEffects": false,
|
|
450
450
|
"type": "module",
|
|
451
451
|
"dependencies": {
|
|
452
|
-
"@pellux/goodvibes-contracts": "0.33.
|
|
453
|
-
"@pellux/goodvibes-daemon-sdk": "0.33.
|
|
454
|
-
"@pellux/goodvibes-errors": "0.33.
|
|
455
|
-
"@pellux/goodvibes-operator-sdk": "0.33.
|
|
456
|
-
"@pellux/goodvibes-peer-sdk": "0.33.
|
|
457
|
-
"@pellux/goodvibes-transport-core": "0.33.
|
|
458
|
-
"@pellux/goodvibes-transport-http": "0.33.
|
|
459
|
-
"@pellux/goodvibes-transport-realtime": "0.33.
|
|
452
|
+
"@pellux/goodvibes-contracts": "0.33.27",
|
|
453
|
+
"@pellux/goodvibes-daemon-sdk": "0.33.27",
|
|
454
|
+
"@pellux/goodvibes-errors": "0.33.27",
|
|
455
|
+
"@pellux/goodvibes-operator-sdk": "0.33.27",
|
|
456
|
+
"@pellux/goodvibes-peer-sdk": "0.33.27",
|
|
457
|
+
"@pellux/goodvibes-transport-core": "0.33.27",
|
|
458
|
+
"@pellux/goodvibes-transport-http": "0.33.27",
|
|
459
|
+
"@pellux/goodvibes-transport-realtime": "0.33.27"
|
|
460
460
|
},
|
|
461
461
|
"optionalDependencies": {
|
|
462
462
|
"@agentclientprotocol/sdk": "^0.21.0",
|