Packages
Model Context Protocol (MCP) implementation in Elixir with Phoenix integration
Retired package: Release invalid - wrong usage of Mix.env on runtime function prevents application to start
Current section
Files
Jump to
Current section
Files
lib/hermes/server/registry.ex
defmodule Hermes.Server.Registry do
@moduledoc """
Registry for MCP server and transport processes.
This module provides a safe way to manage process names without creating
atoms dynamically at runtime. It uses a via tuple pattern with Registry.
## Usage
# Register a server process
{:ok, _pid} = GenServer.start_link(MyServer, arg, name: Registry.server(MyModule))
# Register a transport process
{:ok, _pid} = GenServer.start_link(Transport, arg, name: Registry.transport(MyModule, :stdio))
# Look up a process
GenServer.call(Registry.server(MyModule), :ping)
"""
def child_spec(_) do
Registry.child_spec(keys: :unique, name: __MODULE__)
end
@doc """
Returns a via tuple for naming a server process.
"""
@spec server(server_module :: module()) :: GenServer.name()
def server(module) do
{:via, Registry, {__MODULE__, {:server, module}}}
end
@doc """
Returns a via tuple for naming a server session process.
"""
@spec server_session(server_module :: module(), session_id :: String.t()) :: GenServer.name()
def server_session(server, session_id) do
{:via, Registry, {__MODULE__, {:session, server, session_id}}}
end
@doc """
Returns a via tuple for naming a transport process.
"""
@spec transport(server_module :: module(), transport_type :: atom()) :: GenServer.name()
def transport(module, type) when is_atom(module) do
{:via, Registry, {__MODULE__, {:transport, module, type}}}
end
@doc """
Returns a via tuple for naming a supervisor process.
"""
@spec supervisor(kind :: atom(), server_module :: module()) :: GenServer.name()
def supervisor(kind \\ :supervisor, module) do
{:via, Registry, {__MODULE__, {kind, module}}}
end
@doc """
Gets the PID of a session-specific server.
"""
@spec whereis_server_session(server_module :: module(), session_id :: String.t()) :: pid | nil
def whereis_server_session(module, session_id) do
case Registry.lookup(__MODULE__, {:session, module, session_id}) do
[{pid, _}] -> pid
[] -> nil
end
end
@doc """
Gets the PID of a supervisor process.
"""
@spec whereis_supervisor(atom(), module()) :: pid() | nil
def whereis_supervisor(server, kind \\ :supervisor) when is_atom(server) do
case Registry.lookup(__MODULE__, {kind, server}) do
[{pid, _}] -> pid
[] -> nil
end
end
@doc """
Gets the PID of a registered server.
"""
@spec whereis_server(module()) :: pid | nil
def whereis_server(module) when is_atom(module) do
case Registry.lookup(__MODULE__, {:server, module}) do
[{pid, _}] -> pid
[] -> nil
end
end
@doc """
Gets the PID of a registered transport.
"""
@spec whereis_transport(module(), atom()) :: pid | nil
def whereis_transport(module, type) when is_atom(module) and is_atom(type) do
case Registry.lookup(__MODULE__, {:transport, module, type}) do
[{pid, _}] -> pid
[] -> nil
end
end
end