Skip to main content
Glama
crunchtools

mcp-metsuke-crunchtools

Official
by crunchtools

save_output_tool

Persist a gathered report output, linking findings to source URLs, and complete the originating run when its run_id is provided.

Instructions

Persist a gathered report output, completing the run that opened it.

The gatherer writes findings here after sweeping the sources. Each finding in payload should carry its own source URL so the compiler can cite it. Pass the run_id Metsuke handed you in the fire callback so this completes that exact in-flight run (one row per fire). Omit run_id for an ad-hoc direct save; Metsuke stamps a fresh run identity either way.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
run_idNoThe run to complete (from the fire callback); None = direct save
statusNoOne of "gathering", "ready", "compiled", "failed" (default: "ready")ready
payloadYesList of findings. Each needs a non-empty summary and should carry its source_url; see Finding for the other allowed keys
window_endNoEnd of the reporting window (ISO date/datetime)
report_nameYesThe report definition this output belongs to
window_startNoStart of the reporting window (ISO date/datetime)
gatherer_run_refNoOpaque reference to the gatherer run that produced this

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed8 schema fields changedv1.1.0
    • changedInput schema / properties / payload / description
      Previous value: -"List of finding objects, each ideally carrying a source URL"New value: +"List of findings. Each needs a non-empty summary and should\ncarry its source_url; see Finding for the other allowed keys"
    • changedInput schema / properties / payload / items / additionalProperties
      Previous value: -trueNew value: +false
    • addedInput schema / properties / payload / items / description
      Added value: +"One gathered finding.\n\nThe fields are declared, not left as a free-form dict, because a model\ncalling the tool fills in what the schema names: with a bare ``object``\nitem, strict tool-calling models emitted ``{}`` for every finding (RT #1505).\n``summary`` is the one field every report uses and the one a finding is\nworthless without. The rest are the keys the live reports use; a report\nthat needs one more adds it here.\n\nExample::\n\n    {\"summary\": \"Fedora 45 Beta shipped with Podman 6.\",\n     \"source_url\": \"https://fedoramagazine.org/...\",\n     \"section\": \"rss-news-roundup\", \"theme\": \"RHEL/Linux\"}"
    • addedInput schema / properties / payload / items / properties
      Added value: +{
      +  "actors": {
      +    "anyOf": [
      +      {
      +        "items": {
      +          "maxLength": 200,
      +          "type": "string"
      +        },
      +        "maxItems": 2000,
      +        "type": "array"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "People or teams involved, by name."
      +  },
      +  "category": {
      +    "anyOf": [
      +      {
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Source category, e.g. the feed category the item came from."
      +  },
      +  "date": {
      +    "anyOf": [
      +      {
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "When it happened, ISO date (YYYY-MM-DD)."
      +  },
      +  "outcome_ref": {
      +    "anyOf": [
      +      {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Tracker key this finding advances, e.g. a Jira issue key."
      +  },
      +  "section": {
      +    "anyOf": [
      +      {
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Report section this belongs in, as named by the report's gather prompt."
      +  },
      +  "source_type": {
      +    "anyOf": [
      +      {
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Kind of source, e.g. 'jira', 'slack', 'email', 'rss', 'web'."
      +  },
      +  "source_url": {
      +    "anyOf": [
      +      {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Clickable link to the evidence; null when no source exists."
      +  },
      +  "summary": {
      +    "description": "One or two sentences stating the finding itself.",
      +    "maxLength": 2000,
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "theme": {
      +    "anyOf": [
      +      {
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Grouping within a section, e.g. 'Security' or 'AI/Agentic'."
      +  },
      +  "title": {
      +    "anyOf": [
      +      {
      +        "maxLength": 2000,
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Headline of the source item, when it has one."
      +  }
      +}
    • addedInput schema / properties / payload / items / required
      Added value: +[
      +  "summary"
      +]
    • addedInput schema / properties / run_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The run to complete (from the fire callback); None = direct save"
      +}
    • changedInput schema / properties / status / description
      Previous value: -"One of \"gathering\", \"ready\", \"compiled\" (default: \"ready\")"New value: +"One of \"gathering\", \"ready\", \"compiled\", \"failed\" (default: \"ready\")"
    • changedInput schema / properties / status / enum
      Previous value: -[
      -  "gathering",
      -  "ready",
      -  "compiled"
      -]New value: +[
      +  "gathering",
      +  "ready",
      +  "compiled",
      +  "failed"
      +]
  2. First observedv0.2.0

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose meaningful behavior: one row per fire, that omitting run_id still produces a fresh run identity ('Metsuke stamps a fresh run identity either way'), and that findings should carry source URLs for downstream citation. It omits idempotency/duplicate handling and permission requirements, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose in the first sentence, then layers usage detail. Four sentences, each earning its place, though domain jargon ('fire callback', 'Metsuke') assumes shared context and slightly reduces standalone clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is unnecessary, and the description correctly focuses on the input-side lifecycle: run_id provenance, payload expectations, and the two save modes. Adequate for a mutation tool of this complexity, with only minor gaps around failure/duplicate behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description mildly enriches run_id semantics ('one row per fire', completes 'that exact in-flight run') and reiterates the source_url expectation, but adds little beyond what the schema descriptions already document for each field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource: 'Persist a gathered report output', and immediately clarifies its transactional role ('completing the run that opened it'). This clearly positions it as the write path, distinguishing it from read-oriented siblings like get_output_tool, list_outputs_tool, and delete_output_tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit timing ('The gatherer writes findings here after sweeping the sources') and two distinct invocation modes: pass run_id from the fire callback to complete an in-flight run, or omit it for an ad-hoc save. It stops short of naming sibling alternatives (e.g., get_output_tool) to route away from, but the when-to-use context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.