OtaKit
OfficialEnables shipping over-the-air web bundle updates for Capacitor apps, including reading a Capacitor project, checking release safety, uploading builds, and publishing releases for the app.
OtaKit
Fully open-source, self-hostable over-the-air update framework for Capacitor apps. Release updates directly to your Capacitor app without app store reviews.
Try it for free: OtaKit.app
Self-hosting
OtaKit is hosted-first — the managed service at otakit.app runs everything for you — but the entire platform is in this repo and can run on your own infrastructure. The minimal stack is the console (a standard Next.js app), Postgres, and an S3-compatible bucket behind a CDN.
Full step-by-step guide: otakit.app/docs/self-host
Related MCP server: Capacitor MCP Server
How it works
Create an app in the dashboard.
Copy its
appIdintocapacitor.config.*.Build the app's web assets.
Run
otakit upload --releaseto upload the bundle and publish a release.The server writes the bundle and manifest to object storage behind the CDN.
On the next app launch or resume, the plugin fetches the manifest from the CDN, compares it to the current bundle, and downloads the new version if available.
If
notifyAppReady()is called within the timeout, the new bundle is confirmed. Otherwise the plugin rolls back to the previous bundle automatically.
MCP & Agent Skills
Ask Claude Code, Codex, or VS Code to ship an update and it reads your Capacitor project, checks whether the change is safe to send over the air, uploads the build, and stops for your approval before anything reaches a device.
One command from your project directory:
npx -y @otakit/cli@latest connectIt detects your client, signs you in if needed, and prints the console, organization, project, and
app it resolved — plus the exact file it will write — before writing anything. --dry-run shows
the plan and writes nothing.
Claude Code has a plugin that ships the server and the OtaKit Agent Skill together:
npx -y @otakit/cli@latest login
claude plugin marketplace add OtaKit/otakit
claude plugin install otakit@otakitSee the MCP and Agent Skills guide for Codex, Claude Code, remote OAuth, permissions, workflows, and self-hosting.
Core concepts
App — the Capacitor app identified by its
appIdBundle — one uploaded web build zip with a version, hash, and size
Release — a promotion of a bundle to a channel, which publishes a manifest to the CDN
Channel — an optional release track such as
stagingRuntime version — an optional native compatibility lane configured in the plugin
Packages
packages/capacitor-plugin— the runtime that lives inside the mobile apppackages/cli— CLI for uploading bundles and creating releasespackages/mcp-core— shared MCP contracts, tool catalog, and server registrationpackages/site— public site, docs, contact, legal pagespackages/console— dashboard, API, auth, billing, and Prisma schemapackages/ingest— Cloudflare Worker for device event ingestiontinybird/— Tinybird datasources and pipes for event analytics
packages/
capacitor-plugin/ Capacitor OTA plugin
cli/ Upload + release CLI
mcp-core/ Shared MCP contracts and tool catalog
ingest/ Cloudflare Worker event ingest service
site/ Next.js public site + docs
console/ Next.js dashboard + API + auth + billing
tinybird/ Tinybird event analytics project
examples/
demo-app/ Demo Capacitor app wired to the local pluginPackage docs
Local development
Node.js 20.9+, pnpm 9+
The console app (
packages/console) requires Postgres and R2-compatible storage. Seepackages/console/.env.example.Device event analytics optionally require the ingest service (
packages/ingest) and a Tinybird workspace.See each package README for setup details.
pnpm install
pnpm dev # starts the console app in dev modeLicense
MIT
Available Tools
23 toolscheck_compatibilityCheck native update compatibilityARead-onlyIdempotentInspect
Compare local native dependencies with the current exact OtaKit release lane using the existing heuristic compatibility rules. Returns unknowns explicitly.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| channel | Yes | Named channel, or null for the base channel | |
| runtimeVersion | Yes | Native runtime lane, or null for the default runtime | |
| nodeModulesPath | No | node_modules holding those dependencies; defaults to the one beside package.json | |
| packageJsonPath | No | package.json that declares the app's native dependencies; defaults to the project root's |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds genuinely useful context beyond that: results come from 'heuristic' rules (i.e., not authoritative) and unknowns are surfaced explicitly rather than silently resolved, which shapes how an agent should treat the output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, and the core operation is front-loaded before the output caveat. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter read-only check with no output schema, the description covers what is compared and flags the heuristic/unknowns nature of the result. It does not describe the comparison scope (which dependency classes, what counts as incompatible), leaving a small gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with appId, channel, runtimeVersion, nodeModulesPath, and packageJsonPath all documented in-schema including defaults and connection-dependent requirements. The description adds no parameter-level meaning, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Compare') and resource ('local native dependencies' vs 'OtaKit release lane'), plus the mechanism used ('existing heuristic compatibility rules'). No sibling tool performs compatibility checking, so it is clearly distinguishable from the release/bundle management tools around it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never says when to call this versus alternatives (e.g., before prepare_release or publish_release), nor any prerequisites or exclusions. The context of 'update compatibility' implies a pre-flight check, but the agent must infer it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_appCreate an OtaKit appAInspect
Register a validated app slug in the current organization and return its ID and minimal Capacitor configuration. Does not edit local files.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | App slug, unique in the organization: 3-120 letters, digits, dots, underscores or hyphens |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, non-idempotent, non-destructive, closed-world behavior, so the bar is lower. The description still adds real value by disclosing the return payload (ID plus minimal Capacitor configuration) and a concrete side-effect boundary ("Does not edit local files"), though it doesn't say what happens on a duplicate slug.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core action and scope front-loaded, followed by the return contract and side-effect boundary. No filler, no restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, no-output-schema tool this is largely sufficient: the description carries the return-value burden itself (ID + Capacitor config) since no output schema exists. It is slightly thin on error/permission behavior and on how the new app relates to bundles or previews.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is exactly one parameter and schema coverage is 100%, with the pattern/length constraints fully documented in the schema. The description only echoes "validated app slug" and adds no format or uniqueness semantics beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ("Register a validated app slug"), targets an explicit scope ("in the current organization"), and states the return payload. It implicitly separates itself from create_preview/list_apps through the word "app," but it never names a sibling, so an agent must infer the distinction rather than being told.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the phrasing: one would use this to provision an app in an org. There is no statement of when to prefer it over create_preview or list_apps, no prerequisite (e.g. org must exist / slug must be free), and no exclusion beyond "Does not edit local files."
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_previewCreate an OtaKit preview linkAInspect
Create a private link and QR code that open an uploaded bundle in the installed app on one phone (plugin 3.2+ with preview links enabled) until the tester exits or the link expires. Nothing is released and no other device is affected. Share the returned url.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| bundleId | Yes | OtaKit bundle ID | |
| expiresIn | No | How long the link works (default 7d) | |
| urlScheme | No | The app's custom URL scheme (for example myapp), needed once per app so the link can open it |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read-only, non-destructive, non-idempotent, open-world behavior. The description goes further by scoping the effect ('private', 'one phone', 'no other device is affected', auto-expiry), which is exactly the kind of blast-radius context annotations cannot convey. It omits whether auth/permissions are required beyond the plugin requirement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with the core action front-loaded and the safety scoping at the end. Every clause earns its place, though the first sentence is long and could be split for scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description usefully tells the agent to 'share the returned url' and mentions the QR code, covering the return shape at a high level. Required appId/urlScheme conditions are covered by the schema, so the definition is nearly complete for calling the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented (appId optionality, bundleId, expiresIn enum with default, urlScheme). The description only loosely ties to expiresIn via 'until ... the link expires'; it adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: creates a private link and QR code that open an uploaded bundle in the installed app on one phone. The single-phone, temporary scope clearly distinguishes it from siblings like publish_release and revoke_preview.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context and prerequisites: plugin 3.2+ with preview links enabled, and the link lives until the tester exits or it expires. It does not explicitly contrast with alternatives such as publish_release, but the described effect ('nothing is released') implicitly rules those out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_bundleDelete an unused OtaKit bundleADestructiveIdempotentInspect
Delete a bundle only when it is absent from all release history. The exact app and bundle IDs are required and the operation is audited.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| bundleId | Yes | OtaKit bundle ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so safety is covered. The description adds genuinely new context: the operation is refused if the bundle appears in release history, it is audited, and exact IDs are needed — all beyond what the annotations state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, with the destructive precondition front-loaded before the ID and audit details. Every clause carries operational weight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive tool with no output schema, the description covers the eligibility precondition, ID requirements, and auditability. It stops short of describing the response or failure modes when the precondition is violated, but the essentials for correct invocation are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented; baseline 3 applies. The description only restates that exact IDs are required, and it slightly overstates by saying both are required while the appId schema notes it is optional on a local connection with a configured project.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Delete a bundle') plus a hard precondition ('only when it is absent from all release history'), which cleanly separates it from the sibling read tools get_bundle and list_bundles. An agent can identify the operation and its guard condition without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear condition for legitimate use ('absent from all release history'), which implicitly tells the agent when NOT to call it. However, it names no alternative action for bundles that are still referenced (e.g. revoke or archive), so the fallback path is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_statusGet OtaKit account and usage statusARead-onlyIdempotentInspect
Return the safe customer-facing plan, usage, limit, period, and overage state needed to explain upload or release failures. Provider IDs are excluded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond them by characterizing the payload as 'safe customer-facing' and disclosing that provider IDs are excluded, which tells the agent the data has been redacted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler. The returned-content scope is front-loaded, and the redaction note follows as a short qualifier. Nothing repeats the title or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description must carry the return-value burden, and it does by enumerating the fields returned (plan, usage, limit, period, overage state) plus the redaction caveat. It does not say what happens when no account/plan exists or how errors surface, but for a zero-parameter read tool this is close to sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, which is the baseline-4 case per the rubric. The description correctly describes no inputs, so no parameter semantics are needed or missing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Return') and a precisely scoped resource: plan, usage, limit, period, and overage state for the OtaKit account. The enumerated payload makes it unmistakably distinct from the sibling tools, which all operate on apps, bundles, releases, or previews rather than account-level status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a concrete usage context: 'needed to explain upload or release failures.' That tells the agent when to reach for this tool over release-specific diagnostics. It stops short of naming alternatives (e.g., get_release_state) or stating exclusions, so it is clear context without explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_bundleGet OtaKit bundle metadataARead-onlyIdempotentInspect
Get authorized safe metadata for a known bundle, including bounded native-package metadata and encryption presence but never keys or storage URLs.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| bundleId | Yes | OtaKit bundle ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and non-destructive, so the safety profile is covered. The description adds genuinely useful scope beyond them: what the payload contains (bounded native-package metadata, encryption presence) and, more importantly, what it will never expose (keys, storage URLs). It stops short of stating authorization requirements despite the word 'authorized'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the verb-and-resource comes first and the security constraints follow. Nothing needs trimming.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of describing returns, and it does so at a useful level (bounded native-package metadata, encryption presence, deliberate omissions). What is missing is any note on authorization prerequisites or failure behavior for an unknown bundleId.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both appId and bundleId fully documented in-schema, including the conditional requirement for appId. The description adds nothing about parameters, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get') and resource ('bundle metadata') and narrows scope to 'a known bundle', implicitly separating it from the list_bundles sibling. It never names an alternative explicitly, so the differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the reader infers it is for fetching metadata when a bundleId is already known. There is no explicit when-to-use, no when-not-to-use, and no pointer to list_bundles or get_release_state for the neighboring questions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_contextShow the active OtaKit contextARead-onlyIdempotentInspect
Show the fixed server origin, organization, actor, role, scopes, mode, and capabilities without exposing credentials.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/non-open-world. The description adds two genuinely new behavioral facts: the context is 'fixed' (server-bound rather than per-call) and credentials are deliberately withheld from output, which matters for an agent reasoning about what it can safely read back.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action, with no redundant or filler text. It ends on the security qualifier rather than burying it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description carries the burden of telling the agent what comes back, and it enumerates the returned fields. Combined with annotations covering the safety profile and zero parameters, nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description's field list describes return content rather than arguments, and adds no parameter meaning because there is none to add.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('Show') plus the exact resource ('the active OtaKit context'), with an enumeration of the fields returned (origin, organization, actor, role, scopes, mode, capabilities). This cleanly separates it from siblings like get_account_status and get_release_state, which concern different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent infers you call this to inspect the current session context. It names no alternatives, prerequisites, or when-not-to-use conditions, which for a no-arg introspection tool is tolerable but not helpful guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_release_healthGet OtaKit release event healthARead-onlyIdempotentInspect
Return bounded client-reported event counts, rollback share, auto-revert thresholds, and analytics availability for a release. Counts are events, not unique devices, installations, or adoption.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| window | No | Period the counts cover, ending now (default 24h) | |
| releaseId | Yes | OtaKit release ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuine behavioral context beyond that: counts are 'bounded' and 'client-reported', and it explicitly warns they are events rather than unique devices/installations/adoption, plus signals that analytics may be unavailable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and returned metrics, followed immediately by the most important interpretive caveat. No padding or restated field names.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing return values, and it does so by naming the four metric groups. It is essentially complete for a read-only tool, though it does not define units or the exact meaning of 'bounded'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so appId, window, and releaseId are fully documented in the schema (including the enum and default). The description adds no separate parameter syntax or format detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Return) and resource (release event health) and enumerates the payload: event counts, rollback share, auto-revert thresholds, analytics availability. An agent immediately knows the tool's output domain, though it never contrasts itself with the sibling get_release_state or get_bundle.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the metrics named; there is no explicit 'use this when…' statement and no mention of when to prefer get_release_state or list_events. The 'Counts are events, not unique devices' caveat aids interpretation but does not route tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_release_stateGet current OtaKit release stateARead-onlyIdempotentInspect
Resolve the exact current release for one (app, channel, runtimeVersion) lane. Returns null rather than selecting another lane.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| channel | Yes | Named channel, or null for the base channel | |
| runtimeVersion | Yes | Native runtime lane, or null for the default runtime |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds genuinely new behavioral context beyond that: it returns null instead of falling back to another lane, which tells the agent not to expect a substitute release. It stops short of describing auth needs or the success payload.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, and the core scope constraint is front-loaded before the null-behavior caveat. Every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only lookup with full annotation coverage and no output schema, the description covers the essential non-obvious behavior (exact-lane resolution, null on miss, no fallback). It could say a bit more about the shape of a successful release object, but that gap is minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so appId, channel, and runtimeVersion are already documented in the schema (including the null-means-base/default semantics). The description only restates the tuple as a 'lane', adding no syntax or format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (resolve) and resource (current release) scoped to exactly one (app, channel, runtimeVersion) lane, which cleanly separates it from siblings like list_releases and get_release_health. An agent can tell what it returns without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The lane-scoping phrase implies when this tool applies (single-lane exact lookup), but the description never names an alternative or states when-not to use it versus list_releases or get_release_health. Usage is inferable rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_projectInspect a local Capacitor projectARead-onlyIdempotentInspect
Inspect the selected local project for Capacitor and OtaKit configuration, build output, plugin version, server target, and notifyAppReady evidence. Does not return source contents.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered and the bar is lower. The description contributes one genuinely additive behavior: 'Does not return source contents,' a negative-scope boundary the annotations do not convey. It says nothing about filesystem access requirements or the nature of the 'selected' project state, but with annotations carrying the rest, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler. The scope enumeration is front-loaded and the return boundary is placed last as a constraint, which is exactly the right ordering for a scan-read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and zero parameters, the description carries the burden of telling the agent what comes back, and the enumeration of inspected areas largely does that. It is slightly short on how results are presented (pass/fail vs raw values) or what happens when no project is selected, which keeps it off a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema defines zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies. The mention of 'the selected local project' hints at implicit context state rather than a parameter, adding mild value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb (inspect) on a specific resource (the selected local Capacitor project) and enumerates exactly what is examined: Capacitor/OtaKit config, build output, plugin version, server target, and notifyAppReady evidence. No sibling (list_bundles, get_bundle, check_compatibility) overlaps this diagnostic scope, so the agent can route to it unambiguously.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a preflight/diagnostic use case by listing what it inspects, but never states when to reach for it versus siblings like check_compatibility or get_release_state, nor any prerequisite (e.g. that a project must be selected first). Usage is inferable but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_appsList OtaKit appsARead-onlyIdempotentInspect
List apps in the connection-bound organization, optionally requiring an exact slug. Never guesses an app when the slug is absent.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | No | Return only the app with exactly this slug | |
| limit | No | Maximum apps (1-50, default 20) | |
| cursor | No | The previous page's nextCursor; omit for the first page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, so safety is covered. The description adds real behavioral context on top: results are scoped to the connection-bound organization, and it explicitly will not infer an app when the slug is missing. Return shape and pagination behavior are left to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler; the primary purpose and scoping constraint are front-loaded, and the negative guarantee about guessing is stated compactly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only paginated list tool with full schema coverage on all three params and annotations covering the safety profile, nothing essential is missing. The absence of any mention of default page size or pagination flow is a minor gap but is already handled by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so slug, limit and cursor are already documented in the schema. The description's 'exact slug' phrasing largely restates the schema's 'exactly this slug' and adds no syntax or format detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (apps) and pins the scope to the connection-bound organization, which distinguishes it from the connection's other list_* siblings. It is clear but never explicitly contrasts itself with the sibling list tools, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'optionally requiring an exact slug' implies the two usage modes (browse all vs. lookup one), and 'Never guesses an app when the slug is absent' hints at lookup semantics. However, no alternative tool is named and no explicit when-not condition is given, so guidance remains implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_audit_logList OtaKit audit activityARead-onlyIdempotentInspect
List bounded organization audit activity for an owner or admin. Operational organization keys and member-role users cannot read it.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results in one page | |
| cursor | No | The previous page's nextCursor; omit for the first page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds authorization context beyond the annotations by naming the roles that can and cannot read the log, which is valuable for an agent. It stops short of describing pagination or result shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, and the core purpose is front-loaded before the access restriction. Every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, annotation-covered list tool with a fully documented schema, the description covers purpose and access sufficiently. The undefined term 'bounded' and absent pagination behavior are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with limit and cursor both documented in the schema, so the baseline is 3. The description adds nothing about page size limits or cursor semantics beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('List bounded organization audit activity') scoped to an organization, which separates it from generic siblings like list_events. It does not explicitly contrast itself with those siblings, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states who may call it (owner or admin) and who may not (operational organization keys, member-role users), which is genuine access guidance. However, it never says when to reach for this tool over alternatives such as list_events, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_bundlesList OtaKit bundlesARead-onlyIdempotentInspect
List safe bundle metadata and release-artifact history for one app, with bounded pagination and optional exact version.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| limit | No | Maximum results in one page | |
| cursor | No | The previous page's nextCursor; omit for the first page | |
| version | No | Return only bundles with exactly this version |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe-read profile (readOnly, idempotent, non-destructive), so the bar is lower. The description still adds value by disclosing that pagination is bounded and that results are 'safe' metadata plus release-artifact history, though it doesn't explain what 'safe' excludes or how the cursor behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler: scope first ('for one app'), then pagination and filter modifiers. Nothing could be cut without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but the description sketches the return content (metadata plus release-artifact history) and the annotations carry the safety profile. It is nearly complete; only the shape of paginated results and what 'safe' omits are left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema, including the appId conditional requirement. The description merely alludes to pagination and exact-version filtering, which the schema states more precisely, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and two concrete resources ('safe bundle metadata and release-artifact history') and scopes them to one app, which cleanly separates it from the singular get_bundle sibling. An agent can tell what this returns without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: listing bundles for an app, with the version filter offered as an optional narrowing. There is no explicit when-to-use guidance versus get_bundle, list_releases, or delete_bundle, and no stated prerequisites beyond what the schema covers.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsList OtaKit client-reported eventsBRead-onlyIdempotentInspect
List a bounded filtered rollout timeline. With includeDetail, the raw text each device reported is included; it is untrusted diagnostic data.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| limit | No | Maximum events (1-200, default 50) | |
| since | No | Only events after this ISO 8601 time; takes precedence over timeframe | |
| action | No | Only events of this kind | |
| channel | No | Named channel, or null for the base channel | |
| platform | No | Only events from this platform | |
| releaseId | No | OtaKit release ID | |
| timeframe | No | How far back to look when since is not set (default 24h) | |
| bundleVersion | No | Only events for this bundle version | |
| includeDetail | No | Set false to leave out each event's raw client-reported detail text, which is included by default | |
| runtimeVersion | No | Native runtime lane, or null for the default runtime |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, so the safety profile is covered. The description adds genuinely useful context beyond them: results are bounded, detail text is opt-out via includeDetail, and that text is untrusted diagnostic data (a meaningful prompt-injection/safety caveat). It stops short of describing ordering or pagination behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with no filler, and the scoping constraint is front-loaded. It is slightly under-specified for an 11-parameter tool, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter list tool with no output schema, the description establishes scope, bounding, and the untrusted-detail caveat, which is adequate to call it. It omits result ordering and any pagination/continuation guidance, and offers nothing to distinguish it from sibling listing tools. Minimum viable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 11 parameters thoroughly, including includeDetail's default-on behavior and since's precedence over timeframe. The description's mention of includeDetail adds no syntax or format detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description says it lists a 'bounded filtered rollout timeline,' which conveys a read/listing operation but frames the resource as a 'timeline' rather than events. The second sentence ('raw text each device reported') is what actually reveals these are client-reported events, so clarity depends on inference. It does not differentiate from siblings such as get_release_health or list_audit_log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No statement of when to use this tool versus alternatives like get_release_health or list_audit_log. The only conditional guidance ('since takes precedence over timeframe') is a parameter interaction, not usage context. An agent gets no routing help.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_releasesList OtaKit release historyBRead-onlyIdempotentInspect
List bounded release history for an app, optionally filtered to a channel, while preserving runtime-lane identity and all release options.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| limit | No | Maximum results in one page | |
| cursor | No | The previous page's nextCursor; omit for the first page | |
| channel | No | Named channel, or null for the base channel |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered structurally. The description adds that the history is "bounded" (paginated) and that lane identity/options are preserved in the result, which is useful but thin and leaves pagination defaults and return shape unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that puts the core action (listing release history for an app) first, with the filter and output characteristics trailing. It is appropriately sized, though the trailing clause is slightly opaque rather than purely informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, fully documented list tool with annotations covering safety, the description is adequate for correct invocation. However, it never explains what "bounded" means in practice or what "runtime-lane identity" implies for the returned records, and with no output schema those terms remain unclarified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so appId, limit, cursor, and channel are fully documented in the schema. The description only restates the app scope and channel filter, adding no format or default details beyond what the schema provides, which is the expected baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List bounded release history for an app") plus the optional channel filter, which distinguishes it from siblings like list_bundles or list_events. It does not name an alternative sibling, and the closing clause about "runtime-lane identity and all release options" is jargon that does not sharpen the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only usage cue is that the result can be optionally filtered to a channel; there is no statement of when to prefer this over list_bundles, get_release_state, or get_release_health, and no exclusions or prerequisites beyond what the schema already implies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_releasePrepare an OtaKit releaseBRead-onlyIdempotentInspect
Preview the exact current and proposed lane state for a bundle and return expectedCurrentReleaseId. Makes no change.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| channel | Yes | Named channel, or null for the base channel | |
| bundleId | Yes | OtaKit bundle ID | |
| autoRevert | No | Enable rollback-share based automatic revert for this release | |
| forceImmediate | No | Make devices apply and reload on their next check | |
| replaceRollout | No | Revert the lane's active rollout and publish this bundle in its place | |
| rolloutPercent | No | Share of devices (1-100, default 100) that receive this release; below 100 starts a gradual rollout on a lane that already has a release | |
| autoRevertMinSample | No | With autoRevert: completed trials (applied plus rolled back) needed before the share is trusted (10-100000, default 50) | |
| autoRevertRatePercent | No | With autoRevert: share of completed update trials that rolled back, over 24 hours, that triggers the revert (1-95, default 20) | |
| compatibilityDecision | No | When the bundle's native dependencies differ from the lane's current release: block (default) refuses; proceed publishes anyway, only after confirming no store build is needed; skip does not compare |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered and "Makes no change" largely repeats it. The description adds the returned expectedCurrentReleaseId, but not the concurrency/precondition semantics that would make that field meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short, front-loaded sentences with no wasted clauses; the return field is named early. Minor redundancy: "Makes no change" restates readOnlyHint rather than adding new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter read-only preview tool with no output schema, the description covers what it does but omits how the preview is consumed (e.g., feeding expectedCurrentReleaseId into publish_release). Note the schema lists mutation-flavored params such as replaceRollout and forceImmediate that the description leaves unexplained in a dry-run context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across 10 parameters, so the schema carries parameter meaning fully; baseline 3 applies. The description mentions no parameter behavior (rolloutPercent, compatibilityDecision, replaceRollout) beyond what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and object: preview the current and proposed lane state for a bundle, plus the concrete return field expectedCurrentReleaseId. The phrase "Makes no change" implicitly contrasts it with publish_release, but the sibling is never named, so the distinction must be inferred.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or when-not guidance; usage is only implied by "Preview" and "Makes no change." The natural pairing with publish_release (and why the returned expectedCurrentReleaseId matters) is left unstated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_revertPrepare an OtaKit revertARead-onlyIdempotentInspect
Verify that a release is current and preview the exact release or built-in fallback that will become current. Makes no change.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| releaseId | Yes | OtaKit release ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, and 'Makes no change' largely restates that. However, the description adds genuinely non-annotation context: that the call verifies currency of the release and previews both the target release and the built-in fallback path, which tells the agent what the operation does behaviorally.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the primary action (verify + preview) front-loaded and the no-side-effect guarantee placed at the end where it matters most.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only preview tool with full annotation coverage and no output schema, the description is nearly sufficient: it conveys the precondition check and what the preview reveals, including the fallback case. Only the workflow linkage to revert_release is left for the agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters (appId documents its local-connection optionality, releaseId is defined), so the schema already does the heavy lifting. The description adds no parameter-level detail, which is the expected baseline here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verbs (verify, preview) plus the resource and scope: it states that it checks whether a release is current and shows what would become current, including the built-in fallback. This clearly separates it from sibling revert_release (which performs the change) and prepare_release.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Makes no change' and the preview framing strongly imply a dry-run step before revert_release, but no sibling is named and no explicit when/when-not condition is stated. Usage is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
publish_releasePublish an OtaKit releaseADestructiveIdempotentInspect
Publish a reviewed bundle to an exact lane. Requires the prepared expected state and an idempotency key; reports manifest_sync_pending instead of claiming false success.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| channel | Yes | Named channel, or null for the base channel | |
| bundleId | Yes | OtaKit bundle ID | |
| autoRevert | No | Enable rollback-share based automatic revert for this release | |
| forceImmediate | No | Make devices apply and reload on their next check | |
| idempotencyKey | Yes | Stable key reused only when retrying this exact mutation | |
| replaceRollout | No | Revert the lane's active rollout and publish this bundle in its place | |
| rolloutPercent | No | Share of devices (1-100, default 100) that receive this release; below 100 starts a gradual rollout on a lane that already has a release | |
| autoRevertMinSample | No | With autoRevert: completed trials (applied plus rolled back) needed before the share is trusted (10-100000, default 50) | |
| autoRevertRatePercent | No | With autoRevert: share of completed update trials that rolled back, over 24 hours, that triggers the revert (1-95, default 20) | |
| compatibilityDecision | No | When the bundle's native dependencies differ from the lane's current release: block (default) refuses; proceed publishes anyway, only after confirming no store build is needed; skip does not compare | |
| expectedCurrentReleaseId | Yes | Release ID shown by prepare, or null when the lane had no release |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag destructiveHint and idempotentHint, but the description adds non-obvious semantics beyond them: the expected-state guard, the idempotency key contract, and notably that a pending sync is reported as manifest_sync_pending rather than false success. This is exactly the kind of behavioral nuance annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, front-loaded with the action and scope, then the requirements and the honesty caveat. Zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, open-world publish mutation with no output schema, the description covers requirements and the failure-reporting behavior. It does not mention permissions/scope needs or what the response looks like, but the critical calling contract is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 12 parameters (including expectedCurrentReleaseId and idempotencyKey) are already documented in the schema. The description reiterates the expected-state and idempotency concepts but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Publish a reviewed bundle to an exact lane'), and the scoping phrase 'exact lane' plus 'prepared expected state' distinguishes it from prepare_release and revert_release among the siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the precondition ('reviewed bundle', 'prepared expected state') and the idempotency requirement, which implies this runs after prepare_release. However, it never explicitly names prepare_release/prepare_revert as the prerequisite tool or states when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
revert_releaseRevert an OtaKit releaseADestructiveIdempotentInspect
Revert the reviewed current release for its exact lane; reverting a release that is rolling out cancels the rollout. Requires expected state and an idempotency key and reports pending manifest synchronization truthfully.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| releaseId | Yes | OtaKit release ID | |
| forceImmediate | No | Make devices apply and reload on their next check | |
| idempotencyKey | Yes | Stable key reused only when retrying this exact mutation | |
| expectedRolloutPercent | No | When cancelling a rollout: the rollout percentage that was reviewed. The revert is refused if the rollout changed or completed meanwhile. | |
| expectedCurrentReleaseId | Yes | OtaKit release ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, but the description adds substantive behavior: cancelling an in-flight rollout, the expected-state concurrency guard, and truthful reporting of pending manifest synchronization. It does not describe permissions or error handling in depth, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One compact sentence front-loads the action and scope before the side-effect and requirement clauses; nothing is redundant. It is densely packed with semicolon-joined clauses rather than being maximally scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, idempotent mutation with no output schema and 6 parameters, the description covers the action, scope, a key side effect, preconditions, and a hint about the response ('reports pending manifest synchronization'). Return shape and failure modes remain unspecified, but these are minor given the rich per-parameter schema and annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (appId, releaseId, forceImmediate, idempotencyKey, expectedRolloutPercent, expectedCurrentReleaseId) is already documented with formats and constraints. The description only alludes to 'expected state and an idempotency key', adding no syntax or semantics beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (revert) plus resource (the reviewed current release) with an explicit scope qualifier ('for its exact lane') that separates it from prepare_revert and set_rollout_percent. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the precondition of a reviewed current release and notes that reverting a rolling-out release cancels the rollout, which implies when the tool applies. However, it never names the sibling to run first (prepare_revert) or says when not to use this tool, so routing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
revoke_previewRevoke an OtaKit preview linkADestructiveIdempotentInspect
Revoke a preview link. Phones on it return to their normal release on their next update check.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| previewId | Yes | OtaKit preview link ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, covering the safety profile. The description adds valuable behavioral context beyond annotations: 'Phones on it return to their normal release on their next update check,' which describes the downstream effect on devices. It does not detail permissions or irreversibility explicitly, but the effect statement is a meaningful addition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and immediately followed by the key consequence. Every sentence earns its place with no redundant or vague wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, full schema coverage, and annotations that already disclose destructiveness and idempotency, the description is largely complete. It tells the agent what happens after revocation, though it omits explicit usage guidance and any note on reversibility beyond what annotations imply.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both appId and previewId are fully documented in the schema. The description adds no parameter-level information, which is acceptable when the schema already provides complete semantics; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb 'Revoke' and resource 'preview link', making the core action clear. However, it does not explicitly differentiate from siblings like create_preview, delete_bundle, or revert_release, so sibling differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus alternatives such as create_preview or delete_bundle. The description only states what the tool does and the resulting effect, leaving usage context entirely implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_rollout_percentChange an OtaKit rollout percentageADestructiveIdempotentInspect
Raise, lower, or complete (100) the active rollout of a lane's current release. Requires the reviewed current percentage and an idempotency key. To cancel a rollout, revert the release instead.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| percent | Yes | Rollout percentage (1-100); 100 completes the rollout | |
| releaseId | Yes | OtaKit release ID | |
| idempotencyKey | Yes | Stable key reused only when retrying this exact mutation | |
| expectedPercent | Yes | Rollout percentage shown by get_release_state when the change was reviewed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds valuable context: requires the reviewed current percentage (expectedPercent) and an idempotency key, and clarifies that cancellation is not handled here but via revert. Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the description's focus on preconditions and alternative action adds real behavioral guidance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler, front-loading the action and scope, then the preconditions and alternative. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with annotations covering safety and 100% schema coverage, the description adds critical usage details: required reviewed percentage, idempotency key, and the cancellation alternative. Lacks detail on failure modes or rate limits, but is otherwise complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema defines all parameters. The description reinforces that the reviewed current percentage must be supplied and an idempotency key is required, which clarifies how to use expectedPercent and idempotencyKey beyond the schema's basic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (raise/lower/complete) and resource (active rollout percentage of a lane's current release). Directs the agent to prepare_revert/revert_release for cancellation, which distinguishes it from the sibling revert tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool (raising, lowering, completing a rollout) and when not to (to cancel a rollout, revert the release instead), naming the alternative approach. Lacks detail on prerequisites like rollout state, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_and_publish_bundleUpload and publish an OtaKit bundleCDestructiveInspect
Run the existing combined local upload and release workflow with an explicit lane, compatibility decision, expected current release, complete release options, and idempotency key.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| channel | Yes | Named channel, or null for the base channel | |
| encrypt | No | Require encryption with OTAKIT_ENCRYPTION_KEY and fail if it is not set; bundles are encrypted whenever that variable is set | |
| version | No | Bundle version; defaults to OTAKIT_VERSION, then a generated one | |
| strategy | No | zip uploads one archive; deltas uploads files separately so devices download only changed ones. Defaults to the project's updateStrategy, then zip | |
| autoRevert | No | Enable rollback-share based automatic revert for this release | |
| sourcePath | No | Built web assets directory in the project; defaults to Capacitor's webDir | |
| versionMode | No | strict requires version or OTAKIT_VERSION; auto (default) generates a version when neither is set | |
| forceImmediate | No | Make devices apply and reload on their next check | |
| idempotencyKey | Yes | Stable key reused only when retrying this exact mutation | |
| replaceRollout | No | Revert the lane's active rollout and publish this bundle in its place | |
| rolloutPercent | No | Share of devices (1-100, default 100) that receive this release; below 100 starts a gradual rollout on a lane that already has a release | |
| runtimeVersion | No | Native runtime lane, or null for the default runtime | |
| nodeModulesPath | No | node_modules holding those dependencies; defaults to the one beside package.json | |
| packageJsonPath | No | package.json that declares the app's native dependencies; defaults to the project root's | |
| autoRevertMinSample | No | With autoRevert: completed trials (applied plus rolled back) needed before the share is trusted (10-100000, default 50) | |
| autoRevertRatePercent | No | With autoRevert: share of completed update trials that rolled back, over 24 hours, that triggers the revert (1-95, default 20) | |
| compatibilityDecision | No | When the bundle's native dependencies differ from the lane's current release: block (default) refuses; proceed publishes anyway, only after confirming no store build is needed; skip does not compare | |
| expectedCurrentReleaseId | Yes | Release ID shown by prepare, or null when the lane had no release |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false, idempotentHint=false and openWorldHint=true, so safety is covered. The description's only added behavioral content is that upload and publish happen together, which largely restates the tool name; it says nothing about the publish side effects, rollout behavior, or failure/partial-failure semantics for a destructive, open-world mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no wasted preamble, but the trailing enumeration ("complete release options") is filler that spends words without conveying meaning. It is compact rather than front-loaded with the information an agent actually needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 19-parameter destructive publish tool with no output schema, the description is far too thin: gradual rollout, auto-revert thresholds, encryption requirements, native-dependency compatibility blocking, and the concurrency guarantee from expectedCurrentReleaseId/idempotencyKey are all left to the schema. The description does not tie the required parameters back to the preflight tool (prepare_release/get_release_state) that supplies them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across 19 parameters, so the schema already explains channel, compatibilityDecision, expectedCurrentReleaseId, rolloutPercent, autoRevert knobs and more. The description only gestures at them ("explicit lane, compatibility decision, expected current release") without adding syntax, defaults, or constraints, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific composite action (combined local upload and release workflow), which implicitly distinguishes it from the sibling pair upload_bundle and publish_release. The phrasing "Run the existing ... workflow" is roundabout rather than a crisp verb+resource statement, but the upload+publish scope is conveyed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance and no mention of the obvious alternatives (upload_bundle, publish_release), even though this tool's whole reason to exist is that it combines them. An agent cannot tell from the description whether to prefer this over the two-step path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_bundleUpload an OtaKit bundleAInspect
Package and upload the selected local web build using the existing zip/delta, native metadata, version, and encryption workflow without publishing it.
| Name | Required | Description | Default |
|---|---|---|---|
| appId | No | OtaKit app ID. Optional on a local connection whose project configures one; required otherwise. | |
| encrypt | No | Require encryption with OTAKIT_ENCRYPTION_KEY and fail if it is not set; bundles are encrypted whenever that variable is set | |
| version | No | Bundle version; defaults to OTAKIT_VERSION, then a generated one | |
| strategy | No | zip uploads one archive; deltas uploads files separately so devices download only changed ones. Defaults to the project's updateStrategy, then zip | |
| sourcePath | No | Built web assets directory in the project; defaults to Capacitor's webDir | |
| versionMode | No | strict requires version or OTAKIT_VERSION; auto (default) generates a version when neither is set | |
| runtimeVersion | No | Native runtime lane, or null for the default runtime | |
| nodeModulesPath | No | node_modules holding those dependencies; defaults to the one beside package.json | |
| packageJsonPath | No | package.json that declares the app's native dependencies; defaults to the project root's |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-destructive, non-idempotent, closed-world mutation, so the safety profile is covered. The description usefully adds that the result is an unpublished bundle and that it reuses the existing zip/delta, metadata, version, and encryption workflow. It does not mention that repeat calls create new bundles (relevant given idempotentHint=false) or what happens on partial failure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the core action, with the non-publishing constraint placed at the end as the key differentiator. Slightly dense with the list of internal workflows, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a nine-parameter mutation tool with no output schema, the description covers purpose and the unpublished outcome but says nothing about what is returned (e.g., a bundle identifier) or what to do next. The rich schema compensates for the parameter gaps, so this is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all nine parameters, including defaults and enum meanings. The description only gestures at the concepts (zip/delta, version, encryption) without adding syntax, formats, or precedence rules beyond what the schema already provides; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Package and upload the selected local web build') and immediately differentiates itself from the closest sibling by ending with 'without publishing it', which is precisely what upload_and_publish_bundle does. An agent can pick between the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'without publishing it' gives a clear selection condition against upload_and_publish_bundle, and 'the selected local web build' implies the prerequisite that a build already exists. It stops short of naming the alternative or listing when-not conditions explicitly, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
23 tool updates
v1.9.1- First observed
check_compatibility - First observed
create_app - First observed
create_preview - First observed
delete_bundle - First observed
get_account_status - First observed
get_bundle - First observed
get_context - First observed
get_release_health - First observed
get_release_state - First observed
inspect_project - First observed
list_apps - First observed
list_audit_log - First observed
list_bundles - First observed
list_events - First observed
list_releases - First observed
prepare_release - First observed
prepare_revert - First observed
publish_release - First observed
revert_release - First observed
revoke_preview - First observed
set_rollout_percent - First observed
upload_and_publish_bundle - First observed
upload_bundle
TDQS
Scored across 23 tools
Most tools target a clearly distinct resource+action (bundles vs releases vs previews vs account), and the prepare/publish and prepare/revert pairs are explicitly framed as preview-vs-apply. The main overlap is upload_and_publish_bundle duplicating the upload_bundle + publish_release path, and get_release_state vs prepare_release vs list_releases require careful reading to distinguish.
All names are snake_case with a consistent verb-first pattern (list_, get_, create_, delete_, upload_, prepare_, publish_, revert_, set_, revoke_, check_, inspect_). The only mild deviation is the compound upload_and_publish_bundle, which is still readable and predictable.
23 tools is on the heavy side but the domain is genuinely broad (apps, bundles, releases, rollouts, reverts, previews, diagnostics, account). Most tools earn their place, though the combined upload_and_publish_bundle is redundant with the atomic upload/publish pair and could be consolidated.
Coverage spans the full bundle/release lifecycle including upload, publish, rollout, revert, preview, and diagnostics (health, events, audit, compatibility). Notable gaps are channel management (channels are referenced in filters but have no create/list/update tools) and app update/delete, which agents cannot perform.
Maintenance
Related MCP Connectors
Deploy the apps your agent builds to a private, shareable HTTPS link, checked for leaked keys first.
Get share links, publish and manage websites, artifacts and agents. No account needed.
Develop, manage, and debug Railway projects, services, and deployments from within agents.
- app-managerOAuthapp.lance
App Store Connect operator for AI agents: icons, TestFlight builds, listings, IAP, rejection fixes.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables MCP-capable agents to manage Apple App Store Connect listings by validating repository-based metadata, planning changes, and applying approved updates through Apple's documented APIs.206 npmMIT
- AlicenseAqualityAmaintenanceGives AI assistants access to current Capacitor documentation, plugin listings, and Ionic blog posts so they can provide accurate answers about Capacitor APIs and CLI usage.449 npm1MIT
- AlicenseAqualityAmaintenanceProvides AI assistants with access to Capawesome documentation and Cloud management tools, enabling app, build, and deployment operations via API token authentication.341 npm2MIT
- AlicenseAqualityBmaintenanceShare Android and iOS builds with testers from your AI agent. Sets up the build for Expo, React Native, Flutter or native apps, uploads the .apk or .ipa, and returns an install link and QR code, plus tester feedback.12569 npmMIT