Metadata-Version: 2.5
Name: eviews-mcp
Version: 1.3.2
Summary: Drive EViews from Python, and expose it to LLM clients over MCP
Project-URL: Homepage, https://merwanroudane.github.io/MCP_EVIEWS/
Project-URL: Documentation, https://merwanroudane.github.io/MCP_EVIEWS/
Project-URL: Guide, https://github.com/merwanroudane/MCP_EVIEWS/blob/main/docs/EViews-Researcher-Guide.md
Project-URL: Repository, https://github.com/merwanroudane/MCP_EVIEWS
Project-URL: Changelog, https://github.com/merwanroudane/MCP_EVIEWS/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/merwanroudane/MCP_EVIEWS/issues
Author-email: Merwan Roudane <merwanroudane920@gmail.com>
Maintainer-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: com-automation,econometrics,eviews,mcp,model-context-protocol,regression,statistics,time-series
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.10
Requires-Dist: mcp[cli]>=1.2.0
Requires-Dist: pywin32>=306; sys_platform == 'win32'
Provides-Extra: dev
Requires-Dist: pandas>=1.5; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: pandas
Requires-Dist: pandas>=1.5; extra == 'pandas'
Description-Content-Type: text/markdown

# eviews-mcp

[![Tests](https://github.com/merwanroudane/MCP_EVIEWS/actions/workflows/tests.yml/badge.svg)](https://github.com/merwanroudane/MCP_EVIEWS/actions/workflows/tests.yml)
[![PyPI](https://img.shields.io/pypi/v/eviews-mcp?color=2c5f9e&label=PyPI)](https://pypi.org/project/eviews-mcp/)
[![Python](https://img.shields.io/pypi/pyversions/eviews-mcp?color=2c5f9e)](https://pypi.org/project/eviews-mcp/)
[![Licence](https://img.shields.io/badge/licence-MIT-2c5f9e)](LICENSE)
[![Platform](https://img.shields.io/badge/platform-Windows-2c5f9e)](https://pypi.org/project/eviews-mcp/)
[![EViews](https://img.shields.io/badge/EViews-10--14-c05621)](https://www.eviews.com)

Drive **EViews** from Python, and expose it to LLM clients over the Model
Context Protocol.

**[Documentation site](https://merwanroudane.github.io/MCP_EVIEWS/)** &nbsp;·&nbsp;
**[Researcher guide](https://github.com/merwanroudane/MCP_EVIEWS/blob/main/docs/EViews-Researcher-Guide.md)** &nbsp;·&nbsp;
**[PyPI](https://pypi.org/project/eviews-mcp/)**

Two things in one package:

- **A library.** An `EViews` class for scripts and notebooks — build workfiles,
  estimate models, read results back as text or pandas DataFrames.
- **An MCP server.** The same capabilities as tools, so an assistant can do
  econometrics in a real EViews session.

Built and tested against **EViews 13** on Windows; EViews 10–14 resolve
correctly through the same COM interface.

> **New to this?** The [**EViews Researcher Guide**](https://github.com/merwanroudane/MCP_EVIEWS/blob/main/docs/EViews-Researcher-Guide.md)
> takes you from a clean machine to a finished ARDL study, with every command and
> every output verified against a real EViews session. No Python knowledge assumed.

## Install

```bash
pip install eviews-mcp
```

With pandas support:

```bash
pip install "eviews-mcp[pandas]"
```

Or from a clone, for development:

```bash
git clone https://github.com/merwanroudane/MCP_EVIEWS.git
cd MCP_EVIEWS
pip install -e .[dev]
```

Requires Windows and a local EViews installation, since it drives EViews
through COM automation.

## Library use

```python
from eviews_mcp import EViews

with EViews() as ev:
    ev.create_workfile("q", "1990q1", "2020q4")
    ev.run("""
        series k   = 100 + @trend + 3*@nrnd
        series l   = 50 + 0.5*@trend + 2*@nrnd
        series gdp = 10 + 0.6*k + 0.3*l + 2*@nrnd
        equation eq1.ls gdp c k l
    """)

    print(ev.show("eq1"))
    print(ev.value("eq1.@r2"))
```

```text
Dependent Variable: GDP
Method: Least Squares
Included observations: 124

Variable      Coefficient   Std. Error   t-Statistic   Prob.

C             9.58073       0.829252     11.5535       2.90e-21
K             0.591693      0.0333819    17.7250       1.99e-35
L             0.322394      0.0673315     4.78816      4.81e-06

R-squared     0.994702      Mean dependent var         131.080
```

### Any EViews view, as text

`show` takes a view, so diagnostics need no extra API:

```python
ev.show("eq1", "wald c(2)=c(3)")   # coefficient restriction test
ev.show("eq1", "resids(t)")        # residual table
ev.show("eq1", "coefcov")          # coefficient covariance
ev.show("eq1", "auto(2)")          # Breusch-Godfrey serial correlation
ev.show("eq1", "white")            # White heteroskedasticity test
ev.show("gdp", "uroot")            # unit root test
ev.show("gdp", "correl")           # correlogram
ev.show("ardl1", "cointrel")       # ARDL long-run relationship
ev.show("var1", "impulse(t)")      # impulse response table
ev.show("var1", "testexog")        # Granger causality
```

`resids` and `impulse` draw graphs by default; the `(t)` variants ask EViews
for the table form. Views that freeze into a spool rather than a table -- the
ARDL cointegrating relationship among them -- cannot be read over COM at all,
so `show` falls back to a text dump for those.

For the numbers rather than the layout, `table()` returns raw rows at full
double precision, and `value()` returns one number:

```python
rows = ev.table("eq1")             # tuple of row tuples
r2   = ev.value("eq1.@r2")         # 0.9947015...
beta = ev.value("eq1.@coefs(2)")
```

### Results as data, not just text

`show` formats a table for reading. These return the numbers instead, for
testing, tabulating, or passing to something else:

```python
ev.coefficients("eq1")
# [{'variable': 'LNK', 'coefficient': 0.549198724914677,
#   'std_error': 0.023936158605687322, 't_stat': 22.94431341143375,
#   'p_value': 5.677925593821611e-41}, ...]

ev.fit("eq1")["R-squared"]        # 0.9858630667863459
```

Order of integration, tested down through differences until stationary:

```python
ev.unit_root("lngdp")
# {'series': 'LNGDP', 'order_of_integration': 1, 'conclusion': 'I(1)',
#  'steps': [{'difference': 0, 'statistic': -0.5001, 'p_value': 0.8856, ...},
#            {'difference': 1, 'statistic': -12.1778, 'p_value': 0.0001, ...}]}
```

Pass `options` to choose the test: `"pp"` for Phillips-Perron, `"kpss"` for
KPSS, `"adf, trend"` to add a trend. KPSS reverses the null, so the reported
order does not apply to it.

The standard post-estimation battery in one call:

```python
report = ev.diagnose("eq1")
report["summary"]
# 'All 3 diagnostics pass at the 0.05 level.'
```

Breusch-Godfrey, White and Jarque-Bera, each with its statistic, p-value and
whether the null is rejected. A test that cannot run is listed under
`report["skipped"]` with the reason EViews gave, so the summary never overstates
how much was actually checked.

These verdicts read p-values against a level you choose. They do not establish
that a specification is sound -- structural breaks, seasonality and short
samples all mislead these tests.

### pandas both ways

```python
frame = ev.to_dataframe(["gdp", "k", "l"])   # indexed 1990Q1, 1990Q2, ...
frame.corr()
```

Writing back, a `DatetimeIndex` or `PeriodIndex` decides the page frequency and
span, so dates stay aligned:

```python
import numpy as np
import pandas as pd

rng = np.random.default_rng(7)
index = pd.period_range("2005Q1", periods=40, freq="Q")
unemployment = 7.0 - 0.05 * np.arange(40) + rng.normal(0, 0.4, 40)

df = pd.DataFrame(
    {"unemployment": unemployment,
     "inflation": 9.0 - 0.9 * unemployment + rng.normal(0, 0.5, 40)},
    index=index,
)

ev.from_dataframe(df)              # creates a quarterly 2005Q1-2014Q4 page
ev.run("equation phillips.ls inflation c unemployment")
```

Non-numeric columns are skipped rather than failing the whole frame.

### Graphs

Graphs cannot be rendered as text, so write them to a file:

```python
ev.export_object("phillips", "residuals.png", view="resids")
```

Graph formats: `png`, `jpg`, `pdf`, `emf`, `wmf`, `bmp`, `gif`, `eps`, `tex`.
Table formats: `csv`, `rtf`, `txt`, `html`.

### Errors

EViews reports failures precisely, including the line number inside a program,
and those messages are passed through unchanged:

```python
ev.run("""series ok = 1
broken_command
""")
```

```text
EViewsError: BROKEN_COMMAND is not defined or is an illegal command in "BROKEN_COMMAND"
in MCP_77B699157F3B.PRG on line 2.
```

The generated program is given a random name each run, so only that part varies.

## MCP server use

Register the `eviews-mcp` command with your MCP client:

```json
{
  "mcpServers": {
    "eviews": {
      "command": "eviews-mcp"
    }
  }
}
```

For Claude Code:

```bash
claude mcp add eviews -- eviews-mcp
```

### Tools

| Tool | Purpose |
|---|---|
| `eviews_status` | Connection, version, active workfile. Start here when debugging. |
| `reset_eviews` | Discard the instance and start clean. |
| `set_eviews_visible` | Show or hide the EViews window. |
| `create_workfile` | New page by frequency and range. |
| `open_workfile` / `save_workfile` | Open and save `.wf1` / `.wf2`. |
| `close_workfile` | Close one or all open workfiles. |
| `workfile_info` | Name, page, frequency, range, sample. |
| `list_objects` | Inventory, filterable by EViews type. |
| `set_sample` | Set the estimation sample. |
| `run_eviews_code` | **Main tool.** Run a block of EViews program code. |
| `run_program_file` | Run an existing `.prg`, with arguments. |
| `command` | A single command line. |
| `show` | **Render any object as a text table.** |
| `evaluate` | One value from an expression. |
| `describe_object` | Type, plus statistics for a series. |
| `equation_coefficients` | Coefficients as a clean table of numbers. |
| `unit_root` | Order of integration, tested down through differences. |
| `diagnose_equation` | Serial correlation, heteroskedasticity and normality. |
| `read_data` | Series as an aligned table or full-precision CSV. |
| `write_series` | Write values into a series. |
| `import_data` | Read `.xlsx`, `.csv`, `.dta`, `.sav`, and more. |
| `export_data` | Write series to a file. |
| `export_object` | Save an object — the way to retrieve graphs. |

Results are not echoed by `run_eviews_code`, because EViews sends program
output to its own log window where COM cannot reach it. Estimate into a named
object and call `show` on it.

## Behaviour worth knowing

These are EViews characteristics that the library handles for you, documented
because they surprise people writing COM code directly.

- **Writes respect the active sample.** Under `smpl 2000m3 2000m6`, writing 12
  values lands 4 and silently leaves the rest NA. Writes therefore default to
  the whole page; pass `sample=""` to opt into the current sample instead.
- **`save` ignores the file extension.** `graph.save "out.png"` writes EMF
  data. The format is passed explicitly, and a save that produces no file
  raises rather than reporting success.
- **Relative paths resolve against EViews**, not the calling process, so paths
  are made absolute before they are handed over.
- **A dated frame governs the page.** Writing a 12-row quarterly frame into an
  open 80-row page would land the values on the wrong dates, so a page matching
  the frame is created instead.
- **No log redirection.** The `output` command requires a frozen object name
  and otherwise writes nothing at all, so it cannot capture a log. Results come
  from freezing an object into a table and reading that.
- **No `GetScalar` / `PutScalar` / `GetString`.** These are not on the EViews
  COM interface at all. `Get` covers them and infers the type.
- **One COM thread.** MCP dispatches synchronous tools across a thread pool,
  and a COM pointer is not valid across apartments, so every EViews call is
  funnelled onto a single apartment-initialised thread.
- **Importing into an open workfile truncates the file** to that page's length,
  silently. Imports therefore create a new workfile by default; merging into the
  current page is opt-in.
- **EViews limits how many workfiles may be open** and then refuses to create
  another, so `close_workfile` exists to keep long sessions healthy.

## Tests

```bash
python tests/test_offline.py        # 27 tests, no EViews needed
python tests/test_live.py           # 25 tests, drives the MCP tool layer
python tests/test_live_client.py    # 58 tests, drives the library API
```

`pytest` runs the offline suite by default; the live suites are opt-in because
they need an EViews licence.

## Licence

MIT. Copyright (c) 2026 Merwan Roudane.
