packages feed

mcp-server-0.2.0.0: CHANGELOG.md

# Revision history for mcp-server

## 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.