Skip to content

fix(mcp): memory_recall hits the right endpoint and forwards format/token_budget (#507)#516

Merged
rohitg00 merged 2 commits into
rohitg00:mainfrom
serhiizghama:fix/507-memory-recall-format-and-endpoint
May 19, 2026
Merged

fix(mcp): memory_recall hits the right endpoint and forwards format/token_budget (#507)#516
rohitg00 merged 2 commits into
rohitg00:mainfrom
serhiizghama:fix/507-memory-recall-format-and-endpoint

Conversation

@serhiizghama
Copy link
Copy Markdown
Contributor

@serhiizghama serhiizghama commented May 18, 2026

Problem

memory_recall in the standalone MCP shim always returns compact results, ignoring the format and token_budget parameters that the tool's input schema advertises (src/mcp/tools-registry.ts).

Two root causes in src/mcp/standalone.ts:

  1. Wrong endpoint. memory_recall and memory_smart_search share a single case that routes both to POST /agentmemory/smart-search. That endpoint always returns compact mode and does not honor format. The endpoint that supports format (and exposes the full facts / narrative / concepts / files shape) is POST /agentmemory/search.
  2. Parameters dropped. validate() never parses format or token_budget, and handleProxy() never includes them in the request body, so even after the endpoint is corrected the server has nothing to act on.

Fixes #507.

Solution

  • Parse format (string, lower-cased) and token_budget (positive integer, accepts string or number) in validate() for both memory_recall and memory_smart_search.
  • Split the proxy case: memory_recall calls POST /agentmemory/search with format defaulted to "full" (matching the schema's documented default) and forwards token_budget when set. memory_smart_search keeps its existing POST /agentmemory/smart-search endpoint but now also forwards format and token_budget when the caller supplies them.
  • Local InMemoryKV fallback behavior is unchanged.

Testing

npm test — 1036 / 1036 passing locally.

Two new tests in test/mcp-standalone-proxy.test.ts:

  • proxies memory_recall to POST /agentmemory/search and forwards format/token_budget (#507) — asserts the request URL, the body shape ({query, limit, format, token_budget}), and that smart-search is not called.
  • memory_recall defaults format to 'full' when omitted (#507) — pins the default so the wire call matches the schema's documented default.

Summary by CodeRabbit

New Features

  • Memory tools now accept format and token_budget optional parameters for customized query behavior
  • Memory recall defaults to "full" format when format parameter is unspecified
  • Token budget parameter validates and accepts both numeric values and numeric string inputs

Tests

  • Added test coverage for memory tool proxy request formatting and parameter handling

Review Change Stack

…at/token_budget

memory_recall and memory_smart_search were sharing the smart-search
endpoint, which always returns compact mode and silently drops the
format and token_budget parameters that the tool schema advertises.
Split the cases so memory_recall hits /agentmemory/search (which
honors format) while memory_smart_search keeps its own endpoint.
Default format to "full" for memory_recall so the documented behavior
matches the wire call.

Signed-off-by: serhiizghama <zmrser@gmail.com>
Two new proxy tests for issue rohitg00#507: one asserts memory_recall calls
POST /agentmemory/search with the format and token_budget fields,
and never falls through to smart-search; the other pins the default
format to "full" when the caller omits it.

Signed-off-by: serhiizghama <zmrser@gmail.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

@serhiizghama is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

This PR fixes a bug where memory_recall used the wrong endpoint and dropped format/token_budget parameters. It extends the type contract, adds argument parsing for format and token_budget, splits the proxy handler so memory_recall routes to /agentmemory/search with proper defaults and optional parameters, and adds tests validating the corrected behavior.

Changes

memory_recall proxy fix with format and token_budget support

Layer / File(s) Summary
Type contract extension
src/mcp/standalone.ts
Extended Validated interface with optional format and tokenBudget properties to support the new parameters in tool arguments.
Argument validation
src/mcp/standalone.ts
Added parsing logic to read format (normalized to lowercase with default "full"), and convert token_budget from number or numeric string into positive integer tokenBudget.
Proxy request construction
src/mcp/standalone.ts
Refactored proxy handler to split memory_recall and memory_smart_search into separate cases: memory_recall now routes to /agentmemory/search with query, limit, default format="full", and optional token_budget; memory_smart_search continues to /agentmemory/smart-search with optional format and token_budget.
Test coverage
test/mcp-standalone-proxy.test.ts
Added tests verifying memory_recall proxies to correct endpoint with format and token_budget forwarded, default format behavior when omitted, and isolation from smart-search endpoint.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related issues

Possibly related PRs

  • rohitg00/agentmemory#150: Introduces memory_recall support for format/token_budget field handling and validation, which this PR extends into the standalone proxy request construction.
  • rohitg00/agentmemory#161: Updates proxy request construction for memory tools in src/mcp/standalone.ts, establishing the routing pattern this PR refines by splitting endpoints and adding parameter forwarding.

Poem

🐰 A rabbit hops through proxy gates,
Where memory_recall now takes the right path—
Format flows free, token budgets aligned,
/agentmemory/search at last gets its due,
No more compact mode where full should shine! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main fix: routing memory_recall to the correct endpoint and forwarding format/token_budget parameters.
Linked Issues check ✅ Passed All objectives from issue #507 are met: memory_recall routes to /agentmemory/search, format and token_budget are parsed and forwarded, memory_smart_search behavior is preserved, and tests verify the fix.
Out of Scope Changes check ✅ Passed All changes directly address issue #507: validate() parsing, handleProxy() routing split, and test coverage for memory_recall behavior are all in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/mcp/standalone.ts (2)

123-133: ⚡ Quick win

Consider validating format against known values.

The format parameter is normalized to lowercase but not validated against expected values (likely "full" or "compact"). Invalid format strings will be forwarded to the server, potentially causing less clear error messages.

🛡️ Proposed validation enhancement
 const fmt = args["format"];
 if (typeof fmt === "string" && fmt.trim()) {
-  v.format = fmt.trim().toLowerCase();
+  const normalized = fmt.trim().toLowerCase();
+  if (normalized === "full" || normalized === "compact") {
+    v.format = normalized;
+  } else {
+    throw new Error(`format must be "full" or "compact", got "${fmt}"`);
+  }
 }
🤖 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 `@src/mcp/standalone.ts` around lines 123 - 133, Normalize and validate
args["format"] before assigning to v.format: accept only known values (e.g.,
"full" and "compact") after trimming and lowercasing; if the provided value is
not one of the allowed options, either set a sensible default (e.g., "full") or
reject it by not setting v.format and returning/logging a clear error. Update
the block handling fmt (the variable and v.format assignment) to perform this
whitelist check so invalid format strings are not forwarded to the server.

254-276: Local fallback doesn't honor format parameter (by design).

For awareness: The local InMemoryKV fallback always returns mode: "compact" regardless of the format parameter. This is mentioned in the PR description as "Local InMemoryKV fallback unchanged." The proxy mode (primary use case) correctly honors the format parameter. Implementing "full" mode locally would require restructuring how the in-memory store tracks narrative, concepts, and files.

🤖 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 `@src/mcp/standalone.ts` around lines 254 - 276, The local InMemoryKV fallback
currently hardcodes mode: "compact" in the memory_recall/memory_smart_search
handler; change it to honor the incoming format parameter by reading v.format
and setting a mode variable (e.g., const mode = v.format === "full" ? "full" :
"compact"), then pass that mode into textResponse({ mode, results }, true); if
you cannot produce a true "full" payload from the in-memory records, log or warn
that "full" is not supported locally and still return the compact-shaped results
but with mode reflecting the requested format behavior; update the
memory_recall/memory_smart_search case (variables: query, limit,
kvInstance.list, results, textResponse) accordingly.
test/mcp-standalone-proxy.test.ts (1)

78-131: ⚡ Quick win

Consider adding test coverage for memory_smart_search format/token_budget forwarding.

While the PR focuses on fixing memory_recall, the changes also enable memory_smart_search to forward format and token_budget parameters. The existing test on lines 56-76 doesn't exercise these new parameters. Adding a test would provide confidence that the enhancement works correctly for both tools.

📋 Example test structure
it("memory_smart_search forwards format and token_budget when provided", async () => {
  let capturedBody: Record<string, unknown> | undefined;
  installFetch((url, init) => {
    if (url.endsWith("/agentmemory/livez")) return new Response("ok", { status: 200 });
    if (url.endsWith("/agentmemory/smart-search")) {
      capturedBody = init?.body ? JSON.parse(init.body as string) : undefined;
      return new Response(JSON.stringify({ mode: "full", results: [] }), { status: 200 });
    }
    return new Response("", { status: 404 });
  });
  
  await handleToolCall("memory_smart_search", {
    query: "test",
    limit: 10,
    format: "full",
    token_budget: 500,
  });
  
  expect(capturedBody).toEqual({
    query: "test",
    limit: 10,
    format: "full",
    token_budget: 500,
  });
});
🤖 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 `@test/mcp-standalone-proxy.test.ts` around lines 78 - 131, Add a new unit test
to verify memory_smart_search forwards format and token_budget to the
agentmemory smart-search endpoint: use installFetch to stub requests (return ok
for "/agentmemory/livez" and capture request body for
"/agentmemory/smart-search"), call handleToolCall("memory_smart_search", {
query, limit, format, token_budget }), and assert the captured body equals the
sent payload (query, limit, format, token_budget) and that the response path is
"/agentmemory/smart-search"; mirror the pattern used in the existing
memory_recall tests and name the captured variable (e.g., capturedBody) so
assertions can access it.
🤖 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.

Nitpick comments:
In `@src/mcp/standalone.ts`:
- Around line 123-133: Normalize and validate args["format"] before assigning to
v.format: accept only known values (e.g., "full" and "compact") after trimming
and lowercasing; if the provided value is not one of the allowed options, either
set a sensible default (e.g., "full") or reject it by not setting v.format and
returning/logging a clear error. Update the block handling fmt (the variable and
v.format assignment) to perform this whitelist check so invalid format strings
are not forwarded to the server.
- Around line 254-276: The local InMemoryKV fallback currently hardcodes mode:
"compact" in the memory_recall/memory_smart_search handler; change it to honor
the incoming format parameter by reading v.format and setting a mode variable
(e.g., const mode = v.format === "full" ? "full" : "compact"), then pass that
mode into textResponse({ mode, results }, true); if you cannot produce a true
"full" payload from the in-memory records, log or warn that "full" is not
supported locally and still return the compact-shaped results but with mode
reflecting the requested format behavior; update the
memory_recall/memory_smart_search case (variables: query, limit,
kvInstance.list, results, textResponse) accordingly.

In `@test/mcp-standalone-proxy.test.ts`:
- Around line 78-131: Add a new unit test to verify memory_smart_search forwards
format and token_budget to the agentmemory smart-search endpoint: use
installFetch to stub requests (return ok for "/agentmemory/livez" and capture
request body for "/agentmemory/smart-search"), call
handleToolCall("memory_smart_search", { query, limit, format, token_budget }),
and assert the captured body equals the sent payload (query, limit, format,
token_budget) and that the response path is "/agentmemory/smart-search"; mirror
the pattern used in the existing memory_recall tests and name the captured
variable (e.g., capturedBody) so assertions can access it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f0444cbf-a79f-4a21-a603-ed4b43ba81ca

📥 Commits

Reviewing files that changed from the base of the PR and between f1e7b2c and 4c33894.

📒 Files selected for processing (2)
  • src/mcp/standalone.ts
  • test/mcp-standalone-proxy.test.ts

@rohitg00 rohitg00 merged commit c2f231f into rohitg00:main May 19, 2026
1 of 2 checks passed
@rohitg00
Copy link
Copy Markdown
Owner

Merged + shipping in next release.

Thanks @serhiizghama — closes #507 and #440 (memory_recall returning compact mode + dropping format/token_budget). Both root causes addressed in a single PR: routes through /agentmemory/search instead of /smart-search, forwards format + token_budget end-to-end, defaults format to 'full' matching the schema.

jonathanzhan1975 pushed a commit to jonathanzhan1975/agentmemory that referenced this pull request May 19, 2026
…oken_budget (rohitg00#507) (rohitg00#516)

* fix(mcp): route memory_recall to /agentmemory/search and forward format/token_budget

memory_recall and memory_smart_search were sharing the smart-search
endpoint, which always returns compact mode and silently drops the
format and token_budget parameters that the tool schema advertises.
Split the cases so memory_recall hits /agentmemory/search (which
honors format) while memory_smart_search keeps its own endpoint.
Default format to "full" for memory_recall so the documented behavior
matches the wire call.

Signed-off-by: serhiizghama <zmrser@gmail.com>

* test(mcp): cover memory_recall endpoint, format forwarding, and defaults

Two new proxy tests for issue rohitg00#507: one asserts memory_recall calls
POST /agentmemory/search with the format and token_budget fields,
and never falls through to smart-search; the other pins the default
format to "full" when the caller omits it.

Signed-off-by: serhiizghama <zmrser@gmail.com>

---------

Signed-off-by: serhiizghama <zmrser@gmail.com>
This was referenced May 19, 2026
rohitg00 added a commit that referenced this pull request May 19, 2026
Quality + integration wave. Bundles 11 PRs since v0.9.20:

Contributor feature:
- #237 OpenCode plugin with 22 auto-capture hooks (@cl0ckt0wer)

Bug fixes (9):
- #516 memory_recall endpoint + format/token_budget (@serhiizghama, closes #507/#440)
- #461 env-file AGENTMEMORY_DROP_STALE_INDEX flag honored (@honor2030, closes #456)
- #487 Windows hook path quoting (@honor2030, closes #477)
- #517 viewer IME composition guard (@jonathanzhan1975)
- #472 chunk large sessions for LLM context window (@efenex)
- #473 surface lessons in smart-search + diagnose tally (@efenex)
- #486 declare all Hermes plugin hooks (@honor2030)
- #500 rebuildIndex non-blocking on boot (@efenex)
- #504 batched embed in rebuildIndex (25h -> 3h) (@efenex)
- #491 cli skip onboarding without tty (@honor2030)

Upstream-installer revert:
- #546 drop --next workaround now that iii-hq/iii#1660 shipped

1067/1067 tests pass across 95 files.
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: memory_recall always returns compact mode — wrong endpoint + format param not forwarded in standalone.mjs

2 participants