kvasir.legal

by Unknown

Not rated
Website

About

Ground your legal AI on verifiable German, Austrian, Swiss & EU law — resolve, search and verify citations with provenance and pinpoint deeplinks. 440k+ statutes, interactive apps in Claude & ChatGPT.

Details

Author
Unknown
Categories
Other, AI, Search, Knowledge Base

German, Austrian, Swiss and EU law as one canonical object per legal entity — norms, statutes, and case law for the German federal courts, Bavaria, NRW, the Austrian supreme courts and the CJEU — withprovenance, sub-units addressable down to the sentence, ready-made citations and thecitation graph. For the key EU digital acts: delegated & implementing acts and Commission guidelines included, linked to their base act. Model-agnostic: call it over REST, or plug it into any agent as anMCPtool. You bring the reasoning; we bring the ground truth.

Base URLhttps://kvasir.legal· questions?[](https://kvasir.legal/cdn-cgi/l/email-protection#f9919c959596b9928f988a908bd7959c9e9895)<<<[email protected]· new to grounding?Why legal AI needs a grounding layer →· how we measure it:the Grounding Benchmark →

Getting access.Free, no invite needed.Create an account →then confirm your email address, and the dashboard (keys, usage, rotation) is yours. Already signed up?Create a key in your dashboard →No key needed to try the sandbox (20 requests/day).

Building something bigger?Tell me what you need — coverage, volume, endpoints. Design partners lock founding conditions.

One endpoint —https://kvasir.legal/mcp— plugs kvasir into the AI you already work with. Your assistant then searches, resolves and verifies citations against the live corpus instead of answering from memory.

Just want to try it?https://kvasir.legal/mcp/demo— the same seven tools,no key, no signup: 10 tool calls per day and IP. Add it as a custom connector (orclaude mcp add --transport http kvasir-demo https://kvasir.legal/mcp/demo) and ask your assistant to check a draft. Use the main/mcpendpoint for real work — it carries your key or OAuth sign-in and your own limits.

ChatGPT.Settings → Connectors →Advanced → Developer mode→ add MCP serverhttps://kvasir.legal/mcpwith headerX-API-Key→ enable it in your chat's tools.

Microsoft 365 Copilot.Available firm-wide via Copilot Studio: your IT admin addshttps://kvasir.legal/mcponce as a custom MCP action (API key asX-API-Key) — every lawyer in the tenant can then use it in Copilot chats.

Perplexity.On plans with connector support: Settings →Connectors→ add an MCP connector with URLhttps://kvasir.legal/mcpand yourX-API-Key.

Le Chat (Mistral).Settings →Connectors→ add MCP connector → URLhttps://kvasir.legal/mcp+X-API-Key.

Developer tools & agents.Any MCP-capable client speaks tohttps://kvasir.legal/mcp(streamable-HTTP) with your key asX-API-Key— or use plain REST (interactive reference).

claude mcp add --transport http kvasir https://kvasir.legal/mcp --header "X-API-Key: kvk_…"

Claude Desktop(claude_desktop_config.json, viamcp-remote):

{ "mcpServers": { "kvasir": { "command": "npx", "args": ["-y", "mcp-remote", "https://kvasir.legal/mcp", "--header", "X-API-Key: kvk_…"] } } }

Cursor / VS Code(.cursor/mcp.json·.vscode/mcp.json):

{ "mcpServers": { "kvasir": { "url": "https://kvasir.legal/mcp", "headers": { "X-API-Key": "kvk_…" } } } }

Try it without a key:resolve,searchandobjectwork keyless insandbox mode— 20 requests per day, no signup. Just call them:

curl --get "https://kvasir.legal/api/v1/resolve?include=none" --data-urlencode "cite=§ 573 Abs. 2 Nr. 2 BGB"

For real use, send an API key as a header (either form works):

X-API-Key: kvk_your_key Authorization: Bearer kvk_your_key

Keyless calls beyond the sandbox trio (or past the daily 20) get401/429with a JSON hint. The machine-readable contract is public at/api/v1/schema(no key needed).

Connecting from Claude or another MCP client?Just addhttps://kvasir.legal/mcpas a connector — you'll be walked through anOAuth sign-inwith your kvasir account instead of pasting a key. Keys and OAuth work side by side; both count against the same tier.

Two scopes, split along the only line that matters —what your client transmits:

On OAuth sign-in you decide with a checkbox; the scope is bound to that connection and a token refresh never widens it. API keys carry both scopes by default — a key restricted tolegal.readcan be issued on request, and then draft checking is refused with403 insufficient_scoperather than merely discouraged. That is how a connector can be provisioned so it istechnically incapableof receiving client documents. SeeTrust & Security.

No key, no signup — this works right now (sandbox, 20/day):

curl --get "https://kvasir.legal/api/v1/resolve?include=none" --data-urlencode "cite=§ 573 Abs. 2 Nr. 2 BGB"
curl -H "X-API-Key: kvk_…" \ "https://kvasir.legal/api/v1/object/norm:bund:BGB:242?include=all"
{ "uri": "norm:bund:BGB:242", "canonical_uri": "norm:bund:BGB:242", "kind": "norm", "exists": true, "identity": { "title": "§ 242 BGB", "subtitle": "Bundesrecht", "href": "/bgb/242" }, "provenance": { "quelle": "bund", "source": "gesetze-im-internet.de", "derived": false, "version": "" }, "content": { "label": "§ 242", "plain_text": "Der Schuldner ist verpflichtet …", "html": "…" }, "units": [ { "path": "a1", "unit": "abs", "label": "1", "text": "…", "citation": "§ 242 Abs. 1 BGB", "deeplink": "/bgb/242#a1" } ], "relations": { "in": [ … cited-by … ], "out": [ … cites … ] } }

Every legal object is addressed by a stable URI:

quellebund(federal),by(Bavaria),nrw(North Rhine-Westphalia),sn(Saxony),bb(Brandenburg),hb(Bremen),at(Austria),ch(Switzerland),eu. Norm URIs are tolerant:norm:bund:BGB:242resolves the same object as the raw slug; the response'scanonical_urigives the clean form. EU norms useart_Nids (norm:eu:GDPR:art_6, not…:6) — when unsure, go through/api/v1/resolve, which returns the canonical URI. Materials are EU legislative documents — Commission proposals (with explanatory memorandum)andCommission guidelines (typ: "guideline"— interpretive, not binding law) — always linked to the acts they founded, amend or concretise: drafting history, official interpretation, and an early-warning signal for pending changes.

Prefer clicking around? Try theinteractive API reference. Building with an LLM? Point it at/llms.txt.

GET/api/v1/resolve?cite=§ 242 Abs. 1 BGB

Citation in, object out.Parses free-text citations (Art. 6 Abs. 1 lit. f DSGVO,C-311/18) — no URI grammar needed. Returns the pinpoint sub-unit and did-you-mean suggestions when something doesn't resolve.

Ranges.§ 433 f. BGBand§ 433 ff. BGBcome back with arange, and the two are deliberately not treated alike.f.means exactly one further provision, sotois exact — and it follows the statute's own order, where§ 311 f. BGBends at§ 311a, not§ 312.ff.is open-ended: its end is not encoded in the citation, so kvasir returnssuggested_to(the end of the innermost section around the first provision) and marks it as an inference, never as a finding. Whatisprovable is that something follows at all —§ 2385 ff. BGByieldsrange.valid: false, because the BGB ends there and the "ff." has nothing to refer to.

Below the provision the marker binds to the deepest level named —§ 305 Abs. 1 ff. BGBmeans paragraphs,§ 573 Abs. 2 Nr. 1 ff. BGBmeans numbers — and comes back asunit_range. There even "ff." is exact: the provision bounds its own list, so§ 305with three paragraphs resolves "Abs. 1 ff." to paragraphs 1–3, with every covered unit inpaths. The open-endedness above exists only because a statute keeps going after § 433; a provision does not.

Several provisions in one string.§§ 433, 434 BGB,§§ 433-435 BGB,§ 573 Abs. 1, 2 BGBand§ 823 Abs. 1 i.V.m. § 1004 BGBall name more than one provision. Each is resolved: the first as the main object, the rest underalso_citedwith their ownexists. Which level a continuation belongs to follows the deepest one already named —, 2afterAbs. 1is a paragraph, after§ 433a section. Top-levelexistsanswers for the whole citation, so one invented number in the list turns it false rather than passing on the strength of the first hit.

Variants and jurisdiction.§ 263 Abs. 1 Var. 2 StGBresolves down to the paragraph and reportsvariant.addressable: false: Tatvarianten count the alternatives inside a provision's wording, but the statute does not number them, so there is nothing to verify against — kvasir says so instead of inventing an anchor. Separately,&quellen=atrestricts the jurisdiction, which matters for abbreviations that exist more than once:§ 15 StGBis German federal law by default and Austrian only if you ask for it. The filter restricts rather than ranks, so no hit means "not found in that jurisdiction".

Versions.§ 433 BGB a.F.asks for an earlier text than the one in force. kvasir serves consolidated current law, so the answer carriesversion.confirmed: false: the citation is fine, the corpus just cannot evidence it. Superseded texts exist only from kvasir's own first index run and are dated bydetection, not by legal effect — so "which version was in force on 1 Jan 2020" is a question this API does not answer, and says so rather than returning today's text as if it were the answer. Archived predecessors, where they exist, are listed undersupersededand retrievable asnormversion:<id>.

GET/api/v1/relations/<uri>?edge_type=zitiert_norm&limit=50

The case law on a provision.include=relationson an object gives a few examples per edge type plus the true total — for § 823 BGB that total is3,460. This endpoint returns the list itself, paged, so you can actually work through it.direction=in(default) is what cites this,outwhat it cites; the response always includesedge_typeswith counts so you know what you can filter on.

Ordered by authority (PageRank) — leading decisions first — with a stable tie-break, so paging never repeats or skips an entry. That matters here: most edges share a score of 0, and without a total order the same decision would surface on two pages while another never appeared.

POST/api/v1/verify{ "citations": [ … ≤200 ] }or{ "text": "…" }

The hallucination check.Verify every citation in a drafted answer in one call: per-citationverified/unresolvedstatus, canonical URI, source and pinpoint unit.

A pinpoint is part of the claim:§ 573 Abs. 6 BGBcomes backunresolved, because that provision ends at paragraph 4 — withnorm_exists: true,unit_exists: falseand areason, so a client can tell "invented paragraph in a real provision" from "invented provision". The same holds on/resolve:existsanswers for thecited pinpoint, not merely for the provision it sits in, so a gate that checks one flag is never told an invented paragraph is fine. The provision itself still comes back underobject, flaggednorm_exists. Where the paragraph list cannot be established with certainty, the citation staysverifiedand carriesunit_requestedplus a hint instead — kvasir does not claim a gap it cannot prove.

POST/api/v1/check-draft{ "text": "…" }

The grounding gate.One call over a full draft, built to run before an AI answer ships: verifies every citation, checksverbatim quotesagainst the canonical source wording (similarity + source excerpt on deviation), and flags repealed law and pending legislative changes to cited acts. Returnssummary.verdict(pass | warn | fail) plus per-finding severities.

GET/api/v1/object/<uri>?include=…

One object.includeis comma-separated; see below.

POST/api/v1/objects{ "uris": [ … ≤100 ], "include": "content" }

Batch-resolve many URIs in one call — e.g. to ground every citation in a draft at once.

GET/api/v1/search?q=…&kinds=norm,decision&quellen=bund,by,eu&limit=20&offset=0

Free-text search → ranked hits[{uri, kind, title, snippet, score}]. Filter by type (kinds:norm,decision, or opt-inmaterialfor EU legislative materials — proposals and Commission guidelines, distinguished bytyp) and jurisdiction (quellen) so every result slot counts. Paginates viaoffset+has_more; per-source caps bound the result pool at roughly 50 hits — refine the query rather than paging deep. Adegradedfield, when present, lists sub-searches that failed: treat those results as incomplete, not as absence.

GET/api/v1/changes?since=2026-07-01T00:00:00Z&kinds=norm,decision

Delta-sync.Every object changed sincesince, as URIs with timestamps. Continue with the response'snext_cursor(keyset — safe across bulk reindexes; plainnext_sincealso provided). Rows may repeat at page boundaries — keep client upserts idempotent.

GET/api/v1/status— live corpus counts + freshness per jurisdiction (public, cached).

Per source:_updated(last write) vs._checked(last successful check against the official source,includingruns that confirmed nothing changed),check_cadenceandfreshnessper scope. Beyondnormsanddecisions, achecksobject carries the remaining scopes — notablyrepeal: when it was last verified that acts of this jurisdiction are still in force. For a currency gate, that is the scope to watch; a fresh text says nothing about continued validity.

GET/api/v1/schema— the contract, machine-readable (public).

GET/api/v1/openapi.json— full OpenAPI 3.1 spec (public). Import into Postman or generate a client SDK.

The quellen parameter (jurisdiction filter)

Every search accepts a jurisdiction filter — comma-separated, on/api/v1/searchasquellen=(aliasjurisdiction=) and on the MCP toolsearch_legalasquellen. Default is all nine. Filter server-side whenever the question is jurisdiction-specific: every result slot is then spent where the answer actually lives, instead of being crowded out by federal German hits. An unknown code returns400with the valid list rather than silently ignoring the filter.

GET /api/v1/search?q=Datenschutz&jurisdiction=at,ch&limit=5→ Austrian and Swiss hits only. The response echoes the active filter in itsquellenfield, so a client can tell a narrowed search from a full one.

Each tool below is documented in full — parameters, returns, required scope and how it handles the data you send — in theMCP tool reference.

Any MCP client calls the layer natively — endpointhttps://kvasir.legal/mcp(OAuth orX-API-Key). Seven tools:

Errors are JSON:{ "error", "hint", "docs_url" }(429s also carry acode:rate_limited|quota_exceeded|sandbox_limit).401= missing/invalid key ·429= limit reached ·503= brief infrastructure hiccup (your key is fine — retry) ·exists:falsemeans the URI matched nothing (not a server error).

Defaults:120 requests/minand50,000/monthper key (design partners: tell us what you need). Every response carriesX-RateLimit-Limit/-Remaining/-Reset; 429s addRetry-After. Sandbox responses carryX-Sandbox-Remaining.

Server that connects Claude/Cursor to the FatSecret Platform API. Search foods, track your diet, manage recipes, and monitor weight directly from your AI assistant.

Connect Google Trends to Claude or ChatGPT via Two Minute Reports MCP. Analyze search demand, trending topics, and keyword interest to grow visibility.

Eagle MCP Server is a local Model Context Protocol bridge that lets AI assistants (e.g. Cursor, Claude) access your Eagle media library so you can tag, categorize, search, and batch-organize assets with natural language.

A context insertion and search server for Claude Desktop and Cursor IDE, using configurable API endpoints.

MCP server for Anthropic Claude Messages API — chat, vision, web search, extended thinking (Rust)

Manage and coordinate multiple Xcode/Swift projects with features like project tracking, smart search, and analytics.

Provides web search functionality powered by the Claude API from Anthropic.

Connect Claude, ChatGPT, Grok or Cursor to 27.6 crore Indian court case records, orders, judgments and cause lists.

e-Gov法令API v2 をラップした Model Context Protocol (MCP) サーバーです。日本の法令データ(法令一覧・改正履歴・法令本文・添付ファイルなど)をMCP対応クライアント(Claude Codeなど)から検索・取得できるようにします。

good-honker is a free conversational front end to the band Goose's show history, usable from Claude. Ask in plain English about setlists, jam charts, venue stats, song history, and upcoming shows. Every answer is fetched live from the open ElGoose.net API and credited to ElGoose; nothing is stored.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.