✅ Via :server_info router option — always emitted (one legacy revision — nothing to gate)
instructions field in init response
MAY
✅ Via :instructions router option
Out of scope:2024-11-05. That revision predates Streamable HTTP
and requires a split-endpoint HTTP+SSE transport that wymcp does not
implement. See Wymcp.ProtocolVersion for the supported set.
1.3 Transports
Feature
Spec requirement
wymcp status
Streamable HTTP (POST + optional SSE)
Defined
✅ POST + GET SSE via Transport.Stream
stdio
Defined
N/A (library is HTTP-focused)
Session management / Mcp-Session-Id header
SHOULD (HTTP)
✅ Full session lifecycle with idle timeout (the earlier sessionless fallback was removed)
SSE keepalive
SHOULD
✅ Configurable keepalive timer
Stream reconnection via Last-Event-Id
MAY
⚠️ Header read but not used for replay
1.4 Authorization
Feature
Spec requirement
wymcp status
OAuth 2.1 / Bearer token flow
SHOULD (HTTP)
⚠️ Wymcp.Auth behaviour with Bearer support; no OAuth discovery
These are requests the server sends to the client via the SSE channel. The
session's server-request round trip (Session.await_client_response/4) pushes a
JSON-RPC request via SSE, holds the caller, and unblocks it when the client POSTs
back a response. Plugs.Classify tags incoming responses so they bypass
validation and route to Methods.DeliverResponse.
3.1 Sampling (server asks client to run LLM)
Feature
Spec
wymcp status
sampling/createMessage
Client capability
✅ Context.sample/3 — blocks until client responds
Capability negotiation
Part of init
✅ Only advertised when client declares sampling
Model preferences (hints, priorities)
Part of request
✅ Passed through via opts
Tool use within sampling
Client declares sampling.tools
❌ Not implemented (client-side concern)
Multi-turn tool loop
Part of sampling
❌ Single-turn only
3.2 Elicitation (server asks client for user input)
Feature
Spec
wymcp status
elicitation/create — form mode
Client capability elicitation.form
✅ Context.elicit/4 — sends JSON Schema, blocks for response
Capability negotiation
Part of init
⚠️ See note below
mode field in request
Defaults to "form" if omitted
⚠️ See note below
Sensitive-info constraint
MUST NOT use form mode
⚠️ Not enforced or documented for tool authors
elicitation/create — URL mode
Client capability elicitation.url
❌ Deferred
notifications/elicitation/complete
Server → Client notification
❌ (needed for URL mode — carries elicitationId)
URLElicitationRequiredError (-32042)
Error response
❌ (structured: data.elicitations[] with mode, elicitationId, url, message)
Implementation notes (form mode):
Capability sub-keys not checked. The spec defines elicitation.form
and elicitation.url as distinct client sub-capabilities. Our
check_capability/2 only tests Map.has_key?(client_capabilities, "elicitation") — it does not verify the client declared form
specifically. Likewise, Initialize advertises "elicitation" => %{}
without declaring which modes the server supports. A spec-strict client
could reasonably interpret the empty map as "no modes supported."
mode field omitted from request.Context.elicit/4 builds params
as %{"message" => …, "requestedSchema" => …} without "mode" => "form". The spec says omitting mode defaults to "form" for backwards
compatibility, so this works today but is implicit. Adding the field
explicitly would be more robust.
Sensitive-information constraint. The spec states: "Servers MUST NOT
use form mode for sensitive information. URL mode MUST be used for
sensitive interactions like credentials." This is not enforced in code
(nor could it easily be), but should be documented as guidance for tool
authors using Context.elicit/4.
3.3 Roots (server asks client for filesystem boundaries)
Feature
Spec
Notes
roots/list
Client capability
❌ Not implemented
notifications/roots/list_changed
Client → Server
❌
4. Utilities (cross-cutting)
4.1 Ping
Feature
Spec
wymcp status
ping → {} response
MUST
✅ Methods.Ping
4.2 Progress Tracking
Feature
Spec
wymcp status
_meta.progressToken in requests
MAY
✅ Context.progress_token/1
notifications/progress with progress, total, message
MAY
✅ Context.report_progress/4
Progress must monotonically increase
MUST (if sent)
⚠️ Caller responsibility (not enforced)
4.3 Cancellation
Feature
Spec
wymcp status
notifications/cancelled with requestId + reason
MAY
✅ Methods.Cancelled
Receiver SHOULD stop work and return error -32800
SHOULD
⚠️ Tracked but no in-flight abort
4.4 Logging
Feature
Spec
wymcp status
logging/setLevel (client → server)
MAY
✅ Methods.LoggingSetLevel, stores level in session
_meta with io.modelcontextprotocol/model-immediate-response
Defined
❌
5. Summary: What wymcp has today
Implemented:
JSON-RPC 2.0 framing with message classification (request/notification/response)
Schema validation via JSV against the 2025-11-25 schema (priv/schema-2025-11-25.json)
Lifecycle: initialize with dynamic capability negotiation, notifications/initialized, ping
Version negotiation: always responds with latest supported version (counter-proposal ready)
Full session management: Mcp-Session-Id, GenServer-per-session, idle timeout, Registry lookup
SSE transport: Transport.Stream with keepalive, bidirectional messaging
Tools: tools/list, tools/call with outputSchema + structuredContent
Tool metadata: optional title/0 and annotations/0 callbacks on Wymcp.Tool
listChanged capability advertised; notifications/tools/list_changed sent on a change to the tool list tools/list would serve, and on stream attach when one is owed
Runtime tool registration/unregistration per session
Server callbacks: Wymcp.Server behaviour with init/2 and terminate/2
Context bridge: session assigns + conn.assigns merged into %Context{}
Auth behaviour with Bearer token support and WWW-Authenticate header
Cancellation: notifications/cancelled with request tracking
Sampling: Context.sample/3 — server asks client's LLM mid-tool-execution
Elicitation: Context.elicit/4 — server asks human for structured form input (see §3.2 notes for spec gaps)
Logging: logging/setLevel method + Context.log/3 with level filtering
Telemetry events for session lifecycle
6. Missing:
Tier 1: Low effort, high value (polish what exists)
Pagination on tools/list
In-flight cancellation — actually abort running tool tasks on notifications/cancelled
Stream reconnection replay — use Last-Event-Id to replay missed events
Elicitation spec alignment — add mode field to requests, check elicitation.form sub-capability, advertise supported modes in server capabilities (see §3.2 notes)
Tier 2: Medium effort, high value (new server features)