A side-by-side look at the Contractor License Verification (TradesAPI) and Apier MCP MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Contractor License Verification (TradesAPI) for legal work as a local process; choose Apier MCP for legal as a local process. You can also run both side by side in one mcpServers block.
CLV_API_URL, CLV_API_KEY.verify_license, batch_verify, list_supported_states.APIER_API_KEY.get_company_summary, get_public_obligations, get_exchange_rate.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Legal | Legal |
| Quality signal | 59/100 · Good | 57/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | Not declared | Not declared |
| Pricing | Not declared | Not declared |
| Required env vars | CLV_API_URLCLV_API_KEY | APIER_API_KEY |
| Verified owner | Community listing | Community listing |
| GitHub stars | 0 | 0 |
| Directory activity | 2 views 0 installs 0 upvotes | 2 views 0 installs 0 upvotes |
| Tools | 4 | 25 |
| Full listing | View Contractor License Verification (TradesAPI) | View Apier MCP |
verify_licenseVerify a single US contractor's license against the official state (or city) licensing board. USE WHEN: the user has a specific license number and wants to confirm it's valid, current, and free of disciplinary action — e.g. 'is TX license TACLA00000103C still active?', 'check if this electrician's license expired', 'pull disciplinary history for this contractor.' DO NOT USE FOR: searching by contractor or business name when the license number is unknown (use search_by_name); discovering what states/cities are supported (use list_supported_states); verifying federal licenses, doctors/lawyers, or non-construction trades (out of scope). RETURNS: {valid, name, license_number, trade, expiration, status, state, disciplinary_actions[], source_url, cached, checked_at}. Result is fetched live from the authoritative state portal; active licenses are cached 24h, expired/not-found results are always re-fetched. EXAMPLE: state='TX', license_number='TACLA00000103C', trade='hvac' → {valid:true, name:'ANDERSON, ORIN RAE', status:'Active', expiration:'05/12/2026', source_url:'https://www.tdlr.texas.gov/...'}. ERRORS: 400 INVALID_INPUT (malformed license/state/trade — fix the args and retry); 502 STATE_PORTAL_UNAVAILABLE (the state portal itself is down — retry after a few minutes); 429 RATE_LIMITED (back off and retry). All errors return a human-readable message; transient errors (502/429) are safe to retry, 400 is not.batch_verifyVerify up to 50 contractor licenses in a single call. Items are dispatched concurrently against their respective state/city portals; one item failing does not abort the others. USE WHEN: the user mentions verifying multiple licenses — phrases like 'I have 12 license numbers', 'verify these 5 contractors', 'bulk-check', 'verify them all', a list of subcontractors on a project, periodic compliance sweeps, COI/insurance review batches. **If the user has stated they want to verify N>1 licenses, this is the tool — don't fall back to list_supported_states first; the user already knows what they want to verify.** Even if the user hasn't pasted the list yet, batch_verify is the right next step (you can ask for the list, then call this). Cheaper in conversation turns than calling verify_license N times. DO NOT USE FOR: a single license (use verify_license — clearer output); >50 licenses in one call (split into multiple batches); searches by name (use search_by_name); discovering what states are supported (use list_supported_states). RETURNS: {summary: {total, succeeded, failed}, results: [{result, error}]} where each result is the same shape as verify_license, and `error` is non-null on per-item failures. Inspect individual `error` strings to retry just the failed items. EXAMPLE: licenses=[{state:'TX', license_number:'TACLA00000103C', trade:'hvac'}, {state:'CA', license_number:'1234567', trade:'general'}] → {summary:{total:2, succeeded:2, failed:0}, results:[...]}. ERRORS: per-item errors are reported in `results[i].error` rather than aborting the whole batch. Top-level 400 only fires on schema violations (e.g. >50 items, empty array).list_supported_statesList every supported jurisdiction TradesAPI can verify contractor licenses against — all 50 US states, DC, and registered city-level licensing portals (Chicago, NYC, Philadelphia, Detroit, Atlanta, Dallas, Las Vegas, Nashville). USE WHEN: the user asks 'what states do you cover', 'do you support [state]', 'which cities have municipal licensing'; before constructing a verify_license call when you're unsure of the trade vocabulary; to confirm a portal is currently healthy before a batch run. DO NOT USE FOR: per-license verification (use verify_license); name searches (use search_by_name). RETURNS: {total_states, total_municipalities, states: [{code, name, portal_url, supported_trades[], supports_name_search, status, municipalities: [{code, city, portal_url, ...}]}]}. `status` is 'healthy' | 'degraded' | 'maintenance'. `supported_trades` is the set of trade values observed in test fixtures (best-effort; some search-only states may return []). `supports_name_search` indicates whether the state's portal allows search_by_name queries. EXAMPLE: returns 51 state rows (50 states + DC) with municipalities nested under their parent state — IL has Chicago nested, NY has NYC, etc. ERRORS: 502 STATE_PORTAL_UNAVAILABLE only if the API itself is down; this tool reads from registry metadata, not state portals, so it's normally always available.search_by_nameFuzzy-search contractors by business or individual name within a single state (or city) licensing database. USE WHEN: the user has a contractor's name but not their license number — 'find Smith Plumbing in Texas', 'is there an active electrician named John Doe in California', vetting a contractor whose card you don't have in hand. Match is case-insensitive and tolerates partial words and reordered tokens (e.g. 'Smith Plumbing' matches 'Plumbing Smith Inc'). DO NOT USE FOR: license-number lookup (use verify_license — it's faster and authoritative); discovery of what states are supported (use list_supported_states); states where supports_name_search:false (the call will 400 — check list_supported_states first). RETURNS: {query: {state, name, trade}, total_results, results: [{name, license_number, trade, status, state, confidence, source_url}], cached, checked_at}. `confidence` is 0.0-1.0 (1.0 = exact match). Results are ranked by confidence descending. EXAMPLE: state='TN', city='nashville', name='100 PERCENT PLUMBING', trade='plumbing' → {results: [{name: '100 PERCENT PLUMBING INC', license_number: '...', confidence: 0.95, ...}]}. COST: this tool deducts 2 credits per call (vs 1 for verify_license) because name searches are more expensive — they may scrape multiple result pages. ERRORS: 400 NAME_SEARCH_NOT_SUPPORTED (this state's portal doesn't expose a name-search endpoint — check list_supported_states.supports_name_search); 502 STATE_PORTAL_UNAVAILABLE (retry); 429 RATE_LIMITED (back off).get_company_summaryA one-shot summary of obligations and deadlines for a Norwegian organisation: your FIRST call when you orient against a company.get_public_obligationsKeyless. Retrieve the universal obligation set for a Norwegian entity type — every regulatory obligation that applies by virtue of BEING that organisational form, before per-company Tier-2 data is layered on.get_exchange_rateKeyless. Norges Bank reference exchange rate for a currency against NOK — the benchmark Norwegian tax and accounting rules accept for foreign-currency obligations.list_acting_capacityResolve every Norwegian regulatory action a person is currently authorised to perform on behalf of a specific organisation.get_company_profileResolve a Norwegian organisasjonsnummer (9 digits) into a structured company profile from Brønnøysund Enhetsregisteret: display name, form of organisation, NACE codes with descriptions, addresses, the dates of registration and dissolution, the `active` / `dissolved` status enum, the MVA-registered…check_authorizationReturn the authorisation snapshot for the calling consumer's delegation on a Norwegian organisation: the `status` enum (`full` / `partial` / `none`), `active_scopes`, `missing_scopes` (empty on `full`) and `delegated_rights`.get_company_contextBrønnøysund identity slice for a Norwegian organisation: legal name, form of organisation, NACE codes, addresses, the dates it was formed or dissolved, and the signaturrett / prokura role-code summary (never personal identifiers).get_company_deadlinesThe upcoming filing calendar for one organisation, horizon_months ahead.get_company_obligationsEvaluate the Apier Rulebook for a Norwegian organisation: one entry per rule with rule_id, obligation_name, evaluation_result (applicable, not_applicable or insufficient_data), a reason, the legal_reference, frequency, data_tier_required and the bokmål description, which is inherited byte for byte…get_public_deadlinesKeyless. The universal Norwegian filing calendar: the deadlines for every Norwegian business in the covered categories (MVA, A-melding, Skattemelding, Årsregnskap), which do not depend on any one organisation.validate_actionDry-run a proposed regulatory action with NO upstream side effect (no government call).explain_compliance_errorKeyless. Resolve a structured Apier compliance error code into a Norwegian-bokmål Explanation envelope: summary, bokmål why, ordered fix_steps, optional documentation link + legal_basis, and an optional handover block (who / where / what / why) for errors a human must resolve.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"contractor-license-verification-tradesapi-2": {
"command": "npx",
"args": [
"-y",
"contractor-license-mcp-server"
],
"env": {
"CLV_API_URL": "YOUR_CLV_API_URL_HERE",
"CLV_API_KEY": "YOUR_CLV_API_KEY_HERE"
}
}
}
}
{
"mcpServers": {
"mcp-375": {
"command": "npx",
"args": [
"-y",
"stdio"
],
"env": {
"APIER_API_KEY": "YOUR_APIER_API_KEY_HERE"
}
}
}
}