Content
# ECHA Chemical Data MCP Server
The European Chemicals Agency (ECHA) data query MCP Server provides 11 tools covering substance information, CLP classification, REACH registration classification, physicochemical properties, ecotoxicology, and toxicology data.
## 🔧 Tool List
| Tool | Description | Data Source | Default Limit |
|------|-------------|-------------|--------------|
| `echa_get_substance_info` | Basic substance information (CAS, EC, name) | REST API | — |
| `echa_list_dossiers` | List of REACH registration dossiers | REST API | `max_results=10` |
| `echa_get_clp_classification` | CLP notified classification (industry self-classification) | REST API | `max_results=5` |
| `echa_get_harmonised_classification` | Harmonised classification (Annex VI official classification) | REST API | — |
| `echa_get_reach_ghs` | REACH dossier GHS classification (Section 2.1) | HTML parsing | — |
| `echa_get_reach_pbt` | REACH dossier PBT assessment (Section 2.3) | HTML parsing | — |
| `echa_get_physchem_data` | Physicochemical properties data (Section 4) | HTML parsing | `max_studies=50` |
| `echa_get_ecotoxicology_data` | Environmental fate + ecotoxicology data (Sections 5/6) | HTML parsing | `max_studies=50` |
| `echa_get_toxicology_summary` | Toxicology summary + DN(M)ELs (quick) | HTML parsing | — |
| `echa_get_toxicology_studies` | Toxicology individual study records (can be filtered by section) | HTML parsing | `max_studies=50` |
| `echa_get_toxicology_full` | Full toxicology data (slow) | HTML parsing | internal limit 100 |
## 📚 Resources
| Resource URI | Description |
|---|---|
| `echa://hcode-mapping` | GHS hazard classification → H-code mapping table (Markdown) |
| `echa://hcode-mapping-json` | H-code mapping table (JSON) |
## 🚀 Quick Start
### Installation
```bash
# pip
pip install echa-cli
# or uv (recommended, automatic environment isolation)
uv tool install echa-cli
# or from source
pip install -e .
```
After installation, two commands are provided:
- `echa-cli` — command-line tool (for direct terminal use)
- `echa-mcp` — start MCP Server (for AI assistant use)
### Method 1: CLI Command Line
No need to start the service, directly query ECHA data:
```bash
# Query basic substance information (CAS, EC, name, molecular formula)
echa-cli substance-info 100.000.002
# Query harmonised classification (Annex VI, legally binding)
echa-cli harmonised 100.000.002
# Query CLP industry notified classification (default first 5)
echa-cli clp 100.000.002
echa-cli clp 100.000.002 --max-results 3
# Query REACH registration dossier list
echa-cli list-dossiers 100.000.002
# Query REACH GHS classification (requires CAS number)
echa-cli reach-ghs 100.000.002 50-00-0
# Query REACH PBT assessment (requires CAS number)
echa-cli reach-pbt 100.000.002 50-00-0
# Query physicochemical properties (Section 4, can be filtered by subsection)
echa-cli physchem 100.000.002 --section 4.8 --max-studies 10
# Query environmental fate and ecotoxicology (Sections 5/6, can be filtered by subsection)
echa-cli ecotox 100.000.002 --section 6.1.1 --max-studies 10
# Toxicology summary + DNEL values (quick, 10-30s)
echa-cli tox-summary 100.000.002
# Specific toxicology section (e.g., acute toxicity 7.2)
echa-cli tox-studies 100.000.002 --section 7.2 --max-studies 10
# Full toxicology data (slow, may take several minutes)
echa-cli tox-full 100.000.002
# View help
echa-cli --help
echa-cli substance-info --help
```
All commands output JSON to stdout, which can be processed with tools like `jq` or `python -m json.tool`.
### Method 2: MCP Server (for AI Assistant Use)
```bash
python -m echa_mcp.server
# or
echa-mcp
```
The service listens on `http://0.0.0.0:7082` (endpoint: `/mcp`, Streamable HTTP transmission) after startup.
Configure to MCP client:
```json
{
"mcpServers": {
"echa": {
"url": "http://192.168.89.193:7082/mcp"
}
}
}
```
## 📋 Example Usage and Return Results
### 1. Query Basic Substance Information — `echa_get_substance_info`
**Input:**
```json
{
"substance_index": "100.000.002"
}
```
**Return:**
```json
{
"substance_index": "100.000.002",
"cas_number": "50-00-0",
"ec_number": "200-001-8",
"chemical_name": "Formaldehyde",
"iupac_name": "formaldehyde",
"molecular_formula": "CH2O",
"inchi": "InChI=1S/CH2O/c1-2/h1H2",
"smiles": "C=O",
"index_number": "605-001-00-5",
"all_cas_numbers": [
"1053659-79-2", "8013-13-6", "1158237-02-5", "50-00-0",
"1416946-65-0", "1227476-28-9", "1156543-56-4", "1357848-44-2",
"8005-38-7", "8006-07-3", "1609158-91-9", "112068-71-0"
],
"all_ec_names": ["Formaldehyde"],
"all_iupac_names": ["formaldehyde"]
}
```
### 2. Query CLP Notified Classification — `echa_get_clp_classification`
**Input:**
```json
{
"substance_index": "100.000.002",
"max_results": 3
}
```
**Return (excerpt):**
```json
{
"substance_index": "100.000.002",
"total_available": 50,
"returned": 3,
"truncated": true,
"classifications": [
{
"notification_percentage": 34.19,
"hazard_categories": ["Carc. 2", "Acute Tox. 3 (Inhalation)", "Skin Corr. 1B", "Skin Sens. 1"],
"hcodes": ["H301", "H311", "H314", "H317", "H331", "H351"],
"signal_word": "Danger"
}
]
}
```
### 3. Recommended Tool Invocation Order
Taking formaldehyde (Formaldehyde, substance_index: `100.000.002`) as an example:
1. `echa_get_substance_info` → Get CAS (50-00-0), EC, name
2. `echa_get_harmonised_classification` → View harmonised classification (Annex VI)
3. `echa_get_clp_classification` → View industry notified classification (default returns top 5)
4. `echa_get_physchem_data` → View physicochemical properties
5. `echa_get_ecotoxicology_data` → View environmental fate and ecotoxicology
6. `echa_get_toxicology_summary` → Quickly view toxicology summary and DNEL values
## 🏗 Technical Architecture
```
echa_mcp/
├── server.py # FastMCP entry, register tools + resources
├── clients/
│ └── echa_client.py # Asynchronous HTTP client (httpx, bypass local proxy)
├── tools/ # MCP tool implementation
│ ├── substance.py # Substance information + dossier list
│ ├── clp_classification.py
│ ├── harmonised_classification.py
│ ├── reach_classification.py
│ ├── properties.py
│ └── toxicology.py
├── parsers/ # HTML parser (compatible with ECHA new UUID document links)
│ ├── common.py # Shared parsing tools
│ ├── section2_parser.py # Section 2 GHS/PBT
│ ├── dossier_sections.py # Section 4/5/6 physicochemical and ecotoxicology
│ └── section7_parser.py # Section 7 toxicology
├── models/ # Pydantic input model
│ ├── substance.py
│ ├── classification.py
│ ├── properties.py
│ └── toxicology.py
└── data/
└── hcode_mapping.py # H-code mapping table
```
## ⚠️ Notes
- **Proxy bypass**: httpx client is configured with `proxy=None`, bypassing local proxies (like ClashX). ECHA's HTML dossier pages (~1MB) may disconnect when downloaded through a proxy.
- **Timeout setting**: Connection timeout 30s / read timeout 120s, adapted for delay from China to connect to ECHA servers.
- **Result limit**: CLP classification defaults to return top 5, dossier defaults to 10, study defaults to 50. Adjustable via `max_results` / `max_studies` parameters.
- **HTML parsing**: Depends on ECHA dossier HTML page structure (using UUID format document links from 2025), may require parser updates if ECHA modifies the frontend structure.
## Dependencies
- `mcp[cli]` >= 1.0.0 (MCP Python SDK)
- `httpx` >= 0.27.0 (asynchronous HTTP)
- `beautifulsoup4` >= 4.12.0 (HTML parsing)
- `pydantic` >= 2.0.0 (input validation)
- `typer` >= 0.9.0 (CLI framework)