Skip to content

Manifest Reference

The upjack manifest is the extension block that transforms a standard MCPB package into a NimbleBrain Upjack app. It lives inside manifest.json at _meta["ai.nimblebrain/upjack"].

{
"name": "@nimblebrain/crm",
"version": "0.1.0",
"description": "Lightweight CRM for founder-led sales",
"mcp_config": { ... },
"_meta": {
"ai.nimblebrain/upjack": {
"upjack_version": "0.1",
"namespace": "apps/crm",
"entities": [ ... ],
"skills": [ ... ]
}
}
}

The outer manifest.json follows the standard MCPB spec. Non-NimbleBrain tools ignore _meta and install the package as a regular MCP server. The NimbleBrain platform reads the upjack extension and performs additional installation steps (workspace scaffolding, entity registration, skill installation).

FieldTypeRequiredDefaultDescription
upjack_versionstringYesFramework version. Const "0.1" for this spec.
namespacestringYesInstall path in tenant workspace. Pattern: ^apps/[a-z][a-z0-9-]*$
displayobjectNoHuman-readable display metadata.
entitiesarrayYesEntity definitions. minItems: 1.
skillsarrayNo[]Skill references.
bundlesobjectNo{}Bundle (MCPB package) dependencies, keyed by alias.
required_toolsarrayNo[]Platform tools the app requires.
required_connectionsarrayNo[]OAuth/API connections the app requires.
schedulesarrayNo[]Cron-based scheduled skill invocations.
hooksarrayNo[]Event-driven skill triggers.
viewsarrayNo[]Named entity views (filtered/sorted perspectives).
contextstringNoPath to a Markdown context file within the package.
seedobjectNoInitial data seeding configuration.
serverobject or nullNoCustom MCP server configuration. null for pure declarative apps. Note: this field lives in the outer MCPB manifest, not in the upjack extension block.
{
"type": "string",
"const": "0.1"
}

Identifies which version of the Upjack framework this manifest targets. Installers check this field to determine compatibility. This spec defines version "0.1".

{
"type": "string",
"pattern": "^apps/[a-z][a-z0-9-]*$"
}

The directory path within the tenant workspace where the app is installed. All entity data, skills, views, and lock files live under this namespace.

Examples: apps/crm, apps/research-tracker, apps/content-pipeline

{
"type": "object",
"properties": {
"name": { "type": "string", "maxLength": 64 },
"icon": { "type": "string", "maxLength": 8 },
"category": {
"type": "string",
"enum": [
"sales", "marketing", "operations", "research",
"finance", "hr", "engineering", "support", "custom"
]
}
}
}
Sub-fieldTypeRequiredDescription
namestringNoHuman-readable app name. Max 64 characters.
iconstringNoEmoji or short icon string. Max 8 characters.
categorystringNoApp category for organization and discovery.
{
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/entity_definition" }
}

Every Upjack app must define at least one entity. Each entity definition describes the data type, its schema, ID prefix, and storage behavior.

Sub-fieldTypeRequiredDefaultDescription
namestringYesEntity type name. Pattern: ^[a-z][a-z0-9_]*$
pluralstringNo{name}sPlural form, used in storage paths and display.
schemastringYesRelative path to JSON Schema file within the package.
prefixstringYesID prefix for ULID generation. Pattern: ^[a-z]{2,4}$
storagestringNodata/{plural}/Relative storage path within the namespace.
indexbooleanNotrueWhether to index this entity for full-text search.
singletonbooleanNofalseWhether only one instance of this entity can exist.
{
"name": "lead",
"plural": "leads",
"schema": "schemas/lead.schema.json",
"prefix": "ld",
"storage": "data/leads/",
"index": true,
"singleton": false
}

The prefix is prepended to the ULID to form the entity ID: ld_01HZ3QKBN9YWVJ0RPFA7MT8C5X. Prefixes must be unique within an app.

{
"type": "array",
"items": { "oneOf": [
{ "$ref": "#/$defs/skill_mpak" },
{ "$ref": "#/$defs/skill_github" },
{ "$ref": "#/$defs/skill_bundled" }
]}
}

Skills can be sourced from three locations:

A skill published as an mpak package.

Sub-fieldTypeRequiredDescription
sourcestringYesConst "mpak"
namestringYesScoped package name. Pattern: ^@[a-z0-9-]+/[a-z0-9-]+$
versionstringYesSemver range (e.g., "^1.0.0", ">=2.0.0 <3.0.0").
integritystringNoSHA-256 hash for verification. Pattern: ^sha256-[a-f0-9]{64}$
{
"source": "mpak",
"name": "@nimblebrain/lead-qualification",
"version": "^1.0.0",
"integrity": "sha256-abc123..."
}

A skill file hosted in a GitHub repository.

Sub-fieldTypeRequiredDescription
sourcestringYesConst "github"
repostringYesGitHub repo in owner/repo format.
pathstringYesPath to the skill file within the repo.
refstringNoGit ref (branch, tag, or commit SHA). Defaults to default branch.
{
"source": "github",
"repo": "NimbleBrainInc/skills",
"path": "sales/lead-qualification.md",
"ref": "main"
}

A skill file included directly in the MCPB package.

Sub-fieldTypeRequiredDescription
sourcestringYesConst "bundled"
pathstringYesRelative path to the SKILL.md file within the package.
{
"source": "bundled",
"path": "skills/deal-review.md"
}
{
"type": "object",
"patternProperties": {
"^[a-z][a-z0-9-]*$": { "$ref": "#/$defs/bundle_dependency" }
},
"additionalProperties": false
}

Bundle dependencies are MCPB packages that provide MCP tools the app needs. They are keyed by a logical alias — skills reference tools via the alias (e.g., email__send_email), not the package name. This enables swappability.

Sub-fieldTypeRequiredDefaultDescription
descriptionstringYesHuman-readable purpose of this dependency.
requiredbooleanNotrueWhether the app can function without this bundle.
defaultobjectYesDefault package (name + version).
alternativesarrayNo[]Alternative packages that satisfy the same contract.
tools_usedarrayYesTool names the app invokes. minItems: 1. This is the compatibility contract.
config_mapobjectNo{}Configuration keys the bundle expects.
{
"email": {
"description": "Email sending capability",
"required": true,
"default": {
"name": "@nimblebrain/aws-ses",
"version": "^1.0.0"
},
"alternatives": [
{ "name": "@nimblebrain/sendgrid", "version": "^1.0.0" }
],
"tools_used": ["send_email", "list_templates"],
"config_map": {
"from_address": "Default sender email address"
}
}
}

The tools_used array is the compatibility contract. During installation, the installer verifies that the chosen package exposes all listed tools. If a tool is missing, installation fails with an explicit error.

{
"type": "array",
"items": { "type": "string" }
}

Platform tools the app requires. These are always-available tools provided by the NimbleBrain platform (not bundle dependencies).

["platform:web_search", "platform:file_read", "platform:git_commit"]
{
"type": "array",
"items": {
"type": "object",
"properties": {
"type": { "type": "string" },
"required": { "type": "boolean", "default": true },
"purpose": { "type": "string" }
},
"required": ["type"]
}
}

OAuth or API connections the user must configure before the app is fully functional.

[
{
"type": "google-workspace",
"required": true,
"purpose": "Access Google Calendar for meeting scheduling"
},
{
"type": "linkedin",
"required": false,
"purpose": "Enrich lead profiles with LinkedIn data"
}
]
{
"type": "array",
"items": { "$ref": "#/$defs/schedule" }
}
Sub-fieldTypeRequiredDefaultDescription
namestringYesSchedule identifier. Pattern: ^[a-z][a-z0-9-]*$
cronstringYes5-field cron expression (minute hour day-of-month month day-of-week).
skillstringYesName of the skill to invoke.
descriptionstringNoHuman-readable description.
enabled_by_defaultbooleanNotrueWhether this schedule is active on install.
{
"name": "weekly-pipeline-review",
"cron": "0 9 * * 1",
"skill": "pipeline-review",
"description": "Review deal pipeline every Monday at 9am",
"enabled_by_default": true
}
{
"type": "array",
"items": { "$ref": "#/$defs/hook" }
}
Sub-fieldTypeRequiredDescription
eventstringYesLifecycle event. Enum: entity.created, entity.updated, entity.deleted, entity.status_changed, app.installed, app.updated
entitystringNoFilter to a specific entity type. Only applies to entity.* events.
conditionstringNoJSONPath expression that must evaluate to true.
skillstringYesName of the skill to invoke when the hook fires.
{
"event": "entity.created",
"entity": "lead",
"skill": "lead-qualification"
},
{
"event": "entity.status_changed",
"entity": "deal",
"condition": "$.status == 'active'",
"skill": "deal-review"
}
{
"type": "array",
"items": { "$ref": "#/$defs/view" }
}
Sub-fieldTypeRequiredDefaultDescription
namestringYesView identifier.
entitystringYesEntity type this view applies to.
descriptionstringNoHuman-readable description.
filterstringNoJSONPath filter expression.
sortstringNoSort expression (field name, prefix with - for descending).
storagestringNoviews/Relative storage path for materialized view data.
{
"name": "open-deals",
"entity": "deal",
"description": "All active deals sorted by expected close date",
"filter": "$.status == 'active'",
"sort": "expected_close",
"storage": "views/"
}
{
"type": "string"
}

Path to a Markdown file within the package that provides additional context for the agent. This file is loaded when the app is active and gives the agent background knowledge about the domain, business rules, or organizational conventions.

"context": "context/crm-overview.md"
{
"type": "object",
"properties": {
"data": { "type": "string" },
"run_on_install": { "type": "boolean", "default": true }
}
}
Sub-fieldTypeRequiredDefaultDescription
datastringYesPath to seed data directory or file within the package.
run_on_installbooleanNotrueWhether to seed data automatically on install.
{
"data": "seed/",
"run_on_install": true
}

The seed directory contains JSON files organized by entity type. The installer creates entities from these files during installation.

See the CRM example manifest for a full working CRM manifest. Here is a summary of what it declares:

  1. Five entity types with typed ID prefixes: contacts (ct_), companies (co_), deals (dl_), pipeline (pl_, singleton), and activities (act_).
  2. Four skills: three bundled in the package, one from mpak.
  3. Three bundle dependencies: email (required, with alternatives), enrichment (optional), and PDF generation (optional).
  4. Two required connections: email (required) and calendar (optional).
  5. Three schedules: daily pipeline review, weekly stale deal alert, nightly lead scoring.
  6. Two hooks: auto-score new contacts, trigger forecast on closed deals.
  7. Three views: hot leads, stale deals, weekly pipeline.
  8. Seed data loaded on install.
  9. Custom MCP server via create_server() (Tier 2 app).

The manifest demonstrates every major Upjack feature: entities with schemas, bundled and external skills, alias-based bundle dependencies with alternatives, hooks, schedules, views, seed data, and server configuration.