Skip to content

Schema quality: 9 errors, 47 warnings across 29 tools (MCP spec compliance) #1467

@blackwell-systems

Description

@blackwell-systems

Summary

Ran mcp-assert lint against Serena v1.2.0 via stdio transport. Found 9 errors and 47 warnings across 29 exposed tools.

Errors (9)

E103: Required parameter has no description (6 occurrences)

Tools affected: write_memory, read_memory, delete_memory, rename_memory (x2)

Required parameters like memory_name, content, old_name, new_name have no description field in the JSON Schema. When an agent calls tools/list, it receives these parameters with no guidance on what values to provide.

Impact: Agents must guess parameter semantics from the name alone. For content (a generic name), this is particularly ambiguous: content of what? A memory entry? A file? JSON?

Fix: Add description strings to the Pydantic model fields:

memory_name: str = Field(description="Name of the memory entry to read/write/delete")
content: str = Field(description="Text content to store in the memory entry")

E102: Parameter has no type defined (3 occurrences)

Tools affected: read_file (end_line), execute_shell_command (cwd), delete_lines (end_line)

These parameters appear in the JSON Schema without a type field. Agents cannot determine whether to send a string, integer, or object.

Impact: Type mismatch errors at runtime. An agent might send "10" (string) instead of 10 (integer) for end_line.

Fix: Ensure Pydantic fields have explicit type annotations that serialize to JSON Schema type fields. For union types (e.g., int | None), use anyOf with explicit types.

Warnings (47)

W103: Required string parameter has no example/pattern (44 occurrences)

Nearly every tool's relative_path, name_path, pattern, command, etc. lacks an example or pattern field. This is the most common schema quality issue.

Impact: Agents may hallucinate path formats (absolute vs relative), pattern syntax (regex vs glob), or command formats. Adding a single example to each parameter eliminates this ambiguity.

Fix (example for relative_path):

relative_path: str = Field(description="...", json_schema_extra={"examples": ["src/serena/agent.py"]})

W106: tools/list response is ~8,848 tokens (34KB)

The full tool schema consumes significant context. This is informational; no action required unless agents report context pressure.

W104: Generic parameter name with no description (1)

write_memory.content is a generic name. Without a description, agents cannot distinguish it from file content, HTTP content, etc.

W102: Optional parameter has no description (1)

list_memories.topic is optional with no description.

Behavioral finding (not captured by lint)

Separately observed: tool exceptions are returned as isError: false with error text embedded in the content. The MCP spec intends isError: true for failed tool executions. This means agents cannot programmatically distinguish success from failure without parsing the text content for "Error:" prefixes.

How to reproduce

pip install mcp-assert
mcp-assert lint -server "serena start-mcp-server --project-from-cwd --transport stdio"

Or with the pytest plugin:

pip install pytest-mcp-assert
pytest --mcp-server "serena start-mcp-server --project-from-cwd" --mcp-lint

Context

We run mcp-assert against MCP servers to surface schema quality issues before agents hit them at runtime. Full methodology and results across 61 servers on the public scorecard.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions