Skip to content

Add batch memory support and serialize MCP InitializeResult - #59

Merged
savioruz merged 2 commits into
mainfrom
feat/batch-memories
Aug 16, 2026
Merged

savioruz merged 2 commits into
mainfrom
feat/batch-memories

Conversation

@savioruz

@savioruz savioruz commented Aug 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two commits: (1) Serialize MCP InitializeResult (issue #52 — bug, critical for strict MCP clients like Claude Code), and (2) Add batch memory support across the HTTP API, MCP add_memory tool, and CLI (issue #53). CI green.

Changes

(1) Serialize MCP InitializeResult — commit 92a6aad (issue #52)

  • crates/memayu-mcp/src/types.rs: derive/bump serde::Serialize (and keep Deserialize) on the MCP protocol types so the initialize response is emitted correctly:
    • InitializeResult → protocolVersion, serverInfo, capabilities (all #[serde(rename_all = "camelCase")]).
    • ServerInfo { name, version }, ServerCapabilities { instructions?, prompts?, resources?, tools?, auth? }, ToolsCapability { listChanged }, etc. — serialized camelCase per the MCP 2024-11-05 spec.
    • New #[cfg(test)] mod tests (ser_deser + camelCase assertions incl. nested tools.listChanged) — verifies the serialized JSON uses protocol_version→protocolVersion, listChanged (nested), and server_info→serverInfo.
  • Fixes MCP initialize response uses snake_case (protocol_version/server_info) instead of camelCase — rejected by strict clients #52: strict MCP clients (Claude Code, etc.) rejected the prior snake_case payload.

(2) Batch memory support — commit 3ee6ec7 (issue #53)

Core:

  • crates/memayu-core/src/service.rs: new BatchMemory { content, metadata }, BatchItemResult::Stored/{ id } | Failed/{ error }, and MemoryService::add_memories_batch(user, &[BatchMemory]) -> Result<Vec<BatchItemResult>>. Ingestion loops each item through the existing add_memory (ADD/UPDATE + dedupe) pipeline; per-item failures are collected, only an empty batch raises CoreError::InvalidInput. New CoreError::InvalidInput(String) variant.
  • crates/memayu-core/src/lib.rs: re-export BatchMemory/BatchItemResult.

HTTP API:

  • crates/memayu-api/src/modules/memory/dto.rs: AddMemoriesBatchRequest { memories: Vec<AddMemoryItem> }, AddMemoryItem { content, metadata }, BatchMemoryError { index, error }, AddMemoriesBatchResponse { status, added, memory_ids, errors }.
  • crates/memayu-api/src/transport/handlers/memory.rs: new POST /api/memories/batch → 400 on empty, else add_memories_batch + per-item result mapping into BatchMemoryError { index }. HTTP 200 even with per-item failures (graceful degradation).
  • crates/memayu-api/src/transport/routes.rs: register /batch.

MCP:

  • crates/memayu-mcp/src/tools/add_memory.rs: add_memory tool gains an optional memories array input (items { content, metadata }); per-item failures are summarized with item {i}: <error> and successes collected. Single-content path unchanged (backward compatible).

CLI:

  • bin/memayu/src/cli.rs: new memayu add --batch / memayu batch style invocation accepting multiple memory payloads; per-item error summary to stderr.

Tests

  • crates/memayu-api/tests/api.rs: add_memories_batch_stores_all (3 valid → added=3, errors []) and add_memories_batch_reports_per_item_errors (3 with one empty-content → added=2, errors present, HTTP 200).
  • bin/memayu/tests/cli.rs: add_batch_stores_all_items, add_batch_reports_partial_failures.
  • crates/memayu-mcp/src/types.rs: ser/serde + camelCase test assertions.

Migration / behavior

  • No DB schema change.
  • Backward compatible API addition: POST /api/memories/add (single) unchanged; /batch is new.
  • MCP add_memory schema: memories array is optional → existing single-content calls work unchanged.

Checklist

Fixes #52 #53

@savioruz savioruz added bug Something isn't working enhancement New feature or request core memayu-core domain logic api HTTP API transport/handlers mcp MCP server tools priority-high Highest priority — must be done before next milestone labels Aug 16, 2026
@savioruz savioruz added this to the v0.1.0 milestone Aug 16, 2026
@savioruz

Copy link
Copy Markdown
Owner Author

Review of PR #59 at 3ee6ec7d591cf50aa65ee16f1bbcf2ab68257d29 (base main), spanning 2 commits: 92a6aad ("serialize MCP InitializeResult", #52) and 3ee6ec7 ("batch memory support", #53).

🔴 Blocking

None. CI green (cargo build, clippy, fmt, test, audit all pass).

🟡 Warning #1 — MCP batch duplicates core add_memories_batch rather than delegating

crates/memayu-mcp/src/tools/add_memory.rs batch path loops backend.add_memory(user_id, content) per item and rolls its own success/failure summary, while memayu-core::MemoryService::add_memories_batch already implements the same per-item ADD/UPDATE+dedupe pipeline with BatchItemResult. The MCP batch therefore does not go through the service batch (it uses its own per-call embedding/dedupe loop). Not a correctness bug (both paths are equivalent today), but it is duplicated logic that can drift — ideally the MCP layer calls add_memories_batch if/when its MemoryBackend gains a batch method. Low priority; flag for follow-up.

Validation

MCP InitializeResult serialization (#52, commit 92a6aad)

  • crates/memayu-mcp/src/types.rs: InitializeResult, ServerInfo, ServerCapabilities (and nested types) now #[derive(Serialize)] + #[serde(rename_all = "camelCase")]. protocol_version→protocolVersion, server_info→serverInfo, nested tools.listChanged all camelCase per MCP 2024-11-05 spec.
  • New #[cfg(test)] mod tests asserts the serialized JSON keys are camelCase including nested capabilities.tools.listChanged, and that server_info.name == "memayu-mcp" + version 0.1.0. Strict clients (Claude Code) that previously rejected the snake_case payload will now accept it.

Batch memory support (#53, commit 3ee6ec7)

Core (memayu-core/src/service.rs):

  • BatchMemory { content, metadata } + BatchItemResult::Stored/{ memory_id } | Failed/{ error }, both re-exported from lib.rs.
  • MemoryService::add_memories_batch(user, &[BatchMemory]) -> Result<Vec<BatchItemResult>>: loops items through the existing add_memory (so ADD/UPDATE + dedupe still runs per item); per-item Err is caught into BatchItemResult::Failed, only an empty batch short-circuits with CoreError::InvalidInput("batch must contain at least one memory"). New CoreError::InvalidInput(String) variant.

HTTP API:

  • DTOs in modules/memory/dto.rs: AddMemoriesBatchRequest { memories: Vec<AddMemoryItem> }, AddMemoryItem { content, metadata }, BatchMemoryError { index, error }, AddMemoriesBatchResponse { status, added, memory_ids, errors }.
  • Handler add_memories_batch → POST /api/memories/batch (registered in routes.rs): 400 on empty memories; per-item failure → BatchMemoryError { index } (zero-based request index); HTTP 200 even when some items fail (graceful degradation — caller inspects errors[]).

MCP (tools/add_memory.rs):

  • add_memory schema gains optional memories array ({ content, metadata }); per-item failures summarized as item {i}: <error>, successes counted; single-content path unchanged → backward compatible.

CLI (bin/memayu/src/cli.rs): add --batch / memayu batch style invocation, per-item error summary to stderr.

Tests

  • crates/memayu-api/tests/api.rs: add_memories_batch_stores_all (3 valid → added:3, memory_ids.len()==3, errors==[], HTTP 200) and add_memories_batch_reports_per_item_errors (3 items, 1 empty-content → added:2, errors non-empty, still HTTP 200).
  • bin/memayu/tests/cli.rs: add_batch_stores_all_items, add_batch_reports_partial_failures.
  • crates/memayu-mcp/src/types.rs: ser/serde + camelCase correctness assertions incl. nested listChanged.

Breaking surface / migration

  • No DB schema change.
  • HTTP API backward compatible (single POST /api/memories/add untouched; /batch is new).
  • MCP MemoryBackend trait is unchanged (no batch method added — MCP loops client-side).
  • CLI batch is additive.

Checklist

Note: PR description updated pre-review (added the two-Commit split, issue refs, checklist, and the #52/#53 issue titles).

@savioruz
savioruz marked this pull request as ready for review August 16, 2026 03:50
@savioruz
savioruz merged commit 5b4f946 into main Aug 16, 2026
5 checks passed
@savioruz
savioruz deleted the feat/batch-memories branch August 25, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api HTTP API transport/handlers bug Something isn't working core memayu-core domain logic enhancement New feature or request mcp MCP server tools priority-high Highest priority — must be done before next milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP initialize response uses snake_case (protocol_version/server_info) instead of camelCase — rejected by strict clients

1 participant