packages feed

mcp-server-0.2.0.1: CHANGELOG.md

# Revision history for mcp-server

## 0.2.0.1 - 2026-08-01

(Supersedes 0.2.0.0, which is **deprecated on Hackage**: it was published
hours before this line landed and was never adopted, so rather than
burning a major version on a release nobody used, 0.2.0.1 replaces it —
including changes that would ordinarily demand a major bump. Anyone
explicitly pinning the deprecated 0.2.0.0 should move here. The unreleased
0.2.1.0 line below is folded in as well.)

* Request cancellation (ADR 0008): in-flight requests can now actually be
  interrupted, per the spec's "stop work as soon as practical, send nothing
  further for that request". On stdio every request runs in its own task
  and `notifications/cancelled` cancels the referenced one (unknown or
  completed ids are ignored); on HTTP, closing an SSE response stream
  cancels the running handler (detected within one keep-alive interval,
  now 5s). Single-JSON HTTP responses only detect a disconnect at the
  final write, so clients wanting cancellable calls should opt into
  streaming via a `progressToken`. Cancellation is delivered as an
  asynchronous exception, so handlers acquiring resources should use
  `bracket` — documented in the README. BREAKING (behavioral): stdio
  requests are now served concurrently rather than strictly
  sequentially — handlers touching shared mutable state must
  synchronize, as was already required with the HTTP transport. New
  dependency: `async`.
* Progress notifications and per-request SSE (ADR 0007): handlers can
  call `reportProgress` and `logToClient` on the `ClientContext` — both
  safe unconditionally. `reportProgress` emits `notifications/progress`
  only when the request carried a `progressToken`; `logToClient` emits
  `notifications/message` only when the request declared
  `io.modelcontextprotocol/logLevel` (per spec MUST NOT otherwise),
  filtered to the declared threshold (new `LogLevel` type, RFC 5424
  ordering). On stdio the notifications interleave before the response;
  on HTTP a request that opted in is answered with an SSE response
  stream (notifications, then the final response), while other requests
  keep the single-JSON response. BREAKING: `ClientContext` carries the
  two actions and loses its `Show`/`Eq` instances;
  `MCP.Server.Handlers.handleMcpMessage` takes the transport's
  notification sink.
* Definition metadata (ADR 0006):
    * `ToolAnnotations` — `readOnlyHint`/`destructiveHint`/`idempotentHint`/
      `openWorldHint` behavioral hints (2025-03-26+) plus a title, all unset
      by default (`defaultToolAnnotations`), carried on `ToolDefinition` and
      driving client permission UX.
    * `Icon` lists (2025-11-25+) on tool, prompt, resource and
      resource-template definitions.
    * Content `Annotations` (`audience`/`priority`/`lastModified`,
      2025-03-26+) attached via the new `ContentAnnotated` wrapper, whose
      annotations merge into the inner block's JSON (and parse back out).
* New `WithOptions` derivations for all five derive families, taking
  per-constructor `DefinitionOptions` (description, title, icons, tool
  annotations, and **constructor-scoped field descriptions** — two
  constructors can now describe a same-named field differently, fixing the
  global-namespace wart of the flat description list, which remains
  supported unchanged).
* BREAKING: `ToolDefinition`, `PromptDefinition`, `ResourceDefinition` and
  `ResourceTemplateDefinition` gain fields, and `Content` gains the
  `ContentAnnotated` constructor. New smart constructors
  (`mkToolDefinition`, `mkPromptDefinition`, `mkResourceDefinition`,
  `mkResourceTemplateDefinition`) build definitions from required fields
  only — construct through them and record-update, so future optional
  fields stop breaking your code. All new JSON fields are omitted when
  unset, so wire output for existing servers is unchanged.

* Derived output schemas and structured content (ADR 0005): the new
  `deriveToolHandlerWithOutput` (and `...WithOutputDescription`) take a
  result record type, derive the tools' `outputSchema` from it (same field
  rules as input derivation: primitives, `Maybe`, lists, all-nullary
  enums, nested records), and serialize the handler's typed values into
  `structuredContent` — the generated serializer mirrors the generated
  schema, so the two cannot drift. Handlers return the new
  `ToolOutput` type: `ToolOutput` (structured value; the JSON is also
  returned as a text content block per the spec's recommendation),
  `ToolOutputWith` (custom content blocks), `ToolOutputError` (isError),
  or `ToolOutputRaw` (plain `ToolResult` escape hatch). Existing
  `ToToolResult` handlers are untouched. The conformance corpus gains an
  `echo_structured` reference tool with cases in both eras.

* The HTTP transport's WAI application is now exported (`mcpApplication`,
  re-exported from `MCP.Server`), so the MCP endpoint can be embedded into
  an existing WAI stack — your own Warp settings, TLS, middleware or router
  — instead of `transportRunHttp` running its own server. `httpPort`/
  `httpHost` are ignored when embedding; everything else (endpoint path,
  Origin validation, bearer auth, `subscriptions/listen` streaming) applies
  as usual.
* The golden wire fixtures are now a self-describing, API-agnostic
  conformance corpus: each case under `test/golden/` is a
  `.request.json`/`.response.json` pair on disk, enumerated by
  `manifest.json`, with the reference server documented in
  `test/golden/README.md`. Other MCP implementations can replay the
  requests and diff the responses without touching any Haskell; the
  fixtures themselves are unchanged.

## 0.2.0.0 - 2026-07-31

A major overhaul of the handler API. The headline changes: the handler
boundary is no longer stringly typed, and the server is dual-era — it speaks
both the legacy initialize-handshake revisions and the stateless
`2026-07-28` revision.

### Dual-era protocol support (2026-07-28)

* Requests that declare a protocol revision in their params `_meta`
  (`io.modelcontextprotocol/protocolVersion`) are served statelessly with
  the modern result envelope: `resultType: "complete"`, the server identity
  in result `_meta`, and — on `tools/list`, `prompts/list`,
  `resources/list`, `resources/read` and `server/discover` — the required
  `ttlMs`/`cacheScope` fields (configurable via `CacheHints` on the
  transport configs; default: no caching, private). Requests without modern
  `_meta` are served byte-identically to before under the revision
  negotiated by `initialize`.
* New `server/discover` method (mandatory in 2026-07-28, and the
  backwards-compatibility probe): supported revisions of both eras,
  handler-gated capabilities, server identity and instructions.
* Declaring an unsupported revision returns
  `UnsupportedProtocolVersionError` (`-32022`) listing the supported set.
* A legacy client proposing `2026-07-28` via `initialize` negotiates down
  to `2025-11-25`: an initializing client is legacy by definition.
* Handlers can read the declared revision, client info and client
  capabilities from the `ClientContext`
  (`clientProtocolVersion`/`clientInfo`/`clientCapabilities`); the new
  `anonymousContext` builds an empty context.
* HTTP: modern requests get the 2026-07-28 request-metadata validation —
  the `MCP-Protocol-Version` header must match the body's declared
  revision, `Mcp-Method` must match the body method, and `Mcp-Name` must
  match `params.name`/`params.uri` for `tools/call`/`resources/read`/
  `prompts/get` (with `=?base64?…?=` sentinel decoding); violations return
  `400` with `HeaderMismatch` (`-32020`). Unknown methods return HTTP 404
  and unsupported revisions HTTP 400, so era-probing clients can
  distinguish them. Legacy requests keep the relaxed pre-2026 rules.

### Change notifications and subscriptions/listen

* New `MCP.Server.Notifications`: create an `McpNotifier` with
  `newMcpNotifier`, hand its `NotificationSource` to a transport
  (`stdioNotifications`/`httpNotifications`), and call
  `notifyToolsListChanged`/`notifyPromptsListChanged`/
  `notifyResourcesListChanged`/`notifyResourceUpdated` when things change.
* `subscriptions/listen` (2026-07-28) is served on both transports: the
  mandatory acknowledgment comes first with the honored filter, every
  message is tagged with the subscription id, only opted-into types are
  delivered, and streams end gracefully (closure responses at stdio EOF;
  closing the SSE stream cancels over HTTP, `notifications/cancelled` over
  stdio). HTTP streams send periodic keep-alive comments and
  `X-Accel-Buffering: no`.
* Legacy stdio clients receive spontaneous untagged notifications after
  `initialize`. Capabilities are era- and transport-aware: `listChanged` is
  advertised only where delivery is possible (stdio legacy push, or
  modern `subscriptions/listen`), and `subscribe` only to modern clients.
* `defaultHttpConfig` is now re-exported from `MCP.Server`.

### Resource templates and completions

* Record constructors of a resource type now derive as resource /templates/
  (`UserProfile { userId :: Text }` →
  `resource://user_profile/{userId}`): the derived read handler matches
  template URIs, percent-decodes the path segments, and parses them into
  the constructor's (typed) fields. `deriveResourceTemplates` derives the
  `resources/templates/list` handler advertising them; the method carries
  the modern cacheability envelope.
* New `completions` handler slot serving `completion/complete` for prompt
  arguments and resource-template parameters (`CompletionRef`,
  `CompletionResult`, capped at 100 values per the spec). The
  `completions` capability is advertised automatically.
* `McpServerHandlers` gains `resourceTemplates` and `completions` fields;
  the new `noHandlers` value lets you construct handler sets by record
  update so future fields don't break your code.

### Typed tool arguments and results (BREAKING)

* Tool arguments arrive as full JSON values (`Map Text Value`). The Template
  Haskell derivation decodes records recursively and now supports **list
  fields**, **enumeration fields** (all-nullary data types, wired as string
  enums), and **nested record fields** in addition to the primitives.
  Primitive parsing is lenient: native JSON types or their string
  representations are both accepted (many clients send numbers/booleans as
  strings). Prompt arguments remain string-valued per the MCP specification.
* `inputSchema` is generated as a real JSON Schema (`Schema`/`SchemaType`
  ADT with `enum`, `items` and nested `object`s), replacing the flat
  `InputSchemaDefinition*` types that silently typed every non-primitive
  field as a string.
* Tool handlers produce a `ToolResult`: multiple content blocks,
  `structuredContent`, `_meta`, and `isError`. Tool *execution* failures
  should be reported via `isError` (see `toolError`) so the model can see
  them — per spec — instead of surfacing as JSON-RPC protocol errors.
  The `ToToolResult` class keeps simple handlers simple: returning
  `Content` or `Text` still works unchanged.
* Prompt handlers produce a `PromptResult` (optional description plus a
  multi-message conversation with user/assistant roles) via the analogous
  `ToPromptResult` class.
* `Content` gains `audio` and `resource_link` variants; embedded resources
  now carry their full contents as the spec requires.
* `ToolDefinition` gains `outputSchema`; `tools/call` responses carry
  `structuredContent`.
* Handler types are fixed to `IO` — the monad parameter was unusable
  through the public API (both transports required `IO`).

### Transport fixes

* stdio: a blank line on stdin no longer terminates the server, EOF shuts
  down cleanly instead of crashing, and malformed input is answered with
  proper JSON-RPC error responses (`-32700`/`-32600`, `id: null`).
* stdio: raw request bodies are no longer logged to stderr by default
  (tool arguments may carry sensitive data) — only message summaries.
  `runMcpServerStdioWithConfig` with `stdioVerbose = True` restores full
  body logging.
* JSON-RPC: messages are classified by shape (method/id presence) instead
  of parse-fallthrough, so a request with a malformed `id` is answered
  with an error rather than silently dropped as a notification. Request
  ids must be integral.
* HTTP: new `httpAllowedOrigins` policy on `HttpConfig` (Origin
  validation / DNS-rebinding protection, a spec MUST); accepted
  notifications return `202` with no body; malformed bodies get JSON-RPC
  error responses; the `Access-Control-Allow-Origin` header is set
  consistently on every response and echoes the validated origin (with
  `Vary: Origin`) when a policy is configured.
* HTTP (BREAKING): the non-spec GET "discovery" endpoint is removed — the
  MCP endpoint now answers GET with `405 Method Not Allowed`, matching the
  spec (no revision defines a GET discovery response, and `2026-07-28`
  requires 405 here).
* Integer tool arguments bound the scientific-notation exponent (1024, the
  same bound aeson uses) so a tiny payload like `1e1000000000` cannot force
  allocation of a gigabyte-sized `Integer`.

## 0.1.0.21 - 2026-07-31

* **BREAKING**: every handler (prompt/resource/tool; list and get/read/call)
  now receives a `ClientContext` as its first argument, so a server can behave
  differently depending on who is calling. On stdio the context is anonymous;
  on HTTP it carries the request's bearer token and the principal returned by
  the authorization callback.
* **BREAKING**: `HttpConfig` gains an `httpAuthorize` field — an optional
  callback that validates the presented `Authorization: Bearer` token and
  returns an application-defined principal (`Nothing` rejects with 401). As it
  now holds a function, `HttpConfig` no longer derives `Show`/`Eq`.
* HTTP transport: accept requests without an `MCP-Protocol-Version` header
  (the spec says to assume `2025-03-26`), exempt `initialize` from the header
  check (it negotiates its version in the body), and keep rejecting a present
  but unsupported header with 400. Previously every request without the header
  was rejected, locking out pre-`2025-06-18` clients.
* `initialize` now advertises only the capabilities that actually have
  handlers, so strict clients no longer drop the server when e.g.
  `prompts/list` answers "not supported".
* CORS: preflight `OPTIONS` requests are exempt from authorization (browsers
  send no credentials on preflight) and `Authorization` is included in
  `Access-Control-Allow-Headers`.
* `http-simple-example` is now built with `-threaded`, which Warp requires;
  previously every request crashed with a `TimerManager` error.

## 0.1.0.20 - 2026-07-31

* Fix protocol version negotiation: echo back any compatible revision the client
  proposes (`2024-11-05`, `2025-03-26`, `2025-06-18`, `2025-11-25`) instead of
  always responding with the server's own version. Fixes clients (e.g. Claude
  Code) that disconnect when they receive a different version than requested.
* Apply the same negotiation to the HTTP transport's `MCP-Protocol-Version`
  header check, which previously rejected anything other than `2025-06-18`.
* Default/fallback advertised version bumped to `2025-11-25`.

## 0.1.0.19 - ???

* Improve handler code generated by TemplateHaskell functions in `MCP.Server.Derive`:
    * Don't repeat `Map.fromList` for each argument in map lookup
    * Properly handle argument parse errors (Return `InvalidParams` error instead of crashing mcp server with `error`)

## 0.1.0.18 - 2026-02-09

* Switch default-language to GHC2021 to support broader range of GHC versions (9.6 - 9.12)

## 0.1.0.17 -- 2026-01-28

* Implement protocol version negotiation according to spec
* Remove unused dependencies, fix GHC warnings
* Add tested-with and haskell-ci generated GitHub Actions config

## 0.1.0.16 -- 2026-01-19

* Bump template-haskell dependency upper bound

## 0.1.0.15 -- 2025-08-13

* Update to MCP spec 2025-06-18

## 0.1.0.14 -- 2025-06-26

* Bump version bounds before adding to Stackage
* Remove support for JSON-RPC batching

## 0.1.0.13 -- 2025-06-17

* Better handling of UTF-8 in logs

## 0.1.0.12 -- 2025-06-17

* Fix unicode handling
* Refactor transports to remove unneeded functions
* Add unicode handling tests

## 0.1.0.11 -- 2025-06-17

* Refactor transports and add HTTP streaming support
* Add `MCP.Server.Handlers` module
* Add `MCP.Server.Transport.Http` and `MCP.Server.Transport.Stdio` modules

## 0.1.0.10 -- 2025-06-13

* Fix resources handling

## 0.1.0.9 -- 2025-06-13

* Bump versions of dependencies
* Port tests to hspec

## 0.1.0.8 -- 2025-06-12

* Support for nestable data types

## 0.1.0.7 -- 2025-06-09

* Documentation updates

## 0.1.0.6 -- 2025-06-09

* Remove pagination support

## 0.1.0.5 -- 2025-06-09

* Add descriptions to constructors and fields

## 0.1.0.4 -- 2025-06-09

* Clean up build configuration

## 0.1.0.3 -- 2025-06-09

* Refactor example modules
* Fix JSON to Haskell type conversion

## 0.1.0.0 -- 2025-06-05

* First version. Released on an unsuspecting world.