Skip to main content
Glama

datajud-mcp

CI TypeScript License: MIT

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 --> T

The 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
    end

MCP 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

get_case

cnjNumber (formatted or 20 digits, check digits validated), court?

{ court, cnjNumber, found, records[] }, one record per instance (first instance, appeal, …) with class, subjects, court unit, dates and latest movement

list_movements

cnjNumber, court?, limit (1–100, default 20), since? (ISO date), order (desc/asc)

{ court, cnjNumber, found, instances[]: { instance, totalMovements, latestMovementAt, movements[] } }

search_cases

court, any of classCode, className, subjectCodes[], courtUnitCode, filedFrom, filedTo; size (1–50), cursor?

{ court, total, results[], nextCursor }

list_courts

segment? (superior, federal, state, labor, electoral, military)

{ courts[]: { alias, name, segment } }, all 91 indices

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 build

Variable

Required

Notes

DATAJUD_API_KEY

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.

ANTHROPIC_API_KEY

agent and evals only

Never commit it.

DATAJUD_TIMEOUT_MS / DATAJUD_TOTAL_TIMEOUT_MS

no

Per attempt (default 90 s) and across retries (default 180 s).

DATAJUD_MAX_ATTEMPTS / DATAJUD_REQUESTS_PER_MINUTE

no

Defaults 4 and 120 (the cap allowed by the Terms of Use).

ANTHROPIC_MODEL / ANTHROPIC_EFFORT / AGENT_MAX_ITERATIONS

no

Defaults claude-opus-5-5, medium, 6.

Run the server

npm start            # compiled (dist/)
npm run dev          # from source with tsx

The 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.js

DataJud 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 GIF

The 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. dataAjuizamento is stored as yyyyMMddHHmmss, although the glossary shows ISO. A range query with 2023-01-01 returns 0 hits with no error, while the same range as 20230101000000 returned 970. search_cases takes ISO dates and converts them.

  • HTTP 200 can mean partial data. Under load DataJud answers 200 with _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. JE and TR), and superior courts keep the origin court's number. So an STJ record is read with court: "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 data
  • Unit 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, needsLawyerAttention where 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. needsLawyerAttention is 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; lastUpdatedAt is 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 tape

License

MIT

Available Tools

4 tools
get_caseGet case by CNJ numberA
Read-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.

NameRequiredDescriptionDefault
courtNoDataJud 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.
cnjNumberYesCNJ unified case number, formatted (NNNNNNN-DD.AAAA.J.TR.OOOO) or as 20 digits. Check digits are validated.

Output Schema

NameRequiredDescription
courtYesCourt alias that was queried
foundYes
recordsYesOne record per instance (e.g. first instance and appeal) held by this court
cnjNumberYes

TDQS

A4.5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 courtsA
Read-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.

NameRequiredDescriptionDefault
segmentNo

Output Schema

NameRequiredDescription
courtsYes

TDQS

A4.3/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 movementsA
Read-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.

NameRequiredDescriptionDefault
courtNoDataJud 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.
limitNoMax movements per instance
orderNodesc
sinceNoOnly movements on or after this ISO date/time
cnjNumberYesCNJ unified case number, formatted (NNNNNNN-DD.AAAA.J.TR.OOOO) or as 20 digits. Check digits are validated.

Output Schema

NameRequiredDescription
courtYes
foundYes
cnjNumberYes
instancesYes

TDQS

A3.8/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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 filtersA
Read-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.

NameRequiredDescriptionDefault
sizeNo
courtYesDataJud 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.
cursorNo`nextCursor` from a previous call
filedToNoFiled on or before (YYYY-MM-DD)
classCodeNoTPU class code, e.g. 1116
classNameNoWords in the class name, e.g. 'Execução Fiscal'
filedFromNoFiled on or after (YYYY-MM-DD)
subjectCodesNoTPU subject codes; matches cases with any of them
courtUnitCodeNoCourt unit (órgão julgador) code

Output Schema

NameRequiredDescription
courtYes
totalYes
resultsYes
nextCursorYesPass as `cursor` to fetch the next page

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 4 tool updatesv0.1.0
    • First observedget_case
    • First observedlist_courts
    • First observedlist_movements
    • First observedsearch_cases

TDQS

A4.3/5.0

Scored across 4 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Connects AI assistants to Brazilian judicial data from DataJud CNJ and 91 courts, enabling process consultation, monitoring, and deadline calculation under the Civil Procedure Code.
    9
    95 PyPI
    120
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables querying public Brazilian court proceedings metadata and movements via the CNJ/DataJud API, covering multiple courts.
    4
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables 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.
    -