manifest.json Reference
Every toolkit must include a manifest.json file at the root of its project folder. The manifest is the policy surface: it declares what your toolkit is, what secrets it needs, which external hosts it is allowed to reach, and which Trove capabilities it requests. trove deploy validates the manifest before uploading anything.
Full example
Section titled “Full example”{ "id": "acme-orders", "name": "Acme Orders", "description": "Query Acme order status and line items.", "version": "1.0.0", "sdk": "@ontrove/mcp@^1", "secrets": ["ORDERS_API_TOKEN"], "egress": ["orders.acme.com"], "scopes": [], "visibility": "private"}Fields
Section titled “Fields”| Type | string |
| Required | Yes |
| Pattern | ^[a-z0-9-]+$ (lowercase, digits, hyphens) |
A stable identifier for the toolkit, unique within your account. The id becomes the namespace prefix for all your tools: a toolkit with "id": "acme-orders" exposes its tools as acme-orders__<tool_name>.
The id also appears in the standalone endpoint URL: https://api.ontrove.sh/mcp/s/<id>.
| Type | string |
| Required | Yes |
A human-readable display name for the toolkit. Shown in the Trove web app, in trove deploy output, and in future sharing/discovery surfaces. Keep it short and descriptive — "Acme Orders", not "Acme Internal Order Status Lookup System v2".
description
Section titled “description”| Type | string |
| Required | No |
A one-sentence description of what the toolkit does. Shown in the Trove web app and used as the MCP server description when the standalone endpoint is queried. Not directly model-visible — model-visible descriptions live on individual tools.
| Type | string — emoji or URL |
| Required | No |
A single emoji or an HTTPS URL to a square PNG/SVG (recommended: 64×64 or 128×128). Shown alongside the toolkit name in the Trove web app.
version
Section titled “version”| Type | string — semver |
| Required | Yes |
The toolkit version, following semver. trove deploy records this in the deployment registry and surfaces it in rollback history. Increment this on each meaningful deploy so you can distinguish versions in trove logs and rollback.
| Type | string — npm package specifier |
| Required | Yes |
The @ontrove/mcp version range your toolkit is authored against. Used by the platform to validate compatibility and pin the correct runtime wrapper at deploy time.
"sdk": "@ontrove/mcp@^1"Always use a caret range (^1) rather than an exact pin so you receive patch-level fixes automatically.
secrets
Section titled “secrets”| Type | string[] |
| Required | No (default: []) |
Names of secrets your toolkit will access via ctx.secret(name). Names are declared here; values are stored separately with trove secret set. Any name not listed here is inaccessible at runtime — ctx.secret("UNDECLARED_NAME") throws.
"secrets": ["ORDERS_API_TOKEN", "METRICS_READ_KEY"]Declare the minimal set your toolkit actually needs. Each secret name must match what you pass to ctx.secret(...) exactly (case-sensitive).
See Secrets and Auth for the vault model and how to set values.
egress
Section titled “egress”| Type | string[] — array of hostnames |
| Required | No (default: [], deny all) |
Outbound HTTP is denied by default. List every public-internet hostname your toolkit needs to reach. Requests to any host not in this list are blocked by Trove at the network level — including redirects that resolve to an unlisted host.
"egress": ["orders.acme.com", "metrics.acme.com"]egress is for public-internet hosts only. Even when listed, a host that resolves to localhost, a private/LAN range, or a reserved address (e.g. 127.0.0.1, 10.0.0.0/8, 192.168.0.0/16, the cloud-metadata IP 169.254.169.254) is blocked — an SSRF defense, see the security model. A toolkit runs in Trove’s cloud and cannot reach your own machine (no localhost, LAN, local files, or Mac apps); for local/private data, use a source (synced by the Mac app) or a local MCP server instead. (orders.acme.com above is a public-internet SaaS host your company exposes — the allowlist accepts it because it resolves to a public address.)
Entries are matched on the exact hostname (no port, no path, no wildcard in V1). If your API uses subdomains, list the specific subdomain you need.
scopes
Section titled “scopes”| Type | string[] |
| Required | No (default: []) |
Trove capabilities your toolkit requests. Absent a scope, the corresponding ctx.trove method is unavailable.
| Scope | What it unlocks |
|---|---|
"trove:search" | ctx.trove.search(...) and ctx.trove.getDocument(...) — read access to the calling user’s knowledge base |
"trove:ingest" | ctx.trove.ingest(...) — write documents into the calling user’s knowledge base |
"scopes": ["trove:search"]A toolkit with no scopes cannot read or write the user’s knowledge base — it can only call external APIs via ctx.fetch. This is the correct default for most toolkits.
visibility
Section titled “visibility”| Type | "private" | "shared" |
| Required | No (default: "private") |
Controls who can see and use the toolkit.
| Value | Meaning |
|---|---|
"private" | Only you can see and use this toolkit. |
"shared" | The toolkit definition (manifest + bundle) can be shared with others, who deploy their own copy with their own secrets. They run an isolated instance; you do not share your secrets or data. |
Validation at deploy time
Section titled “Validation at deploy time”trove deploy validates the manifest before uploading:
- All required fields present and correctly typed
idmatches the allowed patternversionis valid semversdkreferences a known@ontrove/mcpversion range- Every name in
secretsthat has no matching value in the vault produces a warning (not an error — you can set secrets after deploying) - Every hostname in
egressis a valid DNS name
The typed McpServerDefinition export from your server.ts is also validated against the manifest — trove deploy catches mismatches (e.g., a tool calling ctx.secret("X") when "X" is not in manifest.secrets) before anything reaches the platform.
Minimal manifest
Section titled “Minimal manifest”A toolkit with no external calls and no secrets needs only four fields:
{ "id": "my-toolkit", "name": "My Toolkit", "version": "1.0.0", "sdk": "@ontrove/mcp@^1"}