sassymcp 1.12.0__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.
- sassymcp-1.12.0/.claude/scheduled_tasks.lock +1 -0
- sassymcp-1.12.0/.claude/skills/sassymcp-shell.md +36 -0
- sassymcp-1.12.0/.claude/skills/sassymcp-update.md +65 -0
- sassymcp-1.12.0/.gitattributes +6 -0
- sassymcp-1.12.0/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- sassymcp-1.12.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- sassymcp-1.12.0/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- sassymcp-1.12.0/.github/workflows/release.yml +415 -0
- sassymcp-1.12.0/.gitignore +106 -0
- sassymcp-1.12.0/.vscode/settings.json +3 -0
- sassymcp-1.12.0/CHANGELOG.md +500 -0
- sassymcp-1.12.0/IMPROVEMENT_NOTES_2026-04-30.md +219 -0
- sassymcp-1.12.0/LICENSE +21 -0
- sassymcp-1.12.0/MIGRATION.md +191 -0
- sassymcp-1.12.0/PKG-INFO +710 -0
- sassymcp-1.12.0/README.md +668 -0
- sassymcp-1.12.0/audits/mercury_sassymcp_core_report.md +136 -0
- sassymcp-1.12.0/audits/mercury_sassymcp_modules-a_report.md +16 -0
- sassymcp-1.12.0/audits/mercury_sassymcp_modules-b_report.md +147 -0
- sassymcp-1.12.0/autostart-bridge.bat +52 -0
- sassymcp-1.12.0/build-msi.ps1 +118 -0
- sassymcp-1.12.0/build.bat +39 -0
- sassymcp-1.12.0/build.sh +59 -0
- sassymcp-1.12.0/deploy/README.txt +88 -0
- sassymcp-1.12.0/deploy/claude_desktop_config.template.json +11 -0
- sassymcp-1.12.0/deploy/continue_mcp_config.template.json +14 -0
- sassymcp-1.12.0/deploy/cursor_mcp_config.template.json +12 -0
- sassymcp-1.12.0/deploy/grok_desktop_config.template.json +11 -0
- sassymcp-1.12.0/deploy/ssh_debug.txt +0 -0
- sassymcp-1.12.0/deploy/start-beta.bat +11 -0
- sassymcp-1.12.0/deploy/start-lan.bat +71 -0
- sassymcp-1.12.0/deploy/start-local.bat +22 -0
- sassymcp-1.12.0/deploy/start-tunnel.bat +92 -0
- sassymcp-1.12.0/deploy/windsurf_mcp_config.template.json +12 -0
- sassymcp-1.12.0/deploy.bat +141 -0
- sassymcp-1.12.0/docs/SassyWorks.md +153 -0
- sassymcp-1.12.0/docs/TUNNEL.md +196 -0
- sassymcp-1.12.0/docs/launch/00-RUNBOOK.md +121 -0
- sassymcp-1.12.0/docs/launch/01-positioning.md +69 -0
- sassymcp-1.12.0/docs/launch/02-product-hunt.md +75 -0
- sassymcp-1.12.0/docs/launch/03-show-hn.md +70 -0
- sassymcp-1.12.0/docs/launch/04-reddit.md +71 -0
- sassymcp-1.12.0/docs/launch/05-x-thread.md +58 -0
- sassymcp-1.12.0/docs/launch/06-devto-article.md +144 -0
- sassymcp-1.12.0/docs/launch/07-directories.md +111 -0
- sassymcp-1.12.0/docs/launch/08-assets-to-capture.md +64 -0
- sassymcp-1.12.0/docs/releases/_template.md +61 -0
- sassymcp-1.12.0/docs/releases/v1.1.1.md +110 -0
- sassymcp-1.12.0/docs/releases/v1.1.2.md +182 -0
- sassymcp-1.12.0/docs/releases/v1.1.3.md +124 -0
- sassymcp-1.12.0/docs/releases/v1.10.0.md +93 -0
- sassymcp-1.12.0/docs/releases/v1.2.0.md +98 -0
- sassymcp-1.12.0/docs/releases/v1.3.0.md +89 -0
- sassymcp-1.12.0/docs/releases/v1.3.1.md +54 -0
- sassymcp-1.12.0/docs/releases/v1.3.2.md +66 -0
- sassymcp-1.12.0/docs/releases/v1.3.3.md +89 -0
- sassymcp-1.12.0/docs/releases/v1.3.4.md +92 -0
- sassymcp-1.12.0/docs/releases/v1.4.0.md +90 -0
- sassymcp-1.12.0/docs/releases/v1.4.1.md +22 -0
- sassymcp-1.12.0/docs/releases/v1.4.2.md +91 -0
- sassymcp-1.12.0/docs/releases/v1.5.0.md +184 -0
- sassymcp-1.12.0/docs/releases/v1.7.2.md +76 -0
- sassymcp-1.12.0/docs/releases/v1.8.0.md +92 -0
- sassymcp-1.12.0/docs/superpowers/plans/2026-04-05-license-system.md +567 -0
- sassymcp-1.12.0/docs/superpowers/plans/2026-05-03-concurrency-hardening.md +1602 -0
- sassymcp-1.12.0/docs/superpowers/plans/2026-05-03-install-cli-and-dxt.md +660 -0
- sassymcp-1.12.0/docs/superpowers/specs/2026-04-05-sassymcp-product-design.md +191 -0
- sassymcp-1.12.0/docs/superpowers/specs/2026-05-03-install-cli-dxt-vscode-ext-design.md +206 -0
- sassymcp-1.12.0/docs/superpowers/specs/2026-05-03-multi-client-integration-design.md +303 -0
- sassymcp-1.12.0/docs/superpowers/specs/2026-06-06-sassy-brain-cockpit-design.md +104 -0
- sassymcp-1.12.0/hermes_node.py +292 -0
- sassymcp-1.12.0/installer.wxs +304 -0
- sassymcp-1.12.0/mcpb/README.md +35 -0
- sassymcp-1.12.0/mcpb/icon.png +0 -0
- sassymcp-1.12.0/mcpb/manifest.json +24 -0
- sassymcp-1.12.0/personal/.gitkeep +0 -0
- sassymcp-1.12.0/personal/README.md +43 -0
- sassymcp-1.12.0/pyproject.toml +77 -0
- sassymcp-1.12.0/sassymcp/__init__.py +12 -0
- sassymcp-1.12.0/sassymcp/__main__.py +7 -0
- sassymcp-1.12.0/sassymcp/_atomic.py +96 -0
- sassymcp-1.12.0/sassymcp/_audit_io.py +118 -0
- sassymcp-1.12.0/sassymcp/_brain_status.py +100 -0
- sassymcp-1.12.0/sassymcp/_cli_wizard.py +350 -0
- sassymcp-1.12.0/sassymcp/_db.py +40 -0
- sassymcp-1.12.0/sassymcp/_jobctl.py +300 -0
- sassymcp-1.12.0/sassymcp/_lemonsqueezy.py +308 -0
- sassymcp-1.12.0/sassymcp/_paths.py +76 -0
- sassymcp-1.12.0/sassymcp/_phone_status.py +57 -0
- sassymcp-1.12.0/sassymcp/_platform.py +306 -0
- sassymcp-1.12.0/sassymcp/auth.py +336 -0
- sassymcp-1.12.0/sassymcp/control_panel.py +835 -0
- sassymcp-1.12.0/sassymcp/desktop/__init__.py +10 -0
- sassymcp-1.12.0/sassymcp/desktop/__main__.py +3 -0
- sassymcp-1.12.0/sassymcp/desktop/app.py +147 -0
- sassymcp-1.12.0/sassymcp/desktop/bridge.py +141 -0
- sassymcp-1.12.0/sassymcp/install.py +559 -0
- sassymcp-1.12.0/sassymcp/license.py +568 -0
- sassymcp-1.12.0/sassymcp/modules/__init__.py +4 -0
- sassymcp-1.12.0/sassymcp/modules/_confirm.py +134 -0
- sassymcp-1.12.0/sassymcp/modules/_github_client.py +222 -0
- sassymcp-1.12.0/sassymcp/modules/_hooks.py +125 -0
- sassymcp-1.12.0/sassymcp/modules/_rate_limiter.py +157 -0
- sassymcp-1.12.0/sassymcp/modules/_security.py +731 -0
- sassymcp-1.12.0/sassymcp/modules/_tool_loader.py +717 -0
- sassymcp-1.12.0/sassymcp/modules/adb.py +214 -0
- sassymcp-1.12.0/sassymcp/modules/app_launcher.py +565 -0
- sassymcp-1.12.0/sassymcp/modules/audit.py +365 -0
- sassymcp-1.12.0/sassymcp/modules/bluetooth.py +69 -0
- sassymcp-1.12.0/sassymcp/modules/clipboard.py +132 -0
- sassymcp-1.12.0/sassymcp/modules/combos.py +356 -0
- sassymcp-1.12.0/sassymcp/modules/coordination.py +613 -0
- sassymcp-1.12.0/sassymcp/modules/crosslink.py +328 -0
- sassymcp-1.12.0/sassymcp/modules/editor.py +253 -0
- sassymcp-1.12.0/sassymcp/modules/eventlog.py +159 -0
- sassymcp-1.12.0/sassymcp/modules/fileops.py +522 -0
- sassymcp-1.12.0/sassymcp/modules/github_ops.py +1016 -0
- sassymcp-1.12.0/sassymcp/modules/github_quick.py +135 -0
- sassymcp-1.12.0/sassymcp/modules/linux.py +314 -0
- sassymcp-1.12.0/sassymcp/modules/memory.py +431 -0
- sassymcp-1.12.0/sassymcp/modules/meta.py +410 -0
- sassymcp-1.12.0/sassymcp/modules/network_audit.py +224 -0
- sassymcp-1.12.0/sassymcp/modules/observability.py +100 -0
- sassymcp-1.12.0/sassymcp/modules/persona.py +407 -0
- sassymcp-1.12.0/sassymcp/modules/phone_screen.py +784 -0
- sassymcp-1.12.0/sassymcp/modules/process_manager.py +161 -0
- sassymcp-1.12.0/sassymcp/modules/prompts.py +208 -0
- sassymcp-1.12.0/sassymcp/modules/registry.py +180 -0
- sassymcp-1.12.0/sassymcp/modules/runtime_config.py +391 -0
- sassymcp-1.12.0/sassymcp/modules/security_audit.py +274 -0
- sassymcp-1.12.0/sassymcp/modules/selfmod.py +948 -0
- sassymcp-1.12.0/sassymcp/modules/session.py +344 -0
- sassymcp-1.12.0/sassymcp/modules/setup_wizard.py +1044 -0
- sassymcp-1.12.0/sassymcp/modules/shell.py +668 -0
- sassymcp-1.12.0/sassymcp/modules/state_manager.py +94 -0
- sassymcp-1.12.0/sassymcp/modules/tools_manager.py +261 -0
- sassymcp-1.12.0/sassymcp/modules/ui_automation.py +249 -0
- sassymcp-1.12.0/sassymcp/modules/updater.py +365 -0
- sassymcp-1.12.0/sassymcp/modules/utility.py +482 -0
- sassymcp-1.12.0/sassymcp/modules/vision.py +673 -0
- sassymcp-1.12.0/sassymcp/modules/web_inspector.py +354 -0
- sassymcp-1.12.0/sassymcp/overlay/__init__.py +8 -0
- sassymcp-1.12.0/sassymcp/overlay/__main__.py +3 -0
- sassymcp-1.12.0/sassymcp/overlay/app.py +102 -0
- sassymcp-1.12.0/sassymcp/overlay/hotkey.py +23 -0
- sassymcp-1.12.0/sassymcp/overlay/launcher.py +174 -0
- sassymcp-1.12.0/sassymcp/overlay/mesh.py +104 -0
- sassymcp-1.12.0/sassymcp/overlay/tray.py +30 -0
- sassymcp-1.12.0/sassymcp/policy.py +268 -0
- sassymcp-1.12.0/sassymcp/server.py +1327 -0
- sassymcp-1.12.0/sassymcp/skills/sassymcp-tools.md +68 -0
- sassymcp-1.12.0/sassymcp/supervisor.py +585 -0
- sassymcp-1.12.0/sassymcp-billing/.gitignore +6 -0
- sassymcp-1.12.0/sassymcp-billing/package.json +14 -0
- sassymcp-1.12.0/sassymcp-billing/src/index.js +243 -0
- sassymcp-1.12.0/sassymcp-billing/wrangler.toml.example +45 -0
- sassymcp-1.12.0/sassymcp-oauth/package.json +14 -0
- sassymcp-1.12.0/sassymcp-oauth/src/index.js +449 -0
- sassymcp-1.12.0/sassymcp-oauth/wrangler.toml.example +37 -0
- sassymcp-1.12.0/sassymcp-vscode/.gitignore +5 -0
- sassymcp-1.12.0/sassymcp-vscode/.vscode/launch.json +13 -0
- sassymcp-1.12.0/sassymcp-vscode/.vscode/tasks.json +12 -0
- sassymcp-1.12.0/sassymcp-vscode/.vscodeignore +10 -0
- sassymcp-1.12.0/sassymcp-vscode/CHANGELOG.md +46 -0
- sassymcp-1.12.0/sassymcp-vscode/LICENSE +21 -0
- sassymcp-1.12.0/sassymcp-vscode/README.md +47 -0
- sassymcp-1.12.0/sassymcp-vscode/media/cockpit/cockpit.css +2 -0
- sassymcp-1.12.0/sassymcp-vscode/media/cockpit/cockpit.js +8 -0
- sassymcp-1.12.0/sassymcp-vscode/out/brain.js +123 -0
- sassymcp-1.12.0/sassymcp-vscode/out/brain.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/cockpit.js +203 -0
- sassymcp-1.12.0/sassymcp-vscode/out/cockpit.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/cockpitData.js +177 -0
- sassymcp-1.12.0/sassymcp-vscode/out/cockpitData.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/extension.js +150 -0
- sassymcp-1.12.0/sassymcp-vscode/out/extension.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/hermes.js +113 -0
- sassymcp-1.12.0/sassymcp-vscode/out/hermes.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/installer.js +135 -0
- sassymcp-1.12.0/sassymcp-vscode/out/installer.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/setupWizard.js +288 -0
- sassymcp-1.12.0/sassymcp-vscode/out/setupWizard.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/out/status.js +86 -0
- sassymcp-1.12.0/sassymcp-vscode/out/status.js.map +1 -0
- sassymcp-1.12.0/sassymcp-vscode/package-lock.json +4812 -0
- sassymcp-1.12.0/sassymcp-vscode/package.json +120 -0
- sassymcp-1.12.0/sassymcp-vscode/resources/icon.png +0 -0
- sassymcp-1.12.0/sassymcp-vscode/resources/icon.svg +16 -0
- sassymcp-1.12.0/sassymcp-vscode/src/brain.ts +98 -0
- sassymcp-1.12.0/sassymcp-vscode/src/cockpit.ts +190 -0
- sassymcp-1.12.0/sassymcp-vscode/src/cockpitData.ts +204 -0
- sassymcp-1.12.0/sassymcp-vscode/src/extension.ts +135 -0
- sassymcp-1.12.0/sassymcp-vscode/src/hermes.ts +84 -0
- sassymcp-1.12.0/sassymcp-vscode/src/installer.ts +106 -0
- sassymcp-1.12.0/sassymcp-vscode/src/setupWizard.ts +280 -0
- sassymcp-1.12.0/sassymcp-vscode/src/status.ts +54 -0
- sassymcp-1.12.0/sassymcp-vscode/tsconfig.json +16 -0
- sassymcp-1.12.0/sassymcp-vscode/vite.config.ts +35 -0
- sassymcp-1.12.0/sassymcp-vscode/webview/App.tsx +411 -0
- sassymcp-1.12.0/sassymcp-vscode/webview/cockpit.css +273 -0
- sassymcp-1.12.0/sassymcp-vscode/webview/main.tsx +8 -0
- sassymcp-1.12.0/sassymcp-vscode/webview/tsconfig.json +14 -0
- sassymcp-1.12.0/sassymcp-vscode/webview/types.ts +134 -0
- sassymcp-1.12.0/scripts/build-mcpb.ps1 +102 -0
- sassymcp-1.12.0/scripts/check-token.ps1 +9 -0
- sassymcp-1.12.0/scripts/gen-icons.py +104 -0
- sassymcp-1.12.0/scripts/get-auth-header.ps1 +8 -0
- sassymcp-1.12.0/scripts/mcp-init-body.ps1 +14 -0
- sassymcp-1.12.0/scripts/smoke-test.ps1 +40 -0
- sassymcp-1.12.0/scripts/verify-release.ps1 +96 -0
- sassymcp-1.12.0/server.json +22 -0
- sassymcp-1.12.0/start-lan.bat +71 -0
- sassymcp-1.12.0/start-local.bat +22 -0
- sassymcp-1.12.0/start-supervised.bat +47 -0
- sassymcp-1.12.0/start-tunnel.bat +92 -0
- sassymcp-1.12.0/tests/conftest.py +41 -0
- sassymcp-1.12.0/tests/test_atomic_write.py +112 -0
- sassymcp-1.12.0/tests/test_audit_io.py +77 -0
- sassymcp-1.12.0/tests/test_concurrency_integration.py +335 -0
- sassymcp-1.12.0/tests/test_concurrency_stress.py +94 -0
- sassymcp-1.12.0/tests/test_control_panel.py +230 -0
- sassymcp-1.12.0/tests/test_coordination.py +158 -0
- sassymcp-1.12.0/tests/test_db_helper.py +93 -0
- sassymcp-1.12.0/tests/test_discovery.py +97 -0
- sassymcp-1.12.0/tests/test_install.py +414 -0
- sassymcp-1.12.0/tests/test_intercept.py +805 -0
- sassymcp-1.12.0/tests/test_lemonsqueezy.py +455 -0
- sassymcp-1.12.0/tests/test_license_gating.py +241 -0
- sassymcp-1.12.0/tests/test_policy.py +152 -0
- sassymcp-1.12.0/tests/test_shell_auto_promote.py +100 -0
- sassymcp-1.12.0/tests/test_supervisor_lifecycle.py +327 -0
- sassymcp-1.12.0/tests/test_tool_loader_boost.py +160 -0
- sassymcp-1.12.0/tests/test_updater.py +52 -0
- sassymcp-1.12.0/tools/lemonsqueezy_setup.py +309 -0
- sassymcp-1.12.0/tools/mercury_audit_sassymcp.py +235 -0
- sassymcp-1.12.0/tools/verify_audit_fixes.py +479 -0
- sassymcp-1.12.0/uv.lock +1332 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"c893b31e-4d63-4157-b42d-1247cac71aec","pid":21192,"acquiredAt":1782209316903}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sassymcp-shell
|
|
3
|
+
description: Use BEFORE calling sassy_shell, sassy_session_start, or sassy_session_send on a SassyMCP server. Establishes that the default shell is Windows PowerShell so commands are written in PowerShell syntax on the first try (no wasted retries on bash idioms). Also use when generating multi-line scripts to a SassyMCP target.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SassyMCP Shell Context
|
|
7
|
+
|
|
8
|
+
The SassyMCP server runs on **Windows**. `sassy_shell` defaults to `shell="powershell"`. Write commands in PowerShell syntax up front — don't reach for bash habits unless you've explicitly switched to `shell="wsl"` or `shell="cmd"`.
|
|
9
|
+
|
|
10
|
+
## Quick translation
|
|
11
|
+
|
|
12
|
+
| bash / POSIX | PowerShell |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `cd /d V:\foo` | `Set-Location V:\foo` |
|
|
15
|
+
| `cmd1 && cmd2` | `cmd1; cmd2` (or `if ($?) { cmd2 }`) |
|
|
16
|
+
| `cmd1 \|\| cmd2` | `if (-not $?) { cmd2 }` |
|
|
17
|
+
| `mkdir -p foo/bar` | `New-Item -ItemType Directory -Force foo/bar` |
|
|
18
|
+
| `cat foo` | `Get-Content foo` |
|
|
19
|
+
| `grep pat foo` | `Select-String pat foo` |
|
|
20
|
+
| `which X` | `Get-Command X` |
|
|
21
|
+
| `export FOO=bar` | `$env:FOO = "bar"` |
|
|
22
|
+
| `ls -la` | `Get-ChildItem -Force` |
|
|
23
|
+
| `rm -rf …` | intercepted — use `sassy_safe_delete` |
|
|
24
|
+
| escape with `\` | escape with backtick `` ` `` |
|
|
25
|
+
|
|
26
|
+
`sassy_shell` auto-rewrites `&&` → `;` and `cd /d` → `Set-Location` for the PowerShell shell, but writing it correctly the first time saves a round-trip.
|
|
27
|
+
|
|
28
|
+
## Multi-line scripts and file content
|
|
29
|
+
|
|
30
|
+
- Don't try to embed multi-line PowerShell or here-strings inside a single `sassy_shell` argument — quoting collapses, and `Set-Content @'...'@` content gets keyword-scanned even when it's just data.
|
|
31
|
+
- **Use `sassy_write_file(path, content)` instead** — direct .NET write, bypasses all PowerShell quoting and the shell-keyword scanner. Then invoke the resulting file with `sassy_shell`.
|
|
32
|
+
|
|
33
|
+
## When to switch shells
|
|
34
|
+
|
|
35
|
+
- `shell="cmd"`: `.bat` files, `tasklist`/`taskkill`, legacy CMD-only builtins.
|
|
36
|
+
- `shell="wsl"`: real bash — `grep`/`awk`/`sed` pipelines, Linux-native tools, anything where PowerShell equivalents are awkward. WSL receives the command verbatim, no PowerShell rewriting.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sassymcp-update
|
|
3
|
+
description: Use when the user wants to check, review, or apply a SassyMCP update — e.g. "is there a new version of sassymcp?", "update sassymcp", "what changed in the latest sassymcp release?", "show the sassymcp changelog". Walks through Kali-style apt-update / apt-show / apt-upgrade against this server's GitHub Releases (or the license-gated sassyconsultingllc.com endpoint when SASSYMCP_LICENSE_KEY is set). Never auto-installs — surfaces the asset, downloads to staging, and hands the user the run command.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SassyMCP Update Walkthrough
|
|
7
|
+
|
|
8
|
+
This skill walks through the four updater tools added in v1.3.0:
|
|
9
|
+
|
|
10
|
+
| Step | Tool | apt analogue |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| 1 | `sassy_update_check` | `apt update` — refresh remote state |
|
|
13
|
+
| 2 | `sassy_update_changelog` | `apt show <pkg>` — read release notes |
|
|
14
|
+
| 3 | `sassy_update_list` | `apt list --upgradable` — see assets |
|
|
15
|
+
| 4 | `sassy_update_apply` | `apt upgrade` (download phase) — stage the install |
|
|
16
|
+
|
|
17
|
+
## When to invoke
|
|
18
|
+
|
|
19
|
+
Trigger when the user asks anything like:
|
|
20
|
+
- "check for sassymcp updates"
|
|
21
|
+
- "is there a new version?"
|
|
22
|
+
- "what's in the latest release?"
|
|
23
|
+
- "update sassymcp" / "upgrade sassymcp"
|
|
24
|
+
- "show me the changelog"
|
|
25
|
+
- "download the new MSI"
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
1. **Call `sassy_update_check`** with `force=False` (cached, 5 min TTL).
|
|
30
|
+
- If `upgradable: false` — tell the user they're on the latest, stop.
|
|
31
|
+
- If `upgradable: true` — surface the `summary` field (e.g. `1.2.0 → 1.3.0 available`).
|
|
32
|
+
|
|
33
|
+
2. **Call `sassy_update_changelog`** with no `tag` (defaults to latest).
|
|
34
|
+
- Show the user the `name`, `published_at`, and `body` so they know what's
|
|
35
|
+
in the release before downloading 100+ MB.
|
|
36
|
+
|
|
37
|
+
3. **Ask the user which asset they want**:
|
|
38
|
+
- Portable zip (`sassymcp-v*-portable.zip`, ~123 MB) — exe + tools + launchers.
|
|
39
|
+
Extract anywhere; delete the folder to remove. **Recommended.**
|
|
40
|
+
- Standalone exe (`sassymcp.exe`, ~35 MB) — no bundled tools.
|
|
41
|
+
- Or skip — they read the changelog and don't want to upgrade right now.
|
|
42
|
+
|
|
43
|
+
4. **Call `sassy_update_apply`** with the chosen `asset_name`.
|
|
44
|
+
- Returns `downloaded_to` (a path under `%LOCALAPPDATA%\SassyMCP\updates\`)
|
|
45
|
+
and `next_step` — for a portable zip this is an `Expand-Archive`
|
|
46
|
+
command targeting `%LOCALAPPDATA%\SassyMCP\<tag>\`; for the standalone
|
|
47
|
+
exe it's the path to the exe.
|
|
48
|
+
- Echo the `next_step` to the user verbatim — **do not** auto-execute it.
|
|
49
|
+
Updates apply on next launch; this is an explicit user action by design.
|
|
50
|
+
|
|
51
|
+
## License-aware download
|
|
52
|
+
|
|
53
|
+
If the env var `SASSYMCP_LICENSE_KEY` is set, `sassy_update_apply`
|
|
54
|
+
automatically rewrites the download URL to the gated
|
|
55
|
+
`https://sassyconsultingllc.com/download/sassymcp/windows/<asset>?key=...`
|
|
56
|
+
endpoint. The user gets the same file from the licensed mirror instead of
|
|
57
|
+
public GitHub Releases.
|
|
58
|
+
|
|
59
|
+
## What this skill does NOT do
|
|
60
|
+
|
|
61
|
+
- **Never auto-runs the installer.** UAC + user intent. Always returns the
|
|
62
|
+
command for the user to run themselves.
|
|
63
|
+
- **Never modifies the running server.** Update applies on next launch.
|
|
64
|
+
- **Never blocks a downgrade.** If the user passes an older `tag` to
|
|
65
|
+
`sassy_update_apply`, that's their call.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2026 Shane Smith / Sassy Consulting LLC. All rights reserved.
|
|
3
|
+
Proprietary source. This notice is Copyright Management Information (17 U.S.C. 1202); removal or alteration prohibited.
|
|
4
|
+
CodeMark: SCLLC1-SassyMCP-Q3OSLI6ULAIQ
|
|
5
|
+
-->
|
|
6
|
+
---
|
|
7
|
+
name: Bug Report
|
|
8
|
+
about: Something isn't working right
|
|
9
|
+
title: "[Bug] "
|
|
10
|
+
labels: bug
|
|
11
|
+
assignees: ''
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**What happened?**
|
|
15
|
+
A clear description of the bug.
|
|
16
|
+
|
|
17
|
+
**Steps to reproduce**
|
|
18
|
+
1.
|
|
19
|
+
2.
|
|
20
|
+
3.
|
|
21
|
+
|
|
22
|
+
**Expected behavior**
|
|
23
|
+
What should have happened.
|
|
24
|
+
|
|
25
|
+
**Environment**
|
|
26
|
+
- SassyMCP version: v1.1.0
|
|
27
|
+
- MCP client: (Claude Desktop / Grok Desktop / Cursor / other)
|
|
28
|
+
- Transport mode: (stdio / HTTP / SSE)
|
|
29
|
+
- Windows version:
|
|
30
|
+
- Running from: (exe / source)
|
|
31
|
+
|
|
32
|
+
**Relevant logs**
|
|
33
|
+
Paste any error output or server logs here.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
(paste logs here)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Screenshots**
|
|
40
|
+
If applicable, add screenshots.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Copyright (c) 2026 Shane Smith / Sassy Consulting LLC. All rights reserved.
|
|
2
|
+
# Proprietary source. This notice is Copyright Management Information (17 U.S.C. 1202); removal or alteration prohibited.
|
|
3
|
+
# CodeMark: SCLLC1-SassyMCP-TBNJIBENT44G
|
|
4
|
+
blank_issues_enabled: true
|
|
5
|
+
contact_links:
|
|
6
|
+
- name: Documentation
|
|
7
|
+
url: https://github.com/sassyconsultingllc/SassyMCP#readme
|
|
8
|
+
about: Check the README for setup and usage guides
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2026 Shane Smith / Sassy Consulting LLC. All rights reserved.
|
|
3
|
+
Proprietary source. This notice is Copyright Management Information (17 U.S.C. 1202); removal or alteration prohibited.
|
|
4
|
+
CodeMark: SCLLC1-SassyMCP-O3YBHELD3QCV
|
|
5
|
+
-->
|
|
6
|
+
---
|
|
7
|
+
name: Feature Request
|
|
8
|
+
about: Suggest a new tool or improvement
|
|
9
|
+
title: "[Feature] "
|
|
10
|
+
labels: enhancement
|
|
11
|
+
assignees: ''
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
**What would you like?**
|
|
15
|
+
A clear description of the feature or improvement.
|
|
16
|
+
|
|
17
|
+
**Why?**
|
|
18
|
+
What problem does this solve or what workflow does it enable?
|
|
19
|
+
|
|
20
|
+
**Which module would this belong to?**
|
|
21
|
+
(e.g., core, android, system, github, new module)
|
|
22
|
+
|
|
23
|
+
**Alternatives considered**
|
|
24
|
+
Any workarounds you've tried or other approaches.
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# Copyright (c) 2026 Shane Smith / Sassy Consulting LLC. All rights reserved.
|
|
2
|
+
# Proprietary source. This notice is Copyright Management Information (17 U.S.C. 1202); removal or alteration prohibited.
|
|
3
|
+
# CodeMark: SCLLC1-SassyMCP-G725NZONYF5R
|
|
4
|
+
name: Release
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags:
|
|
9
|
+
- "v*.*.*"
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
# Allow manual builds against any branch without tagging. The build jobs
|
|
12
|
+
# produce artifacts; the release/publish jobs only fire on real tag pushes.
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write # needed for gh release create
|
|
16
|
+
|
|
17
|
+
env:
|
|
18
|
+
# Opt in to Node 24 for all JavaScript actions in this workflow. Github
|
|
19
|
+
# deprecated Node 20 in Sept 2025; node24 becomes the default June 2026.
|
|
20
|
+
# Setting this now silences the warnings and confirms forward-compat.
|
|
21
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build-exe:
|
|
25
|
+
name: Build sassymcp.exe (Windows)
|
|
26
|
+
runs-on: windows-latest
|
|
27
|
+
defaults:
|
|
28
|
+
run:
|
|
29
|
+
shell: pwsh # windows-latest defaults to pwsh; making it explicit
|
|
30
|
+
outputs:
|
|
31
|
+
version: ${{ steps.version.outputs.value }}
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.11"
|
|
38
|
+
cache: pip
|
|
39
|
+
|
|
40
|
+
- name: Read version from sassymcp/__init__.py
|
|
41
|
+
id: version
|
|
42
|
+
run: |
|
|
43
|
+
$content = Get-Content sassymcp/__init__.py -Raw
|
|
44
|
+
if ($content -match '__version__\s*=\s*"([^"]+)"') {
|
|
45
|
+
$v = $Matches[1]
|
|
46
|
+
"value=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
47
|
+
Write-Host "Version: $v"
|
|
48
|
+
} else {
|
|
49
|
+
Write-Error "Could not parse __version__"
|
|
50
|
+
exit 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- name: Verify tag matches __version__
|
|
54
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
55
|
+
run: |
|
|
56
|
+
$tagVersion = "${{ github.ref_name }}".TrimStart("v")
|
|
57
|
+
$sourceVersion = "${{ steps.version.outputs.value }}"
|
|
58
|
+
if ($tagVersion -ne $sourceVersion) {
|
|
59
|
+
Write-Error "Tag $tagVersion does not match __version__ $sourceVersion. Bump sassymcp/__init__.py before tagging."
|
|
60
|
+
exit 1
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- name: Install dependencies + PyInstaller
|
|
64
|
+
# Install base deps only — the [all] extras (playwright,
|
|
65
|
+
# pytesseract, watchdog) are lazy-imported with graceful
|
|
66
|
+
# fallbacks, so excluding them keeps the shipped exe at ~35 MB
|
|
67
|
+
# instead of ~73 MB. Users who need OCR or playwright
|
|
68
|
+
# screenshots install those into their own Python.
|
|
69
|
+
run: |
|
|
70
|
+
python -m pip install --upgrade pip
|
|
71
|
+
python -m pip install pyinstaller
|
|
72
|
+
python -m pip install -e .
|
|
73
|
+
|
|
74
|
+
- name: Build sassymcp.exe via PyInstaller
|
|
75
|
+
run: |
|
|
76
|
+
pyinstaller --clean --noconfirm sassymcp.spec
|
|
77
|
+
|
|
78
|
+
- name: Verify exe exists
|
|
79
|
+
run: |
|
|
80
|
+
if (-not (Test-Path dist\sassymcp.exe)) {
|
|
81
|
+
Write-Error "PyInstaller did not produce dist\sassymcp.exe"
|
|
82
|
+
exit 1
|
|
83
|
+
}
|
|
84
|
+
$size = (Get-Item dist\sassymcp.exe).Length / 1MB
|
|
85
|
+
Write-Host "Built dist\sassymcp.exe ($([math]::Round($size, 1)) MB)"
|
|
86
|
+
|
|
87
|
+
- name: Smoke-test exe
|
|
88
|
+
run: |
|
|
89
|
+
# argparse exits 0 after printing --help, which is the success signal.
|
|
90
|
+
$output = & .\dist\sassymcp.exe --help 2>&1
|
|
91
|
+
if ($LASTEXITCODE -ne 0) {
|
|
92
|
+
Write-Error "sassymcp.exe --help exited $LASTEXITCODE; output: $output"
|
|
93
|
+
exit 1
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
- name: Upload exe artifact
|
|
97
|
+
uses: actions/upload-artifact@v4
|
|
98
|
+
with:
|
|
99
|
+
name: sassymcp-exe
|
|
100
|
+
path: dist/sassymcp.exe
|
|
101
|
+
if-no-files-found: error
|
|
102
|
+
|
|
103
|
+
build-dxt:
|
|
104
|
+
name: Build sassymcp.dxt
|
|
105
|
+
runs-on: windows-latest
|
|
106
|
+
needs: build-exe
|
|
107
|
+
defaults:
|
|
108
|
+
run:
|
|
109
|
+
shell: pwsh
|
|
110
|
+
steps:
|
|
111
|
+
- uses: actions/checkout@v4
|
|
112
|
+
|
|
113
|
+
- uses: actions/setup-node@v4
|
|
114
|
+
with:
|
|
115
|
+
node-version: "20"
|
|
116
|
+
|
|
117
|
+
- name: Download exe artifact
|
|
118
|
+
uses: actions/download-artifact@v4
|
|
119
|
+
with:
|
|
120
|
+
name: sassymcp-exe
|
|
121
|
+
path: .
|
|
122
|
+
|
|
123
|
+
- name: Build MCPB (+ byte-identical .dxt)
|
|
124
|
+
# build-mcpb.ps1 packs the bundle via the official @anthropic-ai/mcpb
|
|
125
|
+
# CLI (needs npx, hence setup-node above) and emits BOTH dist\*.mcpb and
|
|
126
|
+
# a byte-identical dist\*.dxt. It auto-syncs mcpb/manifest.json's version
|
|
127
|
+
# to sassymcp/__init__.py. Renamed from the old build-dxt.ps1 (now in
|
|
128
|
+
# scripts/_DELETE_/), which this job still referenced — so every release
|
|
129
|
+
# since the rename failed at "scripts/build-dxt.ps1 not recognized".
|
|
130
|
+
run: |
|
|
131
|
+
& scripts/build-mcpb.ps1
|
|
132
|
+
|
|
133
|
+
- name: Verify DXT exists
|
|
134
|
+
run: |
|
|
135
|
+
$dxt = Get-ChildItem dist\sassymcp-v*.dxt | Select-Object -First 1
|
|
136
|
+
if (-not $dxt) {
|
|
137
|
+
Write-Error "build-dxt.ps1 did not produce a DXT file"
|
|
138
|
+
exit 1
|
|
139
|
+
}
|
|
140
|
+
Write-Host "Built $($dxt.Name) ($([math]::Round($dxt.Length / 1MB, 1)) MB)"
|
|
141
|
+
|
|
142
|
+
- name: Upload DXT artifact
|
|
143
|
+
uses: actions/upload-artifact@v4
|
|
144
|
+
with:
|
|
145
|
+
name: sassymcp-dxt
|
|
146
|
+
path: dist/sassymcp-v*.dxt
|
|
147
|
+
if-no-files-found: error
|
|
148
|
+
|
|
149
|
+
build-vsix:
|
|
150
|
+
name: Build sassymcp-vscode-*.vsix
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
# No `needs:` — the VSIX doesn't depend on the .exe artifact. Build in
|
|
153
|
+
# parallel with build-exe to shave a few minutes off the pipeline.
|
|
154
|
+
steps:
|
|
155
|
+
- uses: actions/checkout@v4
|
|
156
|
+
|
|
157
|
+
- uses: actions/setup-node@v4
|
|
158
|
+
with:
|
|
159
|
+
node-version: "20"
|
|
160
|
+
cache: npm
|
|
161
|
+
cache-dependency-path: sassymcp-vscode/package-lock.json
|
|
162
|
+
|
|
163
|
+
- name: Sync sassymcp-vscode/package.json version with __init__.py
|
|
164
|
+
# The package.json version drives the produced .vsix filename. Keep
|
|
165
|
+
# it locked to the canonical __version__ so the VSIX, the DXT, and
|
|
166
|
+
# the GitHub release tag all carry the same string.
|
|
167
|
+
run: |
|
|
168
|
+
set -euo pipefail
|
|
169
|
+
version=$(python3 -c 'import re,sys; m=re.search(r"__version__\s*=\s*\"([^\"]+)\"", open("sassymcp/__init__.py").read()); print(m.group(1)) if m else sys.exit("could not parse __version__")')
|
|
170
|
+
echo "Syncing sassymcp-vscode/package.json to version $version"
|
|
171
|
+
# Update only the top-level "version" field. jq preserves formatting
|
|
172
|
+
# well enough for our purposes; install jq if not present (it is on
|
|
173
|
+
# ubuntu-latest by default but be explicit).
|
|
174
|
+
which jq >/dev/null || sudo apt-get update && sudo apt-get install -y jq
|
|
175
|
+
tmp=$(mktemp)
|
|
176
|
+
jq --arg v "$version" '.version = $v' sassymcp-vscode/package.json > "$tmp"
|
|
177
|
+
mv "$tmp" sassymcp-vscode/package.json
|
|
178
|
+
# Show the change for the run log
|
|
179
|
+
grep '"version"' sassymcp-vscode/package.json | head -1
|
|
180
|
+
|
|
181
|
+
- name: Install extension dependencies
|
|
182
|
+
working-directory: sassymcp-vscode
|
|
183
|
+
run: npm ci
|
|
184
|
+
|
|
185
|
+
- name: Compile TypeScript
|
|
186
|
+
working-directory: sassymcp-vscode
|
|
187
|
+
run: npm run compile
|
|
188
|
+
|
|
189
|
+
- name: Ensure dist/ exists
|
|
190
|
+
# vsce --out path must be a real directory or vsce errors. Repo root.
|
|
191
|
+
run: mkdir -p dist
|
|
192
|
+
|
|
193
|
+
- name: Package VSIX
|
|
194
|
+
working-directory: sassymcp-vscode
|
|
195
|
+
run: npx --yes @vscode/vsce package --out ../dist/
|
|
196
|
+
|
|
197
|
+
- name: Verify VSIX exists
|
|
198
|
+
run: |
|
|
199
|
+
ls -la dist/
|
|
200
|
+
if ! ls dist/sassymcp-*.vsix 1> /dev/null 2>&1; then
|
|
201
|
+
echo "vsce did not produce a VSIX"
|
|
202
|
+
exit 1
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
- name: Upload VSIX artifact
|
|
206
|
+
uses: actions/upload-artifact@v4
|
|
207
|
+
with:
|
|
208
|
+
name: sassymcp-vsix
|
|
209
|
+
path: dist/sassymcp-*.vsix
|
|
210
|
+
if-no-files-found: error
|
|
211
|
+
|
|
212
|
+
build-macos:
|
|
213
|
+
name: Build sassymcp (macOS ${{ matrix.arch }})
|
|
214
|
+
runs-on: ${{ matrix.runner }}
|
|
215
|
+
# Build each arch on a native runner — PyInstaller can't cross-compile, and
|
|
216
|
+
# building x86_64 on an Intel runner + arm64 on an Apple Silicon runner is
|
|
217
|
+
# what lets us lipo a true universal2 binary in build-macos-universal.
|
|
218
|
+
strategy:
|
|
219
|
+
fail-fast: false
|
|
220
|
+
matrix:
|
|
221
|
+
include:
|
|
222
|
+
- runner: macos-13 # Intel (x86_64)
|
|
223
|
+
arch: x86_64
|
|
224
|
+
- runner: macos-14 # Apple Silicon (arm64)
|
|
225
|
+
arch: arm64
|
|
226
|
+
steps:
|
|
227
|
+
- uses: actions/checkout@v4
|
|
228
|
+
|
|
229
|
+
- uses: actions/setup-python@v5
|
|
230
|
+
with:
|
|
231
|
+
python-version: "3.11"
|
|
232
|
+
cache: pip
|
|
233
|
+
|
|
234
|
+
- name: Verify tag matches __version__
|
|
235
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
236
|
+
run: |
|
|
237
|
+
set -euo pipefail
|
|
238
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
239
|
+
src=$(python3 -c 'import re,sys; m=re.search(r"__version__\s*=\s*\"([^\"]+)\"", open("sassymcp/__init__.py").read()); print(m.group(1)) if m else sys.exit("could not parse __version__")')
|
|
240
|
+
if [ "$tag" != "$src" ]; then
|
|
241
|
+
echo "Tag $tag does not match __version__ $src. Bump sassymcp/__init__.py before tagging."
|
|
242
|
+
exit 1
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
- name: Install dependencies + PyInstaller
|
|
246
|
+
# Base deps only — the [all] extras (playwright/pytesseract/watchdog)
|
|
247
|
+
# are lazy-imported with graceful fallbacks, mirroring build-exe. The
|
|
248
|
+
# spec is platform-aware: pyobjc is pulled on macOS via sys_platform
|
|
249
|
+
# markers, pywinauto is excluded.
|
|
250
|
+
run: |
|
|
251
|
+
python -m pip install --upgrade pip
|
|
252
|
+
python -m pip install pyinstaller
|
|
253
|
+
python -m pip install -e .
|
|
254
|
+
|
|
255
|
+
- name: Confirm runner arch
|
|
256
|
+
run: |
|
|
257
|
+
set -euo pipefail
|
|
258
|
+
echo "uname -m: $(uname -m) (expected ${{ matrix.arch }})"
|
|
259
|
+
test "$(uname -m)" = "${{ matrix.arch }}"
|
|
260
|
+
|
|
261
|
+
- name: Build sassymcp via PyInstaller
|
|
262
|
+
run: pyinstaller --clean --noconfirm sassymcp.spec
|
|
263
|
+
|
|
264
|
+
- name: Verify + smoke-test
|
|
265
|
+
run: |
|
|
266
|
+
set -euo pipefail
|
|
267
|
+
test -f dist/sassymcp || { echo "PyInstaller did not produce dist/sassymcp"; exit 1; }
|
|
268
|
+
chmod +x dist/sassymcp
|
|
269
|
+
file dist/sassymcp
|
|
270
|
+
# argparse exits 0 after --help — the success signal.
|
|
271
|
+
./dist/sassymcp --help >/dev/null
|
|
272
|
+
echo "OK (${{ matrix.arch }})"
|
|
273
|
+
|
|
274
|
+
- name: Upload per-arch artifact
|
|
275
|
+
uses: actions/upload-artifact@v4
|
|
276
|
+
with:
|
|
277
|
+
name: sassymcp-macos-${{ matrix.arch }}
|
|
278
|
+
path: dist/sassymcp
|
|
279
|
+
if-no-files-found: error
|
|
280
|
+
|
|
281
|
+
build-macos-universal:
|
|
282
|
+
name: Merge macOS universal2 binary
|
|
283
|
+
runs-on: macos-latest
|
|
284
|
+
needs: build-macos
|
|
285
|
+
steps:
|
|
286
|
+
- name: Download x86_64 build
|
|
287
|
+
uses: actions/download-artifact@v4
|
|
288
|
+
with:
|
|
289
|
+
name: sassymcp-macos-x86_64
|
|
290
|
+
path: x86_64
|
|
291
|
+
|
|
292
|
+
- name: Download arm64 build
|
|
293
|
+
uses: actions/download-artifact@v4
|
|
294
|
+
with:
|
|
295
|
+
name: sassymcp-macos-arm64
|
|
296
|
+
path: arm64
|
|
297
|
+
|
|
298
|
+
- name: lipo into a universal2 binary
|
|
299
|
+
run: |
|
|
300
|
+
set -euo pipefail
|
|
301
|
+
mkdir -p dist
|
|
302
|
+
lipo -create -output dist/sassymcp-macos x86_64/sassymcp arm64/sassymcp
|
|
303
|
+
chmod +x dist/sassymcp-macos
|
|
304
|
+
echo "=== archs ==="
|
|
305
|
+
lipo -archs dist/sassymcp-macos
|
|
306
|
+
file dist/sassymcp-macos
|
|
307
|
+
lipo -archs dist/sassymcp-macos | grep -q x86_64
|
|
308
|
+
lipo -archs dist/sassymcp-macos | grep -q arm64
|
|
309
|
+
echo "universal2 OK ($(du -h dist/sassymcp-macos | cut -f1))"
|
|
310
|
+
|
|
311
|
+
- name: Smoke-test universal binary
|
|
312
|
+
# macos-latest is arm64; the binary runs its arm64 slice natively.
|
|
313
|
+
run: |
|
|
314
|
+
set -euo pipefail
|
|
315
|
+
./dist/sassymcp-macos --help >/dev/null
|
|
316
|
+
echo "universal --help OK"
|
|
317
|
+
|
|
318
|
+
# NOTE: this binary is UNSIGNED. On download, Gatekeeper quarantines it
|
|
319
|
+
# ("unidentified developer"); users clear it with `xattr -dr
|
|
320
|
+
# com.apple.quarantine sassymcp-macos` or right-click → Open. To ship
|
|
321
|
+
# signed+notarized, add an Apple Developer ID cert + notarytool step here
|
|
322
|
+
# (needs an Apple Developer account + secrets).
|
|
323
|
+
- name: Upload universal artifact
|
|
324
|
+
uses: actions/upload-artifact@v4
|
|
325
|
+
with:
|
|
326
|
+
name: sassymcp-macos
|
|
327
|
+
path: dist/sassymcp-macos
|
|
328
|
+
if-no-files-found: error
|
|
329
|
+
|
|
330
|
+
release:
|
|
331
|
+
name: GitHub Release
|
|
332
|
+
runs-on: ubuntu-latest
|
|
333
|
+
needs: [build-exe, build-dxt, build-vsix, build-macos-universal]
|
|
334
|
+
# Only fire on real tag pushes; workflow_dispatch builds the artifacts
|
|
335
|
+
# for verification but never publishes a release.
|
|
336
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
337
|
+
steps:
|
|
338
|
+
- uses: actions/checkout@v4
|
|
339
|
+
|
|
340
|
+
- name: Download all artifacts
|
|
341
|
+
uses: actions/download-artifact@v4
|
|
342
|
+
with:
|
|
343
|
+
path: release-artifacts
|
|
344
|
+
|
|
345
|
+
- name: List downloaded artifacts
|
|
346
|
+
run: find release-artifacts -type f
|
|
347
|
+
|
|
348
|
+
- name: Look up release notes for this version
|
|
349
|
+
id: notes
|
|
350
|
+
run: |
|
|
351
|
+
set -euo pipefail
|
|
352
|
+
version="${{ github.ref_name }}"
|
|
353
|
+
notes_file="docs/releases/${version}.md"
|
|
354
|
+
if [ -f "$notes_file" ]; then
|
|
355
|
+
echo "notes_file=$notes_file" >> "$GITHUB_OUTPUT"
|
|
356
|
+
echo "Using $notes_file"
|
|
357
|
+
else
|
|
358
|
+
echo "notes_file=" >> "$GITHUB_OUTPUT"
|
|
359
|
+
echo "No docs/releases/${version}.md — falling back to auto-generated notes"
|
|
360
|
+
fi
|
|
361
|
+
|
|
362
|
+
- name: Create GitHub Release with all artifacts
|
|
363
|
+
env:
|
|
364
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
365
|
+
run: |
|
|
366
|
+
set -euo pipefail
|
|
367
|
+
if [ -n "${{ steps.notes.outputs.notes_file }}" ]; then
|
|
368
|
+
gh release create "${{ github.ref_name }}" \
|
|
369
|
+
release-artifacts/sassymcp-exe/sassymcp.exe \
|
|
370
|
+
release-artifacts/sassymcp-macos/sassymcp-macos \
|
|
371
|
+
release-artifacts/sassymcp-dxt/*.dxt \
|
|
372
|
+
release-artifacts/sassymcp-vsix/*.vsix \
|
|
373
|
+
--title "${{ github.ref_name }}" \
|
|
374
|
+
--notes-file "${{ steps.notes.outputs.notes_file }}"
|
|
375
|
+
else
|
|
376
|
+
gh release create "${{ github.ref_name }}" \
|
|
377
|
+
release-artifacts/sassymcp-exe/sassymcp.exe \
|
|
378
|
+
release-artifacts/sassymcp-macos/sassymcp-macos \
|
|
379
|
+
release-artifacts/sassymcp-dxt/*.dxt \
|
|
380
|
+
release-artifacts/sassymcp-vsix/*.vsix \
|
|
381
|
+
--title "${{ github.ref_name }}" \
|
|
382
|
+
--generate-notes
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
publish-vsix:
|
|
386
|
+
name: Publish VSIX to VS Code Marketplace
|
|
387
|
+
runs-on: ubuntu-latest
|
|
388
|
+
needs: build-vsix
|
|
389
|
+
# GitHub Actions does not allow `secrets.*` in job-level `if`. Gate this
|
|
390
|
+
# job on a repository VARIABLE (Settings -> Variables) instead. Set
|
|
391
|
+
# PUBLISH_VSIX=true once VSCE_PAT is configured in repo secrets. Also
|
|
392
|
+
# require a real tag — workflow_dispatch builds shouldn't auto-publish.
|
|
393
|
+
if: ${{ startsWith(github.ref, 'refs/tags/') && vars.PUBLISH_VSIX == 'true' }}
|
|
394
|
+
steps:
|
|
395
|
+
- uses: actions/checkout@v4
|
|
396
|
+
|
|
397
|
+
- uses: actions/setup-node@v4
|
|
398
|
+
with:
|
|
399
|
+
node-version: "20"
|
|
400
|
+
|
|
401
|
+
- name: Download VSIX
|
|
402
|
+
uses: actions/download-artifact@v4
|
|
403
|
+
with:
|
|
404
|
+
name: sassymcp-vsix
|
|
405
|
+
path: dist
|
|
406
|
+
|
|
407
|
+
- name: Publish to Marketplace
|
|
408
|
+
env:
|
|
409
|
+
VSCE_PAT: ${{ secrets.VSCE_PAT }}
|
|
410
|
+
run: |
|
|
411
|
+
if [ -z "$VSCE_PAT" ]; then
|
|
412
|
+
echo "VSCE_PAT secret is empty; cannot publish."
|
|
413
|
+
exit 1
|
|
414
|
+
fi
|
|
415
|
+
npx --yes @vscode/vsce publish --packagePath dist/sassymcp-*.vsix
|