Skip to main content

Changelog

Notable changes to the public API, webhook payloads and MCP tools, newest first. Dates are UTC.

2026-10-25​

  • Added — MCP tool me (title Get current identity): returns the person, organization and token reach behind the connection, with the same JSON as GET /v1/me. Any valid MCP token may call it — no resource scope or permission required — so it is always listed by tools/list. Additive.

2026-10-22​

MCP server, plus the rate-limit bucket it shares with the REST API.

  • Added — every MCP tool carries a human title (List e-mails, Replay webhook delivery), on the tools/list descriptor and in annotations.title. Clients show it instead of the tool identifier. Additive.
  • Changed — the protected-resource metadata advertises in scopes_supported only what the authorization server grants a client registered through the OAuth flow: one inbox/… scope per resource, plus read. inbox/all and write are no longer listed — a client that asked for them was refused at /oauth/authorize.
  • Changed — rate limiting on the MCP server and on the REST API counts per person within the organization (sub + org), on one shared budget. Every token of the same person draws from it — a new token never resets it — and the same person in another organization now has a budget of its own (before, the bucket was sub alone, across organizations). Limits are unchanged.
  • Changed — an unknown path on the MCP host (https://mcp.inbox.kobana.com.br/anything) answers 404 with the JSON body { "error": { "code": "not_found", "message": "not_found" } } for every method, instead of an HTML page. See Endpoints.
  • Documented — the MCP server reads the token only from Authorization: Bearer; a token in the query string (?access_token=) is ignored and the request gets the 401 challenge. This was already the behaviour; it is now stated in Authentication and covered by tests. Likewise limit, cursor and sort are only taken from their named arguments — undeclared keys (per_page, page, a filters object) are dropped (Pagination).
  • Changed (breaking) — destructive MCP tools run only after the server confirms them with the user. A client that cannot confirm — protocol 2025, or 2026-07-28 without elicitation forms — gets the tool error confirmation_required and nothing runs (before, the tool ran and confirmation was left to the client's destructiveHint handling). If the server cannot take the confirmation, the answer is confirmation_unavailable.
  • Changed (breaking) — emails_reprocess, webhooks_test, webhooks_deliveries_replay and inboxes_add_recipient are now destructive (destructiveHint: true): the first three send something outside or re-run an agent that may reply, the last changes who may send to an inbox. emails_reprocess, webhooks_test, webhooks_deliveries_replay and webhooks_regenerate_secret now report idempotentHint: false.
  • Changed — a confirmation runs its action once: sending the same confirmed call again answers confirmation_replayed without running anything. Ask again by calling the tool without requestState.
  • Changed — the MCP request body is limited to 1 MB; above it the answer is 413 with the JSON-RPC error -32600 (Request body too large (limit 1048576 bytes)), checked on Content-Length before authentication and enforced on the stream itself. See Errors.

2026-10-21​

MCP server only — the REST API is unchanged.

  • Changed (breaking) — MCP authentication: the MCP server now requires a token issued for it — aud is the MCP server URL (https://mcp.inbox.kobana.com.br), not the API audience (inbox/prd). A token issued for the REST API is refused with 401 invalid_token, and the reverse holds too; a token naming more than one audience is refused. Connect by the OAuth flow (the client only needs the URL) or with a personal token created with the MCP use.
  • Changed (breaking) — every MCP token is treated as a person's, whatever src it carries: the person's dashboard permissions always apply, and a person who is not a member of the organization reaches nothing (403, no_membership). Before, a token with src=system or src=api passed on scope alone.
  • Added — protocol revision 2026-07-28, next to 2025-06-18 and 2025-03-26, decided by the request body: server/discover, the _meta envelope, -32020 for headers that disagree with the body and 404 for an unknown method. An unsupported version is now 400 with the JSON-RPC error -32022 and the supported list, instead of unsupported_protocol_version.
  • Added — resources under kobana://inbox/ (e-mails, inboxes, agents, runs, webhooks, events, the model catalog and usage), four read-only prompts and completions for their arguments. Each one is reached under the same scope and permission as the tool behind it.
  • Added — on 2026-07-28, a destructive tool asks the user to confirm first (resultType: "input_required"); declining answers user_declined. Clients without elicitation, and the 2025 revisions, behave as before.
  • Added — the token's access level (read, write, all) is honoured next to inbox/… + write: with resource scopes in the token, the resources define the reach and the level acts within them. See Scopes.
  • Changed — the authorization server being unreachable is 503 with Retry-After (was 500); invalid-token attempts are throttled per IP and answered 429 over the limit. The protected-resource metadata names the authorization server by its issuer.

2026-10-15​

  • Added — Inbox.attachments_allow_rules: an allow list of attachments by extension and/or a regular expression on the filename, on create, update, upsert and the MCP inbox tools. An attachment outside the list is ignored — the agent does not see it, the attachments_max_* limits do not count it, and a workflow step that references it fails before any request. The e-mail records it in metadata.ignoredAttachments. Default null processes every attachment, as before. Additive.
  • Changed (behaviour) — a text attachment, or one sent to the agent as base64, above 256 KB now reaches the agent as its headline and (conteúdo não enviado: …) instead of its content. PDFs and images are unaffected. Before, a large unreadable attachment (an Outlook .msg, say) could push the request past the model's input limit and fail the run.

2026-10-07​

  • Added — every outbound webhook now carries X-Idempotency-Key. On the original dispatch and every automatic retry it is the event id (SystemEvent.id, the same value as X-Kobana-Event-Id), so an endpoint that honours idempotency keys processes the event once and answers the original response to the repeats. A manual replay sends a fresh, random key instead, so the destination treats it as a new delivery rather than deduplicating it against whatever that event already settled. See Headers. Additive.
  • Changed (behaviour) — WebhookDelivery: a scheduled retry is no longer sent once any delivery of the same event to the same webhook has succeeded, typically after a manual replay. Previously the retry chain of the original failed delivery kept running after the replay got the event through, so the destination could receive one more attempt after a 2xx. The next_retry_at of the earlier failed rows is now cleared at that point. No field changed shape.

2026-09-30​

  • Changed (behaviour) — Agent workflows no longer stop at the first failure. Every step is attempted; a failing step is failed on its own and the steps after it still run. A step that references a step that did not succeed (failed or skipped) is skipped and never sent, with error depends on step N, which did not succeed. The run is still failed if any step failed, and its error now lists every failure, one per line (step <position>: <error>). No retry, still sequential.
  • Added — failed_steps on workflow.run.failed webhooks (failedSteps on the system event): the positions of every failed step. failed_step and error keep describing the first failure.

failed_steps is additive and no field changed shape — but the execution change is a behaviour change: a run that used to stop at step 1 now also runs the independent steps after it.

2026-09-29​

  • Added — Steps and placeholders: a request step may carry form instead of body. It is sent as multipart/form-data, one part per field; the two are mutually exclusive.
  • Added — placeholder namespace ${{email.attachments.N}}: the N-th attachment of the e-mail behind the run. As the whole value of a form field it is uploaded as a binary file part (bytes, filename and content type from the e-mail); inside any string it resolves to the file's base64. .base64, .filename, .content_type and .size are also available. The bytes never pass through the model.
  • Changed — WorkflowRun steps now expose request.form (null for a body step). A file field is recorded as a { attachment, filename, content_type, size } descriptor, and an attachment referenced as base64 inside request.body is stored as [attachment N: …] rather than as its bytes.

All additive — nothing existing changed shape or behaviour.

2026-09-24​

  • Changed (breaking) — Authentication: the Bearer token is now an RS256 access token issued by the Kobana authorization server, verified against the public key it publishes. Tokens signed with the previous shared HS512 secret are no longer accepted. Nothing changes in how you send the token — only which tokens verify.
    • org is now required, and it is what scopes your data. sub is the person (users.public_id); the tenant is org (accounts.public_id). A token without org is refused rather than falling back to sub — a fallback would match nothing and answer 403 to everything, with nothing naming the cause.
    • iss is now the authorization server's URL (https://account[.{env}].kobana.com.br); aud is this API's URL (https://api.inbox[.{env}].kobana.com.br) and may be a list, matched by contains.
    • exp is now required. A token without an expiry is rejected.
    • New failure mode 500 as_unavailable: our authorization server could not be reached. It is deliberately not a 401 — your token may be perfectly valid; retry shortly.

2026-09-09​

  • Added — Agent workflows: an agent may now end its run with a workflow array alongside result, and the platform executes it as a chain of HTTP requests against your systems. Sequential, fail-fast, executed once.
  • Added — Secret resource and /v1/secrets (GET, POST, PUT upsert by key, GET/PATCH/DELETE by id). Values a workflow step references as ${{secrets.KEY}}; the value is write-only and is never returned by any endpoint. Scope inbox/secrets (+ write).
  • Added — WorkflowRun resource and /v1/workflow-runs (GET list, GET by id with every step). Read-only. Scope inbox/workflow_runs. Counts are grouped under summary: { total, succeeded, error }, and each step's HTTP call under request: {} / response: {}.
  • Added — MCP tools secrets_list, secrets_get, secrets_create, secrets_upsert, secrets_update, secrets_delete, workflow_runs_list, workflow_runs_get, and the matching stdio servers.
  • Added — webhook events workflow.run.succeeded, workflow.run.failed, workflow_run.db.created, workflow_run.db.updated, workflow_run.status_changed.
  • Changed — email.agent.processed payloads now also carry workflow_run_id (null when the agent returned no workflow). Additive: existing consumers are unaffected.

All additive — nothing existing changed shape or behaviour.

2026-09-08​

  • Added — email.* webhook payloads now carry data.email.download_url: a ready-to-use link to the original .eml, valid for 30 minutes, that a webhook receiver can follow with no mTLS certificate or API JWT. See Downloading the .eml from a webhook. Additive change — existing data.email consumers are unaffected.