workspaces-euc-mcp-server 0.1.8__tar.gz → 0.1.9__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.
Files changed (54) hide show
  1. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/CHANGELOG.md +9 -0
  2. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/DESIGN.md +6 -4
  3. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/PKG-INFO +10 -9
  4. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/README.md +9 -8
  5. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/pyproject.toml +1 -1
  6. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_sso.py +14 -0
  7. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/__init__.py +1 -1
  8. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/server.py +18 -12
  9. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/_common.py +1 -1
  10. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.dockerignore +0 -0
  11. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.github/workflows/ci.yml +0 -0
  12. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.github/workflows/docker-publish.yml +0 -0
  13. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.github/workflows/publish.yml +0 -0
  14. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.gitignore +0 -0
  15. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/.pre-commit-config.yaml +0 -0
  16. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/Dockerfile +0 -0
  17. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/LICENSE +0 -0
  18. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/iam/README.md +0 -0
  19. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/iam/tier0-diagnostics.json +0 -0
  20. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/iam/tier1-cost.json +0 -0
  21. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/iam/tier2-lifecycle.json +0 -0
  22. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/iam/tier3-destructive.json +0 -0
  23. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/scripts/smoke_readonly.py +0 -0
  24. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/__init__.py +0 -0
  25. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_clients.py +0 -0
  26. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_cost.py +0 -0
  27. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_destructive.py +0 -0
  28. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_diagnostics.py +0 -0
  29. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_governance.py +0 -0
  30. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_images.py +0 -0
  31. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_inventory.py +0 -0
  32. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_lifecycle.py +0 -0
  33. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_naming.py +0 -0
  34. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_no_embedded_secrets.py +0 -0
  35. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_performance.py +0 -0
  36. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_pricing.py +0 -0
  37. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_reporting.py +0 -0
  38. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/tests/test_secure_browser.py +0 -0
  39. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/clients.py +0 -0
  40. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/consts.py +0 -0
  41. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/models.py +0 -0
  42. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/sso.py +0 -0
  43. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/__init__.py +0 -0
  44. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/cost.py +0 -0
  45. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/destructive.py +0 -0
  46. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/diagnostics.py +0 -0
  47. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/governance.py +0 -0
  48. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/images.py +0 -0
  49. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/inventory.py +0 -0
  50. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/lifecycle.py +0 -0
  51. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/performance.py +0 -0
  52. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/pricing.py +0 -0
  53. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/reporting.py +0 -0
  54. {workspaces_euc_mcp_server-0.1.8 → workspaces_euc_mcp_server-0.1.9}/workspaces_euc_mcp_server/tools/secure_browser.py +0 -0
@@ -5,6 +5,15 @@ All notable changes to this project are documented here. The format is based on
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.1.9] - 2026-06-03
9
+
10
+ ### Changed
11
+ - **SSO auto-login is now ON by default** (previously opt-in via `--sso-auto-login`). When an AWS
12
+ call fails with an expired SSO token, the server automatically runs `aws sso login` (opens the
13
+ browser) and reports in the result that the token expired and that sign-in was launched — no flag
14
+ needed. Disable with **`--no-sso-auto-login`** or `WORKSPACES_EUC_SSO_AUTO_LOGIN=0` (e.g.
15
+ headless/CI). The browser approval is still required and credentials are still never stored.
16
+
8
17
  ## [0.1.8] - 2026-06-03
9
18
 
10
19
  ### Added
@@ -94,10 +94,12 @@
94
94
  - `--enable-writes`: registers Phase-2 lifecycle tools (still dry-run/confirm gated).
95
95
  - `--enable-destructive`: separately gates terminate/rebuild/restore.
96
96
  - `--max-bulk-targets N`: blast-radius cap for any bulk mutation.
97
- - `--sso-auto-login` (default **off**): on an expired-SSO-token error, launch `aws sso login`
98
- (opens the browser) so the user needn't use a terminal. Opt-in; never stores credentials — it
99
- only invokes the AWS CLI, which writes the standard token cache. Debounced so a burst of failing
100
- calls opens the browser once.
97
+ - `--sso-auto-login` / `--no-sso-auto-login` (default **on**): on an expired-SSO-token error,
98
+ launch `aws sso login` (opens the browser) so the user needn't use a terminal, and report in the
99
+ result that the token expired and sign-in was launched. Never stores credentials it only
100
+ invokes the AWS CLI, which writes the standard token cache. Debounced so a burst of failing calls
101
+ opens the browser once. Disable with `--no-sso-auto-login` / `WORKSPACES_EUC_SSO_AUTO_LOGIN=0`
102
+ for headless/CI.
101
103
  - `AWS_REGION` / `AWS_PROFILE`: standard.
102
104
 
103
105
  ## 5. Tool inventory
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workspaces-euc-mcp-server
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: MCP server for administering the Amazon WorkSpaces family of End User Computing services (Personal, Pools, Applications, Secure Browser, Core).
5
5
  Project-URL: Homepage, https://github.com/bengroeneveldsg/aws-workspaces-euc-mcp
6
6
  Project-URL: Repository, https://github.com/bengroeneveldsg/aws-workspaces-euc-mcp
@@ -264,13 +264,14 @@ If calls fail with an expired-token / `UnauthorizedException` error, your sessio
264
264
  re-authenticate (for SSO, `aws sso login --profile <name>`) and retry. Nothing in the MCP config
265
265
  changes.
266
266
 
267
- > **Tip — auto re-login (no terminal):** launch the server with **`--sso-auto-login`** (or set
268
- > `WORKSPACES_EUC_SSO_AUTO_LOGIN=1`). When an AWS call then fails with an expired SSO token, the
269
- > server **automatically runs `aws sso login` for you** opening your browser to the approval
270
- > screen — so you just click *Allow* and re-ask, without ever opening a terminal. Off by default;
271
- > the browser approval itself is still required (inherent to SSO), and the server still never
272
- > stores credentials (it just invokes the AWS CLI). Note: signing into the AWS **Console** does
273
- > *not* refresh the CLI/SSO token — only `aws sso login` does.
267
+ > **Auto re-login (no terminal) — on by default:** when an AWS call fails with an expired SSO
268
+ > token, the server **automatically runs `aws sso login` for you** opening your browser to the
269
+ > approval screen and tells you in chat that the token expired and that sign-in was launched. You
270
+ > just click *Allow* and re-ask, without ever opening a terminal. The browser approval itself is
271
+ > still required (inherent to SSO), and the server still never stores credentials (it just invokes
272
+ > the AWS CLI). Disable with **`--no-sso-auto-login`** (or `WORKSPACES_EUC_SSO_AUTO_LOGIN=0`) for
273
+ > headless/CI use. Note: signing into the AWS **Console** does *not* refresh the CLI/SSO token —
274
+ > only `aws sso login` does.
274
275
 
275
276
  ## Enabling write / destructive tools — the safety gates
276
277
 
@@ -367,7 +368,7 @@ workspaces-euc-mcp-server --enable-writes --enable-destructive --max-bulk-target
367
368
  | `--enable-writes` | off | Register Phase 2 lifecycle (write) tools. |
368
369
  | `--enable-destructive` | off | Allow terminate/rebuild/restore (requires `--enable-writes`). |
369
370
  | `--max-bulk-targets` | 25 | Blast-radius cap for bulk mutations (Phase 2). |
370
- | `--sso-auto-login` | off | On an expired SSO token, auto-launch `aws sso login` (opens your browser) instead of requiring a manual terminal command. Also via `WORKSPACES_EUC_SSO_AUTO_LOGIN=1`. |
371
+ | `--sso-auto-login` / `--no-sso-auto-login` | **on** | On an expired SSO token, auto-launch `aws sso login` (opens your browser) instead of requiring a manual terminal command. **On by default**; disable with `--no-sso-auto-login` or `WORKSPACES_EUC_SSO_AUTO_LOGIN=0` (e.g. headless/CI). |
371
372
 
372
373
  The server starts **read-only**; mutating tools require both the launch flag **and** the matching
373
374
  IAM tier.
@@ -234,13 +234,14 @@ If calls fail with an expired-token / `UnauthorizedException` error, your sessio
234
234
  re-authenticate (for SSO, `aws sso login --profile <name>`) and retry. Nothing in the MCP config
235
235
  changes.
236
236
 
237
- > **Tip — auto re-login (no terminal):** launch the server with **`--sso-auto-login`** (or set
238
- > `WORKSPACES_EUC_SSO_AUTO_LOGIN=1`). When an AWS call then fails with an expired SSO token, the
239
- > server **automatically runs `aws sso login` for you** opening your browser to the approval
240
- > screen — so you just click *Allow* and re-ask, without ever opening a terminal. Off by default;
241
- > the browser approval itself is still required (inherent to SSO), and the server still never
242
- > stores credentials (it just invokes the AWS CLI). Note: signing into the AWS **Console** does
243
- > *not* refresh the CLI/SSO token — only `aws sso login` does.
237
+ > **Auto re-login (no terminal) — on by default:** when an AWS call fails with an expired SSO
238
+ > token, the server **automatically runs `aws sso login` for you** opening your browser to the
239
+ > approval screen and tells you in chat that the token expired and that sign-in was launched. You
240
+ > just click *Allow* and re-ask, without ever opening a terminal. The browser approval itself is
241
+ > still required (inherent to SSO), and the server still never stores credentials (it just invokes
242
+ > the AWS CLI). Disable with **`--no-sso-auto-login`** (or `WORKSPACES_EUC_SSO_AUTO_LOGIN=0`) for
243
+ > headless/CI use. Note: signing into the AWS **Console** does *not* refresh the CLI/SSO token —
244
+ > only `aws sso login` does.
244
245
 
245
246
  ## Enabling write / destructive tools — the safety gates
246
247
 
@@ -337,7 +338,7 @@ workspaces-euc-mcp-server --enable-writes --enable-destructive --max-bulk-target
337
338
  | `--enable-writes` | off | Register Phase 2 lifecycle (write) tools. |
338
339
  | `--enable-destructive` | off | Allow terminate/rebuild/restore (requires `--enable-writes`). |
339
340
  | `--max-bulk-targets` | 25 | Blast-radius cap for bulk mutations (Phase 2). |
340
- | `--sso-auto-login` | off | On an expired SSO token, auto-launch `aws sso login` (opens your browser) instead of requiring a manual terminal command. Also via `WORKSPACES_EUC_SSO_AUTO_LOGIN=1`. |
341
+ | `--sso-auto-login` / `--no-sso-auto-login` | **on** | On an expired SSO token, auto-launch `aws sso login` (opens your browser) instead of requiring a manual terminal command. **On by default**; disable with `--no-sso-auto-login` or `WORKSPACES_EUC_SSO_AUTO_LOGIN=0` (e.g. headless/CI). |
341
342
 
342
343
  The server starts **read-only**; mutating tools require both the launch flag **and** the matching
343
344
  IAM tier.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "workspaces-euc-mcp-server"
3
- version = "0.1.8"
3
+ version = "0.1.9"
4
4
  description = "MCP server for administering the Amazon WorkSpaces family of End User Computing services (Personal, Pools, Applications, Secure Browser, Core)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -92,6 +92,20 @@ def test_try_call_hint_when_auto_login_disabled():
92
92
  assert "Console does NOT refresh" in errors[0].message
93
93
 
94
94
 
95
+ def test_create_server_enables_sso_auto_login_by_default():
96
+ from workspaces_euc_mcp_server.server import create_server
97
+
98
+ try:
99
+ create_server(region="us-east-1")
100
+ assert _common._SSO_HANDLER is not None
101
+ assert _common._SSO_HANDLER.enabled is True
102
+ # Opt-out still works.
103
+ create_server(region="us-east-1", sso_auto_login=False)
104
+ assert _common._SSO_HANDLER is None
105
+ finally:
106
+ _common.register_sso_handler(None)
107
+
108
+
95
109
  class _FakeTokenError(BotoCoreError):
96
110
  """A BotoCoreError subclass whose str() is a controllable token-error message."""
97
111
 
@@ -3,4 +3,4 @@
3
3
  # A copy of the License is located at http://www.apache.org/licenses/LICENSE-2.0
4
4
  """MCP server for administering the Amazon WorkSpaces End User Computing portfolio."""
5
5
 
6
- __version__ = "0.1.8"
6
+ __version__ = "0.1.9"
@@ -39,20 +39,23 @@ def create_server(
39
39
  enable_writes: bool = False,
40
40
  enable_destructive: bool = False,
41
41
  max_bulk_targets: int = consts.DEFAULT_MAX_BULK_TARGETS,
42
- sso_auto_login: bool = False,
42
+ sso_auto_login: bool = True,
43
43
  ) -> FastMCP:
44
44
  """Build the FastMCP server, registering tools according to the safety flags."""
45
45
  factory = ClientFactory(
46
46
  region=region, profile=profile, role_arn=role_arn, external_id=external_id
47
47
  )
48
48
 
49
- # Opt-in: when an AWS call fails with an expired SSO token, auto-launch `aws sso login`
50
- # (opens the browser) so the user never has to use a terminal. No-op unless enabled.
49
+ # On by default: when an AWS call fails with an expired SSO token, auto-launch `aws sso login`
50
+ # (opens the browser) so the user never has to use a terminal. Disable for headless/CI.
51
51
  _common.register_sso_handler(
52
52
  SsoAutoLogin(profile=profile, enabled=sso_auto_login) if sso_auto_login else None
53
53
  )
54
- if sso_auto_login:
55
- logger.info("SSO auto-login enabled: expired tokens will trigger `aws sso login`.")
54
+ logger.info(
55
+ "SSO auto-login {}: expired tokens {} trigger `aws sso login`.",
56
+ "enabled" if sso_auto_login else "disabled",
57
+ "will" if sso_auto_login else "will NOT",
58
+ )
56
59
 
57
60
  mcp = FastMCP(consts.SERVER_NAME, instructions=consts.SERVER_INSTRUCTIONS)
58
61
 
@@ -123,19 +126,22 @@ def main() -> None:
123
126
  )
124
127
  parser.add_argument(
125
128
  "--sso-auto-login",
126
- action="store_true",
127
- help="When an AWS call fails with an expired SSO token, auto-launch `aws sso login` "
128
- "(opens your browser) instead of requiring a manual terminal command. Off by default; "
129
- "can also be enabled with WORKSPACES_EUC_SSO_AUTO_LOGIN=1.",
129
+ action=argparse.BooleanOptionalAction,
130
+ default=True,
131
+ help="On an expired SSO token, auto-launch `aws sso login` (opens your browser) so you "
132
+ "re-authenticate without a terminal. ON by default; disable with --no-sso-auto-login "
133
+ "(or WORKSPACES_EUC_SSO_AUTO_LOGIN=0) for headless/CI environments.",
130
134
  )
131
135
  args = parser.parse_args()
132
136
 
133
137
  if args.enable_destructive and not args.enable_writes:
134
138
  parser.error("--enable-destructive requires --enable-writes.")
135
139
 
136
- sso_auto_login = args.sso_auto_login or os.environ.get(
137
- "WORKSPACES_EUC_SSO_AUTO_LOGIN", ""
138
- ).strip().lower() in ("1", "true", "yes")
140
+ # On by default; an explicit env var (if set) overrides the flag, so it can force-disable too.
141
+ sso_auto_login = args.sso_auto_login
142
+ _sso_env = os.environ.get("WORKSPACES_EUC_SSO_AUTO_LOGIN")
143
+ if _sso_env is not None:
144
+ sso_auto_login = _sso_env.strip().lower() in ("1", "true", "yes", "on")
139
145
 
140
146
  logger.remove()
141
147
  logger.add(sys.stderr, level=os.environ.get("FASTMCP_LOG_LEVEL", "INFO").upper())
@@ -79,7 +79,7 @@ def _sso_hint() -> str:
79
79
  )
80
80
  return (
81
81
  " [SSO session expired — run `aws sso login --profile <your-profile>` to re-authenticate "
82
- "(or launch the server with --sso-auto-login to open sign-in automatically). "
82
+ "(automatic sign-in is disabled via --no-sso-auto-login). "
83
83
  "Note: signing into the AWS Console does NOT refresh the CLI/SSO token.]"
84
84
  )
85
85