gauss-mcp
# gauss-mcp
[](LICENSE)
[](https://www.python.org/)
[](https://github.com/merwanroudane/mcp_gauss)
[](https://www.aptech.com/)
Drive **GAUSS** from Python, and expose it to LLM clients over the Model
Context Protocol.
Author: Dr Merwan Roudane
Built and tested against **GAUSS 26.1.1** on Windows.
## Why this exists
Aptech publishes a [reference for AI assistants](https://github.com/aptech/gauss-llm-reference)
so they write better GAUSS, but writing is not running: an assistant that cannot
execute the code never learns whether it worked or what the numbers were. This
connects an assistant to a real GAUSS installation, so the results come from
GAUSS rather than from the model.
## How it drives GAUSS
Through `tgauss`, the terminal build that ships with an ordinary GAUSS
installation — not the GAUSS Engine, which is richer but needs a separate
licence key from Aptech.
Each call is its own `tgauss` process, so nothing would normally carry over.
The workspace is saved on the way out and restored on the way in, which makes a
run of calls behave like one continuous session: a matrix built in one call is
still there in the next.
## Install
The distribution is **`gauss-lang-mcp`** on PyPI: plain `gauss-mcp` was already
taken by an unrelated package about import workflows, nothing to do with the
Aptech language. The import name stays `gauss_mcp`.
```bash
pip install "gauss-lang-mcp[pandas]"
```
GAUSS is found automatically under `C:\gauss*` and `C:\Program Files\gauss*`.
Set `GAUSS_HOME` to choose between installations.
## Library use
```python
from gauss_mcp import Gauss
with Gauss() as g:
g.run("""
rndseed 90210;
n = 400;
x = rndn(n, 1);
y = 1.25 + 0.8*x + 0.3*rndn(n, 1);
des = ones(n,1)~x;
bhat = invpd(des'des)*des'y;
""")
print(g.get_matrix("bhat")) # [[1.2489...], [0.8043...]]
```
Values cross as CSV rather than as printed text, so they keep full double
precision instead of GAUSS's display rounding:
```python
g.run("pi_like = 3.14159265358979;")
g.get_scalar("pi_like") # 3.14159265358979, every digit
```
pandas both ways:
```python
frame = g.to_dataframe(["x", "y"])
g.from_dataframe(frame)
```
## MCP server use
```json
{
"mcpServers": {
"gauss": { "command": "gauss-lang-mcp" }
}
}
```
### Tools
| Tool | Purpose |
|---|---|
| `gauss_status` | Where GAUSS is, its version, what the workspace holds |
| `run_gauss_code` | **Main tool.** Run GAUSS code and return what it printed |
| `list_symbols` | Every symbol with its type and dimensions |
| `describe_symbol` | Type and shape of one symbol |
| `get_matrix` | Read a matrix out at full precision |
| `put_matrix` | Create a matrix from numbers given in the conversation |
| `read_csv` / `write_csv` | Move data between files and the workspace |
| `clear_workspace` | Start again from empty |
## Errors
GAUSS reports its own code, message and line, and those are passed through:
```text
GaussError: G0025: Undefined symbol: 'no_such_thing' on line 2
```
The line refers to **your** code. The workspace restore is prepended to every
generated program, which shifts GAUSS's own numbering by a line; that offset is
corrected before you see it.
## Behaviour worth knowing
Characteristics of GAUSS and of `tgauss` that this package handles for you,
each confirmed against a live installation rather than assumed.
- **The exit code is always 0**, whether the program succeeded or died. It
carries nothing, so errors are read from stderr instead.
- **stdout is clean.** The banner and job header go to stderr, so the program's
own output needs no filtering.
- **GAUSS compiles before it runs.** An undefined symbol anywhere means nothing
executed and no output appears. A runtime error leaves the output produced up
to that point, followed by "Program execute failed".
- **Symbol names ignore case.** `X` and `x` are the same symbol, so assigning to
one overwrites the other. This surprises people arriving from R or Python.
- **The child must not inherit stdin.** Under MCP, the server's stdin is the
JSON-RPC stream; a `tgauss` that inherited it would read the protocol itself.
Every subprocess call detaches stdin.
- **Restoring a workspace uses `use`, not `loadall`.** `saveall` writes a `.gcg`
and `use <name>;` must be the first statement of the program that reads it.
## Tests
```bash
python tests/test_offline.py # 10 tests, no GAUSS needed
python tests/test_live.py # 24 tests, drives a real installation
```
## Licence
MIT. Copyright (c) 2026 Merwan Roudane.
TDQS
Scored across 9 tools
Most tools are clearly distinct: listing, describing, getting, putting, reading, writing, status, clearing, and executing. The main overlap is between gauss_status reporting what the workspace holds and list_symbols listing every symbol, but the descriptions are clear enough to prevent serious confusion.
The overwhelming majority of tools follow a consistent verb_noun pattern such as list_symbols, put_matrix, read_csv, and run_gauss_code. The one outlier is gauss_status, which lacks a verb and breaks the otherwise predictable pattern.
With nine tools, the server is well-scoped for a GAUSS workspace MCP. Each tool covers a distinct need—inspection, data exchange, file I/O, status, reset, and arbitrary code execution—without feeling bloated or thin.
The server covers the core GAUSS workflow well: list and describe symbols, get and put matrices, import/export CSV, check status, clear the workspace, and run arbitrary GAUSS code. There is no dedicated delete-symbol or rename tool, but run_gauss_code can handle those cases, so the gap is minor.