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

ToolWhat 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

FieldTypeRequiredNotes
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

FieldTypeRequiredNotes
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
{
  "type": [
    "string",
    "null"
  ],
  "enum": [
    "beta",
    "developer",
    "team",
    "scale",
    "enterprise",
    null
  ],
  "description": "Subscription tier the bearer token belongs to, or null when unknown."
}
quota_remaining number | null yes
Schema
{
  "type": [
    "number",
    "null"
  ]
}
reason string | null yes

Stable code when `valid=false`: `quota_exceeded`, `cipher_not_granted`, `invalid_token`, etc.

Schema
{
  "type": [
    "string",
    "null"
  ],
  "description": "Stable code when `valid=false`: `quota_exceeded`, `cipher_not_granted`, `invalid_token`, etc."
}
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

FieldTypeRequiredNotes
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

FieldTypeRequiredNotes
success boolean yes
plaintext string | null yes
Schema
{
  "type": [
    "string",
    "null"
  ]
}
error object yes
Schema
{
  "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
}
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

FieldTypeRequiredNotes
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

FieldTypeRequiredNotes
success boolean yes
content object | null yes
Schema
{
  "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 object yes
Schema
{
  "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
}
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

FieldTypeRequiredNotes
token string yes

Cryptolect bearer token in the `crypt_<tier>_<28-base62>` format issued by `POST /v1/subscriptions/tokens`.

Output

FieldTypeRequiredNotes
ciphers array yes
Schema
{
  "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
  }
}
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

FieldTypeRequiredNotes
cipher_id string yes

Public-facing cipher identifier (e.g., `pub-abc123`).

current_token string | null yes
Schema
{
  "type": [
    "string",
    "null"
  ]
}

Output

FieldTypeRequiredNotes
cipher_id string yes
cipher_label string yes
publisher_domain string yes
acquire_options array yes
Schema
{
  "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
  }
}
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.