Metadata-Version: 2.4
Name: dataprem-mcp
Version: 0.3.2
Summary: MCP server exposing Spanish public-data sources (Catastro, BORME, CENDOJ, public tenders) to AI agents
Project-URL: Homepage, https://dataprem.com
Project-URL: Repository, https://github.com/tekniadev/dataprem-mcp
Project-URL: Issues, https://github.com/tekniadev/dataprem-mcp/issues
Project-URL: Changelog, https://github.com/tekniadev/dataprem-mcp/blob/master/CHANGELOG.md
Author-email: Teknia <info@dataprem.com>
License-Expression: MIT
Keywords: borme,catastro,cendoj,mcp,model-context-protocol,open-data,public-data,spain
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# DataPrem MCP Server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that exposes Spanish public-data sources to AI agents (Claude Desktop, Cursor, ChatGPT, …).

It is a thin client of the [DataPrem REST API](https://api.dataprem.com): each MCP tool maps to an HTTPS call against `api.dataprem.com` using your API key.

## Tool status (v0.3.0)

| Tool | Status | Real source | Available |
|------|--------|-------------|:---------:|
| `dataprem_catastro_lookup` | **Live** | Sede Electrónica del Catastro via DataPrem API | ✅ |
| `dataprem_borme_search` | Stub | Boletín Oficial del Registro Mercantil | Phase 3 (TK-481) |
| `dataprem_cendoj_search` | Stub | Centro de Documentación Judicial | Phase 4 (TK-487) |
| `dataprem_tenders_search` | Stub | Plataforma de Contratación del Sector Público | Phase 3 (TK-482) |

Stubs return demonstration data flagged with `_status: "stub"` in the payload — useful so the LLM learns the expected shape of each tool and for UX mockups, but they are not real data.

## Getting an API key

The "live" tools require a valid Bearer token from `api.dataprem.com`. While we are in pre-monetisation (Phase 1) tokens are issued manually:

1. Request access by email to `info@dataprem.com` describing the use case (B2B integrator, B2C professional, …).
2. You will receive a token prefixed `dpa_…` along with the API URL.
3. Configure it in your MCP client (next section).

In Phase 2 the `/account` portal (TK-477) will let you generate and rotate tokens self-service.

## Installation

Requires Python 3.11+.

```bash
# Via PyPI (recommended for MCP clients)
uvx dataprem-mcp

# Or local install for development
pip install -e ".[dev]"
```

## Claude Desktop configuration

Edit `claude_desktop_config.json` (Mac: `~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "dataprem": {
      "command": "uvx",
      "args": ["dataprem-mcp"],
      "env": {
        "DATAPREM_API_KEY": "dpa_YOUR_TOKEN_HERE",
        "DATAPREM_API_URL": "https://api.dataprem.com"
      }
    }
  }
}
```

Restart Claude Desktop. The four tools should show up as available to the model.

## Server-side HTTP transport

For clients that cannot spawn the server as a subprocess (e.g. a multi-request web app) there is a `streamable-http` transport that runs the server as a long-lived process listening for JSON-RPC over HTTP.

```bash
# Without Docker
python -m dataprem_mcp --transport streamable-http --host 0.0.0.0 --port 8080

# With Docker
docker compose up dataprem_mcp     # local image build; exposed only on the internal network
```

The MCP endpoint is `/mcp` (no trailing slash). The standard handshake (`initialize` → `tools/list` → `tools/call`) works with `Content-Type: application/json` and `Accept: application/json, text/event-stream`. Each conversation receives an `mcp-session-id` that the client must echo back on subsequent requests.

```bash
# Example: initialize handshake
curl -sL -X POST http://127.0.0.1:8080/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "clientInfo": {"name": "smoke", "version": "1"},
      "capabilities": {}
    }
  }' -i
```

By default the compose service does not publish the port to the host: place it on a Docker network shared with your client and reach it as `http://dataprem_mcp:8080/mcp`.

### Alternative configuration (local development)

```json
{
  "mcpServers": {
    "dataprem-dev": {
      "command": "python",
      "args": ["-m", "dataprem_mcp"],
      "cwd": "/path/to/dataprem-mcp",
      "env": {
        "DATAPREM_API_KEY": "dpa_dev_token",
        "DATAPREM_API_URL": "http://localhost:8000"
      }
    }
  }
}
```

## Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `DATAPREM_API_KEY` | _(empty)_ | Bearer token (`dpa_…`). **Required** for live tools. |
| `DATAPREM_API_URL` | `https://api.dataprem.com` | API base URL. Override to point at a development environment. |

## Tools — reference

### `dataprem_catastro_lookup` ✅ Live

Looks up cadastral data for a property. Two modes are supported:

**By cadastral reference:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `refcat` | string | Cadastral reference (14, 18 or 20 characters) |

**By address:**

| Parameter | Type | Required | Description |
|-----------|------|:--------:|-------------|
| `address` | string | yes | Literal address (street type + name + number) |
| `city` | string | yes | Municipality |
| `province` | string | no | Province |

Returns the normalised cadastral record (class, use, surfaces, year of construction, address with INE codes, breakdown of constructions by floor and use). **Does not expose the owner** for LOPD/GDPR reasons.

### `dataprem_borme_search` (stub — Phase 3)

| Parameter | Type | Required |
|-----------|------|:--------:|
| `company_name` | string | yes |
| `date_from` | string YYYY-MM-DD | no |
| `date_to` | string YYYY-MM-DD | no |

### `dataprem_cendoj_search` (stub — Phase 4)

| Parameter | Type | Required |
|-----------|------|:--------:|
| `query` | string | yes |
| `court` | string | no |
| `date_from` | string YYYY-MM-DD | no |

### `dataprem_tenders_search` (stub — Phase 3)

| Parameter | Type | Required |
|-----------|------|:--------:|
| `query` | string | yes |
| `location` | string | no |
| `status` | `"open"` \| `"closed"` \| `"all"` | no |

## Response shape

Every tool returns a `dict`. **Live** tools mark success or failure with `ok`:

```json
{ "ok": true, "data": { ... cadastral record ... } }

{ "ok": false, "error": "unauthorized", "message": "API key invalid or revoked..." }
```

**Stub** tools advertise their nature with `_status` and the real ETA:

```json
{ "_status": "stub", "_eta_phase": "Phase 3 (TK-481)", "_message": "Demonstration data...", ...demo data... }
```

Error codes returned by live tools:

| `error` | Meaning |
|---------|---------|
| `missing_api_key` | `DATAPREM_API_KEY` is not set in the environment |
| `invalid_request` | Required parameters are missing |
| `unauthorized` | Token revoked or expired |
| `not_found` | The upstream returned no match |
| `validation_error` | Catastro rejected the input (malformed RC, unknown street, …) |
| `rate_limited` | Monthly quota exhausted |
| `upstream_error` | Catastro or DataPrem temporarily unavailable |
| `upstream_unreachable` | `DATAPREM_API_URL` cannot be reached |

## Development

```bash
# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run the server with a local API key
DATAPREM_API_KEY=dpa_xxx DATAPREM_API_URL=http://localhost python -m dataprem_mcp
```

## License

MIT
