# Developers: every way into xpsflow

xpsflow is one tool layer with several doors. Whichever you walk through, the same deterministic functions run, the same `results.json` comes out, and every number in it can be traced to the call that produced it. Pick the door that fits your workflow.

| You want to | Use | Needs |
|---|---|---|
| Try it on a file right now | [the browser workbench](/app/) | nothing to install |
| Analyze files from a terminal or a script | the command line | Python 3.11 to 3.13 |
| Call the analysis from your own Python | the library | the package |
| Drive it from another program over HTTP | the local HTTP API | `xpsflow serve` |
| Let an AI client run the analysis | the MCP server | `xpsflow mcp` |
| Look up reference data without installing anything | the hosted MCP endpoint at `/mcp` | nothing |
| Talk to it in plain language | the assistant | a model endpoint |

## Install

```bash
pip install "xpsflow[web,pdf,mcp]"          # once the first release is on PyPI
pip install "xpsflow[web,pdf,mcp] @ git+https://github.com/KarthikSubramanian07/XPS-Flow"   # today
```

`xpsflow version` prints the version; `xpsflow --help` lists every command. The extras are optional: `web` adds the local workbench and HTTP API, `pdf` adds PDF reports (WeasyPrint), `mcp` adds the Model Context Protocol server.

## Command line

```bash
xpsflow run sample.vms --out runs/sample          # the whole pipeline: results.json, report.pdf, figures
xpsflow run sample.kal --template templates/Ti2p.yaml --out runs/ti
xpsflow batch data/ --out runs/batch              # every sample in a directory, one comparison report
xpsflow inspect sample.vms                        # what is in the file, before anything is fitted
xpsflow serve                                     # the workbench at http://127.0.0.1:8765
xpsflow chat sample.vms                           # the assistant, in the terminal
xpsflow mcp --data ./data                         # the MCP server over stdio
xpsflow models                                    # which models the configured endpoint serves
```

`results.json` holds every number: spectra metadata, quality grades, the calibration shift, survey matches, each fit with its components, uncertainties, model-selection table and audit, the composition in three readings, and the templates that were used, with their provenance. A run can be repeated from that file and the saved templates alone.

## Python

```python
from pathlib import Path
from xpsflow.agent.session import Session
from xpsflow.agent.tools import registry

# A session: where it writes, and the only directory its tools may read from.
s = Session(id="demo", work_dir=Path("runs/demo"), sandbox=Path("examples"))
registry.call(s, "load_data", {"paths": ["demo.vms"]})
registry.call(s, "check_quality", {})
registry.call(s, "calibrate_energy", {"mode": "adventitious_carbon"})
registry.call(s, "use_template", {"key": "demo/Te 3d", "template": "Te3d"})
fit = registry.call(s, "fit_spectrum", {"key": "demo/Te 3d"})["result"]
print(fit["components"], fit["audit"])
print(registry.call(s, "quantify", {})["result"]["atomic_percent"])
```

Every call returns `{"ok": true, "result": ...}` or `{"ok": false, "error": ...}`, the same compact JSON the assistant and the MCP client receive. The registry is the same list of tools every other door exposes, so a script written against it behaves exactly like the workbench; `registry.tool_schemas()` returns the JSON schema of each tool, and `xpsflow.pipeline` runs the whole sequence in one call when you want the report too.

## HTTP API

`xpsflow serve` starts the workbench and its API on `http://127.0.0.1:8765`. The surface is described by an OpenAPI document, published here at [/openapi.json](/openapi.json) and served live at `/openapi.json` on the local server, with an interactive explorer at `/api/docs`.

```bash
SID=$(curl -s http://127.0.0.1:8765/api/session | jq -r .sid)
curl -s -F files=@sample.vms "http://127.0.0.1:8765/api/upload?sid=$SID"
curl -s "http://127.0.0.1:8765/api/tools" | jq '.tools[].name'
curl -s -X POST "http://127.0.0.1:8765/api/tool/fit_spectrum?sid=$SID" \
     -H 'Content-Type: application/json' -d '{"arguments": {"key": "sample/Ti 2p"}}'
curl -s "http://127.0.0.1:8765/api/composition?sid=$SID"
curl -s "http://127.0.0.1:8765/api/report?sid=$SID&format=pdf" -o report.pdf
```

Every error is JSON with the same shape: a `detail` message and an `error` object with a stable `code`, the `status`, a one-sentence `message`, a `hint` that says what to do, and a `docs` link. A request to an unknown tool, for example, returns `404` with `"code": "not_found"` and the hint to list the tools first. The server answers only to `localhost` and `127.0.0.1` unless started otherwise, refuses cross-origin writes, and caps upload and body sizes; the [security page](/docs/security) has the limits.

## MCP: the analysis tools, from any AI client

```bash
xpsflow mcp --data ./data                 # stdio, for desktop clients and editors
xpsflow mcp --http --port 8766            # streamable HTTP at http://127.0.0.1:8766/mcp
```

Register the stdio server with any client that reads an MCP configuration:

```json
{ "mcpServers": { "xpsflow": { "command": "xpsflow", "args": ["mcp", "--data", "/path/to/data"] } } }
```

Nineteen tools (`load_data`, `check_quality`, `calibrate_energy`, `identify_survey`, `propose_fit`, `use_template`, `fit_spectrum`, `quantify`, ..., and, with the `crucible` extra, [`crucible_search`, `crucible_load` and `crucible_publish`](/docs/crucible)), two resources (the templates and each element's curated states) and an `analyze-sample` prompt that walks a client through the standard workflow. Each connection gets its own sandboxed session that can only read the directory you point it at. The [MCP page](/docs/mcp) documents every tool and the security model.

## MCP: reference data, hosted on this site

This site also serves a read-only MCP server over streamable HTTP at `https://xpsflow.pages.dev/mcp`, so an agent can look things up before anyone installs anything: `lookup_element`, `lines_near` (which core levels sit near a binding energy), `find_chemical_state` (by name or by energy, with citations), `list_templates`, `get_template` and `read_docs`. Point an MCP client at the URL, or call it by hand:

```bash
curl -s https://xpsflow.pages.dev/mcp -H 'Content-Type: application/json' \
     -H 'Accept: application/json, text/event-stream' \
     -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"find_chemical_state","arguments":{"query":"TiO2"}}}'
```

The server card at [/.well-known/mcp/server-card.json](/.well-known/mcp/server-card.json) lists both servers and their transports. Nothing is analyzed on the site; the hosted endpoint only answers from the curated tables and the documentation.

## The assistant

The assistant is a short tool-calling loop around the same registry. It needs a chat-completions endpoint that supports tool calling; a 7B-class local model is enough.

```bash
export XPSFLOW_LLM_PRESET=ollama           # or cborg, openai, custom
xpsflow chat sample.vms
```

Raw spectra are never sent to the model; it sees compact JSON results and explains them. The [assistant page](/docs/assistant) covers each preset and how to check that a model can call tools.

## For agents reading this page

Machine-readable entry points: [/llms.txt](/llms.txt) (what exists and when to use it), [/agents.md](/agents.md) (when to reach for xpsflow and how to call it), [/openapi.json](/openapi.json) (the local HTTP API), [/.well-known/mcp/server-card.json](/.well-known/mcp/server-card.json) (both MCP servers), [/sitemap.xml](/sitemap.xml). Every documentation page has a Markdown twin at the same address with `.md` appended, or by asking for `Accept: text/markdown`.
