Skip to main content
Glama

eviews-mcp

Tests PyPI Python Licence Platform EViews

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

Documentation site  ·  Researcher guide  ·  PyPI

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 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

pip install eviews-mcp

With pandas support:

pip install "eviews-mcp[pandas]"

Or from a clone, for development:

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

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"))
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:

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:

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:

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:

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:

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

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:

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:

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:

ev.run("""series ok = 1
broken_command
""")
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:

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

For Claude Code:

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.

Troubleshooting

If the server will not start

A version before 1.3.3 could install the MCP SDK 2.x, which removed the module this server is built on. The symptom is the same every time:

ModuleNotFoundError: No module named 'mcp.server.fastmcp'

1.3.3 pins the SDK below 2.0. Upgrading fixes it -- but pip may serve a cached index that predates the release, so bypass the cache:

pip install --upgrade --no-cache-dir "eviews-mcp[pandas]"

Confirm the server itself imports, not just the package. The package imports lazily and succeeds even when the SDK is unusable, so checking it proves nothing:

python -c "import eviews_mcp.server as s; print(len(s.mcp._tool_manager.list_tools()), 'tools')"

Twenty-four tools means the install is healthy.

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

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    # 62 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.