11defmodule Anubis.Protocol do
2- @ moduledoc false
2+ @ moduledoc """
3+ MCP protocol version management.
4+
5+ Provides version validation, negotiation, feature detection, and transport
6+ compatibility checking. Delegates version-specific logic to modules under
7+ `Anubis.Protocol.*` via `Anubis.Protocol.Registry`.
8+
9+ ## Adding a new protocol version
10+
11+ 1. Create a new module under `lib/anubis/protocol/` implementing `Anubis.Protocol.Behaviour`
12+ 2. Register it in `Anubis.Protocol.Registry`
13+ """
314
415 alias Anubis.MCP.Error
16+ alias Anubis.Protocol.Registry
517
618 @ type version :: String . t ( )
719 @ type feature :: atom ( )
820
9- @ supported_versions [ "2024-11-05" , "2025-03-26" , "2025-06-18" ]
10- @ latest_version "2025-06-18"
11- @ fallback_version "2025-03-26"
12-
13- @ features_2024_11_05 [
14- :basic_messaging ,
15- :resources ,
16- :tools ,
17- :prompts ,
18- :logging ,
19- :progress ,
20- :cancellation ,
21- :ping ,
22- :roots ,
23- :sampling
24- ]
25-
26- @ features_2025_03_26 [
27- :authorization ,
28- :audio_content ,
29- :tool_annotations ,
30- :progress_messages ,
31- :completion_capability
32- | @ features_2024_11_05
33- ]
34-
35- @ features_2025_06_18 [
36- :elicitation ,
37- :structured_tool_results ,
38- :tool_output_schemas ,
39- :model_preferences ,
40- :embedded_resources_in_prompts ,
41- :embedded_resources_in_tools
42- | @ features_2025_03_26
43- ]
44-
4521 @ doc """
4622 Returns all supported protocol versions.
4723 """
4824 @ spec supported_versions ( ) :: [ version ( ) ]
49- def supported_versions , do: @ supported_versions
25+ defdelegate supported_versions ( ) , to: Registry
5026
5127 @ doc """
5228 Returns the latest supported protocol version.
5329 """
5430 @ spec latest_version ( ) :: version ( )
55- def latest_version , do: @ latest_version
31+ defdelegate latest_version ( ) , to: Registry
5632
5733 @ doc """
5834 Returns the fallback protocol version for compatibility.
5935 """
6036 @ spec fallback_version ( ) :: version ( )
61- def fallback_version , do: @ fallback_version
37+ defdelegate fallback_version ( ) , to: Registry
6238
6339 @ doc """
6440 Validates if a protocol version is supported.
6541 """
6642 @ spec validate_version ( version ( ) ) :: :ok | { :error , Error . t ( ) }
67- def validate_version ( version ) when version in @ supported_versions , do: :ok
68-
6943 def validate_version ( version ) do
70- { :error ,
71- Error . protocol ( :invalid_params , % {
72- version: version ,
73- supported: @ supported_versions
74- } ) }
44+ if Registry . supported? ( version ) do
45+ :ok
46+ else
47+ { :error ,
48+ Error . protocol ( :invalid_params , % {
49+ version: version ,
50+ supported: supported_versions ( )
51+ } ) }
52+ end
7553 end
7654
7755 @ doc """
@@ -95,28 +73,29 @@ defmodule Anubis.Protocol do
9573
9674 defp supported_transport_versions ( transport ) do
9775 case transport . supported_protocol_versions ( ) do
98- :all -> @ supported_versions
76+ :all -> supported_versions ( )
9977 [ _ | _ ] = versions -> versions
10078 end
10179 end
10280
10381 @ doc """
10482 Returns the set of features supported by a protocol version.
83+
84+ Delegates to the version module's `supported_features/0` callback.
10585 """
10686 @ spec get_features ( version ( ) ) :: list ( feature ( ) )
107- def get_features ( "2024-11-05" ) , do: @ features_2024_11_05
108- def get_features ( "2025-03-26" ) , do: @ features_2025_03_26
109- def get_features ( "2025-06-18" ) , do: @ features_2025_06_18
87+ def get_features ( version ) do
88+ case Registry . get_features ( version ) do
89+ { :ok , features } -> features
90+ :error -> [ ]
91+ end
92+ end
11093
11194 @ doc """
11295 Checks if a feature is supported by a protocol version.
11396 """
11497 @ spec supports_feature? ( version ( ) , feature ( ) ) :: boolean ( )
115- def supports_feature? ( version , feature ) when is_binary ( version ) and is_atom ( feature ) do
116- version
117- |> get_features ( )
118- |> Enum . member? ( feature )
119- end
98+ defdelegate supports_feature? ( version , feature ) , to: Registry
12099
121100 @ doc """
122101 Negotiates protocol version between client and server versions.
@@ -127,25 +106,36 @@ defmodule Anubis.Protocol do
127106 { :ok , version ( ) } | { :error , Error . t ( ) }
128107 def negotiate_version ( client_version , server_version ) do
129108 cond do
130- client_version == server_version and client_version in @ supported_versions ->
109+ client_version == server_version and Registry . supported? ( client_version ) ->
131110 { :ok , client_version }
132111
133- server_version in @ supported_versions ->
112+ Registry . supported? ( server_version ) ->
134113 { :ok , server_version }
135114
136- client_version in @ supported_versions ->
115+ Registry . supported? ( client_version ) ->
137116 { :ok , client_version }
138117
139118 true ->
140119 { :error ,
141120 Error . protocol ( :invalid_params , % {
142121 client_version: client_version ,
143122 server_version: server_version ,
144- supported: @ supported_versions
123+ supported: supported_versions ( )
145124 } ) }
146125 end
147126 end
148127
128+ @ doc """
129+ Returns the protocol module for a given version string.
130+
131+ ## Examples
132+
133+ iex> Anubis.Protocol.get_module("2025-06-18")
134+ {:ok, Anubis.Protocol.V2025_06_18}
135+ """
136+ @ spec get_module ( version ( ) ) :: { :ok , module ( ) } | :error
137+ defdelegate get_module ( version ) , to: Registry , as: :get
138+
149139 @ doc """
150140 Returns transport modules that support a protocol version.
151141 """
0 commit comments