Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
eca81ec
Add .NET CLI implementation
asklar Sep 20, 2025
48b577c
Configure .NET tool for NuGet publishing
asklar Sep 20, 2025
b05feac
update readme
asklar Sep 20, 2025
eb0b94b
Optimize NuGet package size and bump version to 0.1.1
asklar Sep 20, 2025
41f2284
feat: Enhance Pack and Validate commands with dynamic tool discovery …
asklar Oct 5, 2025
ec6b503
fix: Refactor code for improved readability and consistency across mu…
asklar Oct 5, 2025
ef6e52b
0.2.0
asklar Oct 5, 2025
1280f4b
feat: Update validate command to support optional manifest argument a…
asklar Oct 5, 2025
880e8fe
Initial plan
Copilot Oct 12, 2025
ebd5a7c
Add _meta property and Windows static_responses support to .NET tool
Copilot Oct 12, 2025
91d8485
Fix static_responses serialization to use clean JSON structure
Copilot Oct 12, 2025
28ee865
Remove accidentally committed build artifacts from examples
Copilot Oct 12, 2025
23bd699
Use typed responses for initialize and tools/list static responses
Copilot Oct 12, 2025
8ff4d1b
Remove accidentally committed build artifacts
Copilot Oct 12, 2025
d59cd21
Use strongly typed models for static responses and get protocol versi…
Copilot Oct 12, 2025
6d175d6
Remove accidentally committed package-lock.json
Copilot Oct 12, 2025
095b351
Add YAML pipeline to test .NET tool with examples
Copilot Oct 12, 2025
8d374c6
Update .github/workflows/test-dotnet.yml
asklar Oct 12, 2025
7e04790
Fix Windows PowerShell syntax error and add user/asklar/dotnet branch…
Copilot Oct 12, 2025
9dc590c
Fix init command hanging by using --yes flag for non-interactive mode
Copilot Oct 13, 2025
cd2d423
Add CI test verifying inputSchema capture with hello-world example an…
Copilot Oct 13, 2025
8ebe23d
Remove accidentally committed example artifacts
Copilot Oct 13, 2025
8d3365b
Add real CI test for file-system-node with schema discovery using mod…
Copilot Oct 13, 2025
8873c36
Remove accidentally committed example artifacts
Copilot Oct 13, 2025
3b0ab56
Remove package-lock.json from examples
Copilot Oct 13, 2025
0cda640
Improve CI test to print full manifest and use JSON parsing for valid…
Copilot Oct 13, 2025
bfed1a1
Remove accidentally committed artifacts
Copilot Oct 13, 2025
66ddac4
Remove package-lock.json from examples
Copilot Oct 13, 2025
83ed03e
Fix null field serialization in static_responses by filtering at assi…
Copilot Oct 13, 2025
bfac6c3
Remove accidentally committed package-lock.json
Copilot Oct 13, 2025
a311216
Revert example manifest.json files to original state - CI should gene…
Copilot Oct 13, 2025
d0d0902
Revert yarn.lock for hello-world-node example to original state
Copilot Oct 13, 2025
7e51b72
Properly revert yarn.lock to original state before any PR changes
Copilot Oct 13, 2025
7f823f7
Update version to 0.3.0 in mcpb.csproj
asklar Oct 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
290 changes: 290 additions & 0 deletions .github/workflows/test-dotnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
name: Test .NET Tool

on:
pull_request:
branches:
- main
- user/asklar/dotnet
paths:
- 'dotnet/**'
- 'examples/**'
- '.github/workflows/test-dotnet.yml'
push:
branches:
- main
- user/asklar/dotnet
paths:
- 'dotnet/**'
- 'examples/**'
- '.github/workflows/test-dotnet.yml'

permissions:
contents: read

jobs:
test-dotnet:
name: Test .NET Tool
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macos-latest
runs-on: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup .NET
uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0
with:
dotnet-version: '8.0.x'

- name: Setup Node.js (for examples)
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '20.x'

# Step a) Run .NET tests
- name: Run .NET Tests
shell: bash
run: |
cd dotnet
dotnet restore
dotnet build -c Release
dotnet test -c Release --no-build --verbosity normal

# Step b) Validate basic CLI functionality
- name: Test CLI - Help Command
shell: bash
run: |
cd dotnet
dotnet run --project mcpb/mcpb.csproj -- --help

- name: Test CLI - Version Command
shell: bash
run: |
cd dotnet
dotnet run --project mcpb/mcpb.csproj -- --version

# Step c) Test with examples - hello-world-node
- name: Setup hello-world-node Example
shell: bash
run: |
cd examples/hello-world-node
npm install

- name: Test CLI - Validate hello-world-node Manifest
shell: bash
run: |
cd dotnet
dotnet run --project mcpb/mcpb.csproj -- validate ../examples/hello-world-node/manifest.json

- name: Test CLI - Pack hello-world-node (with update and output)
shell: bash
run: |
cd examples/hello-world-node
echo "=== Original Manifest ==="
cat manifest.json
echo ""
echo "=== Running mcpb pack --update ==="
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . hello-world-test.mcpb --update
echo ""
echo "=== Updated Manifest with _meta ==="
cat manifest.json
echo ""
echo "=== Verifying _meta field was added ==="
if grep -q '"_meta"' manifest.json; then
echo "✓ _meta field found in manifest"
else
echo "✗ _meta field NOT found in manifest"
exit 1
fi
echo ""
echo "=== Verifying static_responses ==="
if grep -q '"static_responses"' manifest.json; then
echo "✓ static_responses found in manifest"
else
echo "✗ static_responses NOT found in manifest"
exit 1
fi
echo ""
echo "=== Verifying inputSchema is present in tools/list ==="
if grep -q '"inputSchema"' manifest.json; then
echo "✓ inputSchema found in manifest"
echo ""
echo "=== Extracting tool schema from _meta ==="
cat manifest.json | grep -A 50 '"tools/list"' | head -50
else
echo "✗ inputSchema NOT found in manifest"
exit 1
fi
echo ""
echo "=== Verifying initialize response with protocolVersion ==="
if grep -q '"protocolVersion"' manifest.json; then
echo "✓ protocolVersion found"
echo ""
echo "=== Initialize response ==="
cat manifest.json | grep -A 20 '"initialize"' | head -20
else
echo "✗ protocolVersion NOT found"
exit 1
fi

# Test with file-system-node example
- name: Setup file-system-node Example
shell: bash
run: |
cd examples/file-system-node
npm install

- name: Test CLI - Validate file-system-node Manifest
shell: bash
run: |
cd dotnet
dotnet run --project mcpb/mcpb.csproj -- validate ../examples/file-system-node/manifest.json

- name: Test CLI - Pack file-system-node (no update)
shell: bash
run: |
cd examples/file-system-node
echo "=== Testing pack without --update ==="
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . file-system-test.mcpb --force || true
echo ""
echo "=== Manifest (should be unchanged) ==="
cat manifest.json

- name: Test CLI - Update file-system-node with schema discovery
shell: bash
run: |
cd examples/file-system-node
echo "=== File-system-node example requires allowed_directories argument ==="
echo "=== Temporarily modifying manifest to include test directory ==="
cp manifest.json manifest.json.backup
TEST_DIR="$(cd .. && pwd)"
echo "Using test directory: $TEST_DIR"
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
echo ""
echo "=== Running mcpb pack --update to discover schemas ==="
dotnet run --project ../../dotnet/mcpb/mcpb.csproj -- pack . /tmp/fs-test.mcpb --update || echo "Pack may have warnings"
echo ""
echo "=== FULL UPDATED MANIFEST ==="
cat manifest.json | jq .
echo ""
echo "=== Verifying _meta field exists ==="
if [ "$(cat manifest.json | jq -r '._meta | type')" = "object" ]; then
echo "✓ _meta field is present and is an object"
else
echo "✗ _meta field NOT found or not an object"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying com.microsoft.windows in _meta ==="
if [ "$(cat manifest.json | jq -r '._meta["com.microsoft.windows"] | type')" = "object" ]; then
echo "✓ com.microsoft.windows field is present"
else
echo "✗ com.microsoft.windows field NOT found"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying static_responses in com.microsoft.windows ==="
if [ "$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses | type')" = "object" ]; then
echo "✓ static_responses field is present"
else
echo "✗ static_responses field NOT found"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying protocolVersion in initialize response ==="
PROTOCOL_VERSION=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses.initialize.protocolVersion')
if [ "$PROTOCOL_VERSION" != "null" ] && [ -n "$PROTOCOL_VERSION" ]; then
echo "✓ protocolVersion found: $PROTOCOL_VERSION"
else
echo "✗ protocolVersion NOT found"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying tools/list has tools array ==="
TOOLS_COUNT=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses["tools/list"].tools | length')
if [ "$TOOLS_COUNT" -gt 0 ]; then
echo "✓ tools/list contains $TOOLS_COUNT tools"
else
echo "✗ tools/list does not contain any tools"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying inputSchema for read_file tool ==="
READ_FILE_SCHEMA=$(cat manifest.json | jq '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "read_file") | .inputSchema')
if [ "$READ_FILE_SCHEMA" != "null" ] && [ -n "$READ_FILE_SCHEMA" ]; then
echo "✓ inputSchema found for read_file"
echo "$READ_FILE_SCHEMA" | jq .
else
echo "✗ inputSchema NOT found for read_file"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying inputSchema has required 'path' property for read_file ==="
HAS_PATH=$(cat manifest.json | jq -r '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "read_file") | .inputSchema.properties.path | type')
if [ "$HAS_PATH" = "object" ]; then
echo "✓ read_file inputSchema has 'path' property"
else
echo "✗ read_file inputSchema missing 'path' property"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Verifying inputSchema for write_file tool ==="
WRITE_FILE_SCHEMA=$(cat manifest.json | jq '._meta["com.microsoft.windows"].static_responses["tools/list"].tools[] | select(.name == "write_file") | .inputSchema')
if [ "$WRITE_FILE_SCHEMA" != "null" ] && [ -n "$WRITE_FILE_SCHEMA" ]; then
echo "✓ inputSchema found for write_file"
echo "$WRITE_FILE_SCHEMA" | jq .
else
echo "✗ inputSchema NOT found for write_file"
mv manifest.json.backup manifest.json
exit 1
fi
echo ""
echo "=== Restoring original manifest ==="
mv manifest.json.backup manifest.json

# Test init command
- name: Test CLI - Init Command
shell: bash
run: |
cd dotnet
mkdir -p ../test-init
cd ../test-init
echo "=== Testing mcpb init ==="
dotnet run --project ../dotnet/mcpb/mcpb.csproj -- init --yes --server-type node --entry-point server/index.js
echo ""
echo "=== Generated Manifest ==="
cat manifest.json
echo ""
echo "=== Verifying manifest was created ==="
if [ -f manifest.json ]; then
echo "✓ manifest.json created"
else
echo "✗ manifest.json NOT created"
exit 1
fi

# Clean up test artifacts
- name: Cleanup
if: always()
shell: bash
run: |
cd examples/hello-world-node
git checkout manifest.json || true
rm -f hello-world-test.mcpb || true
cd ../file-system-node
git checkout manifest.json || true
rm -f file-system-test.mcpb file-system-schema-test.mcpb || true
cd ../../
rm -rf test-init || true
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,25 @@ self-signed-key.pem
invalid-json.json
**/server/lib/**

# .NET build artifacts
**/[Bb]in/
**/[Oo]bj/

# StyleCop
StyleCopReport.xml
*.pdb
*.tmp
.vs/**

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload

**/server/lib/**

.yarn/install-state.gz
Loading