Skip to main content
Glama
devantage

MCP Brazil Public Data

by devantage
README.md
![Logo](https://s3.devantage.com.br/devantage-public/logo-100x100.png)

# MCP Brazil Public Data

A modern [Model Context Protocol](https://modelcontextprotocol.io) server for
Brazilian public data, backed by [BrasilAPI](https://brasilapi.com.br) — no API key required.
Exposes 15 tools and 2 guided prompts covering companies (CNPJ), postal codes (CEP), banking, economy, geography, and more.

Inspired by the project [`alanpcf/brasil-data-mcp`](https://github.com/alanpcf/brasil-data-mcp), but adding Streamable-HTTP transport.

## Requirements

- Python 3.10+
- [uv](https://github.com/astral-sh/uv) (or Docker, for the containerized setup)

## Installation

```bash
uv venv

uv pip install -e ".[dev]"
```

## Running

The server supports two transports, selected via the `MCP_TRANSPORT` environment variable (see [Configuration](#configuration)).

### STDIO

The server speaks MCP over **stdio** by default (the transport used by most MCP
clients such as Claude Desktop and Claude Code):

```bash
source .venv/bin/activate

mcp-brazil-public-data
```

### Streamable HTTP

To serve over **streamable HTTP** instead:

```bash
source .venv/bin/activate

MCP_TRANSPORT=http mcp-brazil-public-data
```

The HTTP endpoint is then available at `http://0.0.0.0:8080/mcp/`.

### Docker

Build the image and run it in HTTP mode (the image defaults to HTTP on port 8080):

```bash
docker build -t mcp-brazil-public-data .

docker run --rm -p 8080:8080 mcp-brazil-public-data
```

Override any setting at runtime with `-e`, e.g. a different port:

```bash
docker run --rm -p 9000:9000 -e MCP_PORT=9000 mcp-brazil-public-data
```

## Configuration

| Variable        | Default   | Description                                                         |
| --------------- | --------- | ------------------------------------------------------------------- |
| `MCP_TRANSPORT` | `stdio`   | Transport to use: `stdio` or `http` (streamable HTTP).              |
| `MCP_HOST`      | `0.0.0.0` | Host/interface to bind when using HTTP. Use `0.0.0.0` to expose it. |
| `MCP_PORT`      | `8080`    | Port to listen on when using HTTP.                                  |

## Available Tools

### Companies & Finance

| Tool            | Description                                                    | Source          |
| --------------- | -------------------------------------------------------------- | --------------- |
| `lookup_cnpj`   | Company registration data (legal name, status, partners, CNAE) | Federal Revenue |
| `lookup_broker` | CVM-authorized brokerage firm by CNPJ                          | CVM             |
| `list_banks`    | List of ~250 registered banks                                  | BACEN           |
| `get_bank`      | Bank data by COMPE code                                        | BACEN           |

### Location & Geography

| Tool                  | Description                                   | Source          |
| --------------------- | --------------------------------------------- | --------------- |
| `lookup_cep`          | Full address from a postal code (CEP)         | Correios/ViaCEP |
| `lookup_ddd`          | State and cities served by an area code (DDD) | —               |
| `list_states`         | 27 states (UFs) with IBGE codes               | IBGE            |
| `list_municipalities` | Municipalities of a state with IBGE codes     | IBGE            |

### Economy

| Tool                | Description                                 | Source |
| ------------------- | ------------------------------------------- | ------ |
| `list_rates`        | Current economic indices (SELIC, CDI, IPCA) | BACEN  |
| `get_rate`          | Current value of an index by symbol         | BACEN  |
| `list_currencies`   | Foreign currencies available for quotes     | BACEN  |
| `get_exchange_rate` | PTAX quote of a currency on a date          | BACEN  |

### Reference

| Tool              | Description                  | Source           |
| ----------------- | ---------------------------- | ---------------- |
| `list_holidays`   | National holidays for a year | —                |
| `lookup_isbn`     | Book metadata by ISBN        | CBL/Google Books |
| `check_br_domain` | Status of a `.br` domain     | Registro.br      |

### Guided Prompts

| Prompt              | Description                                                |
| ------------------- | ---------------------------------------------------------- |
| `analyze_company`   | Looks up a CNPJ and produces a structured company analysis |
| `economic_overview` | Combines current economic rates with the year's holidays   |

## Development

### Testing

Run the test suite with:

```bash
pytest
```

## License

[MIT](./LICENSE)

TDQS

A3.6/5.0

Scored across 15 tools

Disambiguation3/5

Most tools are distinct (CNPJ, CEP, DDD, ISBN, bank, broker, domain are clearly separate). However, list_rates/get_rate and list_currencies/get_exchange_rate are legitimate duos, but list_banks/get_bank alongside list_rates/get_rate create a repetitive pattern where the list/get pairing could cause an agent to pick the wrong 'get' for a given symbol/code. list_states and list_municipalities are related but distinct enough.

Naming Consistency4/5

The set follows a mostly consistent pattern: list_X for enumeration (list_states, list_banks, list_holidays, list_rates, list_currencies, list_municipalities), lookup_X for single-record lookups by identifier (lookup_cnpj, lookup_cep, lookup_ddd, lookup_isbn, lookup_broker), and get_X for fetching specific values (get_bank, get_rate, get_exchange_rate). The mixing of 'lookup' and 'get' for similar operations is the only inconsistency, though both are clear.

Tool Count4/5

15 tools is slightly on the higher side but reasonable for a broad 'public data' server covering multiple domains (geography, companies, finance, telecom, books, domains). Each tool targets a distinct data source, so none feel redundant. Could arguably be trimmed, but the scope justifies the count.

Completeness3/5

The server covers a broad but shallow set of disjoint domains. Within each domain there are clear gaps: holidays has no state/municipal holidays (noted in description), banks has list+get but no search-by-name, rates/currencies are read-only with no historical range beyond specific date for exchange. The domain is inherently a heterogeneous reference service, so completeness is hard to define, but several common lookups (e.g., CNPJ search by name, CEP range) are absent.

Maintenance

ActivityStale
ResponsivenessNo issues