Skip to content

App SDK Contracts

Audience: third-party marketplace artifact authors. Everything here is re-exported by @mnemose/app-sdk under the semver promise below.

Semver promise

  • Schema fields are additive-only within a minor release: new optional fields, new artifact kinds (kind values), and new named exports may land in minors without notice.
  • Removing an export, removing/narrowing a field, or making an optional field required requires a major version bump and a migration note.
  • The exported surface is pinned by a snapshot test (test/contract.test.ts); any snapshot diff must be called out in the PR.

Artifact kinds

Every marketplace artifact carries a kind discriminator (MarketplaceArtifactKind). Absent kinds default to "app" for backwards compatibility. Authoring guide stubs per kind:

KindWhat it installsStatus
appGateway module, console routes, jobsStable — validate with AppManifestSchema
provider-configLLM provider entry into llm_provider_configStub — lands with wave M-3
harnessAgent/model configuration preset (importable JSON, optional skills)Stub — wave M-3
mcp-toolMCP server registration via McpToolSpecSchema + installMcpToolStable (ADR 0014)
skill / skillsetBehavior packs mounted at .agents/skills in the agent sandboxStub — wave M-3
cloud-providerCloud-adapter implementation + installer provisioning stepStub — wave M-4
compute-providerIsolated compute backend (MicroVM, Dynamic Workers) via contributes.backendKindsStable (ADR 0014)

All kinds share one identity envelope today: author against AppManifestSchema, set kind, and the catalog/loader dispatch on it.

Port interfaces

Apps interact with cloud infrastructure only through ports from @mnemose/cloud-adapters/ports (re-exported as types): EventBus, BlobStorage, Secrets, Kms, Scheduler, IaaS, IdentityProvider, Workflow, CloudCredentials. Never import adapter implementations directly; provisioning injects the tenant-bound implementations.

CQRS conventions

Commands and events flow over the platform bus per docs/architecture.md:

  • Commands are imperative requests (do-thing), handled exactly once.
  • Events are past-tense facts (thing-done) emitted on the EventBus port; apps declare emitted/consumed event names in the manifest’s events array.
  • New topics require registration only — core command/event topics are not modified (see ADR 0012 “functional waterline”).

Validation

Use the environment-agnostic helpers (safeParseAppManifest, parseAppManifest, validateAppManifest, parseCatalogRegistry) — they run on Node.js, Workers, and browsers. Gate CI on schema validation before publishing any artifact.

Lifecycle commands and events

The full lifecycle command/event surface is re-exported from @mnemose/app-sdk (single source of truth: @mnemose/domain, mirrored by @mnemose/marketplace):

  • Commands: InstallApp, UninstallApp, EnableApp, DisableApp, UpdateAppConfig (union: AppLifecycleCommandSchema).
  • Events: AppInstalled, AppUninstalled, AppEnabled, AppDisabled, AppConfigUpdated (union: AppLifecycleEventSchema).

Third-party code should parse outgoing lifecycle payloads with AppLifecycleCommandSchema and validate incoming lifecycle facts with AppLifecycleEventSchema rather than re-declaring these shapes. The UpdateAppConfig command carries a full replacement config object plus an optional semver version bump; it emits AppConfigUpdated once handled on the platform command subscriber.

Compute providers (ADR 0014)

Compute-provider apps install isolated compute backends. The manifest’s contributes.backendKinds array declares one or more backend kinds:

{
"kind": "compute-provider",
"contributes": {
"backendKinds": [{
"kind": "cf-sandbox",
"schemaModule": "./schema.js",
"adapterFactoryModule": "./adapter.js",
"adapterFactoryExport": "createCfSandboxAdapter"
}]
}
}

At boot, the gateway module calls registerBackendKind() (to add the Zod schema to the open SandboxComputeBackendSchema union) and registerAdapterFactory() (to register the adapter factory in the ExecutionAdapterRegistry). SandboxDO resolves the adapter by backendKind at dispatch time.

Reference implementations in app-store/apps/:

  • cf-sandbox-provider — Cloudflare Sandbox SDK (Containers + DOs)
  • dynamic-workers-provider — Dynamic Workers (isolated V8)
  • microvm-provider — Remote MicroVM (libkrun, microsandbox)

MCP tool artifacts (ADR 0014)

MCP tool artifacts register MCP servers discoverable by the ToolRegistry. Validate with McpToolSpecSchema and install via installMcpTool():

import { McpToolSpecSchema, parseMcpToolSpec } from "@mnemose/app-sdk";
const spec = parseMcpToolSpec({
specVersion: "1",
id: "my-mcp-server",
name: "My MCP Server",
version: "1.0.0",
transport: "http",
endpoint: "https://my-server.example.com/mcp",
tools: ["my-tool.search", "my-tool.execute"],
});

Service bindings (ADR 0014)

Apps can declare service bindings via contributes.serviceBindings — HTTP, MCP, or GraphQL services that bind into sandboxes. The dynamic-workers-provider app uses this to ship its search-and-execute SDK as an MCP service.