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.
Files changed (32) hide show
  1. {echa_cli-1.0.0 → echa_cli-1.1.0}/PKG-INFO +3 -2
  2. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/PKG-INFO +3 -2
  3. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/requires.txt +3 -1
  4. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/cli.py +44 -1
  5. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/server.py +7 -1
  6. {echa_cli-1.0.0 → echa_cli-1.1.0}/pyproject.toml +4 -2
  7. {echa_cli-1.0.0 → echa_cli-1.1.0}/LICENSE +0 -0
  8. {echa_cli-1.0.0 → echa_cli-1.1.0}/README.md +0 -0
  9. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/SOURCES.txt +0 -0
  10. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/dependency_links.txt +0 -0
  11. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/entry_points.txt +0 -0
  12. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_cli.egg-info/top_level.txt +0 -0
  13. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/__init__.py +0 -0
  14. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/clients/__init__.py +0 -0
  15. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/clients/echa_client.py +0 -0
  16. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/data/__init__.py +0 -0
  17. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/data/hcode_mapping.py +0 -0
  18. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/__init__.py +0 -0
  19. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/classification.py +0 -0
  20. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/substance.py +0 -0
  21. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/models/toxicology.py +0 -0
  22. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/__init__.py +0 -0
  23. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/common.py +0 -0
  24. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/section2_parser.py +0 -0
  25. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/parsers/section7_parser.py +0 -0
  26. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/__init__.py +0 -0
  27. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/clp_classification.py +0 -0
  28. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/harmonised_classification.py +0 -0
  29. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/reach_classification.py +0 -0
  30. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/substance.py +0 -0
  31. {echa_cli-1.0.0 → echa_cli-1.1.0}/echa_mcp/tools/toxicology.py +0 -0
  32. {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.0.0
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.0.0
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,5 +1,7 @@
1
- mcp[cli]>=1.0.0
2
1
  httpx>=0.27.0
3
2
  beautifulsoup4>=4.12.0
4
3
  pydantic>=2.0.0
5
4
  typer>=0.9.0
5
+
6
+ [mcp]
7
+ mcp[cli]>=1.0.0
@@ -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
- from mcp.server.fastmcp import FastMCP
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.0.0"
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