Skip to content

Commit a1b469c

Browse files
schematize metadata + field annotations
1 parent 4217daf commit a1b469c

4 files changed

Lines changed: 436 additions & 47 deletions

File tree

mp_api/client/core/utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
if TYPE_CHECKING:
1616
from typing import Any
1717

18-
_MAPI_SETTINGS = MAPIClientSettings()
19-
2018

2119
def _compare_emmet_ver(
2220
ref_version: str, op: Literal["==", ">", ">=", "<", "<="]

mp_api/mcp/_schemas.py

Lines changed: 287 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,285 @@
88
from mp_api.client.core.utils import validate_ids
99

1010

11-
class OpenAIResult(BaseModel):
12-
"""Schematize result for OpenAI support."""
11+
class MaterialMetadata(BaseModel):
12+
"""Define metadata associated to a material.
1313
14-
id: str
15-
title: str | None = None
16-
text: str | None = None
17-
url: str | None = None
18-
metadata: dict[str, str] | None = None
14+
These fields are a subset of the `emmet.core.summary.SummaryDoc`
15+
model fields, with a few extra fields to include
16+
robocrystallographer autogenerated descriptions and similarity scores.
17+
"""
18+
19+
nsites: int | None = Field(
20+
None,
21+
description="The number of sites in the structure as found on the Materials Project.",
22+
)
23+
24+
nelements: int | None = Field(
25+
None, description="The number of unique elements in this structure."
26+
)
27+
formula_pretty: str | None = Field(
28+
None, description="The chemical formula of this material."
29+
)
30+
formula_anonymous: str | None = Field(
31+
None,
32+
description="The chemical formula of this material's prototype, i.e., without sp.",
33+
)
34+
chemsys: str | None = Field(
35+
None,
36+
description="A dash-delimited string separating the unique elements in this material.",
37+
)
38+
volume: float | None = Field(
39+
None,
40+
description="The volume of the structure associated with this material in cubic Angstrom (ų).",
41+
)
42+
density: float | None = Field(
43+
None,
44+
description="The volume of the structure associated with this material in grams per cubic centimeter (g/cm³).",
45+
)
46+
density_atomic: float | None = Field(
47+
None,
48+
description="The volume per atom of the structure associated with this material in ų/atom.",
49+
)
50+
51+
space_group_number: int | None = Field(
52+
None,
53+
description="The international space group number of this material (Reference: https://en.wikipedia.org/wiki/Space_group#Table_of_space_groups_in_3_dimensions).",
54+
)
55+
56+
space_group_symbol: str | None = Field(
57+
None,
58+
description="The international space group symbol of this material (Reference: https://en.wikipedia.org/wiki/Space_group#Table_of_space_groups_in_3_dimensions).",
59+
)
60+
61+
crystal_system: str | None = Field(
62+
None,
63+
description="The crystal system of this material (Reference: https://en.wikipedia.org/wiki/Crystal_system)",
64+
)
65+
66+
point_group: str | None = Field(None, description="The point group of the lattice.")
67+
68+
material_id: str | None = Field(
69+
None,
70+
description="The Materials Project ID of this material, generally of the form `mp-1`, `mp-2`, etc.",
71+
)
72+
73+
deprecated: bool = Field(
74+
True,
75+
description=(
76+
"If True, the Materials Project considers this material to be deprecated / untrustworthy. "
77+
"If False, the data contained herein should be considered robust."
78+
),
79+
)
80+
81+
formation_energy_per_atom: float | None = Field(
82+
None,
83+
description="The DFT-computed enthalpy of formation at zero kelvin (0K) with corrections, in eV/atom.",
84+
)
85+
86+
energy_above_hull: float | None = Field(
87+
None,
88+
description=(
89+
"The energy above the thermodynamic hull for this material, in eV/atom. "
90+
"This quantity is non-negative. Zero indicates a stable material. "
91+
"Small values indicate slightly unstable materials, which may stabilize at "
92+
"higher temperatures. Large values indicate highly unstable materials."
93+
),
94+
)
95+
96+
is_stable: bool | None = Field(
97+
None,
98+
description="Whether this material lies on the hull, i.e., its `energy_above_hull` is almost zero.",
99+
)
100+
101+
equilibrium_reaction_energy_per_atom: float | None = Field(
102+
None,
103+
description="The reaction energy of a stable entry from the neighboring equilibrium stable materials in eV."
104+
" Also known as the inverse distance to hull.",
105+
)
106+
107+
band_gap: float | None = Field(
108+
None,
109+
description="The electronic band gap energy in eV.",
110+
)
111+
112+
cbm: float | None = Field(
113+
None,
114+
description="The Conduction Band Minimum (CBM) in eV.",
115+
)
116+
117+
vbm: float | None = Field(
118+
None,
119+
description="The Valence Band Maximum (VBM) in eV.",
120+
)
121+
122+
efermi: float | None = Field(
123+
None,
124+
description="The Fermi energy (or Fermi level) in eV.",
125+
)
126+
127+
is_gap_direct: bool | None = Field(
128+
None,
129+
description="Whether the band gap is direct.",
130+
)
131+
132+
is_metal: bool | None = Field(
133+
None,
134+
description="Whether the material is a metal (`band_gap` = 0).",
135+
)
136+
137+
is_magnetic: bool | None = Field(
138+
None,
139+
description="Whether the material is magnetic.",
140+
)
141+
142+
ordering: str | None = Field(
143+
None,
144+
description=(
145+
"Type of collinear magnetic ordering: "
146+
"`NM` indicates non-magnetic, "
147+
"`FM` indicates ferromagnetic, "
148+
"`FiM` indicates ferrimagnetic, "
149+
"and `AFM` indicates antiferromagnetic."
150+
),
151+
)
152+
153+
total_magnetization: float | None = Field(
154+
None,
155+
description="Total magnetization in Bohr magneton, μB.",
156+
)
157+
158+
total_magnetization_normalized_vol: float | None = Field(
159+
None,
160+
description="Total magnetization normalized by volume in μB/ų.",
161+
)
162+
163+
total_magnetization_normalized_formula_units: float | None = Field(
164+
None,
165+
description="Total magnetization normalized by formula unit in μB/(formula unit).",
166+
)
167+
168+
num_magnetic_sites: int | None = Field(
169+
None,
170+
description="The number of magnetic sites.",
171+
)
172+
173+
num_unique_magnetic_sites: int | None = Field(
174+
None,
175+
description="The number of unique magnetic sites.",
176+
)
177+
178+
bulk_modulus_voigt: float | None = Field(
179+
None, description="Voigt average of the bulk modulus in gigapascal (GPa)."
180+
)
181+
182+
bulk_modulus_reuss: float | None = Field(
183+
None, description="Reuss average of the bulk modulus in GPa."
184+
)
185+
186+
bulk_modulus_vrh: float | None = Field(
187+
None, description="Voigt-Reuss-Hill average of the bulk modulus in GPa."
188+
)
189+
190+
shear_modulus_voigt: float | None = Field(
191+
None, description="Voigt average of the shear modulus in GPa."
192+
)
193+
194+
shear_modulus_reuss: float | None = Field(
195+
None, description="Reuss average of the shear modulus in GPa."
196+
)
197+
198+
shear_modulus_vrh: float | None = Field(
199+
None, description="Voigt-Reuss-Hill average of the shear modulus in GPa."
200+
)
201+
202+
universal_anisotropy: float | None = Field(
203+
None, description="Elastic anisotropy, dimensionless."
204+
)
205+
206+
homogeneous_poisson: float | None = Field(
207+
None, description="Poisson ratio, dimensionless."
208+
)
209+
210+
e_total: float | None = Field(
211+
None,
212+
description="Total dielectric constant, dimensionless.",
213+
)
214+
215+
e_ionic: float | None = Field(
216+
None,
217+
description="Ionic contribution to dielectric constant, dimensionless.",
218+
)
219+
220+
e_electronic: float | None = Field(
221+
None,
222+
description="Electronic contribution to dielectric constant, dimensionless.",
223+
)
224+
225+
n: float | None = Field(
226+
None,
227+
description="The optical refractive index, dimensionless.",
228+
)
229+
230+
theoretical: bool = Field(
231+
True,
232+
description=(
233+
"Whether the material has not been matched to a structure "
234+
"in an experimental database. If this is `True`, then both "
235+
"`linked_icsd_ids` and `linked_pf_ids` should be `None`."
236+
),
237+
)
238+
239+
linked_icsd_ids: str | None = Field(
240+
None,
241+
description=(
242+
"A comma-delimited list of Inorganic Crystal Structure Database "
243+
"(ICSD) identifiers of materials which have been matched to this "
244+
"material. Example: 'icsd-1, icsd-2, icsd-10'"
245+
),
246+
)
247+
248+
linked_pf_ids: str | None = Field(
249+
None,
250+
description=(
251+
"A comma-delimited list of Pauling File (pf) "
252+
"identifiers of materials which have been matched to this "
253+
"material. Example: 'pf-1, pf-2, pf-10'"
254+
),
255+
)
256+
257+
structurally_similar_materials: str | None = Field(
258+
None,
259+
description=(
260+
"A comma-delimited list of structurally similar materials "
261+
"in the Materials Project, with additional information about their "
262+
"chemistry and similarity ranking. Example: "
263+
r"'mp-104: LiS (98.1% similar); mp-50505: NaP (94.3% similar)'"
264+
),
265+
)
266+
267+
268+
class FetchResult(BaseModel):
269+
"""Schematize result of the `fetch` MCP tool.
270+
271+
This schema is designed for compatibility with OpenAI's spec:
272+
https://platform.openai.com/docs/mcp#fetch-tool
273+
274+
However it should be compatible with other LLMs as well.
275+
"""
276+
277+
id: str = Field(
278+
description="The Materials Project ID of this entry, of the form `mp-13`."
279+
)
280+
title: str | None = Field(None, description="Typically the Materials Project ID.")
281+
text: str | None = Field(
282+
None,
283+
description="The robocrystallographer autogenerated description of this material.",
284+
)
285+
url: str | None = Field(None, description="A link to the Materials Project website")
286+
metadata: MaterialMetadata | None = Field(
287+
None,
288+
description="Auxiliary materials data aggregated from the summary and similarity collections in the Materials Project.",
289+
)
19290

20291
@model_validator(mode="before")
21292
def set_url(cls, config: Any) -> Any:
@@ -31,7 +302,13 @@ def set_url(cls, config: Any) -> Any:
31302
return config
32303

33304

34-
class OpenAISearchOutput(BaseModel):
35-
"""Schematize data for OpenAI support."""
305+
class SearchOutput(BaseModel):
306+
"""Schematize data for the MCP `search` tool.
307+
308+
This schema is designed for compatibility with OpenAI's spec:
309+
https://platform.openai.com/docs/mcp#search-tool
310+
311+
But will also be compatible with most other LLMs.
312+
"""
36313

37-
results: list[OpenAIResult] = Field([])
314+
results: list[FetchResult] = Field([], description="A list of results")

0 commit comments

Comments
 (0)