# io.github.bayesian-energy/convexity-mcp (npm · convexity-mcp)

Build, edit, solve and analyse Convexity energy-system models from any MCP client; drives the app.

- Trust score: 64/100 (medium)
- Change this week: 0
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-21

## Components

- npm · `convexity-mcp`: 64/100 (this document), [markdown](https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp.md), [page](https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp)

## Channel facts

- Registry: `npm`
- Package: `convexity-mcp`
- Version: `0.6.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-21.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 24 of 51 dependencies flagged as unhealthy (1 deprecated).
- **Provenance & Transparency**: 6/100
  - Repository check failed: the declared repository URL returned HTTP 404.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: the license (SEE LICENSE IN LICENSE.md) isn't a recognized OSI-approved license.
  - Actively maintained (last published 12 days ago).
  - Security-disclosure policy not yet verified: we couldn't inspect the source repository.
- **Schema Quality & AI Usability**: 86/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 7212 tokens (~118/item across 61 items; 39 tools + 22 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability check failed: the tool surface changed between 0.2.1 and 0.6.0: 61 tool removals, 0 breaking changes, 21 additions.
- **Tool Coverage**: 95/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 85% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 39 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 41 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the io.github.bayesian-energy/convexity-mcp server?

io.github.bayesian-energy/convexity-mcp runs locally as an npm package, launched with npx -y convexity-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add bayesian-energy-convexity-mcp -- npx -y convexity-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "bayesian-energy-convexity-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "convexity-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "bayesian-energy-convexity-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "convexity-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add bayesian-energy-convexity-mcp -- npx -y convexity-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "bayesian-energy-convexity-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "convexity-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add bayesian-energy-convexity-mcp --command npx --arg -y --arg convexity-mcp
```

### Hermes

```yaml
mcp_servers:
  bayesian-energy-convexity-mcp:
    command: "npx"
    args: ["-y", "convexity-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "bayesian-energy-convexity-mcp": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "convexity-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add bayesian-energy-convexity-mcp -t stdio -c npx -a -y convexity-mcp
```

### Other

```json
{
  "mcpServers": {
    "bayesian-energy-convexity-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "convexity-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-09 (score 64, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-09-08 (score 49, −15)

- [security regression] Malware scan: pass → unverified
- [functional improvement] Schema quality: 142 → 118
- [functional] Destructive annotations: 0 → pass
- [functional] Package version: 0.5.0 → 0.6.0

### 2026-09-07 (score 64, +1)

No change was recorded against any check on this day. Stability & Change Management went from 11 to 14.

### 2026-09-06 (score 63, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-09-05 (score 48, −4)

- [security regression] Malware scan: pass → unverified
- [security improvement] Known CVEs: unverified → pass
- [functional improvement] Dependency health: unverified → 0.81
- [functional] Package version: 0.4.1 → 0.5.0

### 2026-09-04 (score 52, +7)

- [security regression] Stability: 0.03 → unverified
- [security regression] Known CVEs: pass → unverified
- [security regression] Tool safety: pass → unverified
- [security regression] Stability: 0.03 → fail
- [security improvement] Malware scan: unverified → pass
- [functional regression] Schema quality: 15158 → 19426
- [functional regression] Tool coverage: 95% → 86%
- [functional regression] Tool coverage: 95% → 88%
- [functional regression] Dependency health: 0.81 → unverified
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional improvement] Schema quality: 15158 → 11732
- [functional] First check of Schema quality: unverified
- [functional] First check of Schema quality: 100
- [functional] Package version: 0.3.0 → 0.4.1
- [functional] Package version: 0.3.0 → 0.4.0

### 2026-09-03 (score 45, −15)

- [security regression] Malware scan: pass → unverified
- [functional regression] Tool coverage: 100% → 95%
- [functional regression] Schema quality: 12950 → 15158
- [functional improvement] Stability: unverified → 0.03
- [functional] Package version: 0.2.1 → 0.3.0

### 2026-09-02 (score 60)

First indexed and scored.

## MCP tools (39)

### `set_component_attribute` (~190 tokens)

Set a static attribute value for a component, looked up by name. Pass scenario_id to set the value only for a specific scenario (leaving the base case unchanged).

Input parameters:

- `attribute_name` (string, required): Name of the attribute (e.g. 'marginal_cost', 'p_nom', 'efficiency')
- `component_name` (string, required): Name of the component (e.g. 'Gen2', 'Solar_Farm')
- `replace_timeseries` (boolean): Required true to replace an attribute that currently holds a timeseries with a single value (otherwise refused, so a profile is never lost by accident; to rescale one use modify_timeseries).
- `scenario_id` (integer): Optional scenario ID. If provided, sets the value only for this scenario. If omitted, sets the value for the currently-active scenario.
- `value` (number|string|boolean, required): The value to set

### `get_model_summary` (~154 tokens)

Get a summary of the current model. When aggregate:true (or auto-selected for large models), returns counts by type/carrier and capacity totals without a per-row dump. When aggregate:false, returns full component rows with every set static attribute (p_min_pu, efficiencies, cyclic flags — the ones that change dispatch). Use this before EDITING a model — it replaces multiple list_components/get_attribute calls. For analysis or results, orient with assess_model and pull aggregates with get_statistic instead.

Input parameters:

- `aggregate` (boolean): If true, return counts by type/carrier and capacity totals — no per-row component dump. If false, return full component rows with key attributes. Defaults to true when component_count > 500.

### `list_validation_rules` (~148 tokens)

The attribute vocabulary. With no filter: an index — per component type, the attribute groups and attribute names (cheap; start here). Pass component_type for that type's rules (data type, unit, default, required, input vs result, timeseries allowed), optionally narrowed by group_name. Use get_validation_rule for one attribute in full.

Input parameters:

- `component_type` (string): e.g. 'GENERATOR', 'LOAD', 'LINK', 'STORAGE_UNIT', 'BUS' — omit for the index.
- `group_name` (string): Only rules in this group (group names come from the index).
- `names_only` (boolean): With component_type: return attribute names only.

### `get_validation_rule` (~88 tokens)

Get the validation rule for a specific component type and attribute, including data type, default value, and valid range.

Input parameters:

- `attribute_name` (string, required): Name of the attribute (e.g. 'p_nom', 'marginal_cost')
- `component_type` (string, required): Component type (e.g. 'GENERATOR', 'LOAD', 'LINK', 'STORAGE_UNIT', 'BUS')

### `create_scenario` (~212 tokens)

Create a new scenario in the network. Use this to set up ensembles or sensitivity analyses. The returned scenario_id is what every other tool's scenario_id takes (solve, results, attributes, timeseries); the base case is scenario_id omitted or "base". After creating a scenario, use set_component_attribute with scenario_id to override attribute values.

ENSEMBLE CONVENTION: To create an ensemble, use '/' in the name: 'ensemble_name/member_name'. For example, to create a 'climate' ensemble with 3 members, call create_scenario three times with names 'climate/dry', 'climate/wet', 'climate/normal'. The app automatically groups scenarios sharing the same prefix into an ensemble.

Input parameters:

- `description` (string): Optional description of the scenario
- `name` (string, required): Name of the scenario (e.g. 'High Prices', 'Ensemble Member 1')
- `probability` (number): Optional probability weight (0–1) for ensemble scenarios.

### `list_scenarios` (~78 tokens)

List all scenarios defined in the network, including their run status and descriptions. By default the 'Actual' scenario is excluded. Set include_actual=true when the user asks about actuals data or wants to compare actuals against other scenarios.

Input parameters:

- `include_actual` (boolean): If true, include the 'Actual' scenario. Default is false.

### `get_component_timeseries` (~261 tokens)

Get a compact summary of a timeseries attribute (length, min/max/mean, p05/p50/p95, zero_count, first/last 5 values, variation hint). Use for load profiles (p_set), generation (p), capacity factors (p_max_pu), marginal prices, state of charge, etc. Pass full=true ONLY when you need the raw array (e.g. to plot or inspect a specific hour) — otherwise the summary is enough to reason about shape.

Input parameters:

- `attribute_name` (string, required): Name of the timeseries attribute (e.g. 'p_set', 'p', 'p_max_pu', 'marginal_price', 'state_of_charge')
- `component_name` (string, required): Name of the component (e.g. 'Load3', 'Solar_Farm')
- `full` (boolean): If true, include the raw values array in addition to the summary. Default false — summary alone is cheap to read and enough for most reasoning.
- `max_points` (integer): Cap on values read (defaults to 8760). The return is still summary-only unless full=true.
- `scenario_id` (integer): Optional scenario ID. If omitted, returns the timeseries for the currently-active scenario.

### `set_attribute_batch` (~73 tokens)

Set static attributes on multiple components in one call. Pass a list of updates, each with component_name, attribute_name, and value. Much more efficient than calling set_component_attribute repeatedly. Example: set annual_failure_frequency on 30 generators in one call.

Input parameters:

- `updates` (array, required): List of attribute updates to apply.

### `get_summary_stats` (~211 tokens)

Get overall summary statistics for the current model from the loaded solve results: power/transmission/energy capacity, dispatch, emissions, capital/operational/total cost — each broken down by carrier — plus unmet load and LOLH per bus. This is the whole-horizon total; for a per-year breakdown use get_yearly_results. Pass scenario_id for a specific scenario; omit for the base case. Optionally filter to one bus. Read-only.

Input parameters:

- `bus_id` (integer): Optional bus ID to filter the summary.
- `include_zero` (boolean): Keep carriers with nothing in a table (the full matrix). Default false: only carriers with a value, so the answer is what happened.
- `scenario_id` (integer|string): Which scenario to read: a scenario id number for a named scenario, or the string "base" for the Base Scenario (the as-built network — it has NO numeric id, so never pass a guessed number for it). Omi…

### `get_prices` (~216 tokens)

Wholesale electricity prices from the loaded solve: a load-weighted system price, a per-bus breakdown in the model's currency per MWh, and a separate scarcity line for any bus that shed load. Use it for any price question, per scenario; pass price_type "marginal" for the LP shadow price. Read-only; needs a solved scenario.

Input parameters:

- `bus_names` (array): Optional: restrict to these bus names (e.g. a single market zone). Omit to read every bus.
- `price_type` (string): Which price: "clearing" (pay-as-clear wholesale price, the default) or "marginal" (LP shadow price of the power balance, includes binding constraint effects).
- `scenario_id` (integer|string): Which scenario to read: a scenario id number for a named scenario, or the string "base" for the Base Scenario (the as-built network — it has NO numeric id, so never pass a guessed number for it). Omi…

### `compare_scenarios` (~220 tokens)

Compare two or more scenarios on one metric, by technology, in a single call — use this for any "compare scenario A vs B" request instead of reading each scenario separately and subtracting by hand. Returns an aligned per-technology table of values for each scenario plus signed deltas against the baseline (the FIRST scenario, usually the Base Scenario). Read-only; only over solved scenarios.

Input parameters:

- `bus_id` (integer): Optional bus id to restrict the comparison to one location.
- `metric` (string, required): What to compare by technology: generation (MWh), capacity (MW), capital_cost / operating_cost / system_cost (€), emissions (tCO2), or financial metrics: revenue (€), market_value / lcoe (€/MWh), capt…
- `scenario_ids` (array, required): Two or more scenarios to compare. Each is a scenario id number or the string "base" for the Base Scenario. The FIRST is the baseline that deltas are measured against (usually "base").

### `get_solve_results` (~177 tokens)

Get the results from the most recent optimization solve that has been loaded into the current model. Returns status, objective value, solve time, and network statistics. Pass scenario_id to get results for a specific scenario; omit for the base case. Returns a "not solved" message when no solve has been loaded (the model has not been solved, or the solve result has not been loaded from the Jobs panel yet).

Input parameters:

- `compact` (boolean): Return only the headline numbers and core summary, not the full per-carrier breakdown.
- `scenario_id` (integer|string): Which scenario to read: a scenario id number for a named scenario, or the string "base" for the Base Scenario (the as-built network — it has NO numeric id, so never pass a guessed number for it). Omi…

### `set_dashboard_config` (~325 tokens)

Configure the analytics dashboard from the app’s built-in chart templates. Sets up which charts appear in the Analytics tab, with auto-generated layout. Call this after building a model to give the user a pre-configured analytics view. REPLACES the whole dashboard — to append one custom chart, use create_chart instead. TO COMPARE SCENARIOS SIDE BY SIDE: give a chart `scenarios` (names or ids, "base" for the base case) and it becomes one pinned chart per scenario; pass group_by "scenario" to arrange the canvas by scenario. A chart with no scenario follows the active-scenario cursor instead, so it re-renders in place when the scenario changes and never shows two at once. Valid template ids — timeseries: dispatch, curtailment, available-capacity, availability, lmp, lcp, link-flows, transformer-flows · summary: generation, system-cost, power-capacity, transmission-capacity, storage-capacity, emissions, curtailment-summary, unmet-load · reliability: unmet-load-timeseries, lol-duration-curve, lolh-distribution, load-duration-curve · map: network.

Input parameters:

- `charts` (array, required): Charts to show, in order.
- `group_by` (string): Arrange the canvas by scenario ('scenario') or as a plain stack ('none', the default). Use 'scenario' whenever charts are pinned.
- `scenario` (string|number): Which scenario the active cursor points at — a name, an id, or "base". Only affects charts that are not pinned.

### `cloud_solve_machines` (~64 tokens)

List the cloud machine sizes available for cloud_solve_submit with their vCPUs, memory, parallel-scenario capacity and hourly price in GBP (the charged rate). Call this before submitting so you can tell the user what a solve will cost; never guess prices.

### `cloud_solve_submit` (~287 tokens)

Solve the open model in the Convexity cloud (paid per hour of machine time; needs a signed-in account with cloud solve enabled). Quote cloud_solve_machines first; pass wait: true to block until it finishes, then cloud_solve_fetch_result brings the solved model back beside the original.

Input parameters:

- `confirm_cost` (boolean): Required true for machine sizes above s: confirms the user has seen the hourly price and agreed.
- `machine_size` (string): Cloud machine size from cloud_solve_machines. Default xs.
- `max_run_duration_seconds` (integer): Wall-clock cap for the whole job; the job is killed past it. Omit for the service default (1 hour).
- `max_workers` (integer): Scenarios solved in parallel on the machine (bounded by its capacity). Omit for the size default.
- `scenario_ids` (array): Scenario ids to solve (null = base case). Omit to solve the active scenario.
- `solver_name` (string): Solver engine. 'highs' is free and always available; 'mosek' needs the entitlement on the account.
- `timeout_seconds` (integer): With wait: give up waiting after this long (default 900).
- `wait` (boolean): Block until the cloud job is terminal (progress is reported), then return its status. Default false: return once submitted.

### `cloud_solve_status` (~65 tokens)

Status of a cloud solve: phase, timings, per-scenario progress and any error. Without job_uuid, lists the cloud solves submitted from this machine (newest first) so you can find the id.

Input parameters:

- `job_uuid` (string): From cloud_solve_submit.

### `cloud_solve_logs` (~81 tokens)

Solver output of a cloud solve (structured log lines, newest page first via page_token). Use it to explain a FAILED or INFEASIBLE job or to report progress; keep page_size small.

Input parameters:

- `job_uuid` (string, required)
- `page_size` (integer)
- `page_token` (string): next_page_token from a previous call.

### `cloud_solve_fetch_result` (~115 tokens)

Download a SOLVED cloud job into a new file beside the source model (<model>_solved.db, never overwriting the original) and make it the active model, so the results tools read from it. Pass save_path to choose the destination.

Input parameters:

- `job_uuid` (string, required)
- `overwrite` (boolean): Allow save_path to replace an existing file.
- `save_path` (string): Absolute .db path for the solved model. Default: a _solved sibling of the model that was submitted.

### `cloud_solve_cancel` (~34 tokens)

Cancel a queued or running cloud solve. Billing stops once the machine is released.

Input parameters:

- `job_uuid` (string, required)

### `show_folder_in_app` (~79 tokens)

Point the Convexity app's file explorer at a folder (default: the open model's folder) so the user sees the model file. open_in_app does this on its own; use this to show another folder or to refresh the listing.

Input parameters:

- `path` (string): Absolute folder or .db path. Default: the open model.

### `open_in_app` (~127 tokens)

Open a model in the Convexity desktop app and bring the app to the front — starting the app if it is not running. Defaults to the active model. Once the app has the model open, edits made here appear in it live and solve_via_desktop_app can run it locally. With no tab connected this opens the web app in the computer's DEFAULT browser, already paired.

Input parameters:

- `name` (string): Web app: the model's name as the tab's Files panel shows it.
- `path` (string): Absolute .db path. Default: the active model.

### `app_state` (~54 tokens)

Whether the Convexity desktop app is running, its version, the model it currently has loaded, and whether its solve backend is up. Cheap; call it before choosing between the app (free, live) and the cloud.

### `show_in_app` (~69 tokens)

Switch the Convexity app to a view: 'map', 'table', 'analytics' (results), 'jobs', 'text' or 'settings'. To focus specific components on the map or filter the table, use show_on_map / show_in_table.

Input parameters:

- `view` (string, required)

### `solve_via_desktop_app` (~305 tokens)

Solve the open model through the running Convexity app: on DESKTOP this queues one job per scenario in the app’s Job Queue exactly as the Run button does — free, on this computer, results written into the model file in place, so the results tools read them once desktop_app_jobs reports it completed. ON WEB THERE IS NO LOCAL SOLVER: the tab submits a CLOUD solve instead, which is BILLED to the account (machine_size, default xs) and loads its result back into the tab. Say so before solving on web if the user has not already asked for a cloud run. Do not edit the model while its solve is running. Returns at once; solves take minutes.

Input parameters:

- `machine_size` (string): Web app only: the cloud machine the tab submits to (default xs; billed).
- `max_parallel_jobs` (integer): How many of the queued scenarios may solve at once.
- `scenario_ids` (array): Scenario ids to solve (null = base case). Omit to solve the active scenario.
- `solver_name` (string): Solver engine installed locally; 'highs' is always available, 'mosek' only with a local licence.
- `timeout_seconds` (integer): With wait: give up waiting after this long (default 900).
- `wait` (boolean): Block until the jobs finish (progress is reported), then return their outcome. Default false: return as soon as they are queued.

### `wait_for_solve` (~116 tokens)

Block until solve jobs finish, reporting progress on the way, then return each one's outcome (failed local jobs include their log tail). Pass job_ids (desktop app queue, from solve_via_desktop_app) and/or job_uuids (cloud, from cloud_solve_submit); with neither it waits for every unfinished job in the app's queue.

Input parameters:

- `job_ids` (array)
- `job_uuids` (array)
- `timeout_seconds` (integer): Give up after this long (default 900).

### `list_jobs` (~70 tokens)

Every solve job this machine knows about: the desktop app's queue (when the app is running) and the cloud jobs submitted from here, newest first, with live status. One view instead of desktop_app_jobs plus cloud_solve_status.

Input parameters:

- `limit` (integer): Rows per source (default 10).

### `show_on_map` (~204 tokens)

Navigate the user's map view to show specific components. Supports three modes:
1\. By component IDs/names: flies to and selects the specific components.
2\. By carrier names: hides all other carriers on the map and zooms to fit the matching components. Use this when the user asks to see a category like 'solar farms', 'wind turbines', 'gas plants' etc.
3\. Both: filters by carrier AND selects specific components.
Use after creating components or when the user asks to see something on the map. Needs the Convexity desktop app running (open_in_app starts it).

Input parameters:

- `carrier_names` (array): List of carrier names to filter the map to (e.g. ['solar', 'wind']). The map will hide all other carriers and zoom to fit the matching components.
- `component_ids` (array): List of component IDs to show on the map.
- `component_names` (array): List of component names to show on the map.

### `show_in_table` (~156 tokens)

Switch the user to the table view for a component type — the whole table when only component_type is given, or filtered by component IDs, names (exact) or carrier names (e.g. 'show all oil generators'). Needs the Convexity desktop app running (open_in_app starts it).

Input parameters:

- `carrier_names` (array): List of carrier names to filter by (e.g. ['oil', 'solar']). All components of the given type with these carriers will be shown.
- `component_ids` (array): List of component IDs to filter the table to.
- `component_names` (array): List of component names to filter the table to.
- `component_type` (string, required): The component type to show in the table.

### `account_status` (~63 tokens)

The signed-in Convexity account: which cloud features the organisation has enabled (cloud solve, solvers, data APIs, playbook signing, MCP access) and which Modelverse models it may open. Call it before promising a cloud feature, or to explain a refusal.

### `search_docs` (~54 tokens)

Search the Convexity product documentation for how features work. Use when the user asks how to do something in Convexity or how a concept works.

Input parameters:

- `query` (string, required)
- `top_k` (integer)

### `get_worked_example` (~408 tokens)

A complete walkthrough for a common task, as text: three_bus_network (Build a small gas + wind + load network on a one-week hourly axis, then solve it locally and show the dispatch in the Convexity app.); load_demand_from_csv (Load a half-hourly regional demand file onto the matching loads of an existing model, aligned to its hourly axis.); solve_and_plot (Solve a model locally through the Convexity app, then set the Results Viewer up with a dispatch chart and a price chart and show it.); describe_model (A read-only summary of a model: component counts, capacity by carrier, whether timeseries data is loaded.); parameter_sweep (Create one scenario per value of a single attribute, solve them all locally, and compare system cost across the sweep.); unit_commitment (Turn a thermal generator into a unit-commitment unit with a minimum up time, using the attribute rules to find the right names.); compare_scenario (Create a scenario that changes one thing, solve the base case and the scenario locally, and report how system cost and prices moved.); compare_on_canvas (Solve a scenario against the base case and show both in the Analytics dashboard at once, grouped by scenario — not one at a time.); write_playbook (Write a small playbook for the open model, save it into the model, run it locally through the Convexity app, and report its outputs.); publish_playbook (Publish a playbook stored in a model as a page anyone with the link can run, with a daily run cap. Needs an API key.); run_playbook_cloud (Sign a playbook source file and run it in the cloud against a model on the smallest machine, then report its outputs. Paid; needs an API key.). The same content as the MCP prompts, for clients that do not surface prompts.

Input parameters:

- `name` (string): Which walkthrough. Omit to list them.

### `get_open_model` (~49 tokens)

Report which model .db file this server is currently operating on, and whether it is writable or read-only (and why). Call this first when the user names a file, to check it matches.

### `open_model` (~79 tokens)

Switch to a different Convexity model: absolute path to a .db file on disk. All subsequent tools operate on it. Edits are written in place — suggest the user works on a copy of any model they care about. Resets the active scenario to the base case.

Input parameters:

- `path` (string, required): Absolute path to a model .db.

### `create_model` (~195 tokens)

Create a brand-new blank Convexity model at an absolute .db path (must not already exist) and make it the active model. Sets the time axis (naive-UTC timestamps) and seeds the default carrier set. Use this when the user wants to build a model from scratch — no need to ask them to create a file in the app first.

Input parameters:

- `description` (string): Model description.
- `end_time` (string, required): Axis end (inclusive), "YYYY-MM-DD HH:MM:SS" (UTC).
- `name` (string, required): Model name.
- `path` (string): Absolute path for the new .db. Default: ~/models/<name>.db, the folder the Convexity app shows.
- `start_time` (string, required): Axis start, "YYYY-MM-DD HH:MM:SS" (UTC).
- `time_resolution_minutes` (integer): Period length in minutes (default hourly).

### `use_scenario` (~56 tokens)

Set the active scenario for all subsequent tool calls. Pass a scenario id from list_scenarios, or null to work on the base case.

Input parameters:

- `scenario_id` (integer|null, required): Scenario id, or null for the base case.

### `create_components_batch` (~120 tokens)

Create many components in one call: each item names its type (bus, generator, load, link, storage_unit, carrier) and its fields; any other key is set as a static attribute. Buses need latitude and longitude; generators, loads and storage units take their bus's position unless given one. Carriers, then buses, then the rest are created in order, so references resolve; a line is a link with p_nom. PROCESS is read-only here.

Input parameters:

- `items` (array, required)
- `stop_on_error` (boolean)

### `set_timeseries_batch` (~111 tokens)

Set several timeseries in one call without shipping every value: each series gives values (full array), OR constant (one number for every period), OR pattern (a short array tiled along the time axis — 24 values on an hourly model is a daily profile, 168 a weekly one; add scale for its peak), OR scale_of (copy another component's series and multiply/offset it). Use load_timeseries_from_file for data that lives in a file.

Input parameters:

- `series` (array, required)

### `list_more_tools` (~106 tokens)

The tools beyond the default set, by area: build (single-component edits, timeseries operations, data files, constraints, comments), analyse (statistics, carrier breakdowns, reliability, ensembles, sweeps, diagnostics), app (import/export through the desktop app), data (renewables, demand, costs, outlook). Returns their names and purposes — call any of them by name afterwards, whether or not your client refreshes its tool list.

Input parameters:

- `toolsets` (array, required)

### `preview_model_map` (~104 tokens)

Render a map of the model as an inline image: buses at their coordinates, lines and links between them, and generators (triangles), loads (squares) and storage (diamonds) ringed around their bus. Use it to show the user the network — especially right after edits, to confirm what changed and where. Optionally pass component names to highlight.

Input parameters:

- `highlight` (array): Component names (buses, lines, links) to highlight and label.

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp#diagnostics

## Score history

- 2026-09-21: 64
- 2026-09-20: 64
- 2026-09-19: 64
- 2026-09-18: 64
- 2026-09-17: 64
- 2026-09-16: 64
- 2026-09-15: 64
- 2026-09-14: 64
- 2026-09-13: 64
- 2026-09-12: 64
- 2026-09-11: 64
- 2026-09-10: 64
- 2026-09-09: 64
- 2026-09-08: 49
- 2026-09-07: 64
- 2026-09-06: 63
- 2026-09-05: 48
- 2026-09-04: 52
- 2026-09-03: 45
- 2026-09-02: 60

## Common questions

### What is the io.github.bayesian-energy/convexity-mcp server?

io.github.bayesian-energy/convexity-mcp is listed in the public MCP registry as io.github.bayesian-energy/convexity-mcp. Build, edit, solve and analyse Convexity energy-system models from any MCP client; drives the app. This page covers its npm package (convexity-mcp).

### Is the io.github.bayesian-energy/convexity-mcp server safe to use?

io.github.bayesian-energy/convexity-mcp scores 64 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 21 September 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the io.github.bayesian-energy/convexity-mcp server expose?

io.github.bayesian-energy/convexity-mcp exposes 39 tools: set_component_attribute, get_model_summary, list_validation_rules, get_validation_rule, create_scenario, and 34 more. Their descriptions and schemas cost roughly 5,524 tokens of context every time the server is loaded.

### Is the io.github.bayesian-energy/convexity-mcp server still maintained?

io.github.bayesian-energy/convexity-mcp is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- npm package: https://www.npmjs.com/package/convexity-mcp
- Socket report: https://socket.dev/npm/package/convexity-mcp
- Changelog RSS feed: https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp.json
- HTML version of this page: https://verifymcp.io/servers/bayesian-energy-convexity-mcp/convexity-mcp
