v0.2.6

MCP-UI-Org/mcp-uiv0.2.6Jul 9, 2026by het0814

AI Summary

This release focuses on security hardening, implementing HttpOnly session cookies, streaming file uploads to prevent memory exhaustion, and adding strict input validation across the API and CLI.

Key Highlights

  • Session cookies hardened to HttpOnly/SameSite=Strict with Secure flag set dynamically based on HTTPS.
  • Implemented streaming file uploads to prevent memory and event-loop exhaustion.
  • Added strict input validation for blank content and memory types across API and CLI.
  • Fixed TypeScript SDK issues including URL encoding of agent/memory IDs.

New Features

  • Timestamp normalization for imports to preserve source chronology.
  • Improved error handling that passes existing exceptions through unchanged.

Full Release Notes

# Release Notes for v0.2.6

This release closes out a second wave of security hardening: HttpOnly/SameSite session cookies (correctly scoped to `Secure` only over HTTPS) with proper renewal, fully non-blocking streaming file uploads to prevent memory and event-loop exhaustion, strict input validation (blank content/queries, provenance, memory types) across the API and CLI, and a round of TypeScript SDK correctness fixes (URL-encoded agent IDs, session bootstrap, cookie handling).

## Security

- **Session cookie hardening** (`memanto/app/routes/auth_deps.py`,
  `memanto/app/ui/routes/ui_router.py`, `memanto/app/routes/sessions.py`)
  - Browser UI sessions now use an `HttpOnly`, `SameSite=Strict` cookie
    (`memanto_session_token`) instead of JS-readable token storage, with
    `set_session_cookie()` / `clear_session_cookie()` helpers.
  - The cookie's `Secure` flag is now set dynamically from the actual request
    scheme (`request.url.scheme == "https"`) rather than hardcoded — Memanto
    defaults to plain HTTP (`0.0.0.0`, no built-in TLS), so a hardcoded
    `Secure=True` would have silently stopped browsers from ever sending the
    cookie back in that default deployment.
  - Session renewal now correctly updates the cookie with the new token on the
    response — previously a renewed session invalidated the old token without
    refreshing the cookie, breaking the very next request.

- **Streaming file uploads** (`memanto/app/routes/memory.py`)
  - `upload_file` previously called `await file.read()`, loading the entire
    file into memory before writing it to disk — for the documented 5 GB max,
    concurrent large uploads could trivially exhaust server RAM. Uploads are
    now streamed to disk in 1 MB chunks with the 5 GB cap enforced during the
    stream (413 if exceeded), not after full buffering.
  - The chunk write itself (`tmp.write(chunk)`) is now dispatched via
    `asyncio.to_thread` so large uploads no longer block the event loop on
    synchronous disk I/O.

- **Blank/invalid input rejected across API and CLI** (`memanto/app/models/__init__.py`,
  `memanto/app/routes/memory.py`, CLI commands)
  - `answer`/`recall` queries, conversation-extraction messages, and CLI batch
    memory content now reject blank/whitespace-only strings via Pydantic
    validators instead of silently accepting empty input.
  - `remember` provenance values and `recall` memory-type filters are now
    validated against the allowed enum values instead of passed through
    unchecked.

- **Session cleared when deleting the active agent** (`memanto/app/services/session_service.py`,
  `memanto/app/routes/sessions.py`)
  - Deleting an agent now also deletes its persisted session state, so a saved
    session token for a deleted agent can no longer be replayed via
    `X-Session-Token`.

- **TypeScript SDK: URL-encode agent/memory IDs** (`sdks/typescript/src/index.ts`)
  - All REST paths built from `agentId`/`memoryId` now run through
    `encodeURIComponent()`, preventing malformed requests or path injection
    when an ID contains special characters.

## Improvements

- **Timestamp normalization for imports** (`memanto/app/utils/temporal_helpers.py`,
  `memanto/app/services/memory_write_service.py`)
  - Imported memory timestamps (e.g. from `memanto migrate`) are now preserved
    as source chronology while being normalized to UTC-naive values for
    downstream confidence calculations, via a shared `as_utc_naive()` helper
    (deduplicated out of `memory_write_service` into `temporal_helpers`).
  - Session-listing sort and session comparisons now normalize datetimes
    consistently before comparing, avoiding naive/aware `datetime` comparison
    errors.

- **Error handling** (`memanto/app/utils/errors.py`)
  - `map_error_to_http_exception` now passes an existing `HTTPException`
    through unchanged instead of re-wrapping it (e.g. avoids turning a 413
    upload-too-large into a generic 500).

- **TypeScript SDK fixes** (`sdks/typescript/src/index.ts`)
  - Fixed `status()` session bootstrap so a session established outside the
    constructor is recognized correctly.
  - Fixed a file-size fallback bug in the upload path.

## Tests

- Large expansion of `tests/test_api.py`, `tests/test_cli.py`, and
  `tests/test_unit.py` covering session-cookie renewal (including the
  HTTP-vs-HTTPS `Secure` flag behavior), streaming upload limits, blank-input
  validators, provenance/type validation, session deletion on agent removal,
  and timestamp normalization.
- Expanded `sdks/typescript/test/memanto.test.ts` for agent-ID encoding and
  session bootstrap behavior.

## Full Changelog

Full Changelog: https://github.com/moorcheh-ai/memanto/compare/v0.2.5...v0.2.6