@toolplex/client 0.1.25 → 0.1.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/mcp-server/index.js +17 -0
- package/dist/mcp-server/policy/callToolObserver.d.ts +4 -0
- package/dist/mcp-server/policy/callToolObserver.js +6 -0
- package/dist/mcp-server/policy/installObserver.d.ts +5 -0
- package/dist/mcp-server/policy/installObserver.js +9 -0
- package/dist/mcp-server/registry.d.ts +10 -1
- package/dist/mcp-server/registry.js +17 -0
- package/dist/mcp-server/toolHandlers/initHandler.js +15 -0
- package/dist/mcp-server/toolHandlers/installServerHandler.js +18 -2
- package/dist/mcp-server/toolplexServer.js +2 -0
- package/dist/server-manager/serverManager.d.ts +6 -1
- package/dist/server-manager/serverManager.js +56 -4
- package/dist/shared/mcpServerTypes.d.ts +12 -0
- package/dist/src/mcp-server/policy/callToolObserver.js +6 -0
- package/dist/src/mcp-server/policy/installObserver.js +9 -0
- package/dist/src/mcp-server/registry.js +17 -0
- package/dist/src/mcp-server/toolHandlers/initHandler.js +15 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/mcp-server/index.js
CHANGED
|
@@ -20,6 +20,22 @@ const bundledDependencies = {
|
|
|
20
20
|
uvx: process.env.TOOLPLEX_UVX_PATH,
|
|
21
21
|
git: process.env.TOOLPLEX_GIT_PATH,
|
|
22
22
|
};
|
|
23
|
+
// Parse session resume history for restored chat sessions
|
|
24
|
+
// This allows the enforcement layer to validate save_playbook and submit_feedback
|
|
25
|
+
// based on historical tool usage from the database
|
|
26
|
+
let sessionResumeHistory;
|
|
27
|
+
if (process.env.TOOLPLEX_SESSION_RESUME_HISTORY) {
|
|
28
|
+
try {
|
|
29
|
+
sessionResumeHistory = JSON.parse(process.env.TOOLPLEX_SESSION_RESUME_HISTORY);
|
|
30
|
+
FileLogger.info(`Parsed session resume history - ` +
|
|
31
|
+
`${sessionResumeHistory?.tool_calls.length || 0} tool calls, ` +
|
|
32
|
+
`${sessionResumeHistory?.installs.length || 0} installs, ` +
|
|
33
|
+
`${sessionResumeHistory?.uninstalls.length || 0} uninstalls`);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
FileLogger.warn(`Failed to parse session resume history: ${error}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
23
39
|
if (!apiKey) {
|
|
24
40
|
process.exit(1);
|
|
25
41
|
}
|
|
@@ -30,6 +46,7 @@ const config = {
|
|
|
30
46
|
clientName,
|
|
31
47
|
logLevel,
|
|
32
48
|
bundledDependencies,
|
|
49
|
+
sessionResumeHistory,
|
|
33
50
|
};
|
|
34
51
|
serve(config).catch(() => {
|
|
35
52
|
process.exit(1);
|
|
@@ -2,6 +2,10 @@ declare class CallToolObserver {
|
|
|
2
2
|
private serverToolCalls;
|
|
3
3
|
constructor();
|
|
4
4
|
recordCall(serverId: string, toolName: string): void;
|
|
5
|
+
seedHistory(history: Array<{
|
|
6
|
+
server_id: string;
|
|
7
|
+
tool_name: string;
|
|
8
|
+
}>): void;
|
|
5
9
|
wasServerCalled(serverId: string): boolean;
|
|
6
10
|
wasToolCalled(serverId: string, toolName: string): boolean;
|
|
7
11
|
clear(): void;
|
|
@@ -9,6 +9,12 @@ class CallToolObserver {
|
|
|
9
9
|
}
|
|
10
10
|
this.serverToolCalls.get(serverId).add(toolName);
|
|
11
11
|
}
|
|
12
|
+
// Seed the observer with historical tool calls (for session resume)
|
|
13
|
+
seedHistory(history) {
|
|
14
|
+
history.forEach(({ server_id, tool_name }) => {
|
|
15
|
+
this.recordCall(server_id, tool_name);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
12
18
|
// Check if a server was called at all
|
|
13
19
|
wasServerCalled(serverId) {
|
|
14
20
|
return (this.serverToolCalls.has(serverId) &&
|
|
@@ -3,6 +3,11 @@ declare class InstallObserver {
|
|
|
3
3
|
constructor();
|
|
4
4
|
recordInstall(serverId: string): void;
|
|
5
5
|
recordUninstall(serverId: string): void;
|
|
6
|
+
seedHistory(installs: Array<{
|
|
7
|
+
server_id: string;
|
|
8
|
+
}>, uninstalls: Array<{
|
|
9
|
+
server_id: string;
|
|
10
|
+
}>): void;
|
|
6
11
|
wasServerInstalled(serverId: string): boolean;
|
|
7
12
|
wasServerUninstalled(serverId: string): boolean;
|
|
8
13
|
clear(): void;
|
|
@@ -10,6 +10,15 @@ class InstallObserver {
|
|
|
10
10
|
recordUninstall(serverId) {
|
|
11
11
|
this.recordAction(serverId, "uninstall");
|
|
12
12
|
}
|
|
13
|
+
// Seed the observer with historical install/uninstall actions (for session resume)
|
|
14
|
+
seedHistory(installs, uninstalls) {
|
|
15
|
+
installs.forEach(({ server_id }) => {
|
|
16
|
+
this.recordInstall(server_id);
|
|
17
|
+
});
|
|
18
|
+
uninstalls.forEach(({ server_id }) => {
|
|
19
|
+
this.recordUninstall(server_id);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
13
22
|
// Check if a server has been installed
|
|
14
23
|
wasServerInstalled(serverId) {
|
|
15
24
|
return (this.serverInstallActions.has(serverId) &&
|
|
@@ -6,7 +6,7 @@ import { PromptsCache } from "./promptsCache.js";
|
|
|
6
6
|
import { ToolDefinitionsCache } from "./toolDefinitionsCache.js";
|
|
7
7
|
import { ServersCache } from "./serversCache.js";
|
|
8
8
|
import { PolicyEnforcer } from "./policy/policyEnforcer.js";
|
|
9
|
-
import { BundledDependencies } from "../shared/mcpServerTypes.js";
|
|
9
|
+
import { BundledDependencies, ToolplexServerConfig } from "../shared/mcpServerTypes.js";
|
|
10
10
|
/**
|
|
11
11
|
* In-memory global registry for the ToolPlex client.
|
|
12
12
|
* Maintains singleton instances of core services and clients used throughout the application.
|
|
@@ -21,6 +21,7 @@ declare class Registry {
|
|
|
21
21
|
private static _serversCache;
|
|
22
22
|
private static _policyEnforcer;
|
|
23
23
|
private static _bundledDependencies;
|
|
24
|
+
private static _serverConfig;
|
|
24
25
|
static init(clientContext: ClientContext): Promise<void>;
|
|
25
26
|
static getClientContext(): ClientContext;
|
|
26
27
|
static getToolplexApiService(): ToolplexApiService;
|
|
@@ -46,6 +47,14 @@ declare class Registry {
|
|
|
46
47
|
* Returns undefined if the dependency is not available.
|
|
47
48
|
*/
|
|
48
49
|
static getBundledDependencyPath(depName: "node" | "python" | "git" | "uvx" | "npx"): string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Set the server configuration (includes session resume history).
|
|
52
|
+
*/
|
|
53
|
+
static setServerConfig(config: ToolplexServerConfig): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get the server configuration.
|
|
56
|
+
*/
|
|
57
|
+
static getServerConfig(): ToolplexServerConfig;
|
|
49
58
|
static reset(): void;
|
|
50
59
|
}
|
|
51
60
|
export default Registry;
|
|
@@ -101,6 +101,21 @@ class Registry {
|
|
|
101
101
|
static getBundledDependencyPath(depName) {
|
|
102
102
|
return this._bundledDependencies[depName];
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Set the server configuration (includes session resume history).
|
|
106
|
+
*/
|
|
107
|
+
static setServerConfig(config) {
|
|
108
|
+
this._serverConfig = config;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the server configuration.
|
|
112
|
+
*/
|
|
113
|
+
static getServerConfig() {
|
|
114
|
+
if (!this._serverConfig) {
|
|
115
|
+
throw new Error("ServerConfig not set in Registry");
|
|
116
|
+
}
|
|
117
|
+
return this._serverConfig;
|
|
118
|
+
}
|
|
104
119
|
static reset() {
|
|
105
120
|
this._clientContext = null;
|
|
106
121
|
this._toolplexApiService = null;
|
|
@@ -120,6 +135,7 @@ class Registry {
|
|
|
120
135
|
}
|
|
121
136
|
this._policyEnforcer = null;
|
|
122
137
|
this._bundledDependencies = {};
|
|
138
|
+
this._serverConfig = null;
|
|
123
139
|
}
|
|
124
140
|
}
|
|
125
141
|
Registry._clientContext = null;
|
|
@@ -131,4 +147,5 @@ Registry._toolDefinitionsCache = null;
|
|
|
131
147
|
Registry._serversCache = null;
|
|
132
148
|
Registry._policyEnforcer = null;
|
|
133
149
|
Registry._bundledDependencies = {};
|
|
150
|
+
Registry._serverConfig = null;
|
|
134
151
|
export default Registry;
|
|
@@ -100,6 +100,21 @@ export async function handleInitialize(params) {
|
|
|
100
100
|
promptsCache.init(processedPrompts);
|
|
101
101
|
// Init PolicyEnforce after setting permissions and flags
|
|
102
102
|
policyEnforcer.init(clientContext);
|
|
103
|
+
// Seed enforcement history if provided (for restored sessions)
|
|
104
|
+
const serverConfig = Registry.getServerConfig();
|
|
105
|
+
if (serverConfig.sessionResumeHistory) {
|
|
106
|
+
const { tool_calls, installs, uninstalls } = serverConfig.sessionResumeHistory;
|
|
107
|
+
await logger.info(`Seeding enforcement history from restored session - ` +
|
|
108
|
+
`${tool_calls.length} tool calls, ${installs.length} installs, ${uninstalls.length} uninstalls`);
|
|
109
|
+
const callToolObserver = policyEnforcer.getCallToolObserver();
|
|
110
|
+
callToolObserver.seedHistory(tool_calls);
|
|
111
|
+
const installObserver = policyEnforcer.getInstallObserver();
|
|
112
|
+
installObserver.seedHistory(installs, uninstalls);
|
|
113
|
+
await logger.info("Enforcement history seeded successfully");
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
await logger.debug("No session resume history provided (new session)");
|
|
117
|
+
}
|
|
103
118
|
const allSucceeded = serverManagerInitResults.succeeded;
|
|
104
119
|
const allFailures = serverManagerInitResults.failures;
|
|
105
120
|
// Initialize the serversCache with the succeeded servers
|
|
@@ -117,8 +117,24 @@ export async function handleInstallServer(params) {
|
|
|
117
117
|
}
|
|
118
118
|
// Validate server ID format
|
|
119
119
|
validateServerIdOrThrow(server_id);
|
|
120
|
-
// Validate
|
|
121
|
-
if (config.
|
|
120
|
+
// Validate stdio transport configuration early to avoid timeouts
|
|
121
|
+
if (config.transport === "stdio") {
|
|
122
|
+
// Validate that command is provided
|
|
123
|
+
if (!config.command) {
|
|
124
|
+
throw new Error("Command is required for stdio transport");
|
|
125
|
+
}
|
|
126
|
+
// Validate command is installed
|
|
127
|
+
await RuntimeCheck.validateCommandOrThrow(config.command);
|
|
128
|
+
// Check that args is provided and not empty for package managers
|
|
129
|
+
// Package managers like npx, uvx, pnpm dlx, etc. require a package name as first arg
|
|
130
|
+
const command = config.command.toLowerCase();
|
|
131
|
+
const requiresPackageName = ["npx", "uvx", "pnpm", "yarn"].some((pm) => command.includes(pm));
|
|
132
|
+
if (requiresPackageName && (!config.args || config.args.length === 0)) {
|
|
133
|
+
throw new Error(`Package manager command '${config.command}' requires args to specify package name. Received args: ${config.args ? "[]" : "undefined"}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (config.command) {
|
|
137
|
+
// For non-stdio transports, still validate command if provided
|
|
122
138
|
await RuntimeCheck.validateCommandOrThrow(config.command);
|
|
123
139
|
}
|
|
124
140
|
// Check if server is disallowed using policy enforcer
|
|
@@ -39,6 +39,8 @@ export async function serve(config) {
|
|
|
39
39
|
Registry.setBundledDependencies(config.bundledDependencies);
|
|
40
40
|
await logger.debug(`Bundled dependencies registered: ${JSON.stringify(config.bundledDependencies)}`);
|
|
41
41
|
}
|
|
42
|
+
// Store server config in Registry (includes session resume history)
|
|
43
|
+
Registry.setServerConfig(config);
|
|
42
44
|
await logger.info(`Starting Toolplex server in ${config.dev ? "development" : "production"} mode`);
|
|
43
45
|
const server = new Server({
|
|
44
46
|
name: "toolplex-server",
|
|
@@ -12,12 +12,17 @@ export declare class ServerManager {
|
|
|
12
12
|
private config;
|
|
13
13
|
private installationPromises;
|
|
14
14
|
private configLock;
|
|
15
|
+
private static readonly MAX_STDERR_LINES;
|
|
15
16
|
constructor();
|
|
16
17
|
private loadConfig;
|
|
17
18
|
private saveConfig;
|
|
18
19
|
initialize(): Promise<InitializeResult>;
|
|
19
20
|
getServerName(serverId: string): Promise<string>;
|
|
20
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Helper to attach stderr listener as soon as transport starts
|
|
23
|
+
*/
|
|
24
|
+
private attachStderrListener;
|
|
25
|
+
connectWithHandshakeTimeout(client: Client, transport: SSEClientTransport | StdioClientTransport, ms?: number, stderrBuffer?: string[], serverId?: string): Promise<{
|
|
21
26
|
tools?: Tool[];
|
|
22
27
|
}>;
|
|
23
28
|
install(serverId: string, serverName: string, description: string, config: ServerConfig): Promise<void>;
|
|
@@ -136,13 +136,51 @@ export class ServerManager {
|
|
|
136
136
|
await logger.debug(`Getting name for server ${serverId}`);
|
|
137
137
|
return this.serverNames.get(serverId) || serverId;
|
|
138
138
|
}
|
|
139
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Helper to attach stderr listener as soon as transport starts
|
|
141
|
+
*/
|
|
142
|
+
async attachStderrListener(transport, serverId, stderrBuffer, maxLines) {
|
|
143
|
+
// Poll for stderr availability (it becomes available after transport.start())
|
|
144
|
+
const maxAttempts = 100; // 1 second total
|
|
145
|
+
const pollInterval = 10; // 10ms between checks
|
|
146
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
147
|
+
if (transport.stderr) {
|
|
148
|
+
transport.stderr.on("data", (chunk) => {
|
|
149
|
+
const lines = chunk
|
|
150
|
+
.toString()
|
|
151
|
+
.split("\n")
|
|
152
|
+
.filter((l) => l.trim());
|
|
153
|
+
stderrBuffer.push(...lines);
|
|
154
|
+
// Keep only the last maxLines to prevent memory issues
|
|
155
|
+
if (stderrBuffer.length > maxLines) {
|
|
156
|
+
stderrBuffer.splice(0, stderrBuffer.length - maxLines);
|
|
157
|
+
}
|
|
158
|
+
// Also log stderr in real-time for debugging
|
|
159
|
+
lines.forEach((line) => {
|
|
160
|
+
logger.debug(`[${serverId} stderr] ${line}`);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
166
|
+
}
|
|
167
|
+
// If stderr never became available, that's okay (might be SSE transport)
|
|
168
|
+
}
|
|
169
|
+
async connectWithHandshakeTimeout(client, transport, ms = 60000, stderrBuffer, serverId) {
|
|
140
170
|
let connectTimeout;
|
|
141
171
|
let listToolsTimeout;
|
|
142
172
|
try {
|
|
173
|
+
// Start stderr monitoring in parallel for stdio transports
|
|
174
|
+
const stderrMonitoring = transport instanceof StdioClientTransport && stderrBuffer && serverId
|
|
175
|
+
? this.attachStderrListener(transport, serverId, stderrBuffer, ServerManager.MAX_STDERR_LINES)
|
|
176
|
+
: Promise.resolve();
|
|
143
177
|
// Race connect() with timeout
|
|
144
178
|
await Promise.race([
|
|
145
|
-
|
|
179
|
+
(async () => {
|
|
180
|
+
await client.connect(transport);
|
|
181
|
+
// Ensure stderr listener is attached after connection starts
|
|
182
|
+
await stderrMonitoring;
|
|
183
|
+
})(),
|
|
146
184
|
new Promise((_, reject) => {
|
|
147
185
|
connectTimeout = setTimeout(() => reject(new Error(`connect() timed out in ${ms} ms`)), ms);
|
|
148
186
|
}),
|
|
@@ -195,6 +233,7 @@ export class ServerManager {
|
|
|
195
233
|
await this.removeServer(serverId);
|
|
196
234
|
}
|
|
197
235
|
let transport;
|
|
236
|
+
const stderrBuffer = [];
|
|
198
237
|
if (config.transport === "sse") {
|
|
199
238
|
if (!config.url)
|
|
200
239
|
throw new Error("URL is required for SSE transport");
|
|
@@ -226,7 +265,7 @@ export class ServerManager {
|
|
|
226
265
|
}
|
|
227
266
|
const client = new Client({ name: serverId, version: "1.0.0" }, { capabilities: { prompts: {}, resources: {}, tools: {} } });
|
|
228
267
|
try {
|
|
229
|
-
const toolsResponse = await this.connectWithHandshakeTimeout(client, transport, 60000);
|
|
268
|
+
const toolsResponse = await this.connectWithHandshakeTimeout(client, transport, 60000, stderrBuffer, serverId);
|
|
230
269
|
const tools = toolsResponse.tools || [];
|
|
231
270
|
this.sessions.set(serverId, client);
|
|
232
271
|
this.tools.set(serverId, tools);
|
|
@@ -258,7 +297,18 @@ export class ServerManager {
|
|
|
258
297
|
await logger.warn(`Failed to close transport during cleanup: ${closeErr}`);
|
|
259
298
|
}
|
|
260
299
|
}
|
|
261
|
-
|
|
300
|
+
// Enhance error message with stderr output if available
|
|
301
|
+
const baseError = err instanceof Error ? err.message : String(err);
|
|
302
|
+
let enhancedError = baseError;
|
|
303
|
+
if (stderrBuffer.length > 0) {
|
|
304
|
+
const stderrPreview = stderrBuffer.join("\n");
|
|
305
|
+
enhancedError = `${baseError}\n\nServer stderr output:\n${stderrPreview}`;
|
|
306
|
+
await logger.error(`Installation failed for ${serverId}. Error: ${baseError}. Stderr: ${stderrPreview}`);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
await logger.error(`Installation failed for ${serverId}: ${baseError}`);
|
|
310
|
+
}
|
|
311
|
+
throw new Error(enhancedError);
|
|
262
312
|
}
|
|
263
313
|
}
|
|
264
314
|
async callTool(serverId, toolName,
|
|
@@ -411,3 +461,5 @@ export class ServerManager {
|
|
|
411
461
|
this.installationPromises.clear();
|
|
412
462
|
}
|
|
413
463
|
}
|
|
464
|
+
// Maximum number of stderr lines to capture during installation
|
|
465
|
+
ServerManager.MAX_STDERR_LINES = 50;
|
|
@@ -21,6 +21,18 @@ export interface ToolplexServerConfig {
|
|
|
21
21
|
clientName: string;
|
|
22
22
|
logLevel: LogLevel;
|
|
23
23
|
bundledDependencies?: BundledDependencies;
|
|
24
|
+
sessionResumeHistory?: {
|
|
25
|
+
tool_calls: Array<{
|
|
26
|
+
server_id: string;
|
|
27
|
+
tool_name: string;
|
|
28
|
+
}>;
|
|
29
|
+
installs: Array<{
|
|
30
|
+
server_id: string;
|
|
31
|
+
}>;
|
|
32
|
+
uninstalls: Array<{
|
|
33
|
+
server_id: string;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
24
36
|
}
|
|
25
37
|
export declare const TransportTypeSchema: z.ZodEnum<["stdio", "sse"]>;
|
|
26
38
|
export type TransportType = z.infer<typeof TransportTypeSchema>;
|
|
@@ -9,6 +9,12 @@ class CallToolObserver {
|
|
|
9
9
|
}
|
|
10
10
|
this.serverToolCalls.get(serverId).add(toolName);
|
|
11
11
|
}
|
|
12
|
+
// Seed the observer with historical tool calls (for session resume)
|
|
13
|
+
seedHistory(history) {
|
|
14
|
+
history.forEach(({ server_id, tool_name }) => {
|
|
15
|
+
this.recordCall(server_id, tool_name);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
12
18
|
// Check if a server was called at all
|
|
13
19
|
wasServerCalled(serverId) {
|
|
14
20
|
return (this.serverToolCalls.has(serverId) &&
|
|
@@ -10,6 +10,15 @@ class InstallObserver {
|
|
|
10
10
|
recordUninstall(serverId) {
|
|
11
11
|
this.recordAction(serverId, "uninstall");
|
|
12
12
|
}
|
|
13
|
+
// Seed the observer with historical install/uninstall actions (for session resume)
|
|
14
|
+
seedHistory(installs, uninstalls) {
|
|
15
|
+
installs.forEach(({ server_id }) => {
|
|
16
|
+
this.recordInstall(server_id);
|
|
17
|
+
});
|
|
18
|
+
uninstalls.forEach(({ server_id }) => {
|
|
19
|
+
this.recordUninstall(server_id);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
13
22
|
// Check if a server has been installed
|
|
14
23
|
wasServerInstalled(serverId) {
|
|
15
24
|
return (this.serverInstallActions.has(serverId) &&
|
|
@@ -101,6 +101,21 @@ class Registry {
|
|
|
101
101
|
static getBundledDependencyPath(depName) {
|
|
102
102
|
return this._bundledDependencies[depName];
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Set the server configuration (includes session resume history).
|
|
106
|
+
*/
|
|
107
|
+
static setServerConfig(config) {
|
|
108
|
+
this._serverConfig = config;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the server configuration.
|
|
112
|
+
*/
|
|
113
|
+
static getServerConfig() {
|
|
114
|
+
if (!this._serverConfig) {
|
|
115
|
+
throw new Error("ServerConfig not set in Registry");
|
|
116
|
+
}
|
|
117
|
+
return this._serverConfig;
|
|
118
|
+
}
|
|
104
119
|
static reset() {
|
|
105
120
|
this._clientContext = null;
|
|
106
121
|
this._toolplexApiService = null;
|
|
@@ -120,6 +135,7 @@ class Registry {
|
|
|
120
135
|
}
|
|
121
136
|
this._policyEnforcer = null;
|
|
122
137
|
this._bundledDependencies = {};
|
|
138
|
+
this._serverConfig = null;
|
|
123
139
|
}
|
|
124
140
|
}
|
|
125
141
|
Registry._clientContext = null;
|
|
@@ -131,4 +147,5 @@ Registry._toolDefinitionsCache = null;
|
|
|
131
147
|
Registry._serversCache = null;
|
|
132
148
|
Registry._policyEnforcer = null;
|
|
133
149
|
Registry._bundledDependencies = {};
|
|
150
|
+
Registry._serverConfig = null;
|
|
134
151
|
export default Registry;
|
|
@@ -100,6 +100,21 @@ export async function handleInitialize(params) {
|
|
|
100
100
|
promptsCache.init(processedPrompts);
|
|
101
101
|
// Init PolicyEnforce after setting permissions and flags
|
|
102
102
|
policyEnforcer.init(clientContext);
|
|
103
|
+
// Seed enforcement history if provided (for restored sessions)
|
|
104
|
+
const serverConfig = Registry.getServerConfig();
|
|
105
|
+
if (serverConfig.sessionResumeHistory) {
|
|
106
|
+
const { tool_calls, installs, uninstalls } = serverConfig.sessionResumeHistory;
|
|
107
|
+
await logger.info(`Seeding enforcement history from restored session - ` +
|
|
108
|
+
`${tool_calls.length} tool calls, ${installs.length} installs, ${uninstalls.length} uninstalls`);
|
|
109
|
+
const callToolObserver = policyEnforcer.getCallToolObserver();
|
|
110
|
+
callToolObserver.seedHistory(tool_calls);
|
|
111
|
+
const installObserver = policyEnforcer.getInstallObserver();
|
|
112
|
+
installObserver.seedHistory(installs, uninstalls);
|
|
113
|
+
await logger.info("Enforcement history seeded successfully");
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
await logger.debug("No session resume history provided (new session)");
|
|
117
|
+
}
|
|
103
118
|
const allSucceeded = serverManagerInitResults.succeeded;
|
|
104
119
|
const allFailures = serverManagerInitResults.failures;
|
|
105
120
|
// Initialize the serversCache with the succeeded servers
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "0.1.
|
|
1
|
+
export declare const version = "0.1.27";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.1.
|
|
1
|
+
export const version = '0.1.27';
|