NitroStack 1.1 · Code Mode

Keep the tool catalog out of the prompt.

The model writes a short script. The script calls your MCP tools on the server. Only the final result comes back into the chat.

NitroStack — Product Hunt top post of the day

01

What NitroStack is

NitroStack is a TypeScript framework for Model Context Protocol (MCP) servers. MCP is the protocol agents use to call tools. You describe those tools in code. The server speaks MCP. The model calls the tools.

The path the docs describe is short. Create a server with the SDK, test tool calls in NitroStudio, then deploy to NitroCloud. Cloud hosting includes push-to-deploy, scale-to-zero, custom domains, and TLS. This page is about one opt-in piece of that server: Code Mode, shipped in @nitrostack/core and @nitrostack/cli 1.1.

Read this if you are building or already running an MCP server and the tool list is large enough to crowd the prompt. After this page you should know when to turn Code Mode on, the three tools the model sees, and what the sandbox will not do.

02

What Code Mode changes

Normal MCP works like this. The server answers tools/list with every tool. The model calls one tool, reads the result in the chat, thinks, and calls the next tool.

Code Mode uses the same protocol and a different shape. The model does not see the full catalog. It gets a small set of meta-tools, writes a short script, and that script calls the real tools next to the server. Only the final return value comes back to the model.

NitroStack did not invent this. Cloudflare named it Code Mode. Anthropic published the same idea as code execution with MCP. NitroStack puts it on your server, as a transform, so a normal @Tool controller stays as it is.

03

Why a full catalog breaks

Three things get worse once a server exposes dozens of tools.

  1. The prompt fills up before the user types. Every schema sits in context. Cloudflare has published that their full API, exposed as native tools, is about 1.17 million tokens. Anthropic's engineering post describes a drop from about 150,000 tokens to about 2,000 when they stopped putting the whole catalog in context. Those are their measurements, not a NitroStack benchmark of your server.
  2. Each step is another model turn. Fetch rows, filter them, then aggregate. The intermediate data comes back into the chat every time.
  3. Models have read more real code than tool-call JSON. Cloudflare's line is that LLMs are better at writing code to call MCP than at calling MCP directly. A large flat catalog makes the wrong tool more likely.

Splitting one product into many small servers, or adding search-then-call, helps the model find a tool. It does not remove the hop for every step. Code Mode is the version that runs those steps in one script.

04

What the model sees

ToolJob
searchFind tools by keyword or regular expression.
get_schemaReturn the parameter schema for the tools you name.
executeRun a JavaScript string in the sandbox.

Inside execute, the script calls a real tool with await callTool(name, args). That call hits your controller in the same process. NitroStack marks the async context so the internal call skips the transform pipeline and does not call itself again.

The loop is the whole trick.

  1. 1The model receives the three meta-tools, not the full catalog.
  2. 2search answers “what exists for invoices?”
  3. 3get_schema returns how to call the tools it found.
  4. 4execute runs the script in QuickJS.
  5. 5The script calls your tools locally. Intermediate data stays in the worker.
  6. 6The model receives only the return value.

The documented runtime is JavaScript (ES2020) on QuickJS compiled to WebAssembly, in a pre-warmed Node worker pool. The default pool size is 4. The caps we document with the transform are a 128 MB heap, a 15 second timeout, and 50 tool calls per script. Destructive tools stay blocked unless you set allowDestructive: true. You can change those numbers when you construct the transform. They are configuration, not a measured throughput claim.

05

Turn it on

You need @nitrostack/core and @nitrostack/cli at 1.1.0 or later. Code Mode stays off until you pass it in transforms. AppModule below is your existing module. This snippet shows the transform, not a new controller.

server.ts
import { McpApp, Module, CodeModeTransform } from '@nitrostack/core';

@McpApp({
  module: AppModule,
  server: { name: 'your-service', version: '1.1.0' },
  transforms: [
    new CodeModeTransform({
      workerPoolSize: 4,
      memoryLimitMb: 128,
      timeoutMs: 15000,
      maxToolCalls: 50,
      allowDestructive: false,
    }),
  ],
})
@Module({
  name: 'app',
  controllers: [], // your existing controllers
})
export class AppModule {}

Or start from the CLI preset:

terminal
npx @nitrostack/cli@1.1.0 init my-code-server --preset code-mode

The template docs are at docs.nitrostack.ai/templates/code-mode. The 1.1 write-up is Introducing Code Mode and MCP Tool Transforms. If you leave transforms unset, a server on stdio, SSE, or stateless HTTP keeps the previous behavior.

06

A script the model can run

This is the shape of a script inside execute. It assumes two tools that your server may not have. It is an example of the call pattern, not a tool NitroStack ships.

execute.js
const users = await callTool('get_customers', { limit: 1000 });
const active = users.filter((user) => user.status === 'active');
const analytics = await callTool('calculate_churn', {
  userIds: active.map((user) => user.id),
});

return {
  totalAnalyzed: active.length,
  highRiskCount: analytics.highRisk.length,
};

The filter runs in the worker. The model does not receive the thousand customer rows. It receives the object the script returns. If those tools return a different shape, the script has to match that shape. The transform does not invent fields for you.

07

How it compares

CloudflareAnthropicNitroStack
SandboxV8 isolate / Dynamic WorkerSandbox runtime, tools as filesQuickJS WASM in a Node worker
What the model writesTypeScript or JS against a generated SDKCode that imports tools from a virtual filesystemJS that calls callTool(name, args)
Meta-toolsOften search and executeCode execution over the filessearch, get_schema, execute
Where it sitsTheir Agents SDK, or their API MCP serverTheir code-execution patternYour MCP server, as a transform

Primary posts: Cloudflare, September 2025, Anthropic, November 2025, and Cloudflare's server-side follow-up.

08

When not to use it

Use BM25SearchTransform when you only need a smaller catalog. That transform exposes search_tools and call_tool. There is no sandbox and no script. The 1.1 post illustrates a 60-tool catalog at about 14,200 tokens against about 1,650 tokens for that search-and-call surface. Treat that as the illustration in the post. It is not a measurement of your catalog.

The same post says you can mark a tool alwaysVisible: true when the model should call it directly, with no search step. Use that for a tool the agent hits on almost every turn.

Code Mode is a poor default for a server with a few tools. The extra search and script steps cost a turn you did not need. If the catalog is small, leave the transform off.

09

Questions

What is Code Mode?

A way to use MCP where the model does not receive every tool. It gets a few meta-tools, writes a short script, and that script calls your real tools on the server. The model sees the script's return value, not every intermediate payload.

Do I have to rewrite my tools?

No. Code Mode is an opt-in transform in front of the tools you already wrote. Your @Tool controllers stay as they are. If you do not add transforms, the server keeps answering tools/list with the full catalog.

What does the model actually see?

Three synthetic tools: search, get_schema, and execute. search finds tools by keyword or regular expression. get_schema returns the parameter schema for the tools you name. execute runs a JavaScript string in the sandbox.

Where does the script run?

In QuickJS compiled to WebAssembly, inside a Node worker. It is not a Cloudflare Worker and not a container. The default pool is 4 workers. The documented caps are a 128 MB heap, a 15 second timeout, and 50 tool calls per script.

What stops a bad script?

The timeout kills a script that runs too long. The memory cap bounds the heap. maxToolCalls stops a script from calling tools without limit. Destructive tools stay blocked unless you set allowDestructive to true. Those are the controls NitroStack documents. They are not a general security review of your tools.

How is this different from Cloudflare and Anthropic?

Same pattern, different box. Cloudflare named Code Mode and runs it in a V8 isolate, often with search and execute against a generated SDK. Anthropic published code execution with MCP: tools as files, and the agent writes code that imports them. NitroStack runs JavaScript plus callTool(name, args) inside your MCP server.

Should I use Code Mode or BM25 search?

Use BM25SearchTransform when you only need a smaller catalog: search_tools and call_tool, with no script and no sandbox. Use Code Mode when the model should filter, loop, or combine tools before anything returns to the chat. A server with a handful of tools usually does not need either.

How do I try Code Mode?

Watch the walkthrough on this page, sign up for NitroStack Cloud to deploy a server, or star the repo on GitHub. The template is at docs.nitrostack.ai/templates/code-mode.

If the catalog is the problem, start here.

Watch the walkthrough, sign up for NitroStack Cloud to deploy, or star the repo.

Ask the team for a free POC.

Submit a request for a free POC with our team. Send it whether you need one or not. We will tell you if it fits.

Request a free POC