MCP tools reference
Five tools, one bundle, one canonical URL. Agents can discover the live
schema at /.well-known/mcp-tools.json
— the same JSON Schemas the EmDash plugin serves, generated from the same
source so they cannot drift.
The five tools
| Tool | What it's for |
|---|---|
cryptolect.check_access | Cheap pre-flight: does the supplied bearer token currently have decode access to a given cipher? Use before spending quota on a `cryptolect.decode` call. |
cryptolect.decode | Decode a single emojitext payload using the bearer's subscription. Burns one quota unit on success. Returns the upstream wire error code on failure (`cipher_not_granted`, `quota_exceeded`, `decode_failed`, etc.). |
cryptolect.read_gated_post | Convenience: fetch a published page by URL, walk its Portable Text body for `cryptolectGated` blocks, decode each via the bearer, and return both plaintext and decoded blocks together. Falls back to per-block error envelopes if any individual cipher is not granted. |
cryptolect.list_accessible_ciphers | List the ciphers the bearer's subscription holds active grants for, plus current quota state. Useful for deciding what gated content is safe to attempt. |
cryptolect.get_acquisition_info | Given a cipher the current token does NOT have access to, return acquisition options (subscription tiers, beta-invite URL) so the agent's host code can prompt the human operator. |
cryptolect.check_access
Cheap pre-flight: does the supplied bearer token currently have decode access to a given cipher? Use before spending quota on a `cryptolect.decode` call.
Input
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`. |
cipher_id | string | yes | Public-facing cipher identifier (e.g., `pub-abc123`). |
Output
| Field | Type | Required | Notes |
|---|---|---|---|
valid | boolean | yes | — |
tier | string | null | yes | Subscription tier the bearer token belongs to, or null when unknown. Allowed values: "beta", "developer", "team", "scale", "enterprise", null Schema |
quota_remaining | number | null | yes | — Schema |
reason | string | null | yes | Stable code when `valid=false`: `quota_exceeded`, `cipher_not_granted`, `invalid_token`, etc. Schema |
Full JSON Schema
{
"name": "cryptolect.check_access",
"description": "Cheap pre-flight: does the supplied bearer token currently have decode access to a given cipher? Use before spending quota on a `cryptolect.decode` call.",
"inputSchema": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`."
},
"cipher_id": {
"type": "string",
"description": "Public-facing cipher identifier (e.g., `pub-abc123`)."
}
},
"required": [
"token",
"cipher_id"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"valid": {
"type": "boolean"
},
"tier": {
"type": [
"string",
"null"
],
"enum": [
"beta",
"developer",
"team",
"scale",
"enterprise",
null
],
"description": "Subscription tier the bearer token belongs to, or null when unknown."
},
"quota_remaining": {
"type": [
"number",
"null"
]
},
"reason": {
"type": [
"string",
"null"
],
"description": "Stable code when `valid=false`: `quota_exceeded`, `cipher_not_granted`, `invalid_token`, etc."
}
},
"required": [
"valid",
"tier",
"quota_remaining",
"reason"
],
"additionalProperties": false
}
} cryptolect.decode
Decode a single emojitext payload using the bearer's subscription. Burns one quota unit on success. Returns the upstream wire error code on failure (`cipher_not_granted`, `quota_exceeded`, `decode_failed`, etc.).
Input
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`. |
cipher_id | string | yes | Public-facing cipher identifier (e.g., `pub-abc123`). |
encoded_content | string | yes | Emoji-encoded ciphertext as stored on the gated block. |
Output
| Field | Type | Required | Notes |
|---|---|---|---|
success | boolean | yes | — |
plaintext | string | null | yes | — Schema |
error | object | yes | — Schema |
Full JSON Schema
{
"name": "cryptolect.decode",
"description": "Decode a single emojitext payload using the bearer's subscription. Burns one quota unit on success. Returns the upstream wire error code on failure (`cipher_not_granted`, `quota_exceeded`, `decode_failed`, etc.).",
"inputSchema": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`."
},
"cipher_id": {
"type": "string",
"description": "Public-facing cipher identifier (e.g., `pub-abc123`)."
},
"encoded_content": {
"type": "string",
"description": "Emoji-encoded ciphertext as stored on the gated block."
}
},
"required": [
"token",
"cipher_id",
"encoded_content"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"plaintext": {
"type": [
"string",
"null"
]
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Stable wire-error code. See `AGENT_INTERFACE_SPEC.md` §'Stable Error Codes' for the canonical list."
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false,
"nullable": true
}
},
"required": [
"success",
"plaintext",
"error"
],
"additionalProperties": false
}
} cryptolect.read_gated_post
Convenience: fetch a published page by URL, walk its Portable Text body for `cryptolectGated` blocks, decode each via the bearer, and return both plaintext and decoded blocks together. Falls back to per-block error envelopes if any individual cipher is not granted.
Input
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`. |
post_url | string | yes | Absolute URL of the published page. The plugin re-fetches via `ctx.http.fetch`. |
Output
| Field | Type | Required | Notes |
|---|---|---|---|
success | boolean | yes | — |
content | object | null | yes | — Schema |
error | object | yes | — Schema |
Full JSON Schema
{
"name": "cryptolect.read_gated_post",
"description": "Convenience: fetch a published page by URL, walk its Portable Text body for `cryptolectGated` blocks, decode each via the bearer, and return both plaintext and decoded blocks together. Falls back to per-block error envelopes if any individual cipher is not granted.",
"inputSchema": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`."
},
"post_url": {
"type": "string",
"description": "Absolute URL of the published page. The plugin re-fetches via `ctx.http.fetch`."
}
},
"required": [
"token",
"post_url"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"content": {
"type": [
"object",
"null"
],
"properties": {
"plaintext_blocks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"text": {
"type": "string"
}
},
"required": [
"type",
"text"
],
"additionalProperties": true
}
},
"decoded_blocks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"text": {
"type": "string"
},
"cipher_id": {
"type": "string"
}
},
"required": [
"type",
"text",
"cipher_id"
],
"additionalProperties": false
}
}
},
"required": [
"plaintext_blocks",
"decoded_blocks"
],
"additionalProperties": false
},
"error": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Stable wire-error code. See `AGENT_INTERFACE_SPEC.md` §'Stable Error Codes' for the canonical list."
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false,
"nullable": true
}
},
"required": [
"success",
"content",
"error"
],
"additionalProperties": false
}
} cryptolect.list_accessible_ciphers
List the ciphers the bearer's subscription holds active grants for, plus current quota state. Useful for deciding what gated content is safe to attempt.
Input
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`. |
Output
| Field | Type | Required | Notes |
|---|---|---|---|
ciphers | array | yes | — Schema |
Full JSON Schema
{
"name": "cryptolect.list_accessible_ciphers",
"description": "List the ciphers the bearer's subscription holds active grants for, plus current quota state. Useful for deciding what gated content is safe to attempt.",
"inputSchema": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`."
}
},
"required": [
"token"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"ciphers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cipher_id": {
"type": "string"
},
"label": {
"type": "string"
},
"publisher_domain": {
"type": "string"
},
"quota_remaining_for_this_cipher": {
"type": "number"
}
},
"required": [
"cipher_id",
"label",
"publisher_domain",
"quota_remaining_for_this_cipher"
],
"additionalProperties": false
}
}
},
"required": [
"ciphers"
],
"additionalProperties": false
}
} cryptolect.get_acquisition_info
Given a cipher the current token does NOT have access to, return acquisition options (subscription tiers, beta-invite URL) so the agent's host code can prompt the human operator.
Input
| Field | Type | Required | Notes |
|---|---|---|---|
cipher_id | string | yes | Public-facing cipher identifier (e.g., `pub-abc123`). |
current_token | string | null | yes | — Schema |
Output
| Field | Type | Required | Notes |
|---|---|---|---|
cipher_id | string | yes | — |
cipher_label | string | yes | — |
publisher_domain | string | yes | — |
acquire_options | array | yes | — Schema |
Full JSON Schema
{
"name": "cryptolect.get_acquisition_info",
"description": "Given a cipher the current token does NOT have access to, return acquisition options (subscription tiers, beta-invite URL) so the agent's host code can prompt the human operator.",
"inputSchema": {
"type": "object",
"properties": {
"cipher_id": {
"type": "string",
"description": "Public-facing cipher identifier (e.g., `pub-abc123`)."
},
"current_token": {
"type": [
"string",
"null"
]
}
},
"required": [
"cipher_id",
"current_token"
],
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"properties": {
"cipher_id": {
"type": "string"
},
"cipher_label": {
"type": "string"
},
"publisher_domain": {
"type": "string"
},
"acquire_options": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "`subscription` or `beta_invitation`."
},
"tier_options": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"price_usd": {
"type": "number"
},
"quota": {
"type": "number"
}
},
"required": [
"id",
"price_usd",
"quota"
],
"additionalProperties": false
}
},
"register_url": {
"type": "string"
},
"request_access_url": {
"type": "string"
},
"docs_url": {
"type": "string"
}
},
"required": [
"type"
],
"additionalProperties": false
}
}
},
"required": [
"cipher_id",
"cipher_label",
"publisher_domain",
"acquire_options"
],
"additionalProperties": false
}
} Discovery
Agents who already know the publisher's domain can pull the schema bundle directly:
curl https://cryptolect.dev/.well-known/mcp-tools.json | jq '.tools[].name'
Inside an EmDash venue with the plugin installed, the same schemas are
served at GET /api/cryptolect/mcp/tools. Both surfaces emit
the same bytes — the marketing site's copy is generated at build time from
the plugin's source schemas.ts.