open-india-law-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@open-india-law-mcpSearch Supreme Court judgments on fundamental rights"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
open-india-law-mcp
An MCP server that gives any MCP-compatible AI agent (Claude, Claude Code, Claude Desktop, or any other MCP client) structured, correctly-attributed access to Vaquill AI's Open India Law dataset:
12.8M+ court judgments (Supreme Court + all 25 High Courts)
813K+ tribunal/regulator matters
1.1M+ legislation provisions (Central + every State/UT), section by section
It does not download the dataset. Court judgment files alone run to
tens of GB per court, and the full corpus is ~53.6 GB of judgment text plus
463.6 GB of vector embeddings. Instead it uses DuckDB's hf:// support to
run filtered SQL directly against the parquet files on the Hugging Face
Hub, pulling only the row groups and columns a query actually needs.
Why this design ("accessing it rightly")
No hardcoded file list. The dataset can add or rename files between snapshots, so
list_catalogasks the HF Hub what actually exists right now and categorizes it, instead of shipping a guess that goes stale.No guessed schema for judgments. The README documents exact fields for legislation and tribunal records, but not for plain court judgments.
search_judgments/get_judgmentintrospect the real schema at call time (get_schema) and pick the right columns, rather than assuming field names that might not exist.CC BY 4.0 is honored automatically. Every tool response carries an
attributionfield (credit to Vaquill AI / Open India Law, CC BY 4.0) and acaveatfield (point-in-time snapshot, not legal advice, verify againstsource_url/source_pdf_url). An agent doesn't have to remember the license terms — they travel with the data.Scale-aware by construction.
search_judgmentsrequires acourt(scanning all 26 courts in one call isn't something a single query should silently attempt), and every query tool caps results at 200 rows. The genericrun_sqltool refuses anything that isn't a single read-onlySELECT/WITH.
Related MCP server: pk-eli-mcp
Install
Requires Python 3.10+.
git clone <this-repo>
cd open-india-law-mcp
pip install -e .This pulls in mcp, duckdb, and huggingface_hub. The dataset is
public, so no Hugging Face token is required — but if you hit HF rate
limits, set HF_TOKEN in your environment and the server will use it.
Run it — 3 ways
Before any of these: run python smoke_test.py once. It hits the real
Hugging Face API and DuckDB extension CDN and confirms the whole path
works — nothing in this repo could be verified against live data during
development (the build sandbox blocks both hosts), so this is the first
real test.
1. As an MCP server (what Claude Desktop/Code actually run)
open-india-law-mcp
# equivalent: python -m open_india_law_mcp.serverThis starts the stdio MCP server and blocks, waiting for a client to connect over stdin/stdout. You won't see output — that's normal; connect a client (below) rather than running it bare in a terminal to "test" it.
2. Directly from Python — no MCP protocol at all
@mcp.tool() registers a function with the server but returns it
unchanged, so every tool is just a plain importable Python function. Skip
the protocol entirely for a script, notebook, or test:
from open_india_law_mcp import server
catalog = server.list_catalog()
hits = server.search_legislation(query="arbitration", state="central", limit=5)
act = server.get_act(act_id="IND_central_1996_26")Full runnable version: examples/direct_python.py.
3. As a real MCP client, in code
To drive it exactly the way Claude Desktop/Code do internally (spawn as a subprocess, speak MCP over stdio) — useful for testing, or as a template for a non-Claude agent:
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
params = StdioServerParameters(command="open-india-law-mcp")
async def main():
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("list_catalog", {})
print(result.content[0].text)
asyncio.run(main())Full runnable version: examples/mcp_client.py.
Connecting real MCP clients
Claude Code (CLI)
claude mcp add open-india-law -- open-india-law-mcpOr, if it's not on your PATH:
claude mcp add open-india-law -- python -m open_india_law_mcp.serverCheck it registered: claude mcp list. Remove it: claude mcp remove open-india-law.
Claude Desktop
Edit your config file directly — ~/Library/Application Support/Claude/claude_desktop_config.json
on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows:
{
"mcpServers": {
"open-india-law": {
"command": "open-india-law-mcp"
}
}
}If you installed into a virtualenv rather than globally, either use that
venv's full path for command (/path/to/venv/bin/open-india-law-mcp),
or:
{
"mcpServers": {
"open-india-law": {
"command": "python",
"args": ["-m", "open_india_law_mcp.server"],
"cwd": "/path/to/open-india-law-mcp"
}
}
}Restart Claude Desktop after editing the config.
MCP Inspector (interactive debugging, no client needed)
npx @modelcontextprotocol/inspector open-india-law-mcpOpens a browser UI where you can call each tool by hand and see the raw JSON — the fastest way to poke at this without writing any code.
Any other MCP client
This is a standard stdio server; point any MCP-compatible client at the
open-india-law-mcp command the same way you would point it at any other.
Tools
Tool | What it does |
| Lists every court/regulator/state file that currently exists, with its |
| Real column names + types for a file, from |
| Read-only DuckDB SQL against any file(s) from the catalog. Full flexibility, capped at 200 rows. |
| Section-level search of one jurisdiction's Acts. |
| Every section of one Act, in order. |
| Section-level search of one regulator's instruments (SEBI, RBI, ...). |
| Full-text search over one court's judgment chunks. |
| Reassembles a full judgment from its chunks. |
Plus a static resource, open-india-law://about, with the license and
caveats in one place for clients that want to show it up front.
How DuckDB reads parquet straight off the Hugging Face Hub
Nothing here is server-specific — it's plain DuckDB, so you can reproduce
any query from the duckdb CLI with zero Python:
duckdb -c "
INSTALL httpfs; LOAD httpfs;
SELECT act_id, section_number, section_title
FROM read_parquet('hf://datasets/vaquill/open-india-law/in_central_legislation.parquet')
WHERE text ILIKE '%arbitration%'
LIMIT 5;
"The hf:// URI. DuckDB's httpfs extension recognizes
hf://datasets/<repo>/<path> and resolves it to the Hub's actual
CDN/resolve URL under the hood — you never see or construct that URL
yourself. catalog.hf_uri() in this repo just builds the hf:// string;
DuckDB does the resolution.
Why this doesn't download whole files. Parquet stores its schema and
per-row-group statistics (min/max, null counts) in a footer at the end
of the file. httpfs does an HTTP range request for that footer first,
then — for each column/predicate in your query — issues further range
requests only for the row groups whose stats can't rule them out. A
WHERE year = 2023 on a 2 GB file might read a few MB. This is exactly
what lets search_legislation/search_judgments filter multi-GB files in
place instead of streaming them wholesale.
Free-text search doesn't get this for free. ILIKE '%arbitration%'
has no column statistic that can prove a row group doesn't contain the
word — DuckDB has to actually read every row group it can't rule out by
some other predicate. That's why search_judgments requires a court
(one file, not 26) and accepts year_from/year_to: the year filter
prunes row groups first, and only the survivors get scanned for text.
Caching within a connection. duck.py enables enable_object_cache
(keeps parsed parquet footers in memory) and enable_http_metadata_cache
(keeps ETag/size lookups in memory) on every connection it creates. Since
each worker thread reuses one long-lived connection, calling get_schema
then search_legislation against the same file only fetches that footer
once. There's no cross-process or on-disk cache — a fresh server process
starts cold.
Authentication. The dataset is public, so no token is required. If you
hit Hub rate limits, set HF_TOKEN in the environment the server runs in
— duck.py picks it up and registers it as a DuckDB secret
(CREATE SECRET hf_token (TYPE HUGGINGFACE, TOKEN ...)) automatically.
Discovery vs. querying are two different Hub calls. list_catalog
uses huggingface_hub.HfApi.list_repo_files (a small metadata API call,
cached for 15 minutes in catalog.py) to find out what files exist at
all. Actually reading a file's contents is a separate, unrelated path —
DuckDB's own HTTP client via httpfs, not huggingface_hub. The Python
package huggingface_hub is only ever used for that one discovery call.
Performance notes
Narrow before you search: pick one court/state/regulator file, and add a year range when the tool supports it. That's the difference between a sub-second query and one that has to scan a large fraction of a multi-GB file.
Tribunal decisions (CAT, ITAT, NCLT, ...) are ~2.1M scanned PDFs with no text layer per the source dataset — they aren't in the judgment parquet files and this server doesn't attempt OCR. Use
list_catalog/run_sqlagainst whatever tribunal metadata files do exist in the repo.
License
This server's code: MIT (add your own LICENSE file if you want one).
The data it queries is CC BY 4.0 — see attribution.py and the
attribution/caveat fields returned by every tool. The underlying legal
text is Government of India material reproduced under s.52(1)(q) of the
Copyright Act 1957. None of this is legal advice.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables semantic search over Polish court judgments and legislative acts via MCP. Allows LLMs to retrieve legal documents using natural language queries.Apache 2.0
- AlicenseAqualityAmaintenanceMCP server for searching and retrieving Pakistani federal statutes and Supreme Court judgments with structured citations, using static HuggingFace datasets.5Apache 2.0
- AlicenseAqualityDmaintenanceConnects LLMs to the EcourtsIndia Partner API for searching Indian court cases, retrieving orders, reading cause lists, and accessing AI summaries.9MIT
- AlicenseNot gradedqualityDmaintenanceGrounds external agents in public Indian judgments and statutes through MCP, enabling legal search and bounded document packets without requiring the full Roop platform.1MIT
Related MCP Connectors
Public Indian legal search MCP for Roop judgments, statutes, and corpus grounding.
Resolve, search and verify legal citations against the official sources, with provenance.
Connect AI to millions of laws and court cases with the Lawstronaut MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/smridhiwho/india-law-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server