Skip to content

Commit 2d3b0ba

Browse files
precommit
1 parent a8584e4 commit 2d3b0ba

4 files changed

Lines changed: 39 additions & 47 deletions

File tree

mp_api/mcp/_schemas.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,37 @@
11
"""Define auxiliary schemas used by some LLMs."""
2+
from __future__ import annotations
23

34
from typing import Any
5+
46
from pydantic import BaseModel, Field, model_validator
57

68
from mp_api.client.core.utils import validate_ids
79

10+
811
class OpenAIResult(BaseModel):
912
"""Schematize result for OpenAI support."""
1013

11-
id : str
12-
title : str | None = None
13-
text : str | None = None
14-
url : str | None = None
15-
metadata : dict[str,str] | None = None
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
1619

1720
@model_validator(mode="before")
18-
def set_url(cls, config : Any) -> Any:
21+
def set_url(cls, config: Any) -> Any:
1922
"""Set default Materials Project URL and title."""
20-
2123
formatted_mpid = validate_ids([config.get("id")])[0]
2224
if not config.get("title"):
2325
config["title"] = formatted_mpid
2426

2527
if not config.get("url"):
26-
config["url"] = (
27-
"https://next-gen.materialsproject.org/materials/"
28-
f"{formatted_mpid}"
28+
config["url"] = (
29+
"https://next-gen.materialsproject.org/materials/" f"{formatted_mpid}"
2930
)
3031
return config
3132

33+
3234
class OpenAISearchOutput(BaseModel):
3335
"""Schematize data for OpenAI support."""
3436

35-
results : list[OpenAIResult] = Field([])
37+
results: list[OpenAIResult] = Field([])

mp_api/mcp/mp_mcp.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@
1717
Then use the fetch tool to retrieve complete materials summary information.
1818
"""
1919

20+
2021
def get_openai_compat_mcp() -> FastMCP:
2122
"""Create MCP for compatibility with OpenAI models."""
2223
mp_mcp = FastMCP(
2324
"Materials_Project_MCP",
2425
instructions=MCP_SERVER_INSTRUCTIONS,
2526
)
2627
openai_compat_tools = MPOpenAIMcpTools()
27-
for k in {"search","fetch"}:
28-
mp_mcp.tool(getattr(openai_compat_tools,k))
28+
for k in {"search", "fetch"}:
29+
mp_mcp.tool(getattr(openai_compat_tools, k))
2930
return mp_mcp
3031

32+
3133
def get_mcp() -> FastMCP:
3234
"""MCP with finer depth of control over tool names."""
3335
mp_mcp = FastMCP("Materials_Project_MCP")

mp_api/mcp/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Run MCP."""
22
from __future__ import annotations
33

4-
from mp_api.mcp.mp_mcp import get_mcp, get_openai_compat_mcp
4+
from mp_api.mcp.mp_mcp import get_openai_compat_mcp
55

66
mcp = get_openai_compat_mcp()
77

mp_api/mcp/tools.py

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,37 +32,35 @@
3232
from mp_api.mcp.utils import _NeedsMPClient
3333
from mp_api.mcp._schemas import OpenAISearchOutput, OpenAIResult
3434

35+
3536
class MPOpenAIMcpTools(_NeedsMPClient):
3637
"""Define OpenAI-specific MCP for the Materials Project API."""
3738

38-
def search(self, query : str) -> OpenAISearchOutput:
39+
def search(self, query: str) -> OpenAISearchOutput:
3940
"""Define OpenAI compatible search.
40-
41+
4142
Search through the autogenerated robocrystallographer
4243
descriptions of materials to return lists of likely
4344
matching materials.
4445
4546
Args:
4647
query (str) : A natural language query of material keywords.
4748
It is assumed that the query contains comma-delimited keywords.
48-
49-
Returns:
49+
50+
Returns:
5051
OpenAISearchOutput, a dict of `results` each with structure
5152
mp_api.mcp._schemas.OpenAIResult
5253
"""
5354
return OpenAISearchOutput(
54-
retults = [
55-
OpenAIResult(
56-
id = doc["material_id"],
57-
text = doc["description"]
58-
)
55+
retults=[
56+
OpenAIResult(id=doc["material_id"], text=doc["description"])
5957
for doc in self.client.robocrys.search(query.split(","))
6058
]
6159
)
6260

63-
def fetch(self, idx : str) -> OpenAIResult:
61+
def fetch(self, idx: str) -> OpenAIResult:
6462
"""Retrieve complete material information by Materials Project ID.
65-
63+
6664
Args:
6765
idx (str) : A Materials Project ID.
6866
Should be an integer prefixed by `mp-`, ex: "mp-149", "mp-13"
@@ -78,33 +76,25 @@ def fetch(self, idx : str) -> OpenAIResult:
7876
Raises:
7977
MPRestError: If no identifier is specified
8078
"""
81-
if not isinstance(idx,str):
79+
if not isinstance(idx, str):
8280
raise MPRestError(
8381
f"Unknown {idx=}. Should be an integer prefixed by `mp-`, ex: "
8482
"'mp-1', 'mp-1010101'"
8583
)
8684

87-
robo_desc : str | None = None
88-
if len(
89-
robo_docs := self.client.robocrys.search_docs(
90-
material_ids=[idx]
91-
)
92-
) > 0:
85+
robo_desc: str | None = None
86+
if len(robo_docs := self.client.robocrys.search_docs(material_ids=[idx])) > 0:
9387
robo_desc = robo_docs[0]["description"]
9488

9589
if not robo_desc:
96-
return OpenAIResult(id = idx)
90+
return OpenAIResult(id=idx)
9791

98-
metadata : dict[str,str] | None = None
99-
if len(
100-
summary_docs := self.client.summary.search(
101-
material_ids=[idx]
102-
)
103-
) > 0:
92+
metadata: dict[str, str] | None = None
93+
if len(summary_docs := self.client.summary.search(material_ids=[idx])) > 0:
10494
# Try to avoid more nested fields, just provide things with
10595
# simple str or numeric type
10696
metadata = {
107-
k : str(summary_docs[0][k])
97+
k: str(summary_docs[0][k])
10898
for k in self.client.summary.document_model.model_fields
10999
if isinstance(summary_docs[0][k], str | int | float)
110100
}
@@ -113,16 +103,14 @@ def fetch(self, idx : str) -> OpenAIResult:
113103
if summary_docs[0]["database_IDs"]:
114104
metadata.update(
115105
{
116-
f"linked_{database}_ids" : ", ".join(matched_ids)
117-
for database, matched_ids in summary_docs[0]["database_IDs"].items()
106+
f"linked_{database}_ids": ", ".join(matched_ids)
107+
for database, matched_ids in summary_docs[0][
108+
"database_IDs"
109+
].items()
118110
}
119111
)
120112

121-
return OpenAIResult(
122-
id = idx,
123-
text = robo_desc,
124-
metadata = metadata
125-
)
113+
return OpenAIResult(id=idx, text=robo_desc, metadata=metadata)
126114

127115

128116
class MPMcpTools(_NeedsMPClient):

0 commit comments

Comments
 (0)