@frontmcp/plugins 0.4.1 → 0.5.1

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 (98) hide show
  1. package/package.json +8 -3
  2. package/src/cache/cache.plugin.js +27 -25
  3. package/src/cache/cache.plugin.js.map +1 -1
  4. package/src/cache/providers/cache-memory.provider.js +2 -1
  5. package/src/cache/providers/cache-memory.provider.js.map +1 -1
  6. package/src/cache/providers/cache-redis.provider.js +1 -0
  7. package/src/cache/providers/cache-redis.provider.js.map +1 -1
  8. package/src/codecall/README.md +999 -0
  9. package/src/codecall/codecall.plugin.d.ts +41 -0
  10. package/src/codecall/codecall.plugin.js +152 -0
  11. package/src/codecall/codecall.plugin.js.map +1 -0
  12. package/src/codecall/codecall.symbol.d.ts +106 -0
  13. package/src/codecall/codecall.symbol.js +4 -0
  14. package/src/codecall/codecall.symbol.js.map +1 -0
  15. package/src/codecall/codecall.types.d.ts +289 -0
  16. package/src/codecall/codecall.types.js +258 -0
  17. package/src/codecall/codecall.types.js.map +1 -0
  18. package/src/codecall/errors/index.d.ts +1 -0
  19. package/src/codecall/errors/index.js +6 -0
  20. package/src/codecall/errors/index.js.map +1 -0
  21. package/src/codecall/errors/tool-call.errors.d.ts +79 -0
  22. package/src/codecall/errors/tool-call.errors.js +119 -0
  23. package/src/codecall/errors/tool-call.errors.js.map +1 -0
  24. package/src/codecall/index.d.ts +2 -0
  25. package/src/codecall/index.js +8 -0
  26. package/src/codecall/index.js.map +1 -0
  27. package/src/codecall/providers/code-call.config.d.ts +29 -0
  28. package/src/codecall/providers/code-call.config.js +120 -0
  29. package/src/codecall/providers/code-call.config.js.map +1 -0
  30. package/src/codecall/security/index.d.ts +2 -0
  31. package/src/codecall/security/index.js +7 -0
  32. package/src/codecall/security/index.js.map +1 -0
  33. package/src/codecall/security/self-reference-guard.d.ts +32 -0
  34. package/src/codecall/security/self-reference-guard.js +70 -0
  35. package/src/codecall/security/self-reference-guard.js.map +1 -0
  36. package/src/codecall/security/tool-access-control.service.d.ts +104 -0
  37. package/src/codecall/security/tool-access-control.service.js +170 -0
  38. package/src/codecall/security/tool-access-control.service.js.map +1 -0
  39. package/src/codecall/services/audit-logger.service.d.ts +186 -0
  40. package/src/codecall/services/audit-logger.service.js +322 -0
  41. package/src/codecall/services/audit-logger.service.js.map +1 -0
  42. package/src/codecall/services/enclave.service.d.ts +62 -0
  43. package/src/codecall/services/enclave.service.js +214 -0
  44. package/src/codecall/services/enclave.service.js.map +1 -0
  45. package/src/codecall/services/error-enrichment.service.d.ts +94 -0
  46. package/src/codecall/services/error-enrichment.service.js +387 -0
  47. package/src/codecall/services/error-enrichment.service.js.map +1 -0
  48. package/src/codecall/services/index.d.ts +6 -0
  49. package/src/codecall/services/index.js +13 -0
  50. package/src/codecall/services/index.js.map +1 -0
  51. package/src/codecall/services/output-sanitizer.d.ts +86 -0
  52. package/src/codecall/services/output-sanitizer.js +260 -0
  53. package/src/codecall/services/output-sanitizer.js.map +1 -0
  54. package/src/codecall/services/synonym-expansion.service.d.ts +66 -0
  55. package/src/codecall/services/synonym-expansion.service.js +374 -0
  56. package/src/codecall/services/synonym-expansion.service.js.map +1 -0
  57. package/src/codecall/services/tool-search.service.d.ts +175 -0
  58. package/src/codecall/services/tool-search.service.js +587 -0
  59. package/src/codecall/services/tool-search.service.js.map +1 -0
  60. package/src/codecall/tools/describe.schema.d.ts +28 -0
  61. package/src/codecall/tools/describe.schema.js +67 -0
  62. package/src/codecall/tools/describe.schema.js.map +1 -0
  63. package/src/codecall/tools/describe.tool.d.ts +35 -0
  64. package/src/codecall/tools/describe.tool.js +207 -0
  65. package/src/codecall/tools/describe.tool.js.map +1 -0
  66. package/src/codecall/tools/execute.schema.d.ts +115 -0
  67. package/src/codecall/tools/execute.schema.js +116 -0
  68. package/src/codecall/tools/execute.schema.js.map +1 -0
  69. package/src/codecall/tools/execute.tool.d.ts +5 -0
  70. package/src/codecall/tools/execute.tool.js +238 -0
  71. package/src/codecall/tools/execute.tool.js.map +1 -0
  72. package/src/codecall/tools/index.d.ts +4 -0
  73. package/src/codecall/tools/index.js +13 -0
  74. package/src/codecall/tools/index.js.map +1 -0
  75. package/src/codecall/tools/invoke.schema.d.ts +99 -0
  76. package/src/codecall/tools/invoke.schema.js +27 -0
  77. package/src/codecall/tools/invoke.schema.js.map +1 -0
  78. package/src/codecall/tools/invoke.tool.d.ts +13 -0
  79. package/src/codecall/tools/invoke.tool.js +70 -0
  80. package/src/codecall/tools/invoke.tool.js.map +1 -0
  81. package/src/codecall/tools/search.schema.d.ts +30 -0
  82. package/src/codecall/tools/search.schema.js +60 -0
  83. package/src/codecall/tools/search.schema.js.map +1 -0
  84. package/src/codecall/tools/search.tool.d.ts +5 -0
  85. package/src/codecall/tools/search.tool.js +108 -0
  86. package/src/codecall/tools/search.tool.js.map +1 -0
  87. package/src/codecall/utils/describe.utils.d.ts +86 -0
  88. package/src/codecall/utils/describe.utils.js +531 -0
  89. package/src/codecall/utils/describe.utils.js.map +1 -0
  90. package/src/codecall/utils/index.d.ts +2 -0
  91. package/src/codecall/utils/index.js +7 -0
  92. package/src/codecall/utils/index.js.map +1 -0
  93. package/src/codecall/utils/mcp-result.d.ts +6 -0
  94. package/src/codecall/utils/mcp-result.js +36 -0
  95. package/src/codecall/utils/mcp-result.js.map +1 -0
  96. package/src/index.d.ts +2 -0
  97. package/src/index.js +3 -1
  98. package/src/index.js.map +1 -1
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ // file: libs/plugins/src/codecall/tools/execute.tool.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ const sdk_1 = require("@frontmcp/sdk");
6
+ const execute_schema_1 = require("./execute.schema");
7
+ const enclave_service_1 = tslib_1.__importDefault(require("../services/enclave.service"));
8
+ const code_call_config_1 = tslib_1.__importDefault(require("../providers/code-call.config"));
9
+ const security_1 = require("../security");
10
+ const errors_1 = require("../errors");
11
+ const utils_1 = require("../utils");
12
+ /**
13
+ * Determine the error code from an error object.
14
+ * Used to categorize errors for sanitized reporting.
15
+ */
16
+ function getErrorCode(error) {
17
+ if (!(error instanceof Error)) {
18
+ return errors_1.TOOL_CALL_ERROR_CODES.EXECUTION;
19
+ }
20
+ // Check for specific error types
21
+ if (error.name === 'ZodError' || error.message?.includes('validation')) {
22
+ return errors_1.TOOL_CALL_ERROR_CODES.VALIDATION;
23
+ }
24
+ if (error.message?.includes('timeout') || error.message?.includes('timed out')) {
25
+ return errors_1.TOOL_CALL_ERROR_CODES.TIMEOUT;
26
+ }
27
+ if (error.name === 'ToolNotFoundError' || error.message?.includes('not found')) {
28
+ return errors_1.TOOL_CALL_ERROR_CODES.NOT_FOUND;
29
+ }
30
+ return errors_1.TOOL_CALL_ERROR_CODES.EXECUTION;
31
+ }
32
+ let ExecuteTool = class ExecuteTool extends sdk_1.ToolContext {
33
+ async execute(input) {
34
+ const { script, allowedTools } = input;
35
+ // Set up the VM environment with tool integration
36
+ const allowedToolSet = allowedTools ? new Set(allowedTools) : null;
37
+ const environment = {
38
+ callTool: async (name, toolInput, options) => {
39
+ const throwOnError = options?.throwOnError !== false; // Default: true
40
+ // ============================================================
41
+ // SECURITY LAYER 1: Self-reference blocking (FIRST CHECK)
42
+ // This MUST be the first check - no exceptions, no try/catch
43
+ // ============================================================
44
+ (0, security_1.assertNotSelfReference)(name);
45
+ // ============================================================
46
+ // SECURITY LAYER 2: Whitelist check (if configured)
47
+ // ============================================================
48
+ if (allowedToolSet && !allowedToolSet.has(name)) {
49
+ const error = (0, errors_1.createToolCallError)(errors_1.TOOL_CALL_ERROR_CODES.ACCESS_DENIED, name);
50
+ if (throwOnError) {
51
+ throw error;
52
+ }
53
+ return { success: false, error };
54
+ }
55
+ // ============================================================
56
+ // Tool execution through the proper flow system
57
+ // This ensures hooks, validation, quota, and all middleware run
58
+ // ============================================================
59
+ try {
60
+ // Build MCP-compatible CallToolRequest
61
+ const request = {
62
+ method: 'tools/call',
63
+ params: {
64
+ name,
65
+ arguments: toolInput,
66
+ },
67
+ };
68
+ // Build context with auth info
69
+ const ctx = {
70
+ authInfo: this.authInfo,
71
+ };
72
+ // Execute through the flow system - this runs all stages:
73
+ // PRE: parseInput → findTool → createToolCallContext → acquireQuota → acquireSemaphore
74
+ // EXECUTE: validateInput → execute → validateOutput
75
+ // FINALIZE: releaseSemaphore → releaseQuota → finalize
76
+ const mcpResult = await this.scope.runFlow('tools:call-tool', { request, ctx });
77
+ if (!mcpResult) {
78
+ const error = (0, errors_1.createToolCallError)(errors_1.TOOL_CALL_ERROR_CODES.EXECUTION, name, 'Flow returned no result');
79
+ if (throwOnError) {
80
+ throw error;
81
+ }
82
+ return { success: false, error };
83
+ }
84
+ // Extract the actual result from MCP CallToolResult format
85
+ const result = (0, utils_1.extractResultFromCallToolResult)(mcpResult);
86
+ // Success path
87
+ if (throwOnError) {
88
+ return result;
89
+ }
90
+ return { success: true, data: result };
91
+ }
92
+ catch (error) {
93
+ // ============================================================
94
+ // Error sanitization - NEVER expose internal details
95
+ // ============================================================
96
+ // Determine error code from the error type
97
+ const errorCode = getErrorCode(error);
98
+ const rawMessage = error instanceof Error ? error.message : undefined;
99
+ const sanitizedError = (0, errors_1.createToolCallError)(errorCode, name, rawMessage);
100
+ if (throwOnError) {
101
+ // Throw sanitized error (no stack trace, no internal details)
102
+ throw sanitizedError;
103
+ }
104
+ return { success: false, error: sanitizedError };
105
+ }
106
+ },
107
+ getTool: (name) => {
108
+ try {
109
+ const tools = this.scope.tools.getTools(true);
110
+ const tool = tools.find((t) => t.name === name || t.fullName === name);
111
+ if (!tool)
112
+ return undefined;
113
+ return {
114
+ name: tool.name,
115
+ description: tool.metadata?.description,
116
+ inputSchema: tool.rawInputSchema,
117
+ outputSchema: tool.outputSchema,
118
+ };
119
+ }
120
+ catch {
121
+ return undefined;
122
+ }
123
+ },
124
+ console: this.get(code_call_config_1.default).get('resolvedVm.allowConsole') ? console : undefined,
125
+ mcpLog: (level, message, metadata) => {
126
+ // Log through FrontMCP logging system if available
127
+ this.logger?.[level](message, metadata);
128
+ },
129
+ mcpNotify: (event, payload) => {
130
+ // Send notifications through FrontMCP notification system if available
131
+ this.logger?.debug('Notification sent', { event, payload });
132
+ },
133
+ };
134
+ // Get the enclave service and config
135
+ const enclaveService = this.get(enclave_service_1.default);
136
+ const config = this.get(code_call_config_1.default);
137
+ try {
138
+ const executionResult = await enclaveService.execute(script, environment);
139
+ // Map execution result to CodeCall result
140
+ if (executionResult.timedOut) {
141
+ return {
142
+ status: 'timeout',
143
+ error: {
144
+ message: `Script execution timed out after ${config.getAll().resolvedVm.timeoutMs}ms`,
145
+ },
146
+ };
147
+ }
148
+ if (!executionResult.success) {
149
+ const error = executionResult.error;
150
+ // Check if it's a validation error (from AST validation)
151
+ if (error.code === 'VALIDATION_ERROR' || error.name === 'ValidationError') {
152
+ return {
153
+ status: 'illegal_access',
154
+ error: {
155
+ kind: 'IllegalBuiltinAccess',
156
+ message: error.message,
157
+ },
158
+ };
159
+ }
160
+ // Check if it's a tool error
161
+ if (error.toolName) {
162
+ return {
163
+ status: 'tool_error',
164
+ error: {
165
+ source: 'tool',
166
+ toolName: error.toolName,
167
+ toolInput: error.toolInput,
168
+ message: error.message,
169
+ code: error.code,
170
+ details: error.details,
171
+ },
172
+ };
173
+ }
174
+ // Otherwise it's a runtime error
175
+ return {
176
+ status: 'runtime_error',
177
+ error: {
178
+ source: 'script',
179
+ message: error.message,
180
+ name: error.name,
181
+ stack: error.stack,
182
+ },
183
+ };
184
+ }
185
+ // Success!
186
+ return {
187
+ status: 'ok',
188
+ result: executionResult.result,
189
+ logs: executionResult.logs.length > 0 ? executionResult.logs : undefined,
190
+ };
191
+ }
192
+ catch (error) {
193
+ // Type-safe error handling
194
+ const errorName = error instanceof Error ? error.name : 'Error';
195
+ const errorMessage = error instanceof Error ? error.message : String(error);
196
+ const errorStack = error instanceof Error ? error.stack : undefined;
197
+ const errorLoc = error.loc;
198
+ // Check for syntax errors
199
+ if (errorName === 'SyntaxError' || errorMessage?.includes('syntax')) {
200
+ return {
201
+ status: 'syntax_error',
202
+ error: {
203
+ message: errorMessage || 'Syntax error in script',
204
+ location: errorLoc ? { line: errorLoc.line, column: errorLoc.column } : undefined,
205
+ },
206
+ };
207
+ }
208
+ // Unexpected error during execution
209
+ return {
210
+ status: 'runtime_error',
211
+ error: {
212
+ source: 'script',
213
+ message: errorMessage || 'An unexpected error occurred during script execution',
214
+ name: errorName,
215
+ stack: errorStack,
216
+ },
217
+ };
218
+ }
219
+ }
220
+ };
221
+ ExecuteTool = tslib_1.__decorate([
222
+ (0, sdk_1.Tool)({
223
+ name: 'codecall:execute',
224
+ cache: {
225
+ ttl: 0, // No caching - each execution is unique
226
+ slideWindow: false,
227
+ },
228
+ codecall: {
229
+ enabledInCodeCall: false,
230
+ visibleInListTools: true,
231
+ },
232
+ description: execute_schema_1.executeToolDescription,
233
+ inputSchema: execute_schema_1.executeToolInputSchema,
234
+ outputSchema: execute_schema_1.executeToolOutputSchema,
235
+ })
236
+ ], ExecuteTool);
237
+ exports.default = ExecuteTool;
238
+ //# sourceMappingURL=execute.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.tool.js","sourceRoot":"","sources":["../../../../src/codecall/tools/execute.tool.ts"],"names":[],"mappings":"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","sourcesContent":["// file: libs/plugins/src/codecall/tools/execute.tool.ts\n\nimport { Tool, ToolContext } from '@frontmcp/sdk';\nimport {\n CodeCallExecuteResult,\n executeToolOutputSchema,\n executeToolDescription,\n executeToolInputSchema,\n ExecuteToolInput,\n} from './execute.schema';\nimport type { CodeCallVmEnvironment } from '../codecall.symbol';\nimport EnclaveService from '../services/enclave.service';\nimport CodeCallConfig from '../providers/code-call.config';\nimport { assertNotSelfReference } from '../security';\nimport {\n createToolCallError,\n TOOL_CALL_ERROR_CODES,\n ToolCallResult,\n CallToolOptions,\n ToolCallErrorCode,\n} from '../errors';\nimport { extractResultFromCallToolResult } from '../utils';\n\n/**\n * Determine the error code from an error object.\n * Used to categorize errors for sanitized reporting.\n */\nfunction getErrorCode(error: unknown): ToolCallErrorCode {\n if (!(error instanceof Error)) {\n return TOOL_CALL_ERROR_CODES.EXECUTION;\n }\n\n // Check for specific error types\n if (error.name === 'ZodError' || error.message?.includes('validation')) {\n return TOOL_CALL_ERROR_CODES.VALIDATION;\n }\n\n if (error.message?.includes('timeout') || error.message?.includes('timed out')) {\n return TOOL_CALL_ERROR_CODES.TIMEOUT;\n }\n\n if (error.name === 'ToolNotFoundError' || error.message?.includes('not found')) {\n return TOOL_CALL_ERROR_CODES.NOT_FOUND;\n }\n\n return TOOL_CALL_ERROR_CODES.EXECUTION;\n}\n\n@Tool({\n name: 'codecall:execute',\n cache: {\n ttl: 0, // No caching - each execution is unique\n slideWindow: false,\n },\n codecall: {\n enabledInCodeCall: false,\n visibleInListTools: true,\n },\n description: executeToolDescription,\n inputSchema: executeToolInputSchema,\n outputSchema: executeToolOutputSchema,\n})\nexport default class ExecuteTool extends ToolContext {\n async execute(input: ExecuteToolInput): Promise<CodeCallExecuteResult> {\n const { script, allowedTools } = input;\n\n // Set up the VM environment with tool integration\n const allowedToolSet = allowedTools ? new Set(allowedTools) : null;\n\n const environment: CodeCallVmEnvironment = {\n callTool: async <TInput, TResult>(\n name: string,\n toolInput: TInput,\n options?: CallToolOptions,\n ): Promise<TResult | ToolCallResult<TResult>> => {\n const throwOnError = options?.throwOnError !== false; // Default: true\n\n // ============================================================\n // SECURITY LAYER 1: Self-reference blocking (FIRST CHECK)\n // This MUST be the first check - no exceptions, no try/catch\n // ============================================================\n assertNotSelfReference(name);\n\n // ============================================================\n // SECURITY LAYER 2: Whitelist check (if configured)\n // ============================================================\n if (allowedToolSet && !allowedToolSet.has(name)) {\n const error = createToolCallError(TOOL_CALL_ERROR_CODES.ACCESS_DENIED, name);\n if (throwOnError) {\n throw error;\n }\n return { success: false, error };\n }\n\n // ============================================================\n // Tool execution through the proper flow system\n // This ensures hooks, validation, quota, and all middleware run\n // ============================================================\n try {\n // Build MCP-compatible CallToolRequest\n const request = {\n method: 'tools/call' as const,\n params: {\n name,\n arguments: toolInput as Record<string, unknown>,\n },\n };\n\n // Build context with auth info\n const ctx = {\n authInfo: this.authInfo,\n };\n\n // Execute through the flow system - this runs all stages:\n // PRE: parseInput → findTool → createToolCallContext → acquireQuota → acquireSemaphore\n // EXECUTE: validateInput → execute → validateOutput\n // FINALIZE: releaseSemaphore → releaseQuota → finalize\n const mcpResult = await this.scope.runFlow('tools:call-tool', { request, ctx });\n\n if (!mcpResult) {\n const error = createToolCallError(TOOL_CALL_ERROR_CODES.EXECUTION, name, 'Flow returned no result');\n if (throwOnError) {\n throw error;\n }\n return { success: false, error };\n }\n\n // Extract the actual result from MCP CallToolResult format\n const result = extractResultFromCallToolResult(mcpResult);\n\n // Success path\n if (throwOnError) {\n return result as TResult;\n }\n return { success: true, data: result as TResult };\n } catch (error: unknown) {\n // ============================================================\n // Error sanitization - NEVER expose internal details\n // ============================================================\n\n // Determine error code from the error type\n const errorCode = getErrorCode(error);\n const rawMessage = error instanceof Error ? error.message : undefined;\n\n const sanitizedError = createToolCallError(errorCode, name, rawMessage);\n\n if (throwOnError) {\n // Throw sanitized error (no stack trace, no internal details)\n throw sanitizedError;\n }\n return { success: false, error: sanitizedError };\n }\n },\n\n getTool: (name: string) => {\n try {\n const tools = this.scope.tools.getTools(true);\n const tool = tools.find((t) => t.name === name || t.fullName === name);\n\n if (!tool) return undefined;\n\n return {\n name: tool.name,\n description: tool.metadata?.description,\n inputSchema: tool.rawInputSchema,\n outputSchema: tool.outputSchema,\n };\n } catch {\n return undefined;\n }\n },\n\n console: this.get(CodeCallConfig).get('resolvedVm.allowConsole') ? console : undefined,\n\n mcpLog: (level: 'debug' | 'info' | 'warn' | 'error', message: string, metadata?: Record<string, unknown>) => {\n // Log through FrontMCP logging system if available\n this.logger?.[level](message, metadata);\n },\n\n mcpNotify: (event: string, payload: Record<string, unknown>) => {\n // Send notifications through FrontMCP notification system if available\n this.logger?.debug('Notification sent', { event, payload });\n },\n };\n\n // Get the enclave service and config\n const enclaveService = this.get(EnclaveService);\n const config = this.get(CodeCallConfig);\n\n try {\n const executionResult = await enclaveService.execute(script, environment);\n\n // Map execution result to CodeCall result\n if (executionResult.timedOut) {\n return {\n status: 'timeout',\n error: {\n message: `Script execution timed out after ${config.getAll().resolvedVm.timeoutMs}ms`,\n },\n };\n }\n\n if (!executionResult.success) {\n const error = executionResult.error!;\n\n // Check if it's a validation error (from AST validation)\n if (error.code === 'VALIDATION_ERROR' || error.name === 'ValidationError') {\n return {\n status: 'illegal_access',\n error: {\n kind: 'IllegalBuiltinAccess',\n message: error.message,\n },\n };\n }\n\n // Check if it's a tool error\n if (error.toolName) {\n return {\n status: 'tool_error',\n error: {\n source: 'tool',\n toolName: error.toolName,\n toolInput: error.toolInput,\n message: error.message,\n code: error.code,\n details: error.details,\n },\n };\n }\n\n // Otherwise it's a runtime error\n return {\n status: 'runtime_error',\n error: {\n source: 'script',\n message: error.message,\n name: error.name,\n stack: error.stack,\n },\n };\n }\n\n // Success!\n return {\n status: 'ok',\n result: executionResult.result,\n logs: executionResult.logs.length > 0 ? executionResult.logs : undefined,\n };\n } catch (error: unknown) {\n // Type-safe error handling\n const errorName = error instanceof Error ? error.name : 'Error';\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n const errorLoc = (error as { loc?: { line: number; column: number } }).loc;\n\n // Check for syntax errors\n if (errorName === 'SyntaxError' || errorMessage?.includes('syntax')) {\n return {\n status: 'syntax_error',\n error: {\n message: errorMessage || 'Syntax error in script',\n location: errorLoc ? { line: errorLoc.line, column: errorLoc.column } : undefined,\n },\n };\n }\n\n // Unexpected error during execution\n return {\n status: 'runtime_error',\n error: {\n source: 'script',\n message: errorMessage || 'An unexpected error occurred during script execution',\n name: errorName,\n stack: errorStack,\n },\n };\n }\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { default as SearchTool } from './search.tool';
2
+ export { default as DescribeTool } from './describe.tool';
3
+ export { default as ExecuteTool } from './execute.tool';
4
+ export { default as InvokeTool } from './invoke.tool';
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvokeTool = exports.ExecuteTool = exports.DescribeTool = exports.SearchTool = void 0;
4
+ const tslib_1 = require("tslib");
5
+ var search_tool_1 = require("./search.tool");
6
+ Object.defineProperty(exports, "SearchTool", { enumerable: true, get: function () { return tslib_1.__importDefault(search_tool_1).default; } });
7
+ var describe_tool_1 = require("./describe.tool");
8
+ Object.defineProperty(exports, "DescribeTool", { enumerable: true, get: function () { return tslib_1.__importDefault(describe_tool_1).default; } });
9
+ var execute_tool_1 = require("./execute.tool");
10
+ Object.defineProperty(exports, "ExecuteTool", { enumerable: true, get: function () { return tslib_1.__importDefault(execute_tool_1).default; } });
11
+ var invoke_tool_1 = require("./invoke.tool");
12
+ Object.defineProperty(exports, "InvokeTool", { enumerable: true, get: function () { return tslib_1.__importDefault(invoke_tool_1).default; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/codecall/tools/index.ts"],"names":[],"mappings":";;;;AAAA,6CAAsD;AAA7C,kIAAA,OAAO,OAAc;AAC9B,iDAA0D;AAAjD,sIAAA,OAAO,OAAgB;AAChC,+CAAwD;AAA/C,oIAAA,OAAO,OAAe;AAC/B,6CAAsD;AAA7C,kIAAA,OAAO,OAAc","sourcesContent":["export { default as SearchTool } from './search.tool';\nexport { default as DescribeTool } from './describe.tool';\nexport { default as ExecuteTool } from './execute.tool';\nexport { default as InvokeTool } from './invoke.tool';\n"]}
@@ -0,0 +1,99 @@
1
+ import { z } from 'zod';
2
+ export declare const invokeToolDescription = "Call ONE tool directly. Returns standard MCP CallToolResult.\n\nUSE invoke: single tool, no transformation\nUSE execute: multiple tools, loops, filtering, joining\n\nINPUT: tool (string), input (object matching tool schema)\nOUTPUT: MCP CallToolResult (same as standard tool call)\nERRORS: tool_not_found (\u2192 re-search) | validation_error | execution_error | permission_denied\n\nFLOW: search \u2192 describe \u2192 invoke";
3
+ export declare const invokeToolInputSchema: z.ZodObject<{
4
+ tool: z.ZodString;
5
+ input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
6
+ }, z.core.$strip>;
7
+ export type InvokeToolInput = z.infer<typeof invokeToolInputSchema>;
8
+ export declare const invokeToolOutputSchema: z.ZodObject<{
9
+ _meta: z.ZodOptional<z.ZodObject<{
10
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
11
+ taskId: z.ZodString;
12
+ }, z.core.$loose>>;
13
+ }, z.core.$loose>>;
14
+ content: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
15
+ type: z.ZodLiteral<"text">;
16
+ text: z.ZodString;
17
+ annotations: z.ZodOptional<z.ZodObject<{
18
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
19
+ user: "user";
20
+ assistant: "assistant";
21
+ }>>>;
22
+ priority: z.ZodOptional<z.ZodNumber>;
23
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
24
+ }, z.core.$strip>>;
25
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
26
+ }, z.core.$strip>, z.ZodObject<{
27
+ type: z.ZodLiteral<"image">;
28
+ data: z.ZodString;
29
+ mimeType: z.ZodString;
30
+ annotations: z.ZodOptional<z.ZodObject<{
31
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
32
+ user: "user";
33
+ assistant: "assistant";
34
+ }>>>;
35
+ priority: z.ZodOptional<z.ZodNumber>;
36
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
37
+ }, z.core.$strip>>;
38
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
39
+ }, z.core.$strip>, z.ZodObject<{
40
+ type: z.ZodLiteral<"audio">;
41
+ data: z.ZodString;
42
+ mimeType: z.ZodString;
43
+ annotations: z.ZodOptional<z.ZodObject<{
44
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
45
+ user: "user";
46
+ assistant: "assistant";
47
+ }>>>;
48
+ priority: z.ZodOptional<z.ZodNumber>;
49
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
50
+ }, z.core.$strip>>;
51
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
52
+ }, z.core.$strip>, z.ZodObject<{
53
+ uri: z.ZodString;
54
+ description: z.ZodOptional<z.ZodString>;
55
+ mimeType: z.ZodOptional<z.ZodString>;
56
+ annotations: z.ZodOptional<z.ZodObject<{
57
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
58
+ user: "user";
59
+ assistant: "assistant";
60
+ }>>>;
61
+ priority: z.ZodOptional<z.ZodNumber>;
62
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
63
+ }, z.core.$strip>>;
64
+ _meta: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
65
+ icons: z.ZodOptional<z.ZodArray<z.ZodObject<{
66
+ src: z.ZodString;
67
+ mimeType: z.ZodOptional<z.ZodString>;
68
+ sizes: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ }, z.core.$strip>>>;
70
+ name: z.ZodString;
71
+ title: z.ZodOptional<z.ZodString>;
72
+ type: z.ZodLiteral<"resource_link">;
73
+ }, z.core.$strip>, z.ZodObject<{
74
+ type: z.ZodLiteral<"resource">;
75
+ resource: z.ZodUnion<readonly [z.ZodObject<{
76
+ uri: z.ZodString;
77
+ mimeType: z.ZodOptional<z.ZodString>;
78
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
79
+ text: z.ZodString;
80
+ }, z.core.$strip>, z.ZodObject<{
81
+ uri: z.ZodString;
82
+ mimeType: z.ZodOptional<z.ZodString>;
83
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
84
+ blob: z.ZodString;
85
+ }, z.core.$strip>]>;
86
+ annotations: z.ZodOptional<z.ZodObject<{
87
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
88
+ user: "user";
89
+ assistant: "assistant";
90
+ }>>>;
91
+ priority: z.ZodOptional<z.ZodNumber>;
92
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
93
+ }, z.core.$strip>>;
94
+ _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
95
+ }, z.core.$strip>]>>>;
96
+ structuredContent: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
97
+ isError: z.ZodOptional<z.ZodBoolean>;
98
+ }, z.core.$loose>;
99
+ export type InvokeToolOutput = z.infer<typeof invokeToolOutputSchema>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invokeToolOutputSchema = exports.invokeToolInputSchema = exports.invokeToolDescription = void 0;
4
+ // file: libs/plugins/src/codecall/tools/invoke.schema.ts
5
+ const zod_1 = require("zod");
6
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
+ exports.invokeToolDescription = `Call ONE tool directly. Returns standard MCP CallToolResult.
8
+
9
+ USE invoke: single tool, no transformation
10
+ USE execute: multiple tools, loops, filtering, joining
11
+
12
+ INPUT: tool (string), input (object matching tool schema)
13
+ OUTPUT: MCP CallToolResult (same as standard tool call)
14
+ ERRORS: tool_not_found (→ re-search) | validation_error | execution_error | permission_denied
15
+
16
+ FLOW: search → describe → invoke`;
17
+ exports.invokeToolInputSchema = zod_1.z.object({
18
+ tool: zod_1.z
19
+ .string()
20
+ .describe('The name of the tool to invoke (e.g., "users:getById", "billing:getInvoice"). Must be a tool you discovered via codecall:search.'),
21
+ input: zod_1.z
22
+ .record(zod_1.z.string(), zod_1.z.unknown())
23
+ .describe("The input parameters for the tool. Structure must match the tool's input schema (check codecall:describe for schema details)."),
24
+ });
25
+ // Use standard MCP CallToolResult schema - returns same format as direct tool call
26
+ exports.invokeToolOutputSchema = types_js_1.CallToolResultSchema;
27
+ //# sourceMappingURL=invoke.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.schema.js","sourceRoot":"","sources":["../../../../src/codecall/tools/invoke.schema.ts"],"names":[],"mappings":";;;AAAA,yDAAyD;AACzD,6BAAwB;AACxB,iEAA0E;AAE7D,QAAA,qBAAqB,GAAG;;;;;;;;;iCASJ,CAAC;AAErB,QAAA,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,OAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CACP,kIAAkI,CACnI;IACH,KAAK,EAAE,OAAC;SACL,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC;SAC/B,QAAQ,CACP,+HAA+H,CAChI;CACJ,CAAC,CAAC;AAIH,mFAAmF;AACtE,QAAA,sBAAsB,GAAG,+BAAoB,CAAC","sourcesContent":["// file: libs/plugins/src/codecall/tools/invoke.schema.ts\nimport { z } from 'zod';\nimport { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';\n\nexport const invokeToolDescription = `Call ONE tool directly. Returns standard MCP CallToolResult.\n\nUSE invoke: single tool, no transformation\nUSE execute: multiple tools, loops, filtering, joining\n\nINPUT: tool (string), input (object matching tool schema)\nOUTPUT: MCP CallToolResult (same as standard tool call)\nERRORS: tool_not_found (→ re-search) | validation_error | execution_error | permission_denied\n\nFLOW: search → describe → invoke`;\n\nexport const invokeToolInputSchema = z.object({\n tool: z\n .string()\n .describe(\n 'The name of the tool to invoke (e.g., \"users:getById\", \"billing:getInvoice\"). Must be a tool you discovered via codecall:search.',\n ),\n input: z\n .record(z.string(), z.unknown())\n .describe(\n \"The input parameters for the tool. Structure must match the tool's input schema (check codecall:describe for schema details).\",\n ),\n});\n\nexport type InvokeToolInput = z.infer<typeof invokeToolInputSchema>;\n\n// Use standard MCP CallToolResult schema - returns same format as direct tool call\nexport const invokeToolOutputSchema = CallToolResultSchema;\n\nexport type InvokeToolOutput = z.infer<typeof invokeToolOutputSchema>;\n"]}
@@ -0,0 +1,13 @@
1
+ import { ToolContext } from '@frontmcp/sdk';
2
+ import { InvokeToolInput, InvokeToolOutput } from './invoke.schema';
3
+ /**
4
+ * InvokeTool allows direct tool invocation without running JavaScript code.
5
+ * Returns the same CallToolResult format as a standard MCP tool call.
6
+ *
7
+ * Security Considerations:
8
+ * - Self-reference blocking: Cannot invoke codecall:* tools
9
+ * - All middleware (auth, PII, rate limiting) applies via normal tool execution
10
+ */
11
+ export default class InvokeTool extends ToolContext {
12
+ execute(input: InvokeToolInput): Promise<InvokeToolOutput>;
13
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ // file: libs/plugins/src/codecall/tools/invoke.tool.ts
5
+ const sdk_1 = require("@frontmcp/sdk");
6
+ const invoke_schema_1 = require("./invoke.schema");
7
+ const security_1 = require("../security");
8
+ /**
9
+ * Build an MCP error response in CallToolResult format.
10
+ */
11
+ function buildErrorResult(message) {
12
+ return {
13
+ content: [{ type: 'text', text: message }],
14
+ isError: true,
15
+ };
16
+ }
17
+ /**
18
+ * InvokeTool allows direct tool invocation without running JavaScript code.
19
+ * Returns the same CallToolResult format as a standard MCP tool call.
20
+ *
21
+ * Security Considerations:
22
+ * - Self-reference blocking: Cannot invoke codecall:* tools
23
+ * - All middleware (auth, PII, rate limiting) applies via normal tool execution
24
+ */
25
+ let InvokeTool = class InvokeTool extends sdk_1.ToolContext {
26
+ async execute(input) {
27
+ const { tool: toolName, input: toolInput } = input;
28
+ // Security: Cannot invoke codecall:* tools to prevent recursion attacks
29
+ if ((0, security_1.isBlockedSelfReference)(toolName)) {
30
+ return buildErrorResult(`Tool "${toolName}" cannot be invoked directly. CodeCall tools are internal and not accessible via codecall:invoke.`);
31
+ }
32
+ // Execute through the flow system - returns standard CallToolResult
33
+ // Flow handles: findTool, validation, quota, middleware, execution, error formatting
34
+ const request = {
35
+ method: 'tools/call',
36
+ params: {
37
+ name: toolName,
38
+ arguments: toolInput,
39
+ },
40
+ };
41
+ const ctx = {
42
+ authInfo: this.authInfo,
43
+ };
44
+ // runFlow returns CallToolResult directly - no transformation needed
45
+ const result = await this.scope.runFlow('tools:call-tool', { request, ctx });
46
+ // Flow returns null if tool not found or other pre-execution errors
47
+ if (!result) {
48
+ return buildErrorResult(`Tool "${toolName}" not found. Use codecall:search to discover available tools.`);
49
+ }
50
+ return result;
51
+ }
52
+ };
53
+ InvokeTool = tslib_1.__decorate([
54
+ (0, sdk_1.Tool)({
55
+ name: 'codecall:invoke',
56
+ cache: {
57
+ ttl: 0, // No caching - each invocation is unique
58
+ slideWindow: false,
59
+ },
60
+ codecall: {
61
+ enabledInCodeCall: false,
62
+ visibleInListTools: true,
63
+ },
64
+ description: invoke_schema_1.invokeToolDescription,
65
+ inputSchema: invoke_schema_1.invokeToolInputSchema,
66
+ outputSchema: invoke_schema_1.invokeToolOutputSchema,
67
+ })
68
+ ], InvokeTool);
69
+ exports.default = InvokeTool;
70
+ //# sourceMappingURL=invoke.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.tool.js","sourceRoot":"","sources":["../../../../src/codecall/tools/invoke.tool.ts"],"names":[],"mappings":";;;AAAA,uDAAuD;AACvD,uCAAkD;AAElD,mDAMyB;AACzB,0CAAqD;AAErD;;GAEG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AAeY,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,iBAAW;IACjD,KAAK,CAAC,OAAO,CAAC,KAAsB;QAClC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;QAEnD,wEAAwE;QACxE,IAAI,IAAA,iCAAsB,EAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,OAAO,gBAAgB,CACrB,SAAS,QAAQ,mGAAmG,CACrH,CAAC;QACJ,CAAC;QAED,oEAAoE;QACpE,qFAAqF;QACrF,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,YAAqB;YAC7B,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,SAAS;aACrB;SACF,CAAC;QAEF,MAAM,GAAG,GAAG;YACV,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;QAEF,qEAAqE;QACrE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QAE7E,oEAAoE;QACpE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,gBAAgB,CAAC,SAAS,QAAQ,+DAA+D,CAAC,CAAC;QAC5G,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AAnCoB,UAAU;IAd9B,IAAA,UAAI,EAAC;QACJ,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE;YACL,GAAG,EAAE,CAAC,EAAE,yCAAyC;YACjD,WAAW,EAAE,KAAK;SACnB;QACD,QAAQ,EAAE;YACR,iBAAiB,EAAE,KAAK;YACxB,kBAAkB,EAAE,IAAI;SACzB;QACD,WAAW,EAAE,qCAAqB;QAClC,WAAW,EAAE,qCAAqB;QAClC,YAAY,EAAE,sCAAsB;KACrC,CAAC;GACmB,UAAU,CAmC9B;kBAnCoB,UAAU","sourcesContent":["// file: libs/plugins/src/codecall/tools/invoke.tool.ts\nimport { Tool, ToolContext } from '@frontmcp/sdk';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n InvokeToolInput,\n invokeToolInputSchema,\n InvokeToolOutput,\n invokeToolOutputSchema,\n invokeToolDescription,\n} from './invoke.schema';\nimport { isBlockedSelfReference } from '../security';\n\n/**\n * Build an MCP error response in CallToolResult format.\n */\nfunction buildErrorResult(message: string): CallToolResult {\n return {\n content: [{ type: 'text', text: message }],\n isError: true,\n };\n}\n\n/**\n * InvokeTool allows direct tool invocation without running JavaScript code.\n * Returns the same CallToolResult format as a standard MCP tool call.\n *\n * Security Considerations:\n * - Self-reference blocking: Cannot invoke codecall:* tools\n * - All middleware (auth, PII, rate limiting) applies via normal tool execution\n */\n@Tool({\n name: 'codecall:invoke',\n cache: {\n ttl: 0, // No caching - each invocation is unique\n slideWindow: false,\n },\n codecall: {\n enabledInCodeCall: false,\n visibleInListTools: true,\n },\n description: invokeToolDescription,\n inputSchema: invokeToolInputSchema,\n outputSchema: invokeToolOutputSchema,\n})\nexport default class InvokeTool extends ToolContext {\n async execute(input: InvokeToolInput): Promise<InvokeToolOutput> {\n const { tool: toolName, input: toolInput } = input;\n\n // Security: Cannot invoke codecall:* tools to prevent recursion attacks\n if (isBlockedSelfReference(toolName)) {\n return buildErrorResult(\n `Tool \"${toolName}\" cannot be invoked directly. CodeCall tools are internal and not accessible via codecall:invoke.`,\n );\n }\n\n // Execute through the flow system - returns standard CallToolResult\n // Flow handles: findTool, validation, quota, middleware, execution, error formatting\n const request = {\n method: 'tools/call' as const,\n params: {\n name: toolName,\n arguments: toolInput,\n },\n };\n\n const ctx = {\n authInfo: this.authInfo,\n };\n\n // runFlow returns CallToolResult directly - no transformation needed\n const result = await this.scope.runFlow('tools:call-tool', { request, ctx });\n\n // Flow returns null if tool not found or other pre-execution errors\n if (!result) {\n return buildErrorResult(`Tool \"${toolName}\" not found. Use codecall:search to discover available tools.`);\n }\n\n return result;\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ export declare const searchToolDescription = "Find tools by splitting user request into atomic actions.\n\nDECOMPOSE: \"delete users and send email\" \u2192 queries: [\"delete user\", \"send email\"]\nDECOMPOSE: \"get order and refund\" \u2192 queries: [\"get order\", \"calculate refund\"]\n\nAVOID RE-SEARCHING: Use excludeToolNames for already-discovered tools.\nRE-SEARCH WHEN: describe fails (typo?) OR execute returns tool_not_found.\n\nINPUT:\n- queries: string[] (required) - atomic action phrases, max 10\n- appIds?: string[] - filter by app\n- excludeToolNames?: string[] - skip known tools\n- topK?: number (default 5) - results per query\n- minRelevanceScore?: number (default 0.3) - minimum match threshold\n\nOUTPUT: Flat deduplicated tool list. relevanceScore: 0.5+=good, 0.7+=strong match.\n\nFLOW: search \u2192 describe \u2192 execute/invoke";
3
+ export declare const searchToolInputSchema: z.ZodObject<{
4
+ queries: z.ZodArray<z.ZodString>;
5
+ appIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ excludeToolNames: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
+ topK: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
8
+ minRelevanceScore: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
9
+ }, z.core.$strip>;
10
+ export type SearchToolInput = z.infer<typeof searchToolInputSchema>;
11
+ export declare const searchToolOutputSchema: z.ZodObject<{
12
+ tools: z.ZodArray<z.ZodObject<{
13
+ name: z.ZodString;
14
+ appId: z.ZodOptional<z.ZodString>;
15
+ description: z.ZodString;
16
+ relevanceScore: z.ZodNumber;
17
+ matchedQueries: z.ZodArray<z.ZodString>;
18
+ }, z.core.$strip>>;
19
+ warnings: z.ZodArray<z.ZodObject<{
20
+ type: z.ZodEnum<{
21
+ excluded_tool_not_found: "excluded_tool_not_found";
22
+ no_results: "no_results";
23
+ low_relevance: "low_relevance";
24
+ }>;
25
+ message: z.ZodString;
26
+ affectedTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
+ }, z.core.$strip>>;
28
+ totalAvailableTools: z.ZodNumber;
29
+ }, z.core.$strip>;
30
+ export type SearchToolOutput = z.infer<typeof searchToolOutputSchema>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.searchToolOutputSchema = exports.searchToolInputSchema = exports.searchToolDescription = void 0;
4
+ // file: libs/plugins/src/codecall/tools/search.schema.ts
5
+ const zod_1 = require("zod");
6
+ exports.searchToolDescription = `Find tools by splitting user request into atomic actions.
7
+
8
+ DECOMPOSE: "delete users and send email" → queries: ["delete user", "send email"]
9
+ DECOMPOSE: "get order and refund" → queries: ["get order", "calculate refund"]
10
+
11
+ AVOID RE-SEARCHING: Use excludeToolNames for already-discovered tools.
12
+ RE-SEARCH WHEN: describe fails (typo?) OR execute returns tool_not_found.
13
+
14
+ INPUT:
15
+ - queries: string[] (required) - atomic action phrases, max 10
16
+ - appIds?: string[] - filter by app
17
+ - excludeToolNames?: string[] - skip known tools
18
+ - topK?: number (default 5) - results per query
19
+ - minRelevanceScore?: number (default 0.3) - minimum match threshold
20
+
21
+ OUTPUT: Flat deduplicated tool list. relevanceScore: 0.5+=good, 0.7+=strong match.
22
+
23
+ FLOW: search → describe → execute/invoke`;
24
+ exports.searchToolInputSchema = zod_1.z.object({
25
+ queries: zod_1.z
26
+ .array(zod_1.z.string().min(2).max(256))
27
+ .min(1)
28
+ .max(10)
29
+ .describe('Atomic action queries. Split complex requests into simple actions.'),
30
+ appIds: zod_1.z.array(zod_1.z.string()).max(10).optional().describe('Filter by app IDs'),
31
+ excludeToolNames: zod_1.z.array(zod_1.z.string()).max(50).optional().describe('Skip already-known tool names'),
32
+ topK: zod_1.z.number().int().positive().max(50).optional().default(10).describe('Results per query (default 10)'),
33
+ minRelevanceScore: zod_1.z
34
+ .number()
35
+ .min(0)
36
+ .max(1)
37
+ .optional()
38
+ .default(0.1)
39
+ .describe('Minimum relevance threshold (default 0.1)'),
40
+ });
41
+ exports.searchToolOutputSchema = zod_1.z.object({
42
+ tools: zod_1.z
43
+ .array(zod_1.z.object({
44
+ name: zod_1.z.string().describe('Tool name (e.g., "users:list")'),
45
+ appId: zod_1.z.string().optional().describe('App ID'),
46
+ description: zod_1.z.string().describe('What this tool does'),
47
+ relevanceScore: zod_1.z.number().min(0).max(1).describe('Match score (0-1)'),
48
+ matchedQueries: zod_1.z.array(zod_1.z.string()).describe('Which queries matched this tool'),
49
+ }))
50
+ .describe('Deduplicated tools sorted by relevance'),
51
+ warnings: zod_1.z
52
+ .array(zod_1.z.object({
53
+ type: zod_1.z.enum(['excluded_tool_not_found', 'no_results', 'low_relevance']).describe('Warning type'),
54
+ message: zod_1.z.string().describe('Warning message'),
55
+ affectedTools: zod_1.z.array(zod_1.z.string()).optional().describe('Affected tool names'),
56
+ }))
57
+ .describe('Search warnings'),
58
+ totalAvailableTools: zod_1.z.number().int().nonnegative().describe('Total tools in index'),
59
+ });
60
+ //# sourceMappingURL=search.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.schema.js","sourceRoot":"","sources":["../../../../src/codecall/tools/search.schema.ts"],"names":[],"mappings":";;;AAAA,yDAAyD;AACzD,6BAAwB;AAEX,QAAA,qBAAqB,GAAG;;;;;;;;;;;;;;;;;yCAiBI,CAAC;AAE7B,QAAA,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5C,OAAO,EAAE,OAAC;SACP,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,CAAC,oEAAoE,CAAC;IACjF,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAC5E,gBAAgB,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAClG,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAC3G,iBAAiB,EAAE,OAAC;SACjB,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,OAAO,CAAC,GAAG,CAAC;SACZ,QAAQ,CAAC,2CAA2C,CAAC;CACzD,CAAC,CAAC;AAIU,QAAA,sBAAsB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7C,KAAK,EAAE,OAAC;SACL,KAAK,CACJ,OAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAC3D,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/C,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QACvD,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACtE,cAAc,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;KAChF,CAAC,CACH;SACA,QAAQ,CAAC,wCAAwC,CAAC;IACrD,QAAQ,EAAE,OAAC;SACR,KAAK,CACJ,OAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,yBAAyB,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;QACjG,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/C,aAAa,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;KAC9E,CAAC,CACH;SACA,QAAQ,CAAC,iBAAiB,CAAC;IAC9B,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACrF,CAAC,CAAC","sourcesContent":["// file: libs/plugins/src/codecall/tools/search.schema.ts\nimport { z } from 'zod';\n\nexport const searchToolDescription = `Find tools by splitting user request into atomic actions.\n\nDECOMPOSE: \"delete users and send email\" → queries: [\"delete user\", \"send email\"]\nDECOMPOSE: \"get order and refund\" → queries: [\"get order\", \"calculate refund\"]\n\nAVOID RE-SEARCHING: Use excludeToolNames for already-discovered tools.\nRE-SEARCH WHEN: describe fails (typo?) OR execute returns tool_not_found.\n\nINPUT:\n- queries: string[] (required) - atomic action phrases, max 10\n- appIds?: string[] - filter by app\n- excludeToolNames?: string[] - skip known tools\n- topK?: number (default 5) - results per query\n- minRelevanceScore?: number (default 0.3) - minimum match threshold\n\nOUTPUT: Flat deduplicated tool list. relevanceScore: 0.5+=good, 0.7+=strong match.\n\nFLOW: search → describe → execute/invoke`;\n\nexport const searchToolInputSchema = z.object({\n queries: z\n .array(z.string().min(2).max(256))\n .min(1)\n .max(10)\n .describe('Atomic action queries. Split complex requests into simple actions.'),\n appIds: z.array(z.string()).max(10).optional().describe('Filter by app IDs'),\n excludeToolNames: z.array(z.string()).max(50).optional().describe('Skip already-known tool names'),\n topK: z.number().int().positive().max(50).optional().default(10).describe('Results per query (default 10)'),\n minRelevanceScore: z\n .number()\n .min(0)\n .max(1)\n .optional()\n .default(0.1)\n .describe('Minimum relevance threshold (default 0.1)'),\n});\n\nexport type SearchToolInput = z.infer<typeof searchToolInputSchema>;\n\nexport const searchToolOutputSchema = z.object({\n tools: z\n .array(\n z.object({\n name: z.string().describe('Tool name (e.g., \"users:list\")'),\n appId: z.string().optional().describe('App ID'),\n description: z.string().describe('What this tool does'),\n relevanceScore: z.number().min(0).max(1).describe('Match score (0-1)'),\n matchedQueries: z.array(z.string()).describe('Which queries matched this tool'),\n }),\n )\n .describe('Deduplicated tools sorted by relevance'),\n warnings: z\n .array(\n z.object({\n type: z.enum(['excluded_tool_not_found', 'no_results', 'low_relevance']).describe('Warning type'),\n message: z.string().describe('Warning message'),\n affectedTools: z.array(z.string()).optional().describe('Affected tool names'),\n }),\n )\n .describe('Search warnings'),\n totalAvailableTools: z.number().int().nonnegative().describe('Total tools in index'),\n});\n\nexport type SearchToolOutput = z.infer<typeof searchToolOutputSchema>;\n"]}
@@ -0,0 +1,5 @@
1
+ import { ToolContext } from '@frontmcp/sdk';
2
+ import { SearchToolInput, SearchToolOutput } from './search.schema';
3
+ export default class SearchTool extends ToolContext {
4
+ execute(input: SearchToolInput): Promise<SearchToolOutput>;
5
+ }