Skip to content

MCP cat should pair node content with its hash #93

Description

@jlrickert

Problem

The MCP cat tool splits one logical node read across two response surfaces:

  • content[] contains the rendered node document.
  • structuredContent.nodes[] contains node_id and hash, but no document content.

Clients that consume only structured output report that the body is missing. Clients that consume only text see the body but not the precondition hash required by edit. Multi-node reads force clients to correlate a rendered YAML document stream with structured rows by position, which is fragile and unnecessarily client-specific.

This was observed in agent use: one client reported that cat did not return the body or hash, while another had to read both MCP response fields and correlate them manually.

Current implementation

pkg/mcp/tools_read.go already defines:

type nodeReadOutput struct {
    NodeID  string `json:"node_id"`
    Hash    string `json:"hash"`
    Content string `json:"content,omitempty"`
}

However, registerCat uses:

res.StructuredContent = map[string]any{"nodes": nodeReadOutputs(views, false)}

The false omits Content. Existing precondition tests require the structured hash but do not require structured content.

Simply switching this argument to true may not be sufficient: nodeReadOutputs currently copies NodeView.Content, which is README content only. The default rendered cat document also includes metadata/frontmatter, and that complete document is what an agent needs to round-trip safely through edit.

Proposed response shape

Return each node as one authoritative machine-readable row:

{
  "nodes": [
    {
      "node_id": "541",
      "hash": "e0bec87937342270106e4a2d072264e3",
      "content": "---\n...metadata...\n---\n# Meeting notes\n..."
    }
  ]
}

Keep the existing text content[] rendering for human-readable output and backward compatibility.

Acceptance criteria

  • Every structuredContent.nodes[] row from cat pairs node_id, hash, and the corresponding node document.
  • In default mode, the structured document can be sent back to edit without dropping metadata.
  • Single-node and multi-node reads require no positional correlation between separate response fields.
  • The semantics of content_only, meta_only, and stats_only are explicit and tested in structured output.
  • Existing human-readable text output remains compatible.
  • Tests assert both the structured hash and structured document content, including a multi-node case.

Why this matters

The hash is a precondition over node state, while the document is the candidate input for the subsequent write. Returning them as a pair makes the read-modify-write contract self-contained and prevents clients from accidentally editing the wrong node version or dropping frontmatter.

Activity

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions