Skip to content

Commit 5b8591a

Browse files
chore: harden waxmcp release pipeline and version bump
1 parent ee48e2f commit 5b8591a

File tree

11 files changed

+252
-23
lines changed

11 files changed

+252
-23
lines changed

.github/workflows/release-waxmcp.yml

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,36 @@ jobs:
5353
if: ${{ matrix.source-build }}
5454
run: |
5555
set -euo pipefail
56-
swift build --product WaxCLI --traits MCPServer --configuration release --triple "${{ matrix.triple }}"
57-
BIN_PATH="$(swift build --product WaxCLI --traits MCPServer --configuration release --triple "${{ matrix.triple }}" --show-bin-path)"
58-
mkdir -p npm/waxmcp/dist/${{ matrix.platform }}
59-
cp "$BIN_PATH/WaxCLI" npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI
60-
chmod +x npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI
56+
./Scripts/build-waxmcp-binaries.sh "${{ matrix.platform }}" "${{ matrix.triple }}"
6157
6258
- name: Reuse checked-in x64 binary
6359
if: ${{ !matrix.source-build }}
6460
run: |
6561
set -euo pipefail
66-
test -f npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI
67-
chmod +x npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI
62+
./Scripts/build-waxmcp-binaries.sh "${{ matrix.platform }}"
63+
64+
- name: Verify packaged binary
65+
run: |
66+
set -euo pipefail
67+
PLATFORM_DIR="npm/waxmcp/dist/${{ matrix.platform }}"
68+
test -f "$PLATFORM_DIR/WaxCLI"
69+
test -f "$PLATFORM_DIR/WaxCLI.sha256"
70+
if command -v shasum >/dev/null 2>&1; then
71+
shasum -a 256 -c "$PLATFORM_DIR/WaxCLI.sha256"
72+
else
73+
sha256sum -c "$PLATFORM_DIR/WaxCLI.sha256"
74+
fi
75+
76+
- name: Smoke check MCP CLI entrypoint
77+
if: ${{ matrix.source-build }}
78+
run: |
79+
set -euo pipefail
80+
npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI mcp serve --help
6881
6982
- uses: actions/upload-artifact@v4
7083
with:
7184
name: waxmcp-${{ matrix.platform }}
72-
path: npm/waxmcp/dist/${{ matrix.platform }}/WaxCLI
85+
path: npm/waxmcp/dist/${{ matrix.platform }}
7386
if-no-files-found: error
7487

7588
publish:
@@ -109,11 +122,23 @@ jobs:
109122

110123
- name: Verify packaged binaries
111124
run: |
125+
set -euo pipefail
112126
chmod +x npm/waxmcp/dist/darwin-arm64/WaxCLI
113127
test -x npm/waxmcp/dist/darwin-arm64/WaxCLI
114128
chmod +x npm/waxmcp/dist/darwin-x64/WaxCLI
115129
test -x npm/waxmcp/dist/darwin-x64/WaxCLI
116130
131+
- name: Verify package integrity
132+
run: |
133+
set -euo pipefail
134+
if command -v shasum >/dev/null 2>&1; then
135+
shasum -a 256 -c "npm/waxmcp/dist/darwin-arm64/WaxCLI.sha256"
136+
shasum -a 256 -c "npm/waxmcp/dist/darwin-x64/WaxCLI.sha256"
137+
else
138+
sha256sum -c "npm/waxmcp/dist/darwin-arm64/WaxCLI.sha256"
139+
sha256sum -c "npm/waxmcp/dist/darwin-x64/WaxCLI.sha256"
140+
fi
141+
117142
- name: Verify version consistency
118143
run: |
119144
set -euo pipefail

Sources/WaxMCPServer/WaxMCPTools.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ enum WaxMCPTools {
2626
}
2727

2828
_ = await server.withMethodHandler(CallTool.self) { params in
29-
await handleCall(params: params, memory: memory)
29+
await handleCall(params: params, memory: memory, structuredMemoryEnabled: structuredMemoryEnabled)
3030
}
3131
}
3232

3333
static func handleCall(
3434
params: CallTool.Parameters,
35-
memory: MemoryOrchestrator
35+
memory: MemoryOrchestrator,
36+
structuredMemoryEnabled: Bool = true
3637
) async -> CallTool.Result {
3738
do {
3839
switch params.name {
@@ -54,16 +55,25 @@ enum WaxMCPTools {
5455
return try await handoff(arguments: params.arguments, memory: memory)
5556
case "wax_handoff_latest":
5657
return try await handoffLatest(arguments: params.arguments, memory: memory)
57-
case "wax_entity_upsert":
58+
case "wax_entity_upsert" where structuredMemoryEnabled:
5859
return try await entityUpsert(arguments: params.arguments, memory: memory)
59-
case "wax_fact_assert":
60+
case "wax_fact_assert" where structuredMemoryEnabled:
6061
return try await factAssert(arguments: params.arguments, memory: memory)
61-
case "wax_fact_retract":
62+
case "wax_fact_retract" where structuredMemoryEnabled:
6263
return try await factRetract(arguments: params.arguments, memory: memory)
63-
case "wax_facts_query":
64+
case "wax_facts_query" where structuredMemoryEnabled:
6465
return try await factsQuery(arguments: params.arguments, memory: memory)
65-
case "wax_entity_resolve":
66+
case "wax_entity_resolve" where structuredMemoryEnabled:
6667
return try await entityResolve(arguments: params.arguments, memory: memory)
68+
case "wax_entity_upsert",
69+
"wax_fact_assert",
70+
"wax_fact_retract",
71+
"wax_facts_query",
72+
"wax_entity_resolve":
73+
return errorResult(
74+
message: "tool '\(params.name)' requires structured memory to be enabled",
75+
code: "feature_disabled"
76+
)
6777
default:
6878
return errorResult(
6979
message: "Unknown tool '\(params.name)'.",

Sources/WaxMCPServer/main.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,19 @@ struct WaxMCPServerCommand: ParsableCommand {
7070
memoryConfig.rag.searchMode = .textOnly
7171
}
7272

73+
let activeToolNames = ToolSchemas.tools(structuredMemoryEnabled: memoryConfig.enableStructuredMemory)
74+
.map(\.name)
75+
76+
let embedderStatus = memoryConfig.enableVectorSearch ? "miniLM" : "text-only"
7377
writeStderr(
74-
"WaxMCPServer features: " +
75-
"structured_memory=\(memoryConfig.enableStructuredMemory) " +
76-
"access_stats_scoring=\(memoryConfig.enableAccessStatsScoring) " +
77-
"license_validation=\(licenseEnabled) " +
78-
"vector_search=\(memoryConfig.enableVectorSearch)"
78+
"WaxMCPServer config: store=\"\(memoryURL.path)\" " +
79+
"structuredMemory=\(memoryConfig.enableStructuredMemory) " +
80+
"accessStatsScoring=\(memoryConfig.enableAccessStatsScoring) " +
81+
"licenseValidation=\(licenseEnabled) " +
82+
"vectorSearch=\(memoryConfig.enableVectorSearch) " +
83+
"embedder=\(embedderStatus)"
7984
)
85+
writeStderr("WaxMCPServer toolset: \(activeToolNames.joined(separator: \",\"))")
8086

8187
let memory = try await MemoryOrchestrator(
8288
at: memoryURL,
@@ -85,12 +91,12 @@ struct WaxMCPServerCommand: ParsableCommand {
8591
)
8692

8793
// SYNC: keep this version in sync with npm/waxmcp/package.json "version"
88-
let serverVersion = "0.1.5"
94+
let serverVersion = "0.1.6"
8995
writeStderr("WaxMCPServer v\(serverVersion) starting")
9096
let server = Server(
9197
name: "WaxMCPServer",
9298
version: serverVersion,
93-
instructions: "Use these tools to store, search, and recall Wax memory.",
99+
instructions: "Use these tools to store, search, and recall Wax memory. Server v\(serverVersion).",
94100
capabilities: .init(tools: .init(listChanged: false)),
95101
configuration: .default
96102
)

Tests/WaxMCPServerTests/WaxMCPServerTests.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ func toolsListContainsExpectedTools() {
2727
#expect(names.count == ToolSchemas.allTools.count)
2828
}
2929

30+
@Test
31+
func toolsListHonorsStructuredMemoryFlag() {
32+
let withStructuredMemory = Set(ToolSchemas.tools(structuredMemoryEnabled: true).map(\.name))
33+
let withoutStructuredMemory = Set(ToolSchemas.tools(structuredMemoryEnabled: false).map(\.name))
34+
#expect(withStructuredMemory.contains("wax_facts_query"))
35+
#expect(!withoutStructuredMemory.contains("wax_facts_query"))
36+
#expect(withStructuredMemory.contains("wax_entity_upsert"))
37+
#expect(!withoutStructuredMemory.contains("wax_entity_upsert"))
38+
#expect(!withoutStructuredMemory.contains("wax_fact_assert"))
39+
}
40+
3041
@Test
3142
func toolSchemaRegression() {
3243
let tools = ToolSchemas.allTools
@@ -158,6 +169,49 @@ func toolsRejectNonIntegralAndOutOfRangeNumericArguments() async throws {
158169
}
159170
}
160171

172+
@Test
173+
func toolsRejectRecallLimitOutOfRange() async throws {
174+
try await withMemory { memory in
175+
let zero = await WaxMCPTools.handleCall(
176+
params: .init(
177+
name: "wax_recall",
178+
arguments: ["query": "actors", "limit": 0]
179+
),
180+
memory: memory,
181+
structuredMemoryEnabled: true
182+
)
183+
#expect(zero.isError == true)
184+
#expect(firstText(in: zero).contains("limit must be between 1 and"))
185+
186+
let tooHigh = await WaxMCPTools.handleCall(
187+
params: .init(
188+
name: "wax_recall",
189+
arguments: ["query": "actors", "limit": 101]
190+
),
191+
memory: memory,
192+
structuredMemoryEnabled: true
193+
)
194+
#expect(tooHigh.isError == true)
195+
#expect(firstText(in: tooHigh).contains("limit must be between 1 and"))
196+
}
197+
}
198+
199+
@Test
200+
func toolsBlockStructuredMemoryOnlyToolsWhenDisabled() async throws {
201+
try await withMemory { memory in
202+
let result = await WaxMCPTools.handleCall(
203+
params: .init(
204+
name: "wax_facts_query",
205+
arguments: ["subject": "agent:codex", "limit": 10]
206+
),
207+
memory: memory,
208+
structuredMemoryEnabled: false
209+
)
210+
#expect(result.isError == true)
211+
#expect(firstText(in: result).contains("structured memory"))
212+
}
213+
}
214+
161215
@Test
162216
func unknownToolReturnsErrorResult() async throws {
163217
try await withMemory { memory in

npm/waxmcp/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@ npm version patch # or minor/major/1.2.3
1616
npm publish --access public
1717
```
1818

19+
This repo also ships a release script that updates `version`, syncs
20+
`Sources/WaxMCPServer/main.swift`'s `serverVersion`, and rebuilds both Darwin binaries:
21+
22+
```bash
23+
cd /path/to/Wax
24+
./Scripts/release-waxmcp.sh patch # or minor / major / 1.2.3
25+
git add npm/waxmcp/package.json Sources/WaxMCPServer/main.swift npm/waxmcp/dist/darwin-*/WaxCLI npm/waxmcp/dist/darwin-*/WaxCLI.sha256
26+
git commit -m "release: bump waxmcp version"
27+
```
28+
29+
`package.json` and `Sources/WaxMCPServer/main.swift` are required to stay in lockstep; the release
30+
workflow checks this before publishing.
31+
32+
Artifacts are packaged with `WaxCLI.sha256` checksums generated by the release scripts for each
33+
platform binary.
34+
1935
By default, the launcher uses this order:
2036

2137
1. `$WAX_CLI_BIN`
-2.08 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
b5356c11681eddd9f4130468c50efea503afe9548ca8952f01db2d2df6fdca42 /Users/chriskarani/CodingProjects/AIStack/Wax/npm/waxmcp/dist/darwin-arm64/WaxCLI
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
299ffb2c2a08a4ee9d4a8441f61bb5bfd14aa18ec36f8fe3794441038c3fce03 /Users/chriskarani/CodingProjects/AIStack/Wax/npm/waxmcp/dist/darwin-x64/WaxCLI

npm/waxmcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "waxmcp",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"description": "npx launcher for the Wax MCP server",
55
"repository": {
66
"type": "git",

scripts/build-waxmcp-binaries.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
PLATFORM=""
5+
TRIPLE=""
6+
7+
usage() {
8+
echo "Usage: $0 <platform> [<triple>|--triple <triple>]" >&2
9+
}
10+
11+
if [[ $# -lt 1 ]]; then
12+
usage
13+
exit 64
14+
fi
15+
16+
PLATFORM="$1"
17+
shift
18+
19+
if [[ $# -gt 0 ]]; then
20+
case "$1" in
21+
--triple)
22+
if [[ $# -lt 2 ]]; then
23+
usage
24+
exit 64
25+
fi
26+
TRIPLE="$2"
27+
shift 2
28+
;;
29+
*)
30+
TRIPLE="$1"
31+
shift
32+
;;
33+
esac
34+
fi
35+
36+
if [[ $# -ne 0 ]]; then
37+
usage
38+
exit 64
39+
fi
40+
41+
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
42+
DIST_DIR="$PROJECT_ROOT/npm/waxmcp/dist/$PLATFORM"
43+
BIN_PATH="$DIST_DIR/WaxCLI"
44+
45+
mkdir -p "$DIST_DIR"
46+
47+
if [[ -n "$TRIPLE" ]]; then
48+
swift build --product WaxCLI --traits MCPServer --configuration release --triple "$TRIPLE"
49+
LOCAL_BIN_PATH="$(swift build --product WaxCLI --traits MCPServer --configuration release --triple "$TRIPLE" --show-bin-path)"
50+
cp "$LOCAL_BIN_PATH/WaxCLI" "$BIN_PATH"
51+
else
52+
if [[ ! -f "$BIN_PATH" ]]; then
53+
echo "ERROR: expected checked-in WaxCLI at $BIN_PATH but it does not exist." >&2
54+
echo "Rebuild with a matching triple or copy the binary first." >&2
55+
exit 1
56+
fi
57+
fi
58+
59+
chmod +x "$BIN_PATH"
60+
61+
echo "Created $BIN_PATH"
62+
63+
if command -v shasum >/dev/null 2>&1; then
64+
shasum -a 256 "$BIN_PATH" > "$BIN_PATH.sha256"
65+
else
66+
sha256sum "$BIN_PATH" > "$BIN_PATH.sha256"
67+
fi
68+
69+
echo "Wrote $BIN_PATH.sha256"

0 commit comments

Comments
 (0)