airstrings-mcp
OfficialManage AirStrings over-the-air string updates, locales, publishing, SDK setup, and A/B experiments from an MCP client.
Bind a directory to an AirStrings project or log in via browser approval (
airstrings_init,airstrings_login).Add, update, remove, or list local string keys and locale values (
airstrings_strings_set,airstrings_strings_rm,airstrings_strings_ls).Push local strings to the API or pull remote strings into the local workspace (
airstrings_push,airstrings_pull).Publish signed bundles to the CDN for SDK delivery (
airstrings_publish).Get public, non-secret SDK setup values: IDs, Ed25519 public keys, protection status, and initializers for web, React Native, iOS, Android, and Go (
airstrings_sdk_config).Inspect workspace status and list environments with protection and key info (
airstrings_status,airstrings_env_list).Preview promotion diffs between environments without applying them (
airstrings_promote_preview).Create/manage A/B experiments on string keys: set variants, check status, start, stop, or promote a variant (
airstrings_variant_set,_status,_start,_stop,_promote).
Provides over-the-air string and locale management for Android apps, including signed bundle publishing, SDK setup snippets, and synchronization of local string CSVs with AirStrings.
Provides over-the-air string and locale management for iOS apps, including signed bundle publishing, SDK setup snippets, and synchronization of local string CSVs with AirStrings.
Provides over-the-air string and locale management for React Native apps, including signed bundle publishing, React Native SDK setup snippets, and synchronization of local string CSVs with AirStrings.
airstrings
CLI and MCP server for AirStrings: over-the-air string updates for iOS, Android, web and React Native apps, and Go backends.
Manage strings and locales from the terminal or let an AI agent do it over MCP. airstrings publish has AirStrings sign the bundle (Ed25519) and push it to the CDN; the SDKs verify the signature before showing anything.
Listed in the MCP Registry as io.github.symbionix-sl/airstrings-cli.
Install
npm install -g @airstrings/cli # any platform, Node 18+
brew install symbionix-sl/airstrings/airstrings # macOS / Linux
go install github.com/symbionix-sl/airstrings-cli/cmd/airstrings@latest # Go 1.26.1+Installs airstrings and airstrings-mcp.
Related MCP server: i1n
Quick start
cd my-project
airstrings init # log in, create a project, bind this folder
airstrings strings set welcome.title en="Hello" es="Hola" --format text
airstrings push # send local strings to staging
airstrings publish # sign + publish staging bundles
airstrings sdk-config # IDs, public key and SDK snippets for productionWith no key, init opens the browser to log in (an owner of your organization approves), stores an org key in ~/.config/airstrings/credentials.json, creates a project named after the folder and writes .airstrings/config.json. --name <name> names the project, --project <id> binds an existing one, airstrings init <project-key> binds to the key's project. Without a terminal it waits up to 90 s for approval; on timeout, --no-browser or CI it exits 9 with the URL: approve, then re-run the same command.
Staging is active after init. Production is protected: it rejects direct writes and publishing, and changes reach it only by promotion, applied by a human in the dashboard or by airstrings promote --to production with a full-power org key.
Keys
Key | Prefix | Covers | Get it |
Org key |
| every project of the org |
|
Project key |
| every environment of one project | dashboard → API keys |
Legacy environment key | 64 hex | one environment | created before 0.18 |
Precedence: AIRSTRINGS_ORG_API_KEY > AIRSTRINGS_API_KEY > workspace key > stored login. In CI use a project key in AIRSTRINGS_API_KEY; across several projects use a gated (non-full-power) org key from the dashboard in AIRSTRINGS_ORG_API_KEY. No init needed when one of these is set.
Commands
# Account and context
airstrings login | logout # store / revoke the org key
airstrings org # stored logins; `org use <name|id>` switches
airstrings status # project, env, key scope, protection + next step
airstrings project # current project; `project ls` lists the org's
airstrings --project <id> <command> # run against another project (org key)
# Environments
airstrings env # environments: protected/open, key stored or not
airstrings env use staging # switch (shorthand: airstrings -e -u staging)
airstrings env rm <name> # remove environment credentials
airstrings locales # locales with string counts
airstrings sdk-config [--env <name>] # IDs + public keys + SDK snippets (default production)
# API keys
airstrings apikey ls # the project's keys (✓ = stored in this workspace)
airstrings apikey rotate # rotate the workspace key
airstrings apikey revoke # revoke the workspace's stored keys (e.g. after a leak)
# Strings (set/rm edit local CSVs; --push also writes to the API)
airstrings strings ls [--local] [--section <s>] [--locale <l>] [--limit <n>] [--key-prefix <p>]
airstrings strings get <key>
airstrings strings set <key> en="Hello" es="Hola" --format text|icu [--section <s>] [--push]
airstrings strings rm <key> [--locale <l>] [--section <s>] [--push]
airstrings sections list | create <name> [--description <d>] | delete <id>
airstrings push | pull [--section <s>] # sync local CSVs with the API (draft strings)
airstrings import csv <file> # bulk import; `import status <id>` to follow
# Publishing
airstrings publish [locale...] # sign + publish bundles (all locales by default)
airstrings bundles # published bundles
airstrings promote preview # diff staging → production + dashboard link to apply
airstrings promote --to production # apply (full-power org key only)
# A/B experiments on a string (text only)
airstrings variants create <key>
airstrings variants set <key> <variant> en="Hi there"
airstrings variants allocation <key> control=50 <variant>=50
airstrings variants start|stop|status|rm <key>
airstrings variants promote <key> <variant> # winner becomes the base string
# Org shared-key bucket
airstrings shared init <api-key> # save the bucket's scoped write key
airstrings shared ls | add | rm | import <file>Publishing to a protected environment exits 7 with the next step: publish to staging, then a human promotes at the printed link. airstrings <command> --help shows every flag.
Workspace
init creates .airstrings/ at the project root; commands find it from any subdirectory.
.airstrings/
config.json # project, active env, workspace keys
strings.csv # unsectioned strings
onboarding/onboarding.csv # one CSV per sectionThe CSVs are plain files you can commit.
Offline fallback bundles
airstrings bundles pull [dir] [--locale <bcp47>]
airstrings doctor # check the bundled-fallback integrationDownloads the published, signed bundles of the active environment into airstrings/bundles/ (or dir, saved to the workspace config) with a manifest.json, verifying every signature first. Commit the folder: SDKs seed from it on startup, re-verifying each bundle, so the app has strings on a cold offline start or in SSG/SSR builds. Re-run it in CI or before each release.
pull fetches draft strings as editable CSVs; bundles pull fetches published, signed bundles for shipping.
MCP server
airstrings mcp install # Claude Code
airstrings mcp install --claude-desktop # Claude Desktop
airstrings mcp status | uninstallOther clients: run airstrings-mcp over stdio. Details: cmd/airstrings-mcp/README.md.
Tool | Does |
| log in, bind a folder to a project |
| active context, environments |
| edit and list local strings (optional |
| sync local strings with the API |
| sign + publish bundles |
| diff between environments + dashboard link |
| IDs, public keys and SDK snippets |
| A/B experiments |
Scripting
--json works on every command. Errors then go to stderr as {"error":{"message":"…","next_step":"…","exit_code":7}}.
Exit | Meaning |
0 | ok |
1 | generic error |
2 | usage / bad input |
3 | auth: bad or expired key, read key used for a write, or no key for this environment |
4 | not found |
5 | network (retry) |
6 | rate limited (retry) |
7 | environment protected: publish to staging, a human promotes |
8 | plan limit reached: upgrade |
9 | login pending: open the printed URL, approve, re-run |
License
MIT, see LICENSE.
Available Tools
17 toolsairstrings_env_listARead-onlyIdempotent
List every environment of the project, same as airstrings env: name, ID, whether it is the default, protection (protected/open), whether this workspace holds a key for it, and which one is active. Use it to pick environment names for airstrings_promote_preview or airstrings_sdk_config; for the overall workspace state and next step, use airstrings_status.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds real value beyond that by disclosing what fields come back (protection mode, key presence, active environment) in the absence of an output schema. It stops short of describing ordering or formatting of the list.
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, both front-loaded: the first defines the operation and its payload, the second routes to siblings. No filler or restated name/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 zero-parameter read tool with no output schema, the description compensates by enumerating the returned fields and covering the sibling-routing decision. An agent has everything needed to call it correctly and interpret the result.
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 no parameters, so there is nothing for the description to disambiguate; the baseline for a zero-param tool is 4. The description correctly avoids inventing arguments.
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 every environment of the project') and then enumerates exactly what is returned: name, ID, default flag, protection status, key presence, and active environment. An agent can distinguish it from airstrings_status 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?
Gives explicit downstream usage ('Use it to pick environment names for airstrings_promote_preview or airstrings_sdk_config') and names the alternative plus the condition that selects it ('for the overall workspace state and next step, use airstrings_status'). This is textbook when-to-use / when-not-to-use routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_initAIdempotent
Bind a directory to an AirStrings project; call this first in a repo with no .airstrings workspace, before any other airstrings_* tool. Writes .airstrings/config.json and stores the key in the workspace. Credentials: api_key, else AIRSTRINGS_ORG_API_KEY, AIRSTRINGS_API_KEY, else the stored login. With none it returns status "pending" and verification_uri_complete: show the user that URL, and once they approve call init again with the same arguments. With an org key it creates a project named after the folder (or name) unless project names an existing one. Returns the project, whether it was created, the active environment, all environments and sections. Use airstrings_login instead only to store an org login without binding a directory.
| Name | Required | Description | Default |
|---|---|---|---|
| dir | No | Directory to initialize (absolute or relative). Defaults to the current working directory. | |
| org | No | Organization ID (org_…) to bind to when the login has several. Uses the stored login for that org, or starts one. | |
| name | No | Name for a project created with an org key. Defaults to the folder or repository name. Ignored when project is set. | |
| api_key | No | Project key (as_proj_…), org key (as_org_…) or legacy environment key. Optional: overrides the env vars and stored login. | |
| project | No | Existing project ID (proj_…) or name to bind instead of creating one. Needs an org key or org login. | |
| base_url | No | API base URL. Defaults to https://api.airstrings.com; only set it for self-hosted or test servers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations establish the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds substance on top: it writes .airstrings/config.json, persists the key in the workspace, documents the full credential precedence chain (api_key > AIRSTRINGS_ORG_API_KEY > AIRSTRINGS_API_KEY > stored login), and describes the interactive pending/verification_uri_complete flow including the requirement to re-call with identical arguments. This is exactly the extra context the annotations cannot carry.
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?
Front-loaded with the action and the ordering constraint, then the credential chain, then the fallback flow, then the return summary. Dense but every clause carries information; it is a long paragraph rather than a tightly structured list, which costs it the top mark.
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 compensates by summarizing the return payload (project, created flag, active environment, all environments and sections). Combined with the credentials, the re-invocation flow, and the sibling alternative, an agent has everything needed to call and interpret this tool.
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 baseline is 3, but the description adds meaning the schema does not: the fallback order among credential sources, and the interaction rule that an org key creates a project named after the folder unless an existing project is named. It stops short of adding syntax or format detail for dir/base_url 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 and resource ('Bind a directory to an AirStrings project') and immediately scopes it to the case it serves ('in a repo with no .airstrings workspace'). It also names the sibling it is not (airstrings_login), so an agent can distinguish it from every other airstrings_* tool 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 an explicit ordering rule ('call this first ... before any other airstrings_* tool') and an explicit exclusion ('Use airstrings_login instead only to store an org login without binding a directory'). Both the when and the when-not are stated rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_loginA
Log in to an AirStrings organization and store an org key on this machine, without binding a directory. The first call returns status "pending" and verification_uri_complete: an organization owner approves that URL in the browser, then call login again to finish; if it is denied or expires, start over. Returns the organization once stored. Use it before airstrings_init when several directories will share one login; to set up a single repo, call airstrings_init directly (it logs in when needed).
| Name | Required | Description | Default |
|---|---|---|---|
| org | No | Organization ID (org_…) the approval must be for; the approval is rejected for any other org. Optional. | |
| base_url | No | API base URL. Defaults to https://api.airstrings.com; only set it for self-hosted or test servers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, openWorldHint=true), the description discloses the full two-step protocol: first call returns status 'pending' with verification_uri_complete, an org owner approves in-browser, the agent must call login again, and denial/expiry means restarting. That async approval and retry behavior is exactly the context annotations cannot carry.
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?
Purpose is front-loaded, followed by the exact call sequence and then the usage rule, with no filler. The length is justified by a genuinely multi-step, stateful flow that would be unusable if abbreviated.
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 stateful auth tool with no output schema, the description covers the return states (pending, verification_uri_complete, organization once stored), the failure/retry path, and the persistence side effect. An agent has everything needed to drive both calls 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 coverage is 100% and the org parameter's constraint ('approval rejected for any other org') is already documented in the schema. The description adds persistence context ('store an org key on this machine') but no new meaning about org or base_url beyond what the schema states, 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+resource ('Log in to an AirStrings organization and store an org key on this machine') and immediately distinguishes itself from siblings by adding 'without binding a directory'. An agent can separate it from airstrings_init 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?
Explicitly routes the agent: 'Use it before airstrings_init when several directories will share one login; to set up a single repo, call airstrings_init directly (it logs in when needed).' This is a named alternative plus the condition that selects it, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_promote_previewARead-onlyIdempotent
Read-only diff of what promoting strings from one environment to another would change (added, updated, and extra keys per locale). Applies nothing — a human reviews the diff and applies the promotion at apply_url in the dashboard. Use it after publishing to staging to hand a production release to a human; agents cannot promote to a protected environment themselves.
| Name | Required | Description | Default |
|---|---|---|---|
| source_env | No | Environment NAME to promote from, e.g. 'staging'. Defaults to the active environment. | |
| target_env | No | Environment NAME to promote to, e.g. 'production'. Defaults to the default environment. Must differ from source_env. |
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 still adds real value by stating 'Applies nothing', that a human applies the change at apply_url in the dashboard, and that protected environments are out of reach for agents. It stops short of describing diff size limits or the full return 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?
Three sentences, front-loaded with the read-only nature of the call, then the human-handoff mechanic, then the usage trigger. No filler and every sentence carries distinct 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 2-optional-parameter tool with no output schema but strong annotations, the description covers what the diff contains and the out-of-band apply path. Minor gaps remain (no mention of pagination or diff size, and apply_url is referenced without saying it comes back in the response).
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% and both parameters are fully documented in the schema, including defaults and the 'must differ from source_env' constraint. The description only reinforces the direction of the promotion, adding 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?
Names a specific operation (read-only diff preview of a cross-environment string promotion) and enumerates the result contents (added, updated, extra keys per locale). It is clearly distinguishable from the sibling airstrings_variant_promote, which acts on variants rather than strings.
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 an explicit trigger ('Use it after publishing to staging to hand a production release to a human') and an explicit limitation ('agents cannot promote to a protected environment themselves'). It does not name a sibling alternative for the actual promotion, but the when-to-use condition is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_publishADestructive
Make the active environment's current server strings live: builds one bundle per locale, signs it (Ed25519) and uploads it to the CDN, where the SDKs pick it up on their next fetch. Publishes what is on the server, so run airstrings_push first for local edits. Each call creates a new bundle revision that replaces the live one; to undo, set the old values and publish again. Refused on a protected environment (production): publish to staging, then use airstrings_promote_preview and hand the apply_url to a human. Returns per-locale status and the published_at time.
| Name | Required | Description | Default |
|---|---|---|---|
| locales | No | Comma-separated locale codes to publish, e.g. 'en,it'. Omit to publish every locale of the project. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive=true, openWorld=true and idempotent=false, and the description adds material context beyond them: every call creates a new bundle revision that replaces the live one, there is no automatic rollback (manual undo via republishing old values), production environments are refused, and signing occurs before CDN upload. This is exactly the behavioral detail an agent needs before mutating live traffic.
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?
Four tightly packed sentences, front-loaded with the what, then prerequisites, then the undo/rollback story, then the production restriction and return payload. No sentence is redundant; each carries a distinct operational fact.
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?
Covers what the tool does, prerequisites, irreversibility and rollback, environment restrictions, and even the return payload (per-locale status and published_at) despite there being no output schema. Nothing needed to invoke 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?
Schema description coverage is 100% for the single 'locales' parameter, so the schema already explains the comma-separated format and the omit-to-publish-all behavior. The description adds nothing about the parameter, which is acceptable but not value-adding; 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 precise verb and resource ('Make the active environment's current server strings live') and enumerates the mechanism: builds per-locale bundles, Ed25519-signs them, uploads to the CDN. It also implicitly separates this from airstrings_push and airstrings_promote_preview by describing what publishing actually does.
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?
Explicit when-to-use ('run airstrings_push first for local edits'), how to undo ('set the old values and publish again'), and when this tool is the wrong choice ('Refused on a protected environment (production): publish to staging, then use airstrings_promote_preview and hand the apply_url to a human'). Names the alternative sibling and the condition that selects it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_pullADestructiveIdempotent
Download the active environment's strings into the local workspace, overwriting the local CSVs with the server state; unpushed local edits in those files are lost, so run airstrings_push first if you want to keep them. Read-only on the server. Returns the string, section and file counts. Use it to start from the server's state; to inspect local files without touching them, use airstrings_strings_ls.
| Name | Required | Description | Default |
|---|---|---|---|
| section | No | Only overwrite this section's CSV. Omit to pull every section. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag destructiveHint=true and readOnlyHint=false, but the description goes further by naming exactly what is destroyed (unpushed local edits in the target CSVs) and clarifying that the operation is read-only on the server despite the destructive local effect. It also discloses the return payload (string, section, file counts), which the annotations do not.
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?
Front-loads the destructive warning before the routing guidance, and every sentence carries distinct load: mutation semantics, safety caveat, alternative tool, and return values. No 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 single-parameter, destructive local-write tool with no output schema, the description covers the safety profile, the alternative tools, and the return value shape. Nothing an agent needs to call it safely 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?
Schema description coverage is 100% and the single 'section' parameter is fully documented in the schema ('Only overwrite this section's CSV. Omit to pull every section.'). The description adds nothing beyond that, 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?
States a specific verb+resource (download the active environment's strings into the local workspace) and defines scope precisely (overwriting local CSVs with the server state). It is immediately distinguishable from airstrings_push (upload) and airstrings_strings_ls (inspect without touching).
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 names two alternatives and the conditions that select them: run airstrings_push first to preserve local edits, and use airstrings_strings_ls to inspect without modifying. Also frames the primary use case ('start from the server's state').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_pushADestructiveIdempotent
Upload the local workspace CSVs to the active environment: upserts every key and locale value, overwriting the server's values for those keys, and creates missing sections. Keys that exist only on the server are left alone (nothing is deleted). Refused on a protected environment: push to staging, then a human promotes. Returns upserted and error counts, the sections and any failed keys. Use after many airstrings_strings_set edits; for one key, strings_set with push=true is enough. Apps see the change only after airstrings_publish.
| Name | Required | Description | Default |
|---|---|---|---|
| section | No | Only push this section's CSV. Omit to push every section and the unsectioned strings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it clarifies the destructiveHint by specifying server-only keys are left alone and nothing is deleted, discloses the protected-environment refusal, names the return payload (upserted and error counts, sections, failed keys), and notes changes are invisible until airstrings_publish. That is rich operational context an agent cannot get from the structured fields.
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?
Front-loaded with the core action, then layered with write semantics, environment constraint, return shape, and sibling routing. Every sentence carries distinct decision-relevant information; there is no 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?
Despite having no output schema, the description enumerates the return fields, covers the destructive/mutation behavior, the protected-env refusal, and the publish dependency. An agent has everything needed to call it correctly and interpret results.
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% and the single section parameter is fully documented in the schema itself ('Only push this section's CSV'). The description does not add syntax or format detail for the parameter beyond what the schema states, 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?
States a specific verb (upload/upsert) and resource (local workspace CSVs to the active environment) and immediately defines the write semantics (overwrite server values, create missing sections). It distinguishes itself from siblings by name, contrasting with airstrings_strings_set, airstrings_publish, and airstrings_promote.
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 explicit when-to-use ('after many airstrings_strings_set edits') and when-not ('for one key, strings_set with push=true is enough'). It also states the alternative path for protected environments ('push to staging, then a human promotes'), leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_sdk_configARead-onlyIdempotent
Public, non-secret SDK setup values for one environment — safe to show the user, commit and embed in app code; no API key or secret is returned. Returns organization, project and environment IDs, Ed25519 public key(s) (verification keys, not credentials), protection (protected/open) and ready-to-paste initializers for web, react_native, ios, android and go. Use it when wiring the AirStrings SDK into an app. Works with any API key of the project — a staging key returns production's config, so no production key is needed for SDK setup.
| Name | Required | Description | Default |
|---|---|---|---|
| env | No | Environment NAME (e.g. 'staging') or ID (env_…). Defaults to the default (production) environment, which is what shipped apps use. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description is free to add what they cannot: that no API key or secret is returned, that the output is safe to show the user, commit, and embed, and that the cross-environment key behavior means no production key is needed. These are substantive behavioral traits an agent could not infer from the annotations.
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 but front-loaded sentences; the safety/secret framing leads and the use case plus key-behavior note follow. It is efficient, though the long parenthetical enumerations of returned fields make it heavier than strictly necessary.
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 return-value burden and does so by listing the concrete fields and artifacts returned (IDs, public keys, protection, per-platform initializers). Combined with the safety and auth notes, an agent has everything needed to call it 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 the single 'env' parameter is already fully documented, including its default to production. The description references 'one environment' but adds no syntax or resolution 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?
The description states a specific verb+resource: returning public, non-secret SDK setup values for one environment, and it enumerates exactly what comes back (org/project/env IDs, Ed25519 public keys, protection state, initializers per platform). This distinguishes it from siblings such as airstrings_env_list or airstrings_init without needing to open their schemas.
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 gives a clear use condition: 'Use it when wiring the AirStrings SDK into an app.' It also preempts a common auth question by explaining that any project API key works and a staging key returns production's config. It stops short of naming an explicit alternative tool or a when-not-to-use case, so it is clear context rather than full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_statusARead-onlyIdempotent
Workspace status, same as airstrings status: project, active environment, key scope (read/write), protection of every environment (protected/open), the keys stored in this workspace (masked; airstrings apikey revoke removes them) and the one next step for this state. Call it first when unsure what to do next or why a write was refused. For just the environment list, use airstrings_env_list.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds real context beyond them: keys are returned masked and are removed via the revoke command, and the tool emits a single next-step recommendation. It does not mention auth prerequisites or freshness of the status snapshot, which keeps 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?
Front-loaded with purpose, then the returned fields, then usage. It is a dense single paragraph, but every clause maps to a concrete behavior or routing decision; only the key-masking aside borders on incidental detail.
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 the return payload, and it does so field by field. For a zero-parameter, read-only diagnostic tool with routing guidance, an agent has everything needed to call it 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?
The tool takes zero parameters, so the baseline is 4 and there is nothing for the description to disambiguate. It correctly implies a parameterless read-and-report call.
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 resource (workspace status) and enumerates exactly what it reports: project, active environment, key scope, per-environment protection, stored (masked) keys, and a suggested next step. It also explicitly distinguishes itself from the sibling airstrings_env_list.
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 explicit trigger conditions ('call it first when unsure what to do next or why a write was refused') and an explicit alternative for a narrower need ('for just the environment list, use airstrings_env_list'). Nothing 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.
airstrings_strings_lsARead-onlyIdempotent
List the strings in the local workspace CSVs: key, section, format and the value per locale. Reads files only, never the API, so it shows unpushed edits; run airstrings_pull first to see what the server currently holds.
| Name | Required | Description | Default |
|---|---|---|---|
| section | No | Only list this section. Omit to list every section and the unsectioned strings. |
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 genuinely useful context beyond that: it reads local files rather than the API and therefore reflects unpushed edits, which materially affects how an agent interprets the results.
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, zero waste. The behavioral distinction (local files, not API) is front-loaded before the routing advice, so the most important disambiguation comes first.
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 compensates by naming the exact returned fields and the local vs. server data source. Combined with complete param coverage and rich annotations, an agent has everything needed to invoke and interpret the tool.
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% and the single optional 'section' parameter is fully documented in the schema, including omit-to-list-all behavior. The description adds no further 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 (strings in local workspace CSVs) and enumerates the returned fields (key, section, format, value per locale). It also draws the boundary against sibling tools by clarifying it reads files only, never the API, so an agent can distinguish it from server-side reads.
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 states the use context ('shows unpushed edits') and routes to the alternative: 'run airstrings_pull first to see what the server currently holds.' The condition selecting this tool vs. airstrings_pull is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_strings_rmADestructiveIdempotent
Remove a string key, or one locale of it, from the local workspace CSV. Local only unless push=true, which also deletes it in the active environment (refused on a protected environment). Deletion cannot be undone except by setting the string again. Returns what was removed and whether it was pushed. Apps keep the old value until the next airstrings_publish.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The string key to remove, e.g. 'onboarding.welcome'. | |
| push | No | Default false. When true, also delete it in the active environment. | |
| locale | No | Remove only this locale's value (e.g. 'it'). Omit to remove the whole key in every locale. | |
| section | No | Section the key lives in. Omit for unsectioned strings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the local-vs-remote split, the protected-environment refusal, irreversibility, the return payload ('what was removed and whether it was pushed'), and the deferred effect on running apps until airstrings_publish. The annotations declare destructive/idempotent, and the description fills in the consequences and guardrails.
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?
Four tight sentences, front-loaded with the action and scope, followed by the push behavior, irreversibility warning, and return value. No filler or repetition.
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 still covers the return value, the mutation's reversibility, the local/remote distinction, and the downstream publish dependency. An agent has everything needed to call this safely.
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 baseline is 3, but the description adds real meaning: the push flag's environment-level effect and its protected-env restriction, and that omitting locale removes the whole key. It does not restate syntax the schema already provides.
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 precise verb and resource with scope: 'Remove a string key, or one locale of it, from the local workspace CSV.' It also implicitly distinguishes itself from airstrings_strings_set by contrasting removal with re-setting, and from airstrings_push by describing the push=true flag.
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 conditions: local-only by default, push=true also deletes in the active environment, refused on a protected environment, and deletion can only be undone by setting the string again. It stops short of naming the sibling tool (airstrings_strings_set) to use for restoration or airstrings_publish for propagation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_strings_setADestructiveIdempotent
Add or update one string key in the local workspace CSV (.airstrings//.csv, or .airstrings/strings.csv without a section). Overwrites the given locales of that key and keeps its other locales. Local only unless push=true, which also upserts the key in the active environment; on a protected environment that push is refused and the local change is rolled back. Returns the key, section and whether it was pushed. Use this for a few keys; after editing many keys, run airstrings_push once instead. Apps see the change only after airstrings_publish.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Dot-separated string key, e.g. 'onboarding.welcome'. Created if it does not exist. | |
| push | No | Default false. When true, also upsert this key in the active environment right after the local write. | |
| format | Yes | 'text' for plain strings or 'icu' for ICU MessageFormat (plurals, select, {placeholders}). Applies to every locale of the key. | |
| values | Yes | JSON object string of locale code to text, e.g. {"en": "Hello", "it": "Ciao"}. | |
| section | No | Section (group of keys) to write to; created on push if missing. Omit for unsectioned strings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses merge semantics (overwrites given locales, keeps others), that writes are local unless push=true, that a protected environment refuses the push and rolls back the local change, and what is returned. The destructiveHint=true annotation is consistent with 'Overwrites'.
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?
Front-loaded with the core action, then behavior, then routing guidance, with no filler. The long middle sentence packs several clauses but each carries distinct operational 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 mutation tool with no output schema, the description covers write scope, push/publish lifecycle, rollback behavior, and the return shape, leaving no material gap 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 baseline is 3, but the description adds real value: the CSV path layout, the sectionless fallback file, and section creation on push. These clarify how section and push interact beyond the field-level text.
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 ('Add or update one string key') and pins the exact target file, distinguishing it from siblings like airstrings_strings_rm and airstrings_push. An agent can select it 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?
Explicitly scopes usage ('Use this for a few keys; after editing many keys, run airstrings_push once instead') and notes that apps see changes only after airstrings_publish, naming the relevant alternative tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_variant_promoteADestructive
End a running or stopped A/B experiment for one string key by making a variant's values the key's base string, overwriting the old base values, then republish that environment's bundles automatically. Cannot be undone except by setting the old values again. Refused on a protected environment (production): promote in a writable environment instead. Returns the experiment and per-locale publish results. Use it once a winner is clear; to end the test without changing the base string, use airstrings_variant_stop.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The string key whose experiment to promote. | |
| variant | Yes | Name of the winning variant, as in airstrings_variant_status (not 'control'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=false, but the description adds substantial context beyond them: the base string is overwritten, the action cannot be undone except by manually resetting old values, bundles are automatically republished, and it is refused on protected environments. This is exactly the operational consequence detail an agent needs before a destructive call.
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?
Five tight sentences, front-loaded with the primary effect, then irreversibility, then the environment restriction, then return value and routing. Every sentence carries distinct decision-relevant information with no 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?
Despite having no output schema, the description states what is returned (the experiment and per-locale publish results). Combined with the irreversibility warning, protected-environment restriction, and sibling routing, an agent has everything needed to invoke this 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% and both parameters are documented there, including the note that 'variant' is not 'control'. The description reinforces the meaning of 'key' and 'variant' in prose but adds no syntax, format, or constraint 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?
Opening sentence names a specific verb (end/promote) and resource (A/B experiment for one string key) and states the precise effect: variant values become the base string, old values overwritten, bundles republished. It is clearly distinguishable from airstrings_variant_stop, which it explicitly contrasts.
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?
Explicit timing guidance ('use it once a winner is clear') plus a named alternative with the condition that selects it ('to end the test without changing the base string, use airstrings_variant_stop'). It also states when the tool will be refused (protected/production environment) and what to do instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_variant_setADestructiveIdempotent
Create or replace the A/B experiment for one text-format string key that already exists on the server in the active environment. Replaces the whole experiment as a new draft, so pass every variant each time; the key's base string is the implicit 'control' variant. Refused while the experiment is running (stop it first) and on a protected environment. Does not start it: call airstrings_variant_start, then airstrings_publish. Returns the stored experiment. To read the current one first, use airstrings_variant_status.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Server-side string key (format text) the experiment belongs to, e.g. 'onboarding.welcome'. | |
| variants | Yes | Each non-control variant name to an object of locale=value pairs, e.g. {"treatment": {"en": "Hi"}}. Never include 'control' — it is the base string. Give a value for every locale the base string has, or airstrings_variant_start will refuse. | |
| allocation | Yes | Variant name to integer traffic weight, including 'control', e.g. {"control": 50, "treatment": 50}. Weights are relative; give every variant in variants a weight. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the whole experiment is replaced (destructive scope), that it is written as a new draft, that every variant must be resupplied because the key's base string is the implicit control, and the two preconditions that cause refusal. The idempotent-by-replacement semantics are also explained, complementing idempotentHint=true rather than merely restating it.
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?
Three dense sentences front-load the operation and replace semantics, then preconditions, then the follow-up tool chain. No sentence is filler and nothing needed for correct invocation is repeated.
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, nested-object mutation tool with no output schema, the definition supplies preconditions, destruction scope, follow-up calls, and even notes that it returns the stored experiment. An agent has everything required to call it safely without additional discovery.
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 baseline is 3 and the schema already documents key, variants (locale/value pairs, never 'control') and allocation weights. The description adds a genuine cross-parameter constraint — 'pass every variant each time' — that explains why the variants object must be complete on every call, which is not obvious from the schema alone.
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 pair and resource ('create or replace the A/B experiment') with tight scoping to a text-format string key in the active environment. It is clearly distinguishable from siblings like airstrings_strings_set and airstrings_variant_start without opening any 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?
Explicitly routes the agent: use airstrings_variant_status to read first, airstrings_variant_start then airstrings_publish to activate, and airstrings_variant_stop before re-running. It also states two hard refusal conditions (experiment running, protected environment), which is exactly the when-not guidance the rubric rewards.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_variant_startA
Start a draft A/B experiment for one string key so its variants are served, split by allocation; takes effect in apps after the next airstrings_publish. Only a draft can start, and every variant must have a value for every locale of the base string. Refused on a protected environment (production): start it in a writable environment instead. Returns the updated experiment. Create the draft first with airstrings_variant_set.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The string key whose experiment to start. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the write/idempotency profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), and the description goes well beyond them: it discloses the non-idempotent downstream effect (live after publish), the draft-only constraint, the validation requirement that every variant cover every locale, the environment refusal behavior, and the return value. Substantial added context.
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?
Four sentences, each carrying distinct load: purpose, timing, preconditions, environment behavior, and return value. Front-loaded with the action, no filler or repetition.
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?
Even without an output schema, the description states what is returned (the updated experiment) and covers the prerequisites, env restrictions and lifecycle effects an agent needs to invoke it correctly. Nothing material is missing for a one-parameter tool.
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% and there is only one parameter, so the schema already documents 'key'. The description adds only the framing 'one string key so its variants are served', which does not meaningfully extend the schema 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?
States a specific verb (start) and resource (draft A/B experiment for one string key) and clearly distinguishes itself from siblings airstrings_variant_set, airstrings_variant_stop and airstrings_variant_promote. An agent can tell exactly which lifecycle operation this is without opening a 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?
Explicit prerequisites (only a draft can start, invoked after airstrings_variant_set), a stated condition for failure (protected/production environments are refused), and a concrete alternative action (start it in a writable environment instead). Timing guidance ('takes effect after the next airstrings_publish') is also given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
airstrings_variant_statusARead-onlyIdempotent
Read the A/B experiment for one string key in the active environment: status (draft, running or stopped), allocation and each variant's values. Returns an error if the key has no experiment. Use it before airstrings_variant_set to keep existing variants, or to check state before start, stop or promote.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The string key whose experiment to read, e.g. 'onboarding.welcome'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint, so the safety profile is covered. The description adds useful context beyond annotations: it describes the error condition when no experiment exists and enumerates the return fields, though it does not mention auth or rate limits.
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 core action and scope, followed by usage guidance. Every sentence earns its place with no redundancy.
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 simple read tool with one parameter, rich annotations, and no output schema, the description covers purpose, usage context, error behavior, and the shape of returned data. An agent has everything needed to call it 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 the single 'key' parameter is fully documented in the schema. The description only restates the key scope ('one string key'), adding 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?
States a specific verb (Read) and resource (the A/B experiment for one string key in the active environment), and enumerates the returned fields (status, allocation, variant values). This clearly distinguishes it from sibling tools like airstrings_status and airstrings_variant_set.
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 names when to use it (before airstrings_variant_set to keep existing variants, or before start/stop/promote to check state) and names the relevant alternative tools. Nothing 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.
airstrings_variant_stopA
Stop a running A/B experiment for one string key: every user gets the base string again after the next airstrings_publish. A stopped experiment cannot restart; airstrings_variant_set creates a new draft, and a stopped experiment can still be promoted. Refused on a protected environment. Returns the updated experiment. To keep a winning variant instead, use airstrings_variant_promote.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | The string key whose experiment to stop. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic mutation profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true). The description adds real behavioral context beyond them: the change is deferred until the next airstrings_publish, the stop is irreversible (cannot restart), it can still be promoted afterwards, and it is refused on protected environments.
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?
Four short sentences, zero filler, and the primary effect (what stopping does to users) is front-loaded ahead of the state-transition caveats and the alternative-tool routing.
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, stating 'Returns the updated experiment' is useful, and the irreversible state transition plus the protected-environment refusal cover the failure modes an agent needs before invoking this.
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?
One parameter with 100% schema description coverage, so the schema already explains 'key'. The description only restates scope ('one string key') without adding format, validation or example 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?
Specific verb (stop) plus resource (a running A/B experiment) plus scope (one string key). It is clearly distinguishable from siblings airstrings_variant_set, airstrings_variant_promote and airstrings_variant_start, all of which are named or implied.
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?
Explicit routing guidance: use airstrings_variant_promote to keep a winning variant, airstrings_variant_set creates a new draft if you need one, and it is refused on protected environments. The when-not condition (protected env) and the alternatives are both stated.
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.
13 tool updates
v0.22.4- Changed
airstrings_init6 fields changed- changed
Input schema / properties / api_key / descriptionPrevious value: -"Project key (as_proj_…), org key (as_org_…) or legacy environment key. Optional."New value: +"Project key (as_proj_…), org key (as_org_…) or legacy environment key. Optional: overrides the env vars and stored login." - changed
Input schema / properties / base_url / descriptionPrevious value: -"API base URL. Defaults to https://api.airstrings.com if omitted."New value: +"API base URL. Defaults to https://api.airstrings.com; only set it for self-hosted or test servers." - changed
Input schema / properties / dir / descriptionPrevious value: -"Directory to initialize. Uses current working directory if omitted."New value: +"Directory to initialize (absolute or relative). Defaults to the current working directory." - changed
Input schema / properties / name / descriptionPrevious value: -"Name for a project created with an org key. Defaults to the folder or repository name."New value: +"Name for a project created with an org key. Defaults to the folder or repository name. Ignored when project is set." - changed
Input schema / properties / org / descriptionPrevious value: -"Organization ID to bind to. Uses the stored login for that org, or logs in. Optional."New value: +"Organization ID (org_…) to bind to when the login has several. Uses the stored login for that org, or starts one." - changed
Input schema / properties / project / descriptionPrevious value: -"Existing project ID or name to bind instead of creating one (org key)."New value: +"Existing project ID (proj_…) or name to bind instead of creating one. Needs an org key or org login."
- Changed
airstrings_login2 fields changed- changed
Input schema / properties / base_url / descriptionPrevious value: -"API base URL. Defaults to https://api.airstrings.com if omitted."New value: +"API base URL. Defaults to https://api.airstrings.com; only set it for self-hosted or test servers." - changed
Input schema / properties / org / descriptionPrevious value: -"Organization ID the approval must be for. Optional."New value: +"Organization ID (org_…) the approval must be for; the approval is rejected for any other org. Optional."
- Changed
airstrings_promote_preview2 fields changed- changed
Input schema / properties / source_env / descriptionPrevious value: -"Source environment NAME. Defaults to the active environment if omitted."New value: +"Environment NAME to promote from, e.g. 'staging'. Defaults to the active environment." - changed
Input schema / properties / target_env / descriptionPrevious value: -"Target environment NAME. Defaults to the default environment if omitted."New value: +"Environment NAME to promote to, e.g. 'production'. Defaults to the default environment. Must differ from source_env."
- Changed
airstrings_publish1 field changed- changed
Input schema / properties / locales / descriptionPrevious value: -"Comma-separated locales to publish. If omitted, publishes all."New value: +"Comma-separated locale codes to publish, e.g. 'en,it'. Omit to publish every locale of the project."
- Changed
airstrings_pull1 field changed- changed
Input schema / properties / section / descriptionPrevious value: -"Pull only this section. If omitted, pulls all."New value: +"Only overwrite this section's CSV. Omit to pull every section."
- Changed
airstrings_push1 field changed- changed
Input schema / properties / section / descriptionPrevious value: -"Push only this section. If omitted, pushes all."New value: +"Only push this section's CSV. Omit to push every section and the unsectioned strings."
- Changed
airstrings_sdk_config1 field changed- changed
Input schema / properties / env / descriptionPrevious value: -"Environment NAME or ID. Defaults to the default (production) environment."New value: +"Environment NAME (e.g. 'staging') or ID (env_…). Defaults to the default (production) environment, which is what shipped apps use."
- Changed
airstrings_strings_ls1 field changed- changed
Input schema / properties / section / descriptionPrevious value: -"Filter to a specific section. If omitted, lists all sections."New value: +"Only list this section. Omit to list every section and the unsectioned strings."
- Changed
airstrings_strings_rm4 fields changed- changed
Input schema / properties / key / descriptionPrevious value: -"The string key to remove"New value: +"The string key to remove, e.g. 'onboarding.welcome'." - changed
Input schema / properties / locale / descriptionPrevious value: -"Remove only this locale. If omitted, removes all locales for the key."New value: +"Remove only this locale's value (e.g. 'it'). Omit to remove the whole key in every locale." - changed
Input schema / properties / push / descriptionPrevious value: -"Also mirror the removal to the API immediately."New value: +"Default false. When true, also delete it in the active environment." - changed
Input schema / properties / section / descriptionPrevious value: -"Section to remove from. If omitted, removes from flat strings.csv"New value: +"Section the key lives in. Omit for unsectioned strings."
- Changed
airstrings_strings_set5 fields changed- changed
Input schema / properties / format / descriptionPrevious value: -"String format: 'text' or 'icu'. Required."New value: +"'text' for plain strings or 'icu' for ICU MessageFormat (plurals, select, {placeholders}). Applies to every locale of the key." - changed
Input schema / properties / key / descriptionPrevious value: -"The string key (e.g., 'onboarding.welcome')"New value: +"Dot-separated string key, e.g. 'onboarding.welcome'. Created if it does not exist." - changed
Input schema / properties / push / descriptionPrevious value: -"Also push this key to the API immediately after the local write."New value: +"Default false. When true, also upsert this key in the active environment right after the local write." - changed
Input schema / properties / section / descriptionPrevious value: -"Section name. If omitted, string goes to flat strings.csv"New value: +"Section (group of keys) to write to; created on push if missing. Omit for unsectioned strings." - changed
Input schema / properties / values / descriptionPrevious value: -"JSON object of locale=value pairs, e.g. {\"en\": \"Hello\", \"it\": \"Ciao\"}"New value: +"JSON object string of locale code to text, e.g. {\"en\": \"Hello\", \"it\": \"Ciao\"}."
- Changed
airstrings_variant_promote1 field changed- changed
Input schema / properties / variant / descriptionPrevious value: -"The variant name to promote to the winning value."New value: +"Name of the winning variant, as in airstrings_variant_status (not 'control')."
- Changed
airstrings_variant_set4 fields changed- changed
Input schema / properties / allocation / descriptionPrevious value: -"Object mapping variant name to integer weight, e.g. {\"control\": 50, \"treatment\": 50}."New value: +"Variant name to integer traffic weight, including 'control', e.g. {\"control\": 50, \"treatment\": 50}. Weights are relative; give every variant in variants a weight." - changed
Input schema / properties / key / descriptionPrevious value: -"The string key the experiment belongs to (e.g., 'onboarding.welcome')."New value: +"Server-side string key (format text) the experiment belongs to, e.g. 'onboarding.welcome'." - changed
Input schema / properties / variants / descriptionPrevious value: -"Object mapping each non-control variant name to an object of locale=value pairs, e.g. {\"treatment\": {\"en\": \"Hi\"}}. Never include 'control' — it is the base string."New value: +"Each non-control variant name to an object of locale=value pairs, e.g. {\"treatment\": {\"en\": \"Hi\"}}. Never include 'control' — it is the base string. Give a value for every locale the base string has, or airstrings_variant_start will refuse." - changed
Input schema / requiredPrevious value: -[ - "key" -]New value: +[ + "key", + "allocation", + "variants" +]
- Changed
airstrings_variant_status1 field changed- changed
Input schema / properties / key / descriptionPrevious value: -"The string key whose experiment to read."New value: +"The string key whose experiment to read, e.g. 'onboarding.welcome'."
17 tool updates
v0.1.0- First observed
airstrings_env_list - First observed
airstrings_init - First observed
airstrings_login - First observed
airstrings_promote_preview - First observed
airstrings_publish - First observed
airstrings_pull - First observed
airstrings_push - First observed
airstrings_sdk_config - First observed
airstrings_status - First observed
airstrings_strings_ls - First observed
airstrings_strings_rm - First observed
airstrings_strings_set - First observed
airstrings_variant_promote - First observed
airstrings_variant_set - First observed
airstrings_variant_start - First observed
airstrings_variant_status - First observed
airstrings_variant_stop
TDQS
Scored across 17 tools
Each tool has a distinct resource+action, and descriptions explicitly disambiguate near-neighbors ('for just the environment list, use airstrings_env_list'; 'to end the test without changing the base string, use airstrings_variant_stop'). The variant family (set/status/start/stop/promote) and the strings family (set/rm/ls vs push/pull/publish) are clearly separated despite similar names.
All tools share the airstrings_ prefix with snake_case and a consistent resource-namespace scheme (variant_*, strings_*, env_list). Minor deviation: some tools are verb-only (login, push, pull, publish) while others are noun_verb (variant_set, strings_rm), but the grouping remains predictable.
17 tools is slightly heavy but each earns its place across distinct domains (auth, workspace init/status, strings sync, publish, A/B variants, SDK config). The 5-tool variant lifecycle is the main driver of the count and is genuinely necessary for the experiment workflow.
Strong lifecycle coverage: auth, init, local/server string CRUD, push/pull/publish, environment listing, promotion preview, and full A/B variant lifecycle. Minor gaps: no environment create/delete or project management/teardown operations, but the core localization and release loop is complete.
Maintenance
Related MCP Connectors
Manage app translations: find missing or duplicate phrases, add languages and export dictionaries.
Localize apps from your AI assistant: translate locale files, set glossaries, connect GitHub repos.
Ship and update Capacitor apps: live updates, channels, rollouts, devices, native builds, stats.
Ship over-the-air updates for Capacitor apps: publish releases after your approval, control staged rollouts, read rollout health, and revert.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides tools for working with iOS Localizable.xcstrings files, enabling automated translation workflows and localization management for iOS/macOS projects using Xcode String Catalogs.75MIT
- AlicenseNot gradedqualityBmaintenanceLocalization as code — push, pull, translate, and extract strings from code with AI. 7 MCP tools for type-safe i18n across 182 languages.66 npm2MIT
- AlicenseAqualityBmaintenanceAI localization from your editor — translate an app's string files into 46 languages with placeholder-safe, reproducible output. Eleven formats (JSON, .arb, .po, .strings, Android XML and more), and every translation is read back and checked before it lands.7339 PyPIMIT
- AlicenseNot gradedqualityCmaintenanceEnables localization of React, Next.js, and Vue apps from an AI assistant by managing projects, languages, translations, glossaries, style guides, and GitHub repository integration.MIT