Noizu.MCP.Peer (Noizu MCP v0.1.1)

Copy Markdown View Source

Sans-IO MCP session core, shared by server sessions and client connections.

Both ends of MCP are symmetric JSON-RPC peers; this module models one end as a pure state machine. The owning process feeds decoded Noizu.MCP.JsonRpc messages through ingest/2 and interprets the returned effectsPeer itself never touches a socket or process.

Effects:

  • {:send, message} — encode and write message to the transport
  • {:dispatch, method, id, params} — an inbound request for the feature layer
  • {:notice, method, params} — an inbound notification for the feature layer
  • {:resolve, tag, id, result} — an outbound request completed (result :: {:ok, map} | {:error, Noizu.MCP.Error.t()})
  • {:cancel_in, id, reason} — the remote cancelled a request we are processing
  • {:progress, tag, id, params} — progress for one of our outbound requests
  • {:ready, remote_info} — handshake complete, normal traffic may flow
  • {:initialize_result, result} — (client) the initialize response arrived; follow with initialized/1
  • {:initialize_failed, reason} — (client) the server negotiated an unsupported version

Summary

Functions

Abandon an outbound request and build the notifications/cancelled to send. Any late response for it is silently ignored. Returns the abandoned request's tag (or nil if the id was unknown).

Process one decoded inbound message; returns {peer, effects}.

(client) Build the initialize request.

(client) Complete the handshake: build notifications/initialized.

Build a new peer.

Build a notification struct (stateless helper).

Issue an outbound request. Returns the assigned id and the request struct to send. opts: :tag (returned in the :resolve effect), :progress_token (adds _meta.progressToken and routes inbound progress notifications).

Respond to an inbound request. Returns :drop when the request was cancelled by the remote (the spec forbids responding after cancellation).

Respond to an inbound request with a protocol error. See respond/3.

Types

effect()

@type effect() :: tuple()

phase()

@type phase() :: :handshake | :initializing | :ready | :closing

role()

@type role() :: :server | :client

t()

@type t() :: %Noizu.MCP.Peer{
  cancelled_in: MapSet.t(),
  instructions: String.t() | nil,
  local_capabilities: map(),
  local_info: Noizu.MCP.Types.Implementation.t(),
  next_id: pos_integer(),
  pending_in: %{optional(Noizu.MCP.JsonRpc.id()) => String.t()},
  pending_out: %{optional(Noizu.MCP.JsonRpc.id()) => map()},
  phase: phase(),
  progress_index: %{optional(term()) => Noizu.MCP.JsonRpc.id()},
  protocol_version: String.t() | nil,
  remote_capabilities: map() | nil,
  remote_info: Noizu.MCP.Types.Implementation.t() | nil,
  role: role()
}

tag()

@type tag() :: term()

Functions

cancel_out(peer, id, reason \\ nil)

@spec cancel_out(t(), Noizu.MCP.JsonRpc.id(), String.t() | nil) ::
  {t(), Noizu.MCP.JsonRpc.Notification.t() | nil, tag() | nil}

Abandon an outbound request and build the notifications/cancelled to send. Any late response for it is silently ignored. Returns the abandoned request's tag (or nil if the id was unknown).

ingest(peer, message)

@spec ingest(t(), Noizu.MCP.JsonRpc.message()) :: {t(), [effect()]}

Process one decoded inbound message; returns {peer, effects}.

init_request(peer)

@spec init_request(t()) :: {t(), Noizu.MCP.JsonRpc.Request.t()}

(client) Build the initialize request.

initialized(peer)

@spec initialized(t()) :: {t(), Noizu.MCP.JsonRpc.Notification.t(), [effect()]}

(client) Complete the handshake: build notifications/initialized.

new(opts)

@spec new(keyword()) :: t()

Build a new peer.

Options: :role (:server | :client, required), :info (Noizu.MCP.Types.Implementation, required), :capabilities (wire-format map), :instructions (server only).

notification(method, params \\ nil)

@spec notification(String.t(), map() | nil) :: Noizu.MCP.JsonRpc.Notification.t()

Build a notification struct (stateless helper).

request(peer, method, params, opts \\ [])

@spec request(t(), String.t(), map() | nil, keyword()) ::
  {t(), Noizu.MCP.JsonRpc.id(), Noizu.MCP.JsonRpc.Request.t()}

Issue an outbound request. Returns the assigned id and the request struct to send. opts: :tag (returned in the :resolve effect), :progress_token (adds _meta.progressToken and routes inbound progress notifications).

respond(peer, id, result)

@spec respond(t(), Noizu.MCP.JsonRpc.id(), map()) ::
  {t(), {:ok, Noizu.MCP.JsonRpc.Response.t()} | :drop}

Respond to an inbound request. Returns :drop when the request was cancelled by the remote (the spec forbids responding after cancellation).

respond_error(peer, id, error)

@spec respond_error(t(), Noizu.MCP.JsonRpc.id(), Noizu.MCP.Error.t()) ::
  {t(), {:ok, Noizu.MCP.JsonRpc.ErrorResponse.t()} | :drop}

Respond to an inbound request with a protocol error. See respond/3.