Skip to main content

rebar.config

{erl_opts, [debug_info, warnings_as_errors]}.

{deps, [
    %% hex package is `erlang_h1' (the short name `h1' was taken);
    %% the OTP app/dep stays `h1' so call sites and the app graph
    %% use `h1' consistently.
    {h1, "~> 0.7.0", {pkg, erlang_h1}},
    {h2, "~> 0.10.0"},
    {hackney, "~> 4.4.2"}
]}.

{shell, [{apps, [barrel_mcp]}]}.

{eunit_opts, [verbose]}.
{cover_enabled, true}.

{dialyzer, [
    {warnings, [unmatched_returns, error_handling, unknown]},
    {plt_extra_apps, [ssl, public_key]}
]}.

{xref_checks, [
    undefined_function_calls,
    undefined_functions,
    locals_not_used,
    deprecated_function_calls,
    deprecated_functions
]}.

{profiles, [
    {test, [
        {deps, [{meck, "1.2.0"}]}
    ]}
]}.

%% meck 1.2.0 still uses the bare `catch' operator, which OTP 29
%% deprecates; relax that one warning for the dep so it builds (our
%% own code uses try...catch).
{overrides, [
    {add, meck, [{erl_opts, [nowarn_deprecated_catch]}]}
]}.

%% Documentation
{project_plugins, [
    {erlfmt, "1.8.0"},
    {rebar3_lint, "5.0.4"},
    rebar3_ex_doc
]}.

{erlfmt, [
    write,
    {files, [
        "{src,include,test}/**/*.{hrl,erl,app.src}",
        "rebar.config"
    ]}
]}.

{ex_doc, [
    {extras, [
        {"README.md", #{title => "Overview"}},
        {"guides/getting-started.md", #{title => "Getting Started"}},
        {"guides/building-a-client.md", #{title => "Building a Client"}},
        {"guides/internals.md", #{title => "Client Internals"}},
        {"guides/features.md", #{title => "Features"}},
        {"guides/http-stream.md", #{title => "Streamable HTTP Transport"}},
        {"guides/stdio.md", #{title => "stdio Transport"}},
        {"guides/authentication.md", #{title => "Authentication"}},
        {"guides/custom-authentication.md", #{title => "Custom Authentication"}},
        {"guides/tools-resources-prompts.md", #{title => "Tools, Resources & Prompts"}},
        {"guides/client.md", #{title => "MCP Client (reference)"}},
        {"docs/pending-features.md", #{title => "Pending Features"}},
        {"CHANGELOG.md", #{title => "Changelog"}},
        {"LICENSE", #{title => "License"}}
    ]},
    {main, "README.md"},
    {homepage_url, "https://github.com/barrel-platform/barrel_mcp"},
    {source_url, "https://github.com/barrel-platform/barrel_mcp"},
    {api_reference, true},
    {groups_for_modules, [
        {"Main API", [barrel_mcp]},
        {"Server Authentication", [
            barrel_mcp_auth,
            barrel_mcp_auth_none,
            barrel_mcp_auth_bearer,
            barrel_mcp_auth_apikey,
            barrel_mcp_auth_basic,
            barrel_mcp_auth_custom
        ]},
        {"Server", [
            barrel_mcp_http,
            barrel_mcp_http_stream,
            barrel_mcp_http_engine,
            barrel_mcp_http_listener,
            barrel_mcp_stdio,
            barrel_mcp_protocol
        ]},
        {"Session", [barrel_mcp_session]},
        {"Client", [
            barrel_mcp_client,
            barrel_mcp_clients,
            barrel_mcp_client_handler,
            barrel_mcp_client_handler_default,
            barrel_mcp_client_transport,
            barrel_mcp_client_stdio,
            barrel_mcp_client_http
        ]},
        {"Client Authentication", [
            barrel_mcp_client_auth,
            barrel_mcp_client_auth_bearer,
            barrel_mcp_client_auth_oauth
        ]},
        {"Utilities", [barrel_mcp_pagination, barrel_mcp_schema]},
        {"Registry", [barrel_mcp_registry]}
    ]}
]}.

{hex, [{doc, ex_doc}]}.

{elvis, [
    {config, [
        #{
            files => ["src/**/*.erl"],
            rules => [
                {elvis_style, no_macros, disable},
                {elvis_style, no_common_caveats_call, disable},
                {elvis_style, no_init_lists, disable},
                {elvis_style, param_pattern_matching, disable},
                %% `barrel_mcp' is the intentional public facade; the
                %% client/registry/engine/session modules expose broad
                %% surfaces (verbs, dispatch, state machine) by design.
                {elvis_style, no_god_modules, #{
                    ignore => [
                        barrel_mcp,
                        barrel_mcp_client,
                        barrel_mcp_registry,
                        barrel_mcp_http_engine,
                        barrel_mcp_session
                    ]
                }},
                %% Auth/transport/handler providers are dispatched
                %% dynamically by design (Provider:init/verify,
                %% Transport:send/recv, Handler:handle_request, ...).
                {elvis_style, no_invalid_dynamic_calls, #{
                    ignore => [
                        barrel_mcp_auth,
                        barrel_mcp_auth_custom,
                        barrel_mcp_client,
                        barrel_mcp_client_auth,
                        barrel_mcp_client_transport,
                        barrel_mcp_registry,
                        barrel_mcp_http_engine,
                        barrel_mcp_http_listener,
                        barrel_mcp_protocol
                    ]
                }},
                %% Transport/session loops block on receive and exit on a
                %% monitored DOWN, so an after clause is wrong.
                {elvis_style, no_receive_without_timeout, #{
                    ignore => [
                        barrel_mcp_http_engine,
                        barrel_mcp_http_listener,
                        barrel_mcp_client_http,
                        barrel_mcp_client_stdio,
                        barrel_mcp_stdio,
                        barrel_mcp_session
                    ]
                }},
                %% camelCase JSON-RPC / JSON-Schema keyword atoms are
                %% external wire shapes, not our naming.
                {elvis_style, atom_naming_convention, #{
                    ignore => [
                        barrel_mcp_protocol,
                        barrel_mcp_schema,
                        barrel_mcp_tool_format
                    ]
                }},
                %% The DRY heuristic flags structurally similar but
                %% intentionally distinct JSON-RPC / schema / state /
                %% transport branches throughout; off project-wide.
                {elvis_style, dont_repeat_yourself, disable},
                %% Internal opaque token/handle types kept private to the
                %% OAuth client module.
                {elvis_style, private_data_types, #{
                    ignore => [barrel_mcp_client_auth_oauth]
                }},
                {elvis_style, no_boolean_in_comparison, #{
                    ignore => [barrel_mcp_protocol]
                }},
                {elvis_style, no_single_clause_case, #{
                    ignore => [barrel_mcp_client]
                }},
                %% stdio transport writes the framed protocol response to
                %% stdout; that io:format is the wire, not a debug call.
                {elvis_style, no_debug_call, #{
                    ignore => [barrel_mcp_stdio]
                }},
                %% The acceptor/handler plumbing nests and threads the
                %% per-stream handler fun positionally.
                {elvis_style, no_deep_nesting, #{
                    ignore => [barrel_mcp_http_listener]
                }},
                {elvis_style, max_anonymous_function_arity, #{
                    ignore => [barrel_mcp_http_listener]
                }},
                %% Long lines flagged here are doc-comment URLs and edoc
                %% examples that cannot wrap; code lines stay under 100.
                {elvis_text_style, max_line_length, #{
                    limit => 100,
                    skip_comments => whole_line
                }}
            ],
            ruleset => erl_files
        },
        #{
            files => ["rebar.config"],
            rules => [
                {elvis_project, no_branch_deps, disable}
            ],
            ruleset => rebar_config
        }
    ]}
]}.