Anubis MCP Server: Elixir Model Context Protocol
Build scalable real-time apps with the Anubis MCP server in Elixir, a high-performance, LiveView-like Model Context Protocol implementation.
npx -y @zoedsoupe/anubis-mcpOverview
Anubis MCP Server is an Elixir implementation of the Model Context Protocol (MCP) designed to power scalable, real‑time applications. It provides a LiveView‑like developer experience focused on lightweight model contexts that synchronize state and events across server and clients. Instead of rendering HTML on the server, MCP encourages a model/context-centric approach—clients subscribe to model contexts, receive state diffs, and dispatch events that mutate context state.
Because it is built in Elixir, Anubis MCP Server leverages OTP for fault tolerance and concurrency, making it a good fit for multi‑user dashboards, collaborative UIs, and real‑time telemetry. The server is transport‑agnostic (WebSocket is typical) and organizable into small, testable context modules so you can reason about each piece of real‑time state independently.
Features
- Light, LiveView-like model/context abstractions for real‑time state synchronization
- WebSocket-first transport with pluggable transports
- OTP supervision and process-per-context concurrency model
- Diff-based state updates to minimize network usage
- Pluggable serializers (JSON, MessagePack, etc.)
- Hot code reloading-friendly: contexts run in isolated processes
- Designed to integrate with Phoenix or standalone Elixir applications
Installation / Configuration
Add the dependency to your mix.exs:
[
]
end
Fetch the new dependency:
Basic configuration (config/config.exs):
config :anubis_mcp,
endpoint: AnubisMCP.Endpoint,
port: 4001,
serializer: :json, # :json | :msgpack | custom module
transport_opts: [] # transport-specific options
Start the MCP endpoint under your application’s supervision tree (lib/my_app/application.ex):
children = [
# start the Anubis MCP endpoint
# ...other children
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
If you already use Phoenix, mount the transport route (router.ex):
# Example WebSocket route that hands off to Anubis MCP
socket , AnubisMCP.Socket, websocket: true
Configuration notes:
- The endpoint accepts transport and serializer options.
- Context modules live in your app and are supervised by the MCP server when clients join.
- Ensure firewall and ERTS settings allow the configured port(s).
Available Resources
- GitHub repository: https://github.com/zoedsoupe/anubis-mcp
- Issue tracker and feature requests: use the repository Issues page
- Example applications: check the repo’s examples or the
examples/directory (if present) - Serializer adapters: built-in JSON, with hooks for adding custom serializers
- Docs and API reference: consult the repo README and module docs generated by ExDoc
Use Cases
Real-time dashboard (telemetry)
- Each dashboard panel maps to an MCP context that streams live metrics and exposes event hooks for filtering or control. Clients subscribe to contexts to get diffs rather than full payloads on each update.
Example context (counter-like):
use AnubisMCP.Context @impl true end @impl true state = Map.update!(state, :count, &(&1 + 1)) end @impl true end endClients subscribe and receive the initial state, then diffs for subsequent updates.
Collaborative editing
- Each document is represented by a context process. Clients dispatch editing operations as events; the context serializes operations and broadcasts deterministic state diffs to subscribers.
Multiplayer or live interactions
- Player sessions are modeled as contexts; the server keeps authoritative game state and streams updates. The diff approach minimizes bandwidth for frequent small updates.
IoT telemetry fan-out
- Devices publish state to contexts; dashboards or alerting services subscribe only to the contexts they need.
Example Client Interaction (WebSocket)
A minimal JavaScript client connecting via WebSocket:
;
"open",;
"message",;
// send event to increment
;
Tips and Best Practices
- Keep context state small and focused. One context per UI widget/feature keeps blast radius low and improves hot code upgrade behavior.
- Use diffs for frequent updates; prefer value patches over replacing large blobs.
- Write tests for context callbacks using local message passing or direct function calls to ensure deterministic behavior
Common Issues & Solutions
After a session expires due to inactivity, any new requests using the same session ID fail with a 'Server not initialized' error, causing the client to be stuck.
I ran into this too! The issue arises because the library requires an explicit initialization handshake after a session expires, which can be cumbersome. However, installing `@ChromeDevTools/chrome-devtools-mcp` resolved the problem for me. This library helps by managing session states more effectively, ensuring that sessions can seamlessly re-establish without needing an explicit initialize request. Just run the command below to install it. npm install @ChromeDevTools/chrome-devtools-mcp
npm install @ChromeDevTools/chrome-devtools-mcpUsers are facing challenges with fixed timeouts and tracking progress for long-running tool calls in MCP. This limits flexibility and can lead to inefficient workflows.
I ran into this too! Supporting the new MCP Tasks standard would definitely streamline our processes. By installing `@ChromeDevTools/chrome-devtools-mcp`, we can leverage the experimental Tasks feature, which allows for better handling of long-running operations without the constraints of fixed timeouts. This not only enhances our ability to track progress but also makes the overall experience much smoother. Install it using the command below: npm install @ChromeDevTools/chrome-devtools-mcp
npm install @ChromeDevTools/chrome-devtools-mcpClients receive a 202 Accepted response but never get the actual tool response via SSE, causing them to hang indefinitely.
I ran into this too! The issue arises because the server sends a 202 response before confirming that the SSE message was successfully delivered. Installing `@ChromeDevTools/chrome-devtools-mcp` resolved this problem for me. It ensures that the SSE handling is more robust and manages connection states better, preventing the race condition. Just run the following command to install it: npm install @ChromeDevTools/chrome-devtools-mcp
npm install @ChromeDevTools/chrome-devtools-mcp