Packages
fnord
0.8.68
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/cmd/config/mcp/check_formatter.ex
defmodule Cmd.Config.MCP.CheckFormatter do
@moduledoc """
Formats MCP check results in a human-friendly format with checkmarks.
"""
@doc """
Formats the test results from Services.MCP.test/1 into human-readable output.
"""
@spec format_results(map()) :: :ok
def format_results(%{servers: servers}) when map_size(servers) == 0 do
UI.puts("Checking MCP servers...")
UI.puts("")
UI.puts("No MCP servers configured")
:ok
end
def format_results(%{servers: servers}) do
UI.puts("Checking MCP servers...")
UI.puts("")
servers
|> Enum.sort_by(fn {name, _} -> name end)
|> Enum.each(fn {name, data} ->
format_server(name, data)
UI.puts("")
end)
:ok
end
defp format_server(name, data) do
# Server name with OAuth indicator if present
server_label =
if data[:has_oauth] do
"#{name} (OAuth)"
else
name
end
UI.puts(IO.ANSI.format([:bright, server_label, :reset], UI.colorize?()))
# Connection status
format_connection_status(data)
# Authentication status
format_auth_status(data)
# Tools status
format_tools_status(data)
# Capabilities status
format_capabilities_status(data)
# If we have tools, show the list
case data do
%{tools: tools} when is_list(tools) and length(tools) > 0 ->
UI.newline()
format_tools_list(tools)
_ ->
:ok
end
# If authentication is a problem, suggest login
case data do
%{auth_status: status} when status in [:missing, :expired] ->
UI.puts("")
UI.puts(IO.ANSI.format([:cyan, " fnord config mcp login #{name}"], UI.colorize?()))
_ ->
:ok
end
end
defp format_connection_status(%{status: "ok"}) do
UI.puts(" #{success_symbol()} Connection")
end
defp format_connection_status(%{status: "error", error: error}) do
UI.puts(" #{error_symbol()} Connection #{format_error_detail(error)}")
end
defp format_connection_status(_) do
UI.puts(" #{error_symbol()} Connection (unknown)")
end
defp format_auth_status(%{has_oauth: true, auth_status: :valid}) do
UI.puts(" #{success_symbol()} Authentication")
end
defp format_auth_status(%{has_oauth: true, auth_status: :expired}) do
UI.puts(" #{warning_symbol()} Authentication (expired)")
end
defp format_auth_status(%{has_oauth: true, auth_status: :missing}) do
UI.puts(" #{error_symbol()} Authentication (no credentials)")
end
defp format_auth_status(%{has_oauth: false}) do
UI.puts(" #{na_symbol()} Authentication (N/A)")
end
defp format_auth_status(_) do
UI.puts(" #{na_symbol()} Authentication (N/A)")
end
defp format_tools_status(%{status: "error"}) do
UI.puts(" #{na_symbol()} Tools (unavailable)")
end
defp format_tools_status(%{tools: tools}) when is_list(tools) do
count = length(tools)
if count > 0 do
UI.puts(" #{success_symbol()} Tools (#{count} available)")
else
UI.puts(" #{warning_symbol()} Tools (none)")
end
end
defp format_tools_status(_) do
UI.puts(" #{na_symbol()} Tools (unavailable)")
end
defp format_capabilities_status(%{status: "error"}) do
UI.puts(" #{na_symbol()} Capabilities (unavailable)")
end
defp format_capabilities_status(%{capabilities: caps}) when is_map(caps) do
cap_names =
caps
|> Enum.filter(fn {_k, v} -> v end)
|> Enum.map(fn {k, _v} -> k end)
|> Enum.sort()
if length(cap_names) > 0 do
caps_str = Enum.join(cap_names, ", ")
UI.puts(" #{success_symbol()} Capabilities (#{caps_str})")
else
UI.puts(" #{warning_symbol()} Capabilities (none)")
end
end
defp format_capabilities_status(_) do
UI.puts(" #{na_symbol()} Capabilities (unavailable)")
end
defp format_tools_list(tools) do
UI.puts(" Available tools:")
Enum.each(tools, fn tool ->
name = tool["name"] || "(unnamed)"
desc = tool["description"] || ""
if desc != "" do
UI.puts(" • #{name} - #{desc}")
else
UI.puts(" • #{name}")
end
end)
end
defp format_error_detail(error) when is_binary(error) do
"(#{error})"
end
defp format_error_detail(error) do
"(#{inspect(error)})"
end
defp success_symbol do
IO.ANSI.format([:green, "✓", :reset], UI.colorize?())
end
defp error_symbol do
IO.ANSI.format([:red, "✗", :reset], UI.colorize?())
end
defp warning_symbol do
IO.ANSI.format([:yellow, "⚠", :reset], UI.colorize?())
end
defp na_symbol do
IO.ANSI.format([:light_black, "-", :reset], UI.colorize?())
end
end