Elixir MCP Server
Okay, here's an example of how you might implement a simplified MCP (Meta-Control Protocol) server using Elixir and Server-Sent Events (SSE) for transport. This is a basic illustration and would need significant expansion for a real-world application. **Conceptual Overview** * **MCP (Meta-Control Protocol):** A protocol for managing and controlling distributed systems. In this simplified example, we'll assume MCP commands are simple text-based instructions. * **SSE (Server-Sent Events):** A unidirectional protocol where the server pushes updates to the client over a single HTTP connection. Ideal for real-time updates and notifications. * **Elixir:** A functional, concurrent language built on the Erlang VM, well-suited for building robust and scalable servers. **Code Example (Elixir with Phoenix Framework)** This example uses the Phoenix framework to handle HTTP requests and SSE. ```elixir # mix.exs (Project dependencies) defmodule McpSseExample.MixProject do use Mix.Project def project do [ app: :mcp_sse_example, version: "0.1.0", elixir: "~> 1.14", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps() ] end # Configuration for the OTP application. # # Type `mix help compile.app` for more information. def application do [ mod: {McpSseExample.Application, []}, extra_applications: [:logger, :runtime_tools] ] end # Specifies which paths to compile per environment. defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] # Specifies your project dependencies. # # Type `mix help deps` for examples and options. defp deps do [ {:phoenix, "~> 1.7.0"}, {:phoenix_html, "~> 3.3"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 0.18"}, {:floki, ">= 0.30.0", only: :test}, {:esbuild, "~> 0.7", runtime: Mix.env() == :dev}, {:telemetry_metrics, "~> 0.6"}, {:telemetry_poller, "~> 1.0"}, {:gettext, "~> 0.20"}, {:jason, "~> 1.2"}, {:plug_cowboy, "~> 2.5"} ] end # Aliases are shortcuts for tasks. defp aliases do [ setup: ["deps.get", "ecto.setup"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "assets.deploy": ["esbuild default --minify", "phx.digest"] ] end end ``` ```elixir # lib/mcp_sse_example_web/router.ex defmodule McpSseExampleWeb.Router do use McpSseExampleWeb, :router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_live_flash plug :put_root_layout, {McpSseExampleWeb.LayoutView, :root} plug :protect_from_forgery plug :put_secure_browser_headers end pipeline :api do plug :accepts, ["json"] end scope "/", McpSseExampleWeb do pipe_through :browser get "/", PageController, :index end # SSE endpoint scope "/mcp", McpSseExampleWeb do pipe_through :api get "/events", McpController, :events end # Other routes may belong here end ``` ```elixir # lib/mcp_sse_example_web/controllers/mcp_controller.ex defmodule McpSseExampleWeb.McpController do use McpSseExampleWeb, :controller require Logger def events(conn, _params) do conn |> put_resp_content_type("text/event-stream") |> send_resp(200, stream_mcp_events()) end defp stream_mcp_events() do # This is a simplified example. In a real application, you would # likely have a GenServer or other process that generates MCP events. # This example just sends a few dummy events. Enum.to_list(1..5) |> Enum.map(fn i -> event_data = "data: MCP Event #{i}\n\n" Logger.info("Sending SSE event: #{event_data}") event_data end) |> Enum.join() end end ``` ```elixir # lib/mcp_sse_example/application.ex defmodule McpSseExample.Application do # See https://hexdocs.pm/elixir/Application.html # for more information on OTP Applications @moduledoc false use Application @impl true def start(_type, _args) do children = [ # Start the Telemetry supervisor McpSseExampleWeb.Telemetry, # Start the PubSub system {Phoenix.PubSub, name: McpSseExample.PubSub}, # Start the Endpoint (http/https) McpSseExampleWeb.Endpoint # Start a worker by calling: McpSseExample.Worker.start_link(arg) # {McpSseExample.Worker, arg} ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: McpSseExample.Supervisor] Supervisor.start_link(children, opts) end # Tell Phoenix to update the endpoint configuration. # # We store the endpoint configuration in a separate file # which defines production environment configuration. @impl true def config_change(changed, conf) do McpSseExampleWeb.Endpoint.config_change(changed, conf) :ok end end ``` ```elixir # lib/mcp_sse_example_web.ex defmodule McpSseExampleWeb do @moduledoc """ The entrypoint for defining your web interface, such as controllers, views, channels and so on. This can be used in your application as: use McpSseExampleWeb, :controller use McpSseExampleWeb, :html The definitions below took the configuration from your application, the router and the endpoint that should be used. Please update the configuration accordingly. """ def controller do quote do use Phoenix.Controller, namespace: McpSseExampleWeb import Plug.Conn import McpSseExampleWeb.Gettext alias McpSseExampleWeb.Router.Helpers, as: Routes end end def html do quote do use Phoenix.Component # Import convenience functions from LiveView import Phoenix.LiveView.Helpers # Include general helpers for rendering HTML unquote(html_helpers()) end end defp html_helpers do quote do # HTML escaping functionality import Phoenix.HTML # Core UI components and translation helpers import McpSseExampleWeb.CoreComponents import McpSseExampleWeb.Gettext end end def router do quote do use Phoenix.Router import Plug.Conn import Phoenix.Controller, only: [get_session: 1, view: 1, put_layout: 1] import McpSseExampleWeb.Gettext end end def channel do quote do use Phoenix.Channel import McpSseExampleWeb.Gettext end end def live_view do quote do use Phoenix.LiveView, layout: {McpSseExampleWeb.LayoutView, :app} import McpSseExampleWeb.HTML import McpSseExampleWeb.Gettext end end def live_component do quote do use Phoenix.LiveComponent import McpSseExampleWeb.HTML end end def view do quote do use Phoenix.View, root: "lib/mcp_sse_example_web/templates", namespace: McpSseExampleWeb # Import convenience functions from LiveView import Phoenix.LiveView.Helpers # Use all HTML helpers (forms, tags, etc) unquote(html_helpers()) end end defp translate_aliases(aliases) do Enum.reduce(aliases, [], fn {key, val}, acc -> case Code.ensure_loaded(val) do {:module, module} -> [{key, module} | acc] :error -> acc end end) end @doc """ When using `"mix phx.gen.auth"` or `"mix phx.gen.live_auth"` you will want to import the authentication module in `McpSseExampleWeb`. import McpSseExampleWeb.Auth """ def auth do quote do use Phoenix.Component import Phoenix.Controller, only: [get_session: 1, view: 1, put_layout: 1] import Phoenix.LiveView.Helpers import McpSseExampleWeb.HTML end end def channel_socket do quote do use Phoenix.Channel.Socket # Channels can be accessed in the controller or view # by calling `channel_socket` and passing it to the # socket assign. # # <%= live_render(@conn, McpSseExampleWeb.MyLive, # socket: channel_socket(@socket, :my_channel)) %> # # Now the channel can be accessed from `MyLive` with: # # @socket.assigns.my_channel end end end ``` **Explanation:** 1. **Dependencies:** The `mix.exs` file defines the necessary dependencies, including `phoenix` for the web framework. 2. **Router:** The `lib/mcp_sse_example_web/router.ex` file defines the routes. The important part is the `/mcp/events` route, which is handled by the `McpController`. 3. **Controller:** The `lib/mcp_sse_example_web/controllers/mcp_controller.ex` file contains the `events` action. * `put_resp_content_type("text/event-stream")`: Sets the correct content type for SSE. * `send_resp(200, stream_mcp_events())`: Sends the response with a status code of 200 and the data generated by `stream_mcp_events()`. * `stream_mcp_events()`: This function *simulates* generating MCP events. In a real application, this would likely involve: * A GenServer or other process that monitors the system being controlled. * Logic to translate system state changes into MCP events. * Sending those events to the SSE stream. * The `data: ...\n\n` format is crucial for SSE. Each event must be formatted this way. `data:` is the event data, and `\n\n` signifies the end of the event. 4. **Application:** The `lib/mcp_sse_example/application.ex` file defines the application's entry point and starts the Phoenix endpoint. **How to Run:** 1. Make sure you have Elixir and Erlang installed. 2. Create a new Phoenix project: `mix phx.new mcp_sse_example --no-ecto` (The `--no-ecto` flag skips database setup, as this example doesn't use a database). 3. Replace the contents of the generated files with the code above. 4. Install dependencies: `mix deps.get` 5. Start the server: `mix phx.server` **Client-Side (JavaScript Example):** ```html <!DOCTYPE html> <html> <head> <title>MCP SSE Client</title> </head> <body> <h1>MCP Events</h1> <div id="events"></div> <script> const eventSource = new EventSource("/mcp/events"); eventSource.onmessage = function(event) { const eventDiv = document.getElementById("events"); const newEvent = document.createElement("p"); newEvent.textContent = event.data; eventDiv.appendChild(newEvent); }; eventSource.onerror = function(error) { console.error("SSE error:", error); }; </script> </body> </html> ``` Save this as `index.html` in the `priv/static` directory of your Phoenix project. Then, you can access it in your browser at `http://localhost:4000/index.html`. You should see the MCP events being displayed. **Important Considerations and Enhancements:** * **Error Handling:** The example has minimal error handling. You need to handle connection errors, event processing errors, and potential errors in the MCP logic. * **Real MCP Logic:** The `stream_mcp_events()` function is a placeholder. You'll need to replace it with the actual logic for generating MCP events based on the state of the system you're controlling. This might involve: * Monitoring system resources (CPU, memory, network). * Responding to external commands. * Publishing status updates. * **Authentication/Authorization:** For a real system, you'll need to implement authentication and authorization to ensure that only authorized clients can access the MCP stream. Phoenix provides mechanisms for this. * **Event IDs and Reconnection:** SSE supports event IDs. You can include an `id:` field in your SSE events. If the client disconnects and reconnects, it can send the last received event ID to the server, and the server can resend any missed events. * **Event Types:** SSE also supports event types. You can include an `event:` field in your SSE events to categorize them. The client can then listen for specific event types. * **GenServer for Event Generation:** A GenServer is a good choice for managing the state and logic for generating MCP events. The GenServer can monitor the system, process commands, and push events to a PubSub topic. The `McpController` can then subscribe to the PubSub topic and stream the events to the client. * **Phoenix PubSub:** Use Phoenix PubSub for broadcasting events to multiple clients. The GenServer generating the events can publish them to a PubSub topic, and the `McpController` can subscribe to that topic and stream the events to connected clients. * **Scalability:** For a highly scalable system, consider using a distributed PubSub system (e.g., Redis PubSub) or a message queue (e.g., RabbitMQ) to distribute events across multiple servers. * **Data Format:** While this example uses simple text, you might want to use JSON for more structured data. You'll need to adjust the client-side JavaScript to parse the JSON. **Chinese Translation of Key Concepts:** * **MCP (Meta-Control Protocol):** 元控制协议 (Yuán kòngzhì xiéyì) * **SSE (Server-Sent Events):** 服务器发送事件 (Fúwùqì fāsòng shìjiàn) * **Elixir:** Elixir (No direct translation, usually referred to by its name) * **Phoenix Framework:** Phoenix 框架 (Phoenix kuàngjià) * **GenServer:** GenServer (No direct translation, usually referred to by its name) * **PubSub:** 发布/订阅 (Fābù/dìngyuè) * **Event:** 事件 (Shìjiàn) * **Stream:** 流 (Liú) * **Endpoint:** 端点 (Duāndiǎn) * **Authentication:** 身份验证 (Shēnfèn yànzhèng) * **Authorization:** 授权 (Shòuquán) This example provides a starting point for building an MCP server with Elixir and SSE. Remember to adapt it to your specific needs and add the necessary error handling, security, and scalability features. Good luck!
epinault
README
推荐服务器
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
MCP Package Docs Server
促进大型语言模型高效访问和获取 Go、Python 和 NPM 包的结构化文档,通过多语言支持和性能优化来增强软件开发。
Claude Code MCP
一个实现了 Claude Code 作为模型上下文协议(Model Context Protocol, MCP)服务器的方案,它可以通过标准化的 MCP 接口来使用 Claude 的软件工程能力(代码生成、编辑、审查和文件操作)。
@kazuph/mcp-taskmanager
用于任务管理的模型上下文协议服务器。它允许 Claude Desktop(或任何 MCP 客户端)在基于队列的系统中管理和执行任务。
mermaid-mcp-server
一个模型上下文协议 (MCP) 服务器,用于将 Mermaid 图表转换为 PNG 图像。
Jira-Context-MCP
MCP 服务器向 AI 编码助手(如 Cursor)提供 Jira 工单信息。

Linear MCP Server
一个模型上下文协议(Model Context Protocol)服务器,它与 Linear 的问题跟踪系统集成,允许大型语言模型(LLM)通过自然语言交互来创建、更新、搜索和评论 Linear 问题。

Sequential Thinking MCP Server
这个服务器通过将复杂问题分解为顺序步骤来促进结构化的问题解决,支持修订,并通过完整的 MCP 集成来实现多条解决方案路径。
Curri MCP Server
通过管理文本笔记、提供笔记创建工具以及使用结构化提示生成摘要,从而实现与 Curri API 的交互。