Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
97a86b3
feat: add first layer approach for mcp server
Apr 22, 2026
d57ee4a
test: add test for mcp server to increase coverage
Apr 22, 2026
ea207ae
docs: add instructions for mcp server connection
Apr 22, 2026
3a0f7df
feat: update dependencies and related files
Apr 22, 2026
676eb72
fix: update fastmcp dependency for release 3
Apr 22, 2026
a2294de
docs: add uvx use for client config
Apr 22, 2026
2fae6b8
docs: add missing docstring for mcp server state class init func
Apr 22, 2026
588c2c0
feat: separate tool list into comprehensible categories and imlement …
Apr 22, 2026
7c3490a
fix: resolve prek errors on new updates
Apr 22, 2026
875d2a5
refactor: add mcp-server-plexosdb folder for separate installation
Apr 22, 2026
3234023
refactor: update mcp server logic to allow only single sesssions
Apr 22, 2026
dd80dcf
refactor: move mcp server logic to independent src/ folder and depend…
Apr 23, 2026
ee227e2
test: add docstring for missing tests
Apr 23, 2026
c271f44
Merge branch 'main' into ml/mcp-server
mcllerena May 22, 2026
ae42d51
Merge branch 'main' into ml/mcp-server
mcllerena Jun 8, 2026
915dd64
fix: remove all file logic for new approach replacement
mcllerena Jun 17, 2026
c8b1c8c
fix: update config files and apply formatter
mcllerena Jun 17, 2026
68db166
feat: change server name and apply specified logic
mcllerena Jun 17, 2026
f3ee679
test: add regression test for mcp server app
mcllerena Jun 17, 2026
a11b6a3
fix: resolve docstring issues and formatter
mcllerena Jun 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
# AGENTS.md

- Assume concurrent human/agent work; never revert or overwrite changes you did not author.
- This repo processes model data into SQLite; watch query/transform cost, memory churn, and fixture representativeness.
- Prefer minimal, behavior-proven changes; add regression coverage for bug fixes and use existing fixtures under `tests/fixtures` or `tests/data` when practical.
- No breadcrumbs after deleting or moving code; remove the old code/comment instead of leaving relocation notes.
- Use `uv sync --all-groups` for setup. For changed areas, run the narrow relevant check first; before broad handoff use `uv run prek run --show-diff-on-failure --color=always --all-files --hook-stage pre-push` when feasible.
- Type-check package changes with `uv run ty check --output-format github ./src/plexosdb`.
- Test package changes with `uv run pytest --cov --cov-report=xml`; benchmark-sensitive changes may need `uv run pytest benchmarks/ -k "not xlarge_300k" --benchmark-only --benchmark-json=benchmark-results.json --no-cov`.
- Build docs for user/operator-facing documentation changes with `uv run sphinx-build docs/source/ docs/_build/`.
- Assume concurrent human/agent work; never revert or overwrite changes you did
not author.
- This repo processes model data into SQLite; watch query/transform cost, memory
churn, and fixture representativeness.
- Prefer minimal, behavior-proven changes; add regression coverage for bug fixes
and use existing fixtures under `tests/fixtures` or `tests/data` when
practical.
- No breadcrumbs after deleting or moving code; remove the old code/comment
instead of leaving relocation notes.
- Use `uv sync --all-groups` for setup. For changed areas, run the narrow
relevant check first; before broad handoff use
`uv run prek run --show-diff-on-failure --color=always --all-files --hook-stage pre-push`
when feasible.
- Type-check package changes with
`uv run ty check --output-format github ./src/plexosdb`.
- Test package changes with `uv run pytest --cov --cov-report=xml`;
benchmark-sensitive changes may need
`uv run pytest benchmarks/ -k "not xlarge_300k" --benchmark-only --benchmark-json=benchmark-results.json --no-cov`.
- Build docs for user/operator-facing documentation changes with
`uv run sphinx-build docs/source/ docs/_build/`.
55 changes: 39 additions & 16 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,61 @@ All notable changes to this project will be documented in this file.

## [1.3.4](https://github.com/NatLabRockies/plexosdb/compare/v1.3.3...v1.3.4) (2026-03-27)


### 🧩 CI

* use release/v1 tag for pypa/gh-action-pypi-publish ([#107](https://github.com/NatLabRockies/plexosdb/issues/107)) ([c4e58b8](https://github.com/NatLabRockies/plexosdb/commit/c4e58b8dc062f3302216b3caa7c9c6c1cc423c86))

- use release/v1 tag for pypa/gh-action-pypi-publish
([#107](https://github.com/NatLabRockies/plexosdb/issues/107))
([c4e58b8](https://github.com/NatLabRockies/plexosdb/commit/c4e58b8dc062f3302216b3caa7c9c6c1cc423c86))

### 📦 Build

* **deps:** bump actions/cache from 5.0.3 to 5.0.4 ([#115](https://github.com/NatLabRockies/plexosdb/issues/115)) ([1ff162a](https://github.com/NatLabRockies/plexosdb/commit/1ff162afe66dfe3bcad7d0dbb0a534b4a9d3374a))
* **deps:** bump astral-sh/setup-uv from 7.5.0 to 7.6.0 ([#117](https://github.com/NatLabRockies/plexosdb/issues/117)) ([13fb3cf](https://github.com/NatLabRockies/plexosdb/commit/13fb3cfb4c7a2affd7df504a2e152c9a2b0c1295))
* **deps:** bump astral-sh/setup-uv from b75dde52aef63a238519e7aecbbe79a4a52e4315 to e06108dd0aef18192324c70427afc47652e63a82 ([#114](https://github.com/NatLabRockies/plexosdb/issues/114)) ([96f3975](https://github.com/NatLabRockies/plexosdb/commit/96f397540b06e68e45075a5d700d2b0a91ebe112))
* **deps:** bump codecov/codecov-action from 5.5.2 to 5.5.3 ([#116](https://github.com/NatLabRockies/plexosdb/issues/116)) ([c86c8e2](https://github.com/NatLabRockies/plexosdb/commit/c86c8e254a85909043c8a7b25a10ff7d169d1e02))
* **deps:** bump googleapis/release-please-action from c3fc4de07084f75a2b61a5b933069bda6edf3d5c to 16a9c90856f42705d54a6fda1823352bdc62cf38 ([#112](https://github.com/NatLabRockies/plexosdb/issues/112)) ([4150d56](https://github.com/NatLabRockies/plexosdb/commit/4150d56065f41cf916912daf9cda39281cf4e3df))
* **deps:** bump peaceiris/actions-gh-pages from e9c66a37f080288a11235e32cbe2dc5fb3a679cc to 4f9cc6602d3f66b9c108549d475ec49e8ef4d45e ([#113](https://github.com/NatLabRockies/plexosdb/issues/113)) ([c697f1d](https://github.com/NatLabRockies/plexosdb/commit/c697f1d7642dac4c16cd5ea9e11e327d684ff548))
- **deps:** bump actions/cache from 5.0.3 to 5.0.4
([#115](https://github.com/NatLabRockies/plexosdb/issues/115))
([1ff162a](https://github.com/NatLabRockies/plexosdb/commit/1ff162afe66dfe3bcad7d0dbb0a534b4a9d3374a))
- **deps:** bump astral-sh/setup-uv from 7.5.0 to 7.6.0
([#117](https://github.com/NatLabRockies/plexosdb/issues/117))
([13fb3cf](https://github.com/NatLabRockies/plexosdb/commit/13fb3cfb4c7a2affd7df504a2e152c9a2b0c1295))
- **deps:** bump astral-sh/setup-uv from
b75dde52aef63a238519e7aecbbe79a4a52e4315 to
e06108dd0aef18192324c70427afc47652e63a82
([#114](https://github.com/NatLabRockies/plexosdb/issues/114))
([96f3975](https://github.com/NatLabRockies/plexosdb/commit/96f397540b06e68e45075a5d700d2b0a91ebe112))
- **deps:** bump codecov/codecov-action from 5.5.2 to 5.5.3
([#116](https://github.com/NatLabRockies/plexosdb/issues/116))
([c86c8e2](https://github.com/NatLabRockies/plexosdb/commit/c86c8e254a85909043c8a7b25a10ff7d169d1e02))
- **deps:** bump googleapis/release-please-action from
c3fc4de07084f75a2b61a5b933069bda6edf3d5c to
16a9c90856f42705d54a6fda1823352bdc62cf38
([#112](https://github.com/NatLabRockies/plexosdb/issues/112))
([4150d56](https://github.com/NatLabRockies/plexosdb/commit/4150d56065f41cf916912daf9cda39281cf4e3df))
- **deps:** bump peaceiris/actions-gh-pages from
e9c66a37f080288a11235e32cbe2dc5fb3a679cc to
4f9cc6602d3f66b9c108549d475ec49e8ef4d45e
([#113](https://github.com/NatLabRockies/plexosdb/issues/113))
([c697f1d](https://github.com/NatLabRockies/plexosdb/commit/c697f1d7642dac4c16cd5ea9e11e327d684ff548))

## [1.3.3](https://github.com/NatLabRockies/plexosdb/compare/v1.3.2...v1.3.3) (2026-03-16)


### 🐛 Bug Fixes

* **ci:** harden all workflows per zizmor audit ([#105](https://github.com/NatLabRockies/plexosdb/issues/105)) ([67ca845](https://github.com/NatLabRockies/plexosdb/commit/67ca84584d1e66410dc66b014a9b710a24b00b95))

- **ci:** harden all workflows per zizmor audit
([#105](https://github.com/NatLabRockies/plexosdb/issues/105))
([67ca845](https://github.com/NatLabRockies/plexosdb/commit/67ca84584d1e66410dc66b014a9b710a24b00b95))

### ⚡ Performance

* Improving performance of adding memberships from records ([#104](https://github.com/NatLabRockies/plexosdb/issues/104)) ([1ea4a39](https://github.com/NatLabRockies/plexosdb/commit/1ea4a39612a1bef1a0f290eaeb40441874a2b8f0))

- Improving performance of adding memberships from records
([#104](https://github.com/NatLabRockies/plexosdb/issues/104))
([1ea4a39](https://github.com/NatLabRockies/plexosdb/commit/1ea4a39612a1bef1a0f290eaeb40441874a2b8f0))

### 📦 Build

* **deps:** bump actions/download-artifact from 7 to 8 ([#101](https://github.com/NatLabRockies/plexosdb/issues/101)) ([0e572a0](https://github.com/NatLabRockies/plexosdb/commit/0e572a07a930f6e25f196e98fc879f65f7dd9daa))
* **deps:** bump actions/upload-artifact from 6 to 7 ([#102](https://github.com/NatLabRockies/plexosdb/issues/102)) ([22b8374](https://github.com/NatLabRockies/plexosdb/commit/22b8374aa7ed9d29eb36258a6a5ad16feb2e21c5))
- **deps:** bump actions/download-artifact from 7 to 8
([#101](https://github.com/NatLabRockies/plexosdb/issues/101))
([0e572a0](https://github.com/NatLabRockies/plexosdb/commit/0e572a07a930f6e25f196e98fc879f65f7dd9daa))
- **deps:** bump actions/upload-artifact from 6 to 7
([#102](https://github.com/NatLabRockies/plexosdb/issues/102))
([22b8374](https://github.com/NatLabRockies/plexosdb/commit/22b8374aa7ed9d29eb36258a6a5ad16feb2e21c5))

## [1.3.2](https://github.com/NatLabRockies/plexosdb/compare/v1.3.1...v1.3.2) (2026-02-12)

Expand Down
1 change: 1 addition & 0 deletions docs/source/howtos/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ manage_relationships
copy_objects
bulk_operations
remove_non_ascii
mcp_server
```
196 changes: 196 additions & 0 deletions docs/source/howtos/mcp_server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Use plexosdb as an MCP Server

This guide shows how to run the PlexosDB MCP server and verify it is working.

## What the server provides

The server exposes a curated set of **29 tools**, grouped in categories similar
to toolsets:

- Session: `health`, `create_empty_session`, `open_xml_session`, `close_session`
- Discovery: `list_objects_by_class`, `list_object_memberships`,
`list_child_objects`, `list_parent_objects`, `get_object_properties`,
`iterate_properties`, `list_classes`, `list_collections`, `list_scenarios`,
`list_models`, `list_scenarios_by_model`, `list_valid_properties`,
`list_reports`, `list_units`, `query_readonly`
- Edit: `add_object`, `add_membership`, `add_property`, `add_scenario`,
`update_object`, `delete_object`, `delete_property`
- Export: `save_xml`, `to_csv`
- Admin: `get_server_config`

Not every `PlexosDB` method in `db.py` is exposed as an MCP tool. Expose methods
in curated batches so the public MCP interface remains stable and easy to
support.

## 1) Install dependencies

Install the package you need:

- Core library only:

```console
uv add plexosdb
```

- MCP server package (includes MCP CLI entrypoint):

```console
uv add plexosdb-mcp
```

For local development from this repository:

```console
uv sync --all-groups
```

## 2) Start the MCP server

Happy path — run from a published package using `uvx`:

```console
uvx plexosdb-mcp
```

Safe path — read-only mode (recommended for untrusted prompts/hosts):

```console
uvx plexosdb-mcp --read-only
```

Smoke checks — verify the server is reachable without starting the MCP daemon:

```console
uvx plexosdb-mcp health
uvx plexosdb-mcp --version
uvx plexosdb-mcp --help
```

You can also set read-only mode via environment variable:

```console
PLEXOSDB_MCP_READ_ONLY=1 uvx plexosdb-mcp
```

Pin a specific version in production:

```console
uvx plexosdb-mcp==0.1.0
uvx plexosdb-mcp==0.1.0 --read-only
```

## 2a) Local development (repo checkout)

When working from this repository before publishing, use the nested project path
so `uv` installs `plexosdb-mcp` rather than the root `plexosdb` package:

```console
uv run --project src/plexosdb-mcp plexosdb-mcp health
uv run --project src/plexosdb-mcp plexosdb-mcp --read-only
```

If it starts successfully, it will wait for MCP client requests.

## 2b) One-shot CLI commands (no Node.js required)

All diagnostic subcommands output JSON to stdout and exit. Errors write a
structured JSON object to stderr and exit with code 1. This makes them safe to
use in pipelines and agent scripts.

| Command | Output |
| --------------------------- | ---------------------------------------------------------------------- |
| `plexosdb-mcp health` | `{"ok": true, "active_sessions": 0, "mode": "cli"}` |
| `plexosdb-mcp version` | `{"ok": true, "version": "…", "plexosdb_version": "…", "python": "…"}` |
| `plexosdb-mcp doctor` | `{"ok": true, "checks": [{…}, …]}` — exits 1 if any check fails |
| `plexosdb-mcp capabilities` | `{"ok": true, "tools": {…}, "subcommands": […]}` |

All data-bearing commands accept `--json` for explicit machine-readable output:

```console
uvx plexosdb-mcp health --json
uvx plexosdb-mcp version --json
uvx plexosdb-mcp doctor --json
uvx plexosdb-mcp capabilities --json
```

**CLI contract:**

- Data goes to **stdout** as compact JSON.
- Diagnostic messages (TTY warnings) go to **stderr**.
- Failures emit `{"ok": false, "error": "…"}` to **stderr** and exit with code
**1**.
- Usage errors (bad flags) exit with code **2** (argparse default).
- `plexosdb-mcp --version` prints the version string and exits 0.

`doctor` is the recommended pre-flight check for agents before opening a
session:

```console
uvx plexosdb-mcp doctor --json && echo "ready"
```

## 3) Interact with the server and verify tools

A simple way to test is with the MCP Inspector:

```console
npx @modelcontextprotocol/inspector uvx plexosdb-mcp
```

`npx` is only required for Inspector UI testing. It is not required for
production use of `plexosdb-mcp` itself.

In the Inspector UI:

1. Connect to the server process.
2. Call `health` and confirm `{ "ok": true }` is returned.
3. Call `create_empty_session` and copy the returned `session_id`.
4. Call `add_object` with:
- `session_id`: `<your-session-id>`
- `class_name`: `Generator`
- `name`: `Solar_MCP_01`
5. Call `list_objects_by_class` with:
- `session_id`: `<your-session-id>`
- `class_name`: `Generator`
6. Confirm `Solar_MCP_01` appears in the response.
7. Call `close_session` and confirm `{ "closed": true }`.

## 4) Load a real XML and export a modified one

Typical sequence:

1. `open_xml_session` with `xml_path` set to your source model file.
2. `add_object` and optional `add_property` or `add_membership`.
3. `save_xml` with `output_path` set to the target file path.
4. `close_session`.

## 5) Configure an MCP client (example)

Most MCP clients support a JSON server entry with command + args. Use this
shape:

```json
{
"mcpServers": {
"plexosdb": {
"command": "uvx",
"args": ["plexosdb-mcp==0.1.0", "--read-only"]
}
}
}
```

Remove `--read-only` only when you intentionally want write/export tools
enabled.

After adding the server entry, reconnect the client and run `health`.

## Notes

- The MCP server keeps only one active session at a time.
- Calling `create_empty_session` or `open_xml_session` replaces any existing
active session and returns a new `session_id`.
- Keep the same `session_id` for all operations in one editing flow.
- Call `close_session` when done to release in-memory DB resources.
- `add_property` requires that the target property is valid for the
class/collection in the current model.
74 changes: 74 additions & 0 deletions extract_signatures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Extract and print simple Python function signatures from a source file."""

from __future__ import annotations

import ast
from pathlib import Path


def _parse_file(file_path: str | Path) -> ast.AST:
"""Parse a Python source file and return its AST."""
return ast.parse(Path(file_path).read_text())


def _format_args(node: ast.FunctionDef | ast.AsyncFunctionDef) -> list[str]:
"""Format all argument kinds from a function AST node."""
args_list: list[str] = [arg.arg for arg in node.args.posonlyargs]
if node.args.posonlyargs:
args_list.append("/")

args_list.extend(arg.arg for arg in node.args.args)

if node.args.vararg:
args_list.append(f"*{node.args.vararg.arg}")
elif node.args.kwonlyargs:
args_list.append("*")

args_list.extend(arg.arg for arg in node.args.kwonlyargs)

if node.args.kwarg:
args_list.append(f"**{node.args.kwarg.arg}")

return args_list


def extract_signatures(file_path: str | Path, methods: list[str]) -> dict[str, str]:
"""Extract signatures for selected methods from a Python source file."""
tree = _parse_file(file_path)
results: dict[str, str] = {}
wanted = set(methods)

for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name in wanted:
args = _format_args(node)
results[node.name] = f"def {node.name}({', '.join(args)})"

return results


def _print_signatures_in_order(signatures: dict[str, str], methods: list[str]) -> None:
"""Print signatures in the same order as requested methods."""
for method in methods:
signature = signatures.get(method)
if signature:
print(signature)


methods = [
"update_object",
"update_property",
"delete_property",
"delete_object",
"add_scenario",
"list_parent_objects",
"list_child_objects",
"list_object_memberships",
"iterate_properties",
"validate_database",
"backup_database",
"to_csv",
"list_models",
"list_scenarios_by_model",
]

_print_signatures_in_order(extract_signatures("src/plexosdb/db.py", methods), methods)
Loading
Loading