@invokta/tooling
@invokta/tooling provides development-time build gates for capability
composition and the final MCP tool catalog. Each command imports a built ESM
module and delegates validation to the same framework boundary used at runtime.
The package adds no runtime contract, adapter, or transport. It never invokes a capability or starts an engine.
Install
Section titled “Install”Install it as a development dependency in an engine that imports capabilities:
yarn add --dev @invokta/toolingThe package is native ESM and requires Node.js 22.20.0 or later. It exposes the
invokta binary and two package-root programmatic APIs.
Commands
Section titled “Commands”The package provides two commands.
check-capabilities
Section titled “check-capabilities”invokta check-capabilities <esm-module> [--export <name>]| Argument | Contract |
|---|---|
<esm-module> |
Exactly one non-empty path to an already-built ESM module, resolved from the current working directory |
--export <name> |
Optional own module export to inspect; defaults to capabilities and may appear once |
The module should contain composition only:
export const capabilities = composeCapabilities({ local, imports,});Build it, then run the check:
invokta check-capabilities ./dist/capabilities.jsinvokta check-capabilities ./dist/capabilities.js \ --export capabilitiesThe selected export must still carry the provenance created by
composeCapabilities. A plain map or a map flattened with object spread is
rejected because collisions may already have been overwritten.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 |
The selected export is a valid tracked composition |
1 |
Composition failed; every detected issue is reported |
2 |
Usage, module loading, export selection, or untracked-map failure |
The command writes diagnostics to standard error and nothing to standard output. A valid composition is silent.
Composition diagnostics
Section titled “Composition diagnostics”Composition issues are deterministic. Collisions come first, sorted by effective ID; other issues remain in composition order. Author-controlled values are encoded as JSON string literals so an ID cannot create a forged diagnostic line.
| Issue code | Meaning |
|---|---|
CAPABILITY_ID_COLLISION |
More than one declaration claims an effective ID |
CAPABILITY_IMPORT_INVALID |
An atomic import did not receive an exported-capability descriptor |
CAPABILITY_IMPORT_ID_NOT_FOUND |
include or remap names an unknown library ID |
CAPABILITY_REMAP_NOT_SELECTED |
A remap key is excluded by include |
Composition diagnostics contain effective IDs, default IDs, and declared source metadata. They exclude schemas, handlers, business input, dependency values, and credentials.
check-mcp
Section titled “check-mcp”invokta check-mcp <esm-module> [--export <name>]The selected export defaults to engine. The command constructs the same MCP
tool catalog used by stdio and HTTP, without starting an adapter or invoking a
capability. Dotted domain IDs remain valid because the check applies to their
derived public aliases.
invokta check-mcp ./dist/engine.jsinvokta check-mcp ./dist/application.js --export supportEngineSuccess is silent. A duplicate derived alias exits 1 with
MCP_TOOL_NAME_COLLISION, the public tool name, and both capability IDs. Usage,
module loading, export selection, or invalid-engine failures exit 2.
CI setup
Section titled “CI setup”Add the gate after the engine build:
{ "scripts": { "build": "tsc -b --pretty false", "check:capabilities": "invokta check-capabilities ./dist/capabilities.js", "check:mcp": "invokta check-mcp ./dist/engine.js" }}yarn buildyarn check:capabilitiesyarn check:mcpRun it for every engine that composes imported capabilities. Literal IDs also receive TypeScript diagnostics, but the built-module gate covers values widened or computed at runtime.
The package root exports both functions and their option types:
import { checkCapabilities, type CheckCapabilitiesIo, type CheckCapabilitiesOptions, checkMcp, type CheckMcpIo, type CheckMcpOptions,} from "@invokta/tooling";interface CheckCapabilitiesIo { readonly writeStderr: ( text: string, ) => void | Promise<void>;}
type CheckMcpIo = CheckCapabilitiesIo;
interface CheckCapabilitiesOptions { readonly argv?: readonly string[]; readonly cwd?: string; readonly io?: Partial<CheckCapabilitiesIo>;}
interface CheckMcpOptions { readonly argv?: readonly string[]; readonly cwd?: string; readonly io?: Partial<CheckMcpIo>;}
function checkCapabilities( options?: CheckCapabilitiesOptions,): Promise<number>;
function checkMcp(options?: CheckMcpOptions): Promise<number>;argv defaults to process.argv.slice(2). cwd defaults to process.cwd() and
controls path resolution. io.writeStderr replaces the diagnostic sink.
const exitCode = await checkCapabilities({ argv: [ "check-capabilities", "./dist/capabilities.js", "--export", "capabilities", ], cwd: process.cwd(),});
process.exitCode = exitCode;Both functions return a numeric exit code and never terminate the process. Read Capability packages for the complete authoring and importing flow.