@frontmcp/plugin-codecall 1.8.5 → 1.8.7

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/esm/index.mjs CHANGED
@@ -2768,6 +2768,43 @@ function generateSampleParams(schema) {
2768
2768
  }
2769
2769
  return Object.keys(params).length > 0 ? params : null;
2770
2770
  }
2771
+ function fitString(schema, value) {
2772
+ let fitted = value;
2773
+ if (schema.maxLength !== void 0 && fitted.length > schema.maxLength) {
2774
+ fitted = fitted.slice(0, Math.max(0, schema.maxLength));
2775
+ }
2776
+ if (schema.minLength !== void 0 && fitted.length < schema.minLength) {
2777
+ fitted = fitted.padEnd(schema.minLength, "x");
2778
+ }
2779
+ return fitted;
2780
+ }
2781
+ function isFreeTextString(schema) {
2782
+ return schema?.type === "string" && schema.enum === void 0 && schema.const === void 0 && schema.default === void 0 && schema.pattern === void 0 && schema.format === void 0;
2783
+ }
2784
+ function acceptsNumber(schema, value) {
2785
+ if (schema.const !== void 0) return schema.const === value;
2786
+ if (schema.enum !== void 0) return schema.enum.includes(value);
2787
+ if (schema.minimum !== void 0 && value < schema.minimum) return false;
2788
+ if (schema.maximum !== void 0 && value > schema.maximum) return false;
2789
+ return true;
2790
+ }
2791
+ function pickNumber(schema, preferred) {
2792
+ const accepted = preferred.find((value) => acceptsNumber(schema, value));
2793
+ if (accepted !== void 0) return accepted;
2794
+ const named = [schema.const, schema.enum?.[0], schema.minimum, schema.maximum].find(
2795
+ (value) => typeof value === "number" && acceptsNumber(schema, value)
2796
+ );
2797
+ return named;
2798
+ }
2799
+ function formatInlineArgs(args) {
2800
+ const entries = Object.entries(args).map(([key, value]) => {
2801
+ const name = /^[A-Za-z_$][\w$]*$/.test(key) ? key : JSON.stringify(key);
2802
+ const plain = typeof value === "string" && [...value].every((ch) => ch !== "'" && ch !== "\\" && ch >= " ");
2803
+ const literal = plain ? `'${value}'` : JSON.stringify(value);
2804
+ return `${name}: ${literal}`;
2805
+ });
2806
+ return entries.length > 0 ? `{ ${entries.join(", ")} }` : "{}";
2807
+ }
2771
2808
  function getSampleValue(schema, key) {
2772
2809
  if (schema.default !== void 0) {
2773
2810
  return schema.default;
@@ -2781,11 +2818,11 @@ function getSampleValue(schema, key) {
2781
2818
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
2782
2819
  switch (type) {
2783
2820
  case "string":
2784
- if (key.toLowerCase().includes("id")) return "abc123";
2785
- if (key.toLowerCase().includes("email")) return "user@example.com";
2786
- if (key.toLowerCase().includes("name")) return "Example";
2787
- if (key.toLowerCase().includes("url")) return "https://example.com";
2788
- return "string";
2821
+ if (key.toLowerCase().includes("id")) return fitString(schema, "abc123");
2822
+ if (key.toLowerCase().includes("email")) return fitString(schema, "user@example.com");
2823
+ if (key.toLowerCase().includes("name")) return fitString(schema, "Example");
2824
+ if (key.toLowerCase().includes("url")) return fitString(schema, "https://example.com");
2825
+ return fitString(schema, "string");
2789
2826
  case "number":
2790
2827
  case "integer":
2791
2828
  if (key.toLowerCase().includes("limit")) return 10;
@@ -2802,24 +2839,88 @@ function getSampleValue(schema, key) {
2802
2839
  return null;
2803
2840
  }
2804
2841
  }
2842
+ var PAGINATION_PROPERTIES = ["limit", "offset", "page", "pagesize", "cursor"];
2843
+ function isPaginationProperty(name) {
2844
+ return PAGINATION_PROPERTIES.includes(name.toLowerCase());
2845
+ }
2805
2846
  function hasPaginationParams(schema) {
2806
2847
  if (!schema || schema.type !== "object" || !schema.properties) {
2807
2848
  return false;
2808
2849
  }
2809
- const props = Object.keys(schema.properties);
2810
- return props.some((p) => ["limit", "offset", "page", "pageSize", "cursor"].includes(p.toLowerCase()));
2850
+ return Object.keys(schema.properties).some(isPaginationProperty);
2811
2851
  }
2812
- function generatePaginationExample(toolName) {
2813
- return {
2814
- description: `Pagination example for ${toolName}`,
2815
- code: `// Fetch first page
2816
- const page1 = await callTool('${toolName}', { limit: 10, offset: 0 });
2852
+ function inputProperties(schema) {
2853
+ if (!schema || schema.type !== "object" || !schema.properties) {
2854
+ return {};
2855
+ }
2856
+ const properties = {};
2857
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
2858
+ if (typeof propSchema !== "boolean") properties[key] = propSchema;
2859
+ }
2860
+ return properties;
2861
+ }
2862
+ function buildExampleArgs(schema, keys, values = {}) {
2863
+ const properties = inputProperties(schema);
2864
+ const args = {};
2865
+ for (const key of [...keys, ...schema?.required ?? []]) {
2866
+ const propSchema = properties[key];
2867
+ if (!propSchema || key in args) continue;
2868
+ args[key] = key in values ? values[key] : getSampleValue(propSchema, key);
2869
+ }
2870
+ return args;
2871
+ }
2872
+ function formatExampleArgs(args) {
2873
+ return Object.keys(args).length > 0 ? JSON.stringify(args, null, 2) : "{}";
2874
+ }
2875
+ function getFilterProperties(schema) {
2876
+ if (!schema || schema.type !== "object" || !schema.properties) {
2877
+ return [];
2878
+ }
2879
+ return Object.keys(schema.properties).filter(
2880
+ (p) => p.toLowerCase().includes("filter") || p.toLowerCase().includes("query") || p.toLowerCase().includes("search") || p.toLowerCase() === "status" || p.toLowerCase() === "type" || p.toLowerCase() === "role"
2881
+ );
2882
+ }
2883
+ function generatePaginationExample(toolName, inputSchema) {
2884
+ const description = `Pagination example for ${toolName}`;
2885
+ const props = Object.keys(inputProperties(inputSchema));
2886
+ const limitKey = props.find((p) => p.toLowerCase() === "limit");
2887
+ const offsetKey = props.find((p) => p.toLowerCase() === "offset");
2888
+ if (limitKey && offsetKey) {
2889
+ const properties = inputProperties(inputSchema);
2890
+ const limit = pickNumber(properties[limitKey], [10]);
2891
+ const firstOffset = pickNumber(properties[offsetKey], [0]);
2892
+ const values = {};
2893
+ if (limit !== void 0) values[limitKey] = limit;
2894
+ if (firstOffset !== void 0) values[offsetKey] = firstOffset;
2895
+ const firstPage = buildExampleArgs(inputSchema, [limitKey, offsetKey], values);
2896
+ const nextOffset = [limit ?? 10, 10, 20, ...properties[offsetKey].enum ?? []].find(
2897
+ (value) => typeof value === "number" && value !== firstPage[offsetKey] && acceptsNumber(properties[offsetKey], value)
2898
+ );
2899
+ if (nextOffset !== void 0) {
2900
+ const secondPage = { ...firstPage, [offsetKey]: nextOffset };
2901
+ return {
2902
+ description,
2903
+ code: `// Fetch first page
2904
+ const page1 = await callTool('${toolName}', ${formatExampleArgs(firstPage)});
2817
2905
 
2818
2906
  // Fetch second page
2819
- const page2 = await callTool('${toolName}', { limit: 10, offset: 10 });
2907
+ const page2 = await callTool('${toolName}', ${formatExampleArgs(secondPage)});
2820
2908
 
2821
2909
  // Combine results
2822
2910
  return [...page1.items, ...page2.items];`
2911
+ };
2912
+ }
2913
+ return {
2914
+ description,
2915
+ code: `const page = await callTool('${toolName}', ${formatExampleArgs(firstPage)});
2916
+ return page.items || page;`
2917
+ };
2918
+ }
2919
+ const args = buildExampleArgs(inputSchema, props.filter(isPaginationProperty));
2920
+ return {
2921
+ description,
2922
+ code: `const page = await callTool('${toolName}', ${formatExampleArgs(args)});
2923
+ return page.items || page;`
2823
2924
  };
2824
2925
  }
2825
2926
  function extractEntityName(toolName) {
@@ -2837,13 +2938,18 @@ function generateCreateExample(toolName, inputSchema) {
2837
2938
  return result;`
2838
2939
  };
2839
2940
  }
2941
+ function idArgs(schema, idParam) {
2942
+ const idSchema = inputProperties(schema)[idParam];
2943
+ const values = isFreeTextString(idSchema) ? { [idParam]: fitString(idSchema, "abc123") } : {};
2944
+ return buildExampleArgs(schema, [idParam], values);
2945
+ }
2840
2946
  function generateGetExample(toolName, inputSchema) {
2841
2947
  const entity = extractEntityName(toolName);
2842
2948
  const idParam = findIdParameter(inputSchema);
2843
2949
  if (idParam) {
2844
2950
  return {
2845
2951
  description: `Get ${entity} by ${idParam}`,
2846
- code: `const ${entity} = await callTool('${toolName}', { ${idParam}: 'abc123' });
2952
+ code: `const ${entity} = await callTool('${toolName}', ${formatInlineArgs(idArgs(inputSchema, idParam))});
2847
2953
  return ${entity};`
2848
2954
  };
2849
2955
  }
@@ -2859,7 +2965,7 @@ function generateListExample(toolName, inputSchema) {
2859
2965
  const entity = extractEntityName(toolName);
2860
2966
  return {
2861
2967
  description: `List all ${entity}s`,
2862
- code: `const result = await callTool('${toolName}', {});
2968
+ code: `const result = await callTool('${toolName}', ${formatExampleArgs(buildExampleArgs(inputSchema, []))});
2863
2969
  return result.items || result;`
2864
2970
  };
2865
2971
  }
@@ -2869,10 +2975,11 @@ function generateUpdateExample(toolName, inputSchema) {
2869
2975
  const updateFields = generateUpdateFields(inputSchema);
2870
2976
  const fieldsStr = updateFields ? JSON.stringify(updateFields, null, 2).replace(/\n/g, "\n ") : "{ /* fields to update */ }";
2871
2977
  if (idParam) {
2978
+ const identifiers = formatInlineArgs(idArgs(inputSchema, idParam)).slice(2, -2);
2872
2979
  return {
2873
2980
  description: `Update ${entity} by ${idParam}`,
2874
2981
  code: `const updated = await callTool('${toolName}', {
2875
- ${idParam}: 'abc123',
2982
+ ${identifiers},
2876
2983
  ...${fieldsStr}
2877
2984
  });
2878
2985
  return updated;`
@@ -2890,7 +2997,7 @@ function generateDeleteExample(toolName, inputSchema) {
2890
2997
  if (idParam) {
2891
2998
  return {
2892
2999
  description: `Delete ${entity} by ${idParam}`,
2893
- code: `const result = await callTool('${toolName}', { ${idParam}: 'abc123' });
3000
+ code: `const result = await callTool('${toolName}', ${formatInlineArgs(idArgs(inputSchema, idParam))});
2894
3001
  return result;`
2895
3002
  };
2896
3003
  }
@@ -2904,17 +3011,18 @@ return result;`
2904
3011
  }
2905
3012
  function generateSearchExample(toolName, inputSchema) {
2906
3013
  const entity = extractEntityName(toolName);
2907
- const queryParam = findQueryParameter(inputSchema);
2908
- if (queryParam) {
2909
- return {
2910
- description: `Search for ${entity}s`,
2911
- code: `const results = await callTool('${toolName}', { ${queryParam}: 'search term' });
2912
- return results.items || results;`
2913
- };
2914
- }
3014
+ const searchParam = findQueryParameter(inputSchema) ?? getFilterProperties(inputSchema)[0];
3015
+ const searchSchema = searchParam ? inputProperties(inputSchema)[searchParam] : void 0;
3016
+ const required = new Set(inputSchema?.required ?? []);
3017
+ const unfillable = searchSchema?.type === "string" && (searchSchema.pattern !== void 0 || searchSchema.format !== void 0) && searchSchema.enum === void 0 && searchSchema.const === void 0 && searchSchema.default === void 0 && !required.has(searchParam ?? "");
3018
+ const args = searchParam && !unfillable ? buildExampleArgs(
3019
+ inputSchema,
3020
+ [searchParam],
3021
+ isFreeTextString(searchSchema) && searchSchema ? { [searchParam]: fitString(searchSchema, "search term") } : {}
3022
+ ) : buildExampleArgs(inputSchema, []);
2915
3023
  return {
2916
3024
  description: `Search for ${entity}s`,
2917
- code: `const results = await callTool('${toolName}', { query: 'search term' });
3025
+ code: `const results = await callTool('${toolName}', ${formatExampleArgs(args)});
2918
3026
  return results.items || results;`
2919
3027
  };
2920
3028
  }
@@ -2971,7 +3079,7 @@ function generateSmartExample(toolName, inputSchema, description) {
2971
3079
  case "get":
2972
3080
  return generateGetExample(toolName, inputSchema);
2973
3081
  case "list":
2974
- return hasPaginationParams(inputSchema) ? generatePaginationExample(toolName) : generateListExample(toolName, inputSchema);
3082
+ return hasPaginationParams(inputSchema) ? generatePaginationExample(toolName, inputSchema) : generateListExample(toolName, inputSchema);
2975
3083
  case "update":
2976
3084
  return generateUpdateExample(toolName, inputSchema);
2977
3085
  case "delete":
@@ -3199,7 +3307,9 @@ var DescribeTool = class extends ToolContext4 {
3199
3307
  *
3200
3308
  * Priority:
3201
3309
  * 1. User-provided examples from @Tool decorator metadata (up to 5)
3202
- * 2. Smart intent-based generation to fill remaining slots
3310
+ * 2. Without any, one smart intent-based example built from the input schema. It is never added
3311
+ * next to the tool's own examples: those show how the tool is called, and a generated one
3312
+ * only guesses (#647).
3203
3313
  * 3. Returns at least 1 example
3204
3314
  */
3205
3315
  generateExamples(tool, inputSchema) {
@@ -3214,7 +3324,7 @@ return result;`
3214
3324
  });
3215
3325
  }
3216
3326
  }
3217
- if (result.length < 5) {
3327
+ if (result.length === 0) {
3218
3328
  result.push(generateSmartExample(tool.name, inputSchema, tool.metadata?.description));
3219
3329
  }
3220
3330
  return result.slice(0, 5);
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-codecall",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "CodeCall plugin for FrontMCP - AgentScript-based meta-tools for orchestrating MCP tools",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -50,14 +50,14 @@
50
50
  "dependencies": {
51
51
  "@enclave-vm/ast": "^2.15.3",
52
52
  "@enclave-vm/core": "^2.15.3",
53
- "@frontmcp/protocol": "1.8.5",
54
- "@frontmcp/sdk": "1.8.5",
53
+ "@frontmcp/protocol": "1.8.7",
54
+ "@frontmcp/sdk": "1.8.7",
55
55
  "acorn": "^8.15.0",
56
56
  "vectoriadb": "^2.3.2"
57
57
  },
58
58
  "peerDependencies": {
59
- "@frontmcp/lazy-zod": "1.8.5",
60
- "@frontmcp/plugin-cache": "1.8.5"
59
+ "@frontmcp/lazy-zod": "1.8.7",
60
+ "@frontmcp/plugin-cache": "1.8.7"
61
61
  },
62
62
  "devDependencies": {
63
63
  "reflect-metadata": "^0.2.2"
package/index.js CHANGED
@@ -2805,6 +2805,43 @@ function generateSampleParams(schema) {
2805
2805
  }
2806
2806
  return Object.keys(params).length > 0 ? params : null;
2807
2807
  }
2808
+ function fitString(schema, value) {
2809
+ let fitted = value;
2810
+ if (schema.maxLength !== void 0 && fitted.length > schema.maxLength) {
2811
+ fitted = fitted.slice(0, Math.max(0, schema.maxLength));
2812
+ }
2813
+ if (schema.minLength !== void 0 && fitted.length < schema.minLength) {
2814
+ fitted = fitted.padEnd(schema.minLength, "x");
2815
+ }
2816
+ return fitted;
2817
+ }
2818
+ function isFreeTextString(schema) {
2819
+ return schema?.type === "string" && schema.enum === void 0 && schema.const === void 0 && schema.default === void 0 && schema.pattern === void 0 && schema.format === void 0;
2820
+ }
2821
+ function acceptsNumber(schema, value) {
2822
+ if (schema.const !== void 0) return schema.const === value;
2823
+ if (schema.enum !== void 0) return schema.enum.includes(value);
2824
+ if (schema.minimum !== void 0 && value < schema.minimum) return false;
2825
+ if (schema.maximum !== void 0 && value > schema.maximum) return false;
2826
+ return true;
2827
+ }
2828
+ function pickNumber(schema, preferred) {
2829
+ const accepted = preferred.find((value) => acceptsNumber(schema, value));
2830
+ if (accepted !== void 0) return accepted;
2831
+ const named = [schema.const, schema.enum?.[0], schema.minimum, schema.maximum].find(
2832
+ (value) => typeof value === "number" && acceptsNumber(schema, value)
2833
+ );
2834
+ return named;
2835
+ }
2836
+ function formatInlineArgs(args) {
2837
+ const entries = Object.entries(args).map(([key, value]) => {
2838
+ const name = /^[A-Za-z_$][\w$]*$/.test(key) ? key : JSON.stringify(key);
2839
+ const plain = typeof value === "string" && [...value].every((ch) => ch !== "'" && ch !== "\\" && ch >= " ");
2840
+ const literal = plain ? `'${value}'` : JSON.stringify(value);
2841
+ return `${name}: ${literal}`;
2842
+ });
2843
+ return entries.length > 0 ? `{ ${entries.join(", ")} }` : "{}";
2844
+ }
2808
2845
  function getSampleValue(schema, key) {
2809
2846
  if (schema.default !== void 0) {
2810
2847
  return schema.default;
@@ -2818,11 +2855,11 @@ function getSampleValue(schema, key) {
2818
2855
  const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
2819
2856
  switch (type) {
2820
2857
  case "string":
2821
- if (key.toLowerCase().includes("id")) return "abc123";
2822
- if (key.toLowerCase().includes("email")) return "user@example.com";
2823
- if (key.toLowerCase().includes("name")) return "Example";
2824
- if (key.toLowerCase().includes("url")) return "https://example.com";
2825
- return "string";
2858
+ if (key.toLowerCase().includes("id")) return fitString(schema, "abc123");
2859
+ if (key.toLowerCase().includes("email")) return fitString(schema, "user@example.com");
2860
+ if (key.toLowerCase().includes("name")) return fitString(schema, "Example");
2861
+ if (key.toLowerCase().includes("url")) return fitString(schema, "https://example.com");
2862
+ return fitString(schema, "string");
2826
2863
  case "number":
2827
2864
  case "integer":
2828
2865
  if (key.toLowerCase().includes("limit")) return 10;
@@ -2839,24 +2876,88 @@ function getSampleValue(schema, key) {
2839
2876
  return null;
2840
2877
  }
2841
2878
  }
2879
+ var PAGINATION_PROPERTIES = ["limit", "offset", "page", "pagesize", "cursor"];
2880
+ function isPaginationProperty(name) {
2881
+ return PAGINATION_PROPERTIES.includes(name.toLowerCase());
2882
+ }
2842
2883
  function hasPaginationParams(schema) {
2843
2884
  if (!schema || schema.type !== "object" || !schema.properties) {
2844
2885
  return false;
2845
2886
  }
2846
- const props = Object.keys(schema.properties);
2847
- return props.some((p) => ["limit", "offset", "page", "pageSize", "cursor"].includes(p.toLowerCase()));
2887
+ return Object.keys(schema.properties).some(isPaginationProperty);
2848
2888
  }
2849
- function generatePaginationExample(toolName) {
2850
- return {
2851
- description: `Pagination example for ${toolName}`,
2852
- code: `// Fetch first page
2853
- const page1 = await callTool('${toolName}', { limit: 10, offset: 0 });
2889
+ function inputProperties(schema) {
2890
+ if (!schema || schema.type !== "object" || !schema.properties) {
2891
+ return {};
2892
+ }
2893
+ const properties = {};
2894
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
2895
+ if (typeof propSchema !== "boolean") properties[key] = propSchema;
2896
+ }
2897
+ return properties;
2898
+ }
2899
+ function buildExampleArgs(schema, keys, values = {}) {
2900
+ const properties = inputProperties(schema);
2901
+ const args = {};
2902
+ for (const key of [...keys, ...schema?.required ?? []]) {
2903
+ const propSchema = properties[key];
2904
+ if (!propSchema || key in args) continue;
2905
+ args[key] = key in values ? values[key] : getSampleValue(propSchema, key);
2906
+ }
2907
+ return args;
2908
+ }
2909
+ function formatExampleArgs(args) {
2910
+ return Object.keys(args).length > 0 ? JSON.stringify(args, null, 2) : "{}";
2911
+ }
2912
+ function getFilterProperties(schema) {
2913
+ if (!schema || schema.type !== "object" || !schema.properties) {
2914
+ return [];
2915
+ }
2916
+ return Object.keys(schema.properties).filter(
2917
+ (p) => p.toLowerCase().includes("filter") || p.toLowerCase().includes("query") || p.toLowerCase().includes("search") || p.toLowerCase() === "status" || p.toLowerCase() === "type" || p.toLowerCase() === "role"
2918
+ );
2919
+ }
2920
+ function generatePaginationExample(toolName, inputSchema) {
2921
+ const description = `Pagination example for ${toolName}`;
2922
+ const props = Object.keys(inputProperties(inputSchema));
2923
+ const limitKey = props.find((p) => p.toLowerCase() === "limit");
2924
+ const offsetKey = props.find((p) => p.toLowerCase() === "offset");
2925
+ if (limitKey && offsetKey) {
2926
+ const properties = inputProperties(inputSchema);
2927
+ const limit = pickNumber(properties[limitKey], [10]);
2928
+ const firstOffset = pickNumber(properties[offsetKey], [0]);
2929
+ const values = {};
2930
+ if (limit !== void 0) values[limitKey] = limit;
2931
+ if (firstOffset !== void 0) values[offsetKey] = firstOffset;
2932
+ const firstPage = buildExampleArgs(inputSchema, [limitKey, offsetKey], values);
2933
+ const nextOffset = [limit ?? 10, 10, 20, ...properties[offsetKey].enum ?? []].find(
2934
+ (value) => typeof value === "number" && value !== firstPage[offsetKey] && acceptsNumber(properties[offsetKey], value)
2935
+ );
2936
+ if (nextOffset !== void 0) {
2937
+ const secondPage = { ...firstPage, [offsetKey]: nextOffset };
2938
+ return {
2939
+ description,
2940
+ code: `// Fetch first page
2941
+ const page1 = await callTool('${toolName}', ${formatExampleArgs(firstPage)});
2854
2942
 
2855
2943
  // Fetch second page
2856
- const page2 = await callTool('${toolName}', { limit: 10, offset: 10 });
2944
+ const page2 = await callTool('${toolName}', ${formatExampleArgs(secondPage)});
2857
2945
 
2858
2946
  // Combine results
2859
2947
  return [...page1.items, ...page2.items];`
2948
+ };
2949
+ }
2950
+ return {
2951
+ description,
2952
+ code: `const page = await callTool('${toolName}', ${formatExampleArgs(firstPage)});
2953
+ return page.items || page;`
2954
+ };
2955
+ }
2956
+ const args = buildExampleArgs(inputSchema, props.filter(isPaginationProperty));
2957
+ return {
2958
+ description,
2959
+ code: `const page = await callTool('${toolName}', ${formatExampleArgs(args)});
2960
+ return page.items || page;`
2860
2961
  };
2861
2962
  }
2862
2963
  function extractEntityName(toolName) {
@@ -2874,13 +2975,18 @@ function generateCreateExample(toolName, inputSchema) {
2874
2975
  return result;`
2875
2976
  };
2876
2977
  }
2978
+ function idArgs(schema, idParam) {
2979
+ const idSchema = inputProperties(schema)[idParam];
2980
+ const values = isFreeTextString(idSchema) ? { [idParam]: fitString(idSchema, "abc123") } : {};
2981
+ return buildExampleArgs(schema, [idParam], values);
2982
+ }
2877
2983
  function generateGetExample(toolName, inputSchema) {
2878
2984
  const entity = extractEntityName(toolName);
2879
2985
  const idParam = findIdParameter(inputSchema);
2880
2986
  if (idParam) {
2881
2987
  return {
2882
2988
  description: `Get ${entity} by ${idParam}`,
2883
- code: `const ${entity} = await callTool('${toolName}', { ${idParam}: 'abc123' });
2989
+ code: `const ${entity} = await callTool('${toolName}', ${formatInlineArgs(idArgs(inputSchema, idParam))});
2884
2990
  return ${entity};`
2885
2991
  };
2886
2992
  }
@@ -2896,7 +3002,7 @@ function generateListExample(toolName, inputSchema) {
2896
3002
  const entity = extractEntityName(toolName);
2897
3003
  return {
2898
3004
  description: `List all ${entity}s`,
2899
- code: `const result = await callTool('${toolName}', {});
3005
+ code: `const result = await callTool('${toolName}', ${formatExampleArgs(buildExampleArgs(inputSchema, []))});
2900
3006
  return result.items || result;`
2901
3007
  };
2902
3008
  }
@@ -2906,10 +3012,11 @@ function generateUpdateExample(toolName, inputSchema) {
2906
3012
  const updateFields = generateUpdateFields(inputSchema);
2907
3013
  const fieldsStr = updateFields ? JSON.stringify(updateFields, null, 2).replace(/\n/g, "\n ") : "{ /* fields to update */ }";
2908
3014
  if (idParam) {
3015
+ const identifiers = formatInlineArgs(idArgs(inputSchema, idParam)).slice(2, -2);
2909
3016
  return {
2910
3017
  description: `Update ${entity} by ${idParam}`,
2911
3018
  code: `const updated = await callTool('${toolName}', {
2912
- ${idParam}: 'abc123',
3019
+ ${identifiers},
2913
3020
  ...${fieldsStr}
2914
3021
  });
2915
3022
  return updated;`
@@ -2927,7 +3034,7 @@ function generateDeleteExample(toolName, inputSchema) {
2927
3034
  if (idParam) {
2928
3035
  return {
2929
3036
  description: `Delete ${entity} by ${idParam}`,
2930
- code: `const result = await callTool('${toolName}', { ${idParam}: 'abc123' });
3037
+ code: `const result = await callTool('${toolName}', ${formatInlineArgs(idArgs(inputSchema, idParam))});
2931
3038
  return result;`
2932
3039
  };
2933
3040
  }
@@ -2941,17 +3048,18 @@ return result;`
2941
3048
  }
2942
3049
  function generateSearchExample(toolName, inputSchema) {
2943
3050
  const entity = extractEntityName(toolName);
2944
- const queryParam = findQueryParameter(inputSchema);
2945
- if (queryParam) {
2946
- return {
2947
- description: `Search for ${entity}s`,
2948
- code: `const results = await callTool('${toolName}', { ${queryParam}: 'search term' });
2949
- return results.items || results;`
2950
- };
2951
- }
3051
+ const searchParam = findQueryParameter(inputSchema) ?? getFilterProperties(inputSchema)[0];
3052
+ const searchSchema = searchParam ? inputProperties(inputSchema)[searchParam] : void 0;
3053
+ const required = new Set(inputSchema?.required ?? []);
3054
+ const unfillable = searchSchema?.type === "string" && (searchSchema.pattern !== void 0 || searchSchema.format !== void 0) && searchSchema.enum === void 0 && searchSchema.const === void 0 && searchSchema.default === void 0 && !required.has(searchParam ?? "");
3055
+ const args = searchParam && !unfillable ? buildExampleArgs(
3056
+ inputSchema,
3057
+ [searchParam],
3058
+ isFreeTextString(searchSchema) && searchSchema ? { [searchParam]: fitString(searchSchema, "search term") } : {}
3059
+ ) : buildExampleArgs(inputSchema, []);
2952
3060
  return {
2953
3061
  description: `Search for ${entity}s`,
2954
- code: `const results = await callTool('${toolName}', { query: 'search term' });
3062
+ code: `const results = await callTool('${toolName}', ${formatExampleArgs(args)});
2955
3063
  return results.items || results;`
2956
3064
  };
2957
3065
  }
@@ -3008,7 +3116,7 @@ function generateSmartExample(toolName, inputSchema, description) {
3008
3116
  case "get":
3009
3117
  return generateGetExample(toolName, inputSchema);
3010
3118
  case "list":
3011
- return hasPaginationParams(inputSchema) ? generatePaginationExample(toolName) : generateListExample(toolName, inputSchema);
3119
+ return hasPaginationParams(inputSchema) ? generatePaginationExample(toolName, inputSchema) : generateListExample(toolName, inputSchema);
3012
3120
  case "update":
3013
3121
  return generateUpdateExample(toolName, inputSchema);
3014
3122
  case "delete":
@@ -3236,7 +3344,9 @@ var DescribeTool = class extends import_sdk7.ToolContext {
3236
3344
  *
3237
3345
  * Priority:
3238
3346
  * 1. User-provided examples from @Tool decorator metadata (up to 5)
3239
- * 2. Smart intent-based generation to fill remaining slots
3347
+ * 2. Without any, one smart intent-based example built from the input schema. It is never added
3348
+ * next to the tool's own examples: those show how the tool is called, and a generated one
3349
+ * only guesses (#647).
3240
3350
  * 3. Returns at least 1 example
3241
3351
  */
3242
3352
  generateExamples(tool, inputSchema) {
@@ -3251,7 +3361,7 @@ return result;`
3251
3361
  });
3252
3362
  }
3253
3363
  }
3254
- if (result.length < 5) {
3364
+ if (result.length === 0) {
3255
3365
  result.push(generateSmartExample(tool.name, inputSchema, tool.metadata?.description));
3256
3366
  }
3257
3367
  return result.slice(0, 5);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/plugin-codecall",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "CodeCall plugin for FrontMCP - AgentScript-based meta-tools for orchestrating MCP tools",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -50,14 +50,14 @@
50
50
  "dependencies": {
51
51
  "@enclave-vm/ast": "^2.15.3",
52
52
  "@enclave-vm/core": "^2.15.3",
53
- "@frontmcp/protocol": "1.8.5",
54
- "@frontmcp/sdk": "1.8.5",
53
+ "@frontmcp/protocol": "1.8.7",
54
+ "@frontmcp/sdk": "1.8.7",
55
55
  "acorn": "^8.15.0",
56
56
  "vectoriadb": "^2.3.2"
57
57
  },
58
58
  "peerDependencies": {
59
- "@frontmcp/lazy-zod": "1.8.5",
60
- "@frontmcp/plugin-cache": "1.8.5"
59
+ "@frontmcp/lazy-zod": "1.8.7",
60
+ "@frontmcp/plugin-cache": "1.8.7"
61
61
  },
62
62
  "devDependencies": {
63
63
  "reflect-metadata": "^0.2.2"
@@ -28,7 +28,9 @@ export default class DescribeTool extends ToolContext {
28
28
  *
29
29
  * Priority:
30
30
  * 1. User-provided examples from @Tool decorator metadata (up to 5)
31
- * 2. Smart intent-based generation to fill remaining slots
31
+ * 2. Without any, one smart intent-based example built from the input schema. It is never added
32
+ * next to the tool's own examples: those show how the tool is called, and a generated one
33
+ * only guesses (#647).
32
34
  * 3. Returns at least 1 example
33
35
  */
34
36
  private generateExamples;
@@ -1 +1 @@
1
- {"version":3,"file":"describe.tool.d.ts","sourceRoot":"","sources":["../../src/tools/describe.tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,WAAW,EAAkB,MAAM,eAAe,CAAC;AAMlF,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAuB3B,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAW;IAC7C,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkEpE;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAkDpB;;OAEG;IACH,OAAO,CAAC,YAAY;IA6BpB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;CAyBzB"}
1
+ {"version":3,"file":"describe.tool.d.ts","sourceRoot":"","sources":["../../src/tools/describe.tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,WAAW,EAAkB,MAAM,eAAe,CAAC;AAMlF,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAuB3B,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAW;IAC7C,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkEpE;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAkDpB;;OAEG;IACH,OAAO,CAAC,YAAY;IA6BpB;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;CAyBzB"}
@@ -46,13 +46,14 @@ export declare function hasFilterParams(schema?: JsonSchema): boolean;
46
46
  */
47
47
  export declare function getFilterProperties(schema?: JsonSchema): string[];
48
48
  /**
49
- * Generate a pagination example for a tool.
49
+ * Generate a pagination example for a tool, paging with the pagination properties its schema
50
+ * declares (two pages when it takes `limit` and `offset`, one otherwise).
50
51
  */
51
- export declare function generatePaginationExample(toolName: string): ToolUsageExample;
52
+ export declare function generatePaginationExample(toolName: string, inputSchema?: JsonSchema): ToolUsageExample;
52
53
  /**
53
- * Generate a filter example for a tool.
54
+ * Generate a filter example for a tool, with a value the property's schema accepts.
54
55
  */
55
- export declare function generateFilterExample(toolName: string, filterProp: string): ToolUsageExample;
56
+ export declare function generateFilterExample(toolName: string, filterProp: string, inputSchema?: JsonSchema): ToolUsageExample;
56
57
  /**
57
58
  * Generate a create example for a tool.
58
59
  * Shows required parameters with contextual sample values.
@@ -63,7 +64,8 @@ export declare function generateCreateExample(toolName: string, inputSchema?: Js
63
64
  */
64
65
  export declare function generateGetExample(toolName: string, inputSchema?: JsonSchema): ToolUsageExample;
65
66
  /**
66
- * Generate a list example for a tool.
67
+ * Generate a list example for a tool: the required properties, or `{}` when it has none. Tools
68
+ * that declare pagination properties get `generatePaginationExample` instead.
67
69
  */
68
70
  export declare function generateListExample(toolName: string, inputSchema?: JsonSchema): ToolUsageExample;
69
71
  /**
@@ -76,6 +78,10 @@ export declare function generateUpdateExample(toolName: string, inputSchema?: Js
76
78
  export declare function generateDeleteExample(toolName: string, inputSchema?: JsonSchema): ToolUsageExample;
77
79
  /**
78
80
  * Generate a search example for a tool.
81
+ *
82
+ * Searches by the tool's query-like property, else by its first filter property (`status`, `type`,
83
+ * ...), with the required properties alongside. Never a `query` the schema does not declare: a tool
84
+ * searched by `status` and `priority` was shown `callTool('<tool>', { query: 'search term' })`.
79
85
  */
80
86
  export declare function generateSearchExample(toolName: string, inputSchema?: JsonSchema): ToolUsageExample;
81
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"describe.utils.d.ts","sourceRoot":"","sources":["../../src/utils/describe.utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,mCAAmC;AACnC,KAAK,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAiB3G;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAwBnF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,UAAU,GAAG,MAAM,CAKnH;AAkFD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,EACrC,SAAS,EAAE,OAAO,GAAG,QAAQ,GAC5B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CASjG;AAyED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAOhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAe5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,CAcjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAY5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAM5F;AAgBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAUlG;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAqB/F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAQhG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CA0BlG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAoBlG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAiBlG;AA2ED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,UAAU,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,gBAAgB,CAuBlB"}
1
+ {"version":3,"file":"describe.utils.d.ts","sourceRoot":"","sources":["../../src/utils/describe.utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,mCAAmC;AACnC,KAAK,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAiB3G;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAwBnF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,UAAU,GAAG,MAAM,CAKnH;AAkFD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,EACrC,SAAS,EAAE,OAAO,GAAG,QAAQ,GAC5B,MAAM,CAkCR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CASjG;AA+ID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAMhE;AA0CD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAe5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,CAcjE;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CA+CtG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,UAAU,GACvB,gBAAgB,CASlB;AAgBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAUlG;AAYD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAqB/F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAQhG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CA2BlG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAoBlG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,GAAG,gBAAgB,CA8BlG;AA2ED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,UAAU,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,gBAAgB,CAuBlB"}