Repository navigation
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughStreamable HTTP MCP transport is available at ChangesStreamable HTTP MCP transport
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Uvicorn
participant StreamableHTTPApp
participant MCPServerSessionManager
Client->>Uvicorn: POST /mcp initialize
Uvicorn->>StreamableHTTPApp: Forward authenticated request
StreamableHTTPApp->>MCPServerSessionManager: Create MCP session
MCPServerSessionManager-->>StreamableHTTPApp: Return session ID
StreamableHTTPApp-->>Client: Return initialization response
Client->>Uvicorn: POST /mcp with session ID
Uvicorn->>StreamableHTTPApp: Route MCP request
StreamableHTTPApp->>MCPServerSessionManager: Route request to session
StreamableHTTPApp-->>Client: Return MCP response
Client->>Uvicorn: DELETE /mcp with session ID
Uvicorn->>StreamableHTTPApp: Forward termination request
StreamableHTTPApp->>MCPServerSessionManager: Remove session
StreamableHTTPApp-->>Client: Return termination response
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/test_streamable_http.py (1)
50-211: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCoverage is strong but has three gaps; add them together.
The lifecycle, auth, DELETE-cleanup, DNS-rebinding, and independent-session tests are solid and each asserts a concrete outcome. Per the comprehensive-review requirement for
tests/**, here are the missing scenarios to add in one pass rather than incrementally:
- GET method on
/mcp. The route acceptsmethods=["GET", "POST", "DELETE"](mnemosyne/mcp_server.pyLines 330-334), but no test exercises the GET path (server-initiated SSE stream). Add a test that opens a GET stream on an initialized session and confirms it is accepted (not 405/404).- Wrong (non-empty, invalid) bearer token for Streamable HTTP.
test_streamable_http_non_loopback_rejects_missing_bearer_token(Lines 157-173) only covers a missing token. Add a case sendingAuthorization: Bearer wrong-tokenagainst a non-loopback app and assert the{"error": "invalid bearer token"}401 path in_BearerTokenMiddleware(mnemosyne/mcp_server.pyLines 239-246) is actually reachable.- Idle-timeout behavior.
test_streamable_http_delete_removes_session_from_manager(Lines 109-133) only assertsmanager.session_idle_timeout == 1800, a static config check, not that idle sessions actually expire. Add a test that builds the app with a very smallsession_idle_timeout(or monkeypatches the manager after construction) and asserts an idle session is reaped and subsequent requests return 404, matching the "bounded idle timeout" requirement from the PR objectives.Per path instructions: "Flag missing or weak test scenarios. Verify that new tests actually assert something meaningful (not just "doesn't crash")."
As per path instructions for
tests/**: "COMPREHENSIVE REVIEW REQUIRED IN A SINGLE PASS. Group ALL suggestions for related fixtures/test files together — never iterate one-by-one... Flag missing or weak test scenarios."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_streamable_http.py` around lines 50 - 211, Extend the Streamable HTTP tests around _build_streamable_http_app with three concrete scenarios: open a GET /mcp request for an initialized session and assert it is accepted; send an incorrect non-empty bearer token to a non-loopback app and assert the 401 response with {"error": "invalid bearer token"}; and configure a very short session_idle_timeout, verify an initialized idle session is reaped, then assert a subsequent session request returns 404. Ensure each test exercises the behavior rather than only checking construction or static configuration.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/cli-reference.md`:
- Around line 95-98: Update the `mcp` CLI entry in the command reference to
include the `[--host HOST]` option, and state that it defaults to `127.0.0.1`
alongside the existing token requirement for non-loopback network transports.
In `@docs/integrations/codex-mcp.md`:
- Around line 37-38: Update the non-loopback MCP startup example near the
mnemosyne command to explicitly assign a placeholder bearer token rather than
merely expanding MNEMOSYNE_MCP_TOKEN. Use a clearly non-secret documentation
value while preserving the existing host, port, and transport options.
In `@mnemosyne/mcp_server.py`:
- Around line 258-264: Wrap the Streamable HTTP imports in
_build_streamable_http_app with an ImportError handler matching _build_sse_app,
including mcp.server.streamable_http_manager, mcp.server.transport_security, and
starlette.routing. Convert missing or incompatible dependencies into the same
actionable RuntimeError with installation instructions, rather than allowing a
raw import failure; keep _run_streamable_http’s separate uvicorn import handling
unchanged.
- Around line 308-317: Update the DELETE cleanup in the request handler around
StreamableHTTPSessionManager to avoid unguarded reliance on the private
_server_instances and _session_owners attributes: pin mcp to a bounded range
such as >=2.0.0,<3, and make cleanup skip safely when either private attribute
is unavailable so exceptions cannot escape the finally block.
---
Outside diff comments:
In `@tests/test_streamable_http.py`:
- Around line 50-211: Extend the Streamable HTTP tests around
_build_streamable_http_app with three concrete scenarios: open a GET /mcp
request for an initialized session and assert it is accepted; send an incorrect
non-empty bearer token to a non-loopback app and assert the 401 response with
{"error": "invalid bearer token"}; and configure a very short
session_idle_timeout, verify an initialized idle session is reaped, then assert
a subsequent session request returns 404. Ensure each test exercises the
behavior rather than only checking construction or static configuration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 77399a12-402d-4836-9179-eab05f51e19f
📒 Files selected for processing (11)
CHANGELOG.mdREADME.mddocs/api/configuration.mdxdocs/api/tool-schema.mdxdocs/cli-reference.mddocs/integrations/codex-mcp.mdmnemosyne/__init__.pymnemosyne/cli.pymnemosyne/mcp_server.pyscripts/generate-docs.pytests/test_streamable_http.py
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
mnemosyne/mcp_server.py (1)
343-356: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueWire
lifespanthrough the normal Starlette constructor instead of mutatingapp.router.lifespan_context.
_build_authenticated_mcp_appcurrently returnsStarlette(routes=routes, middleware=middleware)with no lifespan support, then this path overwrites the internallifespan_context. Add an optionallifespanparameter and pass it toStarlette(...), or thread the context inside_build_authenticated_mcp_app, so the Streamable HTTP lifecycle is managed through the documentedStarletteAPI.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mnemosyne/mcp_server.py` around lines 343 - 356, Update _build_authenticated_mcp_app to accept an optional lifespan context and pass it through the Starlette constructor, then provide lifespan when building the Streamable HTTP app and remove the direct app.router.lifespan_context mutation. Preserve existing behavior for callers that do not supply a lifespan.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_streamable_http.py`:
- Around line 204-227: Increase the polling window in
test_streamable_http_idle_session_is_reaped so CI scheduling delays do not cause
intermittent failures; retain the existing 404 assertion and session-id request
flow while using a longer retry budget or bounded wait for the eventual
expired-session response.
---
Outside diff comments:
In `@mnemosyne/mcp_server.py`:
- Around line 343-356: Update _build_authenticated_mcp_app to accept an optional
lifespan context and pass it through the Starlette constructor, then provide
lifespan when building the Streamable HTTP app and remove the direct
app.router.lifespan_context mutation. Preserve existing behavior for callers
that do not supply a lifespan.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: aeac2501-f509-48c2-bc33-4e0895c7603e
📒 Files selected for processing (5)
docs/cli-reference.mddocs/integrations/codex-mcp.mdmnemosyne/mcp_server.pypyproject.tomltests/test_streamable_http.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_streamable_http.py`:
- Around line 214-225: Update the session cleanup test around
manager._server_instances and manager._session_owners to first assert that
session_id is registered in both registries. Poll until session_id has been
removed from both registries, then preserve the existing assertion and request
validation so the test cannot pass when registration never occurred.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: dcc8b779-0fe6-438e-acc4-94bff77dc0f1
📒 Files selected for processing (1)
tests/test_streamable_http.py
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 (3)
tests/test_streamable_http.py (1)
235-254: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winComplete the network-security test matrix.
Verify that invalid
Hostand invalidOriginuse the correct statuses. MCP SDK 2.0.0 returns421for an invalid Host and403for an invalid Origin. If the test expects421for both, correct the assertion. (raw.githubusercontent.com)The bearer tests cover only missing and invalid credentials. Add a valid-token initialization and follow-up request. Assert
200,mcp-session-id, and a successful session operation. Otherwise, middleware that rejects every token could still pass the tests.As per path instructions:
tests/**requires a “COMPREHENSIVE REVIEW REQUIRED IN A SINGLE PASS”, meaningful assertions, edge-case coverage, and coverage of the MCP tool surface.Also applies to: 257-296
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_streamable_http.py` around lines 235 - 254, Expand test_streamable_http_loopback_rejects_dns_rebinding_headers to separately verify invalid Host returns 421 and invalid Origin returns 403, rather than asserting one status for both headers. Extend the bearer-auth tests around the existing missing and invalid credential cases with a valid-token initialization and follow-up session operation, asserting status 200, the mcp-session-id header, and successful MCP behavior; include meaningful edge-case coverage for the exposed MCP tool surface as required.Source: Path instructions
mnemosyne/mcp_server.py (2)
231-239: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winParse bearer tokens case-insensitively.
Authorizationscheme names are case-insensitive, sobearer <token>andBEARER <token>are rejected byheader.startswith("Bearer ")even with correct tokens. Comparebearerwithcasefold(), and feed the stripped credentials intohmac.compare_digest.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mnemosyne/mcp_server.py` around lines 231 - 239, Update the bearer-token validation in the authorization handling block to recognize the Bearer scheme case-insensitively using casefold(), while preserving the missing-token response for other schemes. Strip the scheme and whitespace first, then pass the resulting credentials to hmac.compare_digest against expected.Source: Path instructions
277-292: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winInclude bare loopback hosts with ports in Streamable HTTP security checks.
:*patterns only match values that include a port. Add exact bare entries forlocalhost,127.0.0.1,[::1], andip6-localhostalongside their:*entries. Include the same bare origins forhttp://localhost,http://127.0.0.1,http://[::1], andhttp://ip6-localhostso default-port Streamable HTTP requests are not rejected.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mnemosyne/mcp_server.py` around lines 277 - 292, Update the TransportSecuritySettings construction in the loopback branch of the server setup to add bare host entries alongside each existing `:*` allowed_hosts pattern, and add the corresponding bare HTTP origins alongside the existing port-pattern entries in allowed_origins for localhost, 127.0.0.1, [::1], and ip6-localhost.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@mnemosyne/mcp_server.py`:
- Around line 231-239: Update the bearer-token validation in the authorization
handling block to recognize the Bearer scheme case-insensitively using
casefold(), while preserving the missing-token response for other schemes. Strip
the scheme and whitespace first, then pass the resulting credentials to
hmac.compare_digest against expected.
- Around line 277-292: Update the TransportSecuritySettings construction in the
loopback branch of the server setup to add bare host entries alongside each
existing `:*` allowed_hosts pattern, and add the corresponding bare HTTP origins
alongside the existing port-pattern entries in allowed_origins for localhost,
127.0.0.1, [::1], and ip6-localhost.
In `@tests/test_streamable_http.py`:
- Around line 235-254: Expand
test_streamable_http_loopback_rejects_dns_rebinding_headers to separately verify
invalid Host returns 421 and invalid Origin returns 403, rather than asserting
one status for both headers. Extend the bearer-auth tests around the existing
missing and invalid credential cases with a valid-token initialization and
follow-up session operation, asserting status 200, the mcp-session-id header,
and successful MCP behavior; include meaningful edge-case coverage for the
exposed MCP tool surface as required.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f0d91330-aaed-46db-805e-2abacd6e5264
📒 Files selected for processing (2)
mnemosyne/mcp_server.pytests/test_streamable_http.py
✅ Action performedReview finished.
|
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Dockerfile`:
- Around line 31-34: Update the Dockerfile installation step for the checkout
copied to /opt/mnemosyne so the image installs the dependencies required by the
SSE transport, including starlette and uvicorn, while retaining the existing mcp
dependencies. Use the package’s established SSE extra if available; otherwise
add the required dependencies explicitly to the pip install command so mnemosyne
mcp --transport sse starts successfully.
In `@tests/test_streamable_http.py`:
- Around line 241-265: Add positive coverage alongside exercise for the expanded
loopback allowlist by parameterizing initialization requests with matching
unported Host and Origin values for localhost, [::1], and ip6-localhost. Send
each request through _streamable_http_client and assert successful status, while
preserving the existing rejected-host and rejected-origin assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 778077ef-acda-447b-b8b0-0825cd668ae9
📒 Files selected for processing (3)
Dockerfilemnemosyne/mcp_server.pytests/test_streamable_http.py
| # Install this checkout with MCP + SSE extras so locally built images contain | ||
| # the source that was used to build them. | ||
| COPY . /opt/mnemosyne | ||
| RUN pip install --no-cache-dir "/opt/mnemosyne[mcp]" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
rg -n -C 8 'optional-dependencies|mcp|sse' pyproject.toml
rg -n -C 4 -- '--transport.*sse|transport.*sse' docker-compose.ymlRepository: mnemosyne-oss/mnemosyne
Length of output: 2508
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'Tracked Docker/Compose/config files:\n'
git ls-files | rg -n '(^|/)(Dockerfile|docker-compose\.ya?ml|pyproject\.toml|\.dockerignore)$' || true
printf '\nDockerfile excerpt:\n'
cat -n Dockerfile | sed -n '1,70p'
printf '\npyproject relevant dependency definitions:\n'
cat -n pyproject.toml | sed -n '1,90p'Repository: mnemosyne-oss/mnemosyne
Length of output: 5575
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'Relevant source files:\n'
git ls-files | rg 'mnemosyne/(cli|integrations/mcp|mc)' || true
printf '\nSearch for SSE imports/usages in mnemosyne packages:\n'
rg -n -C 4 'sse|SSE|sse_transport|sse_server|transport' mnemosyne tests 2>/dev/null || true
printf '\nPyProject script/config candidates containing "mcp" or CLI:\n'
rg -n -C 3 'mnemosyne.*mcp|mcp.*mnemosyne|project\.scripts|entry_points|tool\.setuptools' pyproject.toml README.md docs README.rst 2>/dev/null || trueRepository: mnemosyne-oss/mnemosyne
Length of output: 50380
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'mnemosyne package source files (max 200):\n'
git ls-files 'mnemosyne/*' | head -n 200
git ls-files 'mnemosyne_integrations/*' | head -n 200
printf '\nTop-level scripts/entrypoint candidates:\n'
rg -n -C 4 '^(\[project\.scripts\]|[[:space:]]*mnemosyne.*=[[:space:]]*)' pyproject.toml
rg -n -C 8 'def mcp|class mcp|MCP|mcp' mnemosyne pyproject.toml README.md 2>/dev/null | head -n 220
printf '\nSSE-related imports/usages in mnemosyne source ONLY:\n'
rg -n -C 4 'sse|SSE|sse_transport|sse_server|Transport=' mnemosyne 2>/dev/null | head -n 240
printf '\nDocker context exclusions and dependency install comments:\n'
cat -n .dockerignore | sed -n '1,120p'Repository: mnemosyne-oss/mnemosyne
Length of output: 31822
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'mnemosyne/mcp_server.py outline:\n'
ast-grep outline mnemosyne/mcp_server.py --view compact || true
printf '\n'
wc -l mnemosyne/mcp_server.py
printf '\nMCP server implementation excerpt:\n'
cat -n mnemosyne/mcp_server.py | sed -n '1,260p'
printf '\nmcp server CLI integration excerpt:\n'
cat -n mnemosyne/cli.py | sed -n '1780,1905p'Repository: mnemosyne-oss/mnemosyne
Length of output: 12836
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
cat -n mnemosyne/cli.py | sed -n '1788,1828p'
cat -n mnemosyne/mcp_server.py | sed -n '260,420p'
python3 - <<'PY'
from pathlib import Path
p=Path('pyproject.toml')
s=p.read_text()
start=s.index('[project.optional-dependencies]')
end=s.find('\n[', start+1)
block=s[start:end].strip()
print(block)
print('\nmcp extra contains starlette or uvicorn:', 'starlette' in block or 'uvicorn' in block)
PYRepository: mnemosyne-oss/mnemosyne
Length of output: 7783
Install the MCP SSE dependencies in the Docker image.
The mcp extra installs only mcp and anyio, while --transport sse requires starlette and uvicorn. Add those deps to the install command, or add an explicit sse extra that covers them, so the container can start with mnemosyne mcp --transport sse.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Dockerfile` around lines 31 - 34, Update the Dockerfile installation step for
the checkout copied to /opt/mnemosyne so the image installs the dependencies
required by the SSE transport, including starlette and uvicorn, while retaining
the existing mcp dependencies. Use the package’s established SSE extra if
available; otherwise add the required dependencies explicitly to the pip install
command so mnemosyne mcp --transport sse starts successfully.
e6a416e to
3092f3b
Compare
|
Thanks for the thorough follow-up work. I need to revise my initial review before proceeding: an additional focused review surfaced concerns that require maintainer review through the appropriate channel. Please hold the CI rerun and CodeRabbit follow-up for the moment. I will follow up through that channel before we continue the merge review. |
596ec07 to
e615d7c
Compare
|
Thanks for the Streamable HTTP transport work. It's conflicting with main right now. Could you rebase your branch onto current main and push the refreshed head? Happy to review once it's clean. |
|
@ekinnee one more thing to fix while you're rebasing this. The Please add both to That closes the leak. Thanks for the Streamable HTTP work, this is a solid feature. Happy to merge once it's rebased and this is tightened up. |
ea8c1fa to
2eb3272
Compare
|
@ekinnee I owe you a decision and a straight explanation, three weeks late. I am taking #749 as the canonical Streamable HTTP transport, and closing this as superseded. I want to be precise about why, because "superseded" on its own reads like a verdict on your work and it is not one. You opened this on July 30. At that point the MCP SDK 2.x The reason two implementations exist at all is that I did not make this call for three weeks while both sat with zero review. That is the actual failure here, and it is mine. What I am doing about it:
If you want to review #749 before it lands, I would genuinely value it. You have thought harder about this transport than anyone except its author, and you know where the rough edges are. Closing this one. Nothing about it reflects badly on you, and I hope you send the next one. Generated by Claude Code |
Description
Adds stateful MCP Streamable HTTP support at
/mcpusing the MCP SDK 2.xsession manager. The new transport is available through
mnemosyne mcp --transport streamable-http; stdio remains the default and thelegacy SSE transport remains available.
The implementation also shares bearer authentication across network MCP
transports, enables DNS-rebinding protection for loopback Streamable HTTP,
uses a bounded idle timeout, and unregisters sessions after explicit DELETE.
Documentation, CLI help, and regression coverage are included.
Related Issue
Closes #598
Type of Change
How Has This Been Tested?
pytest tests/ -v)/mcprouting, bearer rejection, DNS-rebinding rejection, and sessionregistry cleanup)
Focused validation:
pytest tests/test_streamable_http.py tests/test_tool_surface_parity.py -q:15 passed
git diff --check: passedThe previously completed CI-shaped serial run reported 2,381 passed and 2
skipped. A later rerun reproduced the known batch rollback/order-sensitive
failures and was interrupted during its slow tail. Parallel xdist execution
is not currently valid for this suite because concurrent module collection
shares SQLite initialization state and produces schema/collection races.
Checklist
mnemosyne/__init__.pyCHANGELOG.mdupdated with a brief entrySummary
/mcp.Architecture
DELETEcleanup.Privacy and Local-First Guarantees
Agent Integration Surfaces
/mcpStreamable HTTP endpoint.stdio,sse, andstreamable-http.Maintainability
_resolve_sse_authremains as a compatibility wrapper.