Skip to content

Schema quality: missing property descriptions across official MCP servers #3669

Open

Description

@KryptosAI

Summary

While running automated quality checks against the official MCP reference servers, I found that most servers are missing description fields on their tool input schema properties. This matters because LLMs use these descriptions to understand how to call tools correctly — without them, the model has to guess what each parameter means from the name alone.

Findings

Tested with MCP Observatory v0.13.0 on 2026-03-22.

server-filesystem (11 tools, 18 missing descriptions)

Every tool property across all 11 tools lacks a description:

  • read_file: path missing description
  • write_file: path, content missing descriptions
  • edit_file: path, edits missing descriptions
  • create_directory: path missing description
  • list_directory: path missing description
  • directory_tree: path, excludePatterns missing descriptions
  • move_file: source, destination missing descriptions
  • search_files: path, pattern, excludePatterns missing descriptions
  • get_file_info: path missing description

server-everything (13 tools, 5 missing descriptions + 4 missing required)

  • get-resource-reference: resourceType missing description
  • 4 tools missing required array: get-resource-links, get-resource-reference, gzip-file-as-resource, trigger-long-running-operation
  • Resource README.md.gz missing description

server-memory (6 tools, 4 missing descriptions)

  • create_entities: entities missing description
  • create_relations: relations missing description
  • add_observations: observations missing description
  • delete_observations: deletions missing description

Why this matters

The MCP spec recommends tool input schemas follow JSON Schema with descriptions. When an LLM sees:

{ "type": "string" }

vs:

{ "type": "string", "description": "Absolute or relative path to the file to read" }

The second version produces significantly better tool-use accuracy. Since these are the reference implementations that other server authors look at, setting a good example here would improve schema quality across the ecosystem.

Suggested fix

Add description fields to all tool input schema properties. Example for read_file:

inputSchema: {
  type: "object",
  properties: {
    path: {
      type: "string",
      description: "Absolute or relative path to the file to read"
    }
  },
  required: ["path"]
}

Reproduction

npx @kryptosai/mcp-observatory score npx -y @modelcontextprotocol/server-filesystem /tmp
npx @kryptosai/mcp-observatory score npx -y @modelcontextprotocol/server-everything
npx @kryptosai/mcp-observatory score npx -y @modelcontextprotocol/server-memory

Activity

  1. khalidsaidi commented on Mar 24, 2026

    @khalidsaidi

    A2ABench has an accepted answer for this imported thread.

    • Thread: https://a2abench-api.web.app/q/cmn1ngym4007rxzty2esf43c0
    • Accepted at: 2026-03-24T20:32:25.823Z
    • Accepted answer agent: ai village
    • Answer preview: "Based on our strict principles of idempotent execution, trace-first architecture, and explicit workflow boundaries, this issue regarding 'Schema quality: missing property descriptions across official MCP servers' can be resolved by enforcing stateless handlers and explicit loop c"
  2. radeshgovind-2005 commented on Mar 27, 2026

    @radeshgovind-2005

    Hi, I've submitted PR #3732 which addresses all the points raised in this issue.

  3. jashshah999 commented on May 5, 2026

    @jashshah999

    This is exactly the kind of issue I built mcpeval to catch automatically. It's a CLI linter for MCP tool schemas that flags missing descriptions, ambiguous parameter names, missing enums, and schema bloat. Runs in CI to prevent these regressions:

    pip install mcpeval
    mcpeval check your_server.json --ci

    Gives you a score out of 100 and actionable fix suggestions for each issue.

  4. PengSpirit commented on May 9, 2026

    @PengSpirit
  5. cliffhall commented on Oct 19, 2026

    @cliffhall
    Member

    Triage: Priority Low (total 4)

    • Severity 2: Many tool input properties still lack descriptions, and adding them is a usability improvement that helps models call the tools correctly.
    • Urgency 2: wanted eventually
    • Bonuses: none

    Board: Servers V2 (#43), Status Incoming, awaiting maintainer review (no milestone yet). Part of the backlog triage in #4875.

  6. cliffhall commented on Oct 20, 2026

    @cliffhall
    Member

    Prior work, from the PR backlog triage (#4877). These outside pull requests addressed this issue against the pre-refactor code:

    They are being closed as part of the backlog triage in #4875, since the repository now takes issues rather than outside PRs and their diffs predate the v2 refactor. They stay readable and serve as prototypes for the fix here. Thank you to their authors.

  7. Pranav-Nexus commented on Oct 21, 2026

    @Pranav-Nexus

    v2 Codebase Audit (origin/main / v2.0.0) & Ready-to-Run Factory Prompt

    Following the v2 spec refactor (#4857) and backlog triage (#4875 / #4877), I audited the current v2 codebase across all three servers (filesystem, memory, everything) to see what was already resolved by the refactor and what still lacks property descriptions under the AGENTS.md rule ("Validate tool input with Zod schemas, with descriptions on the fields").

    1. What v2 Already Fixed vs. What Remains

    • src/filesystem/server.ts (16 properties across 11 tools still missing .describe()):

      • Architectural cleanup opportunity: In v2, tool registration now passes jsonSchema2020(<Tool>ArgsSchema.shape) directly to inputSchema, so adding .describe() on the top-level Zod schemas automatically populates the advertised 2020-12 JSON Schema. However, read_file and read_text_file still inline a duplicate { path, tail, head } object inside jsonSchema2020({...}) instead of passing ReadTextFileArgsSchema.shape.
      • Missing property descriptions:
        • ReadTextFileArgsSchema: path
        • ReadMediaFileArgsSchema: path
        • WriteFileArgsSchema: path, content
        • EditFileArgsSchema: path, edits
        • CreateDirectoryArgsSchema: path
        • ListDirectoryArgsSchema: path
        • ListDirectoryWithSizesArgsSchema: path
        • DirectoryTreeArgsSchema: path, excludePatterns
        • MoveFileArgsSchema: source, destination
        • SearchFilesArgsSchema: path, pattern, excludePatterns
        • GetFileInfoArgsSchema: path
      • Behavioral nuance worth noting in search_files vs directory_tree descriptions:
        • In search_files (lib.ts searchFilesWithValidation), both pattern and excludePatterns are evaluated directly via minimatch(relativePath, ..., { dot: true })—meaning a bare directory name like excludePatterns: ["node_modules"] only excludes the top-level directory entry itself while still traversing children unless **/node_modules/** is passed (and a bare filename pattern: "foo.ts" only matches at the root of path unless **/foo.ts or *.ts is used).
        • In contrast, directory_tree (server.ts buildTree) auto-expands non-wildcard excludePatterns to **/${pattern} and **/${pattern}/**. Calling out the expected glob syntax (e.g., '*.ts', '**/*.json', ['**/node_modules/**']) in the parameter descriptions prevents first-turn agent retries.
    • src/memory/index.ts (5 top-level properties still missing .describe()):

      • delete_entities (entityNames), delete_relations (relations), and open_nodes (names) already have .describe() in v2.
      • Still missing .describe():
        • SearchNodesQuerySchema (search_nodes -> query)
        • create_entities (entities: z.array(EntitySchema))
        • create_relations (relations: z.array(RelationSchema))
        • add_observations (observations: z.array(...))
        • delete_observations (deletions: z.array(...))
    • src/everything/ (1 property missing .describe()):

      • The required arrays and resource descriptions noted in the original v1 report are already resolved in v2.
      • Only src/everything/tools/get-resource-reference.ts -> GetResourceReferenceSchema.shape.resourceType (z.enum([RESOURCE_TYPE_TEXT, RESOURCE_TYPE_BLOB]).default(RESOURCE_TYPE_TEXT)) is still missing .describe().

    2. Prompt for the Agentic Workflow (CONTRIBUTING.md format)

    Per CONTRIBUTING.md, here is a self-contained prompt that can be fed directly into the repository's workflow to close #3669 with protocol-level test assertions in server-tools.test.ts:

    Resolve #3669 by ensuring every advertised tool input schema property across `src/filesystem`, `src/memory`, and `src/everything` has a clear `.describe(...)` annotation, and pin the invariant in protocol-level `listTools()` tests:
    
    1. **`src/filesystem/server.ts`**:
       - Add `.describe(...)` to all 16 undocumented fields across `ReadTextFileArgsSchema` (`path`), `ReadMediaFileArgsSchema` (`path`), `WriteFileArgsSchema` (`path`, `content`), `EditFileArgsSchema` (`path`, `edits`), `CreateDirectoryArgsSchema` (`path`), `ListDirectoryArgsSchema` (`path`), `ListDirectoryWithSizesArgsSchema` (`path`), `DirectoryTreeArgsSchema` (`path`, `excludePatterns`), `MoveFileArgsSchema` (`source`, `destination`), `SearchFilesArgsSchema` (`path`, `pattern`, `excludePatterns`), and `GetFileInfoArgsSchema` (`path`).
       - For `SearchFilesArgsSchema.pattern`, explicitly state that it matches file/directory names (not file contents) using a `minimatch` glob relative to `path` (e.g. `"*.ts"`, `"**/*.json"`).
       - For `excludePatterns` on `SearchFilesArgsSchema` and `DirectoryTreeArgsSchema`, document glob exclusion syntax (e.g. `["**/node_modules/**", "**/.git/**"]`).
       - Deduplicate `read_file` and `read_text_file` `inputSchema` registrations by passing `jsonSchema2020(ReadTextFileArgsSchema.shape)` instead of repeating the inline `{ path, tail, head }` object.
    
    2. **`src/memory/index.ts`**:
       - Add `.describe(...)` to `SearchNodesQuerySchema` and the top-level array fields in `create_entities` (`entities`), `create_relations` (`relations`), `add_observations` (`observations`), and `delete_observations` (`deletions`).
    
    3. **`src/everything/tools/get-resource-reference.ts`**:
       - Add `.describe(...)` to `resourceType` in `GetResourceReferenceSchema`.
    
    4. **Protocol-level tests**:
       - In `src/filesystem/__tests__/server-tools.test.ts` (and equivalent tool-list tests in `memory` and `everything`), add an assertion over `await client.listTools()` verifying that for every tool, every property in `tool.inputSchema.properties` has a non-empty `string` `description`.
       - Run `npm run format` and `npm run local:gate` (including 90% per-file coverage).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions