Skip to content

fix(mcp): preserve Snowflake ID precision across MCP tool boundary - #1100

Merged
wayyoungboy merged 1 commit into
oceanbase:mainfrom
lightzt99:fix/mcp-snowflake-id-precision
Jun 29, 2026
Merged

fix(mcp): preserve Snowflake ID precision across MCP tool boundary#1100
wayyoungboy merged 1 commit into
oceanbase:mainfrom
lightzt99:fix/mcp-snowflake-id-precision

Conversation

@lightzt99

Copy link
Copy Markdown
Collaborator

Summary

Closes #1098.

Snowflake IDs (64-bit integers, e.g. 725653563933458432) exceed JavaScript's Number.MAX_SAFE_INTEGER (2^53 − 1 = 9007199254740991). The MCP tool layer declared memory_id as int and serialized id fields as JSON numbers, so V8-based clients (including Claude Code) silently rounded them — e.g. 725653563933458432725653563933458400 — causing update_memory / delete_memory / get_memory_by_id / delete_memory_with_profile to 404 on any memory added in the same MCP session.

The REST API layer already handles this via @field_serializer on memory_id; this PR brings the MCP layer to parity.

Changes

  • Input: memory_id: intmemory_id: str in the 4 affected tool signatures. FastMCP now emits "type": "string" in the JSON schema, so clients treat the ID as an opaque string. The function body coerces to int(memory_id) before calling the Python SDK, so the SDK contract is unchanged.
  • Output: new _stringify_ids helper recursively converts id / memory_id int fields to strings in MCP responses, applied in _fmt. metadata sub-dicts are passed through unchanged so user-provided numeric fields are not silently rewritten.
  • Error path: non-numeric memory_id (e.g. "abc") returns {"success": False, "error": "memory_id must be a numeric string"} instead of raising — mirrors add_memory's error style.

Test plan

New tests/unit/test_mcp_snowflake_id.py (23 tests) covers:

  • Schema: 4 tools declare memory_id as "type": "string" (not integer / anyOf); limit stays integer, delete_profile stays boolean.
  • Input coercion: each of the 4 tools receives a string Snowflake ID and passes int(memory_id) to the underlying SDK with exact precision (mock assertion).
  • Invalid input: "abc" returns {"success": False, ...} and does not call the SDK.
  • Output serialization: top-level id, nested results[].id, memory_id key all stringified; non-ID ints (count, limit, threshold) and string IDs (user_id, agent_id) untouched; bool not stringified (it is a subclass of int).
  • Metadata skip: {"id": 725..., "metadata": {"id": 42}} → top-level id stringified, metadata.id preserved as int.
  • End-to-end: add_memory returns string id; passing it back to update_memory calls memory.update(memory_id=725653563933458432) (mock assertion).
  • delete_memory_with_profile response: memory_id key stringified.
.venv/bin/python -m pytest tests/unit/test_mcp_snowflake_id.py -q  # 23 passed

Existing MCP tests (tests/unit/server/test_main_mcp_optional.py, tests/unit/test_optional_dependency_imports.py) continue to pass — no regression in import / FastMCP registration paths.

Snowflake IDs are 64-bit integers that exceed JavaScript's
Number.MAX_SAFE_INTEGER (2^53 - 1). When the MCP layer declared
memory_id as int and serialized id fields as JSON numbers, V8-based
clients (including Claude Code) silently rounded them, breaking
subsequent update/delete round-trips.

- Change memory_id parameter type from int to str in get_memory_by_id,
  update_memory, delete_memory, delete_memory_with_profile; coerce to
  int inside the function body so the Python SDK contract is unchanged.
- Add _stringify_ids helper that recursively stringifies id/memory_id
  int fields in MCP responses, skipping metadata sub-dicts so
  user-provided numeric fields are preserved.
- Return {"success": False, "error": "..."} on non-numeric memory_id
  instead of raising, mirroring add_memory's error style.

Closes oceanbase#1098
@wayyoungboy
wayyoungboy merged commit e603816 into oceanbase:main Jun 29, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(mcp): memory_id precision loss for Snowflake IDs in MCP tool layer causes update/delete failures

2 participants