nextmv 1.2.2.dev0__tar.gz → 1.2.3.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/.gitignore +3 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/PKG-INFO +7 -1
- nextmv-1.2.3.dev0/nextmv/__about__.py +1 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/main.py +3 -1
- nextmv-1.2.3.dev0/nextmv/cli/mcp/__init__.py +26 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/serve.py +76 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/server.py +100 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/__init__.py +1 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/_helpers.py +87 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/acceptance.py +107 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/account.py +47 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/app.py +141 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/batch.py +107 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/community.py +45 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/ensemble.py +207 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/input_set.py +130 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/instance.py +128 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/local.py +423 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/managed_input.py +103 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/profile.py +81 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/run.py +235 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/scenario.py +370 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/secrets.py +96 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/shadow.py +145 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/sso.py +29 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/switchback.py +158 -0
- nextmv-1.2.3.dev0/nextmv/cli/mcp/tools/version.py +106 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_run.py +3 -3
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/batch_experiment.py +2 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/pyproject.toml +9 -0
- nextmv-1.2.3.dev0/tests/cli/test_mcp.py +933 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/uv.lock +597 -303
- nextmv-1.2.2.dev0/nextmv/__about__.py +0 -1
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/.python-version +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/CONTRIBUTING.md +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/LICENSE +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/README.md +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/__entrypoint__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/_serialization.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/base_model.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/acceptance/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/account/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/account/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/account/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/account/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/account/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/exists.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/push.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/app/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/batch/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/data/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/data/upload.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/ensemble/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/input_set/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/exists.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/instance/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/managed_input/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/app/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/app/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/app/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/app/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/app/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/subscription/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/subscription/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/subscription/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/subscription/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/subscription/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/version/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/version/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/version/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/version/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/marketplace/version/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/cancel.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/input.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/logs.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/run/track.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/scenario/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/secrets/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/start.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/stop.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/shadow/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/disable.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/domain/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/domain/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/enable.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/sso/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/start.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/stop.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/switchback/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/upload/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/upload/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/exists.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/cloud/version/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/community/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/community/clone.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/community/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/configuration/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/configuration/config.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/configuration/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/configuration/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/configuration/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/delete.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/register.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/registered.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/sync.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/app/update.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/create.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/get.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/input.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/list.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/logs.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/metadata.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/local/run/visuals.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/manifest/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/manifest/init.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/manifest/validate.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/message.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/options.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cli/version.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/acceptance_test.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/account.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_acceptance.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_batch_scenario.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_ensemble.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_input_set.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_instance.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_managed_input.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_secrets.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_shadow.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_switchback.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_utils.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/application/_version.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/assets.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/client.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/community.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/ensemble.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/input_set.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/instance.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/integration.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/marketplace.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/package.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/scenario.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/secrets.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/shadow.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/sso.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/switchback.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/url.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/cloud/version.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/content_format.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/.gitignore +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/README.md +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/input.json +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/main.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/requirements.txt +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/src/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/default_app/src/visuals.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/deprecated.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/input.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/application.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/executor.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/geojson_handler.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/local.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/plotly_handler.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/registry.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/local/runner.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/logger.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/manifest.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/model.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/options.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/output.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/polling.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/run.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/safe.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/status.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/binary_json_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/binary_multi-file_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/go_json_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/go_multi-file_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/java_json_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/java_multi-file_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/python_json_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/nextmv/templates/python_multi-file_app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cli/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cli/test_configuration.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cli/test_main.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cli/test_version.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/app.yaml +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/test_client.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/test_instance.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/test_package.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/cloud/test_scenario.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/integration/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/integration/cloud/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/integration/cloud/test_integration_cloud.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/integration/cloud/test_integration_marketplace.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/local/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/local/test_application.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/local/test_executor.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/local/test_registry.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/local/test_runner.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options1.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options2.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options3.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options4.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options5.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options6.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/scripts/options7.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_base_model.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_entrypoint/__init__.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_entrypoint/test_entrypoint.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_input.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_inputs/test_data.csv +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_inputs/test_data.json +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_inputs/test_data.txt +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_logger.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_manifest.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_model.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_options.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_output.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_polling.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_run.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_safe.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_serialization.py +0 -0
- {nextmv-1.2.2.dev0 → nextmv-1.2.3.dev0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextmv
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3.dev0
|
|
4
4
|
Summary: The all-purpose Python SDK for Nextmv
|
|
5
5
|
Project-URL: Homepage, https://www.nextmv.io
|
|
6
6
|
Project-URL: Documentation, https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
|
|
@@ -227,6 +227,12 @@ Requires-Dist: questionary>=2.1.1
|
|
|
227
227
|
Requires-Dist: requests>=2.31.0
|
|
228
228
|
Requires-Dist: typer>=0.20.1
|
|
229
229
|
Requires-Dist: urllib3>=2.1.0
|
|
230
|
+
Provides-Extra: all
|
|
231
|
+
Requires-Dist: folium>=0.20.0; extra == 'all'
|
|
232
|
+
Requires-Dist: mcp[cli]>=1.0; extra == 'all'
|
|
233
|
+
Requires-Dist: plotly>=6.0.1; extra == 'all'
|
|
234
|
+
Provides-Extra: mcp
|
|
235
|
+
Requires-Dist: mcp[cli]>=1.0; extra == 'mcp'
|
|
230
236
|
Provides-Extra: notebook
|
|
231
237
|
Requires-Dist: mlflow>=3.9.0; extra == 'notebook'
|
|
232
238
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "v1.2.3.dev0"
|
|
@@ -26,6 +26,7 @@ from nextmv.cli.configuration import app as configuration_app
|
|
|
26
26
|
from nextmv.cli.configuration.config import CONFIG_DIR, GO_CLI_PATH, load_config
|
|
27
27
|
from nextmv.cli.local import app as local_app
|
|
28
28
|
from nextmv.cli.manifest import app as manifest_app
|
|
29
|
+
from nextmv.cli.mcp import app as mcp_app
|
|
29
30
|
from nextmv.cli.message import confirmation, error, info, success, warning
|
|
30
31
|
from nextmv.cli.version import app as version_app
|
|
31
32
|
from nextmv.cli.version import version_callback
|
|
@@ -51,6 +52,7 @@ app.add_typer(community_app, name="community")
|
|
|
51
52
|
app.add_typer(configuration_app, name="configuration")
|
|
52
53
|
app.add_typer(local_app, name="local")
|
|
53
54
|
app.add_typer(manifest_app, name="manifest")
|
|
55
|
+
app.add_typer(mcp_app, name="mcp")
|
|
54
56
|
app.add_typer(version_app)
|
|
55
57
|
|
|
56
58
|
|
|
@@ -77,7 +79,7 @@ def callback(
|
|
|
77
79
|
return
|
|
78
80
|
|
|
79
81
|
# Skip checks for certain commands.
|
|
80
|
-
ignored_commands = {"configuration", "version"}
|
|
82
|
+
ignored_commands = {"configuration", "mcp", "version"}
|
|
81
83
|
if ctx.invoked_subcommand in ignored_commands:
|
|
82
84
|
return
|
|
83
85
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""MCP (Model Context Protocol) server for the Nextmv CLI."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from nextmv.cli.mcp.serve import app as serve_app
|
|
6
|
+
|
|
7
|
+
# Set up subcommand application.
|
|
8
|
+
app = typer.Typer()
|
|
9
|
+
app.add_typer(serve_app)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.callback()
|
|
13
|
+
def callback() -> None:
|
|
14
|
+
"""
|
|
15
|
+
Model Context Protocol (MCP) server for LLM integrations.
|
|
16
|
+
|
|
17
|
+
Start an MCP server so that any MCP-compatible client (Claude Code,
|
|
18
|
+
Cursor, VS Code, etc.) can interact with Nextmv Cloud through natural
|
|
19
|
+
language.
|
|
20
|
+
|
|
21
|
+
[bold][underline]Quick start[/underline][/bold]
|
|
22
|
+
|
|
23
|
+
- Register with Claude Code.
|
|
24
|
+
$ [dim]claude mcp add nextmv -- nextmv mcp serve[/dim]
|
|
25
|
+
"""
|
|
26
|
+
pass
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""MCP server command for the Nextmv CLI."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from nextmv.cli.message import error
|
|
8
|
+
|
|
9
|
+
# Set up subcommand application.
|
|
10
|
+
app = typer.Typer()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@app.command()
|
|
14
|
+
def serve(
|
|
15
|
+
port: Annotated[
|
|
16
|
+
int,
|
|
17
|
+
typer.Option(
|
|
18
|
+
"--port",
|
|
19
|
+
help="Port for the HTTP transport.",
|
|
20
|
+
metavar="PORT",
|
|
21
|
+
),
|
|
22
|
+
] = 8080,
|
|
23
|
+
transport: Annotated[
|
|
24
|
+
str,
|
|
25
|
+
typer.Option(
|
|
26
|
+
"--transport",
|
|
27
|
+
"-t",
|
|
28
|
+
help="Transport protocol. "
|
|
29
|
+
"Allowed values: [magenta]stdio[/magenta], [magenta]streamable-http[/magenta].",
|
|
30
|
+
metavar="TRANSPORT",
|
|
31
|
+
),
|
|
32
|
+
] = "stdio",
|
|
33
|
+
) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Start the Nextmv MCP server.
|
|
36
|
+
|
|
37
|
+
The MCP server exposes Nextmv Cloud functionality as tools that any
|
|
38
|
+
MCP-compatible client can use. The default transport is
|
|
39
|
+
[magenta]stdio[/magenta], which is what Claude Code, Cursor, and most
|
|
40
|
+
local clients expect.
|
|
41
|
+
|
|
42
|
+
Requires the [magenta]mcp[/magenta] optional dependency. Install with:
|
|
43
|
+
[code]pip install 'nextmv[mcp]'[/code]
|
|
44
|
+
|
|
45
|
+
[bold][underline]Examples[/underline][/bold]
|
|
46
|
+
|
|
47
|
+
- Start the MCP server with stdio transport (default).
|
|
48
|
+
$ [dim]nextmv mcp serve[/dim]
|
|
49
|
+
|
|
50
|
+
- Start the MCP server with HTTP transport on port 9090.
|
|
51
|
+
$ [dim]nextmv mcp serve --transport streamable-http --port 9090[/dim]
|
|
52
|
+
|
|
53
|
+
- Register with Claude Code.
|
|
54
|
+
$ [dim]claude mcp add nextmv -- nextmv mcp serve[/dim]
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
from nextmv.cli.mcp.server import create_server
|
|
59
|
+
except ImportError:
|
|
60
|
+
error(
|
|
61
|
+
"MCP support requires the [magenta]mcp[/magenta] package. "
|
|
62
|
+
"Install with: [code]pip install 'nextmv[mcp]'[/code]"
|
|
63
|
+
)
|
|
64
|
+
return # unreachable, error() raises
|
|
65
|
+
|
|
66
|
+
server = create_server()
|
|
67
|
+
|
|
68
|
+
if transport == "stdio":
|
|
69
|
+
server.run(transport="stdio")
|
|
70
|
+
elif transport in ("http", "streamable-http"):
|
|
71
|
+
server.run(transport="streamable-http", port=port)
|
|
72
|
+
else:
|
|
73
|
+
error(
|
|
74
|
+
f"Unknown transport [magenta]{transport}[/magenta]. "
|
|
75
|
+
"Allowed values are: [magenta]stdio[/magenta], [magenta]streamable-http[/magenta]."
|
|
76
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Nextmv MCP server definition.
|
|
2
|
+
|
|
3
|
+
This module is the public entry point for the MCP server. It delegates
|
|
4
|
+
tool registration to domain-specific submodules under ``tools/`` and
|
|
5
|
+
re-exports shared helpers so that existing imports continue to work.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from mcp.server.fastmcp import FastMCP
|
|
9
|
+
|
|
10
|
+
# Import tool registration submodules.
|
|
11
|
+
from nextmv.cli.mcp.tools import (
|
|
12
|
+
acceptance,
|
|
13
|
+
account,
|
|
14
|
+
app,
|
|
15
|
+
batch,
|
|
16
|
+
community,
|
|
17
|
+
ensemble,
|
|
18
|
+
input_set,
|
|
19
|
+
instance,
|
|
20
|
+
local,
|
|
21
|
+
managed_input,
|
|
22
|
+
profile,
|
|
23
|
+
run,
|
|
24
|
+
scenario,
|
|
25
|
+
secrets,
|
|
26
|
+
shadow,
|
|
27
|
+
sso,
|
|
28
|
+
switchback,
|
|
29
|
+
version,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Re-export helpers for backward compatibility — tests and external code
|
|
33
|
+
# may import these directly from ``nextmv.cli.mcp.server``.
|
|
34
|
+
from nextmv.cli.mcp.tools._helpers import ( # noqa: F401
|
|
35
|
+
_current_profile,
|
|
36
|
+
_get_app,
|
|
37
|
+
_get_client,
|
|
38
|
+
_get_local_app,
|
|
39
|
+
_mask_key,
|
|
40
|
+
_save_to_file,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Re-export SDK names that tests patch on this module.
|
|
44
|
+
from nextmv.cloud import list_applications # noqa: F401
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def create_server() -> FastMCP:
|
|
48
|
+
"""Create and return the Nextmv MCP server."""
|
|
49
|
+
|
|
50
|
+
mcp = FastMCP(
|
|
51
|
+
"nextmv",
|
|
52
|
+
json_response=True,
|
|
53
|
+
instructions=(
|
|
54
|
+
"Nextmv is a platform for deploying and managing decision "
|
|
55
|
+
"models (optimization, routing, scheduling, etc.). Use these "
|
|
56
|
+
"tools to interact with Nextmv Cloud apps: list apps, submit "
|
|
57
|
+
"runs, check results, manage versions/instances, run experiments, "
|
|
58
|
+
"and work with local applications.\n\n"
|
|
59
|
+
"IMPORTANT: Always use these MCP tools instead of shelling out "
|
|
60
|
+
"to the `nextmv` CLI binary. Large responses (run results, "
|
|
61
|
+
"inputs, logs) are automatically saved to local temp files to "
|
|
62
|
+
"keep the context window small — the tool will return the file "
|
|
63
|
+
"path so you can selectively read what you need. Large inputs "
|
|
64
|
+
"can be passed directly as tool parameters without concern.\n\n"
|
|
65
|
+
"PROFILES: The server supports multiple profiles from "
|
|
66
|
+
"~/.nextmv/config.yaml. Use cloud_list_profiles to see "
|
|
67
|
+
"available profiles and cloud_set_profile to switch. The "
|
|
68
|
+
"default profile is used unless changed. When the user asks "
|
|
69
|
+
"to use a specific profile (e.g. \"list apps in my dev "
|
|
70
|
+
"profile\"), call cloud_set_profile first. Always state which "
|
|
71
|
+
"profile you are using when calling cloud tools, e.g. "
|
|
72
|
+
"(profile: \"default\")."
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Cloud tools
|
|
77
|
+
profile.register(mcp)
|
|
78
|
+
app.register(mcp)
|
|
79
|
+
run.register(mcp)
|
|
80
|
+
version.register(mcp)
|
|
81
|
+
instance.register(mcp)
|
|
82
|
+
batch.register(mcp)
|
|
83
|
+
input_set.register(mcp)
|
|
84
|
+
acceptance.register(mcp)
|
|
85
|
+
scenario.register(mcp)
|
|
86
|
+
ensemble.register(mcp)
|
|
87
|
+
shadow.register(mcp)
|
|
88
|
+
switchback.register(mcp)
|
|
89
|
+
secrets.register(mcp)
|
|
90
|
+
sso.register(mcp)
|
|
91
|
+
account.register(mcp)
|
|
92
|
+
managed_input.register(mcp)
|
|
93
|
+
|
|
94
|
+
# Community tools
|
|
95
|
+
community.register(mcp)
|
|
96
|
+
|
|
97
|
+
# Local tools
|
|
98
|
+
local.register(mcp)
|
|
99
|
+
|
|
100
|
+
return mcp
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""MCP tool registration submodules, organized by domain."""
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Shared helpers for MCP tool modules."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import tempfile
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from nextmv import local
|
|
9
|
+
from nextmv.cloud import Application, Client
|
|
10
|
+
|
|
11
|
+
# Session-level profile. None means "default" (top-level config keys).
|
|
12
|
+
_current_profile: str | None = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _mask_key(key: str | None) -> str | None:
|
|
16
|
+
"""Mask an API key, keeping only the last 4 characters visible."""
|
|
17
|
+
|
|
18
|
+
if not key:
|
|
19
|
+
return None
|
|
20
|
+
if len(key) <= 4:
|
|
21
|
+
return key
|
|
22
|
+
return "X" * (len(key) - 4) + key[-4:]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _get_client(profile: str | None = None) -> Client:
|
|
26
|
+
"""Build a Nextmv Cloud client from env var or CLI config.
|
|
27
|
+
|
|
28
|
+
Checks for credentials in the following order:
|
|
29
|
+
|
|
30
|
+
1. ``NEXTMV_API_KEY`` environment variable (unless a profile is active).
|
|
31
|
+
2. CLI configuration file at ``~/.nextmv/config.yaml``.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
profile: Optional profile name override. If not provided, uses
|
|
35
|
+
the session-level ``_current_profile``.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
resolved = profile or _current_profile
|
|
39
|
+
|
|
40
|
+
api_key = os.getenv("NEXTMV_API_KEY")
|
|
41
|
+
if api_key and not resolved:
|
|
42
|
+
endpoint = os.getenv("NEXTMV_ENDPOINT", "https://api.cloud.nextmv.io")
|
|
43
|
+
if not endpoint.startswith("http"):
|
|
44
|
+
endpoint = f"https://{endpoint}"
|
|
45
|
+
return Client(api_key=api_key, url=endpoint)
|
|
46
|
+
|
|
47
|
+
# Fall back to the CLI configuration file (~/.nextmv/config.yaml).
|
|
48
|
+
try:
|
|
49
|
+
from nextmv.cli.configuration.config import build_client
|
|
50
|
+
|
|
51
|
+
# "default" means use top-level keys (profile=None in build_client).
|
|
52
|
+
p = None if resolved is None or resolved == "default" else resolved
|
|
53
|
+
return build_client(profile=p)
|
|
54
|
+
except Exception as e:
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"No Nextmv API key found. Either set the NEXTMV_API_KEY "
|
|
57
|
+
"environment variable or configure the CLI with: "
|
|
58
|
+
"nextmv configuration create"
|
|
59
|
+
) from e
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _get_app(app_id: str, profile: str | None = None) -> Application:
|
|
63
|
+
"""Build a cloud Application handle for the given ID."""
|
|
64
|
+
|
|
65
|
+
client = _get_client(profile=profile)
|
|
66
|
+
return Application(client=client, id=app_id)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _get_local_app(app_dir: str, app_id: str | None = None) -> local.Application:
|
|
70
|
+
"""Build a local Application, registering it if needed."""
|
|
71
|
+
|
|
72
|
+
app, _ = local.Application.get_or_register(app_src=app_dir, app_id=app_id)
|
|
73
|
+
return app
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _save_to_file(data: Any, prefix: str) -> str:
|
|
77
|
+
"""Serialize data to a temp JSON file and return a message with the path.
|
|
78
|
+
|
|
79
|
+
This keeps large payloads out of the MCP response (and thus out of
|
|
80
|
+
the LLM context window). The caller can selectively read the file
|
|
81
|
+
using standard file-reading tools.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
fd, path = tempfile.mkstemp(suffix=".json", prefix=f"{prefix}_")
|
|
85
|
+
with os.fdopen(fd, "w") as fh:
|
|
86
|
+
json.dump(data, fh, indent=2)
|
|
87
|
+
return f"Data saved to {path} — use file-reading tools to inspect the contents."
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""MCP tools for cloud acceptance tests."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from mcp.server.fastmcp import FastMCP
|
|
6
|
+
|
|
7
|
+
from nextmv.cli.mcp.tools import _helpers
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def register(mcp: FastMCP) -> None:
|
|
11
|
+
"""Register cloud acceptance test tools."""
|
|
12
|
+
|
|
13
|
+
@mcp.tool()
|
|
14
|
+
def cloud_list_acceptance_tests(app_id: str) -> list[dict[str, Any]]:
|
|
15
|
+
"""List acceptance tests for a Nextmv Cloud application.
|
|
16
|
+
|
|
17
|
+
Acceptance tests compare a candidate instance against a
|
|
18
|
+
baseline using defined metrics. Returns a list of test
|
|
19
|
+
summaries.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
app_id: The application ID.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
app = _helpers._get_app(app_id)
|
|
26
|
+
tests = app.list_acceptance_tests()
|
|
27
|
+
return [t.to_dict() for t in tests]
|
|
28
|
+
|
|
29
|
+
@mcp.tool()
|
|
30
|
+
def cloud_get_acceptance_test(
|
|
31
|
+
app_id: str,
|
|
32
|
+
acceptance_test_id: str,
|
|
33
|
+
) -> str:
|
|
34
|
+
"""Get details and results of an acceptance test.
|
|
35
|
+
|
|
36
|
+
Saves the full test data (including metric comparisons and
|
|
37
|
+
pass/fail results) to a local temp file. Use file-reading
|
|
38
|
+
tools to inspect the contents.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
app_id: The application ID.
|
|
42
|
+
acceptance_test_id: The acceptance test ID.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
app = _helpers._get_app(app_id)
|
|
46
|
+
test = app.acceptance_test(acceptance_test_id=acceptance_test_id)
|
|
47
|
+
return _helpers._save_to_file(test.to_dict(), prefix=f"acceptance_test_{acceptance_test_id}")
|
|
48
|
+
|
|
49
|
+
@mcp.tool()
|
|
50
|
+
def cloud_create_acceptance_test(
|
|
51
|
+
app_id: str,
|
|
52
|
+
candidate_instance_id: str,
|
|
53
|
+
baseline_instance_id: str,
|
|
54
|
+
metrics: list[dict[str, Any]],
|
|
55
|
+
acceptance_test_id: str | None = None,
|
|
56
|
+
name: str | None = None,
|
|
57
|
+
input_set_id: str | None = None,
|
|
58
|
+
description: str | None = None,
|
|
59
|
+
) -> dict[str, Any]:
|
|
60
|
+
"""Create an acceptance test comparing two instances.
|
|
61
|
+
|
|
62
|
+
An acceptance test runs both instances against the same input
|
|
63
|
+
set and compares results using the specified metrics to
|
|
64
|
+
determine whether the candidate meets acceptance criteria.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
app_id: The application ID.
|
|
68
|
+
candidate_instance_id: The candidate instance to evaluate.
|
|
69
|
+
baseline_instance_id: The baseline instance to compare
|
|
70
|
+
the candidate against.
|
|
71
|
+
metrics: List of metric definitions. Each metric is a dict
|
|
72
|
+
with keys: ``field``, ``metric_type``, ``params``,
|
|
73
|
+
``statistic``.
|
|
74
|
+
acceptance_test_id: Optional test ID. Auto-generated if
|
|
75
|
+
omitted.
|
|
76
|
+
name: Optional human-readable name.
|
|
77
|
+
input_set_id: Optional input set ID to run the test against.
|
|
78
|
+
description: Optional description.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
app = _helpers._get_app(app_id)
|
|
82
|
+
test = app.new_acceptance_test(
|
|
83
|
+
candidate_instance_id=candidate_instance_id,
|
|
84
|
+
baseline_instance_id=baseline_instance_id,
|
|
85
|
+
metrics=metrics,
|
|
86
|
+
id=acceptance_test_id,
|
|
87
|
+
name=name,
|
|
88
|
+
input_set_id=input_set_id,
|
|
89
|
+
description=description,
|
|
90
|
+
)
|
|
91
|
+
return test.to_dict()
|
|
92
|
+
|
|
93
|
+
@mcp.tool()
|
|
94
|
+
def cloud_delete_acceptance_test(
|
|
95
|
+
app_id: str,
|
|
96
|
+
acceptance_test_id: str,
|
|
97
|
+
) -> str:
|
|
98
|
+
"""Delete an acceptance test permanently.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
app_id: The application ID.
|
|
102
|
+
acceptance_test_id: The acceptance test ID to delete.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
app = _helpers._get_app(app_id)
|
|
106
|
+
app.delete_acceptance_test(acceptance_test_id=acceptance_test_id)
|
|
107
|
+
return f"Deleted acceptance test {acceptance_test_id}"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""MCP tools for cloud account management."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from mcp.server.fastmcp import FastMCP
|
|
6
|
+
|
|
7
|
+
from nextmv.cli.mcp.tools import _helpers
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def register(mcp: FastMCP) -> None:
|
|
11
|
+
"""Register cloud account tools."""
|
|
12
|
+
|
|
13
|
+
@mcp.tool()
|
|
14
|
+
def cloud_get_account(account_id: str) -> dict[str, Any]:
|
|
15
|
+
"""Get details of a Nextmv Cloud account.
|
|
16
|
+
|
|
17
|
+
Returns account information including organization name,
|
|
18
|
+
plan details, and usage limits.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
account_id: The account ID to retrieve.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from nextmv.cloud.account import Account
|
|
25
|
+
|
|
26
|
+
client = _helpers._get_client()
|
|
27
|
+
account = Account.get(client=client, account_id=account_id)
|
|
28
|
+
return account.to_dict()
|
|
29
|
+
|
|
30
|
+
@mcp.tool()
|
|
31
|
+
def cloud_get_queue(account_id: str) -> dict[str, Any]:
|
|
32
|
+
"""Get the run queue for a Nextmv Cloud account.
|
|
33
|
+
|
|
34
|
+
Returns information about currently queued and running runs
|
|
35
|
+
across all applications in the account, including queue
|
|
36
|
+
depth and concurrency usage.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
account_id: The account ID.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from nextmv.cloud.account import Account
|
|
43
|
+
|
|
44
|
+
client = _helpers._get_client()
|
|
45
|
+
account = Account.get(client=client, account_id=account_id)
|
|
46
|
+
queue = account.queue()
|
|
47
|
+
return queue.to_dict()
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""MCP tools for cloud application management."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from mcp.server.fastmcp import FastMCP
|
|
6
|
+
|
|
7
|
+
from nextmv.cli.mcp.tools import _helpers
|
|
8
|
+
from nextmv.cloud import Application, list_applications
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def register(mcp: FastMCP) -> None:
|
|
12
|
+
"""Register cloud application management tools."""
|
|
13
|
+
|
|
14
|
+
@mcp.tool()
|
|
15
|
+
def cloud_list_apps() -> list[dict[str, Any]]:
|
|
16
|
+
"""List all Nextmv Cloud applications in the current account.
|
|
17
|
+
|
|
18
|
+
Returns a list of application dictionaries containing each
|
|
19
|
+
application's ID, name, description, and default instance.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
client = _helpers._get_client()
|
|
23
|
+
apps = list_applications(client)
|
|
24
|
+
return [a.to_dict() for a in apps]
|
|
25
|
+
|
|
26
|
+
@mcp.tool()
|
|
27
|
+
def cloud_get_app(app_id: str) -> dict[str, Any]:
|
|
28
|
+
"""Get details of a specific Nextmv Cloud application.
|
|
29
|
+
|
|
30
|
+
Returns the full application object including its name,
|
|
31
|
+
description, default instance, and creation timestamp.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
app_id: The application ID (e.g., ``"my-routing-app"``).
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
client = _helpers._get_client()
|
|
38
|
+
app = Application.get(client=client, id=app_id)
|
|
39
|
+
return app.to_dict()
|
|
40
|
+
|
|
41
|
+
@mcp.tool()
|
|
42
|
+
def cloud_create_app(
|
|
43
|
+
name: str,
|
|
44
|
+
app_id: str | None = None,
|
|
45
|
+
description: str | None = None,
|
|
46
|
+
) -> dict[str, Any]:
|
|
47
|
+
"""Create a new Nextmv Cloud application.
|
|
48
|
+
|
|
49
|
+
Returns the created application object. A version and default
|
|
50
|
+
instance are automatically provisioned.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
name: A human-readable name for the application.
|
|
54
|
+
app_id: Optional URL-friendly ID. Auto-generated from
|
|
55
|
+
the name if omitted.
|
|
56
|
+
description: Optional description of what the application does.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
client = _helpers._get_client()
|
|
60
|
+
app = Application.new(
|
|
61
|
+
client=client,
|
|
62
|
+
name=name,
|
|
63
|
+
id=app_id,
|
|
64
|
+
description=description,
|
|
65
|
+
)
|
|
66
|
+
return app.to_dict()
|
|
67
|
+
|
|
68
|
+
@mcp.tool()
|
|
69
|
+
def cloud_delete_app(app_id: str) -> str:
|
|
70
|
+
"""Delete a Nextmv Cloud application permanently.
|
|
71
|
+
|
|
72
|
+
This action cannot be undone. All versions, instances, and
|
|
73
|
+
run history associated with the application will be removed.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
app_id: The application ID to delete.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
app = _helpers._get_app(app_id)
|
|
80
|
+
app.delete()
|
|
81
|
+
return f"Deleted application {app_id}"
|
|
82
|
+
|
|
83
|
+
@mcp.tool()
|
|
84
|
+
def cloud_app_exists(app_id: str) -> bool:
|
|
85
|
+
"""Check whether a Nextmv Cloud application exists.
|
|
86
|
+
|
|
87
|
+
Returns True if an application with the given ID exists in
|
|
88
|
+
the current account, False otherwise.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
app_id: The application ID to check.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
client = _helpers._get_client()
|
|
95
|
+
return Application.exists(client=client, id=app_id)
|
|
96
|
+
|
|
97
|
+
@mcp.tool()
|
|
98
|
+
def cloud_update_app(
|
|
99
|
+
app_id: str,
|
|
100
|
+
name: str | None = None,
|
|
101
|
+
description: str | None = None,
|
|
102
|
+
default_instance_id: str | None = None,
|
|
103
|
+
) -> dict[str, Any]:
|
|
104
|
+
"""Update attributes of a Nextmv Cloud application.
|
|
105
|
+
|
|
106
|
+
Only the provided fields are updated; omitted fields remain
|
|
107
|
+
unchanged. Returns the updated application object.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
app_id: The application ID to update.
|
|
111
|
+
name: New human-readable name for the application.
|
|
112
|
+
description: New description.
|
|
113
|
+
default_instance_id: New default instance ID used when no
|
|
114
|
+
instance is specified at run time.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
app = _helpers._get_app(app_id)
|
|
118
|
+
updated = app.update(
|
|
119
|
+
name=name,
|
|
120
|
+
description=description,
|
|
121
|
+
default_instance_id=default_instance_id,
|
|
122
|
+
)
|
|
123
|
+
return updated.to_dict()
|
|
124
|
+
|
|
125
|
+
@mcp.tool()
|
|
126
|
+
def cloud_push_app(app_id: str, app_dir: str) -> str:
|
|
127
|
+
"""Push local application code to a Nextmv Cloud application.
|
|
128
|
+
|
|
129
|
+
Uploads the contents of a local directory as a new version of
|
|
130
|
+
the application. The directory must contain an ``app.yaml``
|
|
131
|
+
manifest.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
app_id: The application ID to push to.
|
|
135
|
+
app_dir: Absolute path to the local directory containing the
|
|
136
|
+
application code and ``app.yaml`` manifest.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
app = _helpers._get_app(app_id)
|
|
140
|
+
app.push(app_dir=app_dir)
|
|
141
|
+
return f"Pushed {app_dir} to application {app_id}"
|