CodeCall exposes four meta-tools that replace direct tool access. This page documents the complete API for each tool with request/response schemas and examples.
codecall:search
Search for tools by natural language query using semantic embeddings.
Request Schema
{
" tool " : " codecall:search " ,
" input " : {
" query " : " string (required) - Natural language search query " ,
" topK " : " number (optional, default: 5) - Maximum results to return " ,
" filter " : {
" appIds " : [ " string " ] // (optional) - Limit to specific apps
}
}
}
Response Schema
{
" tools " : [
{
" name " : " string - Tool name (e.g., 'users:list') " ,
" appId " : " string - Owning app ID " ,
" description " : " string - Tool description " ,
" score " : " number - Relevance score (0-1) "
}
],
" totalIndexed " : " number - Total tools in index "
}
Examples
Search All Apps
Filter by App
{
" tool " : " codecall:search " ,
" input " : {
" query " : " get user profile information " ,
" topK " : 5
}
}
Response Example
{
" tools " : [
{
" name " : " users:getProfile " ,
" appId " : " user-service " ,
" description " : " Get user profile by ID with full details " ,
" score " : 0.94
},
{
" name " : " users:list " ,
" appId " : " user-service " ,
" description " : " List all users with pagination and filtering " ,
" score " : 0.78
},
{
" name " : " auth:whoami " ,
" appId " : " auth-service " ,
" description " : " Get current authenticated user info " ,
" score " : 0.72
}
],
" totalIndexed " : 156
}
Search Strategy
CodeCall supports two embedding strategies:
Strategy Description Best For tfidfTF-IDF text matching (default) Fast, no model loading, works offline embeddingSemantic embeddings via VectoriaDB Better relevance, requires model
CodeCallPlugin . init ({
embedding : {
strategy : ' tfidf ' , // or 'embedding'
similarityThreshold : 0.3 ,
},
});
codecall:describe
Get detailed schemas and documentation for specific tools.
Request Schema
{
" tool " : " codecall:describe " ,
" input " : {
" toolNames " : [ " string (required) - Array of tool names to describe " ]
}
}
Response Schema
{
" tools " : [
{
" name " : " string - Tool name " ,
" appId " : " string - Owning app ID " ,
" description " : " string - Full description " ,
" inputSchema " : { /* JSON Schema */ },
" outputSchema " : { /* JSON Schema or null */ },
" annotations " : {
" destructiveHint " : " boolean (optional) " ,
" idempotentHint " : " boolean (optional) " ,
" openWorldHint " : " boolean (optional) "
},
" usageExamples " : [
{
" description " : " string - Example description " ,
" code " : " string - Example AgentScript code "
}
]
}
],
" notFound " : [ " string (optional) - Tool names that weren't found " ]
}
usageExamples returns up to 5 examples per tool. User-provided examples from the @Tool decorator take priority, with smart-generated examples filling remaining slots based on tool intent (create, list, get, update, delete, search).
Example
{
" tool " : " codecall:describe " ,
" input " : {
" toolNames " : [ " users:list " , " users:getById " ]
}
}
Security Note
codecall:describe will not return information about CodeCall meta-tools themselves. Attempting to describe
codecall:execute returns the tool in notFound.
codecall:execute
Execute a JavaScript (AgentScript) plan that orchestrates multiple tools.
Request Schema
{
" tool " : " codecall:execute " ,
" input " : {
" script " : " string (required) - JavaScript code to execute " ,
" context " : { /* (optional) - Read-only context available as codecallContext */ },
" allowedTools " : [ " string (optional) - Whitelist of allowed tool names " ]
}
}
Response Schema
Success:
{
" status " : " ok " ,
" result " : " any - Return value from script " ,
" logs " : [ " string (optional) - Console output if enabled " ]
}
Error Responses:
{
" status " : " syntax_error " ,
" error " : {
" message " : " Unexpected token at line 5 " ,
" location " : { " line " : 5 , " column " : 12 }
}
}
{
" status " : " illegal_access " ,
" error " : {
" kind " : " IllegalBuiltinAccess " ,
" message " : " Identifier 'eval' is not allowed in AgentScript "
}
}
{
" status " : " runtime_error " ,
" error " : {
" source " : " script " ,
" message " : " Cannot read property 'name' of undefined " ,
" name " : " TypeError "
}
}
{
" status " : " timeout " ,
" error " : {
" message " : " Script execution timed out after 3500ms "
}
}
Example
{
" tool " : " codecall:execute " ,
" input " : {
" script " : " const users = await callTool('users:list', { status: 'active' }); \n const admins = users.users.filter(u => u.role === 'admin'); \n return { adminCount: admins.length, admins: admins.map(a => a.email) }; "
}
}
AgentScript API
Inside codecall:execute scripts, these functions are available:
Call a tool and get the result.
// Basic call
const users = await callTool ( ' users:list ' , { limit : 100 });
// With error handling option
const result = await callTool ( ' users:get ' , { id : ' invalid ' }, {
throwOnError : false // Returns { success, data, error } instead of throwing
});
if ( result . success ) {
return result . data ;
} else {
return { error : result . error . message };
}
Options:
Option Type Default Description throwOnErrorbooleantrueThrow on error or return result object
Get metadata about a tool (name, description, schemas).
const meta = getTool ( ' users:list ' );
console . log ( meta . description );
console . log ( meta . inputSchema );
codecallContext
Read-only context object passed in the request.
// Access context
const tenantId = codecallContext . tenantId ;
const userId = codecallContext . userId ;
// Cannot modify
codecallContext . tenantId = ' other ' ; // ❌ Throws error (frozen object)
console (if enabled)
Standard console methods, captured in response logs.
console . log ( ' Processing users... ' );
console . warn ( ' Large dataset detected ' );
console . error ( ' Validation failed ' );
Console is only available if vm.allowConsole: true in plugin config. Logs are returned in the logs array of the
response.
__safe_parallel(fns, options?)
Execute multiple async operations in parallel with controlled concurrency.
// Fetch multiple users in parallel
const userIds = [ ' user-1 ' , ' user-2 ' , ' user-3 ' , ' user-4 ' , ' user-5 ' ];
const users = await __safe_parallel (
userIds . map ( id => () => callTool ( ' users:get ' , { id })),
{ maxConcurrency : 3 } // Max 3 concurrent requests
);
return users ; // Array of results in same order as input
Options:
Option Type Default Max Description maxConcurrencynumber10 20 Max concurrent operations
Limits:
Limit Value Error Max array size 100 Cannot execute more than 100 operations in parallelMax concurrency 20 Silently clamped
Error Handling:
// If any operation fails, the entire parallel call fails
try {
const results = await __safe_parallel ([
() => callTool ( ' users:get ' , { id : ' valid ' }),
() => callTool ( ' users:get ' , { id : ' invalid ' }), // Throws
() => callTool ( ' users:get ' , { id : ' also-valid ' }),
]);
} catch ( error ) {
// Error message: "1 of 3 parallel operations failed:
// [1]: User not found"
}
Use Cases:
// Batch fetching
const ids = await callTool ( ' users:listIds ' , { limit : 50 });
const users = await __safe_parallel (
ids . map ( id => () => callTool ( ' users:get ' , { id }))
);
// Parallel aggregation
const [ orders , users , metrics ] = await __safe_parallel ([
() => callTool ( ' orders:list ' , { status : ' pending ' }),
() => callTool ( ' users:list ' , { role : ' admin ' }),
() => callTool ( ' analytics:getMetrics ' , {}),
]);
codecall:invoke
Direct tool invocation without JavaScript execution. Useful for simple single-tool calls.
Request Schema
{
" tool " : " codecall:invoke " ,
" input " : {
" tool " : " string (required) - Tool name to invoke " ,
" input " : { /* (required) - Input to pass to the tool */ }
}
}
Response Schema
Success:
{
" status " : " ok " ,
" result " : " any - Tool return value "
}
Error:
{
" status " : " error " ,
" error " : {
" code " : " string - Error code " ,
" message " : " string - Error message "
}
}
Example
{
" tool " : " codecall:invoke " ,
" input " : {
" tool " : " users:getById " ,
" input " : { " id " : " user-123 " }
}
}
When to Use Invoke vs Execute
Use codecall:invoke Use codecall:execute Single tool call Multiple tool calls No data transformation needed Filter/join/transform results Latency-sensitive (no VM overhead) Complex orchestration logic Simple CRUD operations Conditional workflows
Error Codes Reference
Script Execution Errors
Code Status Description Recovery SYNTAX_ERRORsyntax_errorJavaScript syntax error Fix syntax at indicated location VALIDATION_ERRORillegal_accessAST validation failed Remove blocked construct SELF_REFERENCE_BLOCKEDillegal_accessTried to call codecall:* tool Use regular tools only TOOL_NOT_FOUNDtool_errorTool doesn’t exist Check tool name spelling ACCESS_DENIEDtool_errorTool not in allowedTools Add to allowlist EXECUTION_ERRORruntime_errorRuntime error in script Debug script logic TIMEOUTtimeoutExceeded time limit Optimize or increase timeout TOOL_EXECUTION_ERRORtool_errorTool threw an error Check tool input
Worker Pool Errors (when adapter=‘worker_threads’)
Error Class Code Description Recovery WorkerTimeoutErrorWORKER_TIMEOUTExecution exceeded watchdog timeout Reduce script complexity WorkerMemoryErrorWORKER_MEMORY_EXCEEDEDWorker exceeded memory limit Reduce data size or increase limit WorkerCrashedErrorWORKER_CRASHEDWorker process crashed unexpectedly Check for infinite recursion WorkerPoolDisposedErrorPOOL_DISPOSEDPool was shut down during execution Restart the server QueueFullErrorQUEUE_FULLExecution queue at capacity Wait or scale up workers QueueTimeoutErrorQUEUE_TIMEOUTWaited too long in queue Scale up workers ExecutionAbortedErrorEXECUTION_ABORTEDExecution was cancelled N/A (intentional) MessageFloodErrorMESSAGE_FLOODRate limit exceeded Reduce callTool frequency MessageValidationErrorMESSAGE_INVALIDMalformed message from worker Report as bug MessageSizeErrorMESSAGE_TOO_LARGEMessage exceeded size limit Reduce result size WorkerStartupErrorWORKER_STARTUP_FAILEDWorker failed to initialize Check system resources TooManyPendingCallsErrorTOO_MANY_PENDING_CALLSToo many concurrent tool calls Use sequential calls
Error Handling Patterns
Basic Pattern: throwOnError
// Default: throws on error
const users = await callTool ( ' users:list ' , { limit : 100 });
// Safe pattern: returns result object
const result = await callTool ( ' users:get ' , { id : ' maybe-invalid ' }, {
throwOnError : false
});
if ( result . success ) {
return { user : result . data };
} else {
return { error : result . error . message , fallback : ' default-user ' };
}
Retry Pattern
async function retryTool ( toolName , args , maxRetries = 3 ) {
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++) {
const result = await callTool ( toolName , args , { throwOnError : false });
if ( result . success ) {
return result . data ;
}
// Don't retry non-transient errors
if ( result . error . code === ' NOT_FOUND ' || result . error . code === ' VALIDATION_ERROR ' ) {
throw new Error ( result . error . message );
}
// Last attempt - throw
if ( attempt === maxRetries ) {
throw new Error ( ` Failed after ${ maxRetries } attempts: ${ result . error . message } ` );
}
console . warn ( ` Attempt ${ attempt } failed, retrying... ` );
}
}
// Usage
const data = await retryTool ( ' api:fetch ' , { url : ' /data ' });
Fallback Pattern
// Try primary, fall back to secondary
const result = await callTool ( ' cache:get ' , { key : ' users ' }, { throwOnError : false });
const users = result . success
? result . data
: await callTool ( ' db:query ' , { table : ' users ' }); // Fallback to DB
return users ;
Partial Success Pattern
// Process items, collect both successes and failures
const ids = [ ' id-1 ' , ' id-2 ' , ' id-3 ' , ' id-4 ' ];
const results = { success : [], failed : [] };
for ( const id of ids ) {
const result = await callTool ( ' users:get ' , { id }, { throwOnError : false });
if ( result . success ) {
results . success . push ( result . data );
} else {
results . failed . push ({ id , error : result . error . message });
}
}
return {
users : results . success ,
errors : results . failed ,
successRate : results . success . length / ids . length ,
};
Debugging Guide
Using console.log
// Enable in config
CodeCallPlugin . init ({
vm : { allowConsole : true }
});
// In script
const users = await callTool ( ' users:list ' , { limit : 10 });
console . log ( ' Fetched users: ' , users . length );
for ( const user of users ) {
console . log ( ' Processing: ' , user . id , user . email );
}
// Logs appear in response.logs array
Interpreting Error Messages
Maximum iteration limit exceeded
Cause: Loop ran more than maxIterations times
Fix: Use pagination or filter data before looping// Bad: looping over potentially large dataset
for ( const item of items ) { ... }
// Good: paginate or limit
const page = items . slice ( 0 , 100 );
for ( const item of page ) { ... }
Maximum tool call limit exceeded
Script execution timed out
Cause: Script ran longer than timeoutMs
Fix: Optimize, use less data, or increase timeout// Check preset timeout
// locked_down: 2s, secure: 3.5s, balanced: 5s
CodeCallPlugin . init ({
vm : { preset : ' balanced ' , timeoutMs : 8000 }
});
Identifier 'X' is not allowed
Cause: Used a blocked identifier (eval, require, etc.)
Fix: Use allowed alternatives// Blocked
eval ( ' code ' );
require ( ' module ' );
setTimeout ( fn , 100 );
// Allowed
// Use callTool for external operations
await callTool ( ' code:run ' , { script : ' code ' });
Development Mode
For easier debugging during development:
CodeCallPlugin . init ({
vm : {
preset : ' experimental ' , // Longer timeouts, more iterations
allowConsole : true ,
},
// Don't sanitize errors in development
sanitization : {
removeStackTraces : process . env . NODE_ENV === ' production ' ,
removeFilePaths : process . env . NODE_ENV === ' production ' ,
},
});
Testing Strategy
Unit Testing AgentScript
import { Enclave } from ' enclave-vm ' ;
describe ( ' AgentScript ' , () => {
let enclave : Enclave ;
beforeEach (() => {
enclave = new Enclave ({ securityLevel : ' STANDARD ' });
});
afterEach (() => {
enclave . dispose ();
});
it ( ' should execute basic script ' , async () => {
const result = await enclave . execute ( `
return 1 + 1;
` );
expect ( result . success ). toBe ( true );
expect ( result . value ). toBe ( 2 );
});
it ( ' should call tools ' , async () => {
const mockToolHandler = jest . fn (). mockResolvedValue ({ users : [] });
const result = await enclave . execute ( `
const data = await callTool('users:list', {});
return data.users.length;
` , { toolHandler : mockToolHandler });
expect ( mockToolHandler ). toHaveBeenCalledWith ( ' users:list ' , {});
expect ( result . value ). toBe ( 0 );
});
});
import { App , Tool , ToolContext } from ' @frontmcp/sdk ' ;
import { CodeCallPlugin } from ' @frontmcp/plugins ' ;
// Create test app with mock tools
@ App ({ id : ' test-app ' , plugins : [ CodeCallPlugin . init ()] })
class TestApp {
@ Tool ({ name : ' users:list ' })
async listUsers ( ctx : ToolContext ) {
return [
{ id : ' 1 ' , name : ' Alice ' },
{ id : ' 2 ' , name : ' Bob ' },
];
}
}
describe ( ' CodeCall Integration ' , () => {
it ( ' should execute scripts with real tools ' , async () => {
const response = await callMcpTool ( ' codecall:execute ' , {
script : `
const users = await callTool('users:list', {});
return users.map(u => u.name);
` ,
});
expect ( response . status ). toBe ( ' ok ' );
expect ( response . result ). toEqual ([ ' Alice ' , ' Bob ' ]);
});
});
Testing Security Rules
describe ( ' Security ' , () => {
it ( ' should block eval ' , async () => {
const result = await enclave . execute ( `
eval('1 + 1');
` );
expect ( result . success ). toBe ( false );
expect ( result . error ?. message ). toContain ( ' eval ' );
});
it ( ' should block self-reference ' , async () => {
const result = await callMcpTool ( ' codecall:execute ' , {
script : `
await callTool('codecall:execute', { script: 'return 1' });
` ,
});
expect ( result . status ). toBe ( ' illegal_access ' );
expect ( result . error . code ). toBe ( ' SELF_REFERENCE_BLOCKED ' );
});
it ( ' should enforce iteration limit ' , async () => {
const result = await enclave . execute ( `
let i = 0;
for (const x of Array(100000)) { i++; }
return i;
` , { config : { maxIterations : 1000 } });
expect ( result . success ). toBe ( false );
expect ( result . error ?. message ). toContain ( ' iteration limit ' );
});
});
CI/CD Integration
# .github/workflows/test.yml
name : Test CodeCall Scripts
on : [ push , pull_request ]
jobs :
test :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- uses : actions/setup-node@v4
with :
node-version : ' 20 '
- run : npm ci
- run : npm test
# Run CodeCall-specific security tests
- run : npm run test:security
env :
CODECALL_VM_PRESET : secure
Rate Limiting
CodeCall meta-tools respect FrontMCP’s rate limiting:
import { RateLimitPlugin } from ' @frontmcp/plugins ' ;
@ App ({
plugins : [
CodeCallPlugin . init ({ ... }),
RateLimitPlugin . init ({
rules : [
{ tool : ' codecall:execute ' , limit : 10 , window : ' 1m ' },
{ tool : ' codecall:search ' , limit : 100 , window : ' 1m ' },
],
}),
],
})