Skip to main content
Glama

Compare PSR or PSD3 article versions

compare_versions
Read-onlyIdempotent

Use this to compare an article between the held Commission proposal and Council compromise versions of PSR or PSD3, within the same instrument. Serves the word-level comparison the build published: a pair is servable if and only if a diff artefact exists for it — the PSR and PSD3 proposal↔compromise pairs and nothing else. Every other pair, including every consolidated instrument's pinned as-adopted text, is refused with the URL where that text is published; this service never recomputes a comparison. Pairs match in either direction, and a reversed request is the same artefact with the ops inverted. changes reads that artefact structurally — paragraphs added or deleted, figures and durations moved, a heading rewritten — for a caller that needs what KIND of change this was without parsing the word-level ops. It is scoped to the article, not to the page of ops, and locates each entry no more precisely than the served text allows.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
to_locatorNoThe article on the to side.
from_locatorNoThe article on the from side. Alignment is identity on the article number, so naming either side names both.
instrument_idYesRegistry id of the instrument, e.g. "psr".
to_version_idYesVersion id the other side.
from_version_idYesVersion id one side of the pair.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
dataYes
errorYes
coverageYes
warningsYes
paginationYes
provenanceYes
derivationsYes
corpus_releaseYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • removedInput schema / properties / cursor / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedInput schema / properties / cursor / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • changedInput schema / properties / from_locator / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "annex": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Annex number, roman or arabic (\"I\", \"1\"); omit for an instrument whose single annex is unnumbered."
      -      },
      -      "article": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Article number as printed: \"97\", \"45a\", \"69-a\"."
      -      },
      -      "kind": {
      -        "description": "Which kind of provision the locator names.",
      -        "enum": [
      -          "article",
      -          "annex",
      -          "recital"
      -        ],
      -        "type": "string"
      -      },
      -      "paragraph": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Numbered paragraph within the article, e.g. \"2\"."
      -      },
      -      "point": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Lettered point within the paragraph, e.g. \"b\"."
      -      },
      -      "recital": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Recital number, e.g. \"95\"."
      -      },
      -      "subpoint": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Sub-point within the point."
      -      }
      -    },
      -    "required": [
      -      "kind"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "annex": {
      +        "description": "Annex number, roman or arabic (\"I\", \"1\"); omit for an instrument whose single annex is unnumbered.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "article": {
      +        "description": "Article number as printed: \"97\", \"45a\", \"69-a\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "kind": {
      +        "description": "Which kind of provision the locator names.",
      +        "enum": [
      +          "article",
      +          "annex",
      +          "recital"
      +        ],
      +        "type": "string"
      +      },
      +      "paragraph": {
      +        "description": "Numbered paragraph within the article, e.g. \"2\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "point": {
      +        "description": "Lettered point within the paragraph, e.g. \"b\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "recital": {
      +        "description": "Recital number, e.g. \"95\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "subpoint": {
      +        "description": "Sub-point within the point.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "kind"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / to_locator / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "annex": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Annex number, roman or arabic (\"I\", \"1\"); omit for an instrument whose single annex is unnumbered."
      -      },
      -      "article": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Article number as printed: \"97\", \"45a\", \"69-a\"."
      -      },
      -      "kind": {
      -        "description": "Which kind of provision the locator names.",
      -        "enum": [
      -          "article",
      -          "annex",
      -          "recital"
      -        ],
      -        "type": "string"
      -      },
      -      "paragraph": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Numbered paragraph within the article, e.g. \"2\"."
      -      },
      -      "point": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Lettered point within the paragraph, e.g. \"b\"."
      -      },
      -      "recital": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Recital number, e.g. \"95\"."
      -      },
      -      "subpoint": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "Sub-point within the point."
      -      }
      -    },
      -    "required": [
      -      "kind"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "annex": {
      +        "description": "Annex number, roman or arabic (\"I\", \"1\"); omit for an instrument whose single annex is unnumbered.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "article": {
      +        "description": "Article number as printed: \"97\", \"45a\", \"69-a\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "kind": {
      +        "description": "Which kind of provision the locator names.",
      +        "enum": [
      +          "article",
      +          "annex",
      +          "recital"
      +        ],
      +        "type": "string"
      +      },
      +      "paragraph": {
      +        "description": "Numbered paragraph within the article, e.g. \"2\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "point": {
      +        "description": "Lettered point within the paragraph, e.g. \"b\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "recital": {
      +        "description": "Recital number, e.g. \"95\".",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "subpoint": {
      +        "description": "Sub-point within the point.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "kind"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / data / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": {},
      -    "properties": {
      -      "article": {
      -        "type": "string"
      -      },
      -      "changes": {
      -        "anyOf": [
      -          {
      -            "items": {
      -              "additionalProperties": {},
      -              "properties": {
      -                "type": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "type"
      -              ],
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "What KIND of change this comparison evidences, read off the same artefact as pairs[]. Types: paragraph_added, paragraph_deleted, paragraph_amended (with words_changed, counting both sides of a substitution), figure_changed (with from/to quoting the served text), heading_changed, the article_* counterparts of the first three for an article's text outside any numbered paragraph, and none_detected where nothing was found — never an empty list. An entry carries `paragraph` and, where the served text settles it, `point` and `subpoint`, in the §7 locator model's own field names; an article_* entry carries none of them. Those components are a CITATION, not a promise of retrieval: a sub-point is often not a block get_provision serves, so open an entry at the enclosing point, and then the paragraph, which does serve the text the entry quotes. A roman sub-point is always qualified by its letter point (PSR Art 97(2)(a)(ii), never (ii) alone), and a list the text does not settle is left unlocated. ARTICLE-SCOPED, not page-scoped: the whole inventory travels with every page of pairs[], so a client paging through must not concatenate it. Repeated identical entries are repeated occurrences in one paragraph, not duplicates. Null means this release predates the inventory, which is not the same as none_detected."
      -      },
      -      "cite": {
      -        "type": "string"
      -      },
      -      "classification_note": {
      -        "type": "string"
      -      },
      -      "direction": {
      -        "type": "string"
      -      },
      -      "editorial_review_state": {
      -        "type": "string"
      -      },
      -      "from": {
      -        "additionalProperties": {},
      -        "properties": {
      -          "version_id": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "version_id"
      -        ],
      -        "type": "object"
      -      },
      -      "instrument_id": {
      -        "type": "string"
      -      },
      -      "pairs": {
      -        "items": {
      -          "additionalProperties": {},
      -          "properties": {
      -            "ops": {
      -              "items": {
      -                "prefixItems": [
      -                  {
      -                    "type": "string"
      -                  },
      -                  {
      -                    "type": "string"
      -                  }
      -                ],
      -                "type": "array"
      -              },
      -              "type": "array"
      -            }
      -          },
      -          "required": [
      -            "ops"
      -          ],
      -          "type": "object"
      -        },
      -        "type": "array"
      -      },
      -      "status": {
      -        "type": "string"
      -      },
      -      "to": {
      -        "additionalProperties": {},
      -        "properties": {
      -          "version_id": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "version_id"
      -        ],
      -        "type": "object"
      -      }
      -    },
      -    "required": [
      -      "instrument_id",
      -      "article",
      -      "cite",
      -      "from",
      -      "to",
      -      "status",
      -      "direction",
      -      "editorial_review_state",
      -      "classification_note",
      -      "changes",
      -      "pairs"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {},
      +    "properties": {
      +      "article": {
      +        "type": "string"
      +      },
      +      "changes": {
      +        "anyOf": [
      +          {
      +            "items": {
      +              "additionalProperties": {},
      +              "properties": {
      +                "type": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "type"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "What KIND of change this comparison evidences, read off the same artefact as pairs[]. Types: paragraph_added, paragraph_deleted, paragraph_amended (with words_changed, counting both sides of a substitution), figure_changed (with from/to quoting the served text), heading_changed, the article_* counterparts of the first three for an article's text outside any numbered paragraph, and none_detected where nothing was found — never an empty list. An entry carries `paragraph` and, where the served text settles it, `point` and `subpoint`, in the §7 locator model's own field names; an article_* entry carries none of them. Those components are a CITATION, not a promise of retrieval: a sub-point is often not a block get_provision serves, so open an entry at the enclosing point, and then the paragraph, which does serve the text the entry quotes. A roman sub-point is always qualified by its letter point (PSR Art 97(2)(a)(ii), never (ii) alone), and a list the text does not settle is left unlocated. ARTICLE-SCOPED, not page-scoped: the whole inventory travels with every page of pairs[], so a client paging through must not concatenate it. Repeated identical entries are repeated occurrences in one paragraph, not duplicates. Null means this release predates the inventory, which is not the same as none_detected."
      +      },
      +      "cite": {
      +        "type": "string"
      +      },
      +      "classification_note": {
      +        "type": "string"
      +      },
      +      "direction": {
      +        "type": "string"
      +      },
      +      "editorial_review_state": {
      +        "type": "string"
      +      },
      +      "from": {
      +        "additionalProperties": {},
      +        "properties": {
      +          "version_id": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "version_id"
      +        ],
      +        "type": "object"
      +      },
      +      "instrument_id": {
      +        "type": "string"
      +      },
      +      "pairs": {
      +        "items": {
      +          "additionalProperties": {},
      +          "properties": {
      +            "ops": {
      +              "items": {
      +                "items": false,
      +                "maxItems": 2,
      +                "minItems": 2,
      +                "prefixItems": [
      +                  {
      +                    "type": "string"
      +                  },
      +                  {
      +                    "type": "string"
      +                  }
      +                ],
      +                "type": "array"
      +              },
      +              "type": "array"
      +            }
      +          },
      +          "required": [
      +            "ops"
      +          ],
      +          "type": "object"
      +        },
      +        "type": "array"
      +      },
      +      "status": {
      +        "type": "string"
      +      },
      +      "to": {
      +        "additionalProperties": {},
      +        "properties": {
      +          "version_id": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "version_id"
      +        ],
      +        "type": "object"
      +      }
      +    },
      +    "required": [
      +      "instrument_id",
      +      "article",
      +      "cite",
      +      "from",
      +      "to",
      +      "status",
      +      "direction",
      +      "editorial_review_state",
      +      "classification_note",
      +      "changes",
      +      "pairs"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedOutput schema / properties / pagination / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "complete": {
      -        "type": "boolean"
      -      },
      -      "next_cursor": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ]
      -      },
      -      "total": {
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "complete",
      -      "next_cursor"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "complete": {
      +        "type": "boolean"
      +      },
      +      "next_cursor": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "total": {
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "complete",
      +      "next_cursor"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  2. First observed

TDQS

A4.4/5.0
Behavior5/5

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

The description goes well beyond the readOnlyHint and idempotentHint annotations by disclosing that the service never recomputes comparisons, refuses unsupported pairs with the URL to published text, treats reversed requests as the same artefact with inverted ops, and reads changes structurally. This is rich behavioral context that an agent could not infer from annotations alone.

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 front-loaded with the core use case and then layers on precise behavioral constraints. It is dense and uses some domain jargon, but every sentence contributes meaningful information about scope, refusal behavior, or output interpretation.

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?

For a tool with this complexity, the description covers all critical behavioral aspects: which pairs work, which are refused, what happens on reversed requests, how the structural change reading works, and the precision boundary of locators. The presence of an output schema means return-value details do not need to be repeated here.

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 71%, and the schema already documents instrument_id, version IDs, and both locators in detail. The description adds useful context about directionality and pair validity, but it does not explain cursor or limit semantics, which are the undocumented parameters.

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 states a specific action — compare an article between the held Commission proposal and Council compromise versions of PSR or PSD3 — and clearly delineates the resource scope. It distinguishes itself from siblings by naming the exact instrument types and pair types it serves.

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?

The description gives explicit servability conditions: a pair is servable if and only if a diff artefact exists, and only PSR/PSD3 proposal↔compromise pairs qualify. It also states that every other pair is refused, but it does not explicitly name an alternative sibling tool to use instead.

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