Skip to content

Deploying

From inside your toolkit folder:

Terminal window
trove mcp deploy # alias: trove deploy

trove mcp deploy does four things in order:

  1. Reads manifest.json from the project directory (--dir, default .). It must provide a name and a slug/id (or pass --name / --slug).
  2. Bundles server.ts with esbuild, targeting the Cloudflare Workers runtime. The output is a single self-contained script — no node_modules folder is uploaded.
  3. Registers/versions the toolkit through the deployServer(slug, name, manifest) GraphQL mutation. The first deploy creates the mcp_servers row; every deploy creates an immutable mcp_deployments record.
  4. Repoints the active deployment to the new bundle once it is built. Traffic switches on the next tools/call.
Bundling server.ts (esbuild)…
✓ deployed acme-orders (version 1.0.0, building)
acme-orders__lookup_order

The trailing line(s) show the namespaced tool name(s) (slug__toolName) that appear in tools/list on your Trove connection. Add --json for the machine-readable deployServer payload ({ id, version, status, tools }).


After a successful deploy, your tools are live in two places simultaneously:

Your tools appear automatically in your existing Trove MCP connection at https://api.ontrove.sh/mcp. They appear on the next tools/list (e.g. on reconnect or refresh), which then includes acme-orders__lookup_order alongside the core tools.

This is the mobile and web payoff: the user authorized Trove once; your tools just show up, on every device.

Each toolkit is also reachable at its own MCP endpoint:

https://api.ontrove.sh/mcp/s/<server-id>

The standalone endpoint exposes only that toolkit’s tools. Use it when you want to add a single toolkit to a specific MCP client without exposing your full Trove connection, or when you share a toolkit definition with someone else.

Authentication is the same Clerk OAuth 2.1 flow as the main endpoint — the user must still authorize Trove.


Every trove mcp deploy creates a new deployment record (mcp_deployments). The version field in manifest.json is recorded alongside the script name, the SDK version, the byte size, and the computed list of tools.

Deployments are immutable — the uploaded bundle is kept indefinitely (subject to retention limits). Switching between versions is a pointer update, not a re-upload.

List your toolkits and their active deployment:

Terminal window
trove mcp ls
# SLUG NAME STATUS VIS TOOLS ACTIVE
# acme-orders Acme Orders ACTIVE PRIVATE 1 1.2.0

Each toolkit’s full deployments history (with each deployment id) is available on the mcpServer(id) / mcpServers GraphQL query — trove mcp ls --json surfaces it for scripting.


Rollback switches the active deployment pointer to a previous deployment, instantly. Pass the toolkit and the target deployment id (from its deployments list):

Terminal window
trove mcp rollback acme-orders dep_def456
# ✓ rolled back Acme Orders → 1.1.0

No re-upload. No downtime. The old bundle is already on Trove’s infrastructure; the registry repoints to it (the rollbackServer mutation). Traffic switches on the next tools/call.


Explicit ctx.log(...) calls and framework events (tool call received, ctx.fetch result, ToolError thrown, unhandled exceptions) are captured per invocation. Secret values are redacted from all log output before storage — a log line that would contain a known secret value has the value replaced with [redacted].


Pause a toolkit to stop dispatching its tools without deleting it. Paused tools are removed from tools/list responses.

Terminal window
trove mcp pause acme-orders # → pauseServer
trove mcp resume acme-orders # → resumeServer

Pausing is instant. A paused toolkit’s deployments and secrets are retained.


Terminal window
trove mcp rm acme-orders
# ✓ deleted Acme Orders

Deletion is a soft delete — the toolkit is marked deleted and its tools disappear from tools/list immediately, while the deployment records and bundles are retained for a window before permanent removal. Secrets associated with the toolkit are removed from the vault.


A toolkit with the trove:ingest scope can run on a schedule and write back to the user’s knowledge base — effectively a cloud-side source. The proposed shape declares a schedule alongside the tools:

server.ts
export default defineMcpServer({
tools: [ /* ... */ ],
scopes: ["trove:ingest"],
// proposed — not in @ontrove/mcp today
onSchedule: {
cron: "0 8 * * *", // Every day at 08:00 UTC
async handler(ctx) {
const data = await fetchDailyReport(ctx);
// ctx.trove.ingest takes TroveIngestDoc documents; only `title` is required.
await ctx.trove?.ingest([{
title: `Daily Orders Report — ${new Date().toISOString().slice(0, 10)}`,
text: data.summary,
url: "https://orders.acme.com/reports/daily",
}]);
},
},
});

onSchedule plus ctx.trove.ingest runs on a schedule, calls a sanctioned API, and writes the results into your Trove knowledge base — covering use cases that today require a source synced on your Mac, as long as the upstream is a sanctioned API, not a browser-automated site.

The manifest.json for a toolkit with background mode must include "trove:ingest" in scopes and declare the relevant egress hosts.


Before shipping a toolkit to production:

  • manifest.json has a stable id — changing it later is a breaking change
  • All secrets in manifest.secrets have values set with trove secret set <toolkit> <name>
  • egress lists only the hosts you actually call
  • description on each tool is clear and action-oriented (Claude reads it to decide when to call the tool)
  • Read tools declare an output schema; write tools set mutating: true (and mirror scopes)
  • ToolError is thrown for expected error conditions with retryable set correctly
  • version in manifest.json is bumped from the previous deploy
  • trove mcp ls shows the toolkit ACTIVE (not ERROR) after deploy