One address that gives Claude, ChatGPT and your own agents direct access to Georgian legislation, court practice and the legali.ge AI copilot — with answers that cite the exact articles.
Once connected, the assistant decides by itself when to look something up in legali.ge. You just ask in your own words.
🎯
Find the right documents
Describe a situation in any language — find_documents returns the relevant laws, the matching articles and related court practice, ranked by meaning rather than keywords.
⚖️
Court practice
Decisions of the Supreme Court and the Constitutional Court of Georgia, ECtHR case law and Venice Commission opinions, searched by meaning.
📜
Read laws and articles
Metadata, version history, table of contents and the consolidated text of any act from matsne.gov.ge, or a single article with a deep link.
💬
Answers with citations
The legali.ge copilot retrieves statutes and practice and answers with a list of sources — the same engine as on the website.
📝
Draft documents
20 document types — statements of claim, appeals, contracts, NDAs, powers of attorney, demand letters — drafted from a plain description, citing the governing norms.
📂
Your documents and drafts
Upload a contract or a court letter for data extraction, ground answers in it, and edit documents in the legali.ge editor with revision history.
Try these prompts
Paste one into Claude or ChatGPT after connecting. Mentioning legali.ge helps the assistant pick the right tools.
Using legali.ge, find the articles of the Civil Code of Georgia and Supreme Court practice on getting a rental deposit back when the landlord refuses. Quote the articles and give links.
I was dismissed after three years of work without written notice. What does the Labour Code of Georgia say about compensation and the deadline for going to court? Cite the articles via legali.ge.
Read article 128 of the Civil Code of Georgia (document 31702) on legali.ge and explain in plain words which limitation periods apply to a claim for an unpaid loan.
Draft a demand letter to a shop that sold me a defective washing machine and refuses to replace it, under the Georgian law on consumer rights protection. Use legali.ge and leave placeholders for names and dates.
Quick start
The same address works in every client. You approve access once on legali.ge — your password is never shared with the app — and the connection stays active until you revoke it.
You need a legali.ge account (free — sign up). A free account includes a monthly allowance of MCP units and 10 trial AI requests.
claude.ai and Claude Desktop — Pro, Max, Team and Enterprise plans
Open Settings → Connectors.
Click “Add custom connector”.
Name it “legali.ge” and paste the MCP server address.
Click “Connect” — a legali.ge page opens: check the app name and click “Allow”.
Server address
https://mcp.legali.ge/mcp
On Team and Enterprise plans an organisation owner may have to add the connector. Menu names may differ by plan/version.
ChatGPT — plans that support custom connectors (developer mode)
Open Settings → Apps & Connectors → Advanced and turn on Developer mode.
Back in Apps & Connectors, click “Create” (or “Add connector”).
Enter the name “legali.ge”, paste the address into “MCP server URL” and choose OAuth authentication.
Save — a legali.ge page opens: check the app name and click “Allow”.
MCP server URL
https://mcp.legali.ge/mcp
Menu names may differ by plan/version.
Sign in through the browser (recommended):
shell
claude mcp add --transport http legali https://mcp.legali.ge/mcp
Then run /mcp in Claude Code, pick legali and sign in — a legali.ge page opens in your browser.
Or with an API key (for servers and CI, no browser):
In Cursor: Settings → MCP → Add new MCP server (or the file ~/.cursor/mcp.json). Clients that support OAuth need only the url, without headers.
Replace lgk_… with a personal API key — create one in your account under AI connections.
Any HTTP client can call the server: POST one JSON-RPC message per request with a personal API key. The response is a single JSON object (no SSE stream).
1. Initialize (optional for this stateless server, but standard MCP clients send it):
The result carries the data twice: as JSON text in content[0].text and, for objects, as structuredContent.
Replace lgk_… with a personal API key — create one in your account under AI connections.
Authentication
There are two ways to authorize: OAuth for apps that support it (Claude, ChatGPT, Claude Code and most modern clients), and personal API keys for everything else.
OAuth — connect once
You add the server address in the app.
The app opens legali.ge in your browser. If you are signed in, you see which app asks for access and the address it will return to.
You click “Allow”. The app receives tokens tied to your account — never your password.
The app refreshes its tokens automatically. It stays connected as long as you use it at least once every 90 days, until you revoke it in your account.
Personal API keys
An API key lgk_… is for clients that can only send a header — scripts, servers, CI, Cursor, Claude Code without a browser. Send it as Authorization: Bearer lgk_…. The key acts as you and spends your plan’s allowance.
Create a separate key per device or integration, named so you recognise it; revoke it as soon as it is no longer needed.
The key is shown once. legali.ge stores only its SHA-256 hash, so a lost key cannot be recovered — revoke it and create a new one.
Keep keys in environment variables or a secret manager — never in a repository or in browser code.
Issuer: https://mcp.legali.ge. Discovery: /.well-known/oauth-protected-resource (RFC 9728) and /.well-known/oauth-authorization-server (RFC 8414; also served as /.well-known/openid-configuration).
Dynamic client registration (RFC 7591): POST /oauth/register. Redirect URIs: https, http loopback (any port, RFC 8252) or a private-use scheme.
Authorization code with PKCE — S256 only; codes are single-use and expire in 10 minutes. Endpoints: /oauth/authorize, /oauth/token, /oauth/revoke. Scope: mcp.
Access token lga_…: 1 hour. Refresh token lgr_…: 90 days, rotated on every use, and every refresh extends the window — so an app in regular use never has to reconnect. A just-used refresh token is accepted again for 120 s to survive network retries.
A call without a token or with an expired one gets 401 with WWW-Authenticate: Bearer resource_metadata="…", which tells the client where to start the flow.
Revoking a connection in your account invalidates its access and refresh tokens immediately.
Tools reference
Generated from the server’s own definitions (gelaw-mcp 0.2.0). Descriptions and parameter schemas are shown in English exactly as the server sends them to the AI; the one-line summaries are ours.
On the hosted server every call needs a connection (OAuth or API key). The account badge marks tools that work with your personal data or metered databases; the others serve public data.
Picks the laws, articles and court practice relevant to a question — without writing an answer.
Select the documents relevant to a situation or question — WITHOUT generating an answer. Understands the query (domains, Georgian legal terms), searches laws by meaning (vector indexes + LLM rerank), court practice (Supreme/Constitutional Court, ECtHR, Venice Commission) and the curated legal-concept map, and returns ranked laws with the matched article, practice items and anchor articles. Use it to build your own research set, then read texts with get_law / get_article. Prefer it over search_laws for natural-language queries in any language. Costs 10 MCP units.
Parameters: find_documents
Name
Type
Req.
Default
Description
query
string
yes
—
Situation or question in any language (max 2000 chars).
limit
integer
—
10
Max laws to return. min 1 · max 30
lang
string
—
"ru"
Language for the query-understanding summary. One of: karuen
Searches Supreme Court, Constitutional Court, ECtHR and Venice Commission practice by meaning.
Search court practice by meaning: Georgian Supreme Court decisions, Constitutional Court judgments, ECtHR case law and Venice Commission opinions. Returns ranked items with an excerpt and the source link (ECtHR/Venice: short excerpt + official link only). Costs 2 MCP units.
Parameters: search_court_practice
Name
Type
Req.
Default
Description
query
string
yes
—
Legal issue in any language.
sources
array<string>
—
—
Subset of sources; default all. One of: supremeconstcourtechrvenice
Reads a law: metadata, versions, table of contents or the consolidated text page by page.
Read a law / legal act by its matsne document id: metadata (title, type, status, registration code, issuer, dates, list of historical versions), the table of contents (articles with chunk_key for get_article) and/or the consolidated text, paged by characters (follow next_offset). Costs 1 MCP unit.
Parameters: get_law
Name
Type
Req.
Default
Description
doc_id
string
yes
—
Numeric matsne document id, e.g. '31702' (Civil Code).
include
array<string>
—
—
Parts to return; default ['meta','toc']. One of: metatoctext
offset
integer
—
0
Text offset (characters) — pass next_offset to continue. min 0
One article of a law by number or chunk_key, with a deep link.
Read one article of a law: pass doc_id plus either chunk_key (from get_law toc / find_documents, e.g. 'art_128') or the article number ('128', '128_1'). Returns the article title, full text and a deep link. Costs 1 MCP unit.
Free full-text search over the Georgian legal corpus, with filters.
Full-text search over the Georgian legal corpus (matsne.gov.ge). Returns matching documents with title, date, type, status, issuer, registration code and a relevance score. Use the returned id with other tools.
Parameters: search_laws
Name
Type
Req.
Default
Description
query
string
yes
—
Search terms (Georgian or transliterated).
limit
integer
—
20
min 1 · max 200
document_type
string
—
—
Filter by document type (e.g. 'law', 'order').
status
string
—
—
Filter by status (e.g. 'active').
issuer
string
—
—
Filter by issuing authority.
reg_code_prefix
string
—
—
Filter by registration-code prefix; comma-separated for multiple.
Documents similar to a given law: predecessors, implementing acts, amendments.
Documents most similar to a given law (semantic neighbours from the legali.ge document graph) — predecessors, implementing acts, amendments and sister regulations. Free (public data).
The legali.ge AI copilot: an answer on Georgian law with cited sources.
Ask the legali.ge AI legal copilot a question about Georgian law. It retrieves relevant statutes and court practice and answers with citations (the sources array). Answers in the language of the question. Blocks until the answer is ready unless wait=false.
Parameters: ask_legal_question
Name
Type
Req.
Default
Description
question
string
yes
—
The legal question (max 5000 chars).
document
string
—
—
Optional matsne document id to focus the answer on one law.
Drafts a legal document (20 types) from a plain description, citing the norms.
Draft a Georgian legal document from a plain-language description. The backend classifies the case, retrieves the governing statutes and produces a structured draft (markdown) with citations. Blocks until ready unless wait=false. This is the most expensive operation.
Parameters: generate_legal_document
Name
Type
Req.
Default
Description
question
string
yes
—
Description of the situation / what the document must accomplish.
document_type
string
—
"lawsuit"
One of: lawsuitcomplaintappealapplicationcontractpower-of-attorneypetitionobjectionreceiptwillconsentemployment-contractndacompany-chartermeeting-minutesdemand-letternoticesettlement-agreementacceptance-actinvoice
Fetches the result of a long AI job by request_id; waits up to ~45 s.
Fetch the result of an ask_legal_question / generate_legal_document / canvas_ai_edit job by its request_id. Waits up to ~45 s for a job that is still running (wait=false: check once). Returns {status:'processing'} if it is still not ready — call again with the same request_id.
Shows what is left of your AI requests and MCP units, plus the price list.
Your remaining allowances: AI requests (ask / generate / canvas AI — trial, subscription, packages) and MCP data units for this month, plus the price list. Free.
Uploads a PDF, image or text (≤ 4 MB) for structured extraction.
Upload a personal legal document (PDF, JPEG, PNG, WebP or text, <=4MB). The backend extracts structured data asynchronously; poll get_user_document for status. Provide either data_b64, or (local stdio only) a filesystem path.
Parameters: upload_user_document
Name
Type
Req.
Default
Description
filename
string
—
—
content_type
string
—
—
MIME type; inferred from filename/path if omitted.
Creates an editable document, optionally from a template or your own text.
Create a new editable document canvas. Optionally seed it from a document type template and/or initial content. Returns the canvas metadata (including id and headRev).
Parameters: create_canvas
Name
Type
Req.
Default
Description
document_type
string
—
—
Template to seed from (see generate_legal_document types).
Reads a document: metadata, content, chat, any revision.
Fetch a canvas: metadata, content and/or chat thread. Use fields to select what to return; omit rev for the latest revision. Read headRev here before calling save_canvas / restore_canvas.
Saves a new revision of a document (optimistic locking by base_rev).
Save an edited canvas body as a new revision. base_rev MUST equal the current headRev (read it via get_canvas) — a mismatch is a 409 conflict. op_id is auto-generated if omitted.
Parameters: save_canvas
Name
Type
Req.
Default
Description
canvas_id
string
yes
—
base_rev
integer
yes
—
The headRev you edited from.
content
string
yes
—
The full new document body.
op_id
string
—
—
Idempotency key (UUID); auto-generated if omitted.
summary
string
—
—
Short change summary for the version list.
filled
array<integer>
—
—
Indices of placeholders filled by this edit.
JSON schema
inputSchema
{
"type": "object",
"properties": {
"canvas_id": {
"type": "string"
},
"base_rev": {
"type": "integer",
"description": "The headRev you edited from."
},
"content": {
"type": "string",
"description": "The full new document body."
},
"op_id": {
"type": "string",
"description": "Idempotency key (UUID); auto-generated if omitted."
},
"summary": {
"type": "string",
"description": "Short change summary for the version list."
},
"filled": {
"type": "array",
"items": {
"type": "integer"
},
"description": "Indices of placeholders filled by this edit."
}
},
"required": [
"canvas_id",
"base_rev",
"content"
],
"additionalProperties": false
}
AI edit of a document: fill placeholders, redraft a selection or generate from scratch.
Ask the AI to edit a canvas in place (fill placeholders, redraft a selection, or generate from scratch with mode='generate'). The edit is committed server-side as a new revision. Blocks for the result unless wait=false; afterwards read the new content with get_canvas.
Parameters: canvas_ai_edit
Name
Type
Req.
Default
Description
canvas_id
string
yes
—
base_rev
integer
yes
—
Current headRev (from get_canvas).
question
string
yes
—
Instruction for the AI editor.
mode
string
—
""
'generate' to (re)generate the whole document. One of: ""generate
selection
string
—
—
Selected text the edit should target (<=3000 chars).
MCP uses the same account and the same balance as the website. There are two wallets, and nothing is charged twice.
✨ AI requests
ask_legal_question, generate_legal_document and canvas_ai_edit spend one AI request each — the same wallet as the copilot on the website: 10 trial requests, then your subscription’s monthly requests, then request packs.
📚 MCP units
Database tools that are not free on the website — AI document selection, court-practice search and machine reading of texts — spend MCP units. Every plan includes a monthly allowance (the free tier too); unit packs never expire and are used after the allowance.
🔎 Free
Full-text search, related documents, suggested questions, popular queries, your own chats, documents and canvases, get_usage, get_chat_response.
AI edit of a document: fill placeholders, redraft a selection or generate from scratch.
1 AI request
All other tools
free
Monthly allowances
Live figures from the current price list:
Plan
MCP units / month
AI requests / month
Price / month
Unit packs (never expire):
Unit metering is currently in test mode: usage is counted but not blocked.
Current plans and unit packs are listed on the tariffs page.
The monthly allowance resets on the 1st of each calendar month (UTC) and does not roll over. Packs are spent only after it runs out.
Units are charged only after a successful response — errors and timeouts are free.
When a wallet runs out, the tool returns an error result (isError) with a clear message and a top-up link; the assistant shows it to you. Nothing is charged automatically.
Ask the assistant to run get_usage to see both balances and the price list.
Building an integration or an agent for a law firm? The api plan has a large unit allowance and AI requests for automated research.
Transport: MCP Streamable HTTP, revision 2025-06-18 (also negotiates 2025-03-26 and 2024-11-05). Endpoint: POST https://mcp.legali.ge/mcp.
Stateless: every request is authorized on its own, no Mcp-Session-Id is issued, and each JSON-RPC request gets one application/json response — no SSE stream. GET /mcp answers 405; notifications answer 202.
Methods: initialize, ping, tools/list, tools/call. Capabilities: tools only (listChanged: false) — no resources, prompts or sampling.
JSON-RPC batches (an array of messages) are accepted and answered with an array, but the 2025-06-18 spec dropped batching, so generic clients should not rely on it.
CORS is open (Access-Control-Allow-Origin: *), so browser-based clients can call the endpoint directly — but never ship an API key to a browser.
Results: content[0].text holds the JSON as text; object results are also in structuredContent. Tools carry annotations (readOnlyHint, destructiveHint, …) so clients can ask for confirmation before deleting.
Server instructions (sent to the AI)
Tools for the legali.ge Georgian legal database: select relevant laws, articles and court practice for a query, read law texts, ask the AI legal copilot (answers cite sources), draft legal documents, manage personal documents and edit document canvases. Public tools work anonymously; tools marked '(requires authentication)' need a Cognito ID token. To research yourself: find_documents → get_law / get_article / search_court_practice (metered in MCP units; get_usage shows the balance). For a finished cited answer use ask_legal_question; to produce a filing use generate_legal_document or the canvas_* tools (these spend AI requests).
Long-running AI jobs
A copilot answer usually takes 1–2 minutes and a drafted document longer — more than most gateways keep a request open. So ask_legal_question, generate_legal_document and canvas_ai_edit wait up to about 50 seconds. If the result is not ready by then, they return a normal (non-error) result:
structuredContent
{
"status": "processing",
"request_id": "…",
"next": "The job is still running … Call get_chat_response with this request_id to get the result."
}
Then call get_chat_response with that request_id: it waits up to about 45 seconds more and returns the same “processing” object if the job is still running — call it again. When done, it returns status "ready" with the answer and its sources. Pass wait: false to submit without waiting (e.g. to run several jobs in parallel) and collect results later with get_chat_response. The AI request is spent once per job, not per poll.
python
import json, os, urllib.request
MCP = "https://mcp.legali.ge/mcp"
KEY = os.environ["LEGALI_KEY"] # lgk_… (a personal API key)
def call(name, arguments, _id=[0]):
_id[0] += 1
body = {"jsonrpc": "2.0", "id": _id[0], "method": "tools/call",
"params": {"name": name, "arguments": arguments}}
req = urllib.request.Request(MCP, data=json.dumps(body).encode(), method="POST", headers={
"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"})
with urllib.request.urlopen(req, timeout=90) as r:
result = json.load(r)["result"]
if result.get("isError"): # e.g. quota exhausted (status 402)
raise RuntimeError(result["content"][0]["text"])
return result["structuredContent"]
res = call("ask_legal_question", {"question": "landlord refuses to return the rental deposit"})
while res.get("status") == "processing": # not ready within ~50 s
res = call("get_chat_response", {"request_id": res["request_id"]})
print(json.dumps(res, ensure_ascii=False, indent=2))
Errors
What
Meaning
What to do
HTTP 401 WWW-Authenticate
Token missing, expired or revoked
OAuth clients refresh the token or re-run the flow; with an API key, check that it has not been revoked.
Check the message format (e.g. tools/call without name → -32602).
isError: true
The tool ran but the backend refused: text “Error: … (status N)”
400 invalid arguments · 402 quota exhausted (the message names the wallet and links to top up) · 404 not found · 409 canvas revision conflict (re-read headRev with get_canvas).
Usage tips
Research pattern: find_documents once (10 units) → get_article for the articles you actually need (1 unit each) → search_court_practice for a specific point (2 units). Reading a whole code page by page with get_law is rarely needed.
search_laws is free: use it when you know the title or registration code; use find_documents for natural-language questions.
Cache get_law / get_article results on your side: a consolidated text changes only when the act is amended, and get_law meta lists its versions.
Canvas saves are optimistic: read headRev with get_canvas and pass it as base_rev; on 409, re-read and retry.
Check your balance with get_usage before large automated jobs.
Changelog
0.2.0 — database tools metered in MCP units (find_documents, search_court_practice, get_law, get_article, get_usage); OAuth 2.1 with dynamic client registration and rotating refresh tokens; personal API keys; the mcp.legali.ge address; long AI jobs continue through get_chat_response.
0.1 — first release: 22 tools (search, copilot, document drafting, personal documents, editor) with legali.ge account tokens.
Security & privacy
The consent page shows the app’s name and the address it will return to, so a look-alike app is visible before you click “Allow”.
A connected app acts as you: it can do what you can do on legali.ge — search and read, spend your AI requests and MCP units, view, create and delete your chats, documents and canvases. Connect only apps you trust.
Your password is never given to the app. Approving connections and managing keys requires a real signed-in session on legali.ge — an MCP token cannot approve another app.
Revoking a connection or key in your account takes effect immediately. If a legali.ge account is deleted or blocked, all its connections stop working.
The MCP server is a thin proxy over the same API as the website: it inherits every ownership check and rate limit and holds no data of its own. Each backend call carries a short-lived (10-minute) signed assertion for your account.
ECtHR and Venice Commission documents are returned as a short excerpt with a link to the official text, for copyright reasons.
Answers are generated by AI from legal sources and can contain mistakes. The official source of Georgian legislation is matsne.gov.ge; check the cited articles before relying on them.
In Claude, custom connectors are available on Pro, Max, Team and Enterprise plans (claude.ai and Claude Desktop); on Team/Enterprise an organisation owner may need to add it. In ChatGPT, custom MCP connectors are part of developer mode, which is available on some plans only — check Settings → Apps & Connectors. Claude Code, Cursor and other developer tools work with any legali.ge account.
Do I pay twice if I already have a subscription?
No. An AI answer through Claude or ChatGPT spends one request from the same balance as on the site; MCP units are only for database operations and come with your plan’s monthly allowance.
How do I disconnect an app?
Account → AI connections → “Revoke” next to the app (or the key). Access stops immediately; to connect again you approve it anew.
Which languages does it understand?
Ask in any language. The copilot answers in the language of the question, find_documents and search_court_practice accept queries in any language, and suggested questions come in 9 languages. The texts of laws and decisions are in Georgian, as published.
The assistant says the answer is still “processing”. What now?
Nothing is wrong: long answers continue in the background. The assistant should call get_chat_response with the same request_id — ask it to if it doesn’t. The request is spent once.
OAuth or API key — which should I use?
OAuth whenever the client supports it: nothing to copy, tokens refresh themselves, and you can revoke each app separately. API keys are for scripts, servers and clients that only accept a header.
Can I run the server locally?
The server also has a local stdio mode (python -m gelaw_mcp.server_stdio) authenticated with a legali.ge account, for development and self-hosted setups. Metering happens on the legali.ge backend, so prices and limits are the same; for most people the hosted address is simpler.
Is this legal advice?
No. legali.ge is a legal information service: AI answers cite sources but can be wrong, and the official text is published on matsne.gov.ge. For a decision that matters, consult a lawyer.