PluginManifest. This page is a distilled reference to the manifest
surface — enough to author from. For the full field-by-field catalog with every validation
rule, read the SDK’s docs/manifest-reference.md in the codebase. For a guided build, see
Build a plugin.
PluginManifest
The top-level object returned bybuild_manifest(ctx):
Construction-time invariants (a violation fails the build): tool, capability, and
resource names are unique; every
ToolSpec.capability resolves to a capability on the same
manifest; write-class tools live under an approval_required capability and declare
idempotent explicitly.
Identity
PluginIdentity — name (slug matching ^[a-z][a-z0-9_-]*$, equal to the entry-point
name), version, display_name, description, owner, optional homepage.
Auth
PluginAuth.type is one of the AuthType shapes — describing the shape of credentials,
never values:
Credentials are resolved at runtime through the
SecretsProvider on PluginContext; the
manifest only declares what’s required. Prefer the canonical auth_shape over the legacy
auth.type for new plugins — onboarding, health sweepers, and connection setup all read it.
Capabilities
CapabilityMetadata is the routing surface. A capability groups tools and tells the router
when to pick them:
Role floor
minimum_role (None by default) is a hard floor. None lets any actor on the
tenant-reach ladder invoke; TENANT_ADMIN restricts to tenant/super admins (use for
tenant-shared credentials, financial finalization, bulk/admin operations, irreversible
deletes); SUPER_ADMIN restricts to the platform operator. Tenants can tighten further but
cannot loosen below the floor.
Tools
ToolSpec binds a callable to the manifest:
READ tools are idempotent by definition. WRITE-class tools must declare
idempotent
explicitly — False for create-* tools that mint a new resource each call, True for
update/delete/set-state tools whose post-condition depends only on the input.
Connections and profiles
connection_shapesdeclares who owns a connection record: user-owned, tenant-owned, either, a layered user-plus-tenant prerequisite, or none.profilesdeclares deployment variants (commercial/gov cloud, production/sandbox). Hosts project one setup target per profile;config_keysare safe to surface as hints and never carry secret values.
Query-profile and pushdown contract
Every read-capable plugin (one or moreREAD tools) must declare a query profile —
enforced fleet-wide by the check_query_profile gate. Satisfy it one of three ways, in
order of preference:
1
Pushdown
For providers with a native query language, declare a
DatasetPushdown so the host
pushes a plan prefix (filter / project / sort / limit and declared aggregates) down to
the source instead of fetching everything and computing host-side.2
Bounded fetch
Expose a dataset the host can resolve to completeness — an explicit
datasets entry, or
a READ tool returning a single list of flat scalar-field rows, which the SDK
auto-adapts into a queryable dataset.3
Recorded opt-out
When the read surface is genuinely non-tabular (relevance search, ops snapshots), record
a rationale in
[tool.aperium.query_surface]. An empty rationale or a stale key fails
the gate.DatasetSpec validates the pairing at build time: a dynamic dataset (no fixed schema)
declaring pushdown must supply a schema_probe; a fixed-schema dataset must not. An
ordinary refusal degrades to fetch-then-compute; a PlanPrefixRetryError preserves terminal
model remediation without that fallback.
MCP exposure
Most first-party plugins are direct-call and leavemcp unset. Two opt-in surfaces exist:
mcp(McpConfig) — expose this plugin’s tools as an MCP server (STDIO,SSE, orHTTP;portrequired forHTTP/SSE). Opt in only for MCP-adapter examples or plugins deliberately exposed to non-Aperium MCP clients.remote_mcp(RemoteMcpToolsetSpec) — the inverse: the plugin’s tools come from a remote MCP server, introspected at runtime. The host provisions a per-tenant managed server row from a credential-rendered URL template.
JSON wire shape
PluginManifest.model_dump_json() emits a metadata view for external tooling: identity,
auth type, and capabilities dump in full; input/output/config schemas emit as JSON Schema;
handler, resource, and health-check callables are excluded — rehydrating executable code
from JSON is intentionally unsupported.