open-india-law-mcp
Click on "Deploy 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.
Available Tools
8 toolsget_actA
Fetch every section of one Act, in section order.
state is optional -- it's inferred from the act_id itself when omitted (e.g. "IND_west_bengal_1947_12" implies state="west_bengal"). Pass it explicitly if that inference is wrong.
| Name | Required | Description | Default |
|---|---|---|---|
| state | No | ||
| act_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses the non-obvious state inference behavior, gives a concrete example, and explains when to override it. It could add more about pagination or errors, but the core behavior is clear and consistent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the core purpose. Every sentence earns its place: the first gives the action, and the second paragraph clarifies an important optional parameter behavior without filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter fetch with an output schema, the description covers what the tool returns, the ordering, and the state inference rule. It does not explicitly point to search_legislation for broader search use cases, but that is a minor gap given the get-by-id nature of the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does well for state, explaining that it is optional, inferred from act_id, and overridable. The required act_id is only illustrated via example rather than formally described, but the example makes its structure sufficiently inferable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fetch every section of one Act, in section order.' It clearly names the scope (every section), the resource (one Act), and the ordering, and it is readily distinguishable from sibling search tools like search_legislation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence gives clear context: use this when you need all sections of a specific Act in order. It does not explicitly name alternatives or state when not to use this tool, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_judgmentB
Reassemble a full judgment from its chunks, ordered by chunk index.
| Name | Required | Description | Default |
|---|---|---|---|
| court | Yes | ||
| case_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the disclosure burden and does add one behavioral detail: the judgment is assembled from chunks in chunk-index order. It does not mention error behavior, what happens if chunks are missing, or any access constraints, so transparency is partial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler, front-loaded with the action, and all words earn their place. It is an appropriate length for such a simple tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although an output schema exists, the definition lacks parameter semantics, usage guidance, and clarification of what 'chunks' means. An agent may infer the call shape from names, but it is not fully equipped to invoke the tool correctly in ambiguous cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not compensate by explaining how case_id or court are used. The property names are self-explanatory at a basic level, but the description adds no parameter-specific meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Reassemble') and a clear resource ('full judgment'), and explains the mechanism of ordering by chunk index. This is distinct from siblings like search_judgments (searching) and get_act (acts).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies use when a complete judgment text is needed, but it does not state when to prefer search_judgments or other alternatives, nor give explicit exclusions or prerequisites. The usage context is only inferable from the purpose statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_schemaA
Return the real column names and types for a parquet file, given the
hf:// URI you got from list_catalog. Use this before run_sql if
you're not sure a field exists -- the plain court-judgment files don't
have a schema documented anywhere.
| Name | Required | Description | Default |
|---|---|---|---|
| file_uri | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. It conveys read-only intent through 'Return' and adds useful context about undocumented schemas, but it does not mention error cases, authentication, or side effects. The core behavior is transparent enough for a schema lookup, but not richly detailed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first sentence states the action and input source, the second provides usage guidance and context. Every clause earns its place and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity, one required parameter, and the presence of an output schema, the description covers what the tool does, where the input comes from, when to use it, and why it may be needed. No critical missing information prevents correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only provides a string title for file_uri, and schema description coverage is 0%. The description compensates by explaining the parameter is an hf:// URI obtained from list_catalog and refers to a parquet file. It lacks an explicit example or format validation, but the single parameter's meaning is effectively conveyed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Return the real column names and types for a parquet file.' It also clearly distinguishes itself from siblings by referencing the hf:// URI from list_catalog and being a schema-introspection step before run_sql.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this before run_sql when unsure a field exists, and notes that plain court-judgment files lack documented schemas. It gives a concrete condition but does not detail exhaustive when-not-to-use scenarios or all alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_catalogA
List the parquet files that actually exist in the dataset right now,
grouped into judgments (by court), regulations (by issuing body), and
legislation (by jurisdiction). Call this first -- it's how you find the
exact court/state/body names the other tools expect, and it hands
back the hf:// URI for each file for use with run_sql.
Set refresh=True to bypass the 15-minute cache and re-check the repo.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral disclosure burden. It reveals useful behavior: the tool reflects the current state of the repo, groups results, returns file URIs, and caches results for 15 minutes with a refresh option. This goes well beyond a simple list operation, though it does not discuss failure modes or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then explains why to call it first, and ends with the parameter behavior. Every sentence earns its place with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter listing tool with an output schema, the description covers the discovery workflow, the returned URI format, grouping semantics, and caching behavior. An agent has everything needed to decide to call it and to understand what it will get back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must add parameter meaning. It does: refresh=True bypasses the 15-minute cache and re-checks the repo. The default false value is provided by the schema, so the description meaningfully supplements the schema rather than repeating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists parquet files that actually exist in the dataset, grouped into judgments, regulations, and legislation. It also distinguishes itself by framing it as the entry point for discovering names and URIs that other tools expect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Call this first' and explains the tool provides the exact court/state/body names and hf:// URIs needed by run_sql and sibling tools. It gives clear when-to-use context but does not enumerate when not to use it or compare against each sibling directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_sqlA
Run a read-only SELECT against one or more Open India Law parquet
files, referenced by the hf:// URIs from list_catalog, e.g.:
SELECT act_id, title, section_number, section_title
FROM read_parquet('hf://datasets/vaquill/open-india-law/in_central_legislation.parquet')
WHERE text ILIKE '%arbitration%' AND act_status = 'in_force'
ORDER BY year DESCOnly a single SELECT/WITH statement is allowed -- no DDL/DML, no
multiple statements. limit is capped at 200 rows regardless of what
the query asks for, since these files can be tens of GB and a filter
still has to scan every row group it can't rule out via column stats.
Narrow with a specific file (one court/state/regulator), a year range,
and an indexed-looking equality filter (act_id, case_id) wherever you
can -- it's the difference between a sub-second query and a slow scan.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and delivers richly: read-only execution, 'only a single SELECT/WITH statement is allowed -- no DDL/DML, no multiple statements,' the hard 'limit is capped at 200 rows' stop, and the scan-cost rationale for tens-of-GB files. No contradiction with annotations exists since none are present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though long, every sentence earns its place: purpose, a fully executable example, hard constraints, the row cap, and performance guidance. Each element of the example teaches a required convention (URI format, read_parquet invocation, filter patterns), so no portion is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema covers return values, freeing the description to focus on behavior, and it covers everything else an agent needs: prerequisites (list_catalog URIs), structural constraints, the 200-row cap, and an optimization strategy for avoiding slow scans. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for both bare parameters, and it does. It explains the required shape of `sql` (single SELECT/WITH, hf:// URI + read_parquet pattern, example query) and the `limit` cap behavior at 200 rows. This fully makes up for the schema's lack of descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource immediately: 'Run a read-only SELECT against one or more Open India Law parquet files.' The concrete example with hf:// URIs and the reference to `list_catalog` make the scope unambiguous and distinguish it from the higher-level search_* siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear operational context: URIs come from list_catalog, and it advises narrowing 'with a specific file (one court/state/regulator), a year range, and an indexed-looking equality filter (act_id, case_id).' However, it never explicitly states when NOT to use this tool in favor of sibling search/get tools, so routing to alternatives is implied rather than exclusionary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_judgmentsA
Full-text search over one court's judgment chunks.
court is required and fuzzy-matched (e.g. "Bombay", "bombay high
court") against list_catalog()['courts'] -- searching all 26 courts in
one call would mean scanning tens of millions of chunks. Narrow further
with year_from/year_to when you can; it prunes row groups instead of
reading them.
Results are individual chunks, not whole judgments -- use get_judgment with the returned case_id to reassemble the full text of any hit.
| Name | Required | Description | Default |
|---|---|---|---|
| court | Yes | ||
| limit | No | ||
| query | Yes | ||
| year_to | No | ||
| year_from | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers: it reveals that court values are fuzzy-matched against list_catalog()['courts'], that year filters prune row groups for efficiency, and that results are chunks rather than complete judgments. This goes well beyond the structured schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core action, and every sentence adds meaning: required parameter, performance tradeoff, filtering guidance, and result shape. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with five parameters, no annotations, and an existing output schema, the description covers the essential decision context: which parameter is required, how to scope the search, why narrowing matters, and how to follow up on a hit. Nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description compensates for court and year_from/year_to by explaining requiredness, fuzzy matching, and performance behavior. Query and limit are less elaborated, but their purposes are reasonably inferable from the full-text-search framing and the schema defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Full-text search over one court's judgment chunks.' It clearly distinguishes from the sibling search tools (search_legislation, search_regulations) by focusing on judgment chunks and requiring a court.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says court is required, explains the fuzzy-matching behavior, warns against searching all 26 courts due to cost, and recommends using year_from/year_to when possible. It also directs the agent to get_judgment for reassembling full judgments from result chunks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_legislationA
Search Indian legislation at the section level for one jurisdiction.
query: free-text search over the section text, act title and section title (ILIKE, so it's a substring match, not ranked relevance).
state: jurisdiction slug, e.g. "central", "kerala", "west bengal". Fuzzy-matched against list_catalog's legislation_by_state keys.
act_id: exact match, e.g. "IND_central_1860_45", if you already know it.
in_force_only: excludes repealed/spent acts by default.
Each result includes source_url -- the authoritative government page
for that exact provision.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No | ||
| state | No | central | |
| act_id | No | ||
| in_force_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full burden and does so well: it discloses that query is an ILIKE substring match rather than ranked relevance, that state is fuzzy-matched, that in_force_only excludes repealed/spent acts by default, and that each result includes an authoritative source_url.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear summary sentence followed by tight bullet points. Every bullet adds meaningful information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, matching behavior, jurisdiction handling, default filtering, and result provenance, which is sufficient for most calls. It does not mention limit/pagination behavior or what happens when neither query nor act_id is supplied, though the output schema likely covers return structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions are absent, so the description compensates for most parameters: query, state, act_id, and in_force_only all receive added semantics with examples. Only limit is left undocumented, which is a minor gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Search Indian legislation at the section level for one jurisdiction.' This immediately distinguishes it from siblings like get_act, search_regulations, and search_judgments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for using the tool, including what type of search it performs and that state values come from list_catalog. It does not explicitly state when not to use it or name alternatives, but the purpose is clear enough for an agent to choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_regulationsA
Search one regulator's instruments at the provision level, e.g. body="SEBI" or body="RBI". Same query semantics as search_legislation -- the regulator files share the same provision schema. Use list_catalog() to see which regulator slugs are currently published.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| limit | No | ||
| query | No | ||
| in_force_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It adds useful context about provision-level granularity and shared schema semantics, but it does not disclose pagination, result ordering, whether only published instruments are returned, or other runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences front-load the tool's purpose and example, then point to the relevant sibling for schema semantics and list_catalog for valid inputs. Every sentence earns its place with no redundant phrasing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The core invocation path is covered: required body parameter, example values, where to find valid slugs, and the relationship to search_legislation. Gaps remain around the optional parameters and behavior, but the output schema and self-explanatory param names reduce the risk of incorrect calls.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for all four parameters. It gives an example for 'body' but does not explain 'query', 'limit', or 'in_force_only'; the reference to 'same query semantics as search_legislation' is helpful only if the agent already knows that tool's parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Search one regulator's instruments at the provision level.' It also distinguishes itself from sibling search tools by emphasizing 'regulator' and by explicitly linking its query semantics to search_legislation while still framing it as a distinct corpus.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent when to use this tool—for regulator instruments—and points to list_catalog() to discover valid body slugs. It does not explicitly say when not to use it versus search_legislation or search_judgments, but the regulator/provision framing makes the intended domain clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
get_act - First observed
get_judgment - First observed
get_schema - First observed
list_catalog - First observed
run_sql - First observed
search_judgments - First observed
search_legislation - First observed
search_regulations
TDQS
Scored across 8 tools
Each tool targets a clearly distinct function: catalog discovery, schema inspection, raw SQL, legislation search, act retrieval, regulation search, judgment search, and judgment reassembly. The search_* and get_* pairs are cleanly separated, and run_sql is explicitly framed as a lower-level alternative rather than a competing high-level search tool.
All tool names follow a consistent verb_noun snake_case pattern: list_catalog, get_schema, run_sql, search_legislation, get_act, search_regulations, search_judgments, get_judgment. The naming convention is uniform and predictable.
Eight tools is well-scoped for a legal research server: three low-level data-access tools and five domain-specific search/retrieval tools. Each tool earns its place and the count is neither thin nor bloated.
Legislation has both search and full-act retrieval, judgments have search and full-judgment reassembly, and regulations have search but no dedicated get_regulation tool analogous to get_act. That is a minor gap, though an agent can work around it using run_sql.
Maintenance
Related MCP Connectors
Public Indian legal search MCP for Roop judgments, statutes, and corpus grounding.
Structured access to 10 major Indian legal texts (BNS, IPC, etc) for AI agents.
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.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables 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.6Apache 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