---
summary: "mcp-ts-core ^0.9.1: server instructions, schema portability lint, mcp_tool_scopes claim; skill and script syncs."
breaking: false
security: false
---

# 0.4.4 — 2026-05-16

## Changed

- Upgraded `@cyanheads/mcp-ts-core` `^0.8.19 → ^0.9.1`. Notable consumer-facing additions adopted in this release:
  - **`instructions` field on `createApp()`** (framework [#91](https://github.com/cyanheads/mcp-ts-core/issues/91)) — server-level usage hints surfaced to MCP clients via the `tools/list` capabilities envelope. This server now ships a one-paragraph orientation covering tool prefix, ID conventions (H/S/P for candidates, C for committees), and cycle semantics.
  - **Cross-vendor schema portability lint family** (framework [#132](https://github.com/cyanheads/mcp-ts-core/issues/132)) — new `schema-format-portability`, `schema-anyof-needs-type`, `schema-no-discriminator-keyword` (default-on) plus `schema-no-defs`, `schema-dialect-tag` (opt-in via `MCP_LINT_PORTABILITY=strict`). Catches schemas that pass `schema-serializable` but break at OpenAI's tool validator or Gemini's API. Surface passes default rules.
  - **`mcp_tool_scopes` claim union + `MCP_AUTH_DISABLE_SCOPE_CHECKS` bypass** (framework [#128](https://github.com/cyanheads/mcp-ts-core/issues/128)) — `ctx.auth.scopes` now unions `scp`, `scope`, and `mcp_tool_scopes`, letting OIDC providers that can't inject scopes into `scope` (Authentik, Keycloak < 26.5, Zitadel) supply per-tool scopes via a custom claim. The bypass flag exists for managed services where no custom claim is configurable.
  - **`Context.notifyPromptListChanged` / `notifyToolListChanged`** (framework 0.9.1) — handlers can now signal client-side reload for dynamically-disabled tools.
- **`devcheck` outdated-deps parser** now reads markdown-style `bun outdated` output correctly. Previous logic split on `|` and took index `[0]` — but markdown rows start with a leading `|`, so index `[0]` was an empty string and every package was treated as the "Package" header (silent allowlist bypass). Fixed to take index `[1]` and strip `(dev|peer|prod|optional)` workspace markers before allowlist comparison.
- **`scripts/build-changelog.ts` summary cap raised** `250 → 350` chars, matching the framework's relaxed limit.
- DevDep patches: `@biomejs/biome ^2.4.14 → ^2.4.15`, `@types/node ^25.6.2 → ^25.8.0`, `vitest ^4.1.5 → ^4.1.6`.

## Docs

- Synced project skills against framework 0.9.x — `api-linter` documents the five new portability rules; `api-auth` documents the `mcp_tool_scopes` claim and OIDC operator setup; `add-tool` documents mutator response design (return raw pre/post observable state, not synthetic verdicts) plus the new "unit-bearing numeric field names" checklist item; `tool-defs-analysis` adds the matching audit category.
- `CLAUDE.md` checklist: added portability guidance (avoid non-portable `format` emitters — use `z.string()` with the constraint in `.describe()`), Zod literal-union exemption note for `describe-on-fields`, and three OpenFEC-specific items for sparse upstream payloads.
- `README.md`: removed stale `dev:stdio`/`dev:http` watch-mode references (the framework dropped these scripts in `^0.8.6`); aligned Bun prereq with the `engines` constraint (≥1.3.0); OTEL env-var row now links to the framework telemetry docs.
