Skip to content

Commit 37fd676

Browse files
authored
Merge pull request #1 from asklar/copilot/update-mcpb-net-tool
Add Windows static_responses support to MCPB .NET tool
2 parents c36b933 + f9b6076 commit 37fd676

7 files changed

Lines changed: 787 additions & 7 deletions

File tree

.github/workflows/test-dotnet.yml

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
name: Test .NET Tool
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
- user/asklar/dotnet
8+
paths:
9+
- 'dotnet/**'
10+
- 'examples/**'
11+
- '.github/workflows/test-dotnet.yml'
12+
push:
13+
branches:
14+
- main
15+
- user/asklar/dotnet
16+
paths:
17+
- 'dotnet/**'
18+
- 'examples/**'
19+
- '.github/workflows/test-dotnet.yml'
20+
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
test-dotnet:
26+
name: Test .NET Tool
27+
strategy:
28+
matrix:
29+
os:
30+
- ubuntu-latest
31+
- windows-latest
32+
- macos-latest
33+
runs-on: ${{ matrix.os }}
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
38+
39+
- name: Setup .NET
40+
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
41+
with:
42+
dotnet-version: '8.0.x'
43+
44+
- name: Setup Node.js (for examples)
45+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
46+
with:
47+
node-version: '20.x'
48+
49+
# Step a) Run .NET tests
50+
- name: Run .NET Tests
51+
shell: bash
52+
run: |
53+
cd dotnet
54+
dotnet restore
55+
dotnet build -c Release
56+
dotnet test -c Release --no-build --verbosity normal
57+
58+
# Step b) Validate basic CLI functionality
59+
- name: Test CLI - Help Command
60+
shell: bash
61+
run: |
62+
cd dotnet
63+
dotnet run --project mcpb/mcpb.csproj -- --help
64+
65+
- name: Test CLI - Version Command
66+
shell: bash
67+
run: |
68+
cd dotnet
69+
dotnet run --project mcpb/mcpb.csproj -- --version
70+
71+
# Step c) Test with examples - hello-world-node
72+
- name: Setup hello-world-node Example
73+
shell: bash
74+
run: |
75+
cd examples/hello-world-node
76+
npm install
77+
78+
- name: Test CLI - Validate hello-world-node Manifest
79+
shell: bash
80+
run: |
81+
cd dotnet
82+
dotnet run --project mcpb/mcpb.csproj -- validate ../examples/hello-world-node/manifest.json
83+
84+
- name: Test CLI - Pack hello-world-node (with update and output)
85+
shell: bash
86+
run: |
87+
cd examples/hello-world-node
88+
echo "=== Original Manifest ==="
89+
cat manifest.json
90+
echo ""
91+
echo "=== Running mcpb pack --update ==="
92+
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . hello-world-test.mcpb --update
93+
echo ""
94+
echo "=== Updated Manifest with _meta ==="
95+
cat manifest.json
96+
echo ""
97+
echo "=== Verifying _meta field was added ==="
98+
if grep -q '"_meta"' manifest.json; then
99+
echo "✓ _meta field found in manifest"
100+
else
101+
echo "✗ _meta field NOT found in manifest"
102+
exit 1
103+
fi
104+
echo ""
105+
echo "=== Verifying static_responses ==="
106+
if grep -q '"static_responses"' manifest.json; then
107+
echo "✓ static_responses found in manifest"
108+
else
109+
echo "✗ static_responses NOT found in manifest"
110+
exit 1
111+
fi
112+
echo ""
113+
echo "=== Verifying inputSchema is present in tools/list ==="
114+
if grep -q '"inputSchema"' manifest.json; then
115+
echo "✓ inputSchema found in manifest"
116+
echo ""
117+
echo "=== Extracting tool schema from _meta ==="
118+
cat manifest.json | grep -A 50 '"tools/list"' | head -50
119+
else
120+
echo "✗ inputSchema NOT found in manifest"
121+
exit 1
122+
fi
123+
echo ""
124+
echo "=== Verifying initialize response with protocolVersion ==="
125+
if grep -q '"protocolVersion"' manifest.json; then
126+
echo "✓ protocolVersion found"
127+
echo ""
128+
echo "=== Initialize response ==="
129+
cat manifest.json | grep -A 20 '"initialize"' | head -20
130+
else
131+
echo "✗ protocolVersion NOT found"
132+
exit 1
133+
fi
134+
135+
# Test with file-system-node example
136+
- name: Setup file-system-node Example
137+
shell: bash
138+
run: |
139+
cd examples/file-system-node
140+
npm install
141+
142+
- name: Test CLI - Validate file-system-node Manifest
143+
shell: bash
144+
run: |
145+
cd dotnet
146+
dotnet run --project mcpb/mcpb.csproj -- validate ../examples/file-system-node/manifest.json
147+
148+
- name: Test CLI - Pack file-system-node (no update)
149+
shell: bash
150+
run: |
151+
cd examples/file-system-node
152+
echo "=== Testing pack without --update ==="
153+
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . file-system-test.mcpb --force || true
154+
echo ""
155+
echo "=== Manifest (should be unchanged) ==="
156+
cat manifest.json
157+
158+
- name: Test CLI - Update file-system-node with schema discovery
159+
shell: bash
160+
run: |
161+
cd examples/file-system-node
162+
echo "=== File-system-node example requires allowed_directories argument ==="
163+
echo "=== Temporarily modifying manifest to include test directory ==="
164+
cp manifest.json manifest.json.backup
165+
TEST_DIR="$(cd .. && pwd)"
166+
echo "Using test directory: $TEST_DIR"
167+
jq --arg dir "$TEST_DIR" '.server.mcp_config.args = ["${__dirname}/server/index.js", $dir]' manifest.json > manifest.json.tmp && mv manifest.json.tmp manifest.json
168+
echo ""
169+
echo "=== Running mcpb pack --update to discover schemas ==="
170+
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . /tmp/fs-test.mcpb --update || echo "Pack may have warnings"
171+
echo ""
172+
echo "=== FULL UPDATED MANIFEST ==="
173+
cat manifest.json | jq .
174+
echo ""
175+
echo "=== Verifying _meta field exists ==="
176+
if [ "$(cat manifest.json | jq -r '._meta | type')" = "object" ]; then
177+
echo "✓ _meta field is present and is an object"
178+
else
179+
echo "✗ _meta field NOT found or not an object"
180+
mv manifest.json.backup manifest.json
181+
exit 1
182+
fi
183+
echo ""
184+
echo "=== Verifying com.microsoft.windows in _meta ==="
185+
if [ "$(cat manifest.json | jq -r '._meta["com.microsoft.windows"] | type')" = "object" ]; then
186+
echo "✓ com.microsoft.windows field is present"
187+
else
188+
echo "✗ com.microsoft.windows field NOT found"
189+
mv manifest.json.backup manifest.json
190+
exit 1
191+
fi
192+
echo ""
193+
echo "=== Verifying static_responses in com.microsoft.windows ==="
194+
if [ "$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses | type')" = "object" ]; then
195+
echo "✓ static_responses field is present"
196+
else
197+
echo "✗ static_responses field NOT found"
198+
mv manifest.json.backup manifest.json
199+
exit 1
200+
fi
201+
echo ""
202+
echo "=== Verifying protocolVersion in initialize response ==="
203+
PROTOCOL_VERSION=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses.initialize.protocolVersion')
204+
if [ "$PROTOCOL_VERSION" != "null" ] && [ -n "$PROTOCOL_VERSION" ]; then
205+
echo "✓ protocolVersion found: $PROTOCOL_VERSION"
206+
else
207+
echo "✗ protocolVersion NOT found"
208+
mv manifest.json.backup manifest.json
209+
exit 1
210+
fi
211+
echo ""
212+
echo "=== Verifying tools/list has tools array ==="
213+
TOOLS_COUNT=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses["tools/list"].tools | length')
214+
if [ "$TOOLS_COUNT" -gt 0 ]; then
215+
echo "✓ tools/list contains $TOOLS_COUNT tools"
216+
else
217+
echo "✗ tools/list does not contain any tools"
218+
mv manifest.json.backup manifest.json
219+
exit 1
220+
fi
221+
echo ""
222+
echo "=== Verifying inputSchema for read_file tool ==="
223+
READ_FILE_SCHEMA=$(cat manifest.json | jq '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "read_file") | .inputSchema')
224+
if [ "$READ_FILE_SCHEMA" != "null" ] && [ -n "$READ_FILE_SCHEMA" ]; then
225+
echo "✓ inputSchema found for read_file"
226+
echo "$READ_FILE_SCHEMA" | jq .
227+
else
228+
echo "✗ inputSchema NOT found for read_file"
229+
mv manifest.json.backup manifest.json
230+
exit 1
231+
fi
232+
echo ""
233+
echo "=== Verifying inputSchema has required 'path' property for read_file ==="
234+
HAS_PATH=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "read_file") | .inputSchema.properties.path | type')
235+
if [ "$HAS_PATH" = "object" ]; then
236+
echo "✓ read_file inputSchema has 'path' property"
237+
else
238+
echo "✗ read_file inputSchema missing 'path' property"
239+
mv manifest.json.backup manifest.json
240+
exit 1
241+
fi
242+
echo ""
243+
echo "=== Verifying inputSchema for write_file tool ==="
244+
WRITE_FILE_SCHEMA=$(cat manifest.json | jq '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "write_file") | .inputSchema')
245+
if [ "$WRITE_FILE_SCHEMA" != "null" ] && [ -n "$WRITE_FILE_SCHEMA" ]; then
246+
echo "✓ inputSchema found for write_file"
247+
echo "$WRITE_FILE_SCHEMA" | jq .
248+
else
249+
echo "✗ inputSchema NOT found for write_file"
250+
mv manifest.json.backup manifest.json
251+
exit 1
252+
fi
253+
echo ""
254+
echo "=== Restoring original manifest ==="
255+
mv manifest.json.backup manifest.json
256+
257+
# Test init command
258+
- name: Test CLI - Init Command
259+
shell: bash
260+
run: |
261+
cd dotnet
262+
mkdir -p ../test-init
263+
cd ../test-init
264+
echo "=== Testing mcpb init ==="
265+
dotnet run --project ../dotnet/mcpb/mcpb.csproj -- init --yes --server-type node --entry-point server/index.js
266+
echo ""
267+
echo "=== Generated Manifest ==="
268+
cat manifest.json
269+
echo ""
270+
echo "=== Verifying manifest was created ==="
271+
if [ -f manifest.json ]; then
272+
echo "✓ manifest.json created"
273+
else
274+
echo "✗ manifest.json NOT created"
275+
exit 1
276+
fi
277+
278+
# Clean up test artifacts
279+
- name: Cleanup
280+
if: always()
281+
shell: bash
282+
run: |
283+
cd examples/hello-world-node
284+
git checkout manifest.json || true
285+
rm -f hello-world-test.mcpb || true
286+
cd ../file-system-node
287+
git checkout manifest.json || true
288+
rm -f file-system-test.mcpb file-system-schema-test.mcpb || true
289+
cd ../../
290+
rm -rf test-init || true

0 commit comments

Comments
 (0)