Transforms Pipeline Engine
The Transforms Pipeline Engine in NitroStack provides an extensible catalog-transformation architecture designed for enterprise MCP servers. By intercepting tools/list and tools/call requests, transforms enable progressive tool discovery, dynamic session-based visibility gating, and sandboxed WebAssembly script execution, reducing AI model token consumption by up to 98%.
Table of Contents
- Overview & Token Economics
- Architecture Pipeline
- BM25SearchTransform (Progressive Discovery)
- CodeModeTransform (Sandboxed QuickJS WASM)
- VisibilityTransform & Session Gating
- Catalog Bypass Scopes (CatalogTransform)
- Transform Pipeline Configuration
Overview & Token Economics
The Raw Catalog Problem
In enterprise environments, MCP servers often register dozens or hundreds of specialized tools across diverse business domains:
┌────────────────────────────────────────────────────────┐
│ Traditional MCP Architecture │
├────────────────────────────────────────────────────────┤
│ │
│ Client connects -> tools/list │
│ Server dumps 100+ complete tool schemas │
│ │
│ Payload: 15,000 to 40,000 tokens │
│ │
│ Consequences: │
│ • Huge context consumption on EVERY request │
│ • Slower model response times & inflated API costs │
│ • Tool schema distraction leading to hallucinations │
│ • Incompatible with models with smaller contexts │
│ │
└────────────────────────────────────────────────────────┘
The NitroStack Solution
The Transforms Pipeline solves this by replacing the massive raw tool catalog with lightweight synthetic meta-tools and progressive discovery mechanisms:
- Progressive Search Discovery (
BM25SearchTransform): Collapses hundreds of tools into two meta-tools (search_toolsandcall_tool), plus any criticalalwaysVisibletools. The model queries for relevant capabilities only when needed. - Code Mode Orchestration (
CodeModeTransform): Exposes three meta-tools (search,get_schema,execute). The model writes JavaScript code that executes locally inside a QuickJS WebAssembly sandbox, collapsing multi-round-trip chains into a single call. - Dynamic Visibility Gating (
VisibilityTransform): Keeps advanced or destructive tools hidden until explicitly unlocked for a session viactx.enableTools().
┌────────────────────────────────────────────────────────────────────────┐
│ Transforms Pipeline Flow │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ Client Request (tools/list) │
│ │ │
│ ▼ │
│ [Raw Tools Map] (50+ registered tools) │
│ │ │
│ ├── Transform Tools Pipeline: │
│ │ 1. VisibilityTransform (filter hidden/tenant tools) │
│ │ 2. BM25SearchTransform OR CodeModeTransform │
│ │ │
│ ▼ │
│ Client Receives: │
│ • Synthetic meta-tools (search_tools, call_tool) │
│ • Designated alwaysVisible tools │
│ │
└────────────────────────────────────────────────────────────────────────┘
Architecture Pipeline
A transform implements the McpTransform interface, providing lifecycle hooks to reshape the tool catalog and resolve synthetic tool invocations:
export interface McpTransform {
readonly name: string;
/** Called once when transform is attached to a server */
onRegister?(registry: TransformRegistry): void;
/** Releases resources (worker threads, timers) upon server shutdown */
dispose?(): Promise<void> | void;
/** Reshapes, filters, or augments catalog during tools/list */
transformTools?(
tools: Tool[],
context?: ExecutionContext
): Promise<Tool[]> | Tool[];
/** Resolves synthetic or re-routed tools during tools/call */
resolveTool?(
name: string,
next: NextToolHandler,
context?: ExecutionContext
): Promise<Tool | undefined>;
}
Transforms execute sequentially in the order defined in @McpApp({ transforms: [...] }).
BM25SearchTransform (Progressive Discovery)
The BM25SearchTransform indexes all registered tools using an in-memory BM25 information retrieval engine. When a client requests tools/list, it returns two synthetic tools instead of the entire catalog:
search_tools: Performs keyword or natural-language relevance searches against indexed tool names, descriptions, and parameter definitions.call_tool: Dispatches an invocation to any underlying tool returned by the search query.
Configuration
import { McpApp, Module, BM25SearchTransform } from '@nitrostack/core';
import { FinanceController } from './finance.controller.js';
import { InventoryController } from './inventory.controller.js';
@McpApp({
module: AppModule,
server: {
name: 'enterprise-inventory-service',
version: '1.0.0',
},
transforms: [
new BM25SearchTransform({
defaultLimit: 5,
defaultDetail: 'detailed', // 'brief' | 'detailed' | 'full'
alwaysVisible: [
'finance_auth_login',
'inventory_get_status',
],
searchToolDescription:
'Searches available tools by keywords or natural language task description. ' +
'Query to retrieve matching tool names and schemas before calling them.',
}),
],
})
@Module({
controllers: [FinanceController, InventoryController],
})
export class AppModule {}
Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
defaultLimit | number | 5 | Maximum number of search results returned per query. |
defaultDetail | 'brief' | 'detailed' | 'full' | 'detailed' | Schema detail level returned by search_tools. |
alwaysVisible | string[] | [] | List of tool names that bypass catalog collapsing and remain directly visible. |
searchToolName | string | 'search_tools' | Custom name for the synthetic search tool. |
callToolName | string | 'call_tool' | Custom name for the synthetic dispatch tool. |
searchToolDescription | string | Built-in | Custom prompt description for search_tools. |
callToolDescription | string | Built-in | Custom prompt description for call_tool. |
allowRegex | boolean | false | Enable regular expression pattern matching (RegexSearchTransform). |
Interaction Cycle
Client (LLM) NitroStack Server
│ │
│─── 1. tools/list ────────────────▶│
│ │
│◀── 2. Returns: ───────────────────│
│ • search_tools │
│ • call_tool │
│ • inventory_get_status │
│ │
│─── 3. call_tool('search_tools', ──▶
│ { query: 'transfer' }) │
│ │
│◀── 4. Returns: ───────────────────│
│ • finance_transfer_funds │
│ (inputSchema, description) │
│ │
│─── 5. call_tool('call_tool', ─────▶
│ { name: 'finance_transfer_funds',
│ arguments: { to: '123', amount: 500 } })
│ │ Validates Zod schema
│ │ Executes underlying tool
│◀── 6. Result: { transferId: 88 } ─│
When routed through call_tool, NitroStack automatically validates incoming arguments against the underlying tool's Zod schema before execution.
CodeModeTransform (Sandboxed QuickJS WASM)
For complex multi-step workflows, CodeModeTransform lets AI models write JavaScript code that executes inside an isolated WebAssembly sandbox. Instead of making 5 serialized network round-trips to run 5 tools, the model writes a script that runs all 5 tools locally and returns only the final computed result.
Sandboxed Architecture
┌────────────────────────────────────────────────────────────────────────┐
│ Code Mode Architecture │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ NitroStack Server (Node.js Host) │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Worker Thread Pool (4 isolated worker threads) │ │
│ │ ┌────────────────────────────────────────────────────────────┐ │ │
│ │ │ QuickJS WebAssembly Engine (quickjs-emscripten) │ │ │
│ │ │ • ES2020 JavaScript execution environment │ │ │
│ │ │ • No access to Node.js fs, net, process, child_process │ │ │
│ │ │ • Bound callTool(name, args) async bridge │ │ │
│ │ │ • 100MB memory cap | 30s timeout | 50 tool call cap │ │ │
│ │ └────────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
Configuration
import {
McpApp,
Module,
CodeModeTransform,
DEFAULT_CODE_MODE_SEARCH_DESCRIPTION,
} from '@nitrostack/core';
import { DataController } from './data.controller.js';
@McpApp({
module: AppModule,
server: {
name: 'code-mode-analytics-service',
version: '1.0.0',
},
transforms: [
new CodeModeTransform({
workerPoolSize: 4, // Dedicated worker thread pool
memoryLimitMb: 128, // Memory cap per execution
timeoutMs: 15000, // Max execution time (15s)
maxToolCalls: 50, // Max tool invocations per script
allowDestructive: false, // Guard against destructive operations
searchToolDescription: DEFAULT_CODE_MODE_SEARCH_DESCRIPTION,
alwaysVisible: ['data_aggregate_sum'],
}),
],
})
@Module({
controllers: [DataController],
})
export class AppModule {}
Synthetic Meta-Tools
CodeModeTransform presents 3 synthetic meta-tools to the client:
search: Discovers available tools using keywords or natural-language queries.get_schema: Returns full parameter schemas and types for specific tool names.execute: Executes a JavaScript (ES2020) script string within the QuickJS sandbox.
Script Execution Example
When an agent needs to process data across multiple tools, it passes a script to execute:
// Script executed inside QuickJS sandbox
const orders = await callTool('orders_list', { status: 'pending' });
let totalRevenue = 0;
const highValueOrders = [];
for (const order of orders.items) {
const details = await callTool('orders_get_details', { orderId: order.id });
totalRevenue += details.totalAmount;
if (details.totalAmount > 1000) {
highValueOrders.push({ id: order.id, customer: details.customerEmail });
}
}
return {
pendingCount: orders.items.length,
totalRevenue,
highValueOrders,
};
Guardrails & Destructive Action Protection
When allowDestructive: false is configured, any tool decorated with annotations: { destructiveHint: true } is automatically blocked from execution inside the script. If the script attempts to invoke a destructive tool, execution halts immediately with a clear security rejection error.
VisibilityTransform & Session Gating
The VisibilityTransform controls tool availability on a per-session and per-subject basis. Tools can be initialized in a hidden state and dynamically unlocked at runtime.
Declaring Hidden Tools
import { Controller, ToolDecorator as Tool, ExecutionContext, z } from '@nitrostack/core';
@Controller('admin')
export class AdminController {
@Tool({
name: 'purge_cache',
description: 'Purges server caches (requires elevated privilege)',
visibility: 'hidden', // Hidden by default in tools/list
inputSchema: z.object({
tier: z.enum(['all', 'redis', 'memory']),
}),
})
async purgeCache(input: { tier: string }, ctx: ExecutionContext) {
return { purged: input.tier };
}
}
Dynamic Session Unlocking
Handlers can dynamically enable or disable tools for the active session using helpers on ExecutionContext:
@Tool({
name: 'authenticate_admin',
description: 'Authenticates administrator and unlocks administrative tools',
inputSchema: z.object({ passkey: z.string() }),
})
async authenticateAdmin(input: { passkey: string }, ctx: ExecutionContext) {
if (input.passkey !== process.env.ADMIN_KEY) {
throw new Error('Invalid administrative passkey');
}
// Dynamically reveal the hidden tool for this client session
if (ctx.enableTools) {
await ctx.enableTools(['admin_purge_cache']);
}
return { status: 'authenticated', unlockedTools: ['admin_purge_cache'] };
}
Enforcement Rules
- Security Guarding: If a client attempts to directly invoke a hidden tool via
tools/callwithout authorization,VisibilityTransformthrows a JSON-RPC error code-32601(VisibilityResolutionError). - Subject Deny Lists: Deny rules assigned to verified cryptographic identities survive across session reconnections.
Catalog Bypass Scopes (CatalogTransform)
Transforms often need to list or inspect registered tools without triggering infinite recursion or rebuilding search indexes. NitroStack provides CatalogTransform.withBypass():
import { CatalogTransform } from '@nitrostack/core';
// Internal search engine indexing tools
const rawTools = await CatalogTransform.withBypass(async () => {
return await server.getRegisteredTools();
});
BM25SearchTransformandCodeModeTransformhonor the bypass scope and return the raw tool list.VisibilityTransformintentionally ignores the bypass (honorsBypass(): false), ensuring security filtering and tenant boundaries can never be evaded.
Transform Pipeline Configuration
Multiple transforms can be combined in the @McpApp configuration decorator:
import {
McpApp,
Module,
VisibilityTransform,
BM25SearchTransform,
} from '@nitrostack/core';
@McpApp({
module: AppModule,
server: {
name: 'enterprise-hybrid-service',
version: '1.0.0',
},
transforms: [
// 1. First filter hidden tools based on session authorization
new VisibilityTransform(),
// 2. Then index authorized tools into progressive BM25 search
new BM25SearchTransform({
defaultLimit: 5,
alwaysVisible: ['auth_login', 'system_status'],
}),
],
})
@Module({})
export class AppModule {}