@mcpc-tech/cli 0.1.31 → 0.1.32
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/bin/mcpc.cjs +299 -9
- package/bin/mcpc.mjs +299 -9
- package/package.json +1 -1
package/bin/mcpc.cjs
CHANGED
|
@@ -7794,7 +7794,9 @@ ${JSON.stringify(cleanedSchema, null, 2)}
|
|
|
7794
7794
|
tool: tool2
|
|
7795
7795
|
});
|
|
7796
7796
|
try {
|
|
7797
|
-
const result = await this.server.callTool(tool2, toolArgs
|
|
7797
|
+
const result = await this.server.callTool(tool2, toolArgs, {
|
|
7798
|
+
agentName: this.name
|
|
7799
|
+
});
|
|
7798
7800
|
const callToolResult = result ?? {
|
|
7799
7801
|
content: []
|
|
7800
7802
|
};
|
|
@@ -8829,7 +8831,7 @@ function isValidPlugin(plugin) {
|
|
|
8829
8831
|
if (!p2.name || typeof p2.name !== "string" || p2.name.trim() === "") {
|
|
8830
8832
|
return false;
|
|
8831
8833
|
}
|
|
8832
|
-
const hasHook = typeof p2.configureServer === "function" || typeof p2.composeStart === "function" || typeof p2.transformTool === "function" || typeof p2.finalizeComposition === "function" || typeof p2.registerAgentTool === "function" || typeof p2.composeEnd === "function" || typeof p2.transformInput === "function" || typeof p2.transformOutput === "function" || typeof p2.dispose === "function";
|
|
8834
|
+
const hasHook = typeof p2.configureServer === "function" || typeof p2.composeStart === "function" || typeof p2.transformTool === "function" || typeof p2.finalizeComposition === "function" || typeof p2.registerAgentTool === "function" || typeof p2.composeEnd === "function" || typeof p2.transformInput === "function" || typeof p2.transformOutput === "function" || typeof p2.beforeToolExecute === "function" || typeof p2.afterToolExecute === "function" || typeof p2.dispose === "function";
|
|
8833
8835
|
if (!hasHook) return false;
|
|
8834
8836
|
if (p2.enforce && p2.enforce !== "pre" && p2.enforce !== "post") {
|
|
8835
8837
|
return false;
|
|
@@ -9136,6 +9138,113 @@ var PluginManager = class {
|
|
|
9136
9138
|
}
|
|
9137
9139
|
return false;
|
|
9138
9140
|
}
|
|
9141
|
+
// === Tool Execution Lifecycle Hooks ===
|
|
9142
|
+
/**
|
|
9143
|
+
* Trigger beforeToolExecute hooks for all applicable plugins
|
|
9144
|
+
* Returns the combined result from all plugins
|
|
9145
|
+
*
|
|
9146
|
+
* Hook execution order:
|
|
9147
|
+
* 1. 'pre' enforced plugins first
|
|
9148
|
+
* 2. Normal plugins (no enforce)
|
|
9149
|
+
* 3. 'post' enforced plugins last
|
|
9150
|
+
*
|
|
9151
|
+
* If any plugin returns skipExecution=true, execution is skipped
|
|
9152
|
+
* and the result from that plugin is used.
|
|
9153
|
+
*/
|
|
9154
|
+
async triggerBeforeToolExecute(context2) {
|
|
9155
|
+
const beforePlugins = this.plugins.filter((p2) => p2.beforeToolExecute);
|
|
9156
|
+
if (beforePlugins.length === 0) {
|
|
9157
|
+
return void 0;
|
|
9158
|
+
}
|
|
9159
|
+
const sortedPlugins = sortPluginsByOrder(beforePlugins);
|
|
9160
|
+
let currentArgs = context2.args;
|
|
9161
|
+
let combinedMetadata = {};
|
|
9162
|
+
for (const plugin of sortedPlugins) {
|
|
9163
|
+
if (plugin.beforeToolExecute) {
|
|
9164
|
+
try {
|
|
9165
|
+
const result = await plugin.beforeToolExecute({
|
|
9166
|
+
...context2,
|
|
9167
|
+
args: currentArgs
|
|
9168
|
+
});
|
|
9169
|
+
if (result) {
|
|
9170
|
+
if (result.metadata) {
|
|
9171
|
+
combinedMetadata = {
|
|
9172
|
+
...combinedMetadata,
|
|
9173
|
+
...result.metadata
|
|
9174
|
+
};
|
|
9175
|
+
}
|
|
9176
|
+
if (result.skipExecution) {
|
|
9177
|
+
return {
|
|
9178
|
+
skipExecution: true,
|
|
9179
|
+
result: result.result,
|
|
9180
|
+
metadata: combinedMetadata
|
|
9181
|
+
};
|
|
9182
|
+
}
|
|
9183
|
+
if (result.modifiedArgs !== void 0) {
|
|
9184
|
+
currentArgs = result.modifiedArgs;
|
|
9185
|
+
}
|
|
9186
|
+
}
|
|
9187
|
+
} catch (error) {
|
|
9188
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
9189
|
+
await this.logger.error(`Plugin "${plugin.name}" beforeToolExecute failed for "${context2.toolName}": ${errorMsg}`);
|
|
9190
|
+
}
|
|
9191
|
+
}
|
|
9192
|
+
}
|
|
9193
|
+
if (currentArgs !== context2.args) {
|
|
9194
|
+
return {
|
|
9195
|
+
modifiedArgs: currentArgs,
|
|
9196
|
+
metadata: Object.keys(combinedMetadata).length > 0 ? combinedMetadata : void 0
|
|
9197
|
+
};
|
|
9198
|
+
}
|
|
9199
|
+
if (Object.keys(combinedMetadata).length > 0) {
|
|
9200
|
+
return {
|
|
9201
|
+
metadata: combinedMetadata
|
|
9202
|
+
};
|
|
9203
|
+
}
|
|
9204
|
+
return void 0;
|
|
9205
|
+
}
|
|
9206
|
+
/**
|
|
9207
|
+
* Trigger afterToolExecute hooks for all applicable plugins
|
|
9208
|
+
* Returns the final result after all plugins have processed it
|
|
9209
|
+
*/
|
|
9210
|
+
async triggerAfterToolExecute(context2) {
|
|
9211
|
+
const afterPlugins = this.plugins.filter((p2) => p2.afterToolExecute);
|
|
9212
|
+
if (afterPlugins.length === 0) {
|
|
9213
|
+
return void 0;
|
|
9214
|
+
}
|
|
9215
|
+
const sortedPlugins = sortPluginsByOrder(afterPlugins);
|
|
9216
|
+
let currentResult = context2.result;
|
|
9217
|
+
let markAsError = context2.isError;
|
|
9218
|
+
for (const plugin of sortedPlugins) {
|
|
9219
|
+
if (plugin.afterToolExecute) {
|
|
9220
|
+
try {
|
|
9221
|
+
const result = await plugin.afterToolExecute({
|
|
9222
|
+
...context2,
|
|
9223
|
+
result: currentResult,
|
|
9224
|
+
isError: markAsError
|
|
9225
|
+
});
|
|
9226
|
+
if (result) {
|
|
9227
|
+
if (result.modifiedResult !== void 0) {
|
|
9228
|
+
currentResult = result.modifiedResult;
|
|
9229
|
+
}
|
|
9230
|
+
if (result.markAsError !== void 0) {
|
|
9231
|
+
markAsError = result.markAsError;
|
|
9232
|
+
}
|
|
9233
|
+
}
|
|
9234
|
+
} catch (error) {
|
|
9235
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
9236
|
+
await this.logger.error(`Plugin "${plugin.name}" afterToolExecute failed for "${context2.toolName}": ${errorMsg}`);
|
|
9237
|
+
}
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9240
|
+
if (currentResult !== context2.result || markAsError !== context2.isError) {
|
|
9241
|
+
return {
|
|
9242
|
+
modifiedResult: currentResult,
|
|
9243
|
+
markAsError
|
|
9244
|
+
};
|
|
9245
|
+
}
|
|
9246
|
+
return void 0;
|
|
9247
|
+
}
|
|
9139
9248
|
/**
|
|
9140
9249
|
* Dispose all plugins and cleanup resources
|
|
9141
9250
|
*/
|
|
@@ -9366,6 +9475,24 @@ var ToolManager = class {
|
|
|
9366
9475
|
}
|
|
9367
9476
|
return composedTools;
|
|
9368
9477
|
}
|
|
9478
|
+
/**
|
|
9479
|
+
* Get a single tool as ComposedTool object by name
|
|
9480
|
+
*/
|
|
9481
|
+
getComposedTool(name) {
|
|
9482
|
+
const tool2 = this.toolRegistry.get(name);
|
|
9483
|
+
if (!tool2) {
|
|
9484
|
+
return void 0;
|
|
9485
|
+
}
|
|
9486
|
+
return {
|
|
9487
|
+
name,
|
|
9488
|
+
description: tool2.description,
|
|
9489
|
+
inputSchema: tool2.schema ?? {
|
|
9490
|
+
type: "object",
|
|
9491
|
+
properties: {}
|
|
9492
|
+
},
|
|
9493
|
+
execute: tool2.callback
|
|
9494
|
+
};
|
|
9495
|
+
}
|
|
9369
9496
|
};
|
|
9370
9497
|
|
|
9371
9498
|
// __mcpc__cli_latest/node_modules/@jsr/mcpc__core/src/utils/common/schema.js
|
|
@@ -9566,9 +9693,81 @@ var ComposableMCPServer = class extends Server {
|
|
|
9566
9693
|
if (!handler) {
|
|
9567
9694
|
throw new Error(`Tool ${toolName} not found`);
|
|
9568
9695
|
}
|
|
9569
|
-
const
|
|
9570
|
-
const
|
|
9571
|
-
|
|
9696
|
+
const toolDefinition = this.toolManager.getComposedTool(toolName);
|
|
9697
|
+
const startTime = Date.now();
|
|
9698
|
+
const beforeContext = {
|
|
9699
|
+
toolName,
|
|
9700
|
+
args,
|
|
9701
|
+
server: this,
|
|
9702
|
+
toolDefinition,
|
|
9703
|
+
isInternalCall: false
|
|
9704
|
+
};
|
|
9705
|
+
const beforeResult = await this.pluginManager.triggerBeforeToolExecute(beforeContext);
|
|
9706
|
+
if (beforeResult?.skipExecution) {
|
|
9707
|
+
const executionTimeMs2 = Date.now() - startTime;
|
|
9708
|
+
const afterContext2 = {
|
|
9709
|
+
toolName,
|
|
9710
|
+
args,
|
|
9711
|
+
result: beforeResult.result,
|
|
9712
|
+
server: this,
|
|
9713
|
+
wasSkipped: true,
|
|
9714
|
+
executionTimeMs: executionTimeMs2,
|
|
9715
|
+
isError: false,
|
|
9716
|
+
metadata: beforeResult.metadata,
|
|
9717
|
+
isInternalCall: false
|
|
9718
|
+
};
|
|
9719
|
+
const afterResult2 = await this.pluginManager.triggerAfterToolExecute(afterContext2);
|
|
9720
|
+
let finalResult = afterResult2?.modifiedResult ?? beforeResult.result;
|
|
9721
|
+
if (afterResult2?.markAsError && finalResult) {
|
|
9722
|
+
finalResult = {
|
|
9723
|
+
...finalResult,
|
|
9724
|
+
isError: true
|
|
9725
|
+
};
|
|
9726
|
+
}
|
|
9727
|
+
return finalResult;
|
|
9728
|
+
}
|
|
9729
|
+
const effectiveArgs = beforeResult?.modifiedArgs ?? args;
|
|
9730
|
+
const processedArgs = await this.applyPluginTransforms(toolName, effectiveArgs, "input");
|
|
9731
|
+
let result = await handler(processedArgs, extra);
|
|
9732
|
+
const isError = !!result?.isError;
|
|
9733
|
+
result = await this.applyPluginTransforms(toolName, result, "output", args);
|
|
9734
|
+
if (isError && result && !("isError" in result)) {
|
|
9735
|
+
result = {
|
|
9736
|
+
...result,
|
|
9737
|
+
isError: true
|
|
9738
|
+
};
|
|
9739
|
+
}
|
|
9740
|
+
const executionTimeMs = Date.now() - startTime;
|
|
9741
|
+
const afterContext = {
|
|
9742
|
+
toolName,
|
|
9743
|
+
args,
|
|
9744
|
+
result,
|
|
9745
|
+
server: this,
|
|
9746
|
+
wasSkipped: false,
|
|
9747
|
+
executionTimeMs,
|
|
9748
|
+
isError,
|
|
9749
|
+
metadata: beforeResult?.metadata,
|
|
9750
|
+
isInternalCall: false
|
|
9751
|
+
};
|
|
9752
|
+
const afterResult = await this.pluginManager.triggerAfterToolExecute(afterContext);
|
|
9753
|
+
if (afterResult?.modifiedResult !== void 0) {
|
|
9754
|
+
let finalResult = afterResult.modifiedResult;
|
|
9755
|
+
const hasExplicitIsError = finalResult && "isError" in finalResult;
|
|
9756
|
+
if (!hasExplicitIsError && afterResult.markAsError && finalResult) {
|
|
9757
|
+
finalResult = {
|
|
9758
|
+
...finalResult,
|
|
9759
|
+
isError: true
|
|
9760
|
+
};
|
|
9761
|
+
}
|
|
9762
|
+
return finalResult;
|
|
9763
|
+
}
|
|
9764
|
+
if (afterResult?.markAsError && result) {
|
|
9765
|
+
return {
|
|
9766
|
+
...result,
|
|
9767
|
+
isError: true
|
|
9768
|
+
};
|
|
9769
|
+
}
|
|
9770
|
+
return result;
|
|
9572
9771
|
});
|
|
9573
9772
|
this.setRequestHandler(SetLevelRequestSchema, (request) => {
|
|
9574
9773
|
const { level } = request.params;
|
|
@@ -9590,8 +9789,9 @@ var ComposableMCPServer = class extends Server {
|
|
|
9590
9789
|
}
|
|
9591
9790
|
/**
|
|
9592
9791
|
* Call any registered tool directly, whether it's public or internal
|
|
9792
|
+
* Supports tool execution lifecycle hooks for dynamic context handoff
|
|
9593
9793
|
*/
|
|
9594
|
-
async callTool(name, args) {
|
|
9794
|
+
async callTool(name, args, options = {}) {
|
|
9595
9795
|
const resolvedName = this.resolveToolName(name);
|
|
9596
9796
|
if (!resolvedName) {
|
|
9597
9797
|
throw new Error(`Tool ${name} not found`);
|
|
@@ -9600,9 +9800,99 @@ var ComposableMCPServer = class extends Server {
|
|
|
9600
9800
|
if (!callback) {
|
|
9601
9801
|
throw new Error(`Tool ${name} not found`);
|
|
9602
9802
|
}
|
|
9603
|
-
const
|
|
9604
|
-
const
|
|
9605
|
-
|
|
9803
|
+
const toolDefinition = this.toolManager.getComposedTool(resolvedName);
|
|
9804
|
+
const startTime = Date.now();
|
|
9805
|
+
const beforeContext = {
|
|
9806
|
+
toolName: resolvedName,
|
|
9807
|
+
args,
|
|
9808
|
+
server: this,
|
|
9809
|
+
toolDefinition,
|
|
9810
|
+
isInternalCall: true,
|
|
9811
|
+
agentName: options.agentName,
|
|
9812
|
+
executionChain: options.executionChain
|
|
9813
|
+
};
|
|
9814
|
+
const beforeResult = await this.pluginManager.triggerBeforeToolExecute(beforeContext);
|
|
9815
|
+
if (beforeResult?.skipExecution) {
|
|
9816
|
+
const executionTimeMs2 = Date.now() - startTime;
|
|
9817
|
+
const afterContext2 = {
|
|
9818
|
+
toolName: resolvedName,
|
|
9819
|
+
args,
|
|
9820
|
+
result: beforeResult.result,
|
|
9821
|
+
server: this,
|
|
9822
|
+
wasSkipped: true,
|
|
9823
|
+
executionTimeMs: executionTimeMs2,
|
|
9824
|
+
isError: false,
|
|
9825
|
+
metadata: beforeResult.metadata,
|
|
9826
|
+
isInternalCall: true,
|
|
9827
|
+
agentName: options.agentName
|
|
9828
|
+
};
|
|
9829
|
+
const afterResult2 = await this.pluginManager.triggerAfterToolExecute(afterContext2);
|
|
9830
|
+
let finalResult = afterResult2?.modifiedResult ?? beforeResult.result;
|
|
9831
|
+
if (afterResult2?.markAsError && finalResult && typeof finalResult === "object") {
|
|
9832
|
+
finalResult = {
|
|
9833
|
+
...finalResult,
|
|
9834
|
+
isError: true
|
|
9835
|
+
};
|
|
9836
|
+
}
|
|
9837
|
+
return finalResult;
|
|
9838
|
+
}
|
|
9839
|
+
const effectiveArgs = beforeResult?.modifiedArgs ?? args;
|
|
9840
|
+
const processedArgs = await this.applyPluginTransforms(resolvedName, effectiveArgs, "input");
|
|
9841
|
+
let result;
|
|
9842
|
+
let isError = false;
|
|
9843
|
+
try {
|
|
9844
|
+
result = await callback(processedArgs);
|
|
9845
|
+
} catch (error) {
|
|
9846
|
+
isError = true;
|
|
9847
|
+
result = {
|
|
9848
|
+
content: [
|
|
9849
|
+
{
|
|
9850
|
+
type: "text",
|
|
9851
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
9852
|
+
}
|
|
9853
|
+
],
|
|
9854
|
+
isError: true
|
|
9855
|
+
};
|
|
9856
|
+
}
|
|
9857
|
+
result = await this.applyPluginTransforms(resolvedName, result, "output", args);
|
|
9858
|
+
if (isError && result && typeof result === "object" && !("isError" in result)) {
|
|
9859
|
+
result = {
|
|
9860
|
+
...result,
|
|
9861
|
+
isError: true
|
|
9862
|
+
};
|
|
9863
|
+
}
|
|
9864
|
+
const executionTimeMs = Date.now() - startTime;
|
|
9865
|
+
const afterContext = {
|
|
9866
|
+
toolName: resolvedName,
|
|
9867
|
+
args,
|
|
9868
|
+
result,
|
|
9869
|
+
server: this,
|
|
9870
|
+
wasSkipped: false,
|
|
9871
|
+
executionTimeMs,
|
|
9872
|
+
isError,
|
|
9873
|
+
metadata: beforeResult?.metadata,
|
|
9874
|
+
isInternalCall: true,
|
|
9875
|
+
agentName: options.agentName
|
|
9876
|
+
};
|
|
9877
|
+
const afterResult = await this.pluginManager.triggerAfterToolExecute(afterContext);
|
|
9878
|
+
if (afterResult?.modifiedResult !== void 0) {
|
|
9879
|
+
let finalResult = afterResult.modifiedResult;
|
|
9880
|
+
const hasExplicitIsError = finalResult && typeof finalResult === "object" && "isError" in finalResult;
|
|
9881
|
+
if (!hasExplicitIsError && afterResult.markAsError && finalResult && typeof finalResult === "object") {
|
|
9882
|
+
finalResult = {
|
|
9883
|
+
...finalResult,
|
|
9884
|
+
isError: true
|
|
9885
|
+
};
|
|
9886
|
+
}
|
|
9887
|
+
return finalResult;
|
|
9888
|
+
}
|
|
9889
|
+
if (afterResult?.markAsError && result && typeof result === "object") {
|
|
9890
|
+
return {
|
|
9891
|
+
...result,
|
|
9892
|
+
isError: true
|
|
9893
|
+
};
|
|
9894
|
+
}
|
|
9895
|
+
return result;
|
|
9606
9896
|
}
|
|
9607
9897
|
/**
|
|
9608
9898
|
* Get all public tool names (exposed to MCP clients)
|
package/bin/mcpc.mjs
CHANGED
|
@@ -7802,7 +7802,9 @@ ${JSON.stringify(cleanedSchema, null, 2)}
|
|
|
7802
7802
|
tool: tool2
|
|
7803
7803
|
});
|
|
7804
7804
|
try {
|
|
7805
|
-
const result = await this.server.callTool(tool2, toolArgs
|
|
7805
|
+
const result = await this.server.callTool(tool2, toolArgs, {
|
|
7806
|
+
agentName: this.name
|
|
7807
|
+
});
|
|
7806
7808
|
const callToolResult = result ?? {
|
|
7807
7809
|
content: []
|
|
7808
7810
|
};
|
|
@@ -8836,7 +8838,7 @@ function isValidPlugin(plugin) {
|
|
|
8836
8838
|
if (!p2.name || typeof p2.name !== "string" || p2.name.trim() === "") {
|
|
8837
8839
|
return false;
|
|
8838
8840
|
}
|
|
8839
|
-
const hasHook = typeof p2.configureServer === "function" || typeof p2.composeStart === "function" || typeof p2.transformTool === "function" || typeof p2.finalizeComposition === "function" || typeof p2.registerAgentTool === "function" || typeof p2.composeEnd === "function" || typeof p2.transformInput === "function" || typeof p2.transformOutput === "function" || typeof p2.dispose === "function";
|
|
8841
|
+
const hasHook = typeof p2.configureServer === "function" || typeof p2.composeStart === "function" || typeof p2.transformTool === "function" || typeof p2.finalizeComposition === "function" || typeof p2.registerAgentTool === "function" || typeof p2.composeEnd === "function" || typeof p2.transformInput === "function" || typeof p2.transformOutput === "function" || typeof p2.beforeToolExecute === "function" || typeof p2.afterToolExecute === "function" || typeof p2.dispose === "function";
|
|
8840
8842
|
if (!hasHook) return false;
|
|
8841
8843
|
if (p2.enforce && p2.enforce !== "pre" && p2.enforce !== "post") {
|
|
8842
8844
|
return false;
|
|
@@ -9143,6 +9145,113 @@ var PluginManager = class {
|
|
|
9143
9145
|
}
|
|
9144
9146
|
return false;
|
|
9145
9147
|
}
|
|
9148
|
+
// === Tool Execution Lifecycle Hooks ===
|
|
9149
|
+
/**
|
|
9150
|
+
* Trigger beforeToolExecute hooks for all applicable plugins
|
|
9151
|
+
* Returns the combined result from all plugins
|
|
9152
|
+
*
|
|
9153
|
+
* Hook execution order:
|
|
9154
|
+
* 1. 'pre' enforced plugins first
|
|
9155
|
+
* 2. Normal plugins (no enforce)
|
|
9156
|
+
* 3. 'post' enforced plugins last
|
|
9157
|
+
*
|
|
9158
|
+
* If any plugin returns skipExecution=true, execution is skipped
|
|
9159
|
+
* and the result from that plugin is used.
|
|
9160
|
+
*/
|
|
9161
|
+
async triggerBeforeToolExecute(context2) {
|
|
9162
|
+
const beforePlugins = this.plugins.filter((p2) => p2.beforeToolExecute);
|
|
9163
|
+
if (beforePlugins.length === 0) {
|
|
9164
|
+
return void 0;
|
|
9165
|
+
}
|
|
9166
|
+
const sortedPlugins = sortPluginsByOrder(beforePlugins);
|
|
9167
|
+
let currentArgs = context2.args;
|
|
9168
|
+
let combinedMetadata = {};
|
|
9169
|
+
for (const plugin of sortedPlugins) {
|
|
9170
|
+
if (plugin.beforeToolExecute) {
|
|
9171
|
+
try {
|
|
9172
|
+
const result = await plugin.beforeToolExecute({
|
|
9173
|
+
...context2,
|
|
9174
|
+
args: currentArgs
|
|
9175
|
+
});
|
|
9176
|
+
if (result) {
|
|
9177
|
+
if (result.metadata) {
|
|
9178
|
+
combinedMetadata = {
|
|
9179
|
+
...combinedMetadata,
|
|
9180
|
+
...result.metadata
|
|
9181
|
+
};
|
|
9182
|
+
}
|
|
9183
|
+
if (result.skipExecution) {
|
|
9184
|
+
return {
|
|
9185
|
+
skipExecution: true,
|
|
9186
|
+
result: result.result,
|
|
9187
|
+
metadata: combinedMetadata
|
|
9188
|
+
};
|
|
9189
|
+
}
|
|
9190
|
+
if (result.modifiedArgs !== void 0) {
|
|
9191
|
+
currentArgs = result.modifiedArgs;
|
|
9192
|
+
}
|
|
9193
|
+
}
|
|
9194
|
+
} catch (error) {
|
|
9195
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
9196
|
+
await this.logger.error(`Plugin "${plugin.name}" beforeToolExecute failed for "${context2.toolName}": ${errorMsg}`);
|
|
9197
|
+
}
|
|
9198
|
+
}
|
|
9199
|
+
}
|
|
9200
|
+
if (currentArgs !== context2.args) {
|
|
9201
|
+
return {
|
|
9202
|
+
modifiedArgs: currentArgs,
|
|
9203
|
+
metadata: Object.keys(combinedMetadata).length > 0 ? combinedMetadata : void 0
|
|
9204
|
+
};
|
|
9205
|
+
}
|
|
9206
|
+
if (Object.keys(combinedMetadata).length > 0) {
|
|
9207
|
+
return {
|
|
9208
|
+
metadata: combinedMetadata
|
|
9209
|
+
};
|
|
9210
|
+
}
|
|
9211
|
+
return void 0;
|
|
9212
|
+
}
|
|
9213
|
+
/**
|
|
9214
|
+
* Trigger afterToolExecute hooks for all applicable plugins
|
|
9215
|
+
* Returns the final result after all plugins have processed it
|
|
9216
|
+
*/
|
|
9217
|
+
async triggerAfterToolExecute(context2) {
|
|
9218
|
+
const afterPlugins = this.plugins.filter((p2) => p2.afterToolExecute);
|
|
9219
|
+
if (afterPlugins.length === 0) {
|
|
9220
|
+
return void 0;
|
|
9221
|
+
}
|
|
9222
|
+
const sortedPlugins = sortPluginsByOrder(afterPlugins);
|
|
9223
|
+
let currentResult = context2.result;
|
|
9224
|
+
let markAsError = context2.isError;
|
|
9225
|
+
for (const plugin of sortedPlugins) {
|
|
9226
|
+
if (plugin.afterToolExecute) {
|
|
9227
|
+
try {
|
|
9228
|
+
const result = await plugin.afterToolExecute({
|
|
9229
|
+
...context2,
|
|
9230
|
+
result: currentResult,
|
|
9231
|
+
isError: markAsError
|
|
9232
|
+
});
|
|
9233
|
+
if (result) {
|
|
9234
|
+
if (result.modifiedResult !== void 0) {
|
|
9235
|
+
currentResult = result.modifiedResult;
|
|
9236
|
+
}
|
|
9237
|
+
if (result.markAsError !== void 0) {
|
|
9238
|
+
markAsError = result.markAsError;
|
|
9239
|
+
}
|
|
9240
|
+
}
|
|
9241
|
+
} catch (error) {
|
|
9242
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
9243
|
+
await this.logger.error(`Plugin "${plugin.name}" afterToolExecute failed for "${context2.toolName}": ${errorMsg}`);
|
|
9244
|
+
}
|
|
9245
|
+
}
|
|
9246
|
+
}
|
|
9247
|
+
if (currentResult !== context2.result || markAsError !== context2.isError) {
|
|
9248
|
+
return {
|
|
9249
|
+
modifiedResult: currentResult,
|
|
9250
|
+
markAsError
|
|
9251
|
+
};
|
|
9252
|
+
}
|
|
9253
|
+
return void 0;
|
|
9254
|
+
}
|
|
9146
9255
|
/**
|
|
9147
9256
|
* Dispose all plugins and cleanup resources
|
|
9148
9257
|
*/
|
|
@@ -9373,6 +9482,24 @@ var ToolManager = class {
|
|
|
9373
9482
|
}
|
|
9374
9483
|
return composedTools;
|
|
9375
9484
|
}
|
|
9485
|
+
/**
|
|
9486
|
+
* Get a single tool as ComposedTool object by name
|
|
9487
|
+
*/
|
|
9488
|
+
getComposedTool(name) {
|
|
9489
|
+
const tool2 = this.toolRegistry.get(name);
|
|
9490
|
+
if (!tool2) {
|
|
9491
|
+
return void 0;
|
|
9492
|
+
}
|
|
9493
|
+
return {
|
|
9494
|
+
name,
|
|
9495
|
+
description: tool2.description,
|
|
9496
|
+
inputSchema: tool2.schema ?? {
|
|
9497
|
+
type: "object",
|
|
9498
|
+
properties: {}
|
|
9499
|
+
},
|
|
9500
|
+
execute: tool2.callback
|
|
9501
|
+
};
|
|
9502
|
+
}
|
|
9376
9503
|
};
|
|
9377
9504
|
|
|
9378
9505
|
// __mcpc__cli_latest/node_modules/@jsr/mcpc__core/src/utils/common/schema.js
|
|
@@ -9573,9 +9700,81 @@ var ComposableMCPServer = class extends Server {
|
|
|
9573
9700
|
if (!handler) {
|
|
9574
9701
|
throw new Error(`Tool ${toolName} not found`);
|
|
9575
9702
|
}
|
|
9576
|
-
const
|
|
9577
|
-
const
|
|
9578
|
-
|
|
9703
|
+
const toolDefinition = this.toolManager.getComposedTool(toolName);
|
|
9704
|
+
const startTime = Date.now();
|
|
9705
|
+
const beforeContext = {
|
|
9706
|
+
toolName,
|
|
9707
|
+
args,
|
|
9708
|
+
server: this,
|
|
9709
|
+
toolDefinition,
|
|
9710
|
+
isInternalCall: false
|
|
9711
|
+
};
|
|
9712
|
+
const beforeResult = await this.pluginManager.triggerBeforeToolExecute(beforeContext);
|
|
9713
|
+
if (beforeResult?.skipExecution) {
|
|
9714
|
+
const executionTimeMs2 = Date.now() - startTime;
|
|
9715
|
+
const afterContext2 = {
|
|
9716
|
+
toolName,
|
|
9717
|
+
args,
|
|
9718
|
+
result: beforeResult.result,
|
|
9719
|
+
server: this,
|
|
9720
|
+
wasSkipped: true,
|
|
9721
|
+
executionTimeMs: executionTimeMs2,
|
|
9722
|
+
isError: false,
|
|
9723
|
+
metadata: beforeResult.metadata,
|
|
9724
|
+
isInternalCall: false
|
|
9725
|
+
};
|
|
9726
|
+
const afterResult2 = await this.pluginManager.triggerAfterToolExecute(afterContext2);
|
|
9727
|
+
let finalResult = afterResult2?.modifiedResult ?? beforeResult.result;
|
|
9728
|
+
if (afterResult2?.markAsError && finalResult) {
|
|
9729
|
+
finalResult = {
|
|
9730
|
+
...finalResult,
|
|
9731
|
+
isError: true
|
|
9732
|
+
};
|
|
9733
|
+
}
|
|
9734
|
+
return finalResult;
|
|
9735
|
+
}
|
|
9736
|
+
const effectiveArgs = beforeResult?.modifiedArgs ?? args;
|
|
9737
|
+
const processedArgs = await this.applyPluginTransforms(toolName, effectiveArgs, "input");
|
|
9738
|
+
let result = await handler(processedArgs, extra);
|
|
9739
|
+
const isError = !!result?.isError;
|
|
9740
|
+
result = await this.applyPluginTransforms(toolName, result, "output", args);
|
|
9741
|
+
if (isError && result && !("isError" in result)) {
|
|
9742
|
+
result = {
|
|
9743
|
+
...result,
|
|
9744
|
+
isError: true
|
|
9745
|
+
};
|
|
9746
|
+
}
|
|
9747
|
+
const executionTimeMs = Date.now() - startTime;
|
|
9748
|
+
const afterContext = {
|
|
9749
|
+
toolName,
|
|
9750
|
+
args,
|
|
9751
|
+
result,
|
|
9752
|
+
server: this,
|
|
9753
|
+
wasSkipped: false,
|
|
9754
|
+
executionTimeMs,
|
|
9755
|
+
isError,
|
|
9756
|
+
metadata: beforeResult?.metadata,
|
|
9757
|
+
isInternalCall: false
|
|
9758
|
+
};
|
|
9759
|
+
const afterResult = await this.pluginManager.triggerAfterToolExecute(afterContext);
|
|
9760
|
+
if (afterResult?.modifiedResult !== void 0) {
|
|
9761
|
+
let finalResult = afterResult.modifiedResult;
|
|
9762
|
+
const hasExplicitIsError = finalResult && "isError" in finalResult;
|
|
9763
|
+
if (!hasExplicitIsError && afterResult.markAsError && finalResult) {
|
|
9764
|
+
finalResult = {
|
|
9765
|
+
...finalResult,
|
|
9766
|
+
isError: true
|
|
9767
|
+
};
|
|
9768
|
+
}
|
|
9769
|
+
return finalResult;
|
|
9770
|
+
}
|
|
9771
|
+
if (afterResult?.markAsError && result) {
|
|
9772
|
+
return {
|
|
9773
|
+
...result,
|
|
9774
|
+
isError: true
|
|
9775
|
+
};
|
|
9776
|
+
}
|
|
9777
|
+
return result;
|
|
9579
9778
|
});
|
|
9580
9779
|
this.setRequestHandler(SetLevelRequestSchema, (request) => {
|
|
9581
9780
|
const { level } = request.params;
|
|
@@ -9597,8 +9796,9 @@ var ComposableMCPServer = class extends Server {
|
|
|
9597
9796
|
}
|
|
9598
9797
|
/**
|
|
9599
9798
|
* Call any registered tool directly, whether it's public or internal
|
|
9799
|
+
* Supports tool execution lifecycle hooks for dynamic context handoff
|
|
9600
9800
|
*/
|
|
9601
|
-
async callTool(name, args) {
|
|
9801
|
+
async callTool(name, args, options = {}) {
|
|
9602
9802
|
const resolvedName = this.resolveToolName(name);
|
|
9603
9803
|
if (!resolvedName) {
|
|
9604
9804
|
throw new Error(`Tool ${name} not found`);
|
|
@@ -9607,9 +9807,99 @@ var ComposableMCPServer = class extends Server {
|
|
|
9607
9807
|
if (!callback) {
|
|
9608
9808
|
throw new Error(`Tool ${name} not found`);
|
|
9609
9809
|
}
|
|
9610
|
-
const
|
|
9611
|
-
const
|
|
9612
|
-
|
|
9810
|
+
const toolDefinition = this.toolManager.getComposedTool(resolvedName);
|
|
9811
|
+
const startTime = Date.now();
|
|
9812
|
+
const beforeContext = {
|
|
9813
|
+
toolName: resolvedName,
|
|
9814
|
+
args,
|
|
9815
|
+
server: this,
|
|
9816
|
+
toolDefinition,
|
|
9817
|
+
isInternalCall: true,
|
|
9818
|
+
agentName: options.agentName,
|
|
9819
|
+
executionChain: options.executionChain
|
|
9820
|
+
};
|
|
9821
|
+
const beforeResult = await this.pluginManager.triggerBeforeToolExecute(beforeContext);
|
|
9822
|
+
if (beforeResult?.skipExecution) {
|
|
9823
|
+
const executionTimeMs2 = Date.now() - startTime;
|
|
9824
|
+
const afterContext2 = {
|
|
9825
|
+
toolName: resolvedName,
|
|
9826
|
+
args,
|
|
9827
|
+
result: beforeResult.result,
|
|
9828
|
+
server: this,
|
|
9829
|
+
wasSkipped: true,
|
|
9830
|
+
executionTimeMs: executionTimeMs2,
|
|
9831
|
+
isError: false,
|
|
9832
|
+
metadata: beforeResult.metadata,
|
|
9833
|
+
isInternalCall: true,
|
|
9834
|
+
agentName: options.agentName
|
|
9835
|
+
};
|
|
9836
|
+
const afterResult2 = await this.pluginManager.triggerAfterToolExecute(afterContext2);
|
|
9837
|
+
let finalResult = afterResult2?.modifiedResult ?? beforeResult.result;
|
|
9838
|
+
if (afterResult2?.markAsError && finalResult && typeof finalResult === "object") {
|
|
9839
|
+
finalResult = {
|
|
9840
|
+
...finalResult,
|
|
9841
|
+
isError: true
|
|
9842
|
+
};
|
|
9843
|
+
}
|
|
9844
|
+
return finalResult;
|
|
9845
|
+
}
|
|
9846
|
+
const effectiveArgs = beforeResult?.modifiedArgs ?? args;
|
|
9847
|
+
const processedArgs = await this.applyPluginTransforms(resolvedName, effectiveArgs, "input");
|
|
9848
|
+
let result;
|
|
9849
|
+
let isError = false;
|
|
9850
|
+
try {
|
|
9851
|
+
result = await callback(processedArgs);
|
|
9852
|
+
} catch (error) {
|
|
9853
|
+
isError = true;
|
|
9854
|
+
result = {
|
|
9855
|
+
content: [
|
|
9856
|
+
{
|
|
9857
|
+
type: "text",
|
|
9858
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
9859
|
+
}
|
|
9860
|
+
],
|
|
9861
|
+
isError: true
|
|
9862
|
+
};
|
|
9863
|
+
}
|
|
9864
|
+
result = await this.applyPluginTransforms(resolvedName, result, "output", args);
|
|
9865
|
+
if (isError && result && typeof result === "object" && !("isError" in result)) {
|
|
9866
|
+
result = {
|
|
9867
|
+
...result,
|
|
9868
|
+
isError: true
|
|
9869
|
+
};
|
|
9870
|
+
}
|
|
9871
|
+
const executionTimeMs = Date.now() - startTime;
|
|
9872
|
+
const afterContext = {
|
|
9873
|
+
toolName: resolvedName,
|
|
9874
|
+
args,
|
|
9875
|
+
result,
|
|
9876
|
+
server: this,
|
|
9877
|
+
wasSkipped: false,
|
|
9878
|
+
executionTimeMs,
|
|
9879
|
+
isError,
|
|
9880
|
+
metadata: beforeResult?.metadata,
|
|
9881
|
+
isInternalCall: true,
|
|
9882
|
+
agentName: options.agentName
|
|
9883
|
+
};
|
|
9884
|
+
const afterResult = await this.pluginManager.triggerAfterToolExecute(afterContext);
|
|
9885
|
+
if (afterResult?.modifiedResult !== void 0) {
|
|
9886
|
+
let finalResult = afterResult.modifiedResult;
|
|
9887
|
+
const hasExplicitIsError = finalResult && typeof finalResult === "object" && "isError" in finalResult;
|
|
9888
|
+
if (!hasExplicitIsError && afterResult.markAsError && finalResult && typeof finalResult === "object") {
|
|
9889
|
+
finalResult = {
|
|
9890
|
+
...finalResult,
|
|
9891
|
+
isError: true
|
|
9892
|
+
};
|
|
9893
|
+
}
|
|
9894
|
+
return finalResult;
|
|
9895
|
+
}
|
|
9896
|
+
if (afterResult?.markAsError && result && typeof result === "object") {
|
|
9897
|
+
return {
|
|
9898
|
+
...result,
|
|
9899
|
+
isError: true
|
|
9900
|
+
};
|
|
9901
|
+
}
|
|
9902
|
+
return result;
|
|
9613
9903
|
}
|
|
9614
9904
|
/**
|
|
9615
9905
|
* Get all public tool names (exposed to MCP clients)
|