Skip to main content
Glama

LexLint: compliance lint for AI, scraping, and privacy law

Lint an app against the law

run_lint
Read-only

Step 2 of the lint, and the one that returns findings. Pass the activities and jurisdictions set_profile validated, and get lint-style findings: which obligations apply, with severity (warn/info), citation, as_of_date, staleness, and confidence. warn: a live obligation binds the profile (obligation), a posture finding needs attention (posture), or LexLint lacks current data for a declared jurisdiction (coverage). info: context rather than a live duty, and kind says which it is: an instrument LexLint cannot say is in force today (pending), a jurisdiction-wide statement of how the local law treats crawling as a whole, binding nobody on its own (posture), a note about what was not reported (coverage), a duty your customer, a public body or a financial institution, owes and meets through your software (customer_duty, with public_sector or regulated_sector declared; triage it in the product lane), or an instrument whose owed is not yours (obligation). LexLint never reports error: a lint cannot be sure something is prohibited, so it will not say so. Every instrument finding also carries certainty.resultset, which is the axis to present on and is NOT the same cut as kind: present is law as it stands today, including an instrument blocked by a court, whose enforcement is paused (a live risk held in abeyance, never hypothetical); forward is law that may be coming; historical is a spent instrument that is neither. NOTHING IN forward MAY GATE: it is informational, it must never reach an exit code, fail a build, or block a merge, and a bill in committee changing your build colour is a misuse of this tool. Within forward, certainty.rung orders by how much is PINNED to primary text and never by a probability, with rung 1 (enacted, commencement dated) predicting nothing at all; certainty.rung is null where the law library holds no stage to rank by, which is not the same as the lowest rung. If you suppress any part of forward from what you show a user, say so in your output: a run that drops rows and then reports "no basic issues found" is a silent pass. Each instrument finding also carries in_force, whose words is what to print wherever you say when a law binds. Obligations are matched from AI, scraping, privacy, cybersecurity, communications, content-moderation, product-liability, age-gating and reuse law; that is every topic the law library carries, so a declaration can raise findings from any of them and no topic is served by get_law alone any more. A finding whose instrument has a LexLint page carries note_url; show the citation as a link to it, and never construct that URL yourself. A jurisdiction LexLint has no current data for is a WARNING, never a silent pass, and the passing state is "no basic issues found", never "compliant". This is a lint for catching basic issues early, NOT legal advice and NOT a compliance certification. Costs three upstream requests for any number of declared jurisdictions: it reads the whole published law library and filters to your declaration in memory, rather than one request per jurisdiction. A trial key lints at most 10 distinct jurisdictions over its whole life; a declaration past that is refused before anything is spent. A repeat lint against a law library that has not moved since an earlier one can cost fewer, served from this key's own cache. This tool needs sign-in or an UnGovr Open Data key (metered per request; get one at https://ungovr.org/cli-login?client=lexlint).

Input Schema

NameRequiredDescriptionDefault
briefNoSend true when you will show these findings to a person and have no LexLint procedure loaded. Each finding then comes back as one line to print: its summary and first duty clipped to 160 characters, with the citation, note_url, in_force, owed and kind; the full text of any law is one get_law call away. Leave it out when you write lexlint.yml: brief findings drop fields the manifest keeps.
rolesNoWhich role this software's maker holds under each regime, keyed by axis: ai_system (provider, deployer, importer, distributor, product_manufacturer, authorised_representative, the EU AI Act's operators) and personal_data (controller, processor, the GDPR's). {"ai_system": ["provider"], "personal_data": ["processor"]}; "none" alone when asked and none applies. Ask the developer; never infer it from the code. Omitted, an axis routes nothing and run_lint counts the duties a role would move in a coverage line.
activitiesYesWhat the app does, from the profile set_profile returned. Allowed: crawls_web, trains_models, generates_content, deploys_chatbot, automated_outreach, high_risk_decisions, processes_voice, processes_biometrics, publishes_adult_content, operates_social_platform, serves_minors, operates_app_store, ships_mobile_app, aggregates_content, distributes_software_product, handles_health_records, provides_financial_services, operates_essential_service, is_listed_company, provides_telecom_services, statutory_requests, records_calls, records_text_chat, tracks_devices, is_bank, is_lender, is_insurer, is_securities_firm, is_payment_provider, is_crypto_asset_provider, employment_decisions, credit_decisions, insurance_decisions, housing_decisions, education_decisions, health_care_decisions, public_services_decisions, justice_decisions
jurisdictionsYesJurisdiction slugs from the profile set_profile returned, lowercase, "/"-separated (e.g. "us", "us/ca", "eu", "kr"). A slug is the jurisdiction's UnGovr Atlas path: California is https://ungovr.org/us/ca and its Atlas ID is urn:ungovr:us/ca. Its ISO 3166 code, US-CA, is accepted too. A deeper or unresearched path resolves to the nearest jurisdiction with law, and the jurisdictions whose law is researched are listed at https://lexlint.io/law for the developer to check; name every jurisdiction the app operates in: one left off is unlinted, not passed.
public_sectorNoIs this software run by a public body (body), sold to or run for public bodies (supplier), both, or neither (none)? Ask the developer every time the profile is declared; never infer it from the code. Omitted, duties binding only public bodies are reported as the caller's, and run_lint counts them in a coverage line.
client_versionNoThe LexLint plugin version you are running, from your SKILL.md, exactly as check_access takes it. Send it on every lint: a run that skips the preflight otherwise learns nothing about its own staleness. Omitted, update_available comes back null, which means LexLint learned nothing, never that you are current.
regulated_sectorNoWhose duty a financial-law row is. Is this software run by a bank, insurer or other regulated financial entity (body), supplied to one (supplier), or neither (none)? {"financial": "supplier"}. Ask when provides_financial_services or a license class (is_bank, is_lender, is_insurer, is_securities_firm, is_payment_provider, is_crypto_asset_provider) is declared; never infer it. It routes and never matches, so a supplier still declares the classes of its customers. Omitted, the entity's duties are reported as the caller's, and run_lint counts them in a coverage line.

Output Schema

NameRequiredDescriptionDefault
docsYesWhere the full documentation lives.
lintYesOne-line verdict: counts by severity, then the verdict itself. The passing state is "no basic issues found", never "compliant".
briefNoPresent, and true, when the call sent brief: each instrument finding is then one line, and fields it would otherwise carry (detail, why, matched_by, basis, lifecycle, the rest of requires) are not sent. Absent there means not sent, never empty.
noticeYesThe standing disclaimer. Not legal advice, not a certification, not authorization to access any system.
replayNoQuote this when you report a problem with a run, and LexLint can reproduce it exactly: the bundle, the law library build, the instant the run was judged at, and a digest of the declaration. Nothing about the run is stored to make it work.
run_atNoThe instant this run was judged at, ISO 8601. Not the same question as corpus_built_at: a finding's kind, severity, staleness and certainty rung move with the clock as well as with the law library, so an instrument becomes a live obligation the moment its effective_date passes, against a law library that has not moved. Send it back on upload_lint_run's compact form, which rebuilds this run at this instant.
findingsYesEvery finding, one per instrument per jurisdiction. Group these into work items before showing them; eight jurisdictions produce a list nobody reads.
activitiesYesThe declared activities this run was evaluated against, de-duplicated.
model_noticeYesLexLint's advisory to the developer on models outside tested_model_families. Not a gate: the lint runs either way.
jurisdictionsYesThe declared jurisdiction slugs this run was evaluated against, normalized.
client_versionYesThe client_version this call sent back, normalized. Null when none was sent.
latest_versionYesThe newest published LexLint bundle, as the server knows it.
update_commandYesThe plugin update command, shown to the developer and not run by the assistant. Present only when update_available is true.
corpus_built_atYesWhen the bulk export this run read was built. Null on the per-slug request path, which reads no manifest and so has no build stamp: null means "not reported here", never "not built".
update_availableYesThree-valued: true means a newer LexLint plugin is published. Null means LexLint learned nothing about your version, which is NOT the same as being current.
lint_procedure_urlYesA link to show the developer: the written LexLint procedure for the lint loop. Set only for a caller that sent X-API-Key and no bundle version; null for a bundle session, which already holds it, and for a signed-in caller.
freshness_window_daysNoThe law library's re-read cadence in days, as the export publishes it. Not a staleness threshold: no finding is judged or marked against it. Null when the law library states none.
lint_procedure_noticeYesWhy lint_procedure_url is set and what that procedure holds, for the developer. Null with it.
tested_model_familiesYesWhich model families LexLint's procedure is exercised against, as lowercase tokens. Nothing about your model is sent to LexLint.
declaration_sensitivityYesThe finding ids that rest on exactly one declared activity, keyed by that activity in declared order: strike a value the developer doubts and these are the findings that go with it. Show it grouped by activity after the findings. A declared activity nothing rests on alone is absent, and {} means no finding rests on one value. Posture findings rest on crawls_web, which is what draws them; the untagged-activity coverage finding rests on the activity it names; other coverage findings rest on no single value.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.3/5.0
Behavior5/5

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

With annotations already declaring readOnlyHint=true and openWorldHint=false, the description adds substantial context beyond them: severity semantics, kind values, certainty.resultset versus certainty.rung, coverage behavior as a warning rather than silent pass, caching behavior, request costs, trial limits, and authentication requirements. It also discloses important behavioral constraints like 'LexLint never reports error' and that omitted forward findings must be disclosed to avoid a silent pass.

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

Conciseness3/5

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

The opening sentence is well front-loaded and identifies the tool's role in the workflow, but the description then becomes a dense wall of long sentences with parenthetical asides and repeated concepts around kind, certainty, and forward findings. The information is mostly useful and earns its place, but it could be structured more crisply and shortened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only lint tool with an output schema, this description is very complete: it explains what findings contain, how severity and certainty should be interpreted, what coverage warnings mean, authentication and metering requirements, and the legal-advice limitation. An agent has enough context to call it correctly, interpret the findings, and avoid misusing forward-looking results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already carries the detailed meaning of activities, jurisdictions, roles, public_sector, regulated_sector, brief, and client_version. The description reinforces that activities and jurisdictions come from set_profile and that declared jurisdictions should be complete, but it does not add much parameter semantics beyond what the schema already provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description immediately states this is 'Step 2 of the lint, and the one that returns findings,' and explains that it returns lint-style findings with obligations, severity, citation, and confidence. It also distinguishes itself from get_law by saying no topic is served by get_law alone and that full law text is one get_law call away.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It establishes the workflow context clearly: pass the activities and jurisdictions set_profile validated, use brief when presenting results to a person, and leave brief out when writing lexlint.yml. It also gives important use boundaries such as 'NOT legal advice and NOT a compliance certification' and that forward findings must never gate a build or merge. It does not explicitly name a competing findings tool or spell out when not to call run_lint, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources