---
title: Versioning
description: How Signal's connector changes tools, change actions, prompts and widgets without breaking the prompts and habits built on them.
product: signal
section: mcp
order: 9
---

# Versioning

Assistants cache what Signal's connector offers. Claude and ChatGPT keep a connection's tool list, and people write prompts, skills and habits against tool names. These rules keep those working from one release to the next.

## What the contract covers

| Item | The contract |
|---|---|
| **Tool** | Its name, its input schema, its output (structured content and text, field by field), its annotations, its area, whether it reads or writes, and whether View only connections are shown it |
| **Change action** | Its name, its fields, what its card says it will do, what it needs (role permission, plan, module) and its undo rule |
| **Prompt** | Its name, its arguments, and the tools and change actions it names |
| **Widget** | Its id and resource (`ui://signal/<id>.html`), the tools that link it, the fields it reads, and the MCP Apps protocol version. Each widget's payload is versioned `signal.<id>/<N>`. |
| **Refusal codes** | The `code` a refused or failed call answers with |
| **Resources** | Their URIs and what they hold |

The connector's address (`https://crm.empiraa.app/mcp`), its OAuth endpoints and its scopes (`signal:read`, `signal:write`, `offline_access`) are part of the contract too.

## The rules

1. **Names never change.** A published tool, change action, prompt, widget id or refusal code is never renamed, and never reused for something else, even after it's removed.
2. **Additive changes ship at any time**, with a changelog entry:
   - a new tool, change action, prompt or widget
   - a new optional input or argument
   - a new output field (clients must ignore fields they don't know)
   - a new value in an output's list of values
   - a wider accepted input, such as a longer limit or a new accepted value
   - a clearer title or description, or a card or widget that reads better
3. **Breaking changes get a new name and 90 days' overlap.** A change is breaking when someone who relied on the old behavior could be hurt by it:
   - removing or renaming an item or a field
   - a newly required input
   - a narrower accepted input
   - a field whose type or meaning changes
   - a changed default
   - an annotation that loosens safety
   - a change action that changes more than its card used to say, or whose undo rule gets narrower
   - a widget payload a version-1 widget can't draw

   The new item ships beside the old one (for example `list_deals_v2`, or a widget's `signal.<id>/2`). The old one's description starts "Deprecated: use … (removed after YYYY-MM-DD)" and its behavior stays exactly as it was. Both stay for at least 90 days, and each step is in the [changelog](changelog.md).
4. **Change actions follow the same rules**, because clients cache them too.
5. **Safety and privacy fixes are the exception.** A fix that closes a security or privacy hole ships at once, even when it breaks the contract. Its changelog entry says what changed, without the details of the hole.
6. **Signal's own rules still win.** A role, plan, module or workspace switch that refuses a call isn't a contract change. The refusal codes are the contract, not whether a particular person gets a yes.

## Version numbers

- **The connector has no version number of its own.** Its version is the release, and each [changelog](changelog.md) entry is one release. The server name and version a client sees in `initialize` are informational.
- **Widgets are versioned per payload** (`signal.<id>/<N>`). Every widget at launch is version 1.
- **The [tool reference](tools.md) always matches the code.** It's generated from the connector's registries.
