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. failure_mode: set when a patch applies and a file it touches no longer parses; keep the patch and fix the file. syntax_errors: the files behind it, one per file, path then the parser's message.

  • 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. provenance: optional, where a copied patch's bytes came from, {mr, commit, url, base, head, fetched, rerolled}. Send it when source is a local path. 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 the site declares, 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_coreNoCore the added code is checked against: a minor (11.4 or 11.4.x) or a release (11.4.5). A minor with no core release in the data is refused, and so is a major alone. latest checks no references. Defaults to the lock's drupal/core, else the version of a drupal item.
patches_fileNoThe text of the patches file, for a site on cweagans/composer-patches 2.x that keeps its patches out of composer.json. The path is in its own extra.composer-patches.patches-file, patches.json by default.
patches_lockNoThe text of patches.lock.json, which 2.x of the patch manager writes and applies from. Send it to judge what the site actually applies: it answers alone, over extra.patches and the patches file.
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.

  1. Changed1 schema field changed
    • changedInput schema / properties / target_core / description
      Previous 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."New value: +"Core the added code is checked against: a minor (11.4 or 11.4.x) or a release (11.4.5). A minor with no core release in the data is refused, and so is a major alone. latest checks no references. Defaults to the lock's drupal/core, else the version of a drupal item."
  2. Changed1 schema field changed
    • changedInput schema / properties / patch_files / description
      Previous 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."New value: +"The text of every patch the site declares, 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. 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: 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."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. provenance: optional, where a copied patch's bytes came from, {mr, commit, url, base, head, fetched, rerolled}. Send it when source is a local path. 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 / provenance
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "base": {
      +      "type": "string"
      +    },
      +    "commit": {
      +      "type": "string"
      +    },
      +    "fetched": {
      +      "type": "string"
      +    },
      +    "head": {
      +      "type": "string"
      +    },
      +    "mr": {
      +      "type": "string"
      +    },
      +    "rerolled": {
      +      "type": "string"
      +    },
      +    "url": {
      +      "type": "string"
      +    }
      +  },
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
    • addedInput schema / properties / patches_file
      Added value: +{
      +  "description": "The text of the patches file, for a site on cweagans/composer-patches 2.x that keeps its patches out of composer.json. The path is in its own extra.composer-patches.patches-file, patches.json by default.",
      +  "type": "string"
      +}
    • addedInput schema / properties / patches_lock
      Added value: +{
      +  "description": "The text of patches.lock.json, which 2.x of the patch manager writes and applies from. Send it to judge what the site actually applies: it answers alone, over extra.patches and the patches file.",
      +  "type": "string"
      +}
  4. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / upstream
      Added value: +{
      +  "type": "string"
      +}
  5. 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."
  6. 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."
  7. 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."
  8. 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."
  9. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / base
      Added value: +{
      +  "type": "string"
      +}
  10. 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."
  11. 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."
  12. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / resolutions / items / properties / delete
      Added value: +{
      +  "type": "boolean"
      +}
  13. 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"
      +  ]
      +}
  14. 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."
  15. 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."
  16. 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"
      +}
  17. 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"
      -]
  18. Added

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/non-destructive/openWorld=false, and the description adds genuinely new behavioral facts: verdicts come from 'git apply --check against the tag', the service performs no downloading so URL patches must be fetched by the caller, and the caveat that 'An applies patch can still be wrong at runtime'. It stops short of describing performance bounds or how the tag is resolved beyond the failure_mode/unknown notes.

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?

Very dense and long, but the opening question front-loads the purpose and each subsequent line is scoped to either an input parameter or an output field. Some output-field lines (e.g. hunks_shipped/moved_to) are tightly packed and could be split for readability, but little is redundant filler given there is no output schema.

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?

With no output schema, the description carries the full return-value burden and does so: it documents tag, applies_at, fuzzy, hunks_failed, reverse_applies, mr, merged_in_version, suggested verdicts, failure_mode, syntax_errors, core_references/flagged/deprecated/checked, next_step and counts. The unknown-row handling ('Report it as unclear. Never leave the row out.') closes the failure loop for an agent.

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

Parameters4/5

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

Schema description coverage is 100%, so 3 is the floor; the description goes beyond it by stating that a package's patches must be sent together and in composer.json order, and by enumerating the accepted patch sources (.drupal.org/files/issues, git.drupalcode.org MR/commit, .patch or .diff suffixes) and the accepted project/version formats. The order constraint in particular is not enforced by the schema.

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 lead sentence states a precise test with two outcomes ('does each composer patch still apply to the release... and is its fix already in that release'), which is a specific verb+resource rather than a restatement of the name. It also implicitly separates this tool from reroll_patch by naming that sibling as the escalation path for conflicts.

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?

Explicit when-to-use ('Send composer_json and composer_lock after composer update. Add patch_files for every patch'), explicit when-not ('Do not download releases. Do not run patch --dry-run'), and an explicit alternative routing rule ('conflicts: call reroll_patch with that item'). Ordering guidance per package is also given.

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.

Resources