Skip to content

Add missing idempotentHint and openWorldHint to server-filesystem #3402

@agentward-ai

Description

@agentward-ai

Request: Add missing tool annotations — @modelcontextprotocol/server-filesystem v0.2.0

Context

We ran an automated scan of this server via live JSON-RPC handshake. This server is the gold standard for tool annotations in the MCP ecosystem — it's the only official server that provides readOnlyHint, destructiveHint, and idempotentHint on every tool.

This issue is filed to acknowledge that, and to suggest two small additions that would make the coverage complete.

Current Annotation Coverage — 14/14 tools annotated

# Tool readOnlyHint destructiveHint idempotentHint openWorldHint
1 read_file true
2 read_text_file true
3 read_media_file true
4 read_multiple_files true
5 write_file false true true
6 edit_file false true false
7 create_directory false false true
8 list_directory true
9 list_directory_with_sizes true
10 directory_tree true
11 move_file false false false
12 search_files true
13 get_file_info true
14 list_allowed_directories true

Every tool has readOnlyHint. Every write tool has destructiveHint. edit_file correctly reports idempotentHint: false. This is exactly what the MCP spec envisions.

Suggested additions

Two small improvements to reach full annotation coverage:

1. Add idempotentHint to read-only tools

All 10 read-only tools currently omit idempotentHint. Since reads are inherently idempotent, adding idempotentHint: true would let clients safely implement automatic retries on failure.

Affected tools: read_file, read_text_file, read_media_file, read_multiple_files, list_directory, list_directory_with_sizes, directory_tree, search_files, get_file_info, list_allowed_directories

Example — the change for read_text_file:

// Before
server.registerTool(
  "read_text_file",
  {
    description: "Read the complete contents of a file...",
    inputSchema: { path: z.string(), head: z.number().optional(), tail: z.number().optional() },
    annotations: { readOnlyHint: true },
  },
  handler
);

// After — add idempotentHint
server.registerTool(
  "read_text_file",
  {
    description: "Read the complete contents of a file...",
    inputSchema: { path: z.string(), head: z.number().optional(), tail: z.number().optional() },
    annotations: { readOnlyHint: true, idempotentHint: true },
  },
  handler
);

Same one-property addition for all 10 read-only tools.

2. Add openWorldHint: false to all tools

All tools are scoped to allowed directories, making them closed-world by design. Explicitly marking openWorldHint: false communicates that the tool's behavior is fully determined by the configured directories, with no external side effects.

Example — the change for write_file:

// Before
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }

// After — add openWorldHint
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }

Why annotations matter — chaining risks in multi-server setups

This server is commonly installed alongside other MCP servers (GitHub, memory, email, shell). When agents use multiple servers together, tool annotations become the primary signal for distinguishing safe operations from risky ones:

  • write_file + any input server → An agent receiving instructions from email or chat could be directed to overwrite files. destructiveHint: true (already present ✅) enables clients and emerging security tools to gate this regardless of the instruction source.
  • read_media_file + network server → Large base64-encoded files could be exfiltrated if an agent chains a file read into an outbound HTTP call. readOnlyHint: true helps distinguish the safe local read from the risky outbound send.

These composition risks are invisible when testing a server in isolation. Annotations are the metadata that makes them visible to downstream tooling as it matures.

This server as the ecosystem example

We're filing similar annotation requests on server-memory (0/9 annotated), server-github (0/26 annotated), server-sequential-thinking (0/1), and server-everything (0/13). In each of those issues, we reference server-filesystem as the example to follow.

Thank you for setting the standard.


Found via automated scan with AgentWard. Enumerated via live JSON-RPC handshake, protocol 2025-11-25.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions