echa-cli 1.0.0__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {echa_cli-1.0.0 → echa_cli-1.1.0}/PKG-INFO +3 -2
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/PKG-INFO +3 -2
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/requires.txt +3 -1
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/cli.py +44 -1
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/server.py +7 -1
- {echa_cli-1.0.0 → echa_cli-1.1.0}/pyproject.toml +4 -2
- {echa_cli-1.0.0 → echa_cli-1.1.0}/LICENSE +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/README.md +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/SOURCES.txt +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/dependency_links.txt +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/entry_points.txt +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/top_level.txt +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/clients/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/clients/echa_client.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/data/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/data/hcode_mapping.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/classification.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/substance.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/toxicology.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/common.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/section2_parser.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/section7_parser.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/__init__.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/clp_classification.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/harmonised_classification.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/reach_classification.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/substance.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/toxicology.py +0 -0
- {echa_cli-1.0.0 → echa_cli-1.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: echa-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: ECHA Chemical Data CLI — query European Chemicals Agency data from the command line or MCP server
|
|
5
5
|
Author: MagaritaZhu
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,11 +22,12 @@ Classifier: Typing :: Typed
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: mcp[cli]>=1.0.0
|
|
26
25
|
Requires-Dist: httpx>=0.27.0
|
|
27
26
|
Requires-Dist: beautifulsoup4>=4.12.0
|
|
28
27
|
Requires-Dist: pydantic>=2.0.0
|
|
29
28
|
Requires-Dist: typer>=0.9.0
|
|
29
|
+
Provides-Extra: mcp
|
|
30
|
+
Requires-Dist: mcp[cli]>=1.0.0; extra == "mcp"
|
|
30
31
|
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
# ECHA Chemical Data MCP Server
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: echa-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: ECHA Chemical Data CLI — query European Chemicals Agency data from the command line or MCP server
|
|
5
5
|
Author: MagaritaZhu
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,11 +22,12 @@ Classifier: Typing :: Typed
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: mcp[cli]>=1.0.0
|
|
26
25
|
Requires-Dist: httpx>=0.27.0
|
|
27
26
|
Requires-Dist: beautifulsoup4>=4.12.0
|
|
28
27
|
Requires-Dist: pydantic>=2.0.0
|
|
29
28
|
Requires-Dist: typer>=0.9.0
|
|
29
|
+
Provides-Extra: mcp
|
|
30
|
+
Requires-Dist: mcp[cli]>=1.0.0; extra == "mcp"
|
|
30
31
|
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
# ECHA Chemical Data MCP Server
|
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
ECHA Chemical Data CLI — query European Chemicals Agency data from the command line.
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
|
+
echa-cli search ethanol
|
|
7
|
+
echa-cli search 50-00-0
|
|
6
8
|
echa-cli substance-info 100.000.002
|
|
7
9
|
echa-cli harmonised 100.000.002
|
|
8
10
|
echa-cli tox-summary 100.000.002
|
|
9
|
-
echa-cli tox-studies 100.000.002 --section 7.2 --max-studies 10
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
import asyncio
|
|
14
|
+
import json
|
|
13
15
|
import sys
|
|
14
16
|
from typing import Optional
|
|
15
17
|
|
|
@@ -41,6 +43,47 @@ def _run_async(coro):
|
|
|
41
43
|
loop.close()
|
|
42
44
|
|
|
43
45
|
|
|
46
|
+
# ─── Search (resolve CAS/name → substance_index) ─────────────
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@app.command()
|
|
50
|
+
def search(
|
|
51
|
+
query: str = typer.Argument(help="CAS number, chemical name, or EC number"),
|
|
52
|
+
max_results: int = typer.Option(5, help="Maximum results to return"),
|
|
53
|
+
):
|
|
54
|
+
"""Search ECHA for a substance by CAS number, name, or EC number. Returns substance_index."""
|
|
55
|
+
async def _search():
|
|
56
|
+
from .clients.echa_client import get_client
|
|
57
|
+
|
|
58
|
+
client = get_client()
|
|
59
|
+
http_client = await client._get_client()
|
|
60
|
+
|
|
61
|
+
url = "/api-substance/v1/substance"
|
|
62
|
+
params = {"searchText": query, "pageIndex": 1, "pageSize": max_results}
|
|
63
|
+
resp = await http_client.get(url, params=params)
|
|
64
|
+
resp.raise_for_status()
|
|
65
|
+
data = resp.json()
|
|
66
|
+
|
|
67
|
+
items = data.get("items", [])
|
|
68
|
+
if not items:
|
|
69
|
+
return json.dumps({"error": f"No results for '{query}'"}, indent=2)
|
|
70
|
+
|
|
71
|
+
results = []
|
|
72
|
+
for item in items[:max_results]:
|
|
73
|
+
idx = item.get("substanceIndex", {})
|
|
74
|
+
results.append({
|
|
75
|
+
"substance_index": idx.get("rmlId", ""),
|
|
76
|
+
"name": idx.get("rmlName", ""),
|
|
77
|
+
"cas_number": idx.get("rmlCas", ""),
|
|
78
|
+
"ec_number": idx.get("rmlEc", ""),
|
|
79
|
+
"molecular_formula": idx.get("rmlMolFormula", ""),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
return json.dumps({"query": query, "total": len(results), "results": results}, ensure_ascii=False, indent=2)
|
|
83
|
+
|
|
84
|
+
_run_async(_search())
|
|
85
|
+
|
|
86
|
+
|
|
44
87
|
# ─── Substance Info ───────────────────────────────────────────
|
|
45
88
|
|
|
46
89
|
|
|
@@ -15,7 +15,13 @@ Also exposes H-code mapping table as an MCP Resource.
|
|
|
15
15
|
import json
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
try:
|
|
19
|
+
from mcp.server.fastmcp import FastMCP
|
|
20
|
+
except ImportError:
|
|
21
|
+
raise ImportError(
|
|
22
|
+
"MCP SDK is required for the server. "
|
|
23
|
+
"Install with: pip install echa-cli[mcp]"
|
|
24
|
+
)
|
|
19
25
|
|
|
20
26
|
from .models.substance import SubstanceInfoInput, DossierListInput
|
|
21
27
|
from .models.classification import (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "echa-cli"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.1.0"
|
|
4
4
|
description = "ECHA Chemical Data CLI — query European Chemicals Agency data from the command line or MCP server"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -23,13 +23,15 @@ classifiers = [
|
|
|
23
23
|
"Typing :: Typed",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"mcp[cli]>=1.0.0",
|
|
27
26
|
"httpx>=0.27.0",
|
|
28
27
|
"beautifulsoup4>=4.12.0",
|
|
29
28
|
"pydantic>=2.0.0",
|
|
30
29
|
"typer>=0.9.0",
|
|
31
30
|
]
|
|
32
31
|
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
mcp = ["mcp[cli]>=1.0.0"]
|
|
34
|
+
|
|
33
35
|
[project.urls]
|
|
34
36
|
Homepage = "https://github.com/RmMargt/echa-cli"
|
|
35
37
|
Repository = "https://github.com/RmMargt/echa-cli"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|