Class: GroupedToolBuilder<TContext, TCommon, TName, TRouterMap>
Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:160
Fluent builder for creating consolidated MCP tools.
Groups multiple related operations behind a single discriminator field (default: "action"), producing one MCP tool definition with a union schema and auto-generated descriptions.
See
createTool for the recommended factory function
Type Parameters
| Type Parameter | Default type | Description |
|---|---|---|
TContext | void | Application context passed to every handler |
TCommon extends Record<string, unknown> | Record<string, never> | Shape of the common schema (inferred automatically) |
TName extends string | string | Tool name literal (inferred by createTool) |
TRouterMap extends Record<string, unknown> | Record<string, never> | Accumulated action entries for InferRouter (phantom type) |
Implements
ToolBuilder<TContext>
Constructors
Constructor
new GroupedToolBuilder<TContext, TCommon, TName, TRouterMap>(name): GroupedToolBuilder<TContext, TCommon, TName, TRouterMap>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:189
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
GroupedToolBuilder<TContext, TCommon, TName, TRouterMap>
Methods
action()
Call Signature
action<TActionName, TSchema, TOmit>(config): GroupedToolBuilder<TContext, TCommon, TName, TRouterMap & { [K in `${string}.${string}`]: TSchema["_output"] & Omit<TCommon, TOmit> }>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:680
Register a flat action.
Flat actions use simple keys (e.g. "list", "create"). Cannot be mixed with .group() on the same builder.
When a schema is provided, the handler args are fully typed as TSchema["_output"] & TCommon — no type assertions needed.
Type Parameters
| Type Parameter | Default type |
|---|---|
TActionName extends string | - |
TSchema extends ZodObject<ZodRawShape, UnknownKeysParam, ZodTypeAny, { [key: string]: any; }, { [key: string]: any; }> | - |
TOmit extends string | number | symbol | never |
Parameters
| Parameter | Type | Description |
|---|---|---|
config | { description?: string; destructive?: boolean; handler: (ctx, args) => Promise<ToolResponse>; idempotent?: boolean; name: TActionName; omitCommon?: TOmit[]; readOnly?: boolean; schema: TSchema; } | Action configuration |
config.description? | string | - |
config.destructive? | boolean | - |
config.handler | (ctx, args) => Promise<ToolResponse> | - |
config.idempotent? | boolean | - |
config.name | TActionName | - |
config.omitCommon? | TOmit[] | - |
config.readOnly? | boolean | - |
config.schema | TSchema | - |
Returns
GroupedToolBuilder<TContext, TCommon, TName, TRouterMap & { [K in `${string}.${string}`]: TSchema["_output"] & Omit<TCommon, TOmit> }>
this for chaining
Example
createTool<AppContext>('projects')
.action({
name: 'list',
description: 'List all projects',
readOnly: true,
schema: z.object({ status: z.enum(['active', 'archived']).optional() }),
handler: async (ctx, args) => {
// args: { status?: 'active' | 'archived' } — fully typed
return success(await ctx.db.projects.findMany({ where: args }));
},
})
.action({
name: 'delete',
destructive: true,
schema: z.object({ id: z.string() }),
handler: async (ctx, args) => {
await ctx.db.projects.delete({ where: { id: args.id } });
return success('Deleted');
},
});See
- ActionConfig for all configuration options
- GroupedToolBuilder.group for hierarchical grouping
Call Signature
action<TActionName>(config): GroupedToolBuilder<TContext, TCommon, TName, TRouterMap & { [K in `${string}.${string}`]: TCommon extends Record<string, never> ? Record<string, unknown> : TCommon }>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:691
Register a flat action (untyped: no schema, args default to Record<string, unknown>)
Type Parameters
| Type Parameter |
|---|
TActionName extends string |
Parameters
| Parameter | Type |
|---|---|
config | ActionConfig<TContext> & { name: TActionName; } |
Returns
GroupedToolBuilder<TContext, TCommon, TName, TRouterMap & { [K in `${string}.${string}`]: TCommon extends Record<string, never> ? Record<string, unknown> : TCommon }>
annotations()
annotations(a): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:259
Set MCP tool annotations.
Manual override for tool-level annotations. If not set, annotations are automatically aggregated from per-action properties.
Parameters
| Parameter | Type | Description |
|---|---|---|
a | Record<string, unknown> | Annotation key-value pairs |
Returns
this
this for chaining
Example
createTool('admin')
.annotations({ openWorldHint: true, returnDirect: false })See
bindState()
bindState(states, transition?): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:578
Bind this tool to specific FSM states.
When a StateMachineGate is configured, this tool is only visible in tools/list when the FSM is in one of the specified states.
Parameters
| Parameter | Type | Description |
|---|---|---|
states | string[] | FSM state(s) where this tool is visible |
transition? | string | Event to send on successful execution |
Returns
this
this for chaining
buildToolDefinition()
buildToolDefinition(): {
_meta?: {
[key: string]: unknown;
};
annotations?: {
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
readOnlyHint?: boolean;
title?: string;
};
description?: string;
execution?: {
taskSupport?: "optional" | "required" | "forbidden";
};
icons?: {
mimeType?: string;
sizes?: string[];
src: string;
theme?: "light" | "dark";
}[];
inputSchema: {
[key: string]: unknown;
properties?: {
[key: string]: object;
};
required?: string[];
type: "object";
};
name: string;
outputSchema?: {
[key: string]: unknown;
properties?: {
[key: string]: object;
};
required?: string[];
type: "object";
};
title?: string;
};Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:806
Generate the MCP Tool definition.
Compiles all actions into a single MCP tool with auto-generated description, union schema, and aggregated annotations. Caches the result and permanently freezes the builder.
Called automatically by execute if not called explicitly.
Returns
{
_meta?: {
[key: string]: unknown;
};
annotations?: {
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
readOnlyHint?: boolean;
title?: string;
};
description?: string;
execution?: {
taskSupport?: "optional" | "required" | "forbidden";
};
icons?: {
mimeType?: string;
sizes?: string[];
src: string;
theme?: "light" | "dark";
}[];
inputSchema: {
[key: string]: unknown;
properties?: {
[key: string]: object;
};
required?: string[];
type: "object";
};
name: string;
outputSchema?: {
[key: string]: unknown;
properties?: {
[key: string]: object;
};
required?: string[];
type: "object";
};
title?: string;
}The compiled MCP Tool object
| Name | Type | Defined in |
|---|---|---|
_meta? | { [key: string]: unknown; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2397 |
annotations? | { destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; readOnlyHint?: boolean; title?: string; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2383 |
annotations.destructiveHint? | boolean | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2386 |
annotations.idempotentHint? | boolean | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2387 |
annotations.openWorldHint? | boolean | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2388 |
annotations.readOnlyHint? | boolean | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2385 |
annotations.title? | string | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2384 |
description? | string | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2372 |
execution? | { taskSupport?: "optional" | "required" | "forbidden"; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2390 |
execution.taskSupport? | "optional" | "required" | "forbidden" | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2391 |
icons? | { mimeType?: string; sizes?: string[]; src: string; theme?: "light" | "dark"; }[] | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2398 |
inputSchema | { [key: string]: unknown; properties?: { [key: string]: object; }; required?: string[]; type: "object"; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2373 |
inputSchema.properties? | { [key: string]: object; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2375 |
inputSchema.required? | string[] | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2376 |
inputSchema.type | "object" | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2374 |
name | string | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2407 |
outputSchema? | { [key: string]: unknown; properties?: { [key: string]: object; }; required?: string[]; type: "object"; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2378 |
outputSchema.properties? | { [key: string]: object; } | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2380 |
outputSchema.required? | string[] | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2381 |
outputSchema.type | "object" | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2379 |
title? | string | node_modules/@modelcontextprotocol/sdk/dist/esm/types.d.ts:2408 |
Throws
If no actions are registered
Example
const tool = builder.buildToolDefinition();
console.log(tool.name); // "projects"
console.log(tool.description); // Auto-generated
console.log(tool.inputSchema); // Union of all action schemasImplementation of
ToolBuilder.buildToolDefinition
cached()
cached(): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:398
Mark this tool's data as immutable (safe to cache forever).
Use for reference data: countries, currencies, ICD-10 codes. Equivalent to cacheControl: 'immutable' in manual policies.
Returns
this
this for chaining
Example
createTool('countries')
.cached()
.action({ name: 'list', readOnly: true, handler: listCountries });commonSchema()
commonSchema<TSchema>(schema): GroupedToolBuilder<TContext, TSchema["_output"], TName, TRouterMap>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:321
Set a common schema shared by all actions.
Fields from this schema are injected into every action's input and marked as (always required) in the auto-generated description. The return type narrows to propagate types to all handlers.
Type Parameters
| Type Parameter | Description |
|---|---|
TSchema extends ZodObject<ZodRawShape, UnknownKeysParam, ZodTypeAny, { [key: string]: any; }, { [key: string]: any; }> | Zod object schema type (inferred) |
Parameters
| Parameter | Type | Description |
|---|---|---|
schema | TSchema | A z.object() defining shared fields |
Returns
GroupedToolBuilder<TContext, TSchema["_output"], TName, TRouterMap>
A narrowed builder with TCommon set to TSchema["_output"]
Example
createTool<AppContext>('projects')
.commonSchema(z.object({
workspace_id: z.string().describe('Workspace identifier'),
}))
.action({
name: 'list',
handler: async (ctx, args) => {
// ✅ args.workspace_id is typed as string
const projects = await ctx.db.projects.findMany({
where: { workspaceId: args.workspace_id },
});
return success(projects);
},
});concurrency()
concurrency(config): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:494
Set concurrency limits for this tool (Semaphore + Queue pattern).
Prevents thundering-herd scenarios where the LLM fires N concurrent calls in the same millisecond. Implements a semaphore with backpressure queue and load shedding.
When all active slots are occupied, new calls enter the queue. When the queue is full, calls are immediately rejected with a self-healing SERVER_BUSY error.
MCP Spec Compliance: The MCP specification requires servers to rate-limit tool invocations. This method fulfills that requirement.
Zero overhead when not configured — no semaphore exists.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | ConcurrencyConfig | Concurrency configuration |
Returns
this
this for chaining
Example
createTool<AppContext>('billing')
.concurrency({ maxActive: 5, maxQueue: 20 })
.action({ name: 'process_invoice', handler: processInvoice });
// 5 concurrent executions, 20 queued, rest rejectedSee
ConcurrencyConfig for configuration options
debug()
debug(observer): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:863
Enable debug observability for this tool.
When enabled, structured DebugEvent events are emitted at each step of the execution pipeline.
When disabled (the default), there is zero runtime overhead — no conditionals, no timing, no object allocations in the hot path.
Parameters
| Parameter | Type | Description |
|---|---|---|
observer | DebugObserverFn | A DebugObserverFn created by createDebugObserver() |
Returns
this
this for chaining
Example
import { createTool, createDebugObserver, success } from '@vinkius-core/mcp-fusion';
const debug = createDebugObserver();
const tool = createTool<void>('users')
.debug(debug) // ← enable observability
.action({ name: 'list', handler: async () => success([]) });description()
description(desc): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:236
Set the tool description.
Appears as the first line in the auto-generated tool description that the LLM sees.
Parameters
| Parameter | Type | Description |
|---|---|---|
desc | string | Human-readable description of what this tool does |
Returns
this
this for chaining
Example
createTool('projects')
.description('Manage workspace projects')discriminator()
discriminator(field): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:215
Set the discriminator field name.
The discriminator is the field the LLM uses to select which action to execute. Defaults to "action".
Parameters
| Parameter | Type | Description |
|---|---|---|
field | string | Field name for the discriminator enum |
Returns
this
this for chaining
Example
// Custom discriminator
const builder = createTool('projects')
.discriminator('operation')
.action({ name: 'list', handler: listProjects });
// LLM sends: { operation: 'list' }Default Value
"action"
enableSelect()
enableSelect(): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:459
Enable _select reflection for context window optimization.
When enabled, actions that use a Presenter with a Zod schema expose an optional _select parameter in the input schema. The AI can send _select: ['status', 'amount'] to receive only the specified top-level fields in the data payload, reducing context window usage without developer effort.
Disabled by default — opt-in to avoid changing existing tool schemas.
Late Guillotine: UI blocks, system rules, and action suggestions are always computed with the full validated data. Only the wire-facing data block is filtered.
Shallow (top-level only): Nested objects are returned whole. If the AI selects 'user', it gets the entire user object. No recursive GraphQL-style traversal.
Returns
this
this for chaining
Example
createTool<AppContext>('invoices')
.enableSelect() // Expose _select in input schema
.action({
name: 'get',
returns: InvoicePresenter,
handler: async (ctx, args) => ctx.db.invoices.findUnique(args.id),
});
// AI sends: { action: 'get', id: '123', _select: ['status'] }
// Returns: { status: 'paid' } instead of full invoiceSee
Presenter.getSchemaKeys for introspection
execute()
execute(
ctx,
args,
progressSink?,
signal?): Promise<ToolResponse>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:961
Route a tool call to the correct action handler.
Pipeline: parseDiscriminator → resolveAction → validateArgs → runChain
Auto-calls buildToolDefinition if not called yet. If a debug observer is active, structured events are emitted at each pipeline step with timing information.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | TContext | Application context |
args | Record<string, unknown> | Raw arguments from the LLM (includes discriminator) |
progressSink? | ProgressSink | Optional callback for streaming progress notifications. When attached via attachToServer(), this is automatically wired to MCP notifications/progress. When omitted, progress events are silently consumed. |
signal? | AbortSignal | Optional AbortSignal from the MCP SDK protocol layer. Fired when the client sends notifications/cancelled or the connection drops. The framework checks this signal before handler execution and during generator iteration, aborting zombie operations immediately. |
Returns
Promise<ToolResponse>
The handler's ToolResponse
Example
// Direct execution (useful in tests)
const result = await builder.execute(ctx, {
action: 'list',
workspace_id: 'ws_123',
});Implementation of
getActionMetadata()
getActionMetadata(): ActionMetadata[];Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1457
Get metadata for all registered actions.
Useful for programmatic documentation, compliance audits, dashboard generation, or runtime observability.
Returns
Array of ActionMetadata objects
Example
const meta = builder.getActionMetadata();
for (const action of meta) {
console.log(`${action.key}: destructive=${action.destructive}, fields=${action.requiredFields}`);
}See
ActionMetadata for the metadata shape
Implementation of
getActionNames()
getActionNames(): string[];Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1309
Get all registered action keys (e.g. ["list", "create"] or ["users.list", "users.ban"]).
Returns
string[]
Implementation of
getActions()
getActions(): readonly InternalAction<TContext>[];Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1321
Get all registered internal actions. Used by the Exposition Compiler for atomic tool expansion.
Returns
readonly InternalAction<TContext>[]
Read-only array of internal action definitions
Implementation of
getCommonSchema()
getCommonSchema():
| ZodObject<ZodRawShape, UnknownKeysParam, ZodTypeAny, {
[key: string]: any;
}, {
[key: string]: any;
}>
| undefined;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1328
Get the common schema shared across all actions. Used by the Exposition Compiler for schema purification.
Returns
| ZodObject<ZodRawShape, UnknownKeysParam, ZodTypeAny, { [key: string]: any; }, { [key: string]: any; }> | undefined
The common Zod schema, or undefined if not set
Implementation of
getDiscriminator()
getDiscriminator(): string;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1314
Get the discriminator field name (e.g. "action"). Used by the Exposition Compiler.
Returns
string
Implementation of
getFsmBinding()
getFsmBinding():
| {
states: string[];
transition?: string;
}
| undefined;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:589
Get the FSM binding metadata (if any). Used by ToolRegistry and ServerAttachment for FSM gating.
Returns
| { states: string[]; transition?: string; } | undefined
getName()
getName(): string;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1303
Get the tool name.
Returns
string
Implementation of
getSandboxConfig()
getSandboxConfig(): SandboxConfig | undefined;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:562
Get the sandbox configuration (if any). Used by framework internals and tests.
Returns
SandboxConfig | undefined
getSelectEnabled()
getSelectEnabled(): boolean;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1331
Check if _select reflection is enabled. Used by the Exposition Compiler.
Returns
boolean
Implementation of
getStateSyncHints()
getStateSyncHints(): ReadonlyMap<string, StateSyncHint>;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1334
Get per-action state sync hints for auto-policy generation.
Returns
ReadonlyMap<string, StateSyncHint>
Implementation of
getTags()
getTags(): string[];Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1306
Get a copy of the capability tags.
Returns
string[]
Implementation of
getToolName()
getToolName(): string;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:602
Get the tool name. Used by framework internals for tool routing and FSM binding.
Returns
string
group()
Call Signature
group(name, configure): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:747
Register a group of actions under a namespace.
Group actions use compound keys (e.g. "users.create", "billing.refund"). Cannot be mixed with .action() on the same builder.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Group name (must not contain dots) |
configure | GroupConfigurator<TContext, TCommon> | Callback that receives an ActionGroupBuilder |
Returns
this
this for chaining
Example
createTool<AppContext>('platform')
.group('users', 'User management', g => {
g.use(requireAdmin) // Group-scoped middleware
.action({ name: 'list', readOnly: true, handler: listUsers })
.action({ name: 'ban', destructive: true, schema: banSchema, handler: banUser });
})
.group('billing', g => {
g.action({ name: 'refund', destructive: true, schema: refundSchema, handler: issueRefund });
});
// Discriminator enum: "users.list" | "users.ban" | "billing.refund"See
- ActionGroupBuilder for group-level configuration
- GroupedToolBuilder.action for flat actions
Call Signature
group(
name,
description,
configure): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:748
Register a group of actions under a namespace.
Group actions use compound keys (e.g. "users.create", "billing.refund"). Cannot be mixed with .action() on the same builder.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Group name (must not contain dots) |
description | string | - |
configure | GroupConfigurator<TContext, TCommon> | Callback that receives an ActionGroupBuilder |
Returns
this
this for chaining
Example
createTool<AppContext>('platform')
.group('users', 'User management', g => {
g.use(requireAdmin) // Group-scoped middleware
.action({ name: 'list', readOnly: true, handler: listUsers })
.action({ name: 'ban', destructive: true, schema: banSchema, handler: banUser });
})
.group('billing', g => {
g.action({ name: 'refund', destructive: true, schema: refundSchema, handler: issueRefund });
});
// Discriminator enum: "users.list" | "users.ban" | "billing.refund"See
- ActionGroupBuilder for group-level configuration
- GroupedToolBuilder.action for flat actions
invalidates()
invalidates(...patterns): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:372
Declare glob patterns invalidated when this tool succeeds.
Eliminates manual stateSync.policies configuration — the framework auto-collects hints from all builders.
Parameters
| Parameter | Type | Description |
|---|---|---|
...patterns | string[] | Glob patterns (e.g. 'sprints.*', 'tasks.*') |
Returns
this
this for chaining
Example
createTool('tasks')
.invalidates('tasks.*', 'sprints.*')
.action({ name: 'update', handler: updateTask });See
StateSyncConfig for centralized configuration
maxPayloadBytes()
maxPayloadBytes(bytes): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:527
Set maximum payload size for tool responses (Egress Guard).
Prevents oversized responses from crashing the Node process with OOM or overflowing the LLM context window.
When a response exceeds the limit, the text content is truncated and a system intervention message is injected, forcing the LLM to use pagination or filters.
This is a brute-force safety net. For domain-aware truncation with guidance, use Presenter .agentLimit() instead.
Zero overhead when not configured.
Parameters
| Parameter | Type | Description |
|---|---|---|
bytes | number | Maximum payload size in bytes |
Returns
this
this for chaining
Example
createTool<AppContext>('logs')
.maxPayloadBytes(2 * 1024 * 1024) // 2MB
.action({ name: 'search', handler: searchLogs });See
Presenter.agentLimit for domain-level truncation
previewPrompt()
previewPrompt(): string;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:1377
Preview the exact MCP protocol payload that the LLM will receive.
Builds the tool definition if not already built, then renders a human-readable preview of the complete tool including:
- Tool name and description
- Input schema (JSON)
- Annotations (if any)
- Approximate token count (~4 chars per token, GPT-5.2 heuristic)
Call this from your dev environment to optimize token usage and verify the LLM-facing prompt without starting an MCP server.
Returns
string
Formatted string showing the exact MCP payload + token estimate
Example
const projects = defineTool<AppContext>('projects', { ... });
console.log(projects.previewPrompt());
// Output:
// ┌─────────────────────────────────────────┐
// │ MCP Tool Preview: projects │
// ├─────────────────────────────────────────┤
// │ Name: projects │
// │ Actions: 3 (list, create, delete) │
// │ Tags: api, admin │
// ├─── Description ─────────────────────────┤
// │ Manage workspace projects. ... │
// ├─── Input Schema ────────────────────────┤
// │ { "type": "object", ... } │
// ├─── Annotations ─────────────────────────┤
// │ readOnlyHint: false │
// │ destructiveHint: true │
// ├─── Token Estimate ──────────────────────┤
// │ ~342 tokens (1,368 chars) │
// └─────────────────────────────────────────┘See
buildToolDefinition for the raw MCP Tool object
Implementation of
sandbox()
sandbox(config): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:552
Enable zero-trust sandboxed execution for this tool.
Stores the sandbox configuration so that tools built with .sandboxed() on the FluentToolBuilder can propagate it.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | SandboxConfig | Sandbox configuration (timeout, memory, output size) |
Returns
this
this for chaining
Example
createTool<AppContext>('analytics')
.sandbox({ timeout: 5000, memoryLimit: 128 })
.action({ name: 'compute', handler: computeHandler });See
- SandboxConfig for configuration options
- SandboxEngine for the execution engine
stale()
stale(): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:410
Mark this tool's data as volatile (never cache).
Equivalent to cacheControl: 'no-store' in manual policies. Use for dynamic data that changes frequently.
Returns
this
this for chaining
tags()
tags(...tags): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:286
Set capability tags for selective tool exposure.
Tags control which tools the LLM sees via ToolRegistry.attachToServer's filter option. Use tags to implement per-session context gating.
Parameters
| Parameter | Type | Description |
|---|---|---|
...tags | string[] | One or more string tags |
Returns
this
this for chaining
Example
const users = createTool<AppContext>('users').tags('core');
const admin = createTool<AppContext>('admin').tags('admin', 'internal');
// Expose only 'core' tools to the LLM:
registry.attachToServer(server, { filter: { tags: ['core'] } });See
ToolRegistry.getTools for filtered tool retrieval
telemetry()
telemetry(sink): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:883
Enable out-of-band telemetry emission for Inspector TUI.
When set, validate, middleware, presenter.slice, and presenter.rules events are emitted to the TelemetrySink (Shadow Socket IPC), enabling real-time monitoring in the Inspector dashboard.
Zero overhead when not configured — no conditionals in the hot path.
Parameters
| Parameter | Type | Description |
|---|---|---|
sink | TelemetrySink | A TelemetrySink from startServer() or TelemetryBus |
Returns
this
this for chaining
toonDescription()
toonDescription(): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:346
Enable TOON-formatted descriptions for token optimization.
Uses TOON (Token-Oriented Object Notation) to encode action metadata in a compact tabular format, reducing description token count by ~30-50%.
Returns
this
this for chaining
Example
createTool('projects')
.toonDescription() // Compact descriptions
.action({ name: 'list', handler: listProjects })See
toonSuccess for TOON-encoded responses
tracing()
tracing(tracer): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:924
Enable OpenTelemetry-compatible tracing for this tool.
When enabled, each execute() call creates a single span with structured events for each pipeline step (mcp.route, mcp.validate, mcp.middleware, mcp.execute).
Zero overhead when disabled — the fast path has no conditionals.
OTel direct pass-through: The FusionTracer interface is a structural subtype of OTel's Tracer, so you can pass an OTel tracer directly without any adapter:
import { trace } from '@opentelemetry/api';
const tool = createTool<AppContext>('projects')
.tracing(trace.getTracer('mcp-fusion'))
.action({ name: 'list', handler: listProjects });Error classification:
- Validation failures →
SpanStatusCode.UNSET+mcp.error_typeattribute - Handler exceptions →
SpanStatusCode.ERROR+recordException()
Context propagation limitation: Since MCP Fusion does not depend on @opentelemetry/api, it cannot call context.with(trace.setSpan(...)). Auto-instrumented downstream calls (Prisma, HTTP, Redis) inside handlers will appear as siblings, not children, of the MCP span.
Parameters
| Parameter | Type | Description |
|---|---|---|
tracer | FusionTracer | A FusionTracer (or OTel Tracer) instance |
Returns
this
this for chaining
See
- FusionTracer for the interface contract
- SpanStatusCode for status code semantics
use()
use(mw): this;Defined in: packages/core/src/core/builder/GroupedToolBuilder.ts:633
Add middleware to the execution chain.
Middleware runs in registration order (first registered = outermost). Chains are pre-compiled at build time — zero runtime assembly cost.
Accepts both MiddlewareDefinition from f.middleware() and raw MiddlewareFn functions.
Parameters
| Parameter | Type | Description |
|---|---|---|
mw | | MiddlewareFn<TContext> | MiddlewareDefinition<TContext, Record<string, unknown>> | Middleware function or MiddlewareDefinition |
Returns
this
this for chaining
Example
const requireAuth: MiddlewareFn<AppContext> = async (ctx, args, next) => {
if (!ctx.user) return error('Unauthorized');
return next();
};
createTool<AppContext>('projects')
.use(requireAuth) // Runs on every action
.action({ name: 'list', handler: listProjects });See
- MiddlewareFn for the middleware signature
- ActionGroupBuilder.use for group-scoped middleware