Metadata-Version: 2.5
Name: gauss-lang-mcp
Version: 0.1.0
Summary: Drive GAUSS from Python, and expose it to LLM clients over MCP
Project-URL: Homepage, https://github.com/merwanroudane/mcp_gauss
Project-URL: Repository, https://github.com/merwanroudane/mcp_gauss
Project-URL: Issues, https://github.com/merwanroudane/mcp_gauss/issues
Author-email: Merwan Roudane <merwanroudane920@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Merwan Roudane
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: aptech,econometrics,gauss,mcp,model-context-protocol,statistics
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.10
Requires-Dist: mcp[cli]>=1.2.0
Provides-Extra: pandas
Requires-Dist: pandas>=1.5; extra == 'pandas'
Description-Content-Type: text/markdown

# gauss-mcp

[![Licence](https://img.shields.io/badge/licence-MIT-2c5f9e)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.10+-2c5f9e)](https://www.python.org/)
[![Platform](https://img.shields.io/badge/platform-Windows-2c5f9e)](https://github.com/merwanroudane/mcp_gauss)
[![GAUSS](https://img.shields.io/badge/GAUSS-26-c05621)](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.
