@pellux/goodvibes-sdk 0.33.26 → 0.33.28
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/events/ops.d.ts +6 -0
- package/dist/events/ops.d.ts.map +1 -1
- 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/core/context-compaction.d.ts +21 -7
- package/dist/platform/core/context-compaction.d.ts.map +1 -1
- package/dist/platform/core/context-compaction.js +42 -11
- package/dist/platform/core/orchestrator-context-runtime.d.ts.map +1 -1
- package/dist/platform/core/orchestrator-context-runtime.js +133 -25
- 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/runtime/bootstrap-hook-bridge.d.ts.map +1 -1
- package/dist/platform/runtime/bootstrap-hook-bridge.js +4 -3
- package/dist/platform/runtime/emitters/ops.d.ts +6 -0
- package/dist/platform/runtime/emitters/ops.d.ts.map +1 -1
- package/dist/platform/runtime/emitters/ops.js +1 -2
- package/dist/platform/tools/exec/runtime.d.ts.map +1 -1
- package/dist/platform/tools/exec/runtime.js +25 -1
- package/dist/platform/tools/exec/schema.d.ts +6 -1
- package/dist/platform/tools/exec/schema.d.ts.map +1 -1
- package/dist/platform/tools/exec/schema.js +5 -1
- package/dist/platform/version.js +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-routes.d.ts","sourceRoot":"","sources":["../../../../src/platform/daemon/http/mcp-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,UAAU,eAAe;IACvB,QAAQ,CAAC,WAAW,EAAE,IAAI,CACxB,WAAW,EACT,oBAAoB,GACpB,QAAQ,GACR,oBAAoB,GACpB,oBAAoB,GACpB,aAAa,GACb,oBAAoB,GACpB,2BAA2B,GAC3B,cAAc,CACjB,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC;IACzE,QAAQ,CAAC,qBAAqB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;IACxF,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,IAAI,CAAC;CAC1D;AAoED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAkExG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { jsonErrorResponse } from './error-response.js';
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function stringArray(value) {
|
|
6
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === 'string')
|
|
7
|
+
? [...value]
|
|
8
|
+
: undefined;
|
|
9
|
+
}
|
|
10
|
+
function stringRecord(value) {
|
|
11
|
+
if (!isRecord(value))
|
|
12
|
+
return undefined;
|
|
13
|
+
const entries = Object.entries(value);
|
|
14
|
+
if (!entries.every((entry) => typeof entry[1] === 'string'))
|
|
15
|
+
return undefined;
|
|
16
|
+
return Object.fromEntries(entries);
|
|
17
|
+
}
|
|
18
|
+
function parseScope(value) {
|
|
19
|
+
return value === 'global' ? 'global' : 'project';
|
|
20
|
+
}
|
|
21
|
+
function parseServerConfig(value) {
|
|
22
|
+
if (!isRecord(value)) {
|
|
23
|
+
return jsonErrorResponse({ error: 'Missing MCP server config object.' }, { status: 400 });
|
|
24
|
+
}
|
|
25
|
+
if (typeof value.name !== 'string' || !value.name.trim()) {
|
|
26
|
+
return jsonErrorResponse({ error: 'MCP server name is required.' }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
if (typeof value.command !== 'string' || !value.command.trim()) {
|
|
29
|
+
return jsonErrorResponse({ error: 'MCP server command is required.' }, { status: 400 });
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
name: value.name.trim(),
|
|
33
|
+
command: value.command.trim(),
|
|
34
|
+
args: stringArray(value.args) ?? [],
|
|
35
|
+
env: stringRecord(value.env),
|
|
36
|
+
role: typeof value.role === 'string' ? value.role : undefined,
|
|
37
|
+
trustMode: typeof value.trustMode === 'string' ? value.trustMode : undefined,
|
|
38
|
+
allowedPaths: stringArray(value.allowedPaths),
|
|
39
|
+
allowedHosts: stringArray(value.allowedHosts),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function redactServer(server) {
|
|
43
|
+
return {
|
|
44
|
+
name: server.name,
|
|
45
|
+
command: server.command,
|
|
46
|
+
args: server.args ?? [],
|
|
47
|
+
envKeys: Object.keys(server.env ?? {}).sort(),
|
|
48
|
+
role: server.role ?? null,
|
|
49
|
+
trustMode: server.trustMode ?? null,
|
|
50
|
+
allowedPaths: server.allowedPaths ?? [],
|
|
51
|
+
allowedHosts: server.allowedHosts ?? [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function serializeEffectiveConfig(config) {
|
|
55
|
+
return {
|
|
56
|
+
locations: config.locations,
|
|
57
|
+
servers: config.servers.map((entry) => ({
|
|
58
|
+
...redactServer(entry.server),
|
|
59
|
+
source: entry.source,
|
|
60
|
+
})),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export async function dispatchMcpRoutes(req, context) {
|
|
64
|
+
const url = new URL(req.url);
|
|
65
|
+
const { pathname } = url;
|
|
66
|
+
if (pathname === '/api/mcp/config' && req.method === 'GET') {
|
|
67
|
+
return Response.json(serializeEffectiveConfig(context.mcpRegistry.getEffectiveConfig(context.roots)));
|
|
68
|
+
}
|
|
69
|
+
if (pathname === '/api/mcp/servers' && req.method === 'GET') {
|
|
70
|
+
return Response.json({
|
|
71
|
+
servers: context.mcpRegistry.listServers(),
|
|
72
|
+
security: context.mcpRegistry.listServerSecurity(),
|
|
73
|
+
sandboxBindings: context.mcpRegistry.listServerSandboxBindings(),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (pathname === '/api/mcp/tools' && req.method === 'GET') {
|
|
77
|
+
return Response.json({ tools: await context.mcpRegistry.listAllTools() });
|
|
78
|
+
}
|
|
79
|
+
if (pathname === '/api/mcp/reload' && req.method === 'POST') {
|
|
80
|
+
const admin = context.requireAdmin(req);
|
|
81
|
+
if (admin)
|
|
82
|
+
return admin;
|
|
83
|
+
return Response.json({
|
|
84
|
+
reload: await context.mcpRegistry.reload(context.roots),
|
|
85
|
+
config: serializeEffectiveConfig(context.mcpRegistry.getEffectiveConfig(context.roots)),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (pathname === '/api/mcp/config/servers' && req.method === 'POST') {
|
|
89
|
+
const admin = context.requireAdmin(req);
|
|
90
|
+
if (admin)
|
|
91
|
+
return admin;
|
|
92
|
+
const body = await context.parseJsonBody(req);
|
|
93
|
+
if (body instanceof Response)
|
|
94
|
+
return body;
|
|
95
|
+
const server = parseServerConfig(body.server ?? body);
|
|
96
|
+
if (server instanceof Response)
|
|
97
|
+
return server;
|
|
98
|
+
const scope = parseScope(body.scope);
|
|
99
|
+
const result = await context.mcpRegistry.upsertServerConfig(context.roots, scope, server);
|
|
100
|
+
return Response.json({
|
|
101
|
+
scope,
|
|
102
|
+
path: result.path,
|
|
103
|
+
removed: false,
|
|
104
|
+
reload: result.reload,
|
|
105
|
+
config: serializeEffectiveConfig(context.mcpRegistry.getEffectiveConfig(context.roots)),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const serverMatch = pathname.match(/^\/api\/mcp\/config\/servers\/([^/]+)$/);
|
|
109
|
+
if (serverMatch && req.method === 'DELETE') {
|
|
110
|
+
const admin = context.requireAdmin(req);
|
|
111
|
+
if (admin)
|
|
112
|
+
return admin;
|
|
113
|
+
const body = await context.parseOptionalJsonBody(req);
|
|
114
|
+
if (body instanceof Response)
|
|
115
|
+
return body;
|
|
116
|
+
const scope = parseScope(body?.scope ?? url.searchParams.get('scope'));
|
|
117
|
+
const serverName = decodeURIComponent(serverMatch[1]);
|
|
118
|
+
const result = await context.mcpRegistry.removeServerConfig(context.roots, scope, serverName);
|
|
119
|
+
return Response.json({
|
|
120
|
+
scope,
|
|
121
|
+
path: result.path,
|
|
122
|
+
removed: result.removed,
|
|
123
|
+
reload: result.reload,
|
|
124
|
+
config: serializeEffectiveConfig(context.mcpRegistry.getEffectiveConfig(context.roots)),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
@@ -43,6 +43,8 @@ interface DaemonHttpRouterContext {
|
|
|
43
43
|
readonly watcherRegistry: WatcherRegistry;
|
|
44
44
|
readonly voiceService: VoiceService;
|
|
45
45
|
readonly webSearchService: WebSearchService;
|
|
46
|
+
readonly mcpRegistry: import('../../mcp/registry.js').McpRegistry;
|
|
47
|
+
readonly mcpConfigRoots: import('../../mcp/config.js').McpConfigRoots;
|
|
46
48
|
readonly knowledgeService: KnowledgeService;
|
|
47
49
|
readonly homeGraphService: HomeGraphService;
|
|
48
50
|
readonly projectPlanningService: ProjectPlanningService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../src/platform/daemon/http/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAIL,KAAK,iBAAiB,EAGvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC7G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAMpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACjI,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AACpG,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEpI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D,OAAO,KAAK,EAAE,+BAA+B,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA0B5F,OAAO,KAAK,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../src/platform/daemon/http/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,7 @@ import { dispatchCompanionChatRoutes } from '../../companion/companion-chat-rout
|
|
|
28
28
|
import { dispatchModelRoutes } from './model-routes.js';
|
|
29
29
|
import { dispatchBatchRoutes } from './batch-routes.js';
|
|
30
30
|
import { dispatchCloudflareRoutes } from './cloudflare-routes.js';
|
|
31
|
+
import { dispatchMcpRoutes } from './mcp-routes.js';
|
|
31
32
|
import { HomeAssistantConversationRoutes } from './homeassistant-routes.js';
|
|
32
33
|
import { HomeGraphRoutes } from './home-graph-routes.js';
|
|
33
34
|
import { dispatchOpenAICompatibleRoutes } from './openai-compatible-routes.js';
|
|
@@ -182,6 +183,17 @@ export class DaemonHttpRouter {
|
|
|
182
183
|
if (cloudflareResponse)
|
|
183
184
|
return cloudflareResponse;
|
|
184
185
|
}
|
|
186
|
+
if (url.pathname.startsWith('/api/mcp')) {
|
|
187
|
+
const mcpResponse = await dispatchMcpRoutes(req, {
|
|
188
|
+
mcpRegistry: this.context.mcpRegistry,
|
|
189
|
+
roots: this.context.mcpConfigRoots,
|
|
190
|
+
parseJsonBody: (request) => this.parseJsonBody(request),
|
|
191
|
+
parseOptionalJsonBody: (request) => this.parseOptionalJsonBody(request),
|
|
192
|
+
requireAdmin: (request) => this.context.requireAdmin(request),
|
|
193
|
+
});
|
|
194
|
+
if (mcpResponse)
|
|
195
|
+
return mcpResponse;
|
|
196
|
+
}
|
|
185
197
|
if (url.pathname.startsWith('/api/homeassistant')) {
|
|
186
198
|
const homeGraphResponse = await this.getHomeGraphRoutes().handle(req);
|
|
187
199
|
if (homeGraphResponse)
|
|
@@ -21,9 +21,36 @@ export interface McpConfig {
|
|
|
21
21
|
servers: McpServerConfig[];
|
|
22
22
|
}
|
|
23
23
|
export type McpConfigRoots = Pick<ShellPathService, 'workingDirectory' | 'homeDirectory'>;
|
|
24
|
+
export type McpConfigScope = 'project' | 'global';
|
|
25
|
+
export interface McpConfigLocation {
|
|
26
|
+
readonly scope: McpConfigScope | 'external';
|
|
27
|
+
readonly kind: 'global-xdg' | 'global-dotdir' | 'claude-desktop' | 'project-mcp' | 'project-goodvibes';
|
|
28
|
+
readonly path: string;
|
|
29
|
+
readonly writable: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface McpServerConfigEntry {
|
|
32
|
+
readonly server: McpServerConfig;
|
|
33
|
+
readonly source: McpConfigLocation;
|
|
34
|
+
}
|
|
35
|
+
export interface McpEffectiveConfig {
|
|
36
|
+
readonly servers: readonly McpServerConfigEntry[];
|
|
37
|
+
readonly locations: readonly McpConfigLocation[];
|
|
38
|
+
}
|
|
39
|
+
export declare function getMcpConfigLocations(roots: McpConfigRoots): readonly McpConfigLocation[];
|
|
24
40
|
/**
|
|
25
41
|
* loadMcpConfig - Scan multiple locations in precedence order (later wins).
|
|
26
42
|
* Returns merged config from all found files. Returns empty config on failure.
|
|
27
43
|
*/
|
|
28
44
|
export declare function loadMcpConfig(roots: McpConfigRoots): McpConfig;
|
|
45
|
+
export declare function loadMcpEffectiveConfig(roots: McpConfigRoots): McpEffectiveConfig;
|
|
46
|
+
export declare function loadWritableMcpConfig(roots: McpConfigRoots, scope: McpConfigScope): McpConfig;
|
|
47
|
+
export declare function upsertMcpServerConfig(roots: McpConfigRoots, scope: McpConfigScope, server: McpServerConfig): {
|
|
48
|
+
readonly path: string;
|
|
49
|
+
readonly config: McpConfig;
|
|
50
|
+
};
|
|
51
|
+
export declare function removeMcpServerConfig(roots: McpConfigRoots, scope: McpConfigScope, serverName: string): {
|
|
52
|
+
readonly path: string;
|
|
53
|
+
readonly removed: boolean;
|
|
54
|
+
readonly config: McpConfig;
|
|
55
|
+
};
|
|
29
56
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzC,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxH,mEAAmE;IACnE,SAAS,CAAC,EAAE,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;IAChF,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,GAAG,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/platform/mcp/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzC,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxH,mEAAmE;IACnE,SAAS,CAAC,EAAE,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;IAChF,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,GAAG,eAAe,CAAC,CAAC;AAC1F,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,eAAe,GAAG,gBAAgB,GAAG,aAAa,GAAG,mBAAmB,CAAC;IACvG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAClD;AAgCD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,iBAAiB,EAAE,CAmCzF;AA4DD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAE9D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,kBAAkB,CAoBhF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS,CAG7F;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,eAAe,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAUvD;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,MAAM,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAQlF"}
|
|
@@ -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
|
*/
|