diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml
index ff463f8..f365630 100644
--- a/.github/workflows/test-integration.yml
+++ b/.github/workflows/test-integration.yml
@@ -1,7 +1,7 @@
name: Integration tests
-# Fast wiring/integration suite for the macromod integration layer. Runs on
-# PRs and pushes that touch integration/**. It installs the base macromod
+# Fast wiring/integration suite for the policyengine-macro integration layer. Runs on
+# PRs and pushes that touch integration/**. It installs the base policyengine-macro
# package plus the two lightweight model repos (OBR emulator + UK SVAR) so the
# real OBR/SVAR wiring is exercised, but NOT the heavy PolicyEngine country
# models — those (and every full model solve) are marked `slow` and skipped by
@@ -31,7 +31,7 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- - name: Install macromod + the two lightweight model repos
+ - name: Install policyengine-macro + the two lightweight model repos
run: |
python -m pip install --upgrade pip
# Base package (click, numpy, pandas, mcp) + pytest.
diff --git a/.github/workflows/validate-deployment.yml b/.github/workflows/validate-deployment.yml
index ed87a49..a0a4b44 100644
--- a/.github/workflows/validate-deployment.yml
+++ b/.github/workflows/validate-deployment.yml
@@ -55,7 +55,7 @@ jobs:
python-version: "3.13"
- name: Install remote test deps
# The remote suite talks to the public MCP endpoint over HTTP; it needs
- # no Modal auth and does not import the macromod package.
+ # no Modal auth and does not import the policyengine-macro package.
run: pip install --upgrade pip && pip install "mcp[cli]" pytest anyio
- name: Validate the live deployment
working-directory: integration
diff --git a/README.md b/README.md
index c70cab0..07c1103 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ benefits for the UK and US — the same engine that powers
[policyengine.org](https://policyengine.org) — complementing the macro models.
The models live in their own repositories. This repo hosts the **PolicyEngine Macro
-website** and the **integration layer** (`integration/`) — a `macromod` CLI
+website** and the **integration layer** (`integration/`) — a `pe-macro` CLI
and MCP server over the models, with CI auto-deploying the hosted MCP server
to Modal on every merge — merges to the model repos
(obr-macroeconomic-model, boe-var-model) trigger the same redeploy via
@@ -88,11 +88,11 @@ The [connect page](https://macromod.vercel.app/connect/) covers three ways to us
models:
- **MCP** — the hosted Model Context Protocol server is **live** at
- `https://policyengine--macromod-mcp-serve.modal.run/mcp`. Add it as a custom
+ `https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp`. Add it as a custom
connector in Claude or ChatGPT, or in Claude Code:
```bash
- claude mcp add --transport http macromod https://policyengine--macromod-mcp-serve.modal.run/mcp
+ claude mcp add --transport http policyengine-macro https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp
```
Ten tools: `score_reform` (a PolicyEngine reform — the same
@@ -103,19 +103,19 @@ models:
(`calculate_household`, `household_reform_impact`, `list_reform_parameters`,
`population_reform_impact`). `score_reform` with `model='og'` works locally
only: OG-UK is deliberately excluded from the hosted image (a score takes
- tens of minutes) — use `macromod score --model og` instead; `model='obr'`
+ tens of minutes) — use `pe-macro score --model og` instead; `model='obr'`
awaits the microsim static-costing bridge (#9), so raw shocks go through
`obr_shock`.
The server runs serverless and scales to zero — the first call after idle
may take ~10 s to wake.
-- **CLI** — the `macromod` CLI (`score`, `obr-shock`, `variables`, `forecast`,
+- **CLI** — the `pe-macro` CLI (`score`, `obr-shock`, `variables`, `forecast`,
`shocks`, `summary`, `household`, `household-impact`, `population-impact`,
`parameters`, `og-score`) lives
in [`integration/`](integration/); PyPI publish is planned. Install it —
with all three hosted-model packages and their data, no clone — via:
```bash
- pip install "macromod[models] @ git+https://github.com/PolicyEngine/macro#subdirectory=integration"
+ pip install "policyengine-macro[models] @ git+https://github.com/PolicyEngine/macro#subdirectory=integration"
```
- **Code** — drive each model's Python API yourself.
@@ -165,10 +165,10 @@ non-real numbers as illustrative.
## Roadmap
-- [x] `macromod` CLI (in `integration/`; PyPI publish still to come)
-- [x] Local MCP server (`python -m macromod.mcp_server`)
-- [x] Hosted MCP server (`https://policyengine--macromod-mcp-serve.modal.run/mcp`, auto-deployed by CI)
-- [x] OG-UK steady-state scoring (`macromod score --model og` / `macromod og-score`, local only)
+- [x] `pe-macro` CLI (in `integration/`; PyPI publish still to come)
+- [x] Local MCP server (`python -m policyengine_macro.mcp_server`)
+- [x] Hosted MCP server (`https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp`, auto-deployed by CI)
+- [x] OG-UK steady-state scoring (`pe-macro score --model og` / `pe-macro og-score`, local only)
- [x] Population-level PolicyEngine reform scoring (`population_reform_impact`, hosted and local)
- [ ] Additional macroeconomic model classes
- See [#1](https://github.com/PolicyEngine/macro/issues/1) — Rust port of the solver core
diff --git a/connect/index.html b/connect/index.html
index e0e22dc..b5fba83 100644
--- a/connect/index.html
+++ b/connect/index.html
@@ -221,7 +221,7 @@
1
Copy the PolicyEngine Macro URL
Click the copy button — you'll paste it in the next step.
The macromod CLI installs straight from GitHub — one pip install pulls the CLI plus all three models with their data, no cloning required. It lives in this repo's integration/ directory; a shorter pip install macromod will come with PyPI publication.
+
The pe-macro CLI installs straight from GitHub — one pip install pulls the CLI plus all three models with their data, no cloning required. It lives in this repo's integration/ directory; a shorter pip install policyengine-macro will come with PyPI publication.
coding agents with a terminal — Claude Code, Codex — can run the CLI directly, no MCP needed; or add the MCP server with one command (see the MCP tab).
@@ -668,9 +668,9 @@
Sector output, long-run
Under the hood: an 8-variable Bayesian VAR (1992Q1–2023Q2, Covid
dummies) is sampled from its normal-inverse-Wishart posterior, and each
draw is rotated per Arias–Rubio-Ramírez–Waggoner (2018) until the zero
- and sign restrictions name six structural shocks. The macromod CLI
- wraps the common outputs: macromod forecast,
- macromod shocks, macromod summary.
+ and sign restrictions name six structural shocks. The PolicyEngine Macro CLI
+ wraps the common outputs: pe-macro forecast,
+ pe-macro shocks, pe-macro summary.
diff --git a/integration/README.md b/integration/README.md
index f05cded..2e4dc36 100644
--- a/integration/README.md
+++ b/integration/README.md
@@ -1,6 +1,6 @@
# PolicyEngine Macro integration layer
-A single Python package (`macromod`) exposing the suite's models behind
+A single Python package (`policyengine-macro`) exposing the suite's models behind
one CLI and one MCP server:
- **OBR emulator** (`obr_macro`): runs the OBR's published model equations —
@@ -13,7 +13,7 @@ one CLI and one MCP server:
microdata (UK data is private: set `HUGGING_FACE_TOKEN`; the hosted
deployment provisions it server-side).
- **OG-UK** (`oguk`, optional/local-only): overlapping-generations
- steady-state scoring through `macromod score --model og`.
+ steady-state scoring through `pe-macro score --model og`.
`score_reform` is the one reform vocabulary across the suite: the same flat
`{parameter_path: value}` dict as the microsimulation tools, dispatched to a
@@ -35,11 +35,11 @@ scoring model by its declared contract:
Every scoring result also carries a common `score` block — the `ScoreResult`
schema ([#10](https://github.com/PolicyEngine/macro/issues/10)): model id and
class, horizon, per-quantity deltas with units and basis, assumptions,
-caveats, and an optional distributional block — so `macromod compare
+caveats, and an optional distributional block — so `pe-macro compare
--reform '...' --models microsim,obr` renders the same reform through
different model classes in one table.
-`src/macromod/core.py` holds the model adapters (single source of truth);
+`src/policyengine_macro/core.py` holds the model adapters (single source of truth);
`cli.py` and `mcp_server.py` are thin wrappers over the same functions.
## Install
@@ -48,10 +48,10 @@ No clone needed — one pip install pulls the CLI plus the hosted-model
packages (the OBR emulator and the SVAR ship their data as package data):
```bash
-pip install "macromod[models] @ git+https://github.com/PolicyEngine/macro#subdirectory=integration"
+pip install "policyengine-macro[models] @ git+https://github.com/PolicyEngine/macro#subdirectory=integration"
```
-A shorter `pip install macromod` will come with PyPI publication.
+A shorter `pip install policyengine-macro` will come with PyPI publication.
For development, install with the full model set (policyengine included via
the `[models]` extra), then override the two model packages with local
@@ -73,36 +73,36 @@ uv venv .venv-og && uv pip install -p .venv-og/bin/python -e ./integration \
"oguk @ git+https://github.com/PSLmodels/OG-UK"
```
-(`-e ./integration` gives that env the `macromod` executable; the base
+(`-e ./integration` gives that env the `pe-macro` executable (and its legacy `macromod` alias); the base
package pins no policyengine version, so OG-UK's own pins win there.)
## CLI
```bash
-macromod variables # OBR shock variables + units
-macromod score --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
+pe-macro variables # OBR shock variables + units
+pe-macro score --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
--model og # PolicyEngine reform -> OG-UK (slow)
-macromod score --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
+pe-macro score --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
--model obr --years 5 # static costing -> OBR second-round effects
-macromod compare --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
+pe-macro compare --reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}' \
--models microsim,obr # same reform, model classes side by side
-macromod obr-shock --var CGG --shock 1250 --periods 4 # £5bn/yr spending, 1 year
-macromod obr-shock --var TCPRO --shock -0.05 # 5pp corp tax cut (closure auto-on)
-macromod forecast --horizons 12 --draws 500 # YoY GDP & CPI, 68/90 bands
-macromod shocks --draws 500 # P(sign) of latest-quarter shocks
-macromod summary # instant, parses committed results
+pe-macro obr-shock --var CGG --shock 1250 --periods 4 # £5bn/yr spending, 1 year
+pe-macro obr-shock --var TCPRO --shock -0.05 # 5pp corp tax cut (closure auto-on)
+pe-macro forecast --horizons 12 --draws 500 # YoY GDP & CPI, 68/90 bands
+pe-macro shocks --draws 500 # P(sign) of latest-quarter shocks
+pe-macro summary # instant, parses committed results
```
PolicyEngine tools:
```bash
-macromod parameters # curated reform parameters
-macromod household --country uk \
+pe-macro parameters # curated reform parameters
+pe-macro household --country uk \
--people '[{"age":35,"employment_income":50000}]'
-macromod household-impact --country uk \
+pe-macro household-impact --country uk \
--people '[{"age":35,"employment_income":50000}]' \
--reform '{"gov.hmrc.income_tax.rates.uk[0].rate":0.25}'
-macromod population-impact --country uk \
+pe-macro population-impact --country uk \
--reform '{"gov.hmrc.cgt.basic_rate":0.20,"gov.hmrc.cgt.higher_rate":0.40}'
```
@@ -119,7 +119,7 @@ benefits the MCP server).
## MCP server
-Runs over stdio via `python -m macromod.mcp_server`, exposing ten tools:
+Runs over stdio via `python -m policyengine_macro.mcp_server`, exposing ten tools:
`score_reform` (a PolicyEngine reform through a chosen macro model),
`obr_shock` and `list_reform_variables` (raw OBR variable shocks),
`forecast_uk`, `latest_shocks`, `model_summary` (SVAR), and the PolicyEngine
@@ -129,7 +129,7 @@ tools `calculate_household`, `household_reform_impact`,
Test locally with Claude Code:
```bash
-claude mcp add macromod -- python -m macromod.mcp_server
+claude mcp add policyengine-macro -- python -m policyengine_macro.mcp_server
```
Default `draws=500` keeps tool calls to tens of seconds; raise it (e.g. 2000+)
@@ -142,7 +142,7 @@ The MCP server is deployed on Modal (workspace `policyengine`) over
streamable HTTP:
```
-https://policyengine--macromod-mcp-serve.modal.run/mcp
+https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp
```
Defined in `modal_app.py`. `policyengine[models]` is installed in the image;
@@ -158,8 +158,8 @@ model load. The private UK microdata credential comes from the Modal secret
- Claude Code:
```bash
- claude mcp add --transport http macromod-remote \
- https://policyengine--macromod-mcp-serve.modal.run/mcp
+ claude mcp add --transport http policyengine-macro-remote \
+ https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp
```
**Cost profile** — `min_containers=0` (scales to zero, $0 idle),
diff --git a/integration/modal_app.py b/integration/modal_app.py
index 704ac18..93fce9b 100644
--- a/integration/modal_app.py
+++ b/integration/modal_app.py
@@ -2,14 +2,14 @@
modal deploy integration/modal_app.py
-Serves the FastMCP instance from `macromod.mcp_server` (tools: score_reform,
+Serves the FastMCP instance from `policyengine_macro.mcp_server` (tools: score_reform,
obr_shock, list_reform_variables, forecast_uk, latest_shocks, model_summary,
calculate_household, household_reform_impact, list_reform_parameters,
population_reform_impact) as an
-ASGI app at https://policyengine--macromod-mcp-serve.modal.run/mcp
+ASGI app at https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp
Both model repos resolve their data files relative to their own repo root
-(`Path(__file__)`-relative); `macromod.core`'s svar_summary falls back to a
+(`Path(__file__)`-relative); `policyengine_macro.core`'s svar_summary falls back to a
checkout via MACROMOD_BOE_VAR_REPO only when boe_var is absent (it is
installed here, so the fallback never fires). We bake the repos into the
image at the SAME absolute paths and `pip install -e` them, so every path
@@ -35,9 +35,12 @@
POPULATION DATA (population_reform_impact)
------------------------------------------
-- Secret "macromod-hf" provides HUGGING_FACE_TOKEN for the private UK
+- Secret "macromod-hf" (legacy name kept deliberately; renaming the Modal
+ Secret needs maintainer action) provides HUGGING_FACE_TOKEN for the private UK
enhanced-FRS microdata on HuggingFace.
-- A modal.Volume ("macromod-pe-data") is mounted at /root/.cache/macromod;
+- A modal.Volume ("macromod-pe-data" — legacy name kept deliberately, see
+ above) is mounted at /root/.cache/macromod (legacy path, matches the data
+ already on the volume);
HF_HOME points the HuggingFace download cache inside it and
MACROMOD_PE_DATA_DIR puts the derived per-year .h5 files (~92MB/year)
there too, so the ~125MB download + dataset build happens once and
@@ -51,7 +54,7 @@
and a reform score needs two solves. That cannot fit the 600s Modal timeout
with any headroom, so oguk is excluded here; the score_reform MCP tool with
model='og' will return an ImportError on the hosted server. Use the local CLI
-(`macromod score --model og`) or a local MCP server instead. If it is ever added,
+(`pe-macro score --model og`) or a local MCP server instead. If it is ever added,
`pip install git+https://github.com/PSLmodels/OG-UK` works (hatchling build;
heavy deps: ogcore, policyengine-uk==2.88.0), but calibration also downloads
the enhanced FRS dataset (HUGGING_FACE_TOKEN) and UN demographics at runtime.
@@ -92,7 +95,7 @@
"click",
"mcp[cli]>=1.9", # needs FastMCP.streamable_http_app()
# PolicyEngine microsimulation (household calculator tools). Importing
- # it loads the full UK+US country models (~20s), so macromod.core
+ # it loads the full UK+US country models (~20s), so policyengine_macro.core
# imports it lazily inside the pe_* adapters — module import at
# container start stays fast; only the first policyengine tool call
# in a fresh container pays the load.
@@ -135,13 +138,15 @@
)
)
-app = modal.App("macromod-mcp")
+app = modal.App("policyengine-macro-mcp")
# Persistent cache for PolicyEngine population microdata: the HuggingFace
# download cache (HF_HOME) and the derived per-year .h5 datasets both live
# on this volume, so the first population_reform_impact call pays the
# download/build once and every later container reuses it.
+# Legacy path kept deliberately: it matches the data already on the volume.
CACHE_DIR = "/root/.cache/macromod"
+# Volume keeps its legacy name deliberately; renaming needs maintainer action.
pe_data_volume = modal.Volume.from_name("macromod-pe-data", create_if_missing=True)
@@ -156,7 +161,7 @@
min_containers=0, # scale to zero: no idle cost
scaledown_window=300, # stay warm 5 min between calls, then sleep
max_containers=3, # spend cap
- secrets=[modal.Secret.from_name("macromod-hf")],
+ secrets=[modal.Secret.from_name("macromod-hf")], # legacy name kept deliberately
volumes={CACHE_DIR: pe_data_volume},
)
@modal.concurrent(max_inputs=20)
@@ -167,8 +172,8 @@ def serve():
if "HUGGING_FACE_TOKEN" not in os.environ and os.environ.get("HF_TOKEN"):
os.environ["HUGGING_FACE_TOKEN"] = os.environ["HF_TOKEN"]
- from macromod import core
- from macromod.mcp_server import mcp
+ from policyengine_macro import core
+ from policyengine_macro.mcp_server import mcp
# Warm the cheap in-process cache (parses committed results/*.md only —
# NOT a model estimation, which would make cold starts take minutes).
@@ -188,7 +193,7 @@ def serve():
from mcp.server.transport_security import TransportSecuritySettings
mcp.settings.transport_security = TransportSecuritySettings(
- allowed_hosts=["policyengine--macromod-mcp-serve.modal.run"],
+ allowed_hosts=["policyengine--policyengine-macro-mcp-serve.modal.run"],
allowed_origins=["*"],
)
return mcp.streamable_http_app()
diff --git a/integration/pyproject.toml b/integration/pyproject.toml
index c462628..d26eef1 100644
--- a/integration/pyproject.toml
+++ b/integration/pyproject.toml
@@ -3,9 +3,9 @@ requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[project]
-name = "macromod"
+name = "policyengine-macro"
version = "0.1.0"
-description = "MacroMod integration layer: unified CLI and MCP server over the OBR macro emulator and the UK SVAR model"
+description = "PolicyEngine Macro integration layer: unified CLI and MCP server over the OBR macro emulator and the UK SVAR model"
requires-python = ">=3.10"
dependencies = [
"click>=8",
@@ -28,7 +28,9 @@ models = [
]
[project.scripts]
-macromod = "macromod.cli:main"
+pe-macro = "policyengine_macro.cli:main"
+# Legacy alias kept for existing docs/users.
+macromod = "policyengine_macro.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
diff --git a/integration/src/macromod/__init__.py b/integration/src/policyengine_macro/__init__.py
similarity index 82%
rename from integration/src/macromod/__init__.py
rename to integration/src/policyengine_macro/__init__.py
index aeeb59c..9da0d00 100644
--- a/integration/src/macromod/__init__.py
+++ b/integration/src/policyengine_macro/__init__.py
@@ -8,11 +8,11 @@
``obr_shock``.
- UK SVAR / BVAR model (``boe_var``): forecasts and structural shock readings.
-Same functions are exposed via a CLI (``macromod``) and an MCP server
-(``python -m macromod.mcp_server``).
+Same functions are exposed via a CLI (``pe-macro``) and an MCP server
+(``python -m policyengine_macro.mcp_server``).
"""
-from macromod.core import (
+from policyengine_macro.core import (
score_reform,
obr_shock,
obr_list_variables,
diff --git a/integration/src/macromod/cli.py b/integration/src/policyengine_macro/cli.py
similarity index 97%
rename from integration/src/macromod/cli.py
rename to integration/src/policyengine_macro/cli.py
index c00a1dd..0287443 100644
--- a/integration/src/macromod/cli.py
+++ b/integration/src/policyengine_macro/cli.py
@@ -6,7 +6,7 @@
import click
-from macromod import core
+from policyengine_macro import core
def _emit_json(obj) -> None:
@@ -33,7 +33,7 @@ def main() -> None:
show_default=True)
@click.option("--reform", required=True,
help='PolicyEngine reform JSON, e.g. \'{"gov.hmrc.income_tax.rates.uk[0].rate":0.21}\' '
- "(same shape as `macromod population-impact`).")
+ "(same shape as `pe-macro population-impact`).")
@click.option("--model", required=True,
type=click.Choice(list(core.SCORE_MODELS)),
help="Scoring model: og (OG-UK steady state; slow), obr (OBR "
@@ -52,9 +52,9 @@ def score(country, reform, model, year, max_iter, years, dataset, as_json):
"""Score a PolicyEngine reform with a scoring model of the suite.
One reform vocabulary: the same {parameter_path: value} dict as
- `macromod population-impact`. Every result carries a common `score`
- block for cross-model comparison (`macromod compare`). For raw OBR
- variable shocks in model units, use `macromod obr-shock`.
+ `pe-macro population-impact`. Every result carries a common `score`
+ block for cross-model comparison (`pe-macro compare`). For raw OBR
+ variable shocks in model units, use `pe-macro obr-shock`.
"""
try:
res = core.score_reform(
@@ -98,7 +98,7 @@ def _echo_score_block(score: dict) -> None:
@click.option("--country", type=click.Choice(["uk", "us"]), default="uk",
show_default=True)
@click.option("--reform", required=True,
- help='PolicyEngine reform JSON (same shape as `macromod score`).')
+ help='PolicyEngine reform JSON (same shape as `pe-macro score`).')
@click.option("--models", default="microsim,obr", show_default=True,
help="Comma-separated scoring models (og, obr, microsim).")
@click.option("--year", default=2026, show_default=True, help="Reform start year.")
@@ -142,7 +142,7 @@ def compare(country, reform, models, year, as_json):
@main.command("obr-shock")
-@click.option("--var", required=True, help="Policy variable to shock (see `macromod variables`).")
+@click.option("--var", required=True, help="Policy variable to shock (see `pe-macro variables`).")
@click.option("--shock", required=True, type=float,
help="Shock size; units depend on the variable (£m/quarter for CGG, decimal for TCPRO).")
@click.option("--periods", default=12, show_default=True, help="Quarters the shock is applied.")
diff --git a/integration/src/macromod/core.py b/integration/src/policyengine_macro/core.py
similarity index 99%
rename from integration/src/macromod/core.py
rename to integration/src/policyengine_macro/core.py
index 8b906d2..46edd8a 100644
--- a/integration/src/macromod/core.py
+++ b/integration/src/policyengine_macro/core.py
@@ -662,6 +662,8 @@ def _delta(b, r):
def _pe_pop_data_folder() -> str:
import os
+ # MACROMOD_PE_DATA_DIR env var and ~/.cache/macromod path keep their
+ # legacy names deliberately (the hosted Modal volume is mounted there).
return os.environ.get(
"MACROMOD_PE_DATA_DIR",
os.path.expanduser("~/.cache/macromod/policyengine-data"),
diff --git a/integration/src/macromod/mcp_server.py b/integration/src/policyengine_macro/mcp_server.py
similarity index 98%
rename from integration/src/macromod/mcp_server.py
rename to integration/src/policyengine_macro/mcp_server.py
index c747f7f..3ed4bb3 100644
--- a/integration/src/macromod/mcp_server.py
+++ b/integration/src/policyengine_macro/mcp_server.py
@@ -1,17 +1,17 @@
"""PolicyEngine Macro MCP server (stdio transport).
-Run with: python -m macromod.mcp_server
+Run with: python -m policyengine_macro.mcp_server
-Exposes the same adapter functions as the `macromod` CLI as MCP tools.
+Exposes the same adapter functions as the `pe-macro` CLI as MCP tools.
"""
from __future__ import annotations
from mcp.server.fastmcp import FastMCP
-from macromod import core
+from policyengine_macro import core
-mcp = FastMCP("macromod")
+mcp = FastMCP("policyengine-macro")
@mcp.tool()
@@ -41,7 +41,7 @@ def score_reform(
general-equilibrium comparison; the reform enters through
PolicyEngine-estimated tax functions. VERY SLOW (tens of
minutes) and excluded from the hosted server — run it
- locally via `macromod score --model og`; calling it here
+ locally via `pe-macro score --model og`; calling it here
returns install/CLI instructions.
'obr' — OBR macroeconometric emulator via the microsim
static-costing bridge: the reform is costed per year with
diff --git a/integration/tests/conftest.py b/integration/tests/conftest.py
index 33b5347..9b0d279 100644
--- a/integration/tests/conftest.py
+++ b/integration/tests/conftest.py
@@ -1,4 +1,4 @@
-"""Shared pytest configuration for the macromod integration tests.
+"""Shared pytest configuration for the policyengine-macro integration tests.
Tests marked `slow` run a real model estimation/solve or a full PolicyEngine
import (seconds to many minutes). They are skipped by default so a plain
diff --git a/integration/tests/test_contract.py b/integration/tests/test_contract.py
index acaf4bb..4fbbc31 100644
--- a/integration/tests/test_contract.py
+++ b/integration/tests/test_contract.py
@@ -17,7 +17,7 @@
import pytest
-from macromod import core
+from policyengine_macro import core
def _import_or_require(modname: str):
diff --git a/integration/tests/test_core.py b/integration/tests/test_core.py
index b138061..cd3b872 100644
--- a/integration/tests/test_core.py
+++ b/integration/tests/test_core.py
@@ -1,10 +1,10 @@
-"""Unit tests for the macromod adapters (small draws to keep runtime low)."""
+"""Unit tests for the policyengine_macro adapters (small draws to keep runtime low)."""
import json
import pytest
-from macromod import core
+from policyengine_macro import core
def test_list_variables():
@@ -158,7 +158,7 @@ def test_summary_without_boe_var_uses_env_checkout(monkeypatch, tmp_path):
def test_cli_summary_without_boe_var_errors_actionably(monkeypatch):
from click.testing import CliRunner
- from macromod.cli import main
+ from policyengine_macro.cli import main
_block_boe_var(monkeypatch)
monkeypatch.delenv("MACROMOD_BOE_VAR_REPO", raising=False)
@@ -172,7 +172,7 @@ def test_cli_summary_env_checkout_missing_files_errors(monkeypatch, tmp_path):
empty headings and exit 0 (round-2 review, new finding 1)."""
from click.testing import CliRunner
- from macromod.cli import main
+ from policyengine_macro.cli import main
_block_boe_var(monkeypatch)
monkeypatch.setenv("MACROMOD_BOE_VAR_REPO", str(tmp_path))
diff --git a/integration/tests/test_mcp_server.py b/integration/tests/test_mcp_server.py
index 94b7d94..308f304 100644
--- a/integration/tests/test_mcp_server.py
+++ b/integration/tests/test_mcp_server.py
@@ -8,7 +8,7 @@
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
-SERVER = StdioServerParameters(command=sys.executable, args=["-m", "macromod.mcp_server"])
+SERVER = StdioServerParameters(command=sys.executable, args=["-m", "policyengine_macro.mcp_server"])
EXPECTED_TOOLS = {
"score_reform",
diff --git a/integration/tests/test_og.py b/integration/tests/test_og.py
index 20b8cba..01d36c2 100644
--- a/integration/tests/test_og.py
+++ b/integration/tests/test_og.py
@@ -7,7 +7,7 @@
deployment image (see modal_app.py). oguk 0.3.0 calibrates its tax functions
from the PolicyEngine enhanced-FRS microdata and pins policyengine-uk==2.88.0;
policyengine-uk >= 2.89 renamed the dataset keys (enhanced_frs_2023_24_* ->
-populace_uk_*), so calibration KeyError-fails under a newer PE. The macromod
+populace_uk_*), so calibration KeyError-fails under a newer PE. The policyengine-macro
package itself requires policyengine[models]>=4 (which brings pe-uk >= 2.89 for
the household/population tools), so a single env cannot satisfy both. The real
end-to-end solve is therefore skipped when the installed PE is incompatible
@@ -20,7 +20,7 @@
import pytest
-from macromod import core
+from policyengine_macro import core
def _oguk_calibration_skip_reason():
diff --git a/integration/tests/test_population.py b/integration/tests/test_population.py
index e21dd1e..7a8d85d 100644
--- a/integration/tests/test_population.py
+++ b/integration/tests/test_population.py
@@ -14,7 +14,7 @@
import pytest
-from macromod import core
+from policyengine_macro import core
# ---------------------------------------------------------------------------
diff --git a/integration/tests/test_remote_mcp.py b/integration/tests/test_remote_mcp.py
index 10ba955..7eb73a8 100644
--- a/integration/tests/test_remote_mcp.py
+++ b/integration/tests/test_remote_mcp.py
@@ -21,7 +21,7 @@
URL = os.environ.get(
"MACROMOD_REMOTE_URL",
- "https://policyengine--macromod-mcp-serve.modal.run/mcp",
+ "https://policyengine--policyengine-macro-mcp-serve.modal.run/mcp",
)
EXPECTED_TOOLS = {
diff --git a/integration/tests/test_score_schema.py b/integration/tests/test_score_schema.py
index 0759d1c..3df3e00 100644
--- a/integration/tests/test_score_schema.py
+++ b/integration/tests/test_score_schema.py
@@ -13,8 +13,8 @@
import pytest
-from macromod import core
-from macromod.cli import main
+from policyengine_macro import core
+from policyengine_macro.cli import main
# ---------------------------------------------------------------------------
diff --git a/integration/tests/test_wiring.py b/integration/tests/test_wiring.py
index 7b7e6c9..0ac77e4 100644
--- a/integration/tests/test_wiring.py
+++ b/integration/tests/test_wiring.py
@@ -19,8 +19,8 @@
import pytest
from click.testing import CliRunner
-from macromod import core, mcp_server
-from macromod.cli import main
+from policyengine_macro import core, mcp_server
+from policyengine_macro.cli import main
# The full tool surface the server must expose (README + mcp_server.py).
EXPECTED_TOOLS = {
diff --git a/olg/index.html b/olg/index.html
index 8e7d2c8..63cb1ae 100644
--- a/olg/index.html
+++ b/olg/index.html
@@ -362,14 +362,14 @@
Where it plugs in today.
- OG-UK is wired into the macromod CLI as two commands:
+ OG-UK is wired into the PolicyEngine Macro CLI as two commands:
og-baseline (baseline steady state, model units) and
og-score (score a PolicyEngine reform — one or more parameter changes,
baseline + reform steady states mapped to £bn). Both use the fast
configuration: pooled tax functions, single sector, steady state only.
Two prerequisites, stated plainly. First, the calibration needs the
PolicyEngine enhanced-FRS microdata, which is gated:
diff --git a/pe/index.html b/pe/index.html
index cff7a03..dfc328c 100644
--- a/pe/index.html
+++ b/pe/index.html
@@ -212,7 +212,7 @@
What it answers — and what it doesn't yet.
It is a static microsimulation at heart — reforms are modelled statically, with optional post-hoc behavioural responses (e.g. labour supply elasticities). No general equilibrium: that second act is exactly what the macro members of the suite add.
-
PolicyEngine Macro integration status: the household tools — computing one specific family's taxes, benefits, and net income under current law or a reform — are hosted and live on the MCP server (and the macromod CLI): calculate_household, household_reform_impact, and list_reform_parameters. Representative-population reform scoring (population_reform_impact: budgetary impact, deciles, winners/losers over whole microdata) is hosted too — the private enhanced-FRS credential is provisioned server-side — and runs locally with a HUGGING_FACE_TOKEN.
+
PolicyEngine Macro integration status: the household tools — computing one specific family's taxes, benefits, and net income under current law or a reform — are hosted and live on the MCP server (and the pe-macro CLI): calculate_household, household_reform_impact, and list_reform_parameters. Representative-population reform scoring (population_reform_impact: budgetary impact, deciles, winners/losers over whole microdata) is hosted too — the private enhanced-FRS credential is provisioned server-side — and runs locally with a HUGGING_FACE_TOKEN.