Hermes.Server.Registry.Adapter behaviour (hermes_mcp v0.9.1)

Behaviour for registry adapters in MCP servers.

This module defines the interface that registry implementations must follow to be pluggable into the Hermes MCP server architecture. It allows users to provide custom registry implementations (e.g., using Horde for cluster-wide distribution) while maintaining compatibility with the existing API.

Implementing a Custom Registry

To implement a custom registry adapter, create a module that implements all the callbacks defined in this behaviour:

defmodule MyApp.HordeRegistry do
  @behaviour Hermes.Server.Registry.Adapter

  def child_spec(opts) do
    %{
      id: __MODULE__,
      start: {Horde.Registry, :start_link, [
        [
          name: __MODULE__,
          keys: :unique,
          members: :auto
        ] ++ opts
      ]}
    }
  end

  def server(module) do
    {:via, Horde.Registry, {__MODULE__, {:server, module}}}
  end

  # ... implement other callbacks
end

Using a Custom Registry

You can configure a custom registry at multiple levels:

Hermes.Server.start_link(MyServer, :ok, transport: :stdio, registry: MyApp.HordeRegistry)

Default Implementation

The default implementation uses Elixir's built-in Registry module. See Hermes.Server.Registry for the reference implementation.

Summary

Callbacks

Returns a child specification for the registry.

Returns a name for a server process.

Returns a name for a server session process.

Returns a name for a supervisor process.

Returns a name for a transport process.

Gets the PID of a registered server.

Gets the PID of a server session process.

Gets the PID of a supervisor process.

Gets the PID of a transport process.

Callbacks

child_spec(opts)

@callback child_spec(opts :: keyword()) :: Supervisor.child_spec()

Returns a child specification for the registry.

This is used when starting the registry as part of a supervision tree. The implementation should return a valid child specification map or tuple.

server(module)

@callback server(module :: module()) :: GenServer.name()

Returns a name for a server process.

The returned value must be a valid GenServer name that can be passed to GenServer.start_link/3 and similar functions.

Parameters

  • module - The module implementing the server

server_session(server_module, session_id)

@callback server_session(server_module :: module(), session_id :: String.t()) ::
  GenServer.name()

Returns a name for a server session process.

Parameters

  • server_module - The module implementing the server
  • session_id - The unique session identifier

supervisor(kind, server_module)

@callback supervisor(kind :: atom(), server_module :: module()) :: GenServer.name()

Returns a name for a supervisor process.

Parameters

  • kind - The kind of supervisor (e.g., :supervisor, :session_supervisor)
  • server_module - The module implementing the server

transport(server_module, transport_type)

@callback transport(server_module :: module(), transport_type :: atom()) ::
  GenServer.name()

Returns a name for a transport process.

Parameters

  • server_module - The module implementing the server
  • transport_type - The type of transport (e.g., :stdio, :sse, :websocket)

whereis_server(server_module)

@callback whereis_server(server_module :: module()) :: pid() | nil

Gets the PID of a registered server.

Returns the PID if the server is registered, nil otherwise.

Parameters

  • server_module - The module implementing the server

whereis_server_session(server_module, session_id)

@callback whereis_server_session(server_module :: module(), session_id :: String.t()) ::
  pid() | nil

Gets the PID of a server session process.

Returns the PID if the session is registered, nil otherwise.

Parameters

  • server_module - The module implementing the server
  • session_id - The unique session identifier

whereis_supervisor(kind, server_module)

@callback whereis_supervisor(kind :: atom(), server_module :: module()) :: pid() | nil

Gets the PID of a supervisor process.

Returns the PID if the supervisor is registered, nil otherwise.

Parameters

  • kind - The kind of supervisor
  • server_module - The module implementing the server

whereis_transport(server_module, transport_type)

@callback whereis_transport(server_module :: module(), transport_type :: atom()) ::
  pid() | nil

Gets the PID of a transport process.

Returns the PID if the transport is registered, nil otherwise.

Parameters

  • server_module - The module implementing the server
  • transport_type - The type of transport