MCP server (crystod-mcp)#
The CrystOD analyses as tools for an AI assistant. crystod-mcp is a
Model Context Protocol server, shipped as
a separate package in the crystod-mcp/ directory of the repository, that
lets Claude Desktop, Claude Code, or any MCP client call CrystOD directly:
ask “which space groups can the R-point instability of SrTiO3 condense into?”
and the assistant runs crystod_isotropy_subgroups (or the full phonon
workflow) and answers with the table.
I want to … |
tool |
|---|---|
list the isotropy subgroups of an irrep |
|
decompose a product of irreps |
|
reduce a representation from its characters |
|
see how an orbital shell splits in a ligand field |
|
read a character table (point group, or little group of k) |
|
label the phonon modes with irreps |
|
find the subgroups the imaginary modes lead to |
|
get the irreps of the crystal orbitals of an element |
|
list the special k points of a space group |
|
get the point group and SALCs of a molecule |
|
Every tool takes text and returns Markdown, so nothing needs to be on the
assistant’s disk: space groups as symbols or numbers, irreps in ISO-IR
notation (R4+, GM5-), crystal structures as the full text of a POSCAR,
molecules as the full text of an XYZ file, phonon forces as the full text of
a phonopy FORCE_SETS. The text of a structure is written to a temporary
directory for the duration of one call and removed afterwards.
Installation#
crystod-mcp is a separate package so that CrystOD itself carries no MCP dependency. From a checkout of the repository:
pip install ./crystod-mcp
This installs CrystOD (>= 0.4.0) and the MCP Python SDK (2.x) as
dependencies; Python 3.10 or later. Publication on PyPI as crystod-mcp is
planned, after which pip install crystod-mcp and the uvx form below work
without a checkout. crystod-mcp --version checks the installation; the
server itself is started by the MCP client over standard input/output, not
by hand.
Client configuration#
Claude Desktop reads claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json; Windows:
%APPDATA%\Claude\claude_desktop_config.json). python must be the
interpreter in which crystod-mcp is installed – give its full path when it
lives in a conda environment or a venv:
{
"mcpServers": {
"crystod": {
"command": "python",
"args": ["-m", "crystod_mcp"],
"env": {
"CRYSTOD_MCP_TIMEOUT": "60"
}
}
}
}
Claude Code registers the server from the command line:
claude mcp add crystod -- crystod-mcp
(or claude mcp add crystod -- /path/to/env/bin/python -m crystod_mcp to
name the interpreter). With uv installed, once the package is on PyPI:
{
"mcpServers": {
"crystod": {
"command": "uvx",
"args": ["crystod-mcp"]
}
}
}
crystod-mcp/mcp_config.json holds both forms.
The tools#
Tool |
Command it wraps |
Inputs |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The tools are built on the Python API
(crystod.group.isotropy_subgroups, crystod.phonon.label_phonon_modes,
crystod.phonon.scan_imaginary_modes, crystod.bz.get_special_kpoints, …);
the three whose printed report is the natural answer (crystod, the
little-group character table and crystod-mol) return the report of the
command itself. crystod_isotropy_subgroups always returns the whole table:
the API has no maximum-index cut-off (there is no max_index argument).
A tool call with a bad input returns one sentence naming the problem and the
remedy – the tabulated irreps of the space group, the class order of the
character table, the special k points of the space group – instead of a
traceback, so the assistant can correct itself and call again. For example
crystod_isotropy_subgroups("Pm-3m", "R9+") answers
irrep "R9+" is not tabulated for space group Pm-3m (No. 221). Available irreps:
GM1+, GM2+, GM3+, GM4+, GM5+, GM1-, ..., M5-
Example#
crystod_isotropy_subgroups("Pm-3m", "R4+") returns
## Isotropy subgroups of R4+ in Pm-3m (No. 221)
| Direction | Subgroup | No. | Size | Index | Free parameters |
|---|---|---|---|---|---|
| (0,0,a) | I4/mcm | 140 | 2 | 6 | 1 |
| (a,a,a) | R-3c | 167 | 2 | 8 | 1 |
| (0,a,a) | Imma | 74 | 2 | 12 | 1 |
| (0,a,b) | C2/m | 12 | 2 | 24 | 2 |
| (a,a,b) | C2/c | 15 | 2 | 24 | 2 |
| (a,b,c) | P-1 | 2 | 2 | 48 | 3 |
6 isotropy subgroup(s). Size: primitive-cell multiplication relative to the
parent; index: index of the subgroup in the parent; free parameters:
independent order-parameter components (1 = a single amplitude fixes the
structure).
Irrep labels follow ISO-IR (H. T. Stokes, B. J. Campbell and R. Cordes,
Acta Cryst. A69, 388 (2013), https://iso.byu.edu). CrystOD: H. Koiso and
Y. Mochizuki et al., Phys. Rev. B 110, 064104 (2024).
– the same six subgroups as crystod-group --parent Pm-3m --irrep R4+
and the Python API, with the citation footer every result
carries.
Citation#
The irrep labels come from the ISO-IR tables of the ISOTROPY Software Suite that CrystOD bundles, and the analyses are CrystOD’s, so every tool result ends with the two citations (ISO-IR: H. T. Stokes, B. J. Campbell and R. Cordes, Acta Cryst. A69, 388 (2013); CrystOD: H. Koiso and Y. Mochizuki et al., Phys. Rev. B 110, 064104 (2024)). Please keep both when results obtained through the server are published; see Citation. The server returns computed results (labels, decompositions, subgroups), never the tables themselves.
Time limits and resources#
Every call runs under a time limit of 60 s by default; the
CRYSTOD_MCP_TIMEOUT environment variable of the server process (seconds,
set in the client configuration as above) raises or lowers it, and a call
that exceeds it returns an error naming the limit and the variable instead of
hanging the client. The limit bounds the wait, not the computation: the tools that return a CrystOD report run it in a subprocess that is killed at the limit, while the group-theory, k-point, molecular and phonon tools run in a worker thread that finishes in the background after the error has been returned (retrying a long scan with a larger limit while the first one is still running costs a second scan). The group-theory, k-point and molecular tools answer in
well under a second. The phonon tools rebuild the force constants from
FORCE_SETS with phonopy – a few seconds for the 4x4x4 SrTiO3 example, more
for large supercells – and crystod_imaginary_mode_subgroups scans every q
point the supercell resolves. The server runs one calculation per call in a
worker thread (a subprocess for the tools that return a CrystOD report),
needs no network access and keeps no state between calls.
Tests#
pip install -e "./crystod-mcp[test]"
python -m pytest -q crystod-mcp/tests
The tests call every tool on the inputs bundled with CrystOD
(crystod.examples: ScF3, SrTiO3 with its 4x4x4 FORCE_SETS, CH4, NH3),
check the results the CrystOD testsuite expects (Pm-3m R4+ -> I4/mcm, R-3c,
Imma, C2/m, C2/c, P-1; the imaginary R5- mode of SrTiO3 at -1.09 THz; Sc 3d
of ScF3 -> GM3+ + GM5+ at Gamma; CH4 -> Td with A1 + T2 for the H 1s SALCs),
confirm the citation footer on every result and the one-sentence errors, and
connect to the server in-process and over stdio to list the ten tools and
make a call.
License#
MIT, as CrystOD. The MCP Python SDK the server is built on is MIT licensed
(Copyright (c) 2024 Anthropic, PBC); its notice is reproduced in
crystod-mcp/LICENSE.