Skip to main content
Glama

Check composer patches against a release

check_patches
Read-onlyIdempotent

Does each composer patch still apply to the release the site installed, and is its fix already in that release?

  • Send composer_json and composer_lock after composer update. Add patch_files for every patch, a local one read from disk and a URL one fetched by you. Every extra.patches entry is checked at its installed version in one call.

  • Do not download releases. Do not run patch --dry-run.

  • Send a package's patches together, in the order composer.json lists them.

  • items: up to 50 of {project, version, patch, title}, in place of the composer files. project: the drupal.org machine name (webform) or composer name (drupal/webform); drupal or core for Drupal core. version: the installed composer version (1.13.0, 2.0.0-beta4, 11.4.5). patch: the diff text, or its URL on www.drupal.org/files/issues or a git.drupalcode.org merge request or commit, ending .patch or .diff.

  • Per item. tag: the release tag matched, or unknown_version. applies_at: the -p level at which git apply passes, null when none. fuzzy: true when it applied only with reduced context and whitespace ignored; review it. hunks_failed: [{file, line, reason}]. reverse_applies: true when the patched lines are already in the tag. mr: the merge request state when the patch is an MR URL. merged_in_version. suggested.

  • suggested: the verdict. merged: the fix is in the release; drop the patch. applies: keep the patch. conflicts: call reroll_patch with that item. unknown: see error.

  • next_step: the follow-up calls and the row count the report must have. counts: the verdict tally; check the report's table against it. An item that could not be judged comes back unknown with the reason in error. Report it as unclear. Never leave the row out.

  • hunks_shipped, files_shipped: the parts of a patch already in the release verbatim. On a conflicts row, check whether the rest is still needed before re-rolling. moved_to: on a failed hunk, the release path of the renamed file.

  • core_references: what the added code references in core, checked at target_core. flagged: removed or moved classes, and calls whose argument count does not fit the target signature, each with file, line, change_record and replacement. parent::__construct is checked against the constructor of the core parent class. deprecated: a short side list. checked: how many references the catalog knows. Scope: added lines and direct references only (extends, implements, trait use, new, static calls, parent::__construct). A patch that does not apply has a note instead.

  • Verdicts come from git apply --check against the tag. An applies patch can still be wrong at runtime.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemsNoUp to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: the diff text. This service downloads nothing, so fetch a URL patch yourself and send what came back. source: optional, the path or URL the patch was declared with. merge_patch: optional, the .diff form of a merge request, used for the merge of a re-roll while patch decides the verdict. title: optional, echoed back. base: optional, the release the site had before the upgrade. A commit sha or a composer version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock.
patch_filesNoThe text of every patch listed in extra.patches, keyed by the source as written: a path (patches/x.patch) or its base name, or the URL. Fetch a URL patch yourself and send its text under that URL. For a merge request .patch URL, send its .diff form under a second key too.
target_coreNoThe core version the added code is checked against, 11.4.5. Defaults to the lock's drupal/core, else the version of a drupal item.
composer_jsonNoThe contents of composer.json. Send the text; this server cannot read your filesystem. Its extra.patches becomes the item list, one item per patch.
composer_lockNoThe contents of composer.lock. It gives the installed version of each patched package.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed2 schema fields changed
    • changedInput schema / properties / composer_json / description
      Previous value: -"The text of composer.json, not a path. Its extra.patches becomes the item list, one item per patch."New value: +"The contents of composer.json. Send the text; this server cannot read your filesystem. Its extra.patches becomes the item list, one item per patch."
    • changedInput schema / properties / composer_lock / description
      Previous value: -"The text of composer.lock, not a path. It gives the installed version of each patched package."New value: +"The contents of composer.lock. It gives the installed version of each patched package."
  2. Changed4 schema fields changed
    • changedInput schema / properties / items / description
      Previous value: -"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. base: optional, the package's release installed before the upgrade, not version. A commit sha or a composer version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock."New value: +"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: the diff text. This service downloads nothing, so fetch a URL patch yourself and send what came back. source: optional, the path or URL the patch was declared with. merge_patch: optional, the .diff form of a merge request, used for the merge of a re-roll while patch decides the verdict. title: optional, echoed back. base: optional, the release the site had before the upgrade. A commit sha or a composer version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock."
    • addedInput schema / properties / items / items / properties / merge_patch
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / items / items / properties / source
      Added value: +{
      +  "type": "string"
      +}
    • changedInput schema / properties / patch_files / description
      Previous value: -"The text of each local patch file listed in extra.patches, keyed by the path as written (patches/x.patch) or its base name. URL patches need nothing."New value: +"The text of every patch listed in extra.patches, keyed by the source as written: a path (patches/x.patch) or its base name, or the URL. Fetch a URL patch yourself and send its text under that URL. For a merge request .patch URL, send its .diff form under a second key too."
  3. Changed1 schema field changed
    • changedInput schema / properties / items / description
      Previous value: -"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. base: optional, the release the site runs, a commit sha or a version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock."New value: +"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. base: optional, the package's release installed before the upgrade, not version. A commit sha or a composer version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock."
  4. Changed1 schema field changed
    • changedInput schema / properties / items / description
      Previous value: -"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. Leave empty to build the items from composer_json and composer_lock."New value: +"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. base: optional, the release the site runs, a commit sha or a version, tried first as the merge base of a re-roll. Leave empty to build the items from composer_json and composer_lock."
  5. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / base
      Added value: +{
      +  "type": "string"
      +}
  6. Changed1 schema field changed
    • changedInput schema / properties / composer_lock / description
      Previous value: -"The text of composer.lock, not a path, or the slim {\"packages\":[{\"name\",\"version\"}]} form. It gives the installed version of each patched package."New value: +"The text of composer.lock, not a path. It gives the installed version of each patched package."
  7. Changed5 schema fields changed
    • changedInput schema / properties / composer_json / description
      Previous value: -"composer.json contents as text (not a path): extra.patches becomes the item list, one per patch."New value: +"The text of composer.json, not a path. Its extra.patches becomes the item list, one item per patch."
    • changedInput schema / properties / composer_lock / description
      Previous value: -"composer.lock contents as text, not a path (or the slim {\"packages\":[{\"name\",\"version\"}]} form): the installed version of each patched package."New value: +"The text of composer.lock, not a path, or the slim {\"packages\":[{\"name\",\"version\"}]} form. It gives the installed version of each patched package."
    • changedInput schema / properties / items / description
      Previous value: -"Patches to check, up to 50: project (drupal.org machine name webform or composer name drupal/webform; drupal or core for Drupal core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."New value: +"Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4.5. patch: diff text, or a drupal.org or git.drupalcode.org URL. title: optional, echoed back. Leave empty to build the items from composer_json and composer_lock."
    • changedInput schema / properties / patch_files / description
      Previous value: -"Text of each local patch file named in extra.patches, keyed by the path as written (patchs/x.patch) or its base name. URL patches need nothing."New value: +"The text of each local patch file listed in extra.patches, keyed by the path as written (patches/x.patch) or its base name. URL patches need nothing."
    • changedInput schema / properties / target_core / description
      Previous value: -"Core version the code each patch adds is checked against (11.4.5). Defaults to composer.lock's drupal/core, else the version of a drupal item."New value: +"The core version the added code is checked against, 11.4.5. Defaults to the lock's drupal/core, else the version of a drupal item."
  8. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / resolutions / items / properties / delete
      Added value: +{
      +  "type": "boolean"
      +}
  9. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / resolutions
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "choice": {
      +        "type": "string"
      +      },
      +      "file": {
      +        "type": "string"
      +      },
      +      "region": {
      +        "type": "integer"
      +      },
      +      "text": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "file",
      +      "region"
      +    ],
      +    "type": "object"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
  10. Changed1 schema field changed
    • changedInput schema / properties / items / description
      Previous value: -"Patches to check, up to 50: project (drupal.org machine name or composer name drupal/<name>; drupal for core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."New value: +"Patches to check, up to 50: project (drupal.org machine name webform or composer name drupal/webform; drupal or core for Drupal core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."
  11. Changed3 schema fields changed
    • changedInput schema / properties / composer_json / description
      Previous value: -"composer.json text: extra.patches becomes the item list, one per patch."New value: +"composer.json contents as text (not a path): extra.patches becomes the item list, one per patch."
    • changedInput schema / properties / composer_lock / description
      Previous value: -"composer.lock text (or the slim {\"packages\":[{\"name\",\"version\"}]} form): the installed version of each patched package."New value: +"composer.lock contents as text, not a path (or the slim {\"packages\":[{\"name\",\"version\"}]} form): the installed version of each patched package."
    • changedInput schema / properties / items / description
      Previous value: -"Patches to check, up to 50: project (machine name, drupal for core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."New value: +"Patches to check, up to 50: project (drupal.org machine name or composer name drupal/<name>; drupal for core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."
  12. Changed1 schema field changed
    • addedInput schema / properties / target_core
      Added value: +{
      +  "description": "Core version the code each patch adds is checked against (11.4.5). Defaults to composer.lock's drupal/core, else the version of a drupal item.",
      +  "type": "string"
      +}
  13. Changed5 schema fields changed
    • addedInput schema / properties / composer_json
      Added value: +{
      +  "description": "composer.json text: extra.patches becomes the item list, one per patch.",
      +  "type": "string"
      +}
    • addedInput schema / properties / composer_lock
      Added value: +{
      +  "description": "composer.lock text (or the slim {\"packages\":[{\"name\",\"version\"}]} form): the installed version of each patched package.",
      +  "type": "string"
      +}
    • changedInput schema / properties / items / description
      Previous value: -"Patches to check, up to 50: project (machine name, drupal for core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back)."New value: +"Patches to check, up to 50: project (machine name, drupal for core), version (the composer version installed, e.g. 1.13.0 or 11.4.5), patch (unified diff text, or a drupal.org / git.drupalcode.org patch URL), title (optional, echoed back). Leave empty to derive the items from composer_json + composer_lock."
    • addedInput schema / properties / patch_files
      Added value: +{
      +  "additionalProperties": {
      +    "type": "string"
      +  },
      +  "description": "Text of each local patch file named in extra.patches, keyed by the path as written (patchs/x.patch) or its base name. URL patches need nothing.",
      +  "type": "object"
      +}
    • removedInput schema / required
      Removed value: -[
      -  "items"
      -]
  14. Added

TDQS

A4.9/5.0
Behavior5/5

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

The annotations declare readOnlyHint=true and idempotentHint=true, but the description goes far beyond by explaining the internal mechanism: 'Verdicts come from git apply --check against the tag.' It also reveals side-effect-free operation ('This service downloads nothing'), and warning about potential runtime issues ('An applies patch can still be wrong at runtime'). It discloses the scope of checks and the meaning of fuzzy matches, all of which complement the annotations.

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?

The description is long but well-structured with bullet points and a clear hierarchy. It front-loads the purpose and then systematically covers input, output fields, and edge cases. Every sentence carries essential information; there is no fluff. It loses one point only because its length might be off-putting, but given the tool's complexity (many output fields, re-roll logic), this length is justified.

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

Completeness5/5

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

No output schema exists, so the description is the sole source of output semantics. It explains every return field: tag, applies_at, fuzzy, hunks_failed, reverse_applies, mr, merged_in_version, suggested, next_step, counts, hunks_shipped, files_shipped, moved_to, core_references, flagged, deprecated, checked. It also specifies how to handle unclear verdicts ('Report it as unclear. Never leave the row out.') and when to trigger reroll_patch. This is a complete operational guide.

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

Parameters5/5

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

The schema provides descriptions for each parameter, but the tool description adds substantial meaning: it explains the exact format of items (project names, version format, patch URL types), how patch_files should be keyed ('keyed by the source as written'), and the default behavior of target_core. It also clarifies that composer_json's extra.patches becomes the item list. This is far beyond baseline schema descriptions and fully compensates for any gaps.

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?

The description opens with a precise question: 'Does each composer patch still apply to the release the site installed, and is its fix already in that release?' This states the verb (check), resource (composer patches), and the specific evaluation criteria. It is clearly distinguished from sibling tools like scan_composer (which likely scans composer files) and project_upgrade_report (which focuses on upgrades).

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

Usage Guidelines5/5

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

The description gives explicit when-to-use and when-not-to-use instructions: 'Send composer_json and composer_lock after composer update.' It also provides negative directives: 'Do not download releases. Do not run patch --dry-run.' It explains the alternative input mode (items) and when to use it ('Leave empty to build the items from composer_json and composer_lock'). It even specifies follow-up actions like 'conflicts: call reroll_patch with that item.'

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.6/5.0
Disambiguation4/5

Tools cluster into related families (change records, symbol usage, patch checks), but descriptions and cross-references clearly separate list vs detail vs diff operations. Some adjacent tools like lookup_core_symbol and list_symbol_users require careful reading, yet their purposes are distinct enough for an agent to select correctly.

Naming Consistency4/5

Most tools follow a clear snake_case verb_noun pattern: list_*, get_*, lookup_*, query_, scan_, search_, reroll_, describe_. A few names like project_profile, subsystem_coupling, and what_changed deviate from verb_noun but remain consistent in style and readable.

Tool Count4/5

At 16 tools, the set is slightly above the typical well-scoped range, but the domain is broad: patch lifecycle, composer scanning, symbol lookup, change records, project profiles, dataset queries, and code search. Each tool covers a distinct query surface, so none feels redundant.

Completeness5/5

The toolkit covers the full read-only analysis lifecycle: scanning composer constraints, checking and re-rolling patches, exploring datasets, looking up core symbols and their users, listing change records, profiling projects, and assessing upgrade readiness. No obvious dead ends or missing operations for its stated purpose.

Resources