From 88eb6a40c524d092d84767adbdfef7f960624c75 Mon Sep 17 00:00:00 2001 From: Tyler Mathis <35553152+tsmathis@users.noreply.github.com> Date: Thu, 22 Jan 2026 15:55:53 -0800 Subject: [PATCH 01/11] bump emmet-core, clamp upperbound for non-main segment --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9a47e0c2..98e048c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "typing-extensions>=3.7.4.1", "requests>=2.23.0", "monty>=2024.12.10", - "emmet-core>=0.86.3rc0", + "emmet-core>=0.86.3rc1,<0.87.0", "boto3", "orjson >= 3.10,<4", ] @@ -33,7 +33,7 @@ dynamic = ["version"] [project.optional-dependencies] mcp = ["fastmcp"] all = [ - "emmet-core[all]>=0.86.2", + "emmet-core[all]>=0.86.3rc1,<0.87.0", "custodian", "mpcontribs-client>=5.10", "fastmcp", From 9652f62418e35fe50b09d1875af3a06fdf6a5a19 Mon Sep 17 00:00:00 2001 From: Tyler Mathis <35553152+tsmathis@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:04:21 -0800 Subject: [PATCH 02/11] bump matminer --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 98e048c3..ce8646ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,8 +37,7 @@ all = [ "custodian", "mpcontribs-client>=5.10", "fastmcp", - "matminer>=0.9.3", - "scipy<1.17.0", # pending fixes in matminer + "matminer>=0.10.0", ] test = [ "pre-commit", From 2ab5472567016a413d675178ac6c4eb6d371da00 Mon Sep 17 00:00:00 2001 From: esoteric-ephemera Date: Thu, 22 Jan 2026 16:35:47 -0800 Subject: [PATCH 03/11] strip whitespace in mcp tool --- mp_api/mcp/tools.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mp_api/mcp/tools.py b/mp_api/mcp/tools.py index 3642ab67..451ecd96 100644 --- a/mp_api/mcp/tools.py +++ b/mp_api/mcp/tools.py @@ -72,7 +72,8 @@ def search(self, query: str) -> SearchOutput: Args: query (str) : A natural language query of either: - - comma-delimited keywords, example: "polyhedra, orthorhombic, superconductor" + - comma-delimited keywords, example: "polyhedra,orthorhombic,superconductor". + This should contain no whitespace; all whitespace will be removed. - chemical formula, example: "TiO2" - dash-delimited elements for more general chemical system, example: "Li-P-S" To query by formula or chemical system, no commas should be present in the query. @@ -94,11 +95,16 @@ def search(self, query: str) -> SearchOutput: material_ids=material_ids, fields=["description", "material_id"] ) else: - robo_docs += self.client.materials.robocrys.search(query) + robo_docs += self.client.materials.robocrys.search( + query.replace(" ", "").split(",") + ) return SearchOutput( results=[ - FetchResult(id=doc["material_id"], text=doc["description"]) + FetchResult( + id=doc["material_id"], + text=doc["description"], + ) for doc in robo_docs ] ) From 37c091919e6311ef9722ae811ae60c7af71e35af Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 23 Jan 2026 17:55:02 +0000 Subject: [PATCH 04/11] auto dependency upgrades --- .../requirements-ubuntu-latest_py3.11.txt | 28 +++----- ...quirements-ubuntu-latest_py3.11_extras.txt | 66 ++++++++----------- .../requirements-ubuntu-latest_py3.12.txt | 28 +++----- ...quirements-ubuntu-latest_py3.12_extras.txt | 66 ++++++++----------- 4 files changed, 70 insertions(+), 118 deletions(-) diff --git a/requirements/requirements-ubuntu-latest_py3.11.txt b/requirements/requirements-ubuntu-latest_py3.11.txt index b7c060a9..c98cfb87 100644 --- a/requirements/requirements-ubuntu-latest_py3.11.txt +++ b/requirements/requirements-ubuntu-latest_py3.11.txt @@ -10,9 +10,9 @@ bibtexparser==1.4.3 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.30 +boto3==1.42.33 # via mp-api (pyproject.toml) -botocore==1.42.30 +botocore==1.42.33 # via # boto3 # s3transfer @@ -24,13 +24,13 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.87.0.dev4 +emmet-core==0.86.3rc1 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib idna==3.11 # via requests -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -49,8 +49,6 @@ monty==2025.3.3 # pymatgen mpmath==1.3.0 # via sympy -msgpack==1.1.2 - # via mp-api (pyproject.toml) narwhals==2.15.0 # via plotly networkx==3.6.1 @@ -69,13 +67,13 @@ orjson==3.11.5 # via # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via # matplotlib # plotly palettable==3.3.3 # via pymatgen -pandas==2.3.3 +pandas==3.0.0 # via pymatgen pillow==12.1.0 # via matplotlib @@ -101,7 +99,7 @@ pymatgen==2025.10.7 # pymatgen-io-validation pymatgen-io-validation==0.1.2 # via emmet-core -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -112,8 +110,6 @@ python-dateutil==2.9.0.post0 # pandas python-dotenv==1.2.1 # via pydantic-settings -pytz==2025.2 - # via pandas pyyaml==6.0.3 # via pybtex requests==2.32.5 @@ -127,12 +123,10 @@ ruamel-yaml==0.19.1 # pymatgen s3transfer==0.16.0 # via boto3 -scipy==1.16.3 +scipy==1.17.0 # via pymatgen six==1.17.0 # via python-dateutil -smart-open==7.5.0 - # via mp-api (pyproject.toml) spglib==2.7.0 # via pymatgen sympy==1.14.0 @@ -154,13 +148,9 @@ typing-inspection==0.4.2 # via # pydantic # pydantic-settings -tzdata==2025.3 - # via pandas -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen urllib3==2.6.3 # via # botocore # requests -wrapt==2.0.1 - # via smart-open diff --git a/requirements/requirements-ubuntu-latest_py3.11_extras.txt b/requirements/requirements-ubuntu-latest_py3.11_extras.txt index 1c26d0ef..466b050d 100644 --- a/requirements/requirements-ubuntu-latest_py3.11_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.11_extras.txt @@ -41,11 +41,9 @@ blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.30 - # via - # mp-api - # mp-api (pyproject.toml) -botocore==1.42.30 +boto3==1.42.33 + # via mp-api (pyproject.toml) +botocore==1.42.33 # via # boto3 # s3transfer @@ -108,10 +106,8 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.87.0.dev4 - # via - # mp-api - # mp-api (pyproject.toml) +emmet-core[all]==0.86.3rc1 + # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp execnet==2.1.2 @@ -120,7 +116,7 @@ executing==2.2.1 # via stack-data fakeredis[lua]==2.33.0 # via pydocket -fastmcp==2.14.3 +fastmcp==2.14.4 # via mp-api (pyproject.toml) filelock==3.20.3 # via virtualenv @@ -193,7 +189,7 @@ jeepney==0.9.0 # secretstorage jinja2==3.1.6 # via sphinx -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -207,7 +203,9 @@ json2html==1.3.0 jsonpointer==3.0.0 # via jsonschema jsonref==1.1.0 - # via bravado-core + # via + # bravado-core + # fastmcp jsonschema[format-nongpl]==4.26.0 # via # bravado-core @@ -235,9 +233,10 @@ markdown-it-py==4.0.0 # via rich markupsafe==3.0.3 # via jinja2 -matminer==0.9.3 +matminer==0.10.0 # via # emmet-core + # mp-api (pyproject.toml) # robocrys matplotlib==3.10.8 # via @@ -259,7 +258,6 @@ monty==2025.3.3 # custodian # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # robocrys @@ -268,8 +266,6 @@ more-itertools==10.8.0 # inflect # jaraco-classes # jaraco-functools -mp-api[mcp]==0.45.15 - # via mp-api (pyproject.toml) mp-pyrho==0.5.1 # via pymatgen-analysis-defects mpcontribs-client==5.10.4 @@ -280,8 +276,6 @@ msgpack==1.1.2 # via # bravado # bravado-core - # mp-api - # mp-api (pyproject.toml) mypy==1.19.1 # via mp-api (pyproject.toml) mypy-extensions==1.1.0 @@ -341,11 +335,11 @@ opentelemetry-semantic-conventions==0.60b1 # opentelemetry-sdk orjson==3.11.5 # via - # mp-api # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via + # fastmcp # lazy-loader # matplotlib # opentelemetry-instrumentation @@ -413,7 +407,7 @@ py-key-value-aio[disk,keyring,memory,redis]==0.3.0 # pydocket py-key-value-shared==0.3.0 # via py-key-value-aio -pyarrow==22.0.0 +pyarrow==23.0.0 # via emmet-core pybtex==0.25.1 # via @@ -423,7 +417,7 @@ pycodestyle==2.14.0 # via # flake8 # mp-api (pyproject.toml) -pycparser==2.23 +pycparser==3.0 # via cffi pydantic[email]==2.12.5 # via @@ -459,7 +453,6 @@ pymatgen==2025.10.7 # via # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # mp-pyrho # mpcontribs-client @@ -480,7 +473,7 @@ pymongo==4.16.0 # via # matminer # mpcontribs-client -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -545,7 +538,6 @@ requests==2.32.5 # bravado-core # jsonschema-path # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # pymatgen-io-validation @@ -568,7 +560,7 @@ rich==14.2.0 # typer rich-rst==1.3.2 # via cyclopts -robocrys==0.2.12 +robocrys==0.2.13 # via emmet-core roman-numerals==4.1.0 # via sphinx @@ -587,9 +579,10 @@ scikit-image==0.26.0 # via pymatgen-analysis-defects scikit-learn==1.8.0 # via matminer -scipy==1.16.3 +scipy==1.17.0 # via # ase + # matminer # pymatgen # robocrys # scikit-image @@ -598,7 +591,7 @@ seaborn==0.13.2 # via pymatgen-analysis-diffusion secretstorage==3.5.0 # via keyring -seekpath==2.1.0 +seekpath==2.2.0 # via emmet-core semantic-version==2.10.0 # via mpcontribs-client @@ -617,10 +610,6 @@ six==1.17.0 # flatten-dict # python-dateutil # rfc3339-validator -smart-open==7.5.0 - # via - # mp-api - # mp-api (pyproject.toml) snowballstemmer==3.0.1 # via sphinx sortedcontainers==2.4.0 @@ -644,11 +633,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sse-starlette==3.1.2 +sse-starlette==3.2.0 # via mcp stack-data==0.6.3 # via ipython -starlette==0.51.0 +starlette==0.52.1 # via # mcp # sse-starlette @@ -694,7 +683,6 @@ typing-extensions==4.15.0 # flexparser # ipython # mcp - # mp-api # mp-api (pyproject.toml) # mypy # opentelemetry-api @@ -724,7 +712,7 @@ tzdata==2025.3 # pandas ujson==5.11.0 # via mpcontribs-client -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen uri-template==1.3.0 # via jsonschema @@ -739,15 +727,13 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.2.14 +wcwidth==0.3.1 # via prompt-toolkit webcolors==25.10.0 # via jsonschema websockets==16.0 # via fastmcp wrapt==1.17.3 - # via - # opentelemetry-instrumentation - # smart-open + # via opentelemetry-instrumentation zipp==3.23.0 # via importlib-metadata diff --git a/requirements/requirements-ubuntu-latest_py3.12.txt b/requirements/requirements-ubuntu-latest_py3.12.txt index 12285056..b16c3817 100644 --- a/requirements/requirements-ubuntu-latest_py3.12.txt +++ b/requirements/requirements-ubuntu-latest_py3.12.txt @@ -10,9 +10,9 @@ bibtexparser==1.4.3 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.30 +boto3==1.42.33 # via mp-api (pyproject.toml) -botocore==1.42.30 +botocore==1.42.33 # via # boto3 # s3transfer @@ -24,13 +24,13 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.87.0.dev4 +emmet-core==0.86.3rc1 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib idna==3.11 # via requests -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -49,8 +49,6 @@ monty==2025.3.3 # pymatgen mpmath==1.3.0 # via sympy -msgpack==1.1.2 - # via mp-api (pyproject.toml) narwhals==2.15.0 # via plotly networkx==3.6.1 @@ -69,13 +67,13 @@ orjson==3.11.5 # via # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via # matplotlib # plotly palettable==3.3.3 # via pymatgen -pandas==2.3.3 +pandas==3.0.0 # via pymatgen pillow==12.1.0 # via matplotlib @@ -101,7 +99,7 @@ pymatgen==2025.10.7 # pymatgen-io-validation pymatgen-io-validation==0.1.2 # via emmet-core -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -112,8 +110,6 @@ python-dateutil==2.9.0.post0 # pandas python-dotenv==1.2.1 # via pydantic-settings -pytz==2025.2 - # via pandas pyyaml==6.0.3 # via pybtex requests==2.32.5 @@ -127,12 +123,10 @@ ruamel-yaml==0.19.1 # pymatgen s3transfer==0.16.0 # via boto3 -scipy==1.16.3 +scipy==1.17.0 # via pymatgen six==1.17.0 # via python-dateutil -smart-open==7.5.0 - # via mp-api (pyproject.toml) spglib==2.7.0 # via pymatgen sympy==1.14.0 @@ -153,13 +147,9 @@ typing-inspection==0.4.2 # via # pydantic # pydantic-settings -tzdata==2025.3 - # via pandas -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen urllib3==2.6.3 # via # botocore # requests -wrapt==2.0.1 - # via smart-open diff --git a/requirements/requirements-ubuntu-latest_py3.12_extras.txt b/requirements/requirements-ubuntu-latest_py3.12_extras.txt index 5a7a8773..ca8027f6 100644 --- a/requirements/requirements-ubuntu-latest_py3.12_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.12_extras.txt @@ -39,11 +39,9 @@ blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.30 - # via - # mp-api - # mp-api (pyproject.toml) -botocore==1.42.30 +boto3==1.42.33 + # via mp-api (pyproject.toml) +botocore==1.42.33 # via # boto3 # s3transfer @@ -106,10 +104,8 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.87.0.dev4 - # via - # mp-api - # mp-api (pyproject.toml) +emmet-core[all]==0.86.3rc1 + # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp execnet==2.1.2 @@ -118,7 +114,7 @@ executing==2.2.1 # via stack-data fakeredis[lua]==2.33.0 # via pydocket -fastmcp==2.14.3 +fastmcp==2.14.4 # via mp-api (pyproject.toml) filelock==3.20.3 # via virtualenv @@ -189,7 +185,7 @@ jeepney==0.9.0 # secretstorage jinja2==3.1.6 # via sphinx -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -203,7 +199,9 @@ json2html==1.3.0 jsonpointer==3.0.0 # via jsonschema jsonref==1.1.0 - # via bravado-core + # via + # bravado-core + # fastmcp jsonschema[format-nongpl]==4.26.0 # via # bravado-core @@ -231,9 +229,10 @@ markdown-it-py==4.0.0 # via rich markupsafe==3.0.3 # via jinja2 -matminer==0.9.3 +matminer==0.10.0 # via # emmet-core + # mp-api (pyproject.toml) # robocrys matplotlib==3.10.8 # via @@ -255,7 +254,6 @@ monty==2025.3.3 # custodian # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # robocrys @@ -264,8 +262,6 @@ more-itertools==10.8.0 # inflect # jaraco-classes # jaraco-functools -mp-api[mcp]==0.45.15 - # via mp-api (pyproject.toml) mp-pyrho==0.5.1 # via pymatgen-analysis-defects mpcontribs-client==5.10.4 @@ -276,8 +272,6 @@ msgpack==1.1.2 # via # bravado # bravado-core - # mp-api - # mp-api (pyproject.toml) mypy==1.19.1 # via mp-api (pyproject.toml) mypy-extensions==1.1.0 @@ -337,11 +331,11 @@ opentelemetry-semantic-conventions==0.60b1 # opentelemetry-sdk orjson==3.11.5 # via - # mp-api # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via + # fastmcp # lazy-loader # matplotlib # opentelemetry-instrumentation @@ -409,7 +403,7 @@ py-key-value-aio[disk,keyring,memory,redis]==0.3.0 # pydocket py-key-value-shared==0.3.0 # via py-key-value-aio -pyarrow==22.0.0 +pyarrow==23.0.0 # via emmet-core pybtex==0.25.1 # via @@ -419,7 +413,7 @@ pycodestyle==2.14.0 # via # flake8 # mp-api (pyproject.toml) -pycparser==2.23 +pycparser==3.0 # via cffi pydantic[email]==2.12.5 # via @@ -455,7 +449,6 @@ pymatgen==2025.10.7 # via # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # mp-pyrho # mpcontribs-client @@ -476,7 +469,7 @@ pymongo==4.16.0 # via # matminer # mpcontribs-client -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -541,7 +534,6 @@ requests==2.32.5 # bravado-core # jsonschema-path # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # pymatgen-io-validation @@ -564,7 +556,7 @@ rich==14.2.0 # typer rich-rst==1.3.2 # via cyclopts -robocrys==0.2.12 +robocrys==0.2.13 # via emmet-core roman-numerals==4.1.0 # via sphinx @@ -583,9 +575,10 @@ scikit-image==0.26.0 # via pymatgen-analysis-defects scikit-learn==1.8.0 # via matminer -scipy==1.16.3 +scipy==1.17.0 # via # ase + # matminer # pymatgen # robocrys # scikit-image @@ -594,7 +587,7 @@ seaborn==0.13.2 # via pymatgen-analysis-diffusion secretstorage==3.5.0 # via keyring -seekpath==2.1.0 +seekpath==2.2.0 # via emmet-core semantic-version==2.10.0 # via mpcontribs-client @@ -613,10 +606,6 @@ six==1.17.0 # flatten-dict # python-dateutil # rfc3339-validator -smart-open==7.5.0 - # via - # mp-api - # mp-api (pyproject.toml) snowballstemmer==3.0.1 # via sphinx sortedcontainers==2.4.0 @@ -640,11 +629,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sse-starlette==3.1.2 +sse-starlette==3.2.0 # via mcp stack-data==0.6.3 # via ipython -starlette==0.51.0 +starlette==0.52.1 # via # mcp # sse-starlette @@ -688,7 +677,6 @@ typing-extensions==4.15.0 # flexcache # flexparser # mcp - # mp-api # mp-api (pyproject.toml) # mypy # opentelemetry-api @@ -718,7 +706,7 @@ tzdata==2025.3 # pandas ujson==5.11.0 # via mpcontribs-client -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen uri-template==1.3.0 # via jsonschema @@ -733,15 +721,13 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.2.14 +wcwidth==0.3.1 # via prompt-toolkit webcolors==25.10.0 # via jsonschema websockets==16.0 # via fastmcp wrapt==1.17.3 - # via - # opentelemetry-instrumentation - # smart-open + # via opentelemetry-instrumentation zipp==3.23.0 # via importlib-metadata From 36f72c96e66eeece8ca4cc9cbb95e807935fec66 Mon Sep 17 00:00:00 2001 From: Tyler Mathis <35553152+tsmathis@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:05:28 -0800 Subject: [PATCH 05/11] make sure generic resters get attached to mpr --- mp_api/client/mprester.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mp_api/client/mprester.py b/mp_api/client/mprester.py index cebfba1a..1cf1a0d3 100644 --- a/mp_api/client/mprester.py +++ b/mp_api/client/mprester.py @@ -52,8 +52,10 @@ "mp_api.client.routes.materials.materials.MaterialsRester" ), **{f"materials/{k}": v for k, v in MATERIALS_RESTERS.items() if k not in {"doi"}}, - "doi": MATERIALS_RESTERS["doi"], **{f"molecules/{k}": v for k, v in MOLECULES_RESTERS.items()}, +} +GENERIC_RESTERS = { + "doi": MATERIALS_RESTERS["doi"], **GENERIC_RESTERS, } @@ -201,6 +203,9 @@ def __init__( for attr, rester in core_resters.items(): setattr(self, attr, rester) + for attr, rester in GENERIC_RESTERS.items(): + setattr(self, attr, rester) + @property def contribs(self): if self._contribs is None: From ac296fa9d8cef6c2c99ee0e3b86dd856df5504a8 Mon Sep 17 00:00:00 2001 From: Tyler Mathis <35553152+tsmathis@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:40:29 -0800 Subject: [PATCH 06/11] patch --- mp_api/client/mprester.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/mp_api/client/mprester.py b/mp_api/client/mprester.py index 1cf1a0d3..a7fd98a7 100644 --- a/mp_api/client/mprester.py +++ b/mp_api/client/mprester.py @@ -203,7 +203,21 @@ def __init__( for attr, rester in core_resters.items(): setattr(self, attr, rester) - for attr, rester in GENERIC_RESTERS.items(): + # set generics TODO!: refactor + generic_resters = { + rest_name: lazy_rester( + api_key=self.api_key, + endpoint=self.endpoint, + include_user_agent=self._include_user_agent, + session=self.session, + use_document_model=self.use_document_model, + headers=self.headers, + mute_progress_bars=self.mute_progress_bars, + ) + for rest_name, lazy_rester in GENERIC_RESTERS.items() + } + + for attr, rester in generic_resters.items(): setattr(self, attr, rester) @property From 9625174f04d6502021e7a17576d8e0ff7a30aa8c Mon Sep 17 00:00:00 2001 From: esoteric-ephemera Date: Mon, 26 Jan 2026 10:15:41 -0800 Subject: [PATCH 07/11] only warn if api key is not set to allow server to work --- mp_api/client/core/utils.py | 19 ++++++++++++++----- tests/client/test_mprester.py | 4 ++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/mp_api/client/core/utils.py b/mp_api/client/core/utils.py index 23c14164..2a8e6510 100644 --- a/mp_api/client/core/utils.py +++ b/mp_api/client/core/utils.py @@ -1,6 +1,7 @@ from __future__ import annotations import os +import warnings from importlib import import_module from typing import TYPE_CHECKING, Literal from urllib.parse import urljoin @@ -11,7 +12,7 @@ from monty.json import MontyDecoder from packaging.version import parse as parse_version -from mp_api.client.core.exceptions import MPRestError +from mp_api.client.core.exceptions import MPRestError, MPRestWarning from mp_api.client.core.settings import MAPI_CLIENT_SETTINGS if TYPE_CHECKING: @@ -54,7 +55,7 @@ def load_json( return MontyDecoder().process_decoded(data) if deser else data -def validate_api_key(api_key: str | None = None) -> str: +def validate_api_key(api_key: str | None = None) -> str | None: """Find and validate an API key.""" # SETTINGS tries to read API key from ~/.config/.pmgrc.yaml api_key = api_key or os.getenv("MP_API_KEY") @@ -63,11 +64,19 @@ def validate_api_key(api_key: str | None = None) -> str: api_key = PMG_SETTINGS.get("PMG_MAPI_KEY") - if not api_key or len(api_key) != 32: - addendum = " Valid API keys are 32 characters." if api_key else "" + if not api_key: + warnings.warn( + "No API key found, please set explicitly or in " + "the `MP_API_KEY` environment variable.", + category=MPRestWarning, + stacklevel=2, + ) + + elif isinstance(api_key, str) and len(api_key) != 32: raise MPRestError( "Please obtain a valid API key from https://materialsproject.org/api " - f"and export it as an environment variable `MP_API_KEY`.{addendum}" + "and export it as an environment variable `MP_API_KEY`. " + "Valid API keys are 32 characters." ) return api_key diff --git a/tests/client/test_mprester.py b/tests/client/test_mprester.py index f85a621a..63774a49 100644 --- a/tests/client/test_mprester.py +++ b/tests/client/test_mprester.py @@ -430,8 +430,8 @@ def test_get_default_api_key_endpoint(self, monkeypatch: pytest.MonkeyPatch): monkeypatch.delenv("MP_API_KEY", raising=False) monkeypatch.delenv("PMG_MAPI_KEY", raising=False) monkeypatch.setitem(SETTINGS, "PMG_MAPI_KEY", None) - with pytest.raises(MPRestError, match="Please obtain a valid API key"): - MPRester().get_structure_by_material_id("mp-149") + with pytest.warns(MPRestWarning, match="No API key found"): + MPRester() def test_invalid_api_key(self, monkeypatch): monkeypatch.setenv("MP_API_KEY", "INVALID") From bd94974afb91035a17f33f1fb7f3a9dfc8422135 Mon Sep 17 00:00:00 2001 From: esoteric-ephemera Date: Mon, 26 Jan 2026 10:53:42 -0800 Subject: [PATCH 08/11] clean up top-level rester init --- mp_api/client/core/utils.py | 3 ++ mp_api/client/mprester.py | 70 +++++++++++++++------------------ tests/client/core/test_utils.py | 5 +-- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/mp_api/client/core/utils.py b/mp_api/client/core/utils.py index 2a8e6510..935e1453 100644 --- a/mp_api/client/core/utils.py +++ b/mp_api/client/core/utils.py @@ -65,6 +65,9 @@ def validate_api_key(api_key: str | None = None) -> str | None: api_key = PMG_SETTINGS.get("PMG_MAPI_KEY") if not api_key: + # The web server requires the client to initialize without an API key. + # Only warn the user if the API key cannot be identified to permit + # the web server to run. warnings.warn( "No API key found, please set explicitly or in " "the `MP_API_KEY` environment variable.", diff --git a/mp_api/client/mprester.py b/mp_api/client/mprester.py index a7fd98a7..1d9afc5c 100644 --- a/mp_api/client/mprester.py +++ b/mp_api/client/mprester.py @@ -59,6 +59,15 @@ **GENERIC_RESTERS, } +TOP_LEVEL_RESTERS = [ + "molecules/core", + "materials/core", + "_general_store", + "_messages", + "_user_settings", + "doi", +] + class MPRester: """Access the new Materials Project API.""" @@ -181,44 +190,23 @@ def __init__( # Nested rested are then setup to be loaded dynamically with custom __getattr__ functions. self._all_resters = list(RESTER_LAYOUT.values()) - # Instantiate top level molecules and materials resters and set them as attributes - core_suffix = ["molecules/core", "materials/core"] - - core_resters = { - rest_name.split("/")[0]: lazy_rester( - api_key=self.api_key, - endpoint=self.endpoint, - include_user_agent=self._include_user_agent, - session=self.session, - use_document_model=self.use_document_model, - headers=self.headers, - mute_progress_bars=self.mute_progress_bars, - ) - for rest_name, lazy_rester in RESTER_LAYOUT.items() - if rest_name in core_suffix - } - - # Set remaining top level resters, or get an attribute-class name mapping - - for attr, rester in core_resters.items(): - setattr(self, attr, rester) - - # set generics TODO!: refactor - generic_resters = { - rest_name: lazy_rester( - api_key=self.api_key, - endpoint=self.endpoint, - include_user_agent=self._include_user_agent, - session=self.session, - use_document_model=self.use_document_model, - headers=self.headers, - mute_progress_bars=self.mute_progress_bars, - ) - for rest_name, lazy_rester in GENERIC_RESTERS.items() - } - - for attr, rester in generic_resters.items(): - setattr(self, attr, rester) + # Instantiate top level core molecules, materials, and DOI resters, as well + # as the sunder resters to allow the web server to work. + for rest_name, lazy_rester in (RESTER_LAYOUT | GENERIC_RESTERS).items(): + if rest_name in TOP_LEVEL_RESTERS: + setattr( + self, + rest_name.split("/")[0], + lazy_rester( + api_key=self.api_key, + endpoint=self.endpoint, + include_user_agent=self._include_user_agent, + session=self.session, + use_document_model=self.use_document_model, + headers=self.headers, + mute_progress_bars=self.mute_progress_bars, + ), + ) @property def contribs(self): @@ -268,7 +256,11 @@ def __getattr__(self, attr): ) def __dir__(self): - return dir(MPRester) + self._deprecated_attributes + ["materials", "molecules"] + return ( + dir(MPRester) + + self._deprecated_attributes + + [r.split("/", 1)[0] for r in TOP_LEVEL_RESTERS if not r.startswith("_")] + ) def get_task_ids_associated_with_material_id( self, material_id: str, calc_types: list[CalcType] | None = None diff --git a/tests/client/core/test_utils.py b/tests/client/core/test_utils.py index b9cba460..c8916a3c 100644 --- a/tests/client/core/test_utils.py +++ b/tests/client/core/test_utils.py @@ -1,9 +1,8 @@ """Test client core utilities.""" -from packaging.version import parse as parse_version import pytest -from mp_api.client.core.exceptions import MPRestError +from mp_api.client.core.exceptions import MPRestError, MPRestWarning from mp_api.client.core.utils import LazyImport @@ -145,7 +144,7 @@ def test_api_key_validation(monkeypatch: pytest.MonkeyPatch): with pytest.raises(MPRestError, match="32 characters"): validate_api_key("invalid_key") - with pytest.raises(MPRestError, match="Please obtain a valid"): + with pytest.warns(MPRestWarning, match="No API key found"): validate_api_key() junk_api_key = "a" * 32 From d5a0a29e1e3fea59f70f60ded2d44f29b2e99ae1 Mon Sep 17 00:00:00 2001 From: esoteric-ephemera Date: Mon, 26 Jan 2026 13:40:47 -0800 Subject: [PATCH 09/11] allow for MP_API_ENDPOINT to take precedence --- mp_api/client/core/settings.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mp_api/client/core/settings.py b/mp_api/client/core/settings.py index a7b98376..f5818d57 100644 --- a/mp_api/client/core/settings.py +++ b/mp_api/client/core/settings.py @@ -85,9 +85,7 @@ class MAPIClientSettings(BaseSettings): _MAX_LIST_LENGTH, description="Maximum length of query parameter list" ) - ENDPOINT: str = Field( - _DEFAULT_ENDPOINT, description="The default API endpoint to use." - ) + ENDPOINT: str = Field("", description="The default API endpoint to use.") LTOL: float = Field( _EMMET_SETTINGS.LTOL, From f43237f7c2a8c89a6b0e394202a75fe0981c64d8 Mon Sep 17 00:00:00 2001 From: Tyler Mathis <35553152+tsmathis@users.noreply.github.com> Date: Fri, 30 Jan 2026 10:47:20 -0800 Subject: [PATCH 10/11] bump emmet-core to main release segment --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ce8646ca..d91f4029 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "typing-extensions>=3.7.4.1", "requests>=2.23.0", "monty>=2024.12.10", - "emmet-core>=0.86.3rc1,<0.87.0", + "emmet-core>=0.86.3", "boto3", "orjson >= 3.10,<4", ] @@ -33,7 +33,7 @@ dynamic = ["version"] [project.optional-dependencies] mcp = ["fastmcp"] all = [ - "emmet-core[all]>=0.86.3rc1,<0.87.0", + "emmet-core[all]>=0.86.3", "custodian", "mpcontribs-client>=5.10", "fastmcp", From e3f280a678e18636ca3ddcb1f5463e128cd15c81 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 Jan 2026 18:48:54 +0000 Subject: [PATCH 11/11] auto dependency upgrades --- .../requirements-ubuntu-latest_py3.11.txt | 10 +++--- ...quirements-ubuntu-latest_py3.11_extras.txt | 34 +++++++++---------- .../requirements-ubuntu-latest_py3.12.txt | 10 +++--- ...quirements-ubuntu-latest_py3.12_extras.txt | 34 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/requirements/requirements-ubuntu-latest_py3.11.txt b/requirements/requirements-ubuntu-latest_py3.11.txt index c98cfb87..b83dc92a 100644 --- a/requirements/requirements-ubuntu-latest_py3.11.txt +++ b/requirements/requirements-ubuntu-latest_py3.11.txt @@ -6,13 +6,13 @@ # annotated-types==0.7.0 # via pydantic -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.33 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.33 +botocore==1.42.38 # via # boto3 # s3transfer @@ -24,7 +24,7 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.86.3rc1 +emmet-core==0.86.3 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib @@ -63,7 +63,7 @@ numpy==2.4.1 # pymatgen-io-validation # scipy # spglib -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen diff --git a/requirements/requirements-ubuntu-latest_py3.11_extras.txt b/requirements/requirements-ubuntu-latest_py3.11_extras.txt index 466b050d..ffc1a886 100644 --- a/requirements/requirements-ubuntu-latest_py3.11_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.11_extras.txt @@ -35,15 +35,15 @@ beartype==0.22.9 # via # py-key-value-aio # py-key-value-shared -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.33 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.33 +botocore==1.42.38 # via # boto3 # s3transfer @@ -51,7 +51,7 @@ bravado==12.0.1 # via mpcontribs-client bravado-core==6.1.1 # via bravado -cachetools==6.2.4 +cachetools==6.2.6 # via # mpcontribs-client # py-key-value-aio @@ -74,9 +74,9 @@ cloudpickle==3.1.2 # via pydocket contourpy==1.3.3 # via matplotlib -coverage[toml]==7.13.1 +coverage[toml]==7.13.2 # via pytest-cov -cryptography==46.0.3 +cryptography==46.0.4 # via # authlib # pyjwt @@ -85,7 +85,7 @@ custodian==2025.12.14 # via mp-api (pyproject.toml) cycler==0.12.1 # via matplotlib -cyclopts==4.5.0 +cyclopts==4.5.1 # via fastmcp decorator==5.2.1 # via ipython @@ -106,7 +106,7 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.86.3rc1 +emmet-core[all]==0.86.3 # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp @@ -247,7 +247,7 @@ matplotlib-inline==0.2.1 # via ipython mccabe==0.7.0 # via flake8 -mcp==1.25.0 +mcp==1.26.0 # via fastmcp mdurl==0.1.2 # via markdown-it-py @@ -333,7 +333,7 @@ opentelemetry-semantic-conventions==0.60b1 # via # opentelemetry-instrumentation # opentelemetry-sdk -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen @@ -359,7 +359,7 @@ parso==0.8.5 # via jedi pathable==0.4.4 # via jsonschema-path -pathspec==1.0.3 +pathspec==1.0.4 # via mypy pathvalidate==3.3.1 # via py-key-value-aio @@ -393,7 +393,7 @@ prometheus-client==0.24.1 # pydocket prompt-toolkit==3.0.52 # via ipython -psutil==7.2.1 +psutil==7.2.2 # via custodian ptyprocess==0.7.0 # via pexpect @@ -508,7 +508,7 @@ python-dotenv==1.2.1 # pydantic-settings python-json-logger==4.0.0 # via pydocket -python-multipart==0.0.21 +python-multipart==0.0.22 # via mcp pytz==2025.2 # via @@ -551,7 +551,7 @@ rfc3986-validator==0.1.1 # via jsonschema rfc3987-syntax==1.1.0 # via jsonschema -rich==14.2.0 +rich==14.3.1 # via # cyclopts # fastmcp @@ -653,7 +653,7 @@ tabulate==0.9.0 # via pymatgen threadpoolctl==3.6.0 # via scikit-learn -tifffile==2026.1.14 +tifffile==2026.1.28 # via scikit-image tqdm==4.67.1 # via @@ -670,7 +670,7 @@ typer==0.21.1 # via pydocket types-requests==2.32.4.20260107 # via mp-api (pyproject.toml) -types-setuptools==80.9.0.20251223 +types-setuptools==80.10.0.20260124 # via mp-api (pyproject.toml) typing-extensions==4.15.0 # via @@ -727,7 +727,7 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.3.1 +wcwidth==0.5.2 # via prompt-toolkit webcolors==25.10.0 # via jsonschema diff --git a/requirements/requirements-ubuntu-latest_py3.12.txt b/requirements/requirements-ubuntu-latest_py3.12.txt index b16c3817..9822afda 100644 --- a/requirements/requirements-ubuntu-latest_py3.12.txt +++ b/requirements/requirements-ubuntu-latest_py3.12.txt @@ -6,13 +6,13 @@ # annotated-types==0.7.0 # via pydantic -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.33 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.33 +botocore==1.42.38 # via # boto3 # s3transfer @@ -24,7 +24,7 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.86.3rc1 +emmet-core==0.86.3 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib @@ -63,7 +63,7 @@ numpy==2.4.1 # pymatgen-io-validation # scipy # spglib -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen diff --git a/requirements/requirements-ubuntu-latest_py3.12_extras.txt b/requirements/requirements-ubuntu-latest_py3.12_extras.txt index ca8027f6..6c0f7e0e 100644 --- a/requirements/requirements-ubuntu-latest_py3.12_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.12_extras.txt @@ -33,15 +33,15 @@ beartype==0.22.9 # via # py-key-value-aio # py-key-value-shared -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.33 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.33 +botocore==1.42.38 # via # boto3 # s3transfer @@ -49,7 +49,7 @@ bravado==12.0.1 # via mpcontribs-client bravado-core==6.1.1 # via bravado -cachetools==6.2.4 +cachetools==6.2.6 # via # mpcontribs-client # py-key-value-aio @@ -72,9 +72,9 @@ cloudpickle==3.1.2 # via pydocket contourpy==1.3.3 # via matplotlib -coverage[toml]==7.13.1 +coverage[toml]==7.13.2 # via pytest-cov -cryptography==46.0.3 +cryptography==46.0.4 # via # authlib # pyjwt @@ -83,7 +83,7 @@ custodian==2025.12.14 # via mp-api (pyproject.toml) cycler==0.12.1 # via matplotlib -cyclopts==4.5.0 +cyclopts==4.5.1 # via fastmcp decorator==5.2.1 # via ipython @@ -104,7 +104,7 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.86.3rc1 +emmet-core[all]==0.86.3 # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp @@ -243,7 +243,7 @@ matplotlib-inline==0.2.1 # via ipython mccabe==0.7.0 # via flake8 -mcp==1.25.0 +mcp==1.26.0 # via fastmcp mdurl==0.1.2 # via markdown-it-py @@ -329,7 +329,7 @@ opentelemetry-semantic-conventions==0.60b1 # via # opentelemetry-instrumentation # opentelemetry-sdk -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen @@ -355,7 +355,7 @@ parso==0.8.5 # via jedi pathable==0.4.4 # via jsonschema-path -pathspec==1.0.3 +pathspec==1.0.4 # via mypy pathvalidate==3.3.1 # via py-key-value-aio @@ -389,7 +389,7 @@ prometheus-client==0.24.1 # pydocket prompt-toolkit==3.0.52 # via ipython -psutil==7.2.1 +psutil==7.2.2 # via custodian ptyprocess==0.7.0 # via pexpect @@ -504,7 +504,7 @@ python-dotenv==1.2.1 # pydantic-settings python-json-logger==4.0.0 # via pydocket -python-multipart==0.0.21 +python-multipart==0.0.22 # via mcp pytz==2025.2 # via @@ -547,7 +547,7 @@ rfc3986-validator==0.1.1 # via jsonschema rfc3987-syntax==1.1.0 # via jsonschema -rich==14.2.0 +rich==14.3.1 # via # cyclopts # fastmcp @@ -649,7 +649,7 @@ tabulate==0.9.0 # via pymatgen threadpoolctl==3.6.0 # via scikit-learn -tifffile==2026.1.14 +tifffile==2026.1.28 # via scikit-image tqdm==4.67.1 # via @@ -666,7 +666,7 @@ typer==0.21.1 # via pydocket types-requests==2.32.4.20260107 # via mp-api (pyproject.toml) -types-setuptools==80.9.0.20251223 +types-setuptools==80.10.0.20260124 # via mp-api (pyproject.toml) typing-extensions==4.15.0 # via @@ -721,7 +721,7 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.3.1 +wcwidth==0.5.2 # via prompt-toolkit webcolors==25.10.0 # via jsonschema