guohanghui commited on
Commit
06210c4
·
verified ·
1 Parent(s): 07c1785

Update atomman/mcp_output/mcp_plugin/mcp_service.py

Browse files
atomman/mcp_output/mcp_plugin/mcp_service.py CHANGED
@@ -1,124 +1,261 @@
1
  from fastmcp import FastMCP
 
2
 
3
  # Create the FastMCP service application
4
  mcp = FastMCP("atomman_service")
5
 
6
- @mcp.tool(name="list_lattice_parameters", description="List lattice parameters of a crystal structure")
7
- def list_lattice_parameters(lattice: dict) -> dict:
 
8
  """
9
- List the lattice parameters of a given crystal structure.
10
 
11
  Parameters:
12
- - lattice: A dictionary containing lattice vectors and angles.
 
13
 
14
  Returns:
15
- - dict: Lattice parameters including a, b, c, alpha, beta, gamma.
16
  """
17
  try:
18
- from atomman.lattice import Lattice
19
-
20
- lattice_obj = Lattice(**lattice)
21
- params = lattice_obj.parameters()
22
-
23
  return {
24
  "success": True,
25
- "parameters": params
 
 
26
  }
27
  except Exception as e:
28
  return {"success": False, "error": str(e)}
29
 
30
- @mcp.tool(name="calculate_displacement", description="Calculate atomic displacements in a system")
31
- def calculate_displacement(system: dict, displacements: list) -> dict:
 
32
  """
33
- Calculate atomic displacements in a system.
34
 
35
  Parameters:
36
- - system: A dictionary representing the atomic system.
37
- - displacements: A list of displacement vectors.
38
 
39
  Returns:
40
- - dict: Updated atomic positions after applying displacements.
41
  """
42
  try:
43
- from atomman import System
44
-
45
- system_obj = System(**system)
46
- system_obj.displace(displacements)
47
-
48
  return {
49
  "success": True,
50
- "updated_positions": system_obj.atoms.pos
 
 
 
 
 
 
 
51
  }
52
  except Exception as e:
53
  return {"success": False, "error": str(e)}
54
 
55
- @mcp.tool(name="compute_elastic_constants", description="Compute elastic constants of a material")
56
- def compute_elastic_constants(system: dict, strain: dict) -> dict:
 
57
  """
58
- Compute the elastic constants of a material.
59
 
60
  Parameters:
61
- - system: A dictionary representing the atomic system.
62
- - strain: A dictionary representing the strain tensor.
63
 
64
  Returns:
65
- - dict: Elastic constants of the material.
66
  """
67
  try:
68
- from atomman import ElasticConstants
69
-
70
- elastic_constants = ElasticConstants(**strain)
71
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  return {
73
  "success": True,
74
- "elastic_constants": elastic_constants.C
 
 
 
75
  }
76
  except Exception as e:
77
  return {"success": False, "error": str(e)}
78
 
79
- @mcp.tool(name="generate_crystal_structure", description="Generate a crystal structure from lattice and basis")
80
- def generate_crystal_structure(lattice: dict, basis: list) -> dict:
 
81
  """
82
- Generate a crystal structure from lattice parameters and basis atoms.
83
 
84
  Parameters:
85
- - lattice: A dictionary containing lattice vectors and angles.
86
- - basis: A list of basis atoms with positions.
87
 
88
  Returns:
89
- - dict: Generated crystal structure.
90
  """
91
  try:
92
- from atomman import System
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
- system = System(lattice=lattice, atoms=basis)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
 
96
  return {
97
  "success": True,
98
- "system": system.dump('json')
 
 
99
  }
100
  except Exception as e:
101
  return {"success": False, "error": str(e)}
102
 
103
- @mcp.tool(name="analyze_vacancies", description="Analyze vacancies in a crystal structure")
104
- def analyze_vacancies(system: dict) -> dict:
 
105
  """
106
- Analyze vacancies in a crystal structure.
107
 
108
  Parameters:
109
- - system: A dictionary representing the atomic system.
 
 
 
110
 
111
  Returns:
112
- - dict: Information about vacancies in the structure.
113
  """
114
  try:
115
- from atomman.defect import Vacancy
 
 
 
 
 
116
 
117
- vacancy = Vacancy(system)
 
118
 
119
  return {
120
  "success": True,
121
- "vacancies": vacancy.vacancies
 
 
 
122
  }
123
  except Exception as e:
124
  return {"success": False, "error": str(e)}
@@ -128,6 +265,6 @@ def create_app() -> FastMCP:
128
  Create and return the FastMCP application instance.
129
 
130
  Returns:
131
- - FastMCP: The FastMCP application instance.
132
  """
133
  return mcp
 
1
  from fastmcp import FastMCP
2
+ import numpy as np
3
 
4
  # Create the FastMCP service application
5
  mcp = FastMCP("atomman_service")
6
 
7
+
8
+ @mcp.tool(name="create_atoms", description="Create an Atoms object and return its properties")
9
+ def create_atoms(positions: list, symbols: list) -> dict:
10
  """
11
+ Create an Atoms object.
12
 
13
  Parameters:
14
+ - positions: List of atomic positions, e.g. [[0,0,0], [0.5,0.5,0.5]].
15
+ - symbols: List of atomic symbols, e.g. ['Fe', 'Fe'].
16
 
17
  Returns:
18
+ - Dictionary with success status and atoms information.
19
  """
20
  try:
21
+ from atomman.core import Atoms
22
+ atoms = Atoms(positions=positions, symbols=symbols)
 
 
 
23
  return {
24
  "success": True,
25
+ "natoms": atoms.natoms,
26
+ "symbols": list(atoms.symbols),
27
+ "positions": atoms.pos.tolist()
28
  }
29
  except Exception as e:
30
  return {"success": False, "error": str(e)}
31
 
32
+
33
+ @mcp.tool(name="create_box", description="Create a simulation box")
34
+ def create_box(vects: list) -> dict:
35
  """
36
+ Create a Box object.
37
 
38
  Parameters:
39
+ - vects: 3x3 list of box vectors, e.g. [[10,0,0], [0,10,0], [0,0,10]].
 
40
 
41
  Returns:
42
+ - Dictionary with success status and box information.
43
  """
44
  try:
45
+ from atomman.core import Box
46
+ box = Box(vects=vects)
 
 
 
47
  return {
48
  "success": True,
49
+ "vects": box.vects.tolist(),
50
+ "a": float(box.a),
51
+ "b": float(box.b),
52
+ "c": float(box.c),
53
+ "alpha": float(box.alpha),
54
+ "beta": float(box.beta),
55
+ "gamma": float(box.gamma),
56
+ "volume": float(box.volume)
57
  }
58
  except Exception as e:
59
  return {"success": False, "error": str(e)}
60
 
61
+
62
+ @mcp.tool(name="calculate_elastic_constants", description="Calculate elastic constants from Cij matrix")
63
+ def calculate_elastic_constants(Cij: list) -> dict:
64
  """
65
+ Calculate elastic constants.
66
 
67
  Parameters:
68
+ - Cij: 6x6 elastic stiffness matrix in Voigt notation (GPa).
 
69
 
70
  Returns:
71
+ - Dictionary with success status and elastic properties.
72
  """
73
  try:
74
+ from atomman.core import ElasticConstants
75
+ elastic = ElasticConstants(Cij=np.array(Cij))
76
+ return {
77
+ "success": True,
78
+ "Cij": elastic.Cij.tolist(),
79
+ "Sij": elastic.Sij.tolist(),
80
+ "bulk_modulus": float(elastic.bulk()),
81
+ "shear_modulus": float(elastic.shear())
82
+ }
83
+ except Exception as e:
84
+ return {"success": False, "error": str(e)}
85
+
86
+
87
+ @mcp.tool(name="create_system", description="Create an atomic system with atoms and box")
88
+ def create_system(positions: list, symbols: list, box_vects: list) -> dict:
89
+ """
90
+ Create a System object combining atoms and box.
91
+
92
+ Parameters:
93
+ - positions: List of atomic positions, e.g. [[0,0,0], [0.5,0.5,0.5]].
94
+ - symbols: List of atomic symbols, e.g. ['Fe', 'Fe'].
95
+ - box_vects: 3x3 list of box vectors, e.g. [[10,0,0], [0,10,0], [0,0,10]].
96
+
97
+ Returns:
98
+ - Dictionary with success status and system information.
99
+ """
100
+ try:
101
+ from atomman.core import Atoms, Box, System
102
+ atoms = Atoms(positions=positions, symbols=symbols)
103
+ box = Box(vects=box_vects)
104
+ system = System(atoms=atoms, box=box)
105
  return {
106
  "success": True,
107
+ "natoms": system.natoms,
108
+ "symbols": list(system.symbols),
109
+ "box_volume": float(system.box.volume),
110
+ "density": float(system.natoms / system.box.volume)
111
  }
112
  except Exception as e:
113
  return {"success": False, "error": str(e)}
114
 
115
+
116
+ @mcp.tool(name="calculate_miller_indices", description="Convert vectors to Miller indices")
117
+ def calculate_miller_indices(vectors: list) -> dict:
118
  """
119
+ Calculate Miller indices from crystallographic vectors.
120
 
121
  Parameters:
122
+ - vectors: List of vectors to convert, e.g. [[1,1,0], [1,1,1]].
 
123
 
124
  Returns:
125
+ - Dictionary with success status and Miller indices.
126
  """
127
  try:
128
+ from atomman.tools import miller
129
+ indices = miller.vector_crystal_to_cartesian(np.array(vectors))
130
+ return {
131
+ "success": True,
132
+ "miller_indices": indices.tolist() if hasattr(indices, 'tolist') else list(indices)
133
+ }
134
+ except Exception as e:
135
+ return {"success": False, "error": str(e)}
136
+
137
+
138
+ @mcp.tool(name="calculate_vector_angle", description="Calculate angle between two vectors")
139
+ def calculate_vector_angle(vector1: list, vector2: list) -> dict:
140
+ """
141
+ Calculate angle between two vectors.
142
+
143
+ Parameters:
144
+ - vector1: First vector, e.g. [1, 0, 0].
145
+ - vector2: Second vector, e.g. [0, 1, 0].
146
+
147
+ Returns:
148
+ - Dictionary with success status and angle in degrees.
149
+ """
150
+ try:
151
+ from atomman.tools import vect_angle
152
+ angle = vect_angle(vector1, vector2)
153
+ return {
154
+ "success": True,
155
+ "angle_degrees": float(angle)
156
+ }
157
+ except Exception as e:
158
+ return {"success": False, "error": str(e)}
159
+
160
+
161
+ @mcp.tool(name="load_lammps_dump", description="Load atomic structure from LAMMPS dump file content")
162
+ def load_lammps_dump(dump_content: str) -> dict:
163
+ """
164
+ Parse LAMMPS dump file content.
165
+
166
+ Parameters:
167
+ - dump_content: String content of a LAMMPS dump file.
168
+
169
+ Returns:
170
+ - Dictionary with success status and structure information.
171
+ """
172
+ try:
173
+ import atomman as am
174
+ import tempfile
175
+ import os
176
+
177
+ # Write content to temp file
178
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.dump', delete=False) as f:
179
+ f.write(dump_content)
180
+ temp_path = f.name
181
 
182
+ try:
183
+ system = am.load('atom_dump', temp_path)
184
+ result = {
185
+ "success": True,
186
+ "natoms": system.natoms,
187
+ "box_volume": float(system.box.volume)
188
+ }
189
+ finally:
190
+ os.unlink(temp_path)
191
+
192
+ return result
193
+ except Exception as e:
194
+ return {"success": False, "error": str(e)}
195
+
196
+
197
+ @mcp.tool(name="rotate_system", description="Rotate an atomic system")
198
+ def rotate_system(positions: list, symbols: list, box_vects: list, rotation_matrix: list) -> dict:
199
+ """
200
+ Rotate an atomic system by a rotation matrix.
201
+
202
+ Parameters:
203
+ - positions: List of atomic positions.
204
+ - symbols: List of atomic symbols.
205
+ - box_vects: 3x3 list of box vectors.
206
+ - rotation_matrix: 3x3 rotation matrix.
207
+
208
+ Returns:
209
+ - Dictionary with rotated system information.
210
+ """
211
+ try:
212
+ from atomman.core import Atoms, Box, System
213
+ atoms = Atoms(positions=positions, symbols=symbols)
214
+ box = Box(vects=box_vects)
215
+ system = System(atoms=atoms, box=box)
216
 
217
+ rotated = system.rotate(np.array(rotation_matrix))
218
  return {
219
  "success": True,
220
+ "natoms": rotated.natoms,
221
+ "positions": rotated.atoms.pos.tolist(),
222
+ "box_vects": rotated.box.vects.tolist()
223
  }
224
  except Exception as e:
225
  return {"success": False, "error": str(e)}
226
 
227
+
228
+ @mcp.tool(name="calculate_neighbor_list", description="Calculate neighbor list for atoms")
229
+ def calculate_neighbor_list(positions: list, symbols: list, box_vects: list, cutoff: float) -> dict:
230
  """
231
+ Calculate neighbor list for an atomic system.
232
 
233
  Parameters:
234
+ - positions: List of atomic positions.
235
+ - symbols: List of atomic symbols.
236
+ - box_vects: 3x3 list of box vectors.
237
+ - cutoff: Cutoff distance for neighbors.
238
 
239
  Returns:
240
+ - Dictionary with neighbor information.
241
  """
242
  try:
243
+ from atomman.core import Atoms, Box, System
244
+ atoms = Atoms(positions=positions, symbols=symbols)
245
+ box = Box(vects=box_vects)
246
+ system = System(atoms=atoms, box=box)
247
+
248
+ neighbors = system.neighborlist(cutoff=cutoff)
249
 
250
+ # Get coordination numbers
251
+ coord_numbers = [len(neighbors[i]) for i in range(system.natoms)]
252
 
253
  return {
254
  "success": True,
255
+ "natoms": system.natoms,
256
+ "cutoff": cutoff,
257
+ "coordination_numbers": coord_numbers,
258
+ "average_coordination": float(np.mean(coord_numbers))
259
  }
260
  except Exception as e:
261
  return {"success": False, "error": str(e)}
 
265
  Create and return the FastMCP application instance.
266
 
267
  Returns:
268
+ - FastMCP instance.
269
  """
270
  return mcp