@qinisolabs/qiniso 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  *Verified, trustworthy data tools for AI agents. "Qiniso" means "truth" in Zulu.*
10
10
 
11
- [Website](https://qinisolabs.github.io/qiniso/) · [GitHub](https://github.com/qinisolabs/qiniso) · [MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=qiniso)
11
+ [Website](https://qinisolabs.github.io/qiniso/) · [npm](https://www.npmjs.com/package/@qinisolabs/qiniso) · [GitHub](https://github.com/qinisolabs/qiniso) · [MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=qiniso)
12
12
 
13
13
  </div>
14
14
 
@@ -48,7 +48,7 @@ https://qiniso.qinisolabs.workers.dev/mcp
48
48
 
49
49
  Or run it locally over stdio: `npx -p @qinisolabs/qiniso qiniso-mcp`.
50
50
 
51
- ## What it verifies — 34 tools across 8 domains
51
+ ## What it verifies — 47 tools across 8 domains
52
52
 
53
53
  | Domain | Checks |
54
54
  | --- | --- |
@@ -56,7 +56,7 @@ Or run it locally over stdio: `npx -p @qinisolabs/qiniso qiniso-mcp`.
56
56
  | **Web / network** | TLD & domain (IANA root zone), IP, UUID, URL, email |
57
57
  | **Finance** | ISIN, CUSIP, SEDOL, LEI, US ABA routing |
58
58
  | **Crypto** | Ethereum (EIP-55), Bitcoin (Base58Check / Bech32) addresses |
59
- | **National & tax IDs** | Brazil CPF/CNPJ, South Africa ID, Spain DNI/NIE, India Aadhaar, EU/UK VAT |
59
+ | **National & tax IDs** | Brazil CPF/CNPJ, South Africa ID, Spain DNI/NIE, India Aadhaar, Italy Codice Fiscale, Poland PESEL, Netherlands BSN, Belgium NRN, Sweden personnummer, Norway fødselsnummer, Finland HETU, Portugal NIF, Turkey TCKN, China Resident ID, EU/UK VAT |
60
60
  | **Academic** | ISBN-10, ISSN, ORCID |
61
61
  | **Locale** | Phone (global), date parsing, currency, holidays (~200 countries), UK VAT-by-date |
62
62
  | **Addresses** | UK/US address parsing |
@@ -629,6 +629,115 @@ function validateGtin(input) {
629
629
  return result;
630
630
  }
631
631
 
632
+ // ../identifiers/dist/imei.js
633
+ function validateImei(input) {
634
+ const normalized = (input ?? "").replace(/[\s-]/g, "");
635
+ const result = {
636
+ input,
637
+ normalized,
638
+ valid: false,
639
+ type: null,
640
+ tac: null,
641
+ checkDigit: null,
642
+ expectedCheckDigit: null,
643
+ errors: []
644
+ };
645
+ if (!/^\d+$/.test(normalized)) {
646
+ result.errors.push("An IMEI must contain digits only (spaces and dashes are ignored).");
647
+ return result;
648
+ }
649
+ if (normalized.length === 16) {
650
+ result.type = "IMEISV";
651
+ result.tac = normalized.slice(0, 8);
652
+ result.valid = true;
653
+ result.note = "IMEISV (software-version form) has no check digit; format validated only.";
654
+ return result;
655
+ }
656
+ if (normalized.length !== 15) {
657
+ result.errors.push(`An IMEI must be 15 digits (or 16 for IMEISV); got ${normalized.length}.`);
658
+ return result;
659
+ }
660
+ result.type = "IMEI";
661
+ result.tac = normalized.slice(0, 8);
662
+ const expected = luhnCheckDigit(normalized.slice(0, 14));
663
+ result.checkDigit = normalized[14];
664
+ result.expectedCheckDigit = expected;
665
+ if (!luhnValid(normalized)) {
666
+ result.errors.push(`Luhn check digit failed: expected ${expected}, got ${normalized[14]}.`);
667
+ return result;
668
+ }
669
+ result.valid = true;
670
+ return result;
671
+ }
672
+
673
+ // ../identifiers/dist/gln.js
674
+ function validateGln(input) {
675
+ const normalized = (input ?? "").replace(/[\s-]/g, "");
676
+ const result = {
677
+ input,
678
+ normalized,
679
+ valid: false,
680
+ checkDigit: null,
681
+ gs1Prefix: null,
682
+ gs1Country: null,
683
+ errors: []
684
+ };
685
+ if (!/^\d+$/.test(normalized)) {
686
+ result.errors.push("A GLN must contain digits only (spaces and dashes are ignored).");
687
+ return result;
688
+ }
689
+ if (normalized.length !== 13) {
690
+ result.errors.push(`A GLN must be 13 digits; got ${normalized.length}.`);
691
+ return result;
692
+ }
693
+ const prefix3 = normalized.slice(0, 3);
694
+ result.gs1Prefix = prefix3;
695
+ result.gs1Country = gs1Country(prefix3);
696
+ const expected = gtinCheckDigit(normalized.slice(0, 12));
697
+ result.checkDigit = expected;
698
+ if (expected !== normalized[12]) {
699
+ result.errors.push(`Check digit failed: expected ${expected}, got ${normalized[12]}.`);
700
+ return result;
701
+ }
702
+ result.valid = true;
703
+ return result;
704
+ }
705
+
706
+ // ../identifiers/dist/sscc.js
707
+ function validateSscc(input) {
708
+ const normalized = (input ?? "").replace(/[\s-]/g, "");
709
+ const result = {
710
+ input,
711
+ normalized,
712
+ valid: false,
713
+ extensionDigit: null,
714
+ checkDigit: null,
715
+ gs1Prefix: null,
716
+ gs1Country: null,
717
+ errors: []
718
+ };
719
+ if (!/^\d+$/.test(normalized)) {
720
+ result.errors.push("An SSCC must contain digits only (spaces and dashes are ignored).");
721
+ return result;
722
+ }
723
+ if (normalized.length !== 18) {
724
+ result.errors.push(`An SSCC must be 18 digits; got ${normalized.length}.`);
725
+ return result;
726
+ }
727
+ result.extensionDigit = normalized[0];
728
+ const prefix3 = normalized.slice(1, 4);
729
+ result.gs1Prefix = prefix3;
730
+ result.gs1Country = gs1Country(prefix3);
731
+ const expected = gtinCheckDigit(normalized.slice(0, 17));
732
+ result.checkDigit = expected;
733
+ if (expected !== normalized[17]) {
734
+ result.errors.push(`Check digit failed: expected ${expected}, got ${normalized[17]}.`);
735
+ return result;
736
+ }
737
+ result.valid = true;
738
+ return result;
739
+ }
740
+
632
741
  // ../network/dist/data/tlds.json
633
742
  var tlds_default = ["aaa", "aarp", "abb", "abbott", "abbvie", "abc", "able", "abogado", "abudhabi", "ac", "academy", "accenture", "accountant", "accountants", "aco", "actor", "ad", "ads", "adult", "ae", "aeg", "aero", "aetna", "af", "afl", "africa", "ag", "agakhan", "agency", "ai", "aig", "airbus", "airforce", "airtel", "akdn", "al", "alibaba", "alipay", "allfinanz", "allstate", "ally", "alsace", "alstom", "am", "amazon", "americanexpress", "americanfamily", "amex", "amfam", "amica", "amsterdam", "analytics", "android", "anquan", "anz", "ao", "aol", "apartments", "app", "apple", "aq", "aquarelle", "ar", "arab", "aramco", "archi", "army", "arpa", "art", "arte", "as", "asda", "asia", "associates", "at", "athleta", "attorney", "au", "auction", "audi", "audible", "audio", "auspost", "author", "auto", "autos", "aw", "aws", "ax", "axa", "az", "azure", "ba", "baby", "baidu", "banamex", "band", "bank", "bar", "barcelona", "barclaycard", "barclays", "barefoot", "bargains", "baseball", "basketball", "bauhaus", "bayern", "bb", "bbc", "bbt", "bbva", "bcg", "bcn", "bd", "be", "beats", "beauty", "beer", "berlin", "best", "bestbuy", "bet", "bf", "bg", "bh", "bharti", "bi", "bible", "bid", "bike", "bing", "bingo", "bio", "biz", "bj", "black", "blackfriday", "blockbuster", "blog", "bloomberg", "blue", "bm", "bms", "bmw", "bn", "bnpparibas", "bo", "boats", "boehringer", "bofa", "bom", "bond", "boo", "book", "booking", "bosch", "bostik", "boston", "bot", "boutique", "box", "br", "bradesco", "bridgestone", "broadway", "broker", "brother", "brussels", "bs", "bt", "build", "builders", "business", "buy", "buzz", "bv", "bw", "by", "bz", "bzh", "ca", "cab", "cafe", "cal", "call", "calvinklein", "cam", "camera", "camp", "canon", "capetown", "capital", "capitalone", "car", "caravan", "cards", "care", "career", "careers", "cars", "casa", "case", "cash", "casino", "cat", "catering", "catholic", "cba", "cbn", "cbre", "cc", "cd", "center", "ceo", "cern", "cf", "cfa", "cfd", "cg", "ch", "chanel", "channel", "charity", "chase", "chat", "cheap", "chintai", "christmas", "chrome", "church", "ci", "cipriani", "circle", "cisco", "citadel", "citi", "citic", "city", "ck", "cl", "claims", "cleaning", "click", "clinic", "clinique", "clothing", "cloud", "club", "clubmed", "cm", "cn", "co", "coach", "codes", "coffee", "college", "cologne", "com", "commbank", "community", "company", "compare", "computer", "comsec", "condos", "construction", "consulting", "contact", "contractors", "cooking", "cool", "coop", "corsica", "country", "coupon", "coupons", "courses", "cpa", "cr", "credit", "creditcard", "creditunion", "cricket", "crown", "crs", "cruise", "cruises", "cu", "cuisinella", "cv", "cw", "cx", "cy", "cymru", "cyou", "cz", "dad", "dance", "data", "date", "dating", "datsun", "day", "dclk", "dds", "de", "deal", "dealer", "deals", "degree", "delivery", "dell", "deloitte", "delta", "democrat", "dental", "dentist", "desi", "design", "dev", "dhl", "diamonds", "diet", "digital", "direct", "directory", "discount", "discover", "dish", "diy", "dj", "dk", "dm", "dnp", "do", "docs", "doctor", "dog", "domains", "dot", "download", "drive", "dtv", "dubai", "dupont", "durban", "dvag", "dvr", "dz", "earth", "eat", "ec", "eco", "edeka", "edu", "education", "ee", "eg", "email", "emerck", "energy", "engineer", "engineering", "enterprises", "epson", "equipment", "er", "ericsson", "erni", "es", "esq", "estate", "et", "eu", "eurovision", "eus", "events", "exchange", "expert", "exposed", "express", "extraspace", "fage", "fail", "fairwinds", "faith", "family", "fan", "fans", "farm", "farmers", "fashion", "fast", "fedex", "feedback", "ferrari", "ferrero", "fi", "fidelity", "fido", "film", "final", "finance", "financial", "fire", "firestone", "firmdale", "fish", "fishing", "fit", "fitness", "fj", "fk", "flickr", "flights", "flir", "florist", "flowers", "fly", "fm", "fo", "foo", "food", "football", "ford", "forex", "forsale", "forum", "foundation", "fox", "fr", "free", "fresenius", "frl", "frogans", "frontier", "ftr", "fujitsu", "fun", "fund", "furniture", "futbol", "fyi", "ga", "gal", "gallery", "gallo", "gallup", "game", "games", "gap", "garden", "gay", "gb", "gbiz", "gd", "gdn", "ge", "gea", "gent", "genting", "george", "gf", "gg", "ggee", "gh", "gi", "gift", "gifts", "gives", "giving", "gl", "glass", "gle", "global", "globo", "gm", "gmail", "gmbh", "gmo", "gmx", "gn", "godaddy", "gold", "goldpoint", "golf", "goodyear", "goog", "google", "gop", "got", "gov", "gp", "gq", "gr", "grainger", "graphics", "gratis", "green", "gripe", "grocery", "group", "gs", "gt", "gu", "gucci", "guge", "guide", "guitars", "guru", "gw", "gy", "hair", "hamburg", "hangout", "haus", "hbo", "hdfc", "hdfcbank", "health", "healthcare", "help", "helsinki", "here", "hermes", "hiphop", "hisamitsu", "hitachi", "hiv", "hk", "hkt", "hm", "hn", "hockey", "holdings", "holiday", "homedepot", "homegoods", "homes", "homesense", "honda", "horse", "hospital", "host", "hosting", "hot", "hotels", "hotmail", "house", "how", "hr", "hsbc", "ht", "hu", "hughes", "hyatt", "hyundai", "ibm", "icbc", "ice", "icu", "id", "ie", "ieee", "ifm", "ikano", "il", "im", "imamat", "imdb", "immo", "immobilien", "in", "inc", "industries", "infiniti", "info", "ing", "ink", "institute", "insurance", "insure", "int", "international", "intuit", "investments", "io", "ipiranga", "iq", "ir", "irish", "is", "ismaili", "ist", "istanbul", "it", "itau", "itv", "jaguar", "java", "jcb", "je", "jeep", "jetzt", "jewelry", "jio", "jll", "jm", "jmp", "jnj", "jo", "jobs", "joburg", "jot", "joy", "jp", "jpmorgan", "jprs", "juegos", "juniper", "kaufen", "kddi", "ke", "kerryhotels", "kerryproperties", "kfh", "kg", "kh", "ki", "kia", "kids", "kim", "kindle", "kitchen", "kiwi", "km", "kn", "koeln", "komatsu", "kosher", "kp", "kpmg", "kpn", "kr", "krd", "kred", "kuokgroup", "kw", "ky", "kyoto", "kz", "la", "lacaixa", "lamborghini", "lamer", "land", "landrover", "lanxess", "lasalle", "lat", "latino", "latrobe", "law", "lawyer", "lb", "lc", "lds", "lease", "leclerc", "lefrak", "legal", "lego", "lexus", "lgbt", "li", "lidl", "life", "lifeinsurance", "lifestyle", "lighting", "like", "lilly", "limited", "limo", "lincoln", "link", "live", "living", "lk", "llc", "llp", "loan", "loans", "locker", "locus", "lol", "london", "lotte", "lotto", "love", "lpl", "lplfinancial", "lr", "ls", "lt", "ltd", "ltda", "lu", "lundbeck", "luxe", "luxury", "lv", "ly", "ma", "madrid", "maif", "maison", "makeup", "man", "management", "mango", "map", "market", "marketing", "markets", "marriott", "marshalls", "mattel", "mba", "mc", "mckinsey", "md", "me", "med", "media", "meet", "melbourne", "meme", "memorial", "men", "menu", "merck", "merckmsd", "mg", "mh", "miami", "microsoft", "mil", "mini", "mint", "mit", "mitsubishi", "mk", "ml", "mlb", "mls", "mm", "mma", "mn", "mo", "mobi", "mobile", "moda", "moe", "moi", "mom", "monash", "money", "monster", "mormon", "mortgage", "moscow", "moto", "motorcycles", "mov", "movie", "mp", "mq", "mr", "ms", "msd", "mt", "mtn", "mtr", "mu", "museum", "music", "mv", "mw", "mx", "my", "mz", "na", "nab", "nagoya", "name", "navy", "nba", "nc", "ne", "nec", "net", "netbank", "netflix", "network", "neustar", "new", "news", "next", "nextdirect", "nexus", "nf", "nfl", "ng", "ngo", "nhk", "ni", "nico", "nike", "nikon", "ninja", "nissan", "nissay", "nl", "no", "nokia", "norton", "now", "nowruz", "nowtv", "np", "nr", "nra", "nrw", "ntt", "nu", "nyc", "nz", "obi", "observer", "office", "okinawa", "olayan", "olayangroup", "ollo", "om", "omega", "one", "ong", "onl", "online", "ooo", "open", "oracle", "orange", "org", "organic", "origins", "osaka", "otsuka", "ott", "ovh", "pa", "page", "panasonic", "paris", "pars", "partners", "parts", "party", "pay", "pccw", "pe", "pet", "pf", "pfizer", "pg", "ph", "pharmacy", "phd", "philips", "phone", "photo", "photography", "photos", "physio", "pics", "pictet", "pictures", "pid", "pin", "ping", "pink", "pioneer", "pizza", "pk", "pl", "place", "play", "playstation", "plumbing", "plus", "pm", "pn", "pnc", "pohl", "poker", "politie", "porn", "post", "pr", "praxi", "press", "prime", "pro", "prod", "productions", "prof", "progressive", "promo", "properties", "property", "protection", "pru", "prudential", "ps", "pt", "pub", "pw", "pwc", "py", "qa", "qpon", "quebec", "quest", "racing", "radio", "re", "read", "realestate", "realtor", "realty", "recipes", "red", "redumbrella", "rehab", "reise", "reisen", "reit", "reliance", "ren", "rent", "rentals", "repair", "report", "republican", "rest", "restaurant", "review", "reviews", "rexroth", "rich", "richardli", "ricoh", "ril", "rio", "rip", "ro", "rocks", "rodeo", "rogers", "room", "rs", "rsvp", "ru", "rugby", "ruhr", "run", "rw", "rwe", "ryukyu", "sa", "saarland", "safe", "safety", "sakura", "sale", "salon", "samsclub", "samsung", "sandvik", "sandvikcoromant", "sanofi", "sap", "sarl", "sas", "save", "saxo", "sb", "sbi", "sbs", "sc", "scb", "schaeffler", "schmidt", "scholarships", "school", "schule", "schwarz", "science", "scot", "sd", "se", "search", "seat", "secure", "security", "seek", "select", "sener", "services", "seven", "sew", "sex", "sexy", "sfr", "sg", "sh", "shangrila", "sharp", "shell", "shia", "shiksha", "shoes", "shop", "shopping", "shouji", "show", "si", "silk", "sina", "singles", "site", "sj", "sk", "ski", "skin", "sky", "skype", "sl", "sling", "sm", "smart", "smile", "sn", "sncf", "so", "soccer", "social", "softbank", "software", "sohu", "solar", "solutions", "song", "sony", "soy", "spa", "space", "sport", "spot", "sr", "srl", "ss", "st", "stada", "staples", "star", "statebank", "statefarm", "stc", "stcgroup", "stockholm", "storage", "store", "stream", "studio", "study", "style", "su", "sucks", "supplies", "supply", "support", "surf", "surgery", "suzuki", "sv", "swatch", "swiss", "sx", "sy", "sydney", "systems", "sz", "tab", "taipei", "talk", "taobao", "target", "tatamotors", "tatar", "tattoo", "tax", "taxi", "tc", "tci", "td", "tdk", "team", "tech", "technology", "tel", "temasek", "tennis", "teva", "tf", "tg", "th", "thd", "theater", "theatre", "tiaa", "tickets", "tienda", "tips", "tires", "tirol", "tj", "tjmaxx", "tjx", "tk", "tkmaxx", "tl", "tm", "tmall", "tn", "to", "today", "tokyo", "tools", "top", "toray", "toshiba", "total", "tours", "town", "toyota", "toys", "tr", "trade", "trading", "training", "travel", "travelers", "travelersinsurance", "trust", "trv", "tt", "tube", "tui", "tunes", "tushu", "tv", "tvs", "tw", "tz", "ua", "ubank", "ubs", "ug", "uk", "unicom", "university", "uno", "uol", "ups", "us", "uy", "uz", "va", "vacations", "vana", "vanguard", "vc", "ve", "vegas", "ventures", "verisign", "versicherung", "vet", "vg", "vi", "viajes", "video", "vig", "viking", "villas", "vin", "vip", "virgin", "visa", "vision", "viva", "vivo", "vlaanderen", "vn", "vodka", "volvo", "vote", "voting", "voto", "voyage", "vu", "wales", "walmart", "walter", "wang", "wanggou", "watch", "watches", "weather", "weatherchannel", "webcam", "weber", "website", "wed", "wedding", "weibo", "weir", "wf", "whoswho", "wien", "wiki", "williamhill", "win", "windows", "wine", "winners", "wme", "woodside", "work", "works", "world", "wow", "ws", "wtc", "wtf", "xbox", "xerox", "xihuan", "xin", "xn--11b4c3d", "xn--1ck2e1b", "xn--1qqw23a", "xn--2scrj9c", "xn--30rr7y", "xn--3bst00m", "xn--3ds443g", "xn--3e0b707e", "xn--3hcrj9c", "xn--3pxu8k", "xn--42c2d9a", "xn--45br5cyl", "xn--45brj9c", "xn--45q11c", "xn--4dbrk0ce", "xn--4gbrim", "xn--54b7fta0cc", "xn--55qw42g", "xn--55qx5d", "xn--5su34j936bgsg", "xn--5tzm5g", "xn--6frz82g", "xn--6qq986b3xl", "xn--80adxhks", "xn--80ao21a", "xn--80aqecdr1a", "xn--80asehdb", "xn--80aswg", "xn--8y0a063a", "xn--90a3ac", "xn--90ae", "xn--90ais", "xn--9dbq2a", "xn--9et52u", "xn--9krt00a", "xn--b4w605ferd", "xn--bck1b9a5dre4c", "xn--c1avg", "xn--c2br7g", "xn--cck2b3b", "xn--cckwcxetd", "xn--cg4bki", "xn--clchc0ea0b2g2a9gcd", "xn--czr694b", "xn--czrs0t", "xn--czru2d", "xn--d1acj3b", "xn--d1alf", "xn--e1a4c", "xn--eckvdtc9d", "xn--efvy88h", "xn--fct429k", "xn--fhbei", "xn--fiq228c5hs", "xn--fiq64b", "xn--fiqs8s", "xn--fiqz9s", "xn--fjq720a", "xn--flw351e", "xn--fpcrj9c3d", "xn--fzc2c9e2c", "xn--fzys8d69uvgm", "xn--g2xx48c", "xn--gckr3f0f", "xn--gecrj9c", "xn--gk3at1e", "xn--h2breg3eve", "xn--h2brj9c", "xn--h2brj9c8c", "xn--hxt814e", "xn--i1b6b1a6a2e", "xn--imr513n", "xn--io0a7i", "xn--j1aef", "xn--j1amh", "xn--j6w193g", "xn--jlq480n2rg", "xn--jvr189m", "xn--kcrx77d1x4a", "xn--kprw13d", "xn--kpry57d", "xn--kput3i", "xn--l1acc", "xn--lgbbat1ad8j", "xn--mgb9awbf", "xn--mgba3a3ejt", "xn--mgba3a4f16a", "xn--mgba7c0bbn0a", "xn--mgbaam7a8h", "xn--mgbab2bd", "xn--mgbah1a3hjkrd", "xn--mgbai9azgqp6j", "xn--mgbayh7gpa", "xn--mgbbh1a", "xn--mgbbh1a71e", "xn--mgbc0a9azcg", "xn--mgbca7dzdo", "xn--mgbcpq6gpa1a", "xn--mgberp4a5d4ar", "xn--mgbgu82a", "xn--mgbi4ecexp", "xn--mgbpl2fh", "xn--mgbt3dhd", "xn--mgbtx2b", "xn--mgbx4cd0ab", "xn--mix891f", "xn--mk1bu44c", "xn--mxtq1m", "xn--ngbc5azd", "xn--ngbe9e0a", "xn--ngbrx", "xn--node", "xn--nqv7f", "xn--nqv7fs00ema", "xn--nyqy26a", "xn--o3cw4h", "xn--ogbpf8fl", "xn--otu796d", "xn--p1acf", "xn--p1ai", "xn--pgbs0dh", "xn--pssy2u", "xn--q7ce6a", "xn--q9jyb4c", "xn--qcka1pmc", "xn--qxa6a", "xn--qxam", "xn--rhqv96g", "xn--rovu88b", "xn--rvc1e0am3e", "xn--s9brj9c", "xn--ses554g", "xn--t60b56a", "xn--tckwe", "xn--tiq49xqyj", "xn--unup4y", "xn--vermgensberater-ctb", "xn--vermgensberatung-pwb", "xn--vhquv", "xn--vuq861b", "xn--w4r85el8fhu5dnra", "xn--w4rs40l", "xn--wgbh1c", "xn--wgbl6a", "xn--xhq521b", "xn--xkc2al3hye2a", "xn--xkc2dl3a5ee0h", "xn--y9a3aq", "xn--yfro4i67o", "xn--ygbi2ammx", "xn--zfr164b", "xxx", "xyz", "yachts", "yahoo", "yamaxun", "yandex", "ye", "yodobashi", "yoga", "yokohama", "you", "youtube", "yt", "yun", "za", "zappos", "zara", "zero", "zip", "zm", "zone", "zuerich", "zw"];
634
743
 
@@ -1227,6 +1336,225 @@ function validateAadhaar(input) {
1227
1336
  return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (Verhoeff)."] };
1228
1337
  }
1229
1338
 
1339
+ // ../national-id/dist/italy.js
1340
+ var ODD = [1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23];
1341
+ var cval = (c) => c >= "0" && c <= "9" ? c.charCodeAt(0) - 48 : c.charCodeAt(0) - 65;
1342
+ function validateCodiceFiscale(input) {
1343
+ const s = input.toUpperCase().replace(/\s/g, "");
1344
+ const base = {
1345
+ input,
1346
+ normalized: s,
1347
+ valid: false,
1348
+ country: "IT",
1349
+ idType: "Codice Fiscale",
1350
+ errors: []
1351
+ };
1352
+ if (!/^[A-Z0-9]{15}[A-Z]$/.test(s)) {
1353
+ return { ...base, errors: ["Codice Fiscale must be 15 alphanumerics followed by a letter check character."] };
1354
+ }
1355
+ let sum = 0;
1356
+ for (let i = 0; i < 15; i++) {
1357
+ const v = cval(s[i]);
1358
+ sum += i % 2 === 0 ? ODD[v] : v;
1359
+ }
1360
+ const expected = String.fromCharCode(65 + sum % 26);
1361
+ const ok = expected === s[15];
1362
+ return { ...base, valid: ok, errors: ok ? [] : [`Check character failed (mod-26): expected '${expected}'.`] };
1363
+ }
1364
+
1365
+ // ../national-id/dist/poland.js
1366
+ function validatePesel(input) {
1367
+ const clean = input.replace(/\D/g, "");
1368
+ const base = { input, normalized: clean, valid: false, country: "PL", idType: "PESEL", errors: [] };
1369
+ if (clean.length !== 11)
1370
+ return { ...base, errors: ["PESEL must be 11 digits."] };
1371
+ const d = clean.split("").map(Number);
1372
+ const w = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
1373
+ let sum = 0;
1374
+ for (let i = 0; i < 10; i++)
1375
+ sum += w[i] * d[i];
1376
+ const check = (10 - sum % 10) % 10;
1377
+ const ok = check === d[10];
1378
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (PESEL weighted mod-10)."] };
1379
+ }
1380
+
1381
+ // ../national-id/dist/netherlands.js
1382
+ function validateBsn(input) {
1383
+ let clean = input.replace(/\D/g, "");
1384
+ if (clean.length === 8)
1385
+ clean = "0" + clean;
1386
+ const base = { input, normalized: clean, valid: false, country: "NL", idType: "BSN", errors: [] };
1387
+ if (!/^\d{9}$/.test(clean))
1388
+ return { ...base, errors: ["BSN must be 8 or 9 digits."] };
1389
+ const d = clean.split("").map(Number);
1390
+ if (d.every((x) => x === 0))
1391
+ return { ...base, errors: ["Invalid BSN (all zeros)."] };
1392
+ let sum = 0;
1393
+ for (let i = 0; i < 8; i++)
1394
+ sum += (9 - i) * d[i];
1395
+ sum -= d[8];
1396
+ const ok = sum % 11 === 0;
1397
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (BSN 11-test)."] };
1398
+ }
1399
+
1400
+ // ../national-id/dist/belgium.js
1401
+ function validateBeNrn(input) {
1402
+ const clean = input.replace(/\D/g, "");
1403
+ const base = {
1404
+ input,
1405
+ normalized: clean,
1406
+ valid: false,
1407
+ country: "BE",
1408
+ idType: "National Register Number",
1409
+ errors: []
1410
+ };
1411
+ if (clean.length !== 11)
1412
+ return { ...base, errors: ["Belgian NRN must be 11 digits."] };
1413
+ const d = clean.split("").map(Number);
1414
+ const last2 = d[9] * 10 + d[10];
1415
+ const baseNum = Number(clean.slice(0, 9));
1416
+ const c19 = 97 - baseNum % 97;
1417
+ const c20 = 97 - (2e9 + baseNum) % 97;
1418
+ const ok = last2 === c19 || last2 === c20;
1419
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (NRN mod-97)."] };
1420
+ }
1421
+
1422
+ // ../national-id/dist/portugal.js
1423
+ function validateNifPt(input) {
1424
+ const clean = input.replace(/\D/g, "");
1425
+ const base = { input, normalized: clean, valid: false, country: "PT", idType: "NIF", errors: [] };
1426
+ if (clean.length !== 9)
1427
+ return { ...base, errors: ["Portuguese NIF must be 9 digits."] };
1428
+ const d = clean.split("").map(Number);
1429
+ let sum = 0;
1430
+ for (let i = 0; i < 8; i++)
1431
+ sum += d[i] * (9 - i);
1432
+ const r = sum % 11;
1433
+ const check = r < 2 ? 0 : 11 - r;
1434
+ const ok = check === d[8];
1435
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (NIF mod-11)."] };
1436
+ }
1437
+
1438
+ // ../national-id/dist/turkey.js
1439
+ function validateTckn(input) {
1440
+ const clean = input.replace(/\D/g, "");
1441
+ const base = { input, normalized: clean, valid: false, country: "TR", idType: "TCKN", errors: [] };
1442
+ if (clean.length !== 11)
1443
+ return { ...base, errors: ["TCKN must be 11 digits."] };
1444
+ const d = clean.split("").map(Number);
1445
+ if (d[0] === 0)
1446
+ return { ...base, errors: ["TCKN cannot start with 0."] };
1447
+ const odd = d[0] + d[2] + d[4] + d[6] + d[8];
1448
+ const even = d[1] + d[3] + d[5] + d[7];
1449
+ const d10 = ((odd * 7 - even) % 10 + 10) % 10;
1450
+ let sum = 0;
1451
+ for (let i = 0; i < 10; i++)
1452
+ sum += d[i];
1453
+ const d11 = sum % 10;
1454
+ const ok = d10 === d[9] && d11 === d[10];
1455
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (TCKN check digits)."] };
1456
+ }
1457
+
1458
+ // ../national-id/dist/china.js
1459
+ function validateChinaRic(input) {
1460
+ const s = input.toUpperCase().replace(/\s/g, "");
1461
+ const base = {
1462
+ input,
1463
+ normalized: s,
1464
+ valid: false,
1465
+ country: "CN",
1466
+ idType: "Resident Identity Card",
1467
+ errors: []
1468
+ };
1469
+ if (!/^\d{17}[0-9X]$/.test(s)) {
1470
+ return { ...base, errors: ["Chinese ID must be 17 digits followed by a check character (0-9 or X)."] };
1471
+ }
1472
+ const w = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
1473
+ const map = "10X98765432";
1474
+ let sum = 0;
1475
+ for (let i = 0; i < 17; i++)
1476
+ sum += w[i] * (s.charCodeAt(i) - 48);
1477
+ const expected = map[sum % 11];
1478
+ const ok = expected === s[17];
1479
+ return { ...base, valid: ok, errors: ok ? [] : [`Check character failed (ISO 7064 MOD 11-2): expected '${expected}'.`] };
1480
+ }
1481
+
1482
+ // ../national-id/dist/nordics.js
1483
+ function validatePersonnummer(input) {
1484
+ const digits2 = input.replace(/[+\-\s]/g, "");
1485
+ const base = {
1486
+ input,
1487
+ normalized: digits2,
1488
+ valid: false,
1489
+ country: "SE",
1490
+ idType: "Personnummer",
1491
+ errors: []
1492
+ };
1493
+ if (!/^\d{10}$|^\d{12}$/.test(digits2))
1494
+ return { ...base, errors: ["Personnummer must be 10 or 12 digits."] };
1495
+ const ten = digits2.length === 12 ? digits2.slice(2) : digits2;
1496
+ const d = ten.split("").map(Number);
1497
+ let sum = 0;
1498
+ let dbl = true;
1499
+ for (let i = 0; i < 10; i++) {
1500
+ let x = d[i];
1501
+ if (dbl) {
1502
+ x *= 2;
1503
+ if (x > 9)
1504
+ x -= 9;
1505
+ }
1506
+ sum += x;
1507
+ dbl = !dbl;
1508
+ }
1509
+ const ok = sum % 10 === 0;
1510
+ return { ...base, valid: ok, errors: ok ? [] : ["Checksum failed (Luhn)."] };
1511
+ }
1512
+ function validateFodselsnummer(input) {
1513
+ const clean = input.replace(/\D/g, "");
1514
+ const base = {
1515
+ input,
1516
+ normalized: clean,
1517
+ valid: false,
1518
+ country: "NO",
1519
+ idType: "F\xF8dselsnummer",
1520
+ errors: []
1521
+ };
1522
+ if (clean.length !== 11)
1523
+ return { ...base, errors: ["F\xF8dselsnummer must be 11 digits."] };
1524
+ const d = clean.split("").map(Number);
1525
+ const w1 = [3, 7, 6, 1, 8, 9, 4, 5, 2];
1526
+ let s1 = 0;
1527
+ for (let i = 0; i < 9; i++)
1528
+ s1 += w1[i] * d[i];
1529
+ let k1 = 11 - s1 % 11;
1530
+ if (k1 === 11)
1531
+ k1 = 0;
1532
+ if (k1 === 10 || k1 !== d[9])
1533
+ return { ...base, errors: ["First control digit failed (mod-11)."] };
1534
+ const w2 = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
1535
+ let s2 = 0;
1536
+ for (let i = 0; i < 9; i++)
1537
+ s2 += w2[i] * d[i];
1538
+ s2 += w2[9] * k1;
1539
+ let k2 = 11 - s2 % 11;
1540
+ if (k2 === 11)
1541
+ k2 = 0;
1542
+ const ok = k2 !== 10 && k2 === d[10];
1543
+ return { ...base, valid: ok, errors: ok ? [] : ["Second control digit failed (mod-11)."] };
1544
+ }
1545
+ var HETU = "0123456789ABCDEFHJKLMNPRSTUVWXY";
1546
+ function validateHetu(input) {
1547
+ const s = input.toUpperCase().trim();
1548
+ const base = { input, normalized: s, valid: false, country: "FI", idType: "Henkil\xF6tunnus", errors: [] };
1549
+ const m = s.match(/^(\d{6})([+\-A-FYXWVU])(\d{3})([0-9A-Y])$/);
1550
+ if (!m)
1551
+ return { ...base, errors: ["HETU must be DDMMYY + century sign + 3 digits + check character."] };
1552
+ const num = Number(m[1] + m[3]);
1553
+ const expected = HETU[num % 31];
1554
+ const ok = expected === m[4];
1555
+ return { ...base, valid: ok, errors: ok ? [] : [`Check character failed (mod-31): expected '${expected}'.`] };
1556
+ }
1557
+
1230
1558
  // ../academic/dist/isbn10.js
1231
1559
  function validateIsbn10(input) {
1232
1560
  const s = input.replace(/[\s-]/g, "").toUpperCase();
@@ -1758,6 +2086,27 @@ var TOOLS = [
1758
2086
  argDescription: "The barcode digits (EAN-8/UPC-A/EAN-13/GTIN-14); spaces and hyphens are ignored.",
1759
2087
  run: (v) => validateGtin(v)
1760
2088
  },
2089
+ {
2090
+ name: "validate_imei",
2091
+ description: "USE THIS to verify a phone/device IMEI before relying on it \u2014 never assume a 15-digit string is valid or guess its check digit. Checks the Luhn check digit (and recognises the 16-digit IMEISV form), and returns the TAC (device-model code). Validates the number only \u2014 does NOT check whether the device is real, active, or blocklisted/stolen.",
2092
+ argName: "imei",
2093
+ argDescription: "The 15-digit IMEI (or 16-digit IMEISV); spaces and dashes are ignored.",
2094
+ run: (v) => validateImei(v)
2095
+ },
2096
+ {
2097
+ name: "validate_gln",
2098
+ description: "USE THIS to verify a GLN (GS1 Global Location Number \u2014 identifies a company/site/location in supply chains and EDI) before relying on it. Checks the 13-digit GS1 mod-10 check digit and returns the GS1 prefix's issuing country. Validates structure only; does not confirm the location is registered.",
2099
+ argName: "gln",
2100
+ argDescription: "The 13-digit GLN; spaces and dashes are ignored.",
2101
+ run: (v) => validateGln(v)
2102
+ },
2103
+ {
2104
+ name: "validate_sscc",
2105
+ description: "USE THIS to verify an SSCC (GS1 Serial Shipping Container Code \u2014 identifies a pallet/carton/logistics unit) from a shipping label before relying on it. Checks the 18-digit GS1 mod-10 check digit and returns the extension digit and GS1 prefix country. Validates structure only.",
2106
+ argName: "sscc",
2107
+ argDescription: "The 18-digit SSCC; spaces and dashes are ignored.",
2108
+ run: (v) => validateSscc(v)
2109
+ },
1761
2110
  {
1762
2111
  name: "validate_tld",
1763
2112
  description: "USE THIS to check whether a top-level domain is real before trusting a domain or link \u2014 do NOT guess whether a TLD like .zip, .corp, .crypto or .web exists. Checks the suffix against the authoritative IANA root-zone list (kept current). Returns valid:false for TLDs that are not actually delegated.",
@@ -1884,6 +2233,76 @@ var TOOLS = [
1884
2233
  argDescription: "The 12-digit Aadhaar number (spaces ignored).",
1885
2234
  run: (v) => validateAadhaar(v)
1886
2235
  },
2236
+ {
2237
+ name: "validate_codice_fiscale",
2238
+ description: "USE THIS to verify an Italian Codice Fiscale (personal tax code) before relying on it \u2014 do not guess the final check letter. Checks the 16-character format and the mod-26 check character. Validates structure only; does NOT confirm the code is registered with the Agenzia delle Entrate.",
2239
+ argName: "code",
2240
+ argDescription: "The 16-character Codice Fiscale (spaces ignored, case-insensitive).",
2241
+ run: (v) => validateCodiceFiscale(v)
2242
+ },
2243
+ {
2244
+ name: "validate_pesel",
2245
+ description: "USE THIS to verify a Polish PESEL (national identification number) before relying on it \u2014 never assume 11 digits are valid. Checks the weighted mod-10 check digit. Call this for KYC/onboarding of Polish individuals.",
2246
+ argName: "pesel",
2247
+ argDescription: "The 11-digit PESEL (spaces/dashes ignored).",
2248
+ run: (v) => validatePesel(v)
2249
+ },
2250
+ {
2251
+ name: "validate_bsn",
2252
+ description: "USE THIS to verify a Dutch BSN (burgerservicenummer / citizen service number) before relying on it. Checks the 8\u20139 digit form and the '11-test' (elfproef) checksum. Validates structure only; does NOT confirm the number is issued.",
2253
+ argName: "bsn",
2254
+ argDescription: "The 8- or 9-digit BSN (spaces/dots ignored).",
2255
+ run: (v) => validateBsn(v)
2256
+ },
2257
+ {
2258
+ name: "validate_be_nrn",
2259
+ description: "USE THIS to verify a Belgian National Register Number (Rijksregisternummer / Num\xE9ro de Registre National) before relying on it. Checks the 11-digit form and the mod-97 check (handling the born-from-2000 rule). Validates structure only.",
2260
+ argName: "nrn",
2261
+ argDescription: "The 11-digit Belgian National Register Number (punctuation ignored).",
2262
+ run: (v) => validateBeNrn(v)
2263
+ },
2264
+ {
2265
+ name: "validate_personnummer",
2266
+ description: "USE THIS to verify a Swedish personnummer (personal identity number) before relying on it \u2014 never assume the digits are valid. Accepts the 10- or 12-digit form and checks the Luhn check digit. Validates structure only; does NOT confirm the number is registered.",
2267
+ argName: "personnummer",
2268
+ argDescription: "The Swedish personnummer (10 or 12 digits; +/-/spaces ignored).",
2269
+ run: (v) => validatePersonnummer(v)
2270
+ },
2271
+ {
2272
+ name: "validate_fodselsnummer",
2273
+ description: "USE THIS to verify a Norwegian f\xF8dselsnummer (national identity number) before relying on it. Checks the 11-digit form and both mod-11 control digits. Validates structure only; does NOT confirm the number is registered.",
2274
+ argName: "fodselsnummer",
2275
+ argDescription: "The 11-digit Norwegian f\xF8dselsnummer (spaces ignored).",
2276
+ run: (v) => validateFodselsnummer(v)
2277
+ },
2278
+ {
2279
+ name: "validate_hetu",
2280
+ description: "USE THIS to verify a Finnish henkil\xF6tunnus (HETU / personal identity code) before relying on it \u2014 do not guess the check character. Checks the DDMMYY + century sign + individual number + mod-31 check character. Validates structure only.",
2281
+ argName: "hetu",
2282
+ argDescription: "The Finnish HETU, e.g. 131052-308T (case-insensitive).",
2283
+ run: (v) => validateHetu(v)
2284
+ },
2285
+ {
2286
+ name: "validate_nif_pt",
2287
+ description: "USE THIS to verify a Portuguese NIF (N\xFAmero de Identifica\xE7\xE3o Fiscal / tax number) before invoicing or onboarding \u2014 never assume 9 digits are valid. Checks the mod-11 check digit. For the Spanish tax ID use validate_dni.",
2288
+ argName: "nif",
2289
+ argDescription: "The 9-digit Portuguese NIF (spaces ignored).",
2290
+ run: (v) => validateNifPt(v)
2291
+ },
2292
+ {
2293
+ name: "validate_tckn",
2294
+ description: "USE THIS to verify a Turkish T.C. Kimlik No (TCKN / national identity number) before relying on it \u2014 never assume 11 digits are valid. Checks both algorithmic check digits and the leading-digit rule. Validates structure only; does NOT confirm the number is registered.",
2295
+ argName: "tckn",
2296
+ argDescription: "The 11-digit TCKN (spaces ignored).",
2297
+ run: (v) => validateTckn(v)
2298
+ },
2299
+ {
2300
+ name: "validate_china_ric",
2301
+ description: "USE THIS to verify a Chinese Resident Identity Card number (\u5C45\u6C11\u8EAB\u4EFD\u8BC1) before relying on it \u2014 do not guess the check character. Checks the 18-character form and the ISO 7064 MOD 11-2 check character (which may be 'X'). Validates structure only; does NOT confirm the number is registered.",
2302
+ argName: "id",
2303
+ argDescription: "The 18-character Chinese Resident ID (17 digits + check 0-9 or X).",
2304
+ run: (v) => validateChinaRic(v)
2305
+ },
1887
2306
  {
1888
2307
  name: "validate_isbn10",
1889
2308
  description: "USE THIS to verify an ISBN-10 (older book identifier) instead of trusting 10 characters. Checks the mod-11 check digit (which may be 'X'). For 13-digit ISBNs use validate_isbn.",
@@ -1979,7 +2398,7 @@ var TOOLS = [
1979
2398
  runArgs: (a) => validateVat(a.vat ?? "", a.country)
1980
2399
  }
1981
2400
  ];
1982
- var SERVER_INFO = { name: "qiniso", version: "0.2.0" };
2401
+ var SERVER_INFO = { name: "qiniso", version: "0.4.0" };
1983
2402
  var DEFAULT_PROTOCOL = "2025-06-18";
1984
2403
  function argList(t) {
1985
2404
  return t.args ?? [{ name: t.argName, description: t.argDescription }];
@@ -2070,6 +2489,9 @@ export {
2070
2489
  gtinCheckDigit,
2071
2490
  gs1Country,
2072
2491
  validateGtin,
2492
+ validateImei,
2493
+ validateGln,
2494
+ validateSscc,
2073
2495
  isKnownTld,
2074
2496
  knownTldCount,
2075
2497
  validateTld,
@@ -2094,6 +2516,16 @@ export {
2094
2516
  verhoeffValid,
2095
2517
  verhoeffGenerate,
2096
2518
  validateAadhaar,
2519
+ validateCodiceFiscale,
2520
+ validatePesel,
2521
+ validateBsn,
2522
+ validateBeNrn,
2523
+ validateNifPt,
2524
+ validateTckn,
2525
+ validateChinaRic,
2526
+ validatePersonnummer,
2527
+ validateFodselsnummer,
2528
+ validateHetu,
2097
2529
  validateIsbn10,
2098
2530
  validateIssn,
2099
2531
  validateOrcid,
package/dist/http.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  LOGO_SVG,
4
4
  handleRpc
5
- } from "./chunk-I6MBL33Q.js";
5
+ } from "./chunk-RMLPG7ZB.js";
6
6
 
7
7
  // src/http.ts
8
8
  import { createServer } from "http";
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ interface ToolSpec {
25
25
  declare const TOOLS: ToolSpec[];
26
26
  declare const SERVER_INFO: {
27
27
  readonly name: "qiniso";
28
- readonly version: "0.2.0";
28
+ readonly version: "0.4.0";
29
29
  };
30
30
  declare function listTools(): {
31
31
  name: string;
package/dist/index.js CHANGED
@@ -24,27 +24,40 @@ import {
24
24
  supportedIbanCountries,
25
25
  validateAadhaar,
26
26
  validateAba,
27
+ validateBeNrn,
28
+ validateBsn,
27
29
  validateBtcAddress,
28
30
  validateCard,
31
+ validateChinaRic,
29
32
  validateCnpj,
33
+ validateCodiceFiscale,
30
34
  validateCpf,
31
35
  validateCusip,
32
36
  validateDni,
33
37
  validateDomain,
34
38
  validateEmail,
35
39
  validateEthAddress,
40
+ validateFodselsnummer,
41
+ validateGln,
36
42
  validateGtin,
43
+ validateHetu,
37
44
  validateIban,
45
+ validateImei,
38
46
  validateIp,
39
47
  validateIsbn10,
40
48
  validateIsbn13,
41
49
  validateIsin,
42
50
  validateIssn,
43
51
  validateLei,
52
+ validateNifPt,
44
53
  validateOrcid,
54
+ validatePersonnummer,
55
+ validatePesel,
45
56
  validatePhone,
46
57
  validateSaId,
47
58
  validateSedol,
59
+ validateSscc,
60
+ validateTckn,
48
61
  validateTld,
49
62
  validateUrl,
50
63
  validateUuid,
@@ -54,7 +67,7 @@ import {
54
67
  verhoeffGenerate,
55
68
  verhoeffValid,
56
69
  vinCheckDigit
57
- } from "./chunk-I6MBL33Q.js";
70
+ } from "./chunk-RMLPG7ZB.js";
58
71
  export {
59
72
  SERVER_INFO,
60
73
  TOOLS,
@@ -81,27 +94,40 @@ export {
81
94
  supportedIbanCountries,
82
95
  validateAadhaar,
83
96
  validateAba,
97
+ validateBeNrn,
98
+ validateBsn,
84
99
  validateBtcAddress,
85
100
  validateCard,
101
+ validateChinaRic,
86
102
  validateCnpj,
103
+ validateCodiceFiscale,
87
104
  validateCpf,
88
105
  validateCusip,
89
106
  validateDni,
90
107
  validateDomain,
91
108
  validateEmail,
92
109
  validateEthAddress,
110
+ validateFodselsnummer,
111
+ validateGln,
93
112
  validateGtin,
113
+ validateHetu,
94
114
  validateIban,
115
+ validateImei,
95
116
  validateIp,
96
117
  validateIsbn10,
97
118
  validateIsbn13,
98
119
  validateIsin,
99
120
  validateIssn,
100
121
  validateLei,
122
+ validateNifPt,
101
123
  validateOrcid,
124
+ validatePersonnummer,
125
+ validatePesel,
102
126
  validatePhone,
103
127
  validateSaId,
104
128
  validateSedol,
129
+ validateSscc,
130
+ validateTckn,
105
131
  validateTld,
106
132
  validateUrl,
107
133
  validateUuid,
package/dist/server.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  SERVER_INFO,
4
4
  TOOLS
5
- } from "./chunk-I6MBL33Q.js";
5
+ } from "./chunk-RMLPG7ZB.js";
6
6
 
7
7
  // src/server.ts
8
8
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qinisolabs/qiniso",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "mcpName": "io.github.qinisolabs/qiniso",
5
5
  "description": "The deterministic fact-verification layer for AI agents — verify identifiers, locale and more against authoritative ground truth.",
6
6
  "homepage": "https://qinisolabs.github.io/qiniso/",
@@ -48,7 +48,12 @@
48
48
  "upc",
49
49
  "ean",
50
50
  "iban",
51
- "vat"
51
+ "vat",
52
+ "national-id",
53
+ "kyc",
54
+ "pesel",
55
+ "codice-fiscale",
56
+ "tckn"
52
57
  ],
53
58
  "license": "Apache-2.0",
54
59
  "author": "Qiniso",