# Migrating from 2.x to 3.0

v3.0 is a major version bump, but the migration is **purely
additive** — every new capability is opt-in via env or Helm value.
A vanilla `docker compose --profile demo up` runs identically on
2.x and 3.0. No behaviour flips required.

## tl;dr

| You are running… | Required action |
|---|---|
| The OSS demo (`docker compose --profile demo up`) | None — defaults unchanged. |
| `helm install obs ./helm/observability-mcp` (defaults) | None — chart still ships single-replica + no Redis + no SCIM. |
| Any custom Helm values from 2.x | None. Three new value blocks (`airgapped`, `anomalyHistory`, no other touched) are off by default. |
| A plugin author importing from `@thotischner/observability-mcp/sdk` | Switch to `@thotischner/observability-mcp-sdk` (new dedicated SDK package). Both work; the dedicated one is recommended going forward. |

## New opt-in capabilities

| Env / Value | What it does | Docs |
|---|---|---|
| `OMCP_ANOMALY_HISTORY_REMOTE_WRITE=<url>` | Mirror anomaly scores to TSDB. Enables `get_anomaly_history` MCP tool. | [anomaly-history.md](../anomaly-history.md) |
| `OMCP_SCIM_TOKEN=<token>` + `OMCP_SCIM_STORE=<path>` | SCIM 2.0 provisioning at `/scim/v2/*` (Entra/Okta push). | [scim-provisioning.md](../scim-provisioning.md) |
| `OMCP_SCIM_GROUP_ROLE_MAP="admins:admin,sre:operator"` | Map SCIM-provisioned groups to RBAC roles. | – |
| `airgapped: true` (Helm) | Egress-deny NetworkPolicy + `OMCP_AIRGAPPED=true`. | [airgapped-deployment.md](../airgapped-deployment.md) |
| `airgappedExtraEgress: [...]` (Helm) | Operator's allow-listed egress destinations when airgapped. | [airgapped-deployment.md](../airgapped-deployment.md) |
| `anomalyHistory.enabled: true` (Helm) | TSDB sink wired via Helm values. | [anomaly-history.md](../anomaly-history.md) |

## New MCP tools

The tool registry grows from 8 → 11:

- `query_traces(service, duration, filter?, limit?, errorsOnly?)`
- `get_anomaly_history(service, duration, method?)`
- `generate_postmortem(service, duration, format?)`

Existing tool surface is unchanged. Per-credential `OMCP_KEY_PRODUCTS`
allow-lists keep working — bind the new tools into your Products
explicitly if you want them visible to scoped consumers.

## New endpoints

- `POST /api/policy/dry-run-batch` — batch policy evaluation, returns matrix or CSV.
- `/scim/v2/*` — SCIM 2.0 Users + Groups + discovery (opt-in via `OMCP_SCIM_TOKEN`).

## New / changed CLI

- `omcp inspector-config` — emit an MCP Inspector config for the local gateway.
- `omcp-sdk-create-connector <name>` (from the new SDK package) — scaffold a connector skeleton.

## New CI surface

The repo adds the **airgapped** CI workflow that boots the demo
stack with iptables egress blocked. Forks should expect this job
to appear on every PR; it's mandatory for merge.

## Plugin SDK package

`@thotischner/observability-mcp-sdk` 3.0.0 is now the canonical
source for plugin authors. The in-tree `mcp-server/src/sdk/`
remains in sync via a CI parity check.

```bash
npm install @thotischner/observability-mcp-sdk
# Or scaffold a new connector:
npx @thotischner/observability-mcp-sdk create-connector my-connector
```

## Chart bumps

- `mcp-server` 2.0.0 → **3.0.0**
- Helm chart 1.0.0 → **2.0.0** (appVersion `3.0.0`)
- SDK package — first 3.0.0 publish

## Verifying the upgrade

```bash
# 1. /api/conformance still claims MCP 2025-11-25
curl -s http://localhost:3000/api/conformance | jq '.revisions'

# 2. Tool surface now includes the three new tools
TOKEN=any-non-empty-bearer  # anonymous-auth demo accepts anything
curl -sS http://localhost:3000/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | jq '.result.tools[].name'
# expect: list_sources, list_services, query_metrics, query_logs,
#         query_traces, get_service_health, detect_anomalies,
#         get_anomaly_history, generate_postmortem,
#         get_topology, get_blast_radius

# 3. Inspector quickstart still works
npx @thotischner/observability-mcp inspector-config | jq .
```

## Rollback

In-place downgrade to 2.x is supported. The new opt-in values
(`airgapped`, `anomalyHistory.*`, `OMCP_SCIM_*`,
`OMCP_ANOMALY_HISTORY_*`) are silently ignored by 2.x. On-disk
schemas (audit JSONL, products.yaml, sources.yaml, DCR store, the
new `scim.json`) are forward-compatible — a 2.x server reading a
3.0-written file ignores fields it doesn't know.

## After the upgrade

The v3.x incremental follow-ups live in
[CHANGELOG.md](https://github.com/ThoTischner/observability-mcp/blob/main/CHANGELOG.md) under "Deferred to v3.x
(incremental)". The next planned major (v4.x) is up for grabs —
[Issue tracker](https://github.com/ThoTischner/observability-mcp/issues)
and [Discussions](https://github.com/ThoTischner/observability-mcp/discussions)
are open.
