{
  "markdown": "<p align=\"center\">\n  <img src=\"loqate.png\" alt=\"Loqate CLI\" width=\"120\">\n</p>\n\n<h1 align=\"center\">Loqate CLI</h1>\n\n<p align=\"center\">\n  Verify addresses, emails, and phone numbers against Loqate's APIs.<br>\n  Get confidence scores, policy-aware recommendations, and full auditability — in one command.<br>\n  Real-time verification decisioning for agents that need to know whether contact data is good enough for the job.<br>\n  Part of <a href=\"https://agents.gbg.com/reach\">GBG Reach</a>.\n</p>\n\n<p align=\"center\">\n  <code>lqt verify</code> &nbsp;·&nbsp; <code>lqt parse</code> &nbsp;·&nbsp; <code>lqt mcp</code>\n</p>\n\n---\n\n## Install\n\n### macOS\n\n```bash\n# Apple Silicon (M1/M2/M3/M4)\ncurl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_darwin_arm64.tar.gz | tar xz\nsudo mv lqt /usr/local/bin/\n\n# Intel\ncurl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_darwin_amd64.tar.gz | tar xz\nsudo mv lqt /usr/local/bin/\n```\n\n### Linux\n\n```bash\n# x86_64\ncurl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_linux_amd64.tar.gz | tar xz\nsudo mv lqt /usr/local/bin/\n\n# ARM64\ncurl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_linux_arm64.tar.gz | tar xz\nsudo mv lqt /usr/local/bin/\n```\n\n### Windows\n\n1. Download `lqt_windows_amd64.zip` from the [latest release](https://github.com/gbgplc/lqt/releases/latest)\n2. Extract `lqt.exe`\n3. Move it to a directory on your `PATH`, or run it directly\n\n### Verify Installation\n\n```bash\nlqt version\n```\n\n### All Downloads\n\nSee [Releases](https://github.com/gbgplc/lqt/releases) for all versions and platforms. Each release includes SHA-256 checksums.\n\n| Platform | Archive |\n|----------|---------|\n| macOS (Apple Silicon) | `lqt_*_darwin_arm64.tar.gz` |\n| macOS (Intel) | `lqt_*_darwin_amd64.tar.gz` |\n| Linux (x86_64) | `lqt_*_linux_amd64.tar.gz` |\n| Linux (ARM64) | `lqt_*_linux_arm64.tar.gz` |\n| Windows (x86_64) | `lqt_*_windows_amd64.zip` |\n\n---\n\n## Quick Start\n\n### API Keys\n\nYou need a **Loqate API key** for verification. Optionally, an **Anthropic API key** for the `parse` command.\n\n**macOS / Linux:**\n```bash\nexport LOQATE_API_KEY=your-key-here\n\n# Optional — for lqt parse\nexport ANTHROPIC_API_KEY=your-key-here\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:LOQATE_API_KEY=\"your-key-here\"\n\n# Optional — for lqt parse\n$env:ANTHROPIC_API_KEY=\"your-key-here\"\n```\n\n### Your First Verification\n\n**macOS / Linux:**\n```bash\n# Verify an address\nlqt verify --address \"125 Summer Street, Boston, MA 02110, US\"\n\n# Verify address + email + phone with a policy\nlqt verify -a \"10 Downing St, London, GB\" \\\n           -e \"pm@gov.uk\" \\\n           -p \"+442071234567\" \\\n           --policy shipping\n\n# Parse and standardize without calling Loqate (uses Claude)\nlqt parse --address \"125 summer street boston ma 02110 us\"\n```\n\n**Windows (PowerShell):**\n```powershell\n# Verify an address\n.\\lqt.exe verify --address \"125 Summer Street, Boston, MA 02110, US\"\n\n# Verify address + email + phone with a policy\n.\\lqt.exe verify -a \"10 Downing St, London, GB\" -e \"pm@gov.uk\" -p \"+442071234567\" --policy shipping\n\n# Parse and standardize without calling Loqate (uses Claude)\n.\\lqt.exe parse --address \"125 summer street boston ma 02110 us\"\n```\n\n---\n\n## Commands\n\n### verify\n\nVerify addresses, emails, and/or phone numbers against Loqate's APIs. Returns a confidence score and a policy-driven recommendation (accept, review, or reject).\n\n```bash\nlqt verify [flags]\n```\n\n**Flags:**\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--address` | `-a` | Full address to verify |\n| `--locality` | | City/town |\n| `--admin-area` | | State/province |\n| `--postcode` | | Postal/ZIP code |\n| `--country` | `-c` | ISO 2-letter country code |\n| `--detect-country` | | When no country is supplied, guess it from the address and flag the guess in the result. Address-only; off by default. |\n| `--suggest` | | When the address does not clear the policy (`review` or `reject`), look up alternative addresses suggested by Loqate and return them under `address.suggestions`. Not called for an accepted address. **Requires a separately licensed Loqate feature enabled on your account.** Address-only; off by default; not available with `--batch`. |\n| `--suggest-limit` | | Maximum suggestions to return, 1–10 (default 5). Requires `--suggest`. |\n| `--suggest-below` | | Confidence floor for suggestions: an accepted address scoring below it still gets suggestions. Defaults to the active policy's value (standard 0.85). `0` disables the floor. Requires `--suggest`. |\n| `--suggestion-id` | | Verify a suggestion the user chose, by its `id` from `address.suggestions`. Resolves the id to its cleansed components and verifies those. Use instead of `--address`. **Consumes a Loqate credit.** Not available with `--batch` or `--dry-run`. |\n| `--email` | `-e` | Email address to verify |\n| `--phone` | `-p` | Phone number (E.164 format) |\n| `--key` | `-k` | Loqate API key (overrides env) |\n| `--policy` | | Policy name: `strict`, `shipping`, `standard`, `permissive` |\n| `--policy-file` | | Path to custom policy JSON file |\n| `--batch` | `-b` | CSV/TSV/pipe-delimited file path (or `-` for stdin) |\n| `--delimiter` | `-d` | Batch delimiter: `comma`, `tab`, `pipe` (auto-detected if omitted) |\n| `--output` | `-o` | Output format: `json`, `jsonl`, `table` |\n| `--summary` | `-s` | Show batch summary statistics |\n| `--field` | | Extra Loqate input field `Key=Value` (repeatable) |\n| `--option` | | Loqate API option `Key=Value` (repeatable, dot notation for nesting) |\n| `--jsonl` | | JSON Lines output (one object per line) |\n| `--no-color` | | Disable color output |\n| `--verify-url` | | Custom address verification endpoint URL (overrides `LOQATE_VERIFY_URL` env var) |\n| `--verify-key` | | Custom address verification API key (overrides `LOQATE_VERIFY_KEY` env var). When set, `--key` is not required for address-only verification. |\n| `--verbose` | `-v` | Show reasoning log |\n\n**Examples:**\n\n```bash\n# Simple address verification\nlqt verify -a \"1600 Amphitheatre Parkway, Mountain View, CA 94043, US\"\n\n# Multi-field verification with strict policy\nlqt verify -a \"221B Baker St, London, GB\" \\\n           -e \"sherlock@example.com\" \\\n           -p \"+442071234567\" \\\n           --policy strict\n\n# Email-only or phone-only (no address required)\nlqt verify -e \"sherlock@example.com\"\nlqt verify -p \"+442071234567\"\n\n# Guess a missing country from the address (opt-in, address-only)\nlqt verify -a \"10 Downing St, London SW1A 2AA\" --detect-country\n# → result includes: country_guessed, detected_country, country_confidence\n\n# Suggest alternatives when the address does not clear the policy (opt-in, address-only)\nlqt verify -a \"10 downin st london\" -c GB --suggest\nlqt verify -a \"10 downin st london\" -c GB --suggest --suggest-limit 3\n# → result includes: address.suggestions with a list of candidate addresses\n\n# Accepted but not confident: a street-level match accepted at 0.55 still gets alternatives\nlqt verify -a \"marsh wall, E14 9TN\" -c GB --suggest\n# Move or disable the confidence floor\nlqt verify -a \"marsh wall, E14 9TN\" -c GB --suggest --suggest-below 0.95\nlqt verify -a \"marsh wall, E14 9TN\" -c GB --suggest --suggest-below 0\n\n# JSON output for piping to other tools\nlqt verify -a \"10 Downing St, London, GB\" -o json | jq '.address.confidence'\n\n# Extended input fields\nlqt verify -a \"125 Summer St\" --field Organization=\"Acme Corp\" --field Building=\"Suite 200\"\n\n# API options (dot notation for nesting)\n# GeoCode is sent at the request root as a JSON boolean (where Loqate expects it);\n# ServerOptions values are sent as strings (use Loqate's exact casing).\nlqt verify -a \"125 Summer St, Boston, MA 02110, US\" --option GeoCode=true\nlqt verify -a \"125 Summer St, Boston, MA 02110, US\" --option ServerOptions.OutputCasing=Upper\n```\n\nFull list of input fields and API options: [Loqate International Batch Cleanse API](https://docs.loqate.com/api-reference/address-verify/international-batch-cleanse)\n\n#### Address suggestions (`--suggest`)\n\n> **Licensing.** Suggestions use a Loqate feature that is **licensed separately from address\n> verification** and must be enabled on your account. If it isn't, nothing breaks: the\n> verification still returns its normal result and exit code, and the reason appears in\n> `suggestions.error` (typically an unknown-key or licence message from Loqate). Talk to your\n> Loqate account contact to have it enabled.\n\nVerification tells you an address is wrong. Suggestions tell you what the right one probably\nis. Add `--suggest` and `lqt` asks Loqate for real addresses matching what was typed, returning\nthem with the decision.\n\nThe lookup runs when either:\n\n1. the address was **not accepted** (`review` or `reject`), or\n2. the address was accepted but scored **below the policy's suggestion floor** (0.85 on\n   `standard` — see the [Policies](#policies) table).\n\nThe second case is the one that catches near-misses. A policy accepts anything at or above its\nminimum confidence, so *accepted* is not the same as *confident*: on `standard` the input\n`marsh wall, E14 9TN` matches a street and scores exactly 0.55, which is accepted — yet the\nhouse number is missing and better addresses exist. Use `--suggest-below` to move that line\n(`--suggest-below 0` turns the confidence check off and only suggests on review/reject).\n\n```json\n{\n  \"address\": {\n    \"verified_address\": \"Downing Street, London\",\n    \"confidence\": 0.5,\n    \"recommendation\": \"review\",\n    \"suggestions\": {\n      \"requested\": true,\n      \"triggered\": true,\n      \"reason\": \"accepted but confidence 0.55 is below the 0.85 floor\",\n      \"floor\": 0.85,\n      \"source\": \"loqate\",\n      \"count\": 2,\n      \"items\": [\n        {\n          \"id\": \"GB|RM|A|52509479\",\n          \"type\": \"Address\",\n          \"text\": \"10 Downing Street\",\n          \"description\": \"London, SW1A 2AA\",\n          \"address\": \"10 Downing Street, London, SW1A 2AA\"\n        },\n        {\n          \"id\": \"GB|RM|A|52509480\",\n          \"type\": \"Address\",\n          \"text\": \"11 Downing Street\",\n          \"description\": \"London, SW1A 2AB\",\n          \"address\": \"11 Downing Street, London, SW1A 2AB\"\n        }\n      ]\n    }\n  }\n}\n```\n\nThings worth knowing:\n\n- **Off by default**, so existing output is unchanged unless you ask for suggestions.\n- **No lookup for a confidently accepted address** — you pay the extra latency only where it\n  helps. The `suggestions` block is still returned with `\"triggered\": false` and a `reason`, so\n  you can tell \"no alternatives needed\" from \"suggestions were never requested\".\n- **`floor` reports the threshold that was applied**, so you can see why a lookup ran (or\n  didn't) without knowing the policy's configuration.\n- **Suggestions never change the decision.** If the lookup fails, the reason appears in\n  `suggestions.error` and the verification result stands.\n- **Address-only.** With `verify --email` / `--phone`, or `verify_contact`, only the address\n  block is decorated.\n- An entry with `\"expandable\": true` is a street, postcode, or building holding several\n  addresses rather than one deliverable address. Search within it for a specific premise.\n- Suggestion lookups do not consume Loqate verification credits, but the feature must be licensed on your account (see the note above).\n- Suggestions need a standard Loqate key (`--key` / `LOQATE_API_KEY`); `--verify-key` alone\n  covers address verification only.\n- **Not available with `--batch`.** A large file would fan out into an unbounded number of\n  lookups, so the combination is rejected. Verify the file, then re-run the flagged rows\n  individually with `--suggest`.\n\nAvailable on the MCP `verify_address` / `verify_contact` tools and the REST\n`/v1/verify/address` / `/v1/verify/contact` endpoints as `suggest: true`, with optional\n`suggest_limit` (1–10, default 5) and `suggest_below` (0–1).\n\n#### Closing the loop: offer, choose, re-verify\n\n**A suggestion is a candidate, not a verdict.** Items carry no confidence score, no match\nlevel, and no AVC — they are what the reference data thinks the address might have been. Don't\nwrite one into your system of record on faith. Close the loop in three steps:\n\n1. **Verify with `--suggest`.** A non-empty `suggestions.items` means alternatives exist.\n2. **Offer `items[].address` to whoever can decide** — the customer in a checkout or support\n   flow, the agent in an automated one. That field is the ready-to-display line.\n3. **Confirm the choice by its `id`** (`--suggestion-id`). *That* result — its confidence,\n   match level, and standardized fields — is the one you keep. Full flow below.\n\n```bash\n# 1. verify, asking for alternatives\nlqt verify -a \"marsh wall, E14 9TN\" -c GB --suggest -o json > result.json\n\n# 2. show the candidates\njq -r '.address.suggestions.items[] | .address' result.json\n#   1 Marsh Wall, London, E14 9TN\n#   2 Marsh Wall, London, E14 9TN\n\n# 3. re-verify the chosen one — this is the decision of record\nlqt verify -a \"1 Marsh Wall, London, E14 9TN\" -c GB -o json\n```\n\nOver REST it's the same shape — one call with `suggest`, then a plain call with the choice:\n\n```bash\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" -H 'Content-Type: application/json' \\\n  -d '{\"address\":\"marsh wall, E14 9TN\",\"country\":\"GB\",\"suggest\":true}'\n\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" -H 'Content-Type: application/json' \\\n  -d '{\"address\":\"1 Marsh Wall, London, E14 9TN\",\"country\":\"GB\"}'\n```\n\n#### The full flow, end to end\n\n1. **Verify with `--suggest`** — get candidates for an address that didn't come back clean.\n2. **Offer `items[].address`** to whoever decides.\n3. **Confirm with `--suggestion-id`**, using the chosen item's `id`. That result is the one you keep.\n\n```bash\n# 1 + 2\nlqt verify -a \"marsh wall london\" -c GB --suggest -o json > r.json\njq -r '.address.suggestions.items[] | \"\\(.id)\\t\\(.address)\"' r.json\n\n# 3 — confirm the chosen one by id, not by re-typing the text\nlqt verify --suggestion-id \"GB|RM|B|55782678\" -o json\n```\n\nPassing the **id** rather than the text is what makes step 3 accurate: `lqt` fetches that\naddress's cleansed components (company, sub-building, number, street, city, postcode, country)\nand verifies those, so nothing is re-parsed. It matters for suggestions carrying a company name\n— `London Lash, 56 Marsh Wall, London` — where re-reading the text can misplace the company as\npart of the street.\n\nThe result records what it resolved from, so you can audit it without resolving again:\n\n```json\n{\n  \"verified_address\": \"56 Marsh Wall, London, E14 9TP\",\n  \"confidence\": 0.95,\n  \"recommendation\": \"accept\",\n  \"resolved_from\": {\n    \"suggestion_id\": \"GB|RM|B|55782678\",\n    \"address\": \"London Lash, Unit 7, Hampton Tower, 56 Marsh Wall, LONDON, E14 9TP\"\n  }\n}\n```\n\nOver REST, the same two steps:\n\n```bash\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" -H 'Content-Type: application/json' \\\n  -d '{\"address\":\"marsh wall london\",\"country\":\"GB\",\"suggest\":true}'\n\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" -H 'Content-Type: application/json' \\\n  -d '{\"suggestion_id\":\"GB|RM|B|55782678\"}'\n```\n\n**What to know:**\n\n- **Step 3 consumes a Loqate credit** to resolve the id (the search in step 1 does not). Resolve\n  the one address that was chosen — not the whole list to compare.\n- `suggestion_id` replaces `address`; sending both is a `400`.\n- Not available with `--batch`, and not with `--dry-run` (resolving needs a live billable call).\n- A stale id returns `SUGGESTION_NOT_FOUND` / `404`. Ids change over time — search again rather\n  than retrying the same id.\n\n**Just want the address, not a decision?** Resolve it on its own:\n\n```bash\nlqt retrieve --id \"GB|RM|B|55782678\"           # components as JSON\nlqt retrieve --id \"GB|RM|B|55782678\" -o table  # human-readable\n```\n\n`GET /v1/address/{id}` over REST, or the `retrieve_address` MCP tool. This returns reference\ndata, **not** a verification — no confidence, no recommendation — so don't treat it as checked.\n\nFour rules that keep the loop safe:\n\n- **Omit `suggest` on the confirmation call.** If the chosen address still doesn't clear the\n  policy you'd get a fresh set of suggestions, and an automated flow could bounce between them.\n  One round of suggestions, then a plain verify.\n- **Let the re-verify decide** — not the fact that a suggestion existed. If the confirmation\n  returns `review` or `reject`, the record still needs a human. You've narrowed it, not fixed it.\n- **Don't re-verify an `expandable` item as-is.** It's a street, postcode, or building, so\n  verifying it lands at street level at best. Use it to ask for the missing piece (\"which\n  number on Marsh Wall?\") and verify the completed address.\n- **Never store `id`.** It's a Loqate-assigned identifier that changes over time. Key off the\n  verified address returned in step 3.\n\nKeep the country from the original request on the confirmation call — dropping it can change\nthe match.\n\n#### Suggestion ranking comes from Loqate\n\n`lqt` returns suggestions in the order Loqate provides them — no re-ranking or filtering is\napplied. Loqate matches across the whole address record, **including organisation names**, so a\nquery like `marsh wall london` ranks businesses with \"London\" in their name above plain\nresidential addresses on that street:\n\n```\nLondon Lash, 56 Marsh Wall, London, E14 9TP\nLondon Metropolis Ltd, 77 Marsh Wall, London, E14 9SH\n```\n\nThat's standard address-autocomplete behaviour, but it means **suggestion quality tracks input\nquality**. Where you know the country, pass it as `--country` rather than leaving it in the\naddress text — that moves the token out of the fuzzy match and into a filter:\n\n```bash\nlqt verify -a \"marsh wall london\" --suggest      # \"london\" is matchable text\nlqt verify -a \"marsh wall\" -c GB --suggest       # cleaner: country is a filter\n```\n\n\n### parse\n\nParse and standardize contact data using Claude (Haiku). Extracts address components, validates email syntax, and normalizes phone numbers with awareness of 250+ country-specific postal formats. No Loqate API calls — no credits spent.\n\n```bash\nlqt parse [flags]\n```\n\n**Flags:**\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--address` | `-a` | Full address to parse |\n| `--email` | `-e` | Email address to validate |\n| `--phone` | `-p` | Phone number to normalize |\n| `--country` | `-c` | ISO 2-letter country code hint |\n| `--batch` | `-b` | CSV/TSV/pipe-delimited file path (or `-` for stdin) |\n| `--delimiter` | `-d` | Batch delimiter: `comma`, `tab`, `pipe` (auto-detected if omitted) |\n| `--output` | `-o` | Output format: `json`, `jsonl`, `table` |\n| `--jsonl` | | JSON Lines output |\n| `--no-color` | | Disable color output |\n| `--anthropic-key` | | Anthropic API key (overrides env) |\n\n**Examples:**\n\n```bash\n# Parse a messy address into structured components\nlqt parse -a \"125 summer street boston ma 02110 us\"\n\n# Parse address + validate email + normalize phone\nlqt parse -a \"10 downing st london\" -e \"test@mailinator.com\" -p \"02071234567\"\n\n# Batch parse from CSV\nlqt parse --batch messy-data.csv --output json\n```\n\n### policy\n\nList, inspect, and validate verification policies.\n\n```bash\nlqt policy list                  # List all built-in policies\nlqt policy show <name>           # Show full JSON for a policy\nlqt policy validate <file>       # Validate a custom policy JSON file\n```\n\n### mcp\n\nStart an MCP (Model Context Protocol) server. Exposes LQT as tools for AI agents.\n\n```bash\nlqt mcp                    # Stdio transport (launched by clients)\nlqt mcp --http :8080       # HTTP transport (deployed as a service)\nlqt mcp --smoke-test       # Verify the server starts correctly and exit\n```\n\n**Flags:**\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--http` | | Listen address (e.g. `:8080`, `127.0.0.1:8080`) |\n| `--rate-limit` | `10` | Max requests/sec per IP (`0` to disable) |\n| `--rate-burst` | `20` | Max burst size for rate limiter |\n| `--smoke-test` | | Self-test the MCP server (checks tools and prompts register) and exit |\n| `--disable-custom-endpoint` | | Block per-request custom verify endpoint fields |\n| `--rest` | | Also serve the REST API at `/v1` (HTTP mode only) |\n\n---\n\n### REST API\n\nFor clients that don't speak MCP, the HTTP server can also expose a plain REST API — opt-in with `--rest`, mounted at `/v1` on the same port. Same result data as the CLI and MCP.\n\n```bash\nlqt mcp --http :8080 --rest\n```\n\n**Authentication:** your Loqate API key as a bearer token — `Authorization: Bearer <LOQATE_API_KEY>` (or `key` in the request body).\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/v1/verify/address` | Verify an address (supports `detect_country`, `suggest`, `suggestion_id`) |\n| `POST` | `/v1/verify/email` | Verify an email |\n| `POST` | `/v1/verify/phone` | Verify a phone number |\n| `POST` | `/v1/verify/contact` | Verify any combination + overall recommendation (supports `detect_country`, `suggest`) |\n| `GET`  | `/v1/address/{id}` | Resolve a suggestion id to a cleansed address (**consumes a credit**) |\n| `GET`  | `/v1/policies` | List decisioning policies |\n| `GET`  | `/v1/policies/{name}` | Show one policy |\n| `GET`  | `/v1/openapi.json` | OpenAPI 3.1 specification |\n| `GET`  | `/v1/docs` | Interactive API reference |\n\nA recommendation (`accept` / `review` / `reject`) is always returned as HTTP `200` with the decision in the body. Errors use standard status codes: `400` invalid input, `401` missing/invalid key, `429` rate limited, `502` upstream error.\n\n```bash\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"address\":\"125 Summer St, Boston, MA 02110, US\",\"policy\":\"standard\"}'\n\n# Ask for alternatives when the address does not clear the policy\ncurl -s -X POST https://your-host/v1/verify/address \\\n  -H \"Authorization: Bearer $LOQATE_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"address\":\"10 downin st london\",\"country\":\"GB\",\"suggest\":true,\"suggest_limit\":5}'\n```\n\nFull request/response schemas are documented in the OpenAPI spec at `/v1/openapi.json` (browse it at `/v1/docs`).\n\n---\n\n\n### Explaining a result\n\nEvery address verification also returns detail that explains the score without changing it:\n\n| Field | What it tells you |\n|---|---|\n| `matchscore` | 0-100, how closely the returned address resembles what you sent. Surfaced so you need not parse it out of `avc`. |\n| `coverage_level` + `coverage_level_label` | The country's maximum Loqate verification level, as a number and a name: `5` `delivery_point`, `4` `premise`, `3` `street`, `2` `locality`. The label uses the same vocabulary as `match_level`, so when the two are equal the address matched as precisely as that country's data allows. |\n| `coverage_boost` | The level shift applied because that country's data tops out below premise. This is the number that explains why a street-level match in a low-coverage country still scores highly. |\n| `changes` | What Loqate altered, in words. **Opt-in — see below.** |\n\n**To get `changes`, ask Loqate for its per-field status codes:**\n\n```bash\nlqt verify -a \"125 Summer St, Boston, MA 02110, US\" \\\n  --option ServerOptions.FieldStatus=true -o json\n```\n\n```json\n\"changes\": [\n  { \"field\": \"country_name\",            \"change\": \"added\",       \"value\": \"United States\", \"code\": \"5\" },\n  { \"field\": \"postal_code\",             \"change\": \"reformatted\", \"value\": \"02110-1634\",    \"code\": \"2\" },\n  { \"field\": \"postal_code_secondary\",   \"change\": \"added\",       \"value\": \"1634\",          \"code\": \"5\" },\n  { \"field\": \"sub_administrative_area\", \"change\": \"added\",       \"value\": \"Suffolk\",       \"code\": \"5\" }\n]\n```\n\nNothing was wrong with that address; three things were **added** (ZIP+4, county, country name) and the\npostcode was reformatted. Fields Loqate verified without touching are not listed, so a short list means\na clean address.\n\n`change` is one of `added`, `corrected`, `reformatted` or `unrecognised`. `code` is Loqate's original\nstatus code, kept so the categorisation is not lossy — the codes are Loqate's own, documented at\n[docs.loqate.com/report-codes/fieldstatus](https://docs.loqate.com/report-codes/fieldstatus).\n\nAbsent `changes` means you did not ask for the codes. An empty array means you asked and nothing changed.\nThe option also adds a `<field>_status` key per component to `fields`, since that passthrough returns\neverything Loqate sends.\n\nThis detail appears on **every** address verification — single, batch (per row), MCP and REST — because\nall four go through the same result builder.\n\n## Policies\n\nPolicies control what gets accepted, reviewed, or rejected. Every verification runs through a policy — there are no hardcoded thresholds.\n\n| Policy | Addr Confidence | Match Level | Email Confidence | Phone Required | Suggest Below | Use Case |\n|--------|:-:|:-:|:-:|:-:|:-:|------|\n| **strict** | 0.90 | premise | 0.85 | yes | 0.90 | KYC, fraud prevention, regulated |\n| **shipping** | 0.85 | street | 0.50 | no | 0.85 | Physical delivery, ecommerce |\n| **standard** | 0.55 | street | 0.45 | no | 0.85 | General verification (default) |\n| **permissive** | 0.30 | locality | 0.30 | no | 0.70 | Lead capture, early funnel |\n\n**Suggest Below** is not an acceptance threshold — it never changes accept/review/reject. It is\nthe confidence below which `--suggest` looks up alternatives even for an *accepted* address.\nSee [Address suggestions](#address-suggestions---suggest). Custom policies can set their own\nvalue, and the `recommend_policy` MCP tool proposes one for the use case you describe.\n\n### Custom Policies\n\nCreate a JSON file:\n\n```json\n{\n  \"name\": \"my-custom-policy\",\n  \"description\": \"Tuned for my use case\",\n  \"address\": {\n    \"min_confidence\": 0.65,\n    \"min_match_level\": \"street\",\n    \"reject_verification_status\": [\"U\", \"R\"]\n  },\n  \"email\": {\n    \"min_confidence\": 0.50,\n    \"allow_catch_all\": true,\n    \"reject_disposable\": true\n  },\n  \"phone\": {\n    \"min_confidence\": 0.40,\n    \"required\": false\n  }\n}\n```\n\n```bash\nlqt policy validate my-policy.json    # Validate first\nlqt verify -a \"...\" --policy-file my-policy.json\n```\n\n---\n\n## Batch Processing\n\nProcess files with address, email, and phone columns. Supports comma, tab, and pipe delimited input.\n\n```bash\n# CSV (auto-detected)\nlqt verify --batch addresses.csv --policy shipping -o json > results.json\n\n# Tab-delimited\nlqt verify --batch addresses.tsv -o json\n\n# Pipe-delimited\nlqt verify --batch addresses.txt --delimiter pipe -o json\n\n# From stdin\ncat addresses.csv | lqt verify --batch - --policy standard\n\n# With summary statistics\nlqt verify --batch addresses.csv --summary\n```\n\n**Windows (PowerShell):**\n```powershell\n.\\lqt.exe verify --batch addresses.csv --policy shipping -o json > results.json\nGet-Content addresses.csv | .\\lqt.exe verify --batch - --policy standard\n```\n\n### Delimiters\n\nAuto-detected from the first line. Override explicitly with `--delimiter`:\n\n| Value | Aliases | Description |\n|-------|---------|-------------|\n| `comma` | `csv` | Comma-separated (default) |\n| `tab` | `tsv` | Tab-separated |\n| `pipe` | | Pipe-separated |\n\n### Supported Columns\n\nUse a single `address` column or structured fields — or both. All column names are case-insensitive. Every field from the [Loqate International Batch Cleanse API](https://docs.loqate.com/api-reference/address-verify/international-batch-cleanse) is supported.\n\n**Address lines:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| Address (line 1) | `address`, `address1`, `street`, `address_line_1` |\n| Address lines 2-8 | `address2`-`address8`, `address_line_2`-`address_line_8` |\n| Delivery address | `deliveryaddress`, `delivery_address` |\n| Delivery lines 1-8 | `deliveryaddress1`-`deliveryaddress8`, `delivery_address_1`-`delivery_address_8` |\n\n**Geography:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| City | `city`, `locality`, `town` |\n| State/Province | `state`, `admin_area`, `province`, `region`, `administrative_area` |\n| County | `county`, `sub_admin_area`, `sub_administrative_area` |\n| Postal code | `postcode`, `postal_code`, `zip`, `zipcode` |\n| Country | `country`, `country_code` |\n\n**Street / building / premise:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| Street name | `thoroughfare`, `street_name` |\n| Building | `building`, `building_name` |\n| House number | `premise`, `house_number`, `building_number` |\n| Apartment/Suite | `sub_building`, `apartment`, `suite`, `unit`, `flat` |\n\n**Organization / postal:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| Organization | `organization`, `organisation`, `company`, `company_name` |\n| PO Box | `post_box`, `postbox`, `po_box`, `pobox` |\n\n**Contact / person:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| First name | `forename`, `first_name` |\n| Last name | `surname`, `last_name` |\n| Full name | `full_name`, `name` |\n\n**Non-address fields:**\n\n| Field | Accepted column names |\n|-------|----------------------|\n| Email | `email`, `email_address` |\n| Phone | `phone`, `telephone`, `phone_number`, `mobile` |\n\n### Example CSV\n\n```csv\naddress,email,phone,country\n\"125 Summer St, Boston, MA 02110\",user@example.com,+16175551234,US\n\"10 Downing St, London\",pm@gov.uk,+442071234567,GB\n```\n\n---\n\n## MCP Integration\n\nThe `lqt mcp` command exposes LQT as tools for AI agents via the [Model Context Protocol](https://modelcontextprotocol.io/). Connecting the MCP server also provides a built-in usage guide prompt that teaches the AI how to use the tools effectively.\n\n### Claude Code / Cursor\n\nAdd to your project's `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"loqate\": {\n      \"command\": \"lqt\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"LOQATE_API_KEY\": \"your-key-here\",\n        \"ANTHROPIC_API_KEY\": \"your-key-here\"\n      }\n    }\n  }\n}\n```\n\n### Claude Desktop\n\nAdd to Claude Desktop's MCP settings:\n\n```json\n{\n  \"mcpServers\": {\n    \"lqt\": {\n      \"command\": \"/usr/local/bin/lqt\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"LOQATE_API_KEY\": \"your-key-here\",\n        \"ANTHROPIC_API_KEY\": \"your-key-here\"\n      }\n    }\n  }\n}\n```\n\n### GBG-hosted endpoint (recommended)\n\nThe fastest way to use Loqate over MCP is the GBG-hosted endpoint — no install, no infrastructure. Point any MCP client at:\n\n```\nhttps://reach.prod.fabric.gbgplatforms.com/mcp\n```\n\n**Claude Code / Cursor / any MCP client** — `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"loqate\": {\n      \"url\": \"https://reach.prod.fabric.gbgplatforms.com/mcp\"\n    }\n  }\n}\n```\n\nRestart your client, then ask it to \"verify 125 Summer St, Boston, MA 02110, US\". It will discover the tools, call them, and explain the result.\n\n**Authenticate with your Loqate API key — pick one:**\n\n1. **Per-call** — pass `key` in the tool arguments (`{\"key\": \"YOUR-KEY\", \"address\": \"...\"}`).\n2. **Connection-wide** — set `Authorization: Bearer <YOUR-LOQATE-KEY>` on the HTTP connection. Applies to every tool call.\n3. **Out of band (Claude only)** — put `<loqate_api_key>YOUR-KEY</loqate_api_key>` in org / project / user instructions; the model injects it as `key` automatically.\n\nIf you supply none of the three, the server returns a `NO_API_KEY` error. The Bearer header only supplies the standard Loqate key; `verify_key` for a custom address-verify endpoint is separate.\n\n**Sanity check from your terminal** (no client needed):\n\n```bash\n# List tools (no auth required)\ncurl -s -X POST https://reach.prod.fabric.gbgplatforms.com/mcp \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'\n\n# Verify an address (Bearer auth)\ncurl -s -X POST https://reach.prod.fabric.gbgplatforms.com/mcp \\\n  -H 'Authorization: Bearer YOUR-LOQATE-KEY' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"verify_address\",\"arguments\":{\"address\":\"125 Summer St, Boston, MA 02110, US\"}}}'\n```\n\nHosted deployments disable custom verify endpoints for security. If you receive a `CUSTOM_ENDPOINT_DISABLED` error, remove `verify_url` and `verify_key` from your tool arguments.\n\n### GBG-hosted REST endpoint\n\nPrefer plain REST? The same hosted service also exposes the [REST API](#rest-api) — no MCP client required. Authenticate with your Loqate API key as a bearer token.\n\n```bash\n# Verify an address\ncurl -s -X POST https://reach.prod.fabric.gbgplatforms.com/v1/verify/address \\\n  -H 'Authorization: Bearer YOUR-LOQATE-KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"address\":\"125 Summer St, Boston, MA 02110, US\",\"policy\":\"standard\"}'\n\n# Browse the interactive API reference (no key required)\nopen https://reach.prod.fabric.gbgplatforms.com/v1/docs\n```\n\nThe OpenAPI spec (`/v1/openapi.json`) and reference page (`/v1/docs`) are unauthenticated, so you can explore the full API before you have a key.\n\n### Remote HTTP (self-hosted)\n\nIf you'd rather run the server yourself, deploy `lqt mcp --http` as a service:\n\n```json\n{\n  \"mcpServers\": {\n    \"loqate\": {\n      \"url\": \"https://lqt.your-company.com/mcp\"\n    }\n  }\n}\n```\n\nSame three-tier key resolution applies (body `key` → `Authorization: Bearer` → server env `LOQATE_API_KEY`).\n\n### Available Tools\n\n10 tools in stdio mode, 7 in HTTP mode (tools marked *stdio mode only* are not available over HTTP).\n\n| Tool | Description |\n|------|-------------|\n| `verify_address` | Verify an address with confidence score and recommendation (supports `detect_country`, `suggest`, `suggestion_id`) |\n| `verify_email` | Verify an email with risk level and recommendation |\n| `verify_phone` | Verify a phone number with type/carrier and recommendation |\n| `verify_contact` | Verify all fields together with overall recommendation (supports `detect_country`, `suggest`, `suggestion_id`) |\n| `retrieve_address` | Resolve a suggestion id to a cleansed address (consumes a credit; not a verification) |\n| `parse_address` | Parse and standardize an address via Claude (stdio mode only) |\n| `list_policies` | List available decisioning policies |\n| `show_policy` | Show details for a specific policy |\n| `set_policy` | Register a custom policy (stdio mode only) |\n| `recommend_policy` | Get a recommended policy for your use case, including its suggestion confidence floor (stdio mode only) |\n\n---\n\n## Exit Codes\n\nDesigned for scripting and CI/CD:\n\n| Code | Meaning |\n|:---:|---------|\n| **0** | ACCEPT — all fields passed verification |\n| **1** | REVIEW — manual review recommended |\n| **2** | REJECT — verification failed |\n| **3** | ERROR — missing key, invalid input, API failure |\n\n**macOS / Linux:**\n```bash\nlqt verify -a \"125 Summer St, Boston, MA 02110, US\" --policy shipping -o json\ncase $? in\n  0) echo \"Ship it\" ;;\n  1) echo \"Queue for review\" ;;\n  2) echo \"Bad address\" ;;\n  3) echo \"Something broke\" ;;\nesac\n```\n\n**Windows (PowerShell):**\n```powershell\n.\\lqt.exe verify -a \"125 Summer St, Boston, MA 02110, US\" --policy shipping -o json\nswitch ($LASTEXITCODE) {\n  0 { Write-Host \"Ship it\" }\n  1 { Write-Host \"Queue for review\" }\n  2 { Write-Host \"Bad address\" }\n  3 { Write-Host \"Something broke\" }\n}\n```\n\n---\n\n## API Keys\n\n### Loqate API Key (for `verify`)\n\n**macOS / Linux:**\n```bash\n# Environment variable\nexport LOQATE_API_KEY=your-key-here\n\n# Key file (add to .gitignore)\necho \"your-key-here\" > .loqate-key\n\n# Per-command flag\nlqt verify -a \"...\" --key your-key-here\n```\n\n**Windows (PowerShell):**\n```powershell\n# Current session\n$env:LOQATE_API_KEY=\"your-key-here\"\n\n# Persistent (survives restarts)\n[System.Environment]::SetEnvironmentVariable(\"LOQATE_API_KEY\", \"your-key-here\", \"User\")\n\n# Per-command flag\n.\\lqt.exe verify -a \"...\" --key your-key-here\n```\n\n### Anthropic API Key (for `parse`)\n\n**macOS / Linux:**\n```bash\nexport ANTHROPIC_API_KEY=your-key-here\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:ANTHROPIC_API_KEY=\"your-key-here\"\n```\n\n**Resolution order:** flag > environment variable > key file\n\n### Custom Verify Endpoint (optional)\n\nIf you need to route address verification through a different endpoint (e.g., an on-premises or partner-hosted Loqate instance):\n\n**macOS / Linux:**\n```bash\n# Environment variables\nexport LOQATE_VERIFY_URL=https://custom-verify.example.com/v1/batch\nexport LOQATE_VERIFY_KEY=your-custom-key\n\n# Or use flags (override env vars)\nlqt verify -a \"...\" --verify-url https://custom-verify.example.com/v1/batch --verify-key your-custom-key\n```\n\n**Windows (PowerShell):**\n```powershell\n$env:LOQATE_VERIFY_URL=\"https://custom-verify.example.com/v1/batch\"\n$env:LOQATE_VERIFY_KEY=\"your-custom-key\"\n```\n\n**Resolution order:** flag > environment variable > default Loqate endpoint\n\nWhen `--verify-key` is set, the standard `--key` / `LOQATE_API_KEY` is not required for address-only verification. If you also verify email (`-e`) or phone (`-p`), the standard key is still needed for those.\n\nThese flags only affect address verification. Email and phone always use the standard Loqate endpoints.\n\nIn MCP mode, clients can pass `verify_url` and `verify_key` per-request in `verify_address` and `verify_contact` tool inputs.\n\n---\n\n## Support\n\n- **Bug reports & feature requests** — [open an issue](https://github.com/gbgplc/lqt/issues/new/choose)\n- **Security vulnerabilities** — please email [labs@gbg.com](mailto:labs@gbg.com) instead of opening a public issue\n- **General questions** — [start a discussion](https://github.com/gbgplc/lqt/discussions) or open an issue\n\nWhen reporting a bug, please include:\n- `lqt` version (`lqt --version`)\n- OS and architecture (e.g., macOS ARM64, Linux x86_64)\n- The command you ran (redact any API keys)\n- Expected vs actual behavior\n\n---\n\n## License\n\nProprietary — see [LICENSE](LICENSE). Use requires an active Loqate subscription.\n\n---\n\n<p align=\"center\">\n  Built by <a href=\"https://www.gbg.com\">GBG</a>.\n</p>\n",
  "bytes": 38071,
  "sha": "6040ac561880b286ec28f1591357895b57f861e9b445eb845968d1b44a66e40c",
  "repo_slug": "gbgplc/lqt",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_gbgplc_lqt_96105597/readme"
}