Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

com.yaktool/yaktool

NPM · YAKTOOL-MCP · SCANNED SEP 20

73 local deterministic tools: GTIN, feeds, CSV-XLSX, Digital Link QR, e-invoices. Rules cited.

Available components

+4 this week 73 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • No production dependencies, so there is no dependency health to assess. View diagnostics → Pass
Provenance & Transparency19
Schema Quality & AI Usability64
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 25676 tokens (~351/item across 73 items; 73 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management89
  • Stability check failed: the tool surface changed between 0.2.0 and 0.4.2: 1 tool removals, 0 breaking changes, 3 additions. See how to fix → Fail
Tool Coverage99
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 96% of tool parameters carry a description.Partial
Tool Safety50
  • Injection-marker check failed: the description of tool "check_invoice_sequence" contains an instruction to conceal the call from the user, the text "DO NOT TELL THE USER", at byte 953 of that field, plus 1 further marker(s) of the same kind. See how to fix → Fail
  • We read all 73 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 73 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the com.yaktool/yaktool MCP server?

com.yaktool/yaktool runs locally as an npm package, launched with npx -y yaktool-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · yaktool-mcp

# add to Claude Code
claude mcp add com-yaktool-yaktool -- npx -y yaktool-mcp
// .cursor/mcp.json
{
  "mcpServers": {
    "com-yaktool-yaktool": {
      "command": "npx",
      "args": [
        "-y",
        "yaktool-mcp"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "com-yaktool-yaktool": {
      "command": "npx",
      "args": [
        "-y",
        "yaktool-mcp"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add com-yaktool-yaktool -- npx -y yaktool-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-yaktool-yaktool": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "yaktool-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add com-yaktool-yaktool --command npx --arg -y --arg yaktool-mcp
# ~/.hermes/config.yaml
mcp_servers:
  com-yaktool-yaktool:
    command: "npx"
    args: ["-y", "yaktool-mcp"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "com-yaktool-yaktool": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "yaktool-mcp"
      ]
    }
  }
}
# add to Vellum
assistant mcp add com-yaktool-yaktool -t stdio -c npx -a -y yaktool-mcp
// mcp.json
{
  "mcpServers": {
    "com-yaktool-yaktool": {
      "command": "npx",
      "args": [
        "-y",
        "yaktool-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 20 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 85 to 89.

  • 18 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 79 to 82.

  • 16 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 72 to 75.

  • 14 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 65 to 69.

  • 11 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 55 to 59.

  • 9 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 49 to 52.

  • 7 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 42 to 45.

  • 5 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 35 to 39.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 20 Sept 2026 · Analysed npm/yaktool-mcp@0.4.2

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem npm

Background: How many MCP packages publish verified provenance →

Dependencies 0 packages
Packages resolved 0
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 73 exposed · ~25,676 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
generate_slug ~296

Convert one title per line into a URL slug, and report the two things generic slug functions miss. AMBIGUITY: some letters have two accepted romanisations — German expands ü to ue, most software just drops the accent, so "Müller" is legitimately either "muller" or "mueller". Both are returned in `alternatives`; do NOT pick one silently, ask which convention the store uses. COLLISIONS: two titles that reduce to the same slug are not rejected by Shopify — it appends a number, so the second product quietly becomes "name-1" and every link already published for it points at the other product. Nothing in the import report mentions this. `actualHandle` shows what the platform would really create, and `collided` marks the affected rows. Characters from Han, Cyrillic, Arabic and other scripts are DROPPED rather than romanised, because romanisation is language-specific and a guess would produce a confident wrong URL. Removed characters are listed, since dropping punctuation is how two distinct products end up fighting over one URL. Returns { rows[{line,input,slug,alternatives[],actualHandle,collided,findings[]}], summary{total,collisions,ambiguous,empty} }.

NameTypeReqDescription
maxLengthintegerLength past which a slug is flagged as long (default 70).
titlesstringyesOne product title per line.

No output schema declared.

No examples provided.

identify_einvoice ~410

Answer "what is this file" for an EN 16931 e-invoice before validating it: is it UBL or CII syntax, an invoice or credit note, and which profile does its CustomizationID declare — Peppol BIS 3.0, XRechnung (with version), the EN 16931 core, or something unrecognised. THIS IS THE FRONT DOOR, NOT A VALIDATOR. It does not check business rules; it identifies the document and names which validator to send it to. `profile.routesTo` gives the slug of the matching validator on this site when one exists. THE CUSTOMIZATION ID IS THE KEY FIELD. The most common real-world rejection is not a broken rule but a document sent to a receiver running a different profile from the one it declares. `IDD-C02` names the recognised profile; `IDD-C03` means the declared profile is not one recognised here (a national profile not yet covered, a newer version, or a typo). THE CUSTOMIZATION IDs ARE VERIFIED VALUES, NOT GUESSES. Peppol from the Peppol spec; XRechnung extracted from KoSIT's public Schematron (github.com/itplr-kosit/xrechnung-schematron). XRechnung is matched as a family so both the current xeinkauf.de and the legacy xoev-de namespaces are recognised, and the version is extracted. Do not add or infer other profile URNs from memory. CII is IDENTIFIED but the invoice validators here read UBL (IDD-M01). A document that is not well formed is reported with the position (IDD-P01) and still identified as far as it parsed. Returns { input, wellFormed, syntax, kind, rootElement?, namespaceConfirms?, customizationId?, profileId?, profile?{id,label,routesTo?,version?}, findings[] }.

NameTypeReqDescription
xmlstringyesThe e-invoice XML (UBL or CII).

No output schema declared.

No examples provided.

identify_tracking_carrier ~247

Work out which carrier a tracking number belongs to from its format, and VERIFY its check digit where the carrier publishes an algorithm (UPS 1Z, USPS Intelligent Mail package barcode, and UPU S10 for international post). A verified check digit is evidence; a matching shape is only a guess, and the result labels which one you have (`checkDigitValid` is true/false when verifiable, and absent when the carrier publishes no algorithm). AMBIGUITY IS EXPLICIT: many formats are just "N digits" and are shared by several carriers, so ALL matching candidates are returned, sorted with verified ones first — do not treat the first entry as certain when `hasVerified` is false. S10 numbers also decode the country of origin from their final two letters. SCOPE: this identifies formats only — it does NOT track packages or return delivery status, which would require each carrier's API. Returns { input, normalized, candidates[{carrier, format, confidence, checkDigitValid?, checkDigitNote?, origin?, note?}], hasVerified, message? }.

NameTypeReqDescription
trackingNumberstringyesThe tracking number, with or without spaces and hyphens.

No output schema declared.

No examples provided.

interpret_eight_digit_barcode ~118

An 8-digit barcode is ambiguous: it may be a UPC-E (a compressed 12-digit UPC-A) or a GTIN-8/EAN-8 (an independent GS1 range for small packages that expands to nothing). They use different validation and mean different things. This tool returns BOTH readings with validity for each, rather than guessing — use it before assuming which one you have. Returns an array of { format, valid, upcA?, explanation }.

NameTypeReqDescription
digitsstringyesExactly 8 digits.

No output schema declared.

No examples provided.

lint_bullet_points ~457

Lint listing bullets (one per line) for length, all-caps, HTML, off-platform contact details, promotional wording and repeated openings — and screen the copy for the claim language that appears in FDA and FTC enforcement. TWO BULLET FINDINGS MATTER MORE THAN THE REST. BUL-P01 (an email address, phone number or URL) is enforced against the SELLING ACCOUNT, not the listing — treat it as urgent. BUL-C01 means the surplus bullets are not displayed AND not indexed, so copy that lives only there is invisible to search too. THE CLAIM SCREEN IS NOT A COMPLIANCE CHECK, and you must say so whenever you report its output. A hit is not a violation; a clean result is not clearance. Regulators read whole claims in context and no word list is exhaustive. Never tell a user their copy is compliant on the basis of this tool, and never give legal advice about it. Each claim hit carries a `why`. RELAY THE WHY, not just the word. A tool that only flags "cure" teaches people to write "heal", which changes nothing about the risk and makes the copy worse. The disease rule exists because the FDA states only a drug may claim to "diagnose, treat, cure or prevent any disease" — those four verbs are the regulator's own list. "FDA approved" is flagged because the FDA does not approve supplements or cosmetics at all, so it is a false statement about a federal agency rather than an exaggeration. maxBullets and maxCharacters are CATEGORY-SPECIFIC and live behind marketplace logins. The defaults (5, 500) are common general values, not a specification — if the user knows their category limits, pass them. Returns { bullets[], lengths[], claims[{text,bullet,start,end,category,why}], findings[] }; offsets are code points.

NameTypeReqDescription
bulletsstringyesOne bullet per line; leading -, * or • are stripped.
maxBulletsintegerBullets the category displays (default 5).
maxCharactersintegerCharacter limit per bullet (default 500).
skipClaimsbooleanTurn off claim screening for categories where it does not apply.

No output schema declared.

No examples provided.

lint_listing_title ~312

Check a product listing title against 16 marketplace rules and per-platform length limits (Amazon, eBay, Etsy, Walmart, Google Shopping, Shopify SEO). ESSENTIAL for listing-generation agents: titles are rejected or suppressed for length, ALL-CAPS words, emoji, trademark symbols, promotional wording ("free shipping", "best price"), subjective claims, contact details, repeated words, and invisible/full-width/non-Latin characters left over from spreadsheets and translation. Returns `spans` — character ranges (CODE POINT offsets, not UTF-16) marking exactly where each problem sits, so you can fix the specific words rather than rewriting the title. Also returns per-platform verdicts with characters remaining, plus the byte count. Pass `platforms` to narrow the length check to the marketplaces you actually sell on. Returns { input, characters, bytes, limits[], findings[], spans[], ok }. BULK: pass `values` (an array, max 1000) instead of the single value to check a whole column in one call. The result is then { rows, summary } rather than a single result. Do not loop this tool over a column one value at a time.

NameTypeReqDescription
platformsarrayMarketplaces to check length against (e.g. ["Amazon","eBay"]). Defaults to all.
titlestringThe product title exactly as it would be submitted.
valuesarrayBulk form: one value per array element. Use this instead of looping the single-value form.

No output schema declared.

No examples provided.

lookup_un_number ~392

Search the Hazardous Materials Table by product name (perfumery, lithium ion, aerosol) or by UN/NA number. Name search is the primary path — people have a product, not a number. THIS IS A LOOKUP, NOT A CLASSIFICATION, and you must say so. Which entry a product falls under depends on its actual composition, concentration, packaging and mode of transport — a dangerous goods classification done by someone qualified from the product’s safety data sheet. Never tell a user their product "is UN####" on the basis of a word match. ONE NUMBER OFTEN COVERS SEVERAL ENTRIES with different packing groups and different per-package limits — UN1950 (aerosols) has separate flammable, non-flammable and corrosive entries. All of them are returned; DO NOT pick one. Getting the number right is not the same as getting the entry right, and filling the number in while taking the wrong limit is how a shipment is refused with the paperwork apparently complete. A "no match" result is NOT evidence the goods ship as ordinary cargo — many hazardous items are listed under a chemical name rather than the one on the box. Suggest the safety data sheet. UNN-F01 marks entries forbidden on passenger or cargo aircraft: that is not a paperwork question, the goods cannot travel that way. Rows come from 49 CFR 172.101, the US table that adopts the international list — the UN’s own publication and the US regulator’s site both refuse automated access. For international movements say the mode’s own regulations must be confirmed. Returns { query, matches[{id,number,name,hazardClass,packingGroup,labels,passengerLimit,cargoLimit}], matchedBy, findings[] }.

NameTypeReqDescription
limitintegerMaximum entries to return (default 25).
querystringyesA product name or a UN/NA number.

No output schema declared.

No examples provided.

parse_gs1_element_string ~397

Decode a GS1 element string (the data under a GS1-128 / logistics barcode) into its Application Identifiers, using 30 known AI definitions. Accepts the human-readable bracketed form "(01)09501101020917(17)250101(10)LOT1" and raw scanner output where FNC1 appears as the GS control character (U+001D). THE RULE MOST PARSERS GET WRONG: an AI has a predefined length when its FIRST TWO DIGITS appear in the GS1 predefined-length table (00,01,02,03,04,11-19,20,31-36,41) — those are followed directly by the next AI with NO separator. Every other AI is variable-length and MUST be terminated by FNC1 unless it is last. Ignore this and a batch number silently swallows the serial number after it, producing data that looks fine and is wrong. This tool reports a missing separator explicitly. Also validates GTIN/SSCC/GLN check digits inside the string, YYMMDD dates (where day 00 legitimately means END OF MONTH), the decimal indicator on measurement AIs (3103 = 3 implied decimals), the AI character set (lowercase is not permitted), and repeated AIs. Two-digit years resolve on a sliding window; pass `referenceYear` for a deterministic reading. Unknown AIs stop the parse rather than being guessed at, because an unknown AI has no known data length. Returns { input, normalized, elements[{ai, title, value, interpreted?, start, end, findings[]}], findings[], ok }.

NameTypeReqDescription
elementStringstringyesThe GS1 element string, bracketed or raw. Pass it exactly as scanned — separators are part of what gets checked.
referenceYearintegerYear used to resolve two-digit dates (GS1 sliding window). Defaults to the current year.

No output schema declared.

No examples provided.

repair_feed ~441

Repair a tab- or comma-separated feed (first line is the header) in one pass: mojibake, spreadsheet damage, invisible characters, stray whitespace and inconsistent capitalisation. IT ONLY APPLIES REPAIRS THAT HAVE EXACTLY ONE POSSIBLE ANSWER. Mojibake is reversed only when re-encoding the repaired text reproduces the original bytes — several encoding chains produce plausible output and only one round-trips. TWO LISTS COME BACK AND THE SECOND MATTERS AS MUCH AS THE FIRST. `repairs` is what changed; `leftAlone` is every cell it refused to guess at, with the reason and, where they exist, the competing candidates. Relay `leftAlone` to the user — do NOT resolve those cells yourself. A cell a spreadsheet turned into a date could have come from several originals, and choosing needs to know what the product is. UNRECOVERABLE IS NOT THE SAME AS FINE. Scientific notation (8.71E+12) destroys digits permanently; those cells appear in `leftAlone` as needing the source system, not in `repairs`. Never reconstruct the missing digits — a barcode you completed from memory is worse than a visibly broken one. IT WILL NOT MERGE SYNONYMS. L and Large stay separate: whether they mean the same thing is a merchandising decision. Use audit_column to show the seller those sets. Capitalisation IS unified within a column (presentation, never which value a cell holds); pass skipCaseUnification for columns where case carries meaning, such as SKUs. REPAIRING IS NOT VALIDATING — run the result through validate_marketplace_feed afterwards. Returns { header[], rows[], repairs[{row,column,before,after,kind,because}], leftAlone[{row,column,value,because,candidates?}], findings[] } plus `output` when `render` is set.

NameTypeReqDescription
feedstringyesThe feed with a header row.
renderbooleanAlso return the repaired feed as text.
skipCaseUnificationbooleanLeave capitalisation alone (use for columns where case is meaningful, like SKUs).

No output schema declared.

No examples provided.

validate_awb ~304

Check an 11-digit air waybill number: three-digit IATA airline prefix, seven-digit serial, and an UNWEIGHTED MODULO-7 check digit — the serial divided by seven, remainder is the check digit. Nothing is weighted and nothing alternates. USEFUL SHORTCUT: because the check digit is a remainder modulo seven it can only be 0-6, so **a number ending in 7, 8 or 9 is invalid regardless of airline or serial** and needs no arithmetic to reject. Use this to screen a batch before doing anything else. This tool does NOT map the airline prefix to a carrier name — that table is maintained by IATA and not published openly, and an unverified table would give confidently wrong answers about real shipments. Do not fill it in from memory either. Returns { input, normalized, formatted?, airlinePrefix?, serial?, checkDigit?, expectedCheckDigit?, valid, findings[] }. BULK: pass `values` (an array, max 1000) instead of the single value to check a whole column in one call. The result is then { rows, summary } rather than a single result. Do not loop this tool over a column one value at a time.

NameTypeReqDescription
valuestringThe air waybill number, with or without hyphens or spaces.
valuesarrayBulk form: one value per array element. Use this instead of looping the single-value form.

No output schema declared.

No examples provided.

validate_container_number ~275

Validate an 11-character freight container number against ISO 6346 and decode its parts (owner code, equipment category, serial, check digit). Two traps that make hand-written implementations reject valid numbers: (1) the letter values start at A=10 and SKIP EVERY MULTIPLE OF 11, so B=12 (not 11), L=23 (not 22), V=34 (not 33) — an alphabetical mapping is wrong; (2) the weights are POWERS OF TWO (1,2,4,…,512), not position numbers. The fourth letter is the equipment category and may only be U (freight container), J (detachable equipment) or Z (trailer/chassis). The standard has a known weakness: a remainder of 10 is written as 0, so some numbers ending in 0 are genuinely ambiguous — `usedTenAsZero` flags when yours is one of them. Owner prefixes are registered with the BIC; we report the code without a guessed company name. Returns { input, normalized, valid, ownerCode, category{code,description}, serial, checkDigit, expectedCheckDigit, usedTenAsZero, findings[] }.

NameTypeReqDescription
containerNumberstringyesThe 11-character container number, with or without the printed spacing.

No output schema declared.

No examples provided.

validate_google_feed ~289

Pre-flight a Google Merchant Center product feed (CSV or TSV text) against 28 documented rules and get every fixable problem at once, instead of discovering them as disapprovals after upload. Covers: file structure (delimiter, header, duplicate/unknown columns, ragged rows), required attributes (id/title/description/link/image_link/availability/price/condition), product identifiers (FULL GS1 validation of the gtin column including spreadsheet damage, plus the identifier_exists x gtin x brand x mpn logic and duplicate ids), formats and enums (price "9.99 USD" form, availability/condition values, absolute URLs, title/description length), and content quality (all-caps titles, promotional text, placeholder values). SCOPE LIMIT — anything requiring a website visit (landing-page price match, image reachability, policy judgement) is NOT checked, so a clean result is not a guarantee of approval. Returns { rows[{line, id, findings[], ok}], fileFindings[], summary{totalRows, okRows, errorRows, warningRows, byRule, detectedDelimiter, columns, unknownColumns} }. Read summary.byRule first: it shows which single rule affects the most rows.

NameTypeReqDescription
feedstringyesThe feed file contents as text (CSV or TSV, header row first). Pass it raw — delimiter and encoding quirks are part of what gets checked.

No output schema declared.

No examples provided.

validate_gs1_key ~369

Validate the two GS1 keys that are not products: the 18-digit SSCC on a logistic unit and the 13-digit GLN identifying a party or place. Checks the Mod-10 check digit and reports what the number can be. THE MOST IMPORTANT THING THIS RETURNS IS AN AMBIGUITY. A GLN and a GTIN-13 are indistinguishable as numbers — same length, same check digit algorithm, same prefix pool. For 13 digits the `readings` array therefore holds BOTH interpretations with the condition under which each applies. Do not tell a user "this is a GLN"; tell them it is a well-formed 13-digit GS1 key and that the field it sits in decides which. Two damage patterns worth knowing: a 17-digit value is almost always an SSCC whose leading zero a spreadsheet ate (if restoring it validates, the finding gives the recovered number), and a 20-digit value starting 00 is an SSCC still carrying the AI (00) prefix from a GS1-128 scan, which is stripped automatically. Also note the SSCC extension digit is NOT the packaging-level indicator that opens a GTIN-14 — it has no meaning at all. This tool will NOT split the number into company prefix and reference: a GS1 Company Prefix is 7-12 digits and the boundary lives only in GS1 GEPIR. Do not infer it. Returns { rows[{line,input,normalized,valid,keyType,checkDigit,prefixOrigin?,readings[],findings[]}], summary{total,valid,invalid,duplicates} }.

NameTypeReqDescription
expectstringForce a key type; omit to infer from length.
numbersstringyesOne SSCC or GLN per line.

No output schema declared.

No examples provided.

validate_gtin ~277

Validate a single GTIN (GTIN-8 / GTIN-12 UPC-A / GTIN-13 EAN-13 / GTIN-14) against 26 documented rules: check digit (Mod-10), input cleaning (Excel scientific-notation damage, lost leading zeros, separators, full-width digits), format equivalences, GS1 prefix attribution, restricted/coupon/ISBN/ISSN ranges, and placeholder detection. Returns a structured ValidationResult: { input, normalized, valid, format, findings[{ruleId, severity, message, fix?, sourceUrl?}], meta }. `valid` means no error-level findings; warnings (in-store codes, placeholders) do not make it false. Pass the raw value as-is — do NOT pre-clean it; cleaning is part of what gets validated. BULK: pass `values` (an array, max 1000) instead of the single value to check a whole column in one call. The result is then { rows, summary } rather than a single result. Do not loop this tool over a column one value at a time.

NameTypeReqDescription
valuestringThe barcode value exactly as found in the source data (uncleaned).
valuesarrayBulk form: one value per array element. Use this instead of looping the single-value form.

No output schema declared.

No examples provided.

validate_iban ~573

Check one IBAN per line against ISO 7064 mod-97 AND the fixed length and BBAN character layout of the country. STATE THIS WHENEVER YOU REPORT A RESULT: a passing IBAN is structurally consistent and NOTHING MORE. It does not mean the account exists, is open, belongs to anyone in particular, or can receive a payment. The single most common reason a person checks an IBAN is that an invoice arrived with changed bank details — in that situation a "valid" result is not reassurance, and you should say so and suggest confirming by phone on a previously known number. Never let a pass here read as clearance to pay. The length check is the useful part: every country has exactly one IBAN length, so a failure is reported as "Germany is 22 characters, this is 21" rather than "checksum failed", and a character-class failure names the position ("character 9 must be a digit"). Prefer relaying those specifics over a bare verdict. Do NOT substitute `expectedCheckDigits` into the IBAN to make it pass — that hides an error in the account number rather than fixing it. IBAN is not universal: for US, CA, AU, NZ, JP, CN, IN, ZA, MX, HK and SG the result is IBAN-K01 explaining that the country uses a different scheme and naming it. If a user asks for "the IBAN" of a US account, the answer is that no such thing exists — give them the ABA routing number, account number and SWIFT/BIC instead. BIC: pass `bic` instead to check a SWIFT/BIC. Two findings there are worth leading with. BIC-T01 — a "0" in the SECOND position of the location code marks a TEST BIC, not one for the live network; it looks exactly like a normal BIC and nothing reveals it until a payment fails. BIC-C02 — SWIFT assigned XK to Kosovo, which has no ISO 3166-1 code, so a Kosovan BIC is valid despite failing a naive "country must be ISO" check; do not tell a user their XK code is wrong. ISO 9362 is a paid standard and both iso.org and swift.com refuse automated requests, so the BIC structure cited is a public transcription rath…

NameTypeReqDescription
bicstringA SWIFT/BIC to check instead.
ibansstringOne IBAN per line; spaces and lower case are fine.

No output schema declared.

No examples provided.

validate_imei ~249

Validate a device IMEI (15 digits, Luhn check digit) or recognise an IMEISV (16 digits). CRITICAL distinction: an IMEISV has NO check digit — its final two digits are a Software Version Number — so running Luhn over a 16-digit value and reporting "invalid" is a category error, not a finding. This tool identifies which form you have and only checks the checksum where one exists. A 14-digit value is an IMEI missing its check digit, and the completed number is returned. The first 8 digits are the TAC (model identifier); resolving it to an actual device needs the licensed GSMA TAC database, so the code is reported without a guessed model name. A valid check digit proves the digits are consistent — it says nothing about blacklist or stolen status, which live in carrier and GSMA databases. Returns { input, normalized, valid, type: "IMEI"|"IMEISV", tac, serial, checkDigit?, expectedCheckDigit?, softwareVersion?, findings[] }.

NameTypeReqDescription
imeistringyesThe IMEI or IMEISV, with or without spaces, hyphens or slashes.

No output schema declared.

No examples provided.

validate_isbn ~305

Validate an ISBN and return BOTH forms at once. ISBN-10 and ISBN-13 use DIFFERENT checksum algorithms — ISBN-10 is modulo-11 with weights 10..2 where a check value of 10 is written as the letter X; ISBN-13 is the GS1 modulo-10 checksum. Applying the wrong one is the most common ISBN bug. CRITICAL: ISBNs beginning 979 have NO 10-character form (the prefix was introduced after ISBN-10 was retired), so `isbn10` is absent for them — do not synthesise one. The 979-0 sub-range is ISMN (printed music), not a book. Also identifies the registration group (the issuing agency — not the country of printing or the language of the text) and flags structurally implausible values. Returns { input, normalized, format, valid, isbn13, isbn10?, group?, findings[], meta? }. BULK: pass `values` (an array, max 1000) instead of the single value to check a whole column in one call. The result is then { rows, summary } rather than a single result. Do not loop this tool over a column one value at a time.

NameTypeReqDescription
valuestringThe ISBN in either form, with or without hyphens — raw, uncleaned.
valuesarrayBulk form: one value per array element. Use this instead of looping the single-value form.

No output schema declared.

No examples provided.

validate_marketplace_feed ~343

Check a tab- or comma-separated feed (first line is the header) against a destination platform’s profile. THE FINDING THAT JUSTIFIES THIS TOOL IS PFD-X01: a value that is CORRECT ON ANOTHER PLATFORM. Google Shopping writes in_stock with an underscore; Meta writes "in stock" with a space. A working Google feed copied to Meta has the availability field on every row and the value rejected on every row, and what the platform reports is usually just that the product is not live. When you see PFD-X01, lead with "this is the <other platform> spelling" — never send the user to check a spelling that was never wrong. PFD-D01 deserves emphasis too: Meta states that where a content ID repeats, ALL instances are ignored. A duplicate id does not overwrite — BOTH products disappear from the catalogue. ONLY THE META PROFILE IS FIELD-VERIFIED, from Meta’s publicly readable catalog fields reference. TikTok Shop, Walmart and Amazon carry ONLY constraints checkable without their documentation (unique id, core fields present, numeric price, absolute URLs) because their references are login-gated or change per release. Those runs emit PFD-N01 — relay it. A clean result on an unverified profile is NOT a statement that the feed will upload, and you must not fill the gap with a field list from memory. Returns { platform, profile, rows[{line,id?,findings[]}], summary{total,withErrors,duplicateIds}, findings[] }.

NameTypeReqDescription
feedstringyesThe feed with a header row; tab or comma separated.
platformstringyesDestination platform.

No output schema declared.

No examples provided.

validate_media_codes ~409

Check a mixed column of ISSNs and ISRCs; each line is routed by shape, so the caller does not have to sort them first. THE TWO CODES DIFFER IN WHAT CAN BE KNOWN. An ISSN carries a modulus 11 check digit (the eighth character, which may be X), so it can genuinely be checked. An ISRC carries NO check digit of any kind — the only question answerable about one is whether it is the right SHAPE. Never report an ISRC as "valid" meaning verified; say well formed. ISSN ↔ barcode: a periodical EAN-13 is 977 + the first SEVEN ISSN digits + a two-digit variant + a GS1 check digit. The ISSN check character is NOT in the barcode, so converting back requires recomputing it — the classic error in serials data. Pass a 977 barcode in and the recovered ISSN comes back with the character recomputed. ISRC prefixes: do NOT reject QM, QZ, QT, QN, ZZ or CP for "not being a country". IFPI allocates the whole five-character prefix and these are deliberate non-country allocations; rejecting them is a common and wrong behaviour. ISRC year: two digits, defined by IFPI as the year of ASSIGNMENT, and the scheme began in 1989 — so a value between the current year and 89 has no reading as an assignment year. The finding then names both possibilities (typo, or back catalogue coded with the recording year) without choosing. Returns { rows[{line,kind,issn?,isrc?,valid}], summary{total,issn,isrc,valid,invalid} }.

NameTypeReqDescription
codesstringyesOne ISSN, ISRC or 977 periodical barcode per line.
referenceYearintegerThe current year, used to read the ISRC two-digit year. Pass it — this server does not read the clock.

No output schema declared.

No examples provided.

validate_regulated_codes ~363

Check a column of CAS Registry Numbers (chemicals) or NDC codes (US drug products). Set `kind` — the two shapes overlap. CAS numbers carry a check digit (each digit multiplied by its position from the right, modulo 10), so a typo is genuinely detectable; the finding names the expected digit. A pass means well formed, NOT that the number names the substance on the label. THE CRITICAL NDC BEHAVIOUR: an NDC has NO check digit, and a ten-digit NDC WITHOUT hyphens is genuinely ambiguous. The FDA assigns 4-4-2, 5-3-2 or 5-4-1, and the hyphens are the only thing that distinguishes them — so the same ten digits pad into THREE DIFFERENT eleven-digit billing codes (0002735001 → 00002-7350-01 or 00027-0350-01 or 00027-3500-01). `readings` then holds all three. DO NOT pick one and present it as the answer: that is picking a different drug. Ask the user for the hyphenated form off the package or the FDA NDC Directory. Also: the eleven-digit form is a HIPAA BILLING format, not the NDC. The FDA-listed NDC is ten digits, and the padding is not reversible because a leading zero might be padding or might be part of the code. Returns { rows[{line,kind,cas?,ndc?,valid}], summary{total,valid,invalid,ambiguous} } — `ambiguous` counts rows needing a human.

NameTypeReqDescription
codesstringyesOne code per line.
kindstringyesWhich identifier these are.

No output schema declared.

No examples provided.

validate_shopify_csv ~302

Pre-flight a Shopify product CSV against 24 documented rules. Shopify reports problems only AFTER the import, and the most damaging one it never reports at all: if a Handle in the file already exists in the store, the import OVERWRITES that live product (title, description, pricing, variants) and still reports success. Pass `existingHandles` (the Handle column of a store export) to detect exactly which live products this import would replace — without it, that check stays silent rather than guessing. Also checks: header/required columns, handle format, non-adjacent handle blocks (which silently drop variants), variant option structure and duplicate combinations, price/boolean/inventory-policy/URL formats, duplicate SKUs, FULL GS1 validation of the barcode column, and dirty data (smart quotes, invisible characters, spreadsheet damage). Returns { rows[{line, handle, isProductRow, findings[], ok}], products[{handle, lines, variantCount}], fileFindings[], summary{productCount, errorRows, warningRows, overwriteCount, byRule, ...} }. Check summary.overwriteCount first — a non-zero value means live products will be replaced.

NameTypeReqDescription
csvstringyesThe product CSV contents as text, header row first. Pass it raw — encoding and quoting quirks are part of what gets checked.
existingHandlesarrayHandles already in the store (from Products → Export). Enables precise silent-overwrite detection.

No output schema declared.

No examples provided.

validate_tax_ids ~673

Check a column of EU VAT numbers or EORI numbers. Set `kind`. FORMAT AND CHECK DIGIT, NEVER REGISTRATION. There is no EU-wide VAT database — VIES asks each member state in turn — and this server makes no network requests. A pass means the value fits its country's published shape and, for most member states, its check digit is internally consistent; it does NOT mean the number is registered, belongs to that business, or is still active. Before a zero-rated invoice, the user must check VIES. Say this when you report a pass — for every result, not just failures. THE CHECK-DIGIT ALGORITHMS ARE NOT FROM OFFICIAL GOVERNMENT SOURCES, AND YOU MUST SAY SO WHEN RELAYING A RESULT. Most EU tax authorities do not publish their check-digit algorithm at all (the European Commission's own TIN compilation notes Greece's as "not publicly available" — typical, not exceptional). The algorithms here were cross-checked against python-stdnum (a mature, source-visible open-source library), then independently re-derived and verified against real worked examples by this project. That establishes the arithmetic is correct; it does not make it an official specification. Never tell a user a VAT-C02 pass means the number is "verified" or "confirmed" by the tax authority — say it is arithmetically consistent, sourced as above. CHECK-DIGIT COVERAGE IS PARTIAL BY DESIGN. Only the company/legal-entity branch is checked for countries whose scheme also covers individuals (personal-taxpayer numbers reuse a separate national ID checksum and are out of scope). `checksumValid` is `true`/`false` when checked, and `undefined` (VAT-C03) when this country or this branch has no implemented algorithm — undefined is NOT a pass, it means "not further checked", and you must not present it as validated. THE TWO HIGH-VALUE FORMAT FINDINGS ARE PREFIX ERRORS. Greece uses EL, not the ISO code GR — every other member state uses its ISO code, so GR is the natural thing to type and is always wrong; the finding hands back…

NameTypeReqDescription
kindstringyesWhich identifier these are.
numbersstringyesOne number per line.

No output schema declared.

No examples provided.

validate_vin ~283

Validate a 17-character Vehicle Identification Number and decode its sections (WMI/region, descriptor, year code, plant, serial). Three things implementations get wrong: (1) the letter-to-number table is NOT alphabetical — J restarts at 1 and S restarts at 2, and I, O and Q never appear in a VIN at all, so finding one means it was mis-transcribed (we suggest the corrected reading); (2) the MODEL YEAR IS AMBIGUOUS BY DESIGN — position 10 uses 30 codes that repeat, so "A" means 1980, 2010 and 2040. We return ALL candidates with a `likely` flag based on the North American position-7 convention; never report a single year as certain; (3) the check digit is mandatory in North America (FMVSS 115) but frequently unenforced elsewhere, so a failure is strong evidence of a transcription error, NOT proof the VIN is fake. A valid check digit confirms the transcription only — it says nothing about whether the vehicle exists or its title status. Returns { input, normalized, valid, checkDigitValid, expectedCheckDigit, structure{...}, yearCandidates[{year, likely}], findings[] }.

NameTypeReqDescription
vinstringyesThe 17-character VIN, with or without spaces and hyphens.

No output schema declared.

No examples provided.

Common questions

What is the com.yaktool/yaktool MCP server?

com.yaktool/yaktool is an MCP server listed in the public MCP registry as com.yaktool/yaktool. 73 local deterministic tools: GTIN, feeds, CSV-XLSX, Digital Link QR, e-invoices. Rules cited. This page covers its npm package (yaktool-mcp).

Is the com.yaktool/yaktool MCP server safe to use?

com.yaktool/yaktool scores 73 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the com.yaktool/yaktool MCP server expose?

com.yaktool/yaktool exposes 73 tools: validate_gtin, calculate_check_digit, analyze_amazon_search_terms, convert_gtin, validate_google_feed, and 68 more. Their descriptions and schemas cost roughly 25,676 tokens of context every time the server is loaded.

Is the com.yaktool/yaktool MCP server still maintained?

com.yaktool/yaktool is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the com.yaktool/yaktool MCP server under?

com.yaktool/yaktool declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.