Skip to main content
Glama

sanctions-screening-mcp-server

sanctions-screening-mcp-server: trace ownership

sanctions_trace_ownership
Read-onlyIdempotent

Trace the GLEIF Level 2 corporate-ownership graph for an LEI: direct and ultimate parents and/or children, traversed breadth-first to a bounded depth, with relationship type for each edge. Direction both walks up to the parents and down to the children from the root, never sideways into siblings or co-parents. An ultimate-parent edge is a shortcut to the top of the group, not a hop: a node only it reaches within the depth is returned as a leaf flagged reachedVia: ultimate. Set screenNodes to also cross-reference every entity in the graph against all loaded watchlists — resolving "is anyone in this ownership chain sanctioned." Each node is cross-referenced as sanctions_get_entity does it: its legal name and every other and transliterated name screened strict (exact, then all tokens present — never fuzzy), and its LEI and registration number looked up as exact non-document identifiers, the registration number matching only an identifier published for the country of its legal jurisdiction; hits merge to one per designation, an OFAC party both OFAC lists publish to one hit whose sources names both, matchedOn naming every input that produced each. A node with no Level 1 record (missingEntityLeis) has no names, so it is looked up by its LEI alone. Each per-node screen is a screening AID: hits are candidates to verify, and an empty result for a node is not a clearance of that node. Each node whose parents were walked carries parentStatus for its direct and ultimate parent: a published relationship, a reporting exception with the reasons the entity gave (such as NATURAL_PERSONS or NON_CONSOLIDATING), none, or unknown when reporting exceptions are not loaded. The response says what it could not do: complete/truncated/missingEntityLeis report whether the loaded relationship graph within the depth is fully shown, screeningStatus reports whether the cross-reference actually ran, and each screened node reports whether its own hit list was capped. Requires a valid 20-character LEI (use sanctions_resolve_entity to obtain one).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
leiYesThe 20-character GLEIF LEI at the root of the ownership graph.
depthNoMaximum traversal depth from the root entity (1–5), on each side of a both walk. Ultimate-parent edges do not count as hops.
directionNoWalk parents (who owns it), children (what it owns), or both (default): a parents walk plus a children walk from the root, each to depth, never into siblings or co-parents.both
screenNodesNoWhen true, cross-reference every node against all watchlists — the ownership-chain cross-reference: the node's legal, other, and transliterated names screened strict, and its LEI and country-matched registration number looked up as identifiers. A node with no Level 1 record has no names: its LEI lookup alone.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
edgesNoDirected ownership edges between the nodes — every edge joins two nodes of this graph.
errorNoPresent when the call failed. Absent on success.
nodesNoAll entities reached in the traversal, including the root.
caveatNoDecision-support caveat — node screening is an aid, not a determination.
rootLeiNoThe LEI the traversal started from.
completeNoTrue when truncated is false (no loaded relationship on the walked side is left out) AND every node resolved to a GLEIF Level 1 record. It does not say every parent is known — most entities publish no parent relationship; read each node's parentStatus for what GLEIF publishes instead. False means the graph below is a partial view — read truncated and missingEntityLeis for which.
truncatedNoTrue when the loaded relationships hold ownership links on the walked side that this graph does not show: past the requested depth (re-run with a higher depth to see them), or the parents (or, on the children side, children) of a node flagged reachedVia: ultimate, which is never walked. An ultimate-parent edge counts only when it leads to an entity this graph does not return. False means neither: every chain the walk followed ends within the depth. Siblings and co-parents are never walked and never count.
screeningStatusNoWhether the per-node cross-reference ran: screened = every node was screened; not_requested = screenNodes was false; not_ready = screening was requested but the sanctions mirror has never synced, so NO node was screened and the absence of hits says nothing about any node.
flaggedNodeCountNoHow many screened nodes had at least one potential watchlist match.
missingEntityLeisNoLEIs published in the relationship corpus but absent from the GLEIF Level 1 entity mirror. Their nodes carry the LEI in place of a legal name and no jurisdiction/status — never read that LEI as a legal name. A per-node screen for them is the LEI looked up as an identifier, nothing else: with no record there is no legal name, other name, or registration number to screen, so their screenedInputs is empty and each hit is matchedOn their lei.
screenedNodeCountNoHow many nodes were screened (0 when screenNodes is false).
reportingExceptionsLoadedNoWhether GLEIF reporting exceptions are loaded in the mirror. When false, a node's parent level with no published relationship reads unknown rather than exception or none.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed29 schema fields changed
    • changedInput schema / properties / depth / description
      Previous value: -"Maximum traversal depth from the root entity (1–5)."New value: +"Maximum traversal depth from the root entity (1–5), on each side of a both walk. Ultimate-parent edges do not count as hops."
    • changedInput schema / properties / direction / description
      Previous value: -"Walk parents (who owns it), children (what it owns), or both (default)."New value: +"Walk parents (who owns it), children (what it owns), or both (default): a parents walk plus a children walk from the root, each to depth, never into siblings or co-parents."
    • changedInput schema / properties / screenNodes / description
      Previous value: -"When true, screen every node's legal name against all watchlists — the ownership-chain cross-reference."New value: +"When true, cross-reference every node against all watchlists — the ownership-chain cross-reference: the node's legal, other, and transliterated names screened strict, and its LEI and country-matched registration number looked up as identifiers. A node with no Level 1 record has no names: its LEI lookup alone."
    • changedOutput schema / properties / complete / description
      Previous value: -"True when the loaded Level 2 relationships within the requested depth are all shown (nothing was cut off by depth) AND every node resolved to a GLEIF Level 1 record. It does not say every parent is known — most entities publish no parent relationship; read each node's parentStatus for what GLEIF publishes instead. False means the graph below is a partial view — read truncated and missingEntityLeis for which."New value: +"True when truncated is false (no loaded relationship on the walked side is left out) AND every node resolved to a GLEIF Level 1 record. It does not say every parent is known — most entities publish no parent relationship; read each node's parentStatus for what GLEIF publishes instead. False means the graph below is a partial view — read truncated and missingEntityLeis for which."
    • changedOutput schema / properties / edges / description
      Previous value: -"Directed ownership edges between the nodes."New value: +"Directed ownership edges between the nodes — every edge joins two nodes of this graph."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `lei_not_found`: No GLEIF entity exists for the root LEI in the mirror. `mirror_not_ready`: The GLEIF (LEI) mirror has never completed an initial sync. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `lei_not_found`: No GLEIF entity in the mirror carries the root LEI, and its check digits are valid. `invalid_lei_checksum`: No GLEIF entity in the mirror carries the root LEI, and its ISO 17442 check digits fail. `mirror_not_ready`: The GLEIF (LEI) mirror has never completed an initial sync. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "lei_not_found",
      -  "mirror_not_ready"
      -]New value: +[
      +  "lei_not_found",
      +  "invalid_lei_checksum",
      +  "mirror_not_ready"
      +]
    • changedOutput schema / properties / missingEntityLeis / description
      Previous value: -"LEIs published in the relationship corpus but absent from the GLEIF Level 1 entity mirror. Their nodes carry the LEI in place of a legal name and no jurisdiction/status — never read that LEI as a legal name, and note any per-node screen for them ran against the LEI string."New value: +"LEIs published in the relationship corpus but absent from the GLEIF Level 1 entity mirror. Their nodes carry the LEI in place of a legal name and no jurisdiction/status — never read that LEI as a legal name. A per-node screen for them is the LEI looked up as an identifier, nothing else: with no record there is no legal name, other name, or registration number to screen, so their screenedInputs is empty and each hit is matchedOn their lei."
    • changedOutput schema / properties / nodes / items / properties / depth / description
      Previous value: -"Breadth-first depth from the root (root = 0)."New value: +"Breadth-first depth from the root (root = 0), counted over every relationship type except IS_ULTIMATELY_CONSOLIDATED_BY. On a node flagged reachedVia: ultimate it counts that one ultimate hop instead, so it can be shallower than the direct chain to the node."
    • changedOutput schema / properties / nodes / items / properties / parentStatus / properties / direct / properties / status / description
      Previous value: -"relationship = a Level 2 relationship at this level is published (see edges); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown."New value: +"relationship = a Level 2 relationship at this level is published — it is in edges when that parent is also a node of this graph (a flagged leaf's parents and a children-side node's other parents are read for this status, never walked); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown."
    • changedOutput schema / properties / nodes / items / properties / parentStatus / properties / ultimate / properties / status / description
      Previous value: -"relationship = a Level 2 relationship at this level is published (see edges); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown."New value: +"relationship = a Level 2 relationship at this level is published — it is in edges when that parent is also a node of this graph (a flagged leaf's parents and a children-side node's other parents are read for this status, never walked); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown."
    • addedOutput schema / properties / nodes / items / properties / reachedVia
      Added value: +{
      +  "description": "Present (ultimate) when only an IS_ULTIMATELY_CONSOLIDATED_BY edge reaches this node within the depth. That edge is a shortcut to the top of the group, not a hop, so the node is a leaf: its own parents (on the parents side) or children (on the children side) are never walked, and truncated is true when any of them is not in this graph. A higher depth places it by direct links only when a direct chain from the root reaches it; where that chain is broken (a parent reported by exception, or not at all), no depth does.",
      +  "enum": [
      +    "ultimate"
      +  ],
      +  "type": "string"
      +}
    • changedOutput schema / properties / nodes / items / properties / role / description
      Previous value: -"Position relative to the traversal."New value: +"root = the traced entity; parent = an ancestor, reached by walking parents; child = a descendant, reached by walking children. On a both walk, the side that reached the node — siblings and co-parents are never walked."
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / description
      Previous value: -"Per-node screening results, present only when screenNodes is true."New value: +"Per-node cross-reference results, one hit per designation (an OFAC party both OFAC lists publish once) — exact name and identifier matches first, then strong name matches. Present only when screenNodes is true."
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / matchType / description
      Previous value: -"Match classification."New value: +"Match classification of matchedName: exact or strong, never approximate (the cross-reference screens strict, never fuzzy). Absent when only an identifier produced the hit."
    • addedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / matchedIdentifiers
      Added value: +{
      +  "description": "Every identifier the designation publishes that equals this node's LEI or its country-matched registration number, as published. Present only when an identifier produced the hit.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "An identifier the designation publishes that equals the entity's LEI, or its registration number published for the country of its legal jurisdiction.",
      +    "properties": {
      +      "country": {
      +        "description": "Issuing country as published, when published.",
      +        "type": "string"
      +      },
      +      "type": {
      +        "description": "Identifier label as the list publishes it (e.g. Legal Entity Number, Registration Number).",
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "The identifier value, as published.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / matchedName / description
      Previous value: -"The name/alias that matched this node."New value: +"The designation's name or alias that matched one of this node's screened names — the strongest match. Absent when only an identifier produced the hit."
    • addedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / matchedOn
      Added value: +{
      +  "description": "Every input of this node that produced the hit — its legal name, an other or transliterated name, its LEI, or its registration number — in screening order. Only its LEI on a node in missingEntityLeis.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One value of the entity the cross-reference screened.",
      +    "properties": {
      +      "input": {
      +        "description": "Which value: legal_name, or other_name (an other or transliterated name), each screened as a name, strict; lei, or registration_number (the ID at the registration authority), each looked up as a non-document identifier.",
      +        "enum": [
      +          "legal_name",
      +          "other_name",
      +          "lei",
      +          "registration_number"
      +        ],
      +        "type": "string"
      +      },
      +      "nameType": {
      +        "description": "GLEIF's type for an other_name (e.g. TRADING_OR_OPERATING_NAME, AUTO_ASCII_TRANSLITERATED_LEGAL_NAME), or UNKNOWN for a name the mirror stored without one. Present on other_name only.",
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "The value as GLEIF publishes it.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "input",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / score / description
      Previous value: -"Raw Jaro-Winkler similarity (0–1) for approximate hits only."New value: +"Never set by this cross-reference: only an approximate (fuzzy) match carries a raw Jaro-Winkler score, and the cross-reference screens strict."
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / source / description
      Previous value: -"Watchlist the candidate is on."New value: +"Watchlist whose record this hit is attributed to: primaryName comes from it. For an OFAC party both OFAC lists publish, ofac_sdn unless the Consolidated record matched alone or better, and matchedName, matchedIdentifiers, and matchedOn cover what either record matched; sources names every list."
    • addedOutput schema / properties / nodes / items / properties / sanctionsHits / items / properties / sources
      Added value: +{
      +  "description": "Every screened list this candidate is on, in list order: one list, or ofac_sdn and ofac_consolidated together for an OFAC party both OFAC lists publish under one entry ID — one hit, not two. Read this, not source, for every list; the entry ID resolves in sanctions_get_designation under each.",
      +  "items": {
      +    "enum": [
      +      "ofac_sdn",
      +      "ofac_consolidated",
      +      "eu",
      +      "uk",
      +      "un"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / items / required
      Previous value: -[
      -  "source",
      -  "sourceLabel",
      -  "sourceEntryId",
      -  "primaryName",
      -  "matchedName",
      -  "matchType"
      -]New value: +[
      +  "source",
      +  "sourceLabel",
      +  "sourceEntryId",
      +  "sources",
      +  "primaryName",
      +  "matchedOn"
      +]
    • changedOutput schema / properties / nodes / items / properties / sanctionsScreen / description
      Previous value: -"Disclosure for this node's cross-reference screen: how many potential matches existed before the per-node cap, and whether sanctionsHits is the complete set. Present only when the node was screened."New value: +"Disclosure for this node's cross-reference: how many potential matches existed before the per-node cap, whether sanctionsHits is the complete set, and what was screened. Present only when the node was screened."
    • changedOutput schema / properties / nodes / items / properties / sanctionsScreen / properties / hasMore / description
      Previous value: -"True when this node's potential matches were capped — screen its legal name with sanctions_screen_name to page through the rest."New value: +"True when this node's potential matches were capped — re-screen its names with sanctions_screen_name and look up its LEI and registration number with sanctions_screen_identifier to see the rest. A node in missingEntityLeis has no names: look up its LEI."
    • addedOutput schema / properties / nodes / items / properties / sanctionsScreen / properties / screenedInputs
      Added value: +{
      +  "description": "What the cross-reference screened beyond the legal name and the LEI, which it screens on every node with a Level 1 record: every other and transliterated name, then the registration number when the node publishes one (a not-available placeholder such as N/A is none) and a legal jurisdiction to match it by. Empty when there is nothing beyond those two, and always on a node in missingEntityLeis, which has no name and is looked up by its LEI alone.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One value of the entity the cross-reference screened.",
      +    "properties": {
      +      "input": {
      +        "description": "Which value: legal_name, or other_name (an other or transliterated name), each screened as a name, strict; lei, or registration_number (the ID at the registration authority), each looked up as a non-document identifier.",
      +        "enum": [
      +          "legal_name",
      +          "other_name",
      +          "lei",
      +          "registration_number"
      +        ],
      +        "type": "string"
      +      },
      +      "nameType": {
      +        "description": "GLEIF's type for an other_name (e.g. TRADING_OR_OPERATING_NAME, AUTO_ASCII_TRANSLITERATED_LEGAL_NAME), or UNKNOWN for a name the mirror stored without one. Present on other_name only.",
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "The value as GLEIF publishes it.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "input",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / nodes / items / properties / sanctionsScreen / properties / totalAvailable / description
      Previous value: -"Potential matches this node's screen found before the per-node cap was applied."New value: +"Distinct designations this node's cross-reference found across every screened name and identifier, an OFAC party both OFAC lists publish counted once, before the per-node cap was applied."
    • changedOutput schema / properties / nodes / items / properties / sanctionsScreen / properties / totalAvailableBasis / description
      Previous value: -"How to read totalAvailable: exact = the complete strict match set for this node; lower_bound = a bounded scan produced it, so more may exist."New value: +"How to read totalAvailable. Always exact here: every name is screened strict, never fuzzy, and a strict screen counts every designation it reaches, so totalAvailable is the whole set across this node's screened names and identifiers."
    • changedOutput schema / properties / nodes / items / properties / sanctionsScreen / required
      Previous value: -[
      -  "totalAvailable",
      -  "totalAvailableBasis",
      -  "hasMore"
      -]New value: +[
      +  "totalAvailable",
      +  "totalAvailableBasis",
      +  "hasMore",
      +  "screenedInputs"
      +]
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when further ownership relationships exist beyond the requested depth — re-run with a higher depth to see them. False means the traversal reached the edge of the loaded relationship corpus."New value: +"True when the loaded relationships hold ownership links on the walked side that this graph does not show: past the requested depth (re-run with a higher depth to see them), or the parents (or, on the children side, children) of a node flagged reachedVia: ultimate, which is never walked. An ultimate-parent edge counts only when it leads to an entity this graph does not return. False means neither: every chain the walk followed ends within the depth. Siblings and co-parents are never walked and never count."
  2. Changed5 schema fields changed
    • changedInput schema / properties / screenNodes / description
      Previous value: -"When true, screen every node's legal name against all watchlists for beneficial-ownership screening."New value: +"When true, screen every node's legal name against all watchlists — the ownership-chain cross-reference."
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "rootLei",
      -      "nodes",
      -      "edges",
      -      "complete",
      -      "truncated",
      -      "missingEntityLeis",
      -      "screeningStatus",
      -      "screenedNodeCount",
      -      "flaggedNodeCount",
      -      "caveat"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "rootLei",
      +      "nodes",
      +      "edges",
      +      "complete",
      +      "truncated",
      +      "reportingExceptionsLoaded",
      +      "missingEntityLeis",
      +      "screeningStatus",
      +      "screenedNodeCount",
      +      "flaggedNodeCount",
      +      "caveat"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • changedOutput schema / properties / complete / description
      Previous value: -"True only when this is the full known ownership picture: nothing was cut off by the requested depth AND every node resolved to a GLEIF Level 1 record. False means the graph below is a partial view — read truncated and missingEntityLeis for which."New value: +"True when the loaded Level 2 relationships within the requested depth are all shown (nothing was cut off by depth) AND every node resolved to a GLEIF Level 1 record. It does not say every parent is known — most entities publish no parent relationship; read each node's parentStatus for what GLEIF publishes instead. False means the graph below is a partial view — read truncated and missingEntityLeis for which."
    • addedOutput schema / properties / nodes / items / properties / parentStatus
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "What GLEIF publishes about this node's direct and ultimate accounting-consolidation parents. Present only on nodes whose parents the traversal read — every node short of the depth limit when direction is parents or both; absent on a children walk.",
      +  "properties": {
      +    "direct": {
      +      "additionalProperties": false,
      +      "description": "What GLEIF publishes about the direct parent.",
      +      "properties": {
      +        "exceptionReasons": {
      +          "description": "Every reason given in the reporting exception (e.g. NATURAL_PERSONS, NON_CONSOLIDATING, NO_KNOWN_PERSON). Present only when status is exception.",
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "status": {
      +          "description": "relationship = a Level 2 relationship at this level is published (see edges); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown.",
      +          "enum": [
      +            "relationship",
      +            "exception",
      +            "none",
      +            "unknown"
      +          ],
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status"
      +      ],
      +      "type": "object"
      +    },
      +    "ultimate": {
      +      "additionalProperties": false,
      +      "description": "What GLEIF publishes about the ultimate parent.",
      +      "properties": {
      +        "exceptionReasons": {
      +          "description": "Every reason given in the reporting exception (e.g. NATURAL_PERSONS, NON_CONSOLIDATING, NO_KNOWN_PERSON). Present only when status is exception.",
      +          "items": {
      +            "type": "string"
      +          },
      +          "type": "array"
      +        },
      +        "status": {
      +          "description": "relationship = a Level 2 relationship at this level is published (see edges); exception = the entity filed a GLEIF reporting exception instead of naming this parent; none = GLEIF publishes neither; unknown = no relationship is published and reporting exceptions are not loaded in the mirror, so whether one was filed is unknown.",
      +          "enum": [
      +            "relationship",
      +            "exception",
      +            "none",
      +            "unknown"
      +          ],
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status"
      +      ],
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "direct",
      +    "ultimate"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / reportingExceptionsLoaded
      Added value: +{
      +  "description": "Whether GLEIF reporting exceptions are loaded in the mirror. When false, a node's parent level with no published relationship reads unknown rather than exception or none.",
      +  "type": "boolean"
      +}
  3. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "rootLei",
      +      "nodes",
      +      "edges",
      +      "complete",
      +      "truncated",
      +      "missingEntityLeis",
      +      "screeningStatus",
      +      "screenedNodeCount",
      +      "flaggedNodeCount",
      +      "caveat"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `lei_not_found`: No GLEIF entity exists for the root LEI in the mirror. `mirror_not_ready`: The GLEIF (LEI) mirror has never completed an initial sync. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "lei_not_found",
      +            "mirror_not_ready"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "rootLei",
      -  "nodes",
      -  "edges",
      -  "complete",
      -  "truncated",
      -  "missingEntityLeis",
      -  "screeningStatus",
      -  "screenedNodeCount",
      -  "flaggedNodeCount",
      -  "caveat"
      -]
  4. Changed6 schema fields changed
    • addedOutput schema / properties / complete
      Added value: +{
      +  "description": "True only when this is the full known ownership picture: nothing was cut off by the requested depth AND every node resolved to a GLEIF Level 1 record. False means the graph below is a partial view — read truncated and missingEntityLeis for which.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / missingEntityLeis
      Added value: +{
      +  "description": "LEIs published in the relationship corpus but absent from the GLEIF Level 1 entity mirror. Their nodes carry the LEI in place of a legal name and no jurisdiction/status — never read that LEI as a legal name, and note any per-node screen for them ran against the LEI string.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / nodes / items / properties / sanctionsScreen
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Disclosure for this node's cross-reference screen: how many potential matches existed before the per-node cap, and whether sanctionsHits is the complete set. Present only when the node was screened.",
      +  "properties": {
      +    "hasMore": {
      +      "description": "True when this node's potential matches were capped — screen its legal name with sanctions_screen_name to page through the rest.",
      +      "type": "boolean"
      +    },
      +    "totalAvailable": {
      +      "description": "Potential matches this node's screen found before the per-node cap was applied.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "totalAvailableBasis": {
      +      "description": "How to read totalAvailable: exact = the complete strict match set for this node; lower_bound = a bounded scan produced it, so more may exist.",
      +      "enum": [
      +        "exact",
      +        "lower_bound"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "totalAvailable",
      +    "totalAvailableBasis",
      +    "hasMore"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / screeningStatus
      Added value: +{
      +  "description": "Whether the per-node cross-reference ran: screened = every node was screened; not_requested = screenNodes was false; not_ready = screening was requested but the sanctions mirror has never synced, so NO node was screened and the absence of hits says nothing about any node.",
      +  "enum": [
      +    "screened",
      +    "not_requested",
      +    "not_ready"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when further ownership relationships exist beyond the requested depth — re-run with a higher depth to see them. False means the traversal reached the edge of the loaded relationship corpus.",
      +  "type": "boolean"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "rootLei",
      -  "nodes",
      -  "edges",
      -  "screenedNodeCount",
      -  "flaggedNodeCount",
      -  "caveat"
      -]New value: +[
      +  "rootLei",
      +  "nodes",
      +  "edges",
      +  "complete",
      +  "truncated",
      +  "missingEntityLeis",
      +  "screeningStatus",
      +  "screenedNodeCount",
      +  "flaggedNodeCount",
      +  "caveat"
      +]
  5. Changed2 schema fields changed
    • changedOutput schema / properties / nodes / items / properties / sanctionsHits / description
      Previous value: -"Per-node screening results, present only when screen_nodes is true."New value: +"Per-node screening results, present only when screenNodes is true."
    • changedOutput schema / properties / screenedNodeCount / description
      Previous value: -"How many nodes were screened (0 when screen_nodes is false)."New value: +"How many nodes were screened (0 when screenNodes is false)."
  6. First observed

TDQS

A4.3/5.0
Behavior5/5

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

Annotations only declare readOnly/idempotent/closed-world; the description goes far beyond, disclosing that a walk never goes sideways into siblings or co-parents, that an ultimate-parent edge is a shortcut not a hop, that per-node screening is an AID where an empty result is not a clearance, the parentStatus enumerations, and the completeness flags (complete/truncated/missingEntityLeis, screeningStatus, per-node cap). This is unusually rich behavioral disclosure for a read-only tool.

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

Conciseness3/5

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

The purpose is correctly front-loaded in the first sentence, but the remainder is a single ~350-word paragraph packing traversal, screening, status, and error semantics together. For a genuinely complex tool length is defensible, yet the density and repetition of schema/output-schema content make it harder to parse than it needs to be.

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?

Given a traversal-plus-screening tool, the description covers direction, depth semantics, screening behavior, status enums, and the failure/completeness signals an agent must interpret. An output schema exists, so its detailed return-field walkthrough is partly redundant, but nothing needed to call the tool correctly is missing.

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 description coverage is 100%, and the schema already documents lei, depth (ultimate-parent edges do not count as hops), direction (never into siblings or co-parents), and screenNodes. The description largely restates these, adding little syntax or format beyond what the schema provides, so the baseline of 3 applies.

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 opening sentence names a specific verb and resource — tracing the GLEIF Level 2 corporate-ownership graph for an LEI — with scope (direct/ultimate parents and/or children, breadth-first, bounded depth). This is unmistakably distinct from every sibling, none of which traverses ownership. An agent can select it without opening the schema.

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?

It states the prerequisite (a valid 20-character LEI) and routes the agent to sanctions_resolve_entity to obtain one, and explains that screenNodes opts into the cross-reference. What is missing is an explicit contrast with alternatives — e.g. when to trace ownership versus calling sanctions_get_entity or sanctions_screen_name directly — leaving that inference to the agent.

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.