-
Notifications
You must be signed in to change notification settings - Fork 175
Description
Bug: search_notes list parameters fail with Pydantic validation error when called via MCP
Summary
The search_notes tool's list-type filter parameters (entity_types, tags, note_types) always fail with a Pydantic validation error when invoked through the MCP protocol. The MCP transport layer serializes list arguments as strings rather than actual Python lists, causing Pydantic to reject them at the type-validation stage.
The same issue affects the metadata parameter on write_note (expects a dict, receives a string).
Environment
- Basic Memory: Latest version via MCP (as of March 2026)
- MCP Client: Claude Desktop (Cowork mode), also reproducible from Claude Code
- OS: macOS (host), Ubuntu 22 (sandbox)
- Pydantic version: 2.12.x (per error URL in traceback)
Steps to Reproduce
Call search_notes via MCP with any of the three list-type filter parameters:
Example 1: entity_types
{
"tool": "search_notes",
"arguments": {
"query": "test query",
"entity_types": "entity"
}
}Example 2: tags
{
"tool": "search_notes",
"arguments": {
"query": "test query",
"tags": "some-tag"
}
}Example 3: note_types
{
"tool": "search_notes",
"arguments": {
"query": "test query",
"note_types": "note"
}
}Example 4: JSON-encoded list string (also fails)
{
"tool": "search_notes",
"arguments": {
"query": "test query",
"entity_types": "[\"entity\"]"
}
}Example 5: metadata dict on write_note
{
"tool": "write_note",
"arguments": {
"title": "Test Note",
"content": "test",
"directory": "test/",
"metadata": {"key": "value"}
}
}Actual Behavior
All three list parameters produce the same class of Pydantic validation error:
1 validation error for call[search_notes]
entity_types
Input should be a valid list [type=list_type, input_value='entity', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/list_type
1 validation error for call[search_notes]
tags
Input should be a valid list [type=list_type, input_value='finding', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/list_type
1 validation error for call[search_notes]
note_types
Input should be a valid list [type=list_type, input_value='note', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/list_type
Even passing a JSON-serialized list string like "[\"entity\"]" fails identically — Pydantic sees the input type as str regardless of content.
Expected Behavior
The parameters should accept list values as documented in the tool schema and filter results accordingly. For example, entity_types: ["entity"] should return only whole-note entities, tags: ["finding"] should filter by observation tag, and note_types: ["note"] should filter by frontmatter type.
Root Cause Analysis
The MCP JSON-RPC transport appears to serialize all tool arguments as scalar strings before they reach the Python function signature. When Pydantic validates the incoming arguments against the type hints (which expect list and dict types), it receives a str and raises a validation error.
This suggests the deserialization step in the MCP bridge/server does not reconstruct complex types (lists, dicts) from their JSON representations before passing them to the tool handler.
Affected parameters (all on search_notes unless noted):
| Parameter | Expected Type | Received Type |
|---|---|---|
entity_types |
list |
str |
tags |
list |
str |
note_types |
list |
str |
metadata (write_note) |
dict |
str |
Not affected — string-type parameters like query, search_type, project, note_type (singular, on write_note) all work correctly because they're already strings.
Workaround
Currently the only workaround is to avoid these parameters entirely and use more specific query strings to narrow results via semantic or text search. This is functional but loses the precision of type/tag filtering.
Suggested Fix
The MCP server's argument deserialization layer should parse JSON-typed arguments back into their native Python types before passing them to Pydantic-validated tool functions. Specifically, if a parameter's type hint is list or dict and the incoming value is a string, attempt json.loads() on it before validation. Alternatively, add a Pydantic BeforeValidator to these fields that handles the string-to-list/dict coercion.