Packages
corex
0.1.0
0.1.2
0.1.1
0.1.0
0.1.0-rc.1
0.1.0-rc.0
0.1.0-beta.5
0.1.0-beta.4
0.1.0-beta.3
0.1.0-beta.2
0.1.0-beta.1
0.1.0-alpha.33
0.1.0-alpha.32
0.1.0-alpha.31
0.1.0-alpha.30
0.1.0-alpha.29
0.1.0-alpha.28
0.1.0-alpha.27
0.1.0-alpha.26
0.1.0-alpha.25
0.1.0-alpha.24
0.1.0-alpha.23
0.1.0-alpha.22
0.1.0-alpha.21
0.1.0-alpha.20
0.1.0-alpha.19
0.1.0-alpha.18
0.1.0-alpha.17
0.1.0-alpha.16
0.1.0-alpha.15
0.1.0-alpha.14
0.1.0-alpha.13
0.1.0-alpha.12
0.1.0-alpha.11
0.1.0-alpha.10
0.1.0-alpha.9
0.1.0-alpha.8
0.1.0-alpha.7
0.1.0-alpha.6
0.1.0-alpha.5
0.1.0-alpha.4
0.1.0-alpha.3
0.1.0-alpha.2
0.1.0-alpha.1
Accessible and unstyled UI components library written in Elixir and TypeScript that integrates Zag.js state machines into the Phoenix Framework.
Current section
Files
Jump to
Current section
Files
lib/mcp/router.ex
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025 Dashbit
# See LICENSE for third-party notices.
defmodule Corex.MCP.Router do
@moduledoc false
use Plug.Router
import Plug.Conn
require Logger
alias Corex.Json
alias Corex.MCP.Server
@remote_access_forbidden """
For security reasons, Corex.MCP does not accept remote connections by default.
If you really want to allow remote connections, configure plug Corex.MCP with allow_remote_access: true.
"""
@origin_header_forbidden """
For security reasons, Corex.MCP does not accept requests with an origin header for this endpoint.
"""
plug(:match)
plug(:check_remote_ip)
plug(:check_origin)
plug(:dispatch)
get "/" do
conn
|> put_resp_content_type("text/html")
|> send_resp(200, corex_mcp_html())
|> halt()
end
get "/config" do
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Json.encode_to_iodata!(config(conn.private.corex_mcp_config)))
|> halt()
end
get "/mcp" do
Logger.metadata(corex_mcp: true)
conn
|> send_resp(405, "Method Not Allowed")
|> halt()
end
post "/mcp" do
Logger.metadata(corex_mcp: true)
opts =
Plug.Parsers.init(
parsers: [:json],
pass: [],
json_decoder: Json.encoder()
)
conn
|> Plug.Parsers.call(opts)
|> Server.handle_http_message()
|> halt()
end
match "/*_ignored" do
Logger.metadata(corex_mcp: true)
conn
|> send_resp(404, "Not Found")
|> halt()
end
defp check_remote_ip(conn, _opts) do
cond do
loopback_address?(conn.remote_ip) ->
conn
conn.private.corex_mcp_config.allow_remote_access ->
conn
true ->
deny_remote_access(conn)
end
end
defp loopback_address?({127, 0, 0, _}), do: true
defp loopback_address?({0, 0, 0, 0, 0, 0, 0, 1}), do: true
defp loopback_address?({0, 0, 0, 0, 0, 65_535, 32_512, 1}), do: true
defp loopback_address?(_), do: false
defp check_origin(conn, _opts) do
case {conn.path_info, get_req_header(conn, "origin")} do
{[], _} ->
conn
{_, []} ->
conn
{_, _} ->
deny_origin_header(conn)
end
end
defp deny_remote_access(conn) do
Logger.warning(@remote_access_forbidden)
conn
|> send_resp(403, @remote_access_forbidden)
|> halt()
end
defp deny_origin_header(conn) do
Logger.warning(@origin_header_forbidden)
conn
|> send_resp(403, @origin_header_forbidden)
|> halt()
end
defp corex_mcp_html do
"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Corex MCP</title>
</head>
<body>
<p>Corex Model Context Protocol (dev). Use POST to <code>/corex/mcp</code> for JSON-RPC.</p>
</body>
</html>
"""
end
defp package_version(app) do
if vsn = Application.spec(app)[:vsn] do
List.to_string(vsn)
end
end
defp config(plug_config) do
%{
name: "corex",
framework_type: "phoenix",
corex_version: package_version(:corex),
allow_remote_access: plug_config.allow_remote_access
}
end
end