fix(streamable_http): restore session from store on notif/resp registry miss (multi-instance) - #221
mariamaman wants to merge 89 commits into
Conversation
Co-authored-by: Claude <noreply@anthropic.com>
Bumps [plug](https://github.com/elixir-plug/plug) from 1.18.1 to 1.19.0. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/elixir-plug/plug/blob/main/CHANGELOG.md">plug's changelog</a>.</em></p> <blockquote> <h2>v1.19.0 (2025-12-08)</h2> <p>This release requires Elixir v1.14+ and it bumps the recommended :strong and :compatible SSL/TLS ciphers suite to align with modern security standards, prioritizing TLS 1.3 and 1.2. Support for the insecure TLS 1.0 and 1.1 protocols are removed in accordance with RFC 8996.</p> <h3>Enhancements</h3> <ul> <li>[Plug.Router] Allow colon for named segments to be escaped</li> <li>[Plug.SSL] Prioritize TLS 1.3 and 1.2 ciphers</li> <li>[Plug.SSL] Allow excluding redirects based on hosts, paths, or the connection</li> <li>[Plug.Static] Add <code>:raise_on_missing_only</code></li> <li>[Plug.Upload] Partition the uploader to improve performance</li> <li>[Plug.Upload] Add API for deleting files</li> </ul> <h3>Deprecations</h3> <ul> <li>[Plug.Conn.Adapter] Deprecate <code>:owner</code> field</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/elixir-plug/plug/commits">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [styler](https://github.com/adobe/elixir-styler) from 1.9.1 to 1.10.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/adobe/elixir-styler/releases">styler's releases</a>.</em></p> <blockquote> <h2>v1.10.0</h2> <h3>Improvements</h3> <p>Two new standard-library pipe optimizations</p> <ul> <li><code>enum |> Enum.map(fun) |> Enum.intersperse(separator)</code> => <code>Enum.map_intersperse(enum, separator, fun)</code></li> <li><code>enum |> Enum.sort() |> Enum.reverse()</code> => <code>Enum.sort(enum, :desc)</code></li> </ul> <p>And Req (the http client library) pipe optimizations, as detailed below</p> <h4>Req pipe optimizations</h4> <p><a href="https://github.com/wojtekmach/req">Req</a> is a popular HTTP Client. If you aren't using it, you can just ignore this whole section!</p> <p>Reqs 1-arity "execute the request" functions (<code>delete get head patch post put request run</code>) have a 2-arity version that takes a superset of the arguments <code>Req.new/1</code> does as its first argument, and the typical <code>options</code> keyword list as its second argument. And so, many places developers are calling a 1-arity function can be replaced with a 2-arity function.</p> <p>More succinctly, these two statements are equivalent:</p> <ul> <li><code>foo |> Req.new() |> Req.merge(bar) |> Req.post!()</code></li> <li><code>Req.post!(foo, bar)</code></li> </ul> <p>Styler now rewrites the former to the latter, since "less is more" or "code is a liability".</p> <p>It also rewrites <code>|> Keyword.merge(bar) |> Req.foo()</code> to <code>|> Req.foo(bar)</code>. <strong>This changes the program's behaviour</strong>, since <code>Keyword.merge</code> would overwrite existing values in all cases, whereas <code>Req</code> 2-arity functions intelligently deep-merge values for some keys, like <code>:headers</code>.</p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/adobe/elixir-styler/blob/main/CHANGELOG.md">styler's changelog</a>.</em></p> <blockquote> <h2>1.10.0</h2> <h3>Improvements</h3> <p>Two new standard-library pipe optimizations</p> <ul> <li><code>enum |> Enum.map(fun) |> Enum.intersperse(separator)</code> => <code>Enum.map_intersperse(enum, separator, fun)</code></li> <li><code>enum |> Enum.sort() |> Enum.reverse()</code> => <code>Enum.sort(enum, :desc)</code></li> </ul> <p>And Req (the http client library) pipe optimizations, as detailed below</p> <h4>Req pipe optimizations</h4> <p><a href="https://github.com/wojtekmach/req">Req</a> is a popular HTTP Client. If you aren't using it, you can just ignore this whole section!</p> <p>Reqs 1-arity "execute the request" functions (<code>delete get head patch post put request run</code>) have a 2-arity version that takes a superset of the arguments <code>Req.new/1</code> does as its first argument, and the typical <code>options</code> keyword list as its second argument. And so, many places developers are calling a 1-arity function can be replaced with a 2-arity function.</p> <p>More succinctly, these two statements are equivalent:</p> <ul> <li><code>foo |> Req.new() |> Req.merge(bar) |> Req.post!()</code></li> <li><code>Req.post!(foo, bar)</code></li> </ul> <p>Styler now rewrites the former to the latter, since "less is more" or "code is a liability".</p> <p>It also rewrites <code>|> Keyword.merge(bar) |> Req.foo()</code> to <code>|> Req.foo(bar)</code>. <strong>This changes the program's behaviour</strong>, since <code>Keyword.merge</code> would overwrite existing values in all cases, whereas <code>Req</code> 2-arity functions intelligently deep-merge values for some keys, like <code>:headers</code>.</p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/adobe/elixir-styler/commit/70b50451a8ded14ed8364ba26a5958f05220446e"><code>70b5045</code></a> v1.10.0</li> <li><a href="https://github.com/adobe/elixir-styler/commit/2af7d19948f2bfd78780ec38896086daebf048e1"><code>2af7d19</code></a> Enum.map |> Enum.intersperse => Enum.map_intersperse</li> <li><a href="https://github.com/adobe/elixir-styler/commit/7884561a1294c3fbe36689c40851bab444cda078"><code>7884561</code></a> allow docs for Styler.string_to_ast</li> <li><a href="https://github.com/adobe/elixir-styler/commit/a490ad68bce097da65b0258f850a702035238c87"><code>a490ad6</code></a> sort |> reverse => sort(:desc)</li> <li><a href="https://github.com/adobe/elixir-styler/commit/78ced6b4dc2c72df34dbb44973555bc8dfcf3e36"><code>78ced6b</code></a> TIL capital sigils cant be escaped</li> <li><a href="https://github.com/adobe/elixir-styler/commit/1a6a375a6fc2148f778d5f9da04b8f5b6bbcc5b1"><code>1a6a375</code></a> tweak intro sentence</li> <li><a href="https://github.com/adobe/elixir-styler/commit/e48ca6cada3d7cd90b624609827ef0af26bf96fe"><code>e48ca6c</code></a> less is more</li> <li><a href="https://github.com/adobe/elixir-styler/commit/793cf27938a99c1492b0ce611519d91fda68311a"><code>793cf27</code></a> optimize Req pipes</li> <li>See full diff in <a href="https://github.com/adobe/elixir-styler/compare/v1.9.1...v1.10.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.39.1 to 0.39.2. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/elixir-lang/ex_doc/blob/main/CHANGELOG.md">ex_doc's changelog</a>.</em></p> <blockquote> <h2>v0.39.2 (2025-12-04)</h2> <ul> <li>Bug fixes <ul> <li>Do not strip hrefs on summaries</li> <li>Show go to latest for prereleases</li> <li>Prevent fake italic in autocomplete text</li> <li>Rename "Search Hexdocs" link to "Go to package docs"</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/elixir-lang/ex_doc/commit/425378e393769a857dd414255cc83be82e5f079e"><code>425378e</code></a> Release v0.39.2</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/10d8315f7ba2e0e55093580707ff5788fa889922"><code>10d8315</code></a> Ensure IDs rather than hrefs are stripped, closes <a href="https://github.com/elixir-lang/ex_doc/issues/2175">#2175</a></li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/72bb755a90c9a98b645e7e923ebd3bb85ead8f32"><code>72bb755</code></a> Show go to latest for prereleases, closes <a href="https://github.com/elixir-lang/ex_doc/issues/2173">#2173</a></li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/6db9cab2742a19488376e870060f62a589bec672"><code>6db9cab</code></a> Fix docs: Move <code>source_url</code> to <code>project</code> (<a href="https://github.com/elixir-lang/ex_doc/issues/2172">#2172</a>)</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/e7abbaedb88eed88858f85b53862801e5f456a32"><code>e7abbae</code></a> Add Elixir v1.19 and Erlang/OTP 28 to CI (<a href="https://github.com/elixir-lang/ex_doc/issues/2166">#2166</a>)</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/60203be6699d00abef9e054bdcd0669fbca7ae43"><code>60203be</code></a> Update assets</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/a4927a41cd3d6becc3a4e9540fb35ed6c5fb9403"><code>a4927a4</code></a> Prevent fake italic in autocomplete text (<a href="https://github.com/elixir-lang/ex_doc/issues/2168">#2168</a>)</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/c8d1e682a4dc7a1355103b858534f46734f5c78c"><code>c8d1e68</code></a> Rename Search Hexdocs link to Go to package docs</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/33b1ffca53807808ae23fc915f54cd13bd5c5920"><code>33b1ffc</code></a> Release v0.39.1</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/5bb6c18048c4f7c314fc13e4a424fa6c45e9eebb"><code>5bb6c18</code></a> Update assets</li> <li>Additional commits viewable in <a href="https://github.com/elixir-lang/ex_doc/compare/v0.39.1...v0.39.2">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Problem <!-- what problem is the PR is trying to solve? --> ## Solution <!-- how is the PR solving the problem? --> ## Rationale <!-- why was it implemented the way it was? --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved conditional dependency handling for session storage to ensure graceful operation when optional libraries are unavailable. No behavioral changes for existing deployments. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Bumps [credo](https://github.com/rrrene/credo) from 1.7.13 to 1.7.14. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/rrrene/credo/releases">credo's releases</a>.</em></p> <blockquote> <h2>v1.7.14</h2> <p>Check it out on Hex: <a href="https://hex.pm/packages/credo/1.7.14">https://hex.pm/packages/credo/1.7.14</a></p> <ul> <li>Fixed regression for <code>DuplicatedCode</code></li> <li>Expanded <code>Credo.Check.Warning.ExpensiveEmptyEnumCheck</code> to cover less obvious cases</li> <li>New Check: <code>Credo.Check.Warning.StructFieldAmount</code></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rrrene/credo/blob/master/CHANGELOG.md">credo's changelog</a>.</em></p> <blockquote> <h2>1.7.14</h2> <ul> <li>Fixed regression for <code>DuplicatedCode</code></li> <li>Expanded <code>Credo.Check.Warning.ExpensiveEmptyEnumCheck</code> to cover less obvious cases</li> <li>New Check: <code>Credo.Check.Warning.StructFieldAmount</code></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rrrene/credo/commit/b3a8c4ac73b155c21a02683d37dcb523b74f465d"><code>b3a8c4a</code></a> Bump version to 1.7.14</li> <li><a href="https://github.com/rrrene/credo/commit/677f6389a6d38a957811d1df3b71374ea9081cda"><code>677f638</code></a> Update CHANGELOG</li> <li><a href="https://github.com/rrrene/credo/commit/57deb6fdfbb1e1d3b481a7e395ba732c0e757800"><code>57deb6f</code></a> Fix warnings for slow usage of <code>length/1</code></li> <li><a href="https://github.com/rrrene/credo/commit/ace6edda853c9b9163ab0dc55fca843d8e62633d"><code>ace6edd</code></a> Fix missing dep</li> <li><a href="https://github.com/rrrene/credo/commit/1ffd3b235d1f920a8b54b3baf416af7c9b8b89f7"><code>1ffd3b2</code></a> Inline pipe</li> <li><a href="https://github.com/rrrene/credo/commit/d182b847f282c69ac73355526e87a4dfb0980418"><code>d182b84</code></a> Add inch_ex</li> <li><a href="https://github.com/rrrene/credo/commit/a006b49aa56b9bfce0e1e74ef7ea3c445827c681"><code>a006b49</code></a> Fix housekeeping workflow</li> <li><a href="https://github.com/rrrene/credo/commit/cef51ea8b5c8e0586b51e5da02c51e94d49f2362"><code>cef51ea</code></a> Refactor ExpensiveEmptyEnumCheck</li> <li><a href="https://github.com/rrrene/credo/commit/e781dbb93149c2de4671ed9b76b4bca8d15cb85b"><code>e781dbb</code></a> Merge branch 'comparison-against-1' of github.com:hauleth/credo into 1226-emp...</li> <li><a href="https://github.com/rrrene/credo/commit/c20779e6c09c32d250354bf1262aef8759245f16"><code>c20779e</code></a> Update Elixir to 1.19.3</li> <li>Additional commits viewable in <a href="https://github.com/rrrene/credo/compare/v1.7.13...v1.7.14">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zoey <zoey.spessanha@zeetech.io>
🚀 Want to release this? --- ## [0.17.0](zoedsoupe/anubis-mcp@v0.16.0...v0.17.0) (2025-12-09) ### Features * **redis:** add redix_opts for SSL/TLS support ([zoedsoupe#59](zoedsoupe#59)) ([33658ab](zoedsoupe@33658ab)) ### Bug Fixes * added server component description/0 callback ([zoedsoupe#58](zoedsoupe#58)) ([a094473](zoedsoupe@a094473)) * redix should be loaded ([zoedsoupe#71](zoedsoupe#71)) ([09b872f](zoedsoupe@09b872f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Redis SSL/TLS support via redix options. * **Bug Fixes** * Fixed server component description callback issue. * Fixed redix loading issue. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.40.0 to 0.40.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/elixir-lang/ex_doc/blob/main/CHANGELOG.md">ex_doc's changelog</a>.</em></p> <blockquote> <h2>v0.40.1 (2026-01-31)</h2> <ul> <li> <p>Enhancements</p> <ul> <li>Remove link to source from generated .md files</li> <li>Improve word-breaking of module names and sizing of main page titles</li> <li>Include description in llms.txt</li> </ul> </li> <li> <p>Bug fixes</p> <ul> <li>Fix headers in custom groups</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/elixir-lang/ex_doc/commit/20a355b005c31f3ba38c7729d52a02571ea245cd"><code>20a355b</code></a> Release v0.40.1</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/7a71ddf985ca531cc5ab8e0e3c81812209f31cd9"><code>7a71ddf</code></a> Update assets</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/f44f6fe6aae77960b100cd08878986208449a960"><code>f44f6fe</code></a> Turn whitespace minification back on</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/38028674ac14570a700ba8804d6ca4cbba1dc951"><code>3802867</code></a> Improve distinction between docstring headings (H2-H4)</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/e8a46c6fa7d8af5a24af6caf7a266e7995c51ce2"><code>e8a46c6</code></a> Change headings' levels to match their context</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/9cd866c84ccdd1afa9eee772d72511c5ef99cbae"><code>9cd866c</code></a> Fix Summary Types heading size</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/e8e74eec1881dae173e02cf8713ff65e88540d68"><code>e8e74ee</code></a> More word break tests</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/21ec71f709317bdd2e32b6d4d6055857d3761552"><code>21ec71f</code></a> Update assets</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/8611a164fe24d7b9f669cdad96dcaf30e8254fc1"><code>8611a16</code></a> Improve word-breaking of module names and sizing of main page titles (<a href="https://github.com/elixir-lang/ex_doc/issues/2190">#2190</a>)</li> <li><a href="https://github.com/elixir-lang/ex_doc/commit/1b1fe51e479b9bcbf72802e7ef700ed3cedf53ac"><code>1b1fe51</code></a> Bump lodash from 4.17.21 to 4.17.23 in /assets (<a href="https://github.com/elixir-lang/ex_doc/issues/2187">#2187</a>)</li> <li>Additional commits viewable in <a href="https://github.com/elixir-lang/ex_doc/compare/v0.40.0...v0.40.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary This fixes a race condition where responses could be silently lost when an SSE handler process died but the transport hadn't yet processed the `:DOWN` message. **The issue:** 1. SSE handler process dies (network drop, crash, etc.) 2. `:DOWN` message is queued to transport GenServer 3. Before transport processes `:DOWN`, a new request calls `get_sse_handler` 4. `get_sse_handler` returns the stale PID 5. `send/2` silently drops the message to the dead process 6. Client receives HTTP 202 but never gets the actual response **The fix:** - Add `Process.alive?` check in `route_sse_response` before sending - If the handler is stale, clean up the entry and establish a new SSE connection ## Test plan - [x] All existing tests pass (519 tests, 0 failures) - [x] Verified fix in production application (Flux MCP server) 🤖 Generated with [Claude Code](https://claude.ai/code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Improvements** * Server-Sent Events connections are now more resilient with enhanced validation and automatic recovery for stale connections, significantly improving real-time communication reliability and reducing message delivery failures in active use. * **Configuration** * Session logging level is now optional, offering greater configuration flexibility and enabling simplified setup when explicit specification is not required. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Problem The codebase has version-specific protocol logic scattered across multiple modules (Anubis.Protocol, Anubis.MCP.Message, Anubis.Server.Base, Anubis.Server). Adding support for a new MCP spec version means touching many places, and the server macro module had incorrect hardcoded version strings (2024-05-11, 2024-10-07) that don't exist in the supported versions list. This is Phase 1 of the architecture refactor plan addressing issues hermes#179 and hermes#141. ## Solution - Created Anubis.Protocol.Behaviour defining callbacks each version module must implement (version, features, schemas, methods) - Created per-version modules (V2024_11_05, V2025_03_26, V2025_06_18) under lib/anubis/protocol/ encoding version-specific schemas, features, and method lists - Created Anubis.Protocol.Registry as the central dispatch point mapping version strings to modules, with negotiation support - Refactored Anubis.Protocol to delegate to the Registry while preserving its entire public API (zero breaking changes) - Updated Server.Base to use Registry.negotiate/2 instead of a private negotiation function - Fixed Anubis.Server macro to derive @protocol_versions from the Registry instead of a hardcoded (incorrect) list - Stored the negotiated protocol module in Session, Client.State, and Frame.private for downstream use in later phases - Added 64 new tests covering the Registry, version modules, behaviour compliance, feature inheritance, and backward compatibility ## Rationale Version modules inherit from their predecessor (V2025_03_26 delegates to V2024_11_05 for unchanged schemas) to avoid duplication while making differences explicit. The Registry is a compile-time map (not a GenServer) since version data is static. Anubis.Protocol's public API was preserved via defdelegate and thin wrappers so this is a purely internal refactor — no downstream code changes required. Storing the resolved protocol module in session/connection state enables later phases to dispatch version-specific logic without re-resolving. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added multi-version MCP protocol support with dynamic version negotiation and fallback handling. * Introduced version-aware feature discovery to identify capabilities across supported protocol versions. * Enabled automatic protocol module resolution during client initialization. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…oedsoupe#95) ## Problem Transport modules are tightly coupled to GenServer processes, making them impossible to use as pure functions for message parsing/encoding. This blocks Phase 3/4 of the architecture refactor where transports need to be called directly from Session processes and Plug pipelines without a separate transport process. ## Solution Implement the functional `Anubis.Transport` behaviour callbacks (`transport_init/1`, `parse/2`, `encode/2`, `extract_metadata/2`) across all 6 transport modules: - `Anubis.Transport.STDIO` — newline-delimited JSON with partial message buffering - `Anubis.Transport.StreamableHTTP` — JSON with batch array support - `Anubis.Transport.SSE` — JSON string/map parsing - `Anubis.Server.Transport.STDIO` — same as client, with server metadata - `Anubis.Server.Transport.StreamableHTTP` — JSON with Plug.Conn metadata extraction - `Anubis.Server.Transport.SSE` — SSE event format encoding, Plug.Conn metadata Added 64 unit tests covering parse/encode round-trips, buffering, batching, metadata extraction, and cross-transport consistency. ## Rationale Functional callbacks are added alongside existing GenServer code (no breaking changes). The GenServer transport processes remain for backward compatibility — they will be removed in Phase 3 (Server) and Phase 4 (Client) when the architecture shifts to Session-owns-transport. This incremental approach keeps all existing tests passing while preparing the foundation for the next phases.
🚀 Want to release this? --- ## [0.17.1](zoedsoupe/anubis-mcp@v0.17.0...v0.17.1) (2026-02-28) ### Bug Fixes * Check Process.alive? before sending to SSE handler ([zoedsoupe#82](zoedsoupe#82)) ([e1dc705](zoedsoupe@e1dc705)) ### Code Refactoring * **phase-1:** abstract protocol version negotiation ([zoedsoupe#93](zoedsoupe#93)) ([05a2362](zoedsoupe@05a2362)) * **phase-2:** transport layer as functions, backward compatible ([zoedsoupe#95](zoedsoupe#95)) ([105d6a9](zoedsoupe@105d6a9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
…soupe#96) ## Problem The server architecture had a single-GenServer bottleneck (`Server.Base`) that serialized all requests across all sessions through one mailbox. The `Frame` struct accumulated internal state (`transport`, `request`, `private`, `initialized`) that leaked implementation details to users and created transport-dependent branching in user code. Related: https://github.com/cloudwalk/hermes-mcp/issues/179, https://github.com/cloudwalk/hermes-mcp/issues/#141, RFC zoedsoupe#24 ## Solution **Phase 3 — Session-Centric Architecture** - Each MCP session is now an independent GenServer process under `Session.Supervisor` (DynamicSupervisor) - `Server.Base` becomes a coordinator: session lifecycle management, expiry timers, and delegation — no longer processes MCP requests directly - Transport modules (`StreamableHTTP.Plug`, `SSE.Plug`, `STDIO`) route requests to the correct Session process via `Registry` - `Registry` is pluggable (`Registry.Adapter` behaviour) with `Registry.Local` (ETS) as default, supporting future distributed implementations (Horde, Phoenix.Tracker) - Heavy tool execution offloaded to `Task.Supervisor` per session, keeping the session mailbox responsive **Phase 3.5 — Context Refactor** - Introduced `Anubis.Server.Context` — a minimal 4-field struct (`session_id`, `client_info`, `headers`, `remote_ip`) added as a read-only field on `Frame` - Removed `Frame.transport`, `Frame.request`, and `Frame.initialized` fields — these were internal state that polluted the user-facing struct - Transport-agnostic design: STDIO naturally has `headers: %{}, remote_ip: nil`, no type branching needed - Added `Frame.to_saved/1` and `Frame.from_saved/1` for `Session.Store` integration — context is omitted (request-scoped), only user state persists - Session recovery flow: `Registry.lookup` → miss → `Store.load` → `DynamicSupervisor.start_child` → `Registry.register` - No process dictionary usage — context is a value passed through Frame, works naturally with Tasks and async code ## Rationale **Session-per-process over shared GenServer**: the old design forced all sessions through one mailbox — a slow tool call in session A blocked unrelated requests in session B. OTP's model is one process per concurrent unit of work, and an MCP session is exactly that. **Context as a Frame field over process dictionary**: `Process.put` doesn't propagate to `Task.async` spawns, creating silent failures. A struct field on Frame is explicit, testable, and works everywhere Frame is passed. **Minimal Context (4 fields) over full request mirror**: the original plan had 7+ fields including `protocol_version`, `initialized`, `request.id`, `request.method`, `request.params`, and transport type unions. Most duplicated data already available through callback arguments or enforced by Session lifecycle. Users should never branch on transport type — that defeats transport-agnostic design. **Registry and Store as orthogonal concerns**: Registry answers "where is the process?" (ephemeral, dies with process). Store answers "what was the state?" (durable, survives restarts). Both are optional and pluggable independently. --- **Next steps**: - Phase 4 — Client refactor: decompose `Client.Base` (1634 LOC) into `Client.Handlers` + `Client.Sampling` - Phase 5 — Dead code removal, deduplication audit, and documentation fixes (including `CONTRIBUTING.md` license mismatch, outdated API examples in hexdocs pages, missing `pages/home.md`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Error responses now follow JSON‑RPC 2.0 envelope with a top-level "jsonrpc": "2.0". * **Refactor** * Notification API simplified — sending notifications no longer requires passing per-frame state. * Sessions moved to a session-centric model with session-based routing for transports. * Registry and naming model modernized for deterministic transport/session names and pluggable registry options. * Frame model streamlined to public component maps and a read-only per-request context. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem `Anubis.Client.Base` module is currently massive, this is a first try to reduce it ## Solution Extracted sampling capability and other message handlers (tool calls responses for ex) to separate modules ## Rationale N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated Zig tooling in release workflows from v0.14.1 to v0.15.2. * **Refactor** * Reorganized internal client notification and sampling request handling into dedicated modules for improved maintainability and separation of concerns; no changes to external behavior or public interfaces. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Bumps [telemetry](https://github.com/beam-telemetry/telemetry) from 1.3.0 to 1.4.1. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/beam-telemetry/telemetry/blob/main/CHANGELOG.md">telemetry's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/elixir-telemetry/telemetry/tree/v1.4.1">1.4.1</a></h2> <h3>Fixed</h3> <ul> <li>Avoid crashes when <code>telemetry</code> is invoked before started (such as during Elixir compile-time)</li> </ul> <h2><a href="https://github.com/elixir-telemetry/telemetry/tree/v1.4.0">1.4.0</a></h2> <h3>Added</h3> <ul> <li>Add <code>telemetry:persist/0</code> which uses persistent term for faster dispatches (writes are extremely discouraged after persist)</li> </ul> <h3>Fixed</h3> <ul> <li>Fix the <code>telemetry:span_function/0</code> type</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/beam-telemetry/telemetry/commit/11462db509623be85c7acf3f15d0579d0d3f4a79"><code>11462db</code></a> Release v1.4.1</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/11210b44b3bb431059a99847ccaec20352b5bac5"><code>11210b4</code></a> Do not crash on failed persistent term lookup</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/972ff3bb1b0b95f907d93bbb3726b95eee7b725c"><code>972ff3b</code></a> Release v1.4.0</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/ddc7f13e4f93d103422f98eb481d3bade2cb73f8"><code>ddc7f13</code></a> Add "since" doc info and spec to persist/0 (<a href="https://github.com/beam-telemetry/telemetry/issues/146">#146</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/55d657eb6102b8a81a519e9abca5990506e00ee8"><code>55d657e</code></a> Remove function allocation and remote call on execution (<a href="https://github.com/beam-telemetry/telemetry/issues/145">#145</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/c0aff75703636e93dcc581f3dc84c9a7f4dc5870"><code>c0aff75</code></a> Implement <code>telemetry:persist/0</code> (<a href="https://github.com/beam-telemetry/telemetry/issues/144">#144</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/614bfb91e9e42e305b95860cc64d237c01435d65"><code>614bfb9</code></a> Use field name instead of magic number (<a href="https://github.com/beam-telemetry/telemetry/issues/143">#143</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/13a380ed0214a8f5824c99ef9897db50de84c90c"><code>13a380e</code></a> Test CI against multiple OTP versions (24-28) (<a href="https://github.com/beam-telemetry/telemetry/issues/140">#140</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/2f29d755aaf98d1c49a166cf5372755bb7033e72"><code>2f29d75</code></a> Improve docs for failure events (<a href="https://github.com/beam-telemetry/telemetry/issues/139">#139</a>)</li> <li><a href="https://github.com/beam-telemetry/telemetry/commit/7b99309898cc827fda3f1956e23d34d349453f16"><code>7b99309</code></a> Fix the telemetry:span_function/0 type (<a href="https://github.com/beam-telemetry/telemetry/issues/137">#137</a>)</li> <li>See full diff in <a href="https://github.com/beam-telemetry/telemetry/compare/v1.3.0...v1.4.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [credo](https://github.com/rrrene/credo) from 1.7.15 to 1.7.17. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/rrrene/credo/releases">credo's releases</a>.</em></p> <blockquote> <h2>v1.7.17</h2> <p>Check it out on Hex: <a href="https://hex.pm/packages/credo/1.7.17">https://hex.pm/packages/credo/1.7.17</a></p> <ul> <li><code>Credo.Check.Readability.ModuleDoc</code> add new param <code>:ignore_modules_using</code> (defaults to <code>[Credo.Check, Ecto.Schema, Phoenix.LiveView, ~r/\.Web$/]</code>)</li> <li><code>Credo.Check.Warning.UnusedOperation</code> update <code>:modules</code> param: instead of a list of functions to check, <code>:all</code> can be given to check all functions in a module</li> <li>New Check: <code>Credo.Check.Refactor.CondInsteadOfIfElse</code></li> <li>New Check: <code>Credo.Check.Warning.WrongTestFilename</code></li> </ul> <h2>v1.7.16</h2> <p>Check it out on Hex: <a href="https://hex.pm/packages/credo/1.7.16">https://hex.pm/packages/credo/1.7.16</a></p> <ul> <li>Fix compatibility & compiler warnings with Elixir 1.20.0-rc.1</li> <li><code>Credo.Check.Refactor.PassAsyncInTestCases</code> add new param <code>:force_comment_on_explicit_false</code> (defaults to <code>false</code>)</li> <li><code>Credo.Check.Warning.Dbg</code> add new param <code>:allow_captures</code> (defaults to <code>false</code>)</li> <li>New Check: <code>Credo.Check.Warning.UnusedMapOperation</code></li> <li>New Check: <code>Credo.Check.Warning.UnusedOperation</code></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rrrene/credo/blob/master/CHANGELOG.md">credo's changelog</a>.</em></p> <blockquote> <h2>1.7.17</h2> <ul> <li><code>Credo.Check.Readability.ModuleDoc</code> add new param <code>:ignore_modules_using</code> (defaults to <code>[Credo.Check, Ecto.Schema, Phoenix.LiveView, ~r/\.Web$/]</code>)</li> <li><code>Credo.Check.Warning.UnusedOperation</code> update <code>:modules</code> param: instead of a list of functions to check, <code>:all</code> can be given to check all functions in a module</li> <li>New Check: <code>Credo.Check.Refactor.CondInsteadOfIfElse</code></li> <li>New Check: <code>Credo.Check.Warning.WrongTestFilename</code></li> </ul> <h2>1.7.16</h2> <ul> <li>Fix compatibility & compiler warnings with Elixir 1.20.0-rc.1</li> <li><code>Credo.Check.Refactor.PassAsyncInTestCases</code> add new param <code>:force_comment_on_explicit_false</code> (defaults to <code>false</code>)</li> <li><code>Credo.Check.Warning.Dbg</code> add new param <code>:allow_captures</code> (defaults to <code>false</code>)</li> <li>New Check: <code>Credo.Check.Warning.UnusedMapOperation</code></li> <li>New Check: <code>Credo.Check.Warning.UnusedOperation</code></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rrrene/credo/commit/068fcc7bfb3d35ed35a000bd2a9a02b637114119"><code>068fcc7</code></a> Bump version to 1.7.17</li> <li><a href="https://github.com/rrrene/credo/commit/5eccc0d146291867ec6f1e22425159484185b3f8"><code>5eccc0d</code></a> Update CHANGELOG</li> <li><a href="https://github.com/rrrene/credo/commit/0b087207d614db8c31fd3aac0f659c49d750a382"><code>0b08720</code></a> Update .credo.exs</li> <li><a href="https://github.com/rrrene/credo/commit/122a258459418e4ca1f9b1cffbc78b11be870a3e"><code>122a258</code></a> Add :excludes to .formatter.exs</li> <li><a href="https://github.com/rrrene/credo/commit/09960e67678f5fc8e7e06d715eb3d94702d48590"><code>09960e6</code></a> Add defaults to :ignore_modules_using in ModuleDoc</li> <li><a href="https://github.com/rrrene/credo/commit/472f12e222abed650d95c8b662836b68da114836"><code>472f12e</code></a> Add repro for <a href="https://github.com/rrrene/credo/issues/1235">#1235</a> to prevent regressions</li> <li><a href="https://github.com/rrrene/credo/commit/11235d5754a1c93eb321ce2b2e989ed8601c0a0d"><code>11235d5</code></a> Merge branch '1254-module-doc-new-param'</li> <li><a href="https://github.com/rrrene/credo/commit/e73ea15e05a2d2a14083a0b1567b021d9acfb084"><code>e73ea15</code></a> Integrate new param for ModuleDoc</li> <li><a href="https://github.com/rrrene/credo/commit/0cfeba513f76b074a9be9913003115b9df9ada60"><code>0cfeba5</code></a> Update check id for WrongTestFilename</li> <li><a href="https://github.com/rrrene/credo/commit/04cb8633f9bff15557f062b1ca243a962eb53c8c"><code>04cb863</code></a> Merge branch '1258-new-test-files-check'</li> <li>Additional commits viewable in <a href="https://github.com/rrrene/credo/compare/v1.7.15...v1.7.17">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…andlers (zoedsoupe#109) ## Problem After adding Anubis 0.17.1 I noticed that memory usage of my Phoenix application slowly climbed over the hours until it ran out of memory and died. It's a pre-production app with little usage and when that happened there were just logs to connect to the MCP server. ## Solution After adding some tracking, GPT-5.3-Codex diagnosed this as follows: - In streamable HTTP transport, SSE handlers are keyed by session_id. - Reconnects on the same `session_id` can overwrite map entries, and old stream processes can become orphaned (no longer in `sse_handlers`). - Orphaned stream loops sit in receive forever. - `expiry_timers` map in Anubis server is not cleaned on `:session_expired` path. With this fix: - adding pid-aware `unregister_sse_handler/3` so only the expected handler can remove itself - replacing existing handlers safely on register (demonitor old ref, close old handler, monitor/store the new handler) - updating plug on-close and stale-handler cleanup paths to pass the handler pid ## Rationale I've tested this and deployed it to my app, and memory usage has been stable the last few hours. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Enhanced Server-Sent Events (SSE) handler registration logic to properly manage concurrent handler instances for the same session, preventing race conditions and ensuring consistent handler state. * **Tests** * Added test case to verify SSE handler lifecycle behavior when multiple handlers are registered for the same session. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem I have an Elixir app that provides an MCP server and I wanted to utilize the new MCP Apps extension (https://modelcontextprotocol.io/extensions/apps/overview). To do this, I needed support for adding the _meta field to tool declarations so clients know which visual resource to render alongside a tool's output. ## Solution I added a meta field to the Tool struct and wired it through the JSON encoder so _meta appears in the serialized MCP tool object. Tools can now declare `meta: %{"ui" => %{"resourceUri" => "ui://my-app/dashboard"}}` via `use Anubis.Server.Component`. ## Rationale This is the minimal change needed to support the MCP spec's _meta field — I only touched the Tool struct and its serialization path. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Tool components now support optional metadata that can be provided during tool definition and is automatically included in exported tool information and JSON responses. * **Tests** * Added comprehensive tests validating metadata functionality, including JSON encoding and callback optionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Problem Warning `Session store enabled but adapter not available` when the session store is not enabled. ## Solution Properly check the config's `enabled` boolean param ## Rationale <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Refactored session store initialization to improve configuration handling and logging. * **Tests** * Added test coverage for session store configuration scenarios and related logging. * **Note** * No user-facing changes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…upe#98) (zoedsoupe#155) ## Problem Closes zoedsoupe#98. MCP 2025-11-25 introduces Tasks — durable state machines wrapping long-running JSON-RPC requests so requestors can poll instead of relying on timeouts or progress notifications. ## Solution **Phase 1 — server-receiver for `tools/call` only.** Implements: - New protocol module `V2025_11_25` (latest); registers `tasks/get|result|cancel|list` + `notifications/tasks/status` - `:tasks` capability on `use Anubis.Server` (`list?`, `cancel?`, `requests:`) - Tool-level `task_support: :forbidden | :optional | :required`; renders as `execution.taskSupport` in `tools/list`; enforced in `Handlers.Tools` (required→reject non-augmented, forbidden→reject augmented) - `Anubis.Server.Task` struct + `Anubis.Server.TaskStore` behaviour with `Local` adapter; pluggable via `:task_store {mod, opts}` in `Anubis.Server.Supervisor` (mirrors `:registry`/`:supervisor`); supports `:via` for distributed adapters via optional `resolve_name/2` callback - `Frame.task_id` propagated to worker callbacks - Session: detects `params.task` on `tools/call`, persists `Task`, spawns worker via existing `Task.Supervisor`, immediately returns `CreateTaskResult` with `_meta[related-task]`. Routes `tasks/get|cancel|result|list`. `tasks/result` blocks until terminal via per-task waiter list. TTL timer + cancel paths release waiters with proper errors. Terminate cleans up workers + waiters - `Server.send_task_status/1` API → emits `notifications/tasks/status` from session 15 deterministic tests (signal-based stub server, `SyncHelpers.await_state` — no `Process.sleep`). 757 tests + 33 doctests pass; credo strict clean; dialyzer pass. ## Deferred to follow-up PRs - **Phase 2** — client-as-requestor for `tools/call` (`Client.call_tool(task: [ttl: N])`, `get_task/task_result/cancel_task` helpers; return shape decided when designed) - **Phase 3** — server-as-requestor for `sampling/createMessage` + `elicitation/create` - **`tasks/list`** — needs auth-context binding through `Anubis.Server.Context` first; Phase 1 returns `-32601` - **Redis `TaskStore` adapter** — slots into the behaviour without API change - **`input_required` status flow** — schema accepts it; Phase 1 worker path never produces it ## Rationale Phase 1 ships the highest-value slice (server author exposes a long-running tool with a single `task_support: :optional`). Pluggable storage day-one means distributed adapters land later as drop-ins. Strict `2025-11-25` gate keeps the spec contract clean — older protocol versions don't see Tasks. Signal-driven tests over `Process.sleep` keep the suite fast and deterministic, matching the existing async-dispatch pattern.
🚀 Want to release this? --- ## [1.5.0](zoedsoupe/anubis-mcp@v1.4.0...v1.5.0) (2026-05-09) ### Features * MCP Tasks (2025-11-25) — server-receiver for tools/call ([zoedsoupe#98](zoedsoupe#98)) ([zoedsoupe#155](zoedsoupe#155)) ([51348f1](zoedsoupe@51348f1)) ### Bug Fixes * drop compile-connected deps from component/1 macro ([zoedsoupe#154](zoedsoupe#154)) ([1e368b9](zoedsoupe@1e368b9)) ### Continuous Integration * fix flaky test ([939fd76](zoedsoupe@939fd76)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
## Problem MCP servers had no built-in way to authenticate clients per the spec's OAuth 2.1 authorization model. ## Solution Add `Anubis.Server.Authorization` with pluggable `Validator` behaviour, `JWTValidator` (JWKS-backed) and `IntrospectionValidator` impls, `.well-known/oauth-protected-resource` discovery, and 401 + `WWW-Authenticate` enforcement in the SSE and Streamable HTTP plugs. Bearer token claims surface on the request `Frame` so handlers can scope/authorize. ## Rationale Validator behaviour keeps token verification out of the transport layer and lets users plug in custom auth servers. JOSE is optional — JWT validator only compiles when `:jose` is present.
🚀 Want to release this? --- ## [1.6.0](zoedsoupe/anubis-mcp@v1.5.0...v1.6.0) (2026-05-18) ### Features * add OAuth 2.1 authorization for MCP servers ([zoedsoupe#158](zoedsoupe#158)) ([a12a8f6](zoedsoupe@a12a8f6)) * add Registry.PG for distributed session tracking via :pg ([zoedsoupe#160](zoedsoupe#160)) ([512e103](zoedsoupe@512e103)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
🚀 Want to release this? --- ## [1.6.1](zoedsoupe/anubis-mcp@v1.6.0...v1.6.1) (2026-05-23) ### Bug Fixes * Echo request id in "Server not initialized" error ([zoedsoupe#168](zoedsoupe#168)) ([226b71e](zoedsoupe@226b71e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
…ry miss In multi-instance (horizontally scaled) deployments, notification and response POSTs can be routed to a node whose local registry never saw the session. The request path already recovers via find_or_create_session/3 (which restores from the configured Session.Store), but handle_notification_message and handle_response_message returned 404 on a registry miss without consulting the store. This makes them mirror the request path: on a registry miss, restore the session from the store if it exists there, otherwise keep the 404. With no store configured (single node), behaviour is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughProblemSession requests can fail on multi-instance deployments when the session is not in the local registry. SolutionRestore sessions from the configured RationalePreserves single-node 404 behavior while allowing valid sessions routed across instances to succeed. WalkthroughNotification and response message handling now use 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/anubis/server/transport/streamable_http/plug.ex (1)
191-216: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winP1: Handle unexpected restoration errors to prevent a
CaseClauseErrorcrash.Because
start_and_auto_initialize_session/2can return an{:error, reason}tuple (e.g., if auto-initialization fails or the process fails to start), passing that back throughfind_or_restore_session/2will trigger a sneakyCaseClauseErrorhere since we only match{:ok, session_pid}and{:error, :not_found}.Let's add a catch-all error clause to log the failure and gracefully return an HTTP 500 instead of completely crashing the Plug process 😎.
🛠️ Proposed fix to handle restoration errors
defp handle_notification_message(conn, message, session_id, context, opts) do case find_or_restore_session(opts, session_id) do {:ok, session_pid} -> GenServer.cast(session_pid, {:mcp_notification, message, context}) conn |> put_resp_content_type("application/json") |> send_resp(202, "{}") {:error, :not_found} -> send_error(conn, 404, "Session not found") + + {:error, reason} -> + Logging.transport_event("session_restore_failed", %{reason: inspect(reason)}, level: :error) + send_error(conn, 500, "Failed to restore session") end end defp handle_response_message(conn, message, session_id, context, opts) do case find_or_restore_session(opts, session_id) do {:ok, session_pid} -> GenServer.cast(session_pid, {:mcp_response, message, context}) conn |> put_resp_content_type("application/json") |> send_resp(202, "{}") {:error, :not_found} -> send_error(conn, 404, "Session not found") + + {:error, reason} -> + Logging.transport_event("session_restore_failed", %{reason: inspect(reason)}, level: :error) + send_error(conn, 500, "Failed to restore session") end end
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 80feb8bb-a7ae-4aca-8903-13c72c5601f9
📒 Files selected for processing (1)
lib/anubis/server/transport/streamable_http/plug.ex
|
please, merge the |
The merge-base changed after approval.
|
hey, i've messed with the history but i've fixed it and manually merged your contribution. so sorry for that and thanks again for the contribution |
🚀 Want to release this? --- ## [1.9.0](v1.8.0...v1.9.0) (2026-07-16) ### Features * **streamable_http:** add spec resumability (Last-Event-ID replay) ([#216](#216)) ([78e33b4](78e33b4)) * support pre_initialized sessions for cross-pod restore ([#187](#187)) ([13be0d7](13be0d7)) ### Bug Fixes * **session:** return encodable JSON-RPC errors when init/2 fails ([#211](#211)) ([f9af7cc](f9af7cc)) * **streamable_http:** emit telemetry on SSE handler registration ([#217](#217)) ([4a4c528](4a4c528)) * **streamable_http:** restore session from store on notif/resp registry miss ([#221](#221)) ([d757b39](d757b39)) * **streamable_http:** return correct JSON-RPC error codes for parse failures ([#222](#222)) ([1867994](1867994)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Problem
In a horizontally scaled (multi-instance) Streamable-HTTP deployment where nodes are not clustered (no distributed Erlang between instances — common on Cloud Run / serverless), MCP session state held in
Registry.Local(node-local ETS) is invisible to other instances.The request path already handles this:
handle_request_message/5→find_or_create_session/3, which on a registry miss starts a session and, when aSession.Storeis configured, restores it viamaybe_restore_from_store/1.But
handle_notification_message/5andhandle_response_message/5callfind_session/2(registry only) and return404 "Session not found"on a miss — they never consult the configuredSession.Store.Observed failure
initialize(no session id) → instance A creates + persists the session, returnsmcp-session-id.notifications/initialized(session id present) → load-balanced to instance B → registry miss → 404, notification lost.This is intermittent and instance-correlated, and it breaks clients (e.g. the claude.ai MCP connector) that treat the handshake-notification 404 as a fatal transport error — even though a
Session.Store(Redis/DB) is configured.Fix
Make
handle_notification_messageandhandle_response_messageresolve-or-restore from the store on a registry miss, mirroring what the request path already does. When no store is configured (single node), behaviour is unchanged: a registry miss stays a 404.The patch adds
find_or_restore_session/2: on a registry miss, if the session exists inAnubis.get_session_store_adapter(), restore it via the existingstart_and_auto_initialize_session/2; otherwise keep the 404 (so genuinely-missing sessions still 404 rather than being masked).Notes
streamable_http/plug.ex; reuses existingstart_and_auto_initialize_session/2.Session.Storedocs, which already recommend a store for multi-node deployments — this closes the gap where the store isn't consulted on the notif/resp paths.Branch/commit:
mollowai/anubis-mcp@mollow/mcp-notif-resp-store-restore(based onv1.6.1).