@frontmcp/sdk 0.3.1 → 0.4.0

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.
Files changed (148) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +192 -164
  3. package/package.json +7 -4
  4. package/src/__test-utils__/fixtures/hook.fixtures.d.ts +46 -0
  5. package/src/__test-utils__/fixtures/hook.fixtures.js +114 -0
  6. package/src/__test-utils__/fixtures/hook.fixtures.js.map +1 -0
  7. package/src/__test-utils__/fixtures/index.d.ts +7 -0
  8. package/src/__test-utils__/fixtures/index.js +11 -0
  9. package/src/__test-utils__/fixtures/index.js.map +1 -0
  10. package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +46 -0
  11. package/src/__test-utils__/fixtures/plugin.fixtures.js +127 -0
  12. package/src/__test-utils__/fixtures/plugin.fixtures.js.map +1 -0
  13. package/src/__test-utils__/fixtures/provider.fixtures.d.ts +69 -0
  14. package/src/__test-utils__/fixtures/provider.fixtures.js +131 -0
  15. package/src/__test-utils__/fixtures/provider.fixtures.js.map +1 -0
  16. package/src/__test-utils__/fixtures/scope.fixtures.d.ts +14 -0
  17. package/src/__test-utils__/fixtures/scope.fixtures.js +59 -0
  18. package/src/__test-utils__/fixtures/scope.fixtures.js.map +1 -0
  19. package/src/__test-utils__/fixtures/tool.fixtures.d.ts +36 -0
  20. package/src/__test-utils__/fixtures/tool.fixtures.js +91 -0
  21. package/src/__test-utils__/fixtures/tool.fixtures.js.map +1 -0
  22. package/src/__test-utils__/helpers/assertion.helpers.d.ts +45 -0
  23. package/src/__test-utils__/helpers/assertion.helpers.js +153 -0
  24. package/src/__test-utils__/helpers/assertion.helpers.js.map +1 -0
  25. package/src/__test-utils__/helpers/async.helpers.d.ts +48 -0
  26. package/src/__test-utils__/helpers/async.helpers.js +112 -0
  27. package/src/__test-utils__/helpers/async.helpers.js.map +1 -0
  28. package/src/__test-utils__/helpers/index.d.ts +6 -0
  29. package/src/__test-utils__/helpers/index.js +10 -0
  30. package/src/__test-utils__/helpers/index.js.map +1 -0
  31. package/src/__test-utils__/helpers/setup.helpers.d.ts +54 -0
  32. package/src/__test-utils__/helpers/setup.helpers.js +106 -0
  33. package/src/__test-utils__/helpers/setup.helpers.js.map +1 -0
  34. package/src/__test-utils__/index.d.ts +9 -0
  35. package/src/__test-utils__/index.js +14 -0
  36. package/src/__test-utils__/index.js.map +1 -0
  37. package/src/__test-utils__/mocks/flow-instance.mock.d.ts +50 -0
  38. package/src/__test-utils__/mocks/flow-instance.mock.js +72 -0
  39. package/src/__test-utils__/mocks/flow-instance.mock.js.map +1 -0
  40. package/src/__test-utils__/mocks/hook-registry.mock.d.ts +25 -0
  41. package/src/__test-utils__/mocks/hook-registry.mock.js +65 -0
  42. package/src/__test-utils__/mocks/hook-registry.mock.js.map +1 -0
  43. package/src/__test-utils__/mocks/index.d.ts +8 -0
  44. package/src/__test-utils__/mocks/index.js +12 -0
  45. package/src/__test-utils__/mocks/index.js.map +1 -0
  46. package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +43 -0
  47. package/src/__test-utils__/mocks/plugin-registry.mock.js +70 -0
  48. package/src/__test-utils__/mocks/plugin-registry.mock.js.map +1 -0
  49. package/src/__test-utils__/mocks/provider-registry.mock.d.ts +39 -0
  50. package/src/__test-utils__/mocks/provider-registry.mock.js +72 -0
  51. package/src/__test-utils__/mocks/provider-registry.mock.js.map +1 -0
  52. package/src/__test-utils__/mocks/tool-registry.mock.d.ts +43 -0
  53. package/src/__test-utils__/mocks/tool-registry.mock.js +79 -0
  54. package/src/__test-utils__/mocks/tool-registry.mock.js.map +1 -0
  55. package/src/app/app.utils.js.map +1 -1
  56. package/src/app/instances/app.local.instance.js +8 -11
  57. package/src/app/instances/app.local.instance.js.map +1 -1
  58. package/src/auth/flows/oauth.authorize.flow.d.ts +8 -8
  59. package/src/auth/flows/oauth.register.flow.d.ts +4 -4
  60. package/src/auth/flows/oauth.token.flow.d.ts +4 -4
  61. package/src/auth/flows/well-known.jwks.flow.d.ts +12 -12
  62. package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +8 -8
  63. package/src/auth/flows/well-known.prm.flow.d.ts +4 -4
  64. package/src/common/decorators/tool.decorator.d.ts +97 -36
  65. package/src/common/decorators/tool.decorator.js +0 -1
  66. package/src/common/decorators/tool.decorator.js.map +1 -1
  67. package/src/common/entries/tool.entry.d.ts +54 -11
  68. package/src/common/entries/tool.entry.js +19 -0
  69. package/src/common/entries/tool.entry.js.map +1 -1
  70. package/src/common/interfaces/internal/registry.interface.d.ts +10 -2
  71. package/src/common/interfaces/internal/registry.interface.js.map +1 -1
  72. package/src/common/interfaces/plugin.interface.d.ts +1 -1
  73. package/src/common/interfaces/plugin.interface.js.map +1 -1
  74. package/src/common/interfaces/tool.interface.d.ts +12 -7
  75. package/src/common/interfaces/tool.interface.js +1 -1
  76. package/src/common/interfaces/tool.interface.js.map +1 -1
  77. package/src/common/metadata/front-mcp.metadata.d.ts +145 -145
  78. package/src/common/metadata/hook.metadata.d.ts +4 -2
  79. package/src/common/metadata/hook.metadata.js.map +1 -1
  80. package/src/common/metadata/prompt.metadata.d.ts +28 -28
  81. package/src/common/metadata/prompt.metadata.js.map +1 -1
  82. package/src/common/metadata/resource.metadata.d.ts +54 -54
  83. package/src/common/metadata/tool.metadata.d.ts +190 -7
  84. package/src/common/metadata/tool.metadata.js +41 -6
  85. package/src/common/metadata/tool.metadata.js.map +1 -1
  86. package/src/common/schemas/http-output.schema.d.ts +106 -106
  87. package/src/common/tokens/tool.tokens.js.map +1 -1
  88. package/src/common/types/options/logging.options.d.ts +1 -2
  89. package/src/common/types/options/logging.options.js +1 -9
  90. package/src/common/types/options/logging.options.js.map +1 -1
  91. package/src/common/types/options/server-info.options.d.ts +19 -19
  92. package/src/errors/error-handler.d.ts +65 -0
  93. package/src/errors/error-handler.js +107 -0
  94. package/src/errors/error-handler.js.map +1 -0
  95. package/src/errors/index.d.ts +2 -0
  96. package/src/errors/index.js +26 -0
  97. package/src/errors/index.js.map +1 -0
  98. package/src/errors/mcp.error.d.ts +156 -0
  99. package/src/errors/mcp.error.js +243 -0
  100. package/src/errors/mcp.error.js.map +1 -0
  101. package/src/flows/flow.instance.js +7 -6
  102. package/src/flows/flow.instance.js.map +1 -1
  103. package/src/flows/flow.registry.js +1 -1
  104. package/src/flows/flow.registry.js.map +1 -1
  105. package/src/front-mcp/front-mcp.providers.d.ts +20 -20
  106. package/src/hooks/hook.registry.d.ts +5 -3
  107. package/src/hooks/hook.registry.js +13 -1
  108. package/src/hooks/hook.registry.js.map +1 -1
  109. package/src/plugin/plugin.registry.d.ts +7 -2
  110. package/src/plugin/plugin.registry.js +23 -11
  111. package/src/plugin/plugin.registry.js.map +1 -1
  112. package/src/prompt/prompt.registry.js +1 -0
  113. package/src/prompt/prompt.registry.js.map +1 -1
  114. package/src/resource/resource.registry.js +1 -0
  115. package/src/resource/resource.registry.js.map +1 -1
  116. package/src/scope/scope.registry.js +1 -1
  117. package/src/scope/scope.registry.js.map +1 -1
  118. package/src/store/adapters/store.memory.adapter.js +3 -1
  119. package/src/store/adapters/store.memory.adapter.js.map +1 -1
  120. package/src/tool/flows/call-tool.flow.d.ts +1012 -676
  121. package/src/tool/flows/call-tool.flow.js +94 -61
  122. package/src/tool/flows/call-tool.flow.js.map +1 -1
  123. package/src/tool/flows/tools-list.flow.d.ts +347 -590
  124. package/src/tool/flows/tools-list.flow.js +76 -49
  125. package/src/tool/flows/tools-list.flow.js.map +1 -1
  126. package/src/tool/tool.instance.d.ts +27 -8
  127. package/src/tool/tool.instance.js +40 -5
  128. package/src/tool/tool.instance.js.map +1 -1
  129. package/src/tool/tool.registry.js +19 -21
  130. package/src/tool/tool.registry.js.map +1 -1
  131. package/src/tool/tool.utils.d.ts +3 -2
  132. package/src/tool/tool.utils.js +377 -14
  133. package/src/tool/tool.utils.js.map +1 -1
  134. package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
  135. package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
  136. package/src/transport/flows/handle.sse.flow.js +6 -13
  137. package/src/transport/flows/handle.sse.flow.js.map +1 -1
  138. package/src/transport/flows/handle.streamable-http.flow.js +1 -0
  139. package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
  140. package/src/transport/mcp-handlers/call-tool-request.handler.d.ts +1 -1
  141. package/src/transport/mcp-handlers/call-tool-request.handler.js +10 -5
  142. package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
  143. package/src/transport/mcp-handlers/index.d.ts +151 -268
  144. package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +124 -216
  145. package/src/transport/transport.local.js +1 -0
  146. package/src/transport/transport.local.js.map +1 -1
  147. package/src/utils/string.utils.js +1 -1
  148. package/src/utils/string.utils.js.map +1 -1
@@ -5,38 +5,30 @@ const tslib_1 = require("tslib");
5
5
  const common_1 = require("../../common");
6
6
  const zod_1 = require("zod");
7
7
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
8
+ const errors_1 = require("../../errors");
8
9
  const inputSchema = zod_1.z.object({
9
10
  request: types_js_1.CallToolRequestSchema,
10
11
  ctx: zod_1.z.any(),
11
12
  });
12
13
  const outputSchema = types_js_1.CallToolResultSchema;
13
14
  const stateSchema = zod_1.z.object({
14
- input: zod_1.z.object({
15
+ input: zod_1.z
16
+ .object({
15
17
  name: zod_1.z.string().min(1).max(64),
16
18
  arguments: zod_1.z.object({}).passthrough().optional(),
17
- }).passthrough(),
19
+ })
20
+ .passthrough(),
18
21
  authInfo: zod_1.z.any().optional(),
19
22
  tool: zod_1.z.instanceof(common_1.ToolEntry),
20
23
  toolContext: zod_1.z.instanceof(common_1.ToolContext),
24
+ // Store the raw executed output for plugins to see
25
+ rawOutput: zod_1.z.any().optional(),
26
+ output: outputSchema,
21
27
  });
22
28
  const plan = {
23
- pre: [
24
- 'parseInput',
25
- 'findTool',
26
- 'createToolCallContext',
27
- 'acquireQuota',
28
- 'acquireSemaphore',
29
- ],
30
- execute: [
31
- 'validateInput',
32
- 'execute',
33
- 'validateOutput',
34
- ],
35
- finalize: [
36
- 'releaseSemaphore',
37
- 'releaseQuota',
38
- 'finalize',
39
- ],
29
+ pre: ['parseInput', 'findTool', 'createToolCallContext', 'acquireQuota', 'acquireSemaphore'],
30
+ execute: ['validateInput', 'execute', 'validateOutput'],
31
+ finalize: ['releaseSemaphore', 'releaseQuota', 'finalize'],
40
32
  };
41
33
  const name = 'tools:call-tool';
42
34
  const { Stage } = (0, common_1.FlowHooksOf)(name);
@@ -44,10 +36,31 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
44
36
  logger = this.scopeLogger.child('CallToolFlow');
45
37
  async parseInput() {
46
38
  this.logger.verbose('parseInput:start');
47
- const { request: { method, params }, ctx } = inputSchema.parse(this.rawInput);
39
+ let method;
40
+ let params;
41
+ let ctx;
42
+ try {
43
+ const inputData = inputSchema.parse(this.rawInput);
44
+ method = inputData.request.method;
45
+ params = inputData.request.params;
46
+ ctx = inputData.ctx;
47
+ }
48
+ catch (e) {
49
+ throw new errors_1.InvalidInputError('Invalid Input', e instanceof zod_1.z.ZodError ? e.errors : undefined);
50
+ }
48
51
  if (method !== 'tools/call') {
49
52
  this.logger.warn(`parseInput: invalid method "${method}"`);
50
- throw new Error('Invalid method');
53
+ throw new errors_1.InvalidMethodError(method, 'tools/call');
54
+ }
55
+ // Find the tool early to get its owner ID for hook filtering
56
+ const { name } = params;
57
+ const activeTools = this.scope.tools.getTools(true);
58
+ const tool = activeTools.find((entry) => {
59
+ return entry.fullName === name || entry.name === name;
60
+ });
61
+ // Store tool owner ID in the flow input for hook filtering
62
+ if (tool?.owner) {
63
+ this.rawInput._toolOwnerId = tool.owner.id;
51
64
  }
52
65
  this.state.set({ input: params, authInfo: ctx.authInfo });
53
66
  this.logger.verbose('parseInput:done');
@@ -58,11 +71,12 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
58
71
  const activeTools = this.scope.tools.getTools(true);
59
72
  this.logger.info(`findTool: discovered ${activeTools.length} active tool(s) (including hidden)`);
60
73
  const { name } = this.state.required.input;
61
- const tool = activeTools.find(t => t.metadata.name === name);
74
+ const tool = activeTools.find((entry) => {
75
+ return entry.fullName === name || entry.name === name;
76
+ });
62
77
  if (!tool) {
63
- const errorMessage = `Tool "${name}" not found`;
64
- this.logger.warn(errorMessage);
65
- this.fail(new Error(errorMessage));
78
+ this.logger.warn(`findTool: tool "${name}" not found`);
79
+ throw new errors_1.ToolNotFoundError(name);
66
80
  }
67
81
  this.logger = this.logger.child(`CallToolFlow(${name})`);
68
82
  this.state.set('tool', tool);
@@ -73,19 +87,23 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
73
87
  this.logger.verbose('createToolCallContext:start');
74
88
  const { ctx } = this.input;
75
89
  const { tool, input } = this.state.required;
76
- const context = tool.create(input, ctx);
77
- const toolHooks = this.scope.hooks.getClsHooks(tool.record.provide)
78
- .map(hook => {
79
- hook.run = async () => {
80
- return context[hook.metadata.method]();
81
- };
82
- return hook;
83
- });
84
- this.appendContextHooks(toolHooks);
85
- context.input = input;
86
- context.mark('createToolCallContext');
87
- this.state.set('toolContext', context);
88
- this.logger.verbose('createToolCallContext:done');
90
+ try {
91
+ const context = tool.create(input.arguments, ctx);
92
+ const toolHooks = this.scope.hooks.getClsHooks(tool.record.provide).map((hook) => {
93
+ hook.run = async () => {
94
+ return context[hook.metadata.method]();
95
+ };
96
+ return hook;
97
+ });
98
+ this.appendContextHooks(toolHooks);
99
+ context.mark('createToolCallContext');
100
+ this.state.set('toolContext', context);
101
+ this.logger.verbose('createToolCallContext:done');
102
+ }
103
+ catch (error) {
104
+ this.logger.error('createToolCallContext: failed to create context', error);
105
+ throw new errors_1.ToolExecutionError(tool.metadata.name, error instanceof Error ? error : undefined);
106
+ }
89
107
  }
90
108
  async acquireQuota() {
91
109
  this.logger.verbose('acquireQuota:start');
@@ -108,12 +126,16 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
108
126
  }
109
127
  toolContext.mark('validateInput');
110
128
  try {
111
- toolContext.input = tool.inputSchema.parse(input.arguments ?? {});
129
+ toolContext.input = tool.parseInput(input);
130
+ this.logger.verbose('validateInput:done');
112
131
  }
113
132
  catch (err) {
114
- this.fail(new Error(`Invalid input: validation failed`));
133
+ if (err instanceof zod_1.z.ZodError) {
134
+ throw new errors_1.InvalidInputError('Invalid tool input', err.errors);
135
+ }
136
+ this.logger.error('validateInput: failed to parse input', err);
137
+ throw new errors_1.InvalidInputError('Unknown error occurred when trying to parse input');
115
138
  }
116
- this.logger.verbose('validateInput:done');
117
139
  }
118
140
  async execute() {
119
141
  this.logger.verbose('execute:start');
@@ -122,17 +144,24 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
122
144
  return;
123
145
  }
124
146
  toolContext.mark('execute');
125
- toolContext.output = await toolContext.execute(toolContext.input);
126
- this.logger.verbose('execute:done');
147
+ try {
148
+ toolContext.output = await toolContext.execute(toolContext.input);
149
+ this.logger.verbose('execute:done');
150
+ }
151
+ catch (error) {
152
+ this.logger.error('execute: tool execution failed', error);
153
+ throw new errors_1.ToolExecutionError(this.state.tool?.metadata.name || 'unknown', error instanceof Error ? error : undefined);
154
+ }
127
155
  }
128
156
  async validateOutput() {
129
157
  this.logger.verbose('validateOutput:start');
130
- const { tool, toolContext } = this.state;
131
- if (!toolContext || !tool) {
158
+ const { toolContext } = this.state;
159
+ if (!toolContext) {
132
160
  return;
133
161
  }
134
162
  toolContext.mark('validateOutput');
135
- toolContext.output = tool.outputSchema.parse(toolContext.output);
163
+ // Store the RAW output for plugins (cache, PII, etc.) to inspect
164
+ this.state.set('rawOutput', toolContext.output);
136
165
  this.logger.verbose('validateOutput:done');
137
166
  }
138
167
  async releaseSemaphore() {
@@ -149,24 +178,28 @@ let CallToolFlow = class CallToolFlow extends common_1.FlowBase {
149
178
  }
150
179
  async finalize() {
151
180
  this.logger.verbose('finalize:start');
152
- if (!this.state.toolContext) {
153
- this.fail(new Error("error"));
154
- return;
181
+ const { tool, rawOutput } = this.state;
182
+ if (!tool) {
183
+ this.logger.error('finalize: tool not found in state');
184
+ throw new errors_1.ToolExecutionError('unknown', new Error('Tool not found in state'));
155
185
  }
156
- const { tool, toolContext } = this.state.required;
157
- const success = tool.outputSchema.safeParse(toolContext.output).success;
158
- if (success) {
159
- const response = toolContext.output;
160
- this.respond({
161
- content: [{
162
- type: 'text',
163
- text: JSON.stringify(response)
164
- }],
165
- });
186
+ if (rawOutput === undefined) {
187
+ this.logger.error('finalize: tool output not found in state');
188
+ throw new errors_1.ToolExecutionError(tool.metadata.name, new Error('Tool output not found'));
166
189
  }
167
- else {
168
- this.fail(new Error("invalid output schema"));
190
+ // Parse and construct the MCP-compliant output using safeParseOutput
191
+ const parseResult = tool.safeParseOutput(rawOutput);
192
+ if (!parseResult.success) {
193
+ // add support for request id in error messages
194
+ this.logger.error('finalize: output validation failed', {
195
+ tool: tool.metadata.name,
196
+ errors: parseResult.error,
197
+ });
198
+ // Use InvalidOutputError, which hides internal details in production
199
+ throw new errors_1.InvalidOutputError();
169
200
  }
201
+ // Respond with the properly formatted MCP result
202
+ this.respond(parseResult.data);
170
203
  this.logger.verbose('finalize:done');
171
204
  }
172
205
  };
@@ -1 +1 @@
1
- {"version":3,"file":"call-tool.flow.js","sourceRoot":"","sources":["../../../../src/tool/flows/call-tool.flow.ts"],"names":[],"mappings":";;;AAAA,gCAAgC;AAChC,yCAA2G;AAC3G,6BAAsB;AACtB,iEAA+F;AAG/F,MAAM,WAAW,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,OAAO,EAAE,gCAAqB;IAC9B,GAAG,EAAE,OAAC,CAAC,GAAG,EAAE;CACb,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,+BAAoB,CAAC;AAE1C,MAAM,WAAW,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,SAAS,EAAE,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;KACjD,CAAC,CAAC,WAAW,EAAE;IAChB,QAAQ,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAyB;IACnD,IAAI,EAAE,OAAC,CAAC,UAAU,CAAC,kBAAS,CAAC;IAC7B,WAAW,EAAE,OAAC,CAAC,UAAU,CAAC,oBAAW,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG;IACX,GAAG,EAAE;QACH,YAAY;QACZ,UAAU;QACV,uBAAuB;QACvB,cAAc;QACd,kBAAkB;KACnB;IACD,OAAO,EAAE;QACP,eAAe;QACf,SAAS;QACT,gBAAgB;KACjB;IACD,QAAQ,EAAE;QACR,kBAAkB;QAClB,cAAc;QACd,UAAU;KACX;CACkC,CAAC;AActC,MAAM,IAAI,GAAG,iBAA0B,CAAC;AACxC,MAAM,EAAC,KAAK,EAAC,GAAG,IAAA,oBAAW,EAAoB,IAAI,CAAC,CAAC;AAStC,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,iBAAqB;IAC7D,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAG1C,AAAN,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACxC,MAAM,EAAC,OAAO,EAAE,EAAC,MAAM,EAAE,MAAM,EAAC,EAAE,GAAG,EAAC,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE1E,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,MAAM,GAAG,CAAC,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAC,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzC,CAAC;IAIK,AAAN,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACtC,4CAA4C;QAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACnD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,WAAW,CAAC,MAAM,oCAAoC,CAAC,CAAC;QAEjG,MAAM,EAAC,IAAI,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QACzC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,YAAY,GAAG,SAAS,IAAI,aAAa,CAAA;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;QACpC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,IAAI,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;IAGK,AAAN,KAAK,CAAC,qBAAqB;QACzB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;QACnD,MAAM,EAAC,GAAG,EAAC,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;aAChE,GAAG,CAAC,IAAI,CAAC,EAAE;YACV,IAAI,CAAC,GAAG,GAAG,KAAK,IAAI,EAAE;gBACpB,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAA;YACxC,CAAC,CAAA;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAA;QAEJ,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAA;QAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;QACrC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;QACtC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACpD,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC1C,yBAAyB;QACzB,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3C,CAAC;IAGK,AAAN,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QAC9C,+BAA+B;QAC/B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC/C,CAAC;IAIK,AAAN,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAC3C,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC1C,MAAM,EAAC,WAAW,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACjC,IAAI,CAAC;YACH,WAAW,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC5C,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC3B,WAAW,CAAC,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QACjE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAGK,AAAN,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAC5C,MAAM,EAAC,IAAI,EAAE,WAAW,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACvC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAClC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAChE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC7C,CAAC;IAGK,AAAN,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QAC9C,8BAA8B;QAC9B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC/C,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAC1C,wBAAwB;QACxB,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3C,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,EAAC,IAAI,EAAE,WAAW,EAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;QACxE,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC;gBACX,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;qBAC/B,CAAC;aACH,CAAC,CAAA;QAEJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAA;QAC/C,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;CACF,CAAA;AAxJO;IADL,KAAK,CAAC,YAAY,CAAC;;;;8CAYnB;AAIK;IADL,KAAK,CAAC,UAAU,CAAC;;;;4CAkBjB;AAGK;IADL,KAAK,CAAC,uBAAuB,CAAC;;;;yDAmB9B;AAGK;IADL,KAAK,CAAC,cAAc,CAAC;;;;gDAMrB;AAGK;IADL,KAAK,CAAC,kBAAkB,CAAC;;;;oDAMzB;AAIK;IADL,KAAK,CAAC,eAAe,CAAC;;;;iDAetB;AAGK;IADL,KAAK,CAAC,SAAS,CAAC;;;;2CAUhB;AAGK;IADL,KAAK,CAAC,gBAAgB,CAAC;;;;kDAUvB;AAGK;IADL,KAAK,CAAC,kBAAkB,CAAC;;;;oDAMzB;AAGK;IADL,KAAK,CAAC,cAAc,CAAC;;;;gDAMrB;AAGK;IADL,KAAK,CAAC,UAAU,CAAC;;;;4CAsBjB;AA3JkB,YAAY;IAPhC,IAAA,aAAI,EAAC;QACJ,IAAI;QACJ,IAAI;QACJ,WAAW;QACX,YAAY;QACZ,MAAM,EAAE,YAAY;KACrB,CAAC;GACmB,YAAY,CA4JhC;kBA5JoB,YAAY","sourcesContent":["// tools/flows/call-tool.flow.ts\nimport {Flow, FlowBase, FlowHooksOf, FlowPlan, FlowRunOptions, ToolContext, ToolEntry} from '../../common';\nimport {z} from 'zod';\nimport {CallToolRequestSchema, CallToolResultSchema} from '@modelcontextprotocol/sdk/types.js';\nimport {AuthInfo} from \"@modelcontextprotocol/sdk/server/auth/types.js\";\n\nconst inputSchema = z.object({\n request: CallToolRequestSchema,\n ctx: z.any(),\n});\n\nconst outputSchema = CallToolResultSchema;\n\nconst stateSchema = z.object({\n input: z.object({\n name: z.string().min(1).max(64),\n arguments: z.object({}).passthrough().optional(),\n }).passthrough(),\n authInfo: z.any().optional() as z.ZodType<AuthInfo>,\n tool: z.instanceof(ToolEntry),\n toolContext: z.instanceof(ToolContext),\n});\n\nconst plan = {\n pre: [\n 'parseInput',\n 'findTool',\n 'createToolCallContext',\n 'acquireQuota',\n 'acquireSemaphore',\n ],\n execute: [\n 'validateInput',\n 'execute',\n 'validateOutput',\n ],\n finalize: [\n 'releaseSemaphore',\n 'releaseQuota',\n 'finalize',\n ],\n} as const satisfies FlowPlan<string>;\n\ndeclare global {\n interface ExtendFlows {\n 'tools:call-tool': FlowRunOptions<\n CallToolFlow,\n typeof plan,\n typeof inputSchema,\n typeof outputSchema,\n typeof stateSchema\n >;\n }\n}\n\nconst name = 'tools:call-tool' as const;\nconst {Stage} = FlowHooksOf<'tools:call-tool'>(name);\n\n@Flow({\n name,\n plan,\n inputSchema,\n outputSchema,\n access: 'authorized',\n})\nexport default class CallToolFlow extends FlowBase<typeof name> {\n logger = this.scopeLogger.child('CallToolFlow');\n\n @Stage('parseInput')\n async parseInput() {\n this.logger.verbose('parseInput:start');\n const {request: {method, params}, ctx} = inputSchema.parse(this.rawInput);\n\n if (method !== 'tools/call') {\n this.logger.warn(`parseInput: invalid method \"${method}\"`);\n throw new Error('Invalid method');\n }\n\n this.state.set({input: params, authInfo: ctx.authInfo});\n this.logger.verbose('parseInput:done');\n }\n\n\n @Stage('findTool')\n async findTool() {\n this.logger.verbose('findTool:start');\n // TODO: add support for session based tools\n const activeTools = this.scope.tools.getTools(true)\n this.logger.info(`findTool: discovered ${activeTools.length} active tool(s) (including hidden)`);\n\n const {name} = this.state.required.input;\n const tool = activeTools.find(t => t.metadata.name === name);\n if (!tool) {\n const errorMessage = `Tool \"${name}\" not found`\n this.logger.warn(errorMessage);\n this.fail(new Error(errorMessage))\n }\n this.logger = this.logger.child(`CallToolFlow(${name})`);\n this.state.set('tool', tool!);\n this.logger.info(`findTool: tool \"${name}\" found`);\n this.logger.verbose('findTool:done');\n }\n\n @Stage('createToolCallContext')\n async createToolCallContext() {\n this.logger.verbose('createToolCallContext:start');\n const {ctx} = this.input\n const {tool, input} = this.state.required;\n const context = tool.create(input, ctx)\n const toolHooks = this.scope.hooks.getClsHooks(tool.record.provide)\n .map(hook => {\n hook.run = async () => {\n return context[hook.metadata.method]()\n }\n return hook;\n })\n\n this.appendContextHooks(toolHooks)\n context.input = input;\n context.mark('createToolCallContext')\n this.state.set('toolContext', context)\n this.logger.verbose('createToolCallContext:done');\n }\n\n @Stage('acquireQuota')\n async acquireQuota() {\n this.logger.verbose('acquireQuota:start');\n // used for rate limiting\n this.state.toolContext?.mark('acquireQuota')\n this.logger.verbose('acquireQuota:done');\n }\n\n @Stage('acquireSemaphore')\n async acquireSemaphore() {\n this.logger.verbose('acquireSemaphore:start');\n // used for concurrency control\n this.state.toolContext?.mark('acquireSemaphore')\n this.logger.verbose('acquireSemaphore:done');\n }\n\n\n @Stage('validateInput')\n async validateInput() {\n this.logger.verbose('validateInput:start');\n const {tool, input} = this.state.required;\n const {toolContext} = this.state;\n if (!toolContext) {\n return;\n }\n toolContext.mark('validateInput')\n try {\n toolContext.input = tool.inputSchema.parse(input.arguments ?? {});\n } catch (err) {\n this.fail(new Error(`Invalid input: validation failed`));\n }\n this.logger.verbose('validateInput:done');\n }\n\n @Stage('execute')\n async execute() {\n this.logger.verbose('execute:start');\n const toolContext = this.state.toolContext;\n if (!toolContext) {\n return;\n }\n toolContext.mark('execute')\n toolContext.output = await toolContext.execute(toolContext.input)\n this.logger.verbose('execute:done');\n }\n\n @Stage('validateOutput')\n async validateOutput() {\n this.logger.verbose('validateOutput:start');\n const {tool, toolContext} = this.state;\n if (!toolContext || !tool) {\n return;\n }\n toolContext.mark('validateOutput')\n toolContext.output = tool.outputSchema.parse(toolContext.output)\n this.logger.verbose('validateOutput:done');\n }\n\n @Stage('releaseSemaphore')\n async releaseSemaphore() {\n this.logger.verbose('releaseSemaphore:start');\n // release concurrency control\n this.state.toolContext?.mark('releaseSemaphore')\n this.logger.verbose('releaseSemaphore:done');\n }\n\n @Stage('releaseQuota')\n async releaseQuota() {\n this.logger.verbose('releaseQuota:start');\n // release rate limiting\n this.state.toolContext?.mark('releaseQuota')\n this.logger.verbose('releaseQuota:done');\n }\n\n @Stage('finalize')\n async finalize() {\n this.logger.verbose('finalize:start');\n if (!this.state.toolContext) {\n this.fail(new Error(\"error\"))\n return;\n }\n const {tool, toolContext} = this.state.required;\n const success = tool.outputSchema.safeParse(toolContext.output).success;\n if (success) {\n const response = toolContext.output;\n this.respond({\n content: [{\n type: 'text',\n text: JSON.stringify(response)\n }],\n })\n\n } else {\n this.fail(new Error(\"invalid output schema\"))\n }\n this.logger.verbose('finalize:done');\n }\n}\n"]}
1
+ {"version":3,"file":"call-tool.flow.js","sourceRoot":"","sources":["../../../../src/tool/flows/call-tool.flow.ts"],"names":[],"mappings":"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","sourcesContent":["// tools/flows/call-tool.flow.ts\nimport { Flow, FlowBase, FlowHooksOf, FlowPlan, FlowRunOptions, ToolContext, ToolEntry } from '../../common';\nimport { z } from 'zod';\nimport { CallToolRequestSchema, CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';\nimport {\n InvalidMethodError,\n ToolNotFoundError,\n InvalidInputError,\n InvalidOutputError,\n ToolExecutionError,\n} from '../../errors';\n\nconst inputSchema = z.object({\n request: CallToolRequestSchema,\n ctx: z.any(),\n});\n\nconst outputSchema = CallToolResultSchema;\n\nconst stateSchema = z.object({\n input: z\n .object({\n name: z.string().min(1).max(64),\n arguments: z.object({}).passthrough().optional(),\n })\n .passthrough(),\n authInfo: z.any().optional() as z.ZodType<AuthInfo>,\n tool: z.instanceof(ToolEntry),\n toolContext: z.instanceof(ToolContext),\n // Store the raw executed output for plugins to see\n rawOutput: z.any().optional(),\n output: outputSchema,\n});\n\nconst plan = {\n pre: ['parseInput', 'findTool', 'createToolCallContext', 'acquireQuota', 'acquireSemaphore'],\n execute: ['validateInput', 'execute', 'validateOutput'],\n finalize: ['releaseSemaphore', 'releaseQuota', 'finalize'],\n} as const satisfies FlowPlan<string>;\n\ndeclare global {\n interface ExtendFlows {\n 'tools:call-tool': FlowRunOptions<\n CallToolFlow,\n typeof plan,\n typeof inputSchema,\n typeof outputSchema,\n typeof stateSchema\n >;\n }\n}\n\nconst name = 'tools:call-tool' as const;\nconst { Stage } = FlowHooksOf<'tools:call-tool'>(name);\n\n@Flow({\n name,\n plan,\n inputSchema,\n outputSchema,\n access: 'authorized',\n})\nexport default class CallToolFlow extends FlowBase<typeof name> {\n logger = this.scopeLogger.child('CallToolFlow');\n\n @Stage('parseInput')\n async parseInput() {\n this.logger.verbose('parseInput:start');\n\n let method!: string;\n let params: any;\n let ctx: any;\n try {\n const inputData = inputSchema.parse(this.rawInput);\n method = inputData.request.method;\n params = inputData.request.params;\n ctx = inputData.ctx;\n } catch (e) {\n throw new InvalidInputError('Invalid Input', e instanceof z.ZodError ? e.errors : undefined);\n }\n\n if (method !== 'tools/call') {\n this.logger.warn(`parseInput: invalid method \"${method}\"`);\n throw new InvalidMethodError(method, 'tools/call');\n }\n\n // Find the tool early to get its owner ID for hook filtering\n const { name } = params;\n const activeTools = this.scope.tools.getTools(true);\n const tool = activeTools.find((entry) => {\n return entry.fullName === name || entry.name === name;\n });\n\n // Store tool owner ID in the flow input for hook filtering\n if (tool?.owner) {\n (this.rawInput as any)._toolOwnerId = tool.owner.id;\n }\n\n this.state.set({ input: params, authInfo: ctx.authInfo });\n this.logger.verbose('parseInput:done');\n }\n\n @Stage('findTool')\n async findTool() {\n this.logger.verbose('findTool:start');\n // TODO: add support for session based tools\n const activeTools = this.scope.tools.getTools(true);\n this.logger.info(`findTool: discovered ${activeTools.length} active tool(s) (including hidden)`);\n\n const { name } = this.state.required.input;\n const tool = activeTools.find((entry) => {\n return entry.fullName === name || entry.name === name;\n });\n\n if (!tool) {\n this.logger.warn(`findTool: tool \"${name}\" not found`);\n throw new ToolNotFoundError(name);\n }\n\n this.logger = this.logger.child(`CallToolFlow(${name})`);\n this.state.set('tool', tool);\n this.logger.info(`findTool: tool \"${name}\" found`);\n this.logger.verbose('findTool:done');\n }\n\n @Stage('createToolCallContext')\n async createToolCallContext() {\n this.logger.verbose('createToolCallContext:start');\n const { ctx } = this.input;\n const { tool, input } = this.state.required;\n\n try {\n const context = tool.create(input.arguments, ctx);\n const toolHooks = this.scope.hooks.getClsHooks(tool.record.provide).map((hook) => {\n hook.run = async () => {\n return context[hook.metadata.method]();\n };\n return hook;\n });\n\n this.appendContextHooks(toolHooks);\n context.mark('createToolCallContext');\n this.state.set('toolContext', context);\n this.logger.verbose('createToolCallContext:done');\n } catch (error) {\n this.logger.error('createToolCallContext: failed to create context', error);\n throw new ToolExecutionError(tool.metadata.name, error instanceof Error ? error : undefined);\n }\n }\n\n @Stage('acquireQuota')\n async acquireQuota() {\n this.logger.verbose('acquireQuota:start');\n // used for rate limiting\n this.state.toolContext?.mark('acquireQuota');\n this.logger.verbose('acquireQuota:done');\n }\n\n @Stage('acquireSemaphore')\n async acquireSemaphore() {\n this.logger.verbose('acquireSemaphore:start');\n // used for concurrency control\n this.state.toolContext?.mark('acquireSemaphore');\n this.logger.verbose('acquireSemaphore:done');\n }\n\n @Stage('validateInput')\n async validateInput() {\n this.logger.verbose('validateInput:start');\n const { tool, input } = this.state.required;\n const { toolContext } = this.state;\n if (!toolContext) {\n return;\n }\n toolContext.mark('validateInput');\n\n try {\n toolContext.input = tool.parseInput(input);\n this.logger.verbose('validateInput:done');\n } catch (err) {\n if (err instanceof z.ZodError) {\n throw new InvalidInputError('Invalid tool input', err.errors);\n }\n\n this.logger.error('validateInput: failed to parse input', err);\n throw new InvalidInputError('Unknown error occurred when trying to parse input');\n }\n }\n\n @Stage('execute')\n async execute() {\n this.logger.verbose('execute:start');\n const toolContext = this.state.toolContext;\n if (!toolContext) {\n return;\n }\n toolContext.mark('execute');\n\n try {\n toolContext.output = await toolContext.execute(toolContext.input);\n this.logger.verbose('execute:done');\n } catch (error) {\n this.logger.error('execute: tool execution failed', error);\n throw new ToolExecutionError(\n this.state.tool?.metadata.name || 'unknown',\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n @Stage('validateOutput')\n async validateOutput() {\n this.logger.verbose('validateOutput:start');\n const { toolContext } = this.state;\n if (!toolContext) {\n return;\n }\n toolContext.mark('validateOutput');\n\n // Store the RAW output for plugins (cache, PII, etc.) to inspect\n this.state.set('rawOutput', toolContext.output);\n\n this.logger.verbose('validateOutput:done');\n }\n\n @Stage('releaseSemaphore')\n async releaseSemaphore() {\n this.logger.verbose('releaseSemaphore:start');\n // release concurrency control\n this.state.toolContext?.mark('releaseSemaphore');\n this.logger.verbose('releaseSemaphore:done');\n }\n\n @Stage('releaseQuota')\n async releaseQuota() {\n this.logger.verbose('releaseQuota:start');\n // release rate limiting\n this.state.toolContext?.mark('releaseQuota');\n this.logger.verbose('releaseQuota:done');\n }\n\n @Stage('finalize')\n async finalize() {\n this.logger.verbose('finalize:start');\n const { tool, rawOutput } = this.state;\n\n if (!tool) {\n this.logger.error('finalize: tool not found in state');\n throw new ToolExecutionError('unknown', new Error('Tool not found in state'));\n }\n\n if (rawOutput === undefined) {\n this.logger.error('finalize: tool output not found in state');\n throw new ToolExecutionError(tool.metadata.name, new Error('Tool output not found'));\n }\n\n // Parse and construct the MCP-compliant output using safeParseOutput\n const parseResult = tool.safeParseOutput(rawOutput);\n\n if (!parseResult.success) {\n // add support for request id in error messages\n this.logger.error('finalize: output validation failed', {\n tool: tool.metadata.name,\n errors: parseResult.error,\n });\n\n // Use InvalidOutputError, which hides internal details in production\n throw new InvalidOutputError();\n }\n\n // Respond with the properly formatted MCP result\n this.respond(parseResult.data);\n this.logger.verbose('finalize:done');\n }\n}\n"]}