datajud-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., "@datajud-mcpList movements for CNJ case 000123456789-00 and show me the case details."
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.
datajud-mcp
An MCP server for DataJud, the official public API of Brazil's National Council of Justice (CNJ) for court case metadata. It ships with an example Claude agent that turns a case number into a structured status report and flags movements a lawyer should look at.
DataJud exposes the public metadata of cases from 91 Brazilian courts through a single Elasticsearch endpoint. The API is slow, loosely documented, and has a few traps that silently return wrong answers. This project wraps it in typed, validated, retry-safe tools that any MCP client (Claude Desktop, Claude Code, your own agent) can use. The agent shows how to build on top of them with production habits: bounded loops, structured outputs, cost gates and offline evals.
Contents
Related MCP server: DataJud (CNJ)
Architecture
flowchart LR
subgraph Clients
CD[Claude Desktop / Claude Code]
AG["Example agent<br/>examples/agent"]
end
subgraph Server["datajud-mcp (stdio)"]
T["Tools<br/>get_case · list_movements<br/>search_cases · list_courts"]
V["zod validation<br/>CNJ check digits · court resolution"]
N["Normalization<br/>dates · drifting fields · TPU hints"]
subgraph Client["DataJudClient"]
RL["Sliding-window limiter<br/>120 req/min"]
RT["Retry: full-jitter backoff<br/>per-attempt + total deadline"]
F[fetch + AbortSignal]
end
end
DJ[("CNJ DataJud<br/>Elasticsearch API")]
LLM[[Claude API]]
CD -- MCP --> T
AG -- MCP --> T
AG -- "tool use +<br/>structured output" --> LLM
T --> V --> RL --> RT --> F -- "POST /api_publica_*/_search" --> DJ
F --> N --> TThe agent runs a zero-token pre-check before involving Claude:
sequenceDiagram
participant CLI as Agent CLI
participant MCP as datajud-mcp
participant S as State (.datajud-state)
participant C as Claude
CLI->>MCP: list_movements(limit=1)
MCP-->>CLI: counts + latest timestamp per instance
CLI->>S: compare with last fingerprint
alt unchanged
CLI-->>CLI: print "skipped", 0 tokens
else changed or first run
loop at most AGENT_MAX_ITERATIONS
CLI->>C: messages + MCP tools + JSON schema
C-->>CLI: tool_use (get_case, list_movements)
CLI->>MCP: call tools
end
C-->>CLI: CaseSummary JSON
CLI->>S: save fingerprint + summary
endMCP tools
All tools are read-only, validate their input with zod, declare an outputSchema, and return structuredContent plus a JSON text fallback. Failures come back as isError results whose message says what to do next (e.g. "check digits are 36 but should be 35", "CNJ rotated the public key, copy the current one from …").
Tool | Input | Output |
|
|
|
|
|
|
|
|
|
|
|
|
court is optional for case lookups because the court can be derived from the CNJ number (NNNNNNN-DD.AAAA.J.TR.OOOO: segment J, court TR). Each movement carries a hint with a plain-English meaning for common codes from CNJ's procedural tables (TPU). DataJud only returns leaf names such as "Provisório" or "Confirmada", which mean nothing without context.
Quickstart
Requires Node.js 22.12 or newer.
git clone https://github.com/JoaoLuizRTelo/datajud-mcp.git
cd datajud-mcp
npm install
cp .env.example .env # then fill in the values below
npm run buildVariable | Required | Notes |
| yes | CNJ's public key, published at datajud-wiki.cnj.jus.br/api-publica/acesso. It is not a secret, but CNJ rotates it, so copy the current value from there. |
| agent and evals only | Never commit it. |
| no | Per attempt (default 90 s) and across retries (default 180 s). |
| no | Defaults 4 and 120 (the cap allowed by the Terms of Use). |
| no | Defaults |
Run the server
npm start # compiled (dist/)
npm run dev # from source with tsxThe server speaks MCP over stdio and logs only to stderr.
Connect it to Claude Code
claude mcp add datajud --env DATAJUD_API_KEY=<public key> -- node /absolute/path/to/datajud-mcp/dist/src/index.jsDataJud queries often take 20–60 s. Claude Code's default MCP tool timeout is long, but if you set MCP_TOOL_TIMEOUT (or a per-server timeout), keep it above ~200 s so retries can finish.
Connect it to Claude Desktop
Add this to claude_desktop_config.json. On macOS it's in ~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\:
{
"mcpServers": {
"datajud": {
"command": "node",
"args": ["/absolute/path/to/datajud-mcp/dist/src/index.js"],
"env": { "DATAJUD_API_KEY": "<public key>" }
}
}
}Then ask: "What's the status of case 0713383-43.2025.8.07.0006?"
Example agent
npm run agent -- 0713383-43.2025.8.07.0006
npm run agent -- 1035289-48.2022.8.26.0602 --court stj # read the superior court's record
npm run agent -- 0713383-43.2025.8.07.0006 --force # bypass the pre-check
./scripts/demo.sh # the two-run demo used for the GIFThe CLI starts the MCP server as a child process, runs the pre-check, and if anything changed lets Claude call the tools and answer with a schema-constrained CaseSummary.
Run it again with nothing new on DataJud and no LLM call is made:
{
"skipped": true,
"reason": "No new movements since <time of the last successful run>.",
"previousSummary": { "...": "the CaseSummary from that run" },
"tokensSpent": 0
}Design decisions
Full-jitter exponential backoff. A retry waits a random time in [0, min(20 s, 1 s · 2^attempt)] (AWS: "Exponential Backoff and Jitter"). DataJud is one shared public cluster; synchronized retries from many clients make overload worse, and jitter spreads them out. Retry-After is honored when present. Retried: 429, 5xx, timeouts, network errors, Elasticsearch thread-pool rejections and partial-shard responses. Never retried: 400, 401, 404 and client cancellation.
Two time limits. Each HTTP attempt has its own timeout, and the whole search has a total deadline. Without the second one, four slow attempts could stall a tool call for six minutes. The per-attempt timeout is clipped to the time left.
Sliding-window rate limiter. The Terms of Use cap usage at 120 requests/minute. A token bucket can burst to 2× that across a window boundary; a sliding window can't.
Progress heartbeats. The MCP TypeScript SDK's default request timeout is 60 s, which DataJud regularly exceeds. While a tool waits, the server sends notifications/progress every 10 s if the client asked for progress, so clients using resetTimeoutOnProgress keep waiting. Cancellation flows the other way: the MCP request's AbortSignal aborts the HTTP request.
Manual agent loop with a max-iterations guard. The agent owns its loop instead of using the SDK's tool runner. That keeps the failure modes explicit: after AGENT_MAX_ITERATIONS model calls it throws AgentDidNotConvergeError (exit code 2) with the tool calls it made, and refusal, max_tokens and pause_turn each have a defined outcome. Parallel tool calls run concurrently and are answered in one turn. Tool errors go back to the model as is_error results instead of crashing the run.
Structured output. The final answer is constrained with output_config.format (betaZodOutputFormat(CaseSummary)) and re-validated with zod, so callers always get the same shape. The status categories and the attention rule are written into the prompt, which makes them consistent and testable.
Pre-check before the LLM. Monitoring is mostly "nothing happened". The CLI fetches movement counts and the latest timestamp per instance through MCP, compares that fingerprint with the last successful run, and skips Claude when nothing changed. State is saved only after a successful summary, so a failed run is retried next time.
Prompt caching. The system prompt is static and the date lives in the user message, so tools, system prompt and growing history form a cacheable prefix across loop iterations.
Lenient in, strict out. DataJud's live responses drift from its own glossary (string vs number codes, compact vs ISO dates, renamed fields). Raw responses are parsed with permissive zod schemas and normalized into one strict, English-named shape that the tools declare as outputSchema.
What I learned about the live API
I checked each of these against the live API while building, and each is handled in code and covered by a test.
ISO dates silently match nothing.
dataAjuizamentois stored asyyyyMMddHHmmss, although the glossary shows ISO. A range query with2023-01-01returns 0 hits with no error, while the same range as20230101000000returned 970.search_casestakes ISO dates and converts them.HTTP 200 can mean partial data. Under load DataJud answers
200with_shards.failed > 0. An existing case on a failed shard would look "not found". The client treats this as retryable and never returns partial hits.Queries are slow. 18–55 s per query is normal and HTTP 504s happen. The retry path recovered from back-to-back 504s during development.
One number, several records. A case can have one document per instance (e.g.
JEandTR), and superior courts keep the origin court's number. So an STJ record is read withcourt: "stj", not the court derived from the number.No STF. The Supreme Court isn't in the public API. STF numbers get an explicit error instead of a confusing 404.
Testing and evals
npm test # offline: no network, no API keys
npm run check # lint + format + typecheck + tests (what CI runs)
npm run evals # real Claude API, recorded DataJud dataUnit tests: CNJ check digits, court resolution for every justice segment, query builders, date normalization, retry/backoff (deterministic random and clock), rate limiter, error mapping, config.
Integration tests: the real MCP server over an in-memory transport, backed by the real HTTP client with scripted responses (503 → 200, 401, 404, timeouts, partial shards), plus a stdio end-to-end test that spawns the server against a local fake DataJud. The agent is tested with a scripted model against the real MCP server: tool bridging, parallel calls, unknown tools, non-convergence, refusals, schema violations and the pre-check skip path.
Fixtures: DataJud responses recorded with
npm run record-fixture(public metadata only; DataJud has no party data).Evals: 11 recorded cases covering every status category, multi-instance cases, a superior-court record and a not-found case. Grading is deterministic and touches only structured fields:
found,statusCategory,needsLawyerAttentionwhere it is unambiguous, and required movements. Evals run against a fixed "today" so recency rules are reproducible. They are not part of CI because they need a paid API key.
Limitations
Not legal advice.
needsLawyerAttentionis a heuristic over movement codes and dates. DataJud has no deadlines, document text or party data, so the agent cannot know whether a deadline applies to your client.Data freshness. Courts push data to DataJud on their own schedule;
lastUpdatedAtis often days or weeks behind the court's own system.Beta API. CNJ labels the public API as beta, may change it or rotate the public key without notice, and does not guarantee accuracy.
Latency. 20–60 s per call is typical. Interactive clients need a generous tool timeout.
TPU hints are partial. The hint table covers codes seen in real responses, not the full TPU catalog; unknown codes fall back to the Portuguese name.
No STF and no free-text search. Searches filter by codes, class name and dates; the API has no full-text search over decisions.
Terms of use
This project uses only the official public API with CNJ's published key: no scraping, no undocumented endpoints. The Terms of Use allow non-commercial use only (clauses 3.3 and 3.8) and cap traffic at 120 requests/minute (3.13), which the client enforces. Clause 3.9 asks users to inform CNJ about material derived from the API that is made public. The state files store public case metadata only, no personal data (LGPD, section 4).
Project structure
src/
index.ts stdio entrypoint
server.ts McpServer + tool registration
config.ts env validation
datajud/ HTTP client, retry, rate limiter, errors, CNJ numbers, courts, queries, schemas, TPU hints
tools/ one file per MCP tool
examples/agent/ Claude agent: loop, prompts, output schema, pre-check, CLI
evals/ cases, fixtures, grader, runner
test/ unit and integration tests
scripts/ fixture recorder, demo script, VHS tapeLicense
Available Tools
4 toolsget_caseGet case by CNJ numberARead-onlyIdempotent
Fetch the public cover data of a Brazilian court case from CNJ's DataJud: class, subjects, court unit, filing date, instance and its most recent movement. Returns one record per instance. Party and lawyer names are not available in DataJud. Expect 20-60 s latency.
| Name | Required | Description | Default |
|---|---|---|---|
| court | No | DataJud court alias, e.g. 'tjsp', 'trf1', 'trt2', 'tre-sp', 'stj'. Optional when looking up a case number: the origin court is derived from the number. Pass it explicitly to read the record held by a higher court (e.g. 'stj'), since appeals keep the origin case number. | |
| cnjNumber | Yes | CNJ unified case number, formatted (NNNNNNN-DD.AAAA.J.TR.OOOO) or as 20 digits. Check digits are validated. |
Output Schema
| Name | Required | Description |
|---|---|---|
| court | Yes | Court alias that was queried |
| found | Yes | |
| records | Yes | One record per instance (e.g. first instance and appeal) held by this court |
| cnjNumber | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds critical behavioral traits: the scope (Brazilian court), data limitations (lack of names), and performance metrics (20-60s latency). This is rich behavioral context.
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 highly dense but perfectly utilized. Each clause contributes specific, actionable information (what is returned, what is not, how long it takes).
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 that it specifies the data source, the input requirements, the granular return (one record per instance), and performance, the definition is functionally complete for an agent to decide whether to use it and how.
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?
Since the schema coverage is 100%, the baseline score is 3. The description adds minor value by contextually explaining the CNJ number format and the role of the 'court' alias.
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 verb and the resource (public cover data of a Brazilian court case). By naming DataJud and defining the scope (CNJ's system), it clearly distinguishes this tool from generic search or list operations.
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 provides explicit limitations on the data returned, noting that 'Party and lawyer names are not available in DataJud.' This is a crucial usage guideline preventing the agent from expecting specific fields that this tool cannot fulfill.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_courtsList courtsARead-onlyIdempotent
List the courts available in DataJud and their aliases (the court parameter of the other tools). Optionally filter by justice segment. The Supreme Court (STF) is not available.
| Name | Required | Description | Default |
|---|---|---|---|
| segment | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| courts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and closed-world behavior, so the safety profile is covered. The description's added value is the STF-unavailability constraint and the alias-to-`court`-parameter mapping, which is genuinely useful but modest; it says nothing about list size, caching, or freshness.
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, front-loaded with the primary action and what is returned, followed by the filter and the one caveat. No filler and no restatement of the title.
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?
An output schema exists, so return structure needn't be described, and annotations carry the safety profile. What remains for the description — the purpose of the aliases, the optional segment filter, and the STF gap — is all present, so an agent can call this correctly.
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 coverage is 0%, so the description must carry the burden — it identifies the parameter's purpose as filtering by 'justice segment' and marks it optional. The six segment values are supplied by the enum in the schema, so nothing critical is missing, though the description offers no nuance about how the segments map to courts.
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 ('list the courts available in DataJud') and goes further by explaining what the results are for: they are the aliases accepted as the `court` parameter by the sibling tools. That linkage lets an agent place the tool correctly without opening the schema.
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 parenthetical '(the `court` parameter of the other tools)' tells the agent when this tool is needed — as a lookup before calling tools that take a court. It adds one concrete exclusion (STF is not available) but does not spell out what to do if a court is missing or contrast against siblings beyond the parameter linkage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_movementsList case movementsARead-onlyIdempotent
List the procedural movements (docket entries) of a case, newest first by default, grouped by instance. Each movement carries its TPU code, the Portuguese name, structured complements and, for common codes, a plain-English hint. Use since to get only new movements. Expect 20-60 s latency.
| Name | Required | Description | Default |
|---|---|---|---|
| court | No | DataJud court alias, e.g. 'tjsp', 'trf1', 'trt2', 'tre-sp', 'stj'. Optional when looking up a case number: the origin court is derived from the number. Pass it explicitly to read the record held by a higher court (e.g. 'stj'), since appeals keep the origin case number. | |
| limit | No | Max movements per instance | |
| order | No | desc | |
| since | No | Only movements on or after this ISO date/time | |
| cnjNumber | Yes | CNJ unified case number, formatted (NNNNNNN-DD.AAAA.J.TR.OOOO) or as 20 digits. Check digits are validated. |
Output Schema
| Name | Required | Description |
|---|---|---|
| court | Yes | |
| found | Yes | |
| cnjNumber | Yes | |
| instances | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, open-world behavior. The description adds genuinely non-structured context: 20-60 s latency, newest-first default, grouping by instance, and what each movement carries (TPU code, Portuguese name, complements, English hint). The latency warning is especially valuable for an agent planning calls.
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 compact sentences, each carrying distinct information: what is returned, the filtering shortcut, and the operational warning. The latency note is placed last where it does not bury the core purpose.
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?
An output schema exists, so return-value detail is optional, yet the description still summarizes the movement payload well. Remaining gaps are minor: pagination beyond `limit` and what happens when a case is not found are unstated.
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 coverage is 80%, so the schema already documents most parameters well, including the court/limit/since semantics. The description adds meaning to `since` (only new movements) and `order` (newest first by default) but does not explain `limit`'s per-instance scope, which is only visible in 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?
States a specific verb+resource ('List the procedural movements (docket entries) of a case') with default ordering and grouping. It is clearly a read of one case's movements, distinct from get_case and search_cases, though it never names those siblings explicitly.
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?
'Use `since` to get only new movements' is a real usage hint, and the default ordering/grouping set expectations. But there is no guidance on when to choose this over get_case or search_cases, and no exclusions or prerequisites (e.g., how to obtain cnjNumber).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_casesSearch cases by filtersARead-onlyIdempotent
Search one court's public cases by procedural class, subject, court unit and/or filing date range. Class and subject use numeric codes from CNJ's Unified Procedural Tables (TPU); className does a text match instead. Returns case covers without movements. At least one filter is required. Paginate with nextCursor. Expect 20-60 s latency.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | ||
| court | Yes | DataJud court alias, e.g. 'tjsp', 'trf1', 'trt2', 'tre-sp', 'stj'. Optional when looking up a case number: the origin court is derived from the number. Pass it explicitly to read the record held by a higher court (e.g. 'stj'), since appeals keep the origin case number. | |
| cursor | No | `nextCursor` from a previous call | |
| filedTo | No | Filed on or before (YYYY-MM-DD) | |
| classCode | No | TPU class code, e.g. 1116 | |
| className | No | Words in the class name, e.g. 'Execução Fiscal' | |
| filedFrom | No | Filed on or after (YYYY-MM-DD) | |
| subjectCodes | No | TPU subject codes; matches cases with any of them | |
| courtUnitCode | No | Court unit (órgão julgador) code |
Output Schema
| Name | Required | Description |
|---|---|---|
| court | Yes | |
| total | Yes | |
| results | Yes | |
| nextCursor | Yes | Pass as `cursor` to fetch the next page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds genuinely new operational context: 'Expect 20-60 s latency', cursor-based pagination via `nextCursor`, and that responses contain case covers without movements. Latency and pagination are the kind of details structured hints cannot express.
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?
Five short sentences, each carrying distinct load: scope, coding scheme, return shape, constraint, pagination, latency. The most decision-critical facts (single court, at least one filter) appear early.
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?
With an output schema present, return values need not be described, and the description still flags the covers-only shape. For a 9-parameter, 60+ enum-value search tool, latency, pagination, filter requirement, and code-system distinctions cover everything an agent needs before calling.
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 coverage is 89% so the baseline is 3, but the description earns more by explaining that class and subject are TPU numeric codes while `className` is a text match, and that `nextCursor` feeds `cursor`. It does not elaborate on `size`, `courtUnitCode`, or date-range interaction with the court scoping.
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 (search) and resource (public cases) scoped to a single court, and enumerates the filter dimensions: procedural class, subject, court unit, filing date range. The phrase 'Returns case covers without movements' also separates it from the sibling list_movements tool.
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?
Gives a hard precondition ('At least one filter is required') and clarifies the classCode/className choice ('numeric codes from TPU; `className` does a text match instead'), which is real routing guidance between parameters. It does not explicitly say when to prefer get_case over this search, so it stops short of full when/when-not coverage.
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.
4 tool updates
v0.1.0- First observed
get_case - First observed
list_courts - First observed
list_movements - First observed
search_cases
TDQS
Scored across 4 tools
Each tool targets a distinct resource and action: fetching one case, listing movements for a case, listing courts, and searching cases. The boundaries are clear, and the descriptions reinforce when to use search_cases versus get_case or list_movements.
All tools use consistent snake_case verb_noun naming (get_case, list_movements, list_courts, search_cases). The verbs accurately reflect the operations and there are no mixed conventions.
Four tools are well-scoped for a focused court-data server and each earns its place: discovery, search, case retrieval, and movement retrieval. Nothing appears redundant or missing at the count level.
The surface covers the core lifecycle: discover courts, search cases, fetch case covers, and list movements with incremental updates via `since`. A minor gap is the lack of a tool to resolve CNJ TPU class/subject codes, which search_cases requires as numeric inputs.
Maintenance
Related MCP Connectors
JusPronto is case-management software for Brazilian law firms. Its remote MCP server (OAuth 2.1 with PKCE, per-permission scopes, audit log) lets Claude and ChatGPT read the firm's own cases, deadlines, agenda, recent court movements and case files with the page cited. Write actions require the lawyer's approval. Requires a JusPronto account.
Public lookup of Brazilian court cases (metadata + docket) via the CNJ/DataJud API. Free, no login.
Simplified lookup of a person's or company's lawsuits from the CPF or CNPJ. Platform-hosted, no cred
Brazilian legal stack in one MCP: lawsuits, court publications, case law, tenders, certificates.
Related MCP Servers
- AlicenseAqualityAmaintenanceConnects AI assistants to Brazilian judicial data from DataJud CNJ and 91 courts, enabling process consultation, monitoring, and deadline calculation under the Civil Procedure Code.995 PyPI120MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying public Brazilian court proceedings metadata and movements via the CNJ/DataJud API, covering multiple courts.4MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for querying Brazil's CNJ DataJud public API. Enables validating CNJ process numbers, searching lawsuits by number, and listing courts.MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying Brazilian judicial case data through CNJ public APIs: fetching case metadata and movements via DataJud, searching publications and intimations from the national electronic justice gazette (DJEN) by case number or OAB, and downloading publication certificates as PDFs.-