Skip to content

Core Concepts

NimbleBrain’s core value is composing multiple MCP servers into a single, orchestrated workspace. Rather than connecting to one MCP server at a time, NimbleBrain aggregates tools from every installed app into a unified namespace, layers prompts to give the agent awareness of all available capabilities, and filters tool access per-task through skills.

┌──────────────────────────────────────────────────┐
│ ToolRegistry │
│ │
│ ┌─────────┐ ┌─────────┐ ┌──────────────────┐ │
│ │ App 1 │ │ App 2 │ │ App 3 (remote) │ │
│ │ (stdio) │ │ (stdio) │ │ (HTTP/SSE) │ │
│ │ 3 tools │ │ 5 tools │ │ 2 tools │ │
│ └─────────┘ └─────────┘ └──────────────────┘ │
│ │
│ Unified namespace: 10 app tools + system tools │
└──────────────────────────────────────────────────┘
│ │
▼ ▼
Skill filtering Agent Engine
(allowed-tools) (agentic loop)

Three mechanisms make this composable:

MechanismWhat it does
Tool aggregationThe ToolRegistry collects tools from every MCP source (local stdio, remote HTTP/SSE) and presents them as a flat namespace. The agent doesn’t know or care which server owns a tool.
Skill-scoped filteringEach skill declares allowed-tools glob patterns. When a skill matches, only tools matching those patterns (plus system tools) are visible to the agent. This scopes the agent’s capabilities per task.
4-layer prompt compositionSystem prompts are assembled from: (1) identity, (2) core context, (3) installed app metadata with trust scores, and (4) the matched skill’s prompt. Every layer adds awareness without the agent needing to discover it.

Every chat message triggers an agentic loop in the AgentEngine. The loop repeats until the model produces a response with no tool calls, or a limit is reached.

User message
┌─────────────────┐
│ Call Claude │◄─────────────────┐
│ (with tools) │ │
└────────┬────────┘ │
│ │
┌────┴────┐ │
│ Tool │ Yes │
│ calls? │──────► Execute tools │
│ │ in parallel ───┘
└────┬────┘
│ No
Return response

Each pass through the loop is one iteration. Defaults:

SettingDefaultHard cap
Max iterations2550
Max input tokens500,000
Max output tokens16,384
models.defaultanthropic:claude-sonnet-4-6

The engine stops for one of three reasons:

  • complete — the model responded without requesting any tool calls
  • max_iterations — the iteration limit was reached
  • token_budget — cumulative input tokens exceeded maxInputTokens. When this happens, tool calls from the current LLM response are dropped (not executed) to avoid running tools whose results can’t be processed.

All tool calls within a single iteration run in parallel via Promise.all().

Before the engine loop starts, the Runtime orchestrates the composition described above:

  1. Resolve or create a conversation
  2. Match the user message to a skill (triggers, then keywords)
  3. Compose the system prompt — 4-layer: identity + core skills + installed apps + matched skill
  4. Filter the unified tool namespace based on the matched skill’s allowed-tools globs
  5. Run the AgentEngine loop against the composed tool set
  6. Persist the conversation (JSONL or in-memory)

A bundle is an MCP server package installed into NimbleBrain. Bundles follow the MCPB format — each has a manifest.json declaring how to start the server, what tools it provides, and optional UI metadata.

Bundles are installed per workspace and tracked in workspace.json (not nimblebrain.json — bundle entries placed there are stripped on load). They come from:

SourceHow it works
RegistryDownloaded from the mpak registry by scoped name (e.g. @nimblebraininc/ipinfo). Managed across the org via manage_apps.
Connector catalogRemote MCP connectors installed point-and-click from the in-app catalog, or via manage_connectors.
Local pathA bundle directory on the filesystem, for local development.

Each bundle process goes through these states:

starting ──► running ──► crashed ──► dead
│ ▲
└──► stopped ─────────┘
StateMeaning
startingProcess is spawning
runningHealthy and serving tools
crashedProcess exited unexpectedly (will attempt recovery)
deadRepeated crashes, not restarting
stoppedManually stopped via API or CLI

NimbleBrain does not install any MCP bundles by default. Platform capabilities (home, conversations, files, settings, usage, automations) are built in as inline tool sources. Install bundles from the mpak registry, a local path, or a remote URL to give the agent domain-specific tools.

{
"name": "@nimblebraininc/postgres",
"env": { "DATABASE_URL": "postgres://localhost/mydb" }
}
FieldDescription
envEnvironment variables passed to the bundle process
trustScoreMTF trust score (0–100) from the mpak registry
uiUI metadata: name, icon, and placement declarations

Skills are Markdown files with YAML frontmatter. They control what the agent knows and what tools it can use for a given message.

research.md
---
name: research
description: >
Deep research on a topic — search the web, gather sources, and synthesize a
report. Use when the user asks to research, investigate, or analyze a topic.
allowed-tools: websearch__search nb__search
metadata:
nimblebrain:
loading-strategy: dynamic
priority: 50
triggers:
- "research this"
- "deep dive"
---
You are a research agent. Search the web, gather multiple sources,
and synthesize findings into a structured report.
loading-strategyPriorityBehavior
always0–10 (core) or 11–99Always composed into the system prompt — identity, voice, durable rules.
dynamic11–99Loaded on demand, via the activation signals below.

A dynamic skill enters context through any of:

  • Description — its name + description sit in a catalog; the model activates the relevant one (so the description must say what it does and when to use it).
  • Tool-affinity — auto-activates when a tool in the active set matches one of its tool-affinity globs.
  • Triggers — auto-activates on an exact phrase, for deterministic must-fire cases.
User: "research this topic and analyze the sources"
trigger "research this" ── match! ──► research skill activates

An activated skill injects its markdown body into the system prompt; allowed-tools (if set) scopes which tools it may call.

Skills are loaded from three locations (in order):

  1. Built-insrc/skills/builtin/ (shipped with the package)
  2. Global~/.nimblebrain/skills/
  3. Config — directories listed in the skillDirs config option

Tools come from two places: MCP bundles and built-in system tools.

Every NimbleBrain instance has these nb__* tools available:

ToolDescription
nb__searchSearch installed tools (scope: "tools") or the mpak registry (scope: "registry")
nb__statusPlatform status; scope: "bundles" for per-app health, scope: "skills" for loaded skills, scope: "config" for model and limits
nb__delegateSpawn a child agent for sub-tasks (multi-agent delegation)
nb__read_resourceRead an MCP resource by URI
manage_connectorsList the connector catalog, install/disconnect remote MCP connectors per workspace or per user
manage_appsOrg-level management of installed registry apps: list, check for updates, upgrade
manage_workspacesCreate and manage workspaces
manage_membersManage workspace membership
manage_usersManage users (when a managed identity adapter is configured)

App-platform capabilities are exposed through prefixed tool families: conversations__*, files__*, automations__*, skills__*, usage__report, instructions__write_instructions, and compose__effective_context.

NimbleBrain uses tiered tool surfacing to keep the LLM’s tool list manageable:

ConditionWhat the LLM sees
Total tools ≤ 30All tools surfaced directly
Total tools > 30, no skill matchedOnly nb__* system tools. Others available via nb__search (scope: "tools").
Skill matched with allowed-toolsTools matching the globs + system tools. Others via nb__search.

The threshold is configurable via maxDirectTools (default: 30).

The nb__delegate tool spawns a child AgentEngine run with a scoped system prompt and filtered tool set. Named agent profiles are configured in workspace.json:

{
"agents": {
"researcher": {
"description": "Deep research agent",
"systemPrompt": "You are a research agent...",
"tools": ["websearch__*"],
"maxIterations": 8,
"model": "reasoning"
}
}
}

The child agent’s iteration budget is capped at min(child.maxIterations, parent.remaining - 1). Multiple delegations in the same turn run concurrently.

Conversations persist across messages so the agent remembers context.

Conversations are workspace-owned. Every turn is written to a per-conversation JSONL file under the workspace it ran in:

~/.nimblebrain/workspaces/<wsId>/conversations/<ownerId>/<convId>.jsonl

The owner (ownerId) is the authorization principal — only they can read or resume the conversation — while the workspace (wsId) is where it is stored. Persistence is automatic; there is nothing to configure.

Each conversation is a single .jsonl file:

{"id":"conv_abc123","createdAt":"2025-03-15T10:30:00Z"}
{"role":"user","content":"What files are in my home directory?","ts":"..."}
{"role":"assistant","content":"Let me check...","ts":"...","toolCalls":[...]}

Line 1 is metadata (ID, creation timestamp). Lines 2+ are StoredMessage objects with role, content, timestamp, and optional tool call records.

To continue an existing conversation, open it from the Conversations sidebar in the web UI. Through the API, pass conversationId in the chat request body.

NimbleBrain is a full MCP Apps host, implementing the ext-apps specification. MCP Apps are interactive UI applications — built with HTML/JavaScript — that render directly inside the host as sandboxed iframes.

Unlike traditional web apps, MCP Apps:

  • Live inside the conversation — no tab-switching, context stays together
  • Call tools bidirectionally — apps invoke MCP tools and receive pushed results from the agent
  • Inherit the host’s theme — CSS variables are injected automatically
  • Run in a security sandbox — no access to the parent page, cookies, or other apps

Any MCP bundle that declares UI resources and placements becomes an MCP App. See MCP Apps for the full concept and MCP App Bridge for the implementation protocol.

NimbleBrain exposes a /mcp endpoint that turns the platform into a Streamable HTTP MCP server. External MCP clients — Claude Code, Open WebUI, or another NimbleBrain instance — can connect through a single endpoint. Each request names its workspace via the X-Workspace-Id header (validated against your membership): /mcp serves that one workspace’s tools plus your identity tools (conversations, files, automations), and refuses tools in any other workspace. A request with no X-Workspace-Id is identity-only.

This means NimbleBrain is both an MCP client (connecting to installed bundles) and an MCP server (exposing composed tools to external hosts). See MCP Endpoint Reference for configuration and usage.