Skip to content

Add StdioTransport support for Linux with musl #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
132 changes: 117 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,136 @@ permissions:
pull-requests: write

jobs:
test:
timeout-minutes: 5
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
swift-versions: ${{ steps.set-matrix.outputs.swift-versions }}
env:
SWIFT_VERSIONS: |
6.0.3
6.1.0
steps:
- id: set-matrix
run: |
# Convert multi-line string to JSON array (jq is pre-installed on GitHub runners)
VERSIONS=$(echo "$SWIFT_VERSIONS" | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "swift-versions=$VERSIONS" >> $GITHUB_OUTPUT

test-macos:
name: Test (macOS, Swift ${{ matrix.swift-version }})
needs: setup
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
swift-version:
- 6.0.3
- 6.1.0
swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }}
runs-on: macos-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

runs-on: ${{ matrix.os }}
name: Test (${{ matrix.os }}, Swift ${{ matrix.swift-version }})
- name: Setup Swift
uses: swift-actions/setup-swift@v2
with:
swift-version: ${{ matrix.swift-version }}

- name: Build
run: swift build -v

- name: Run tests
run: swift test -v

test-ubuntu:
name: Test (Ubuntu, Swift ${{ matrix.swift-version }})
needs: setup
strategy:
matrix:
swift-version: ${{ fromJson(needs.setup.outputs.swift-versions) }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4

- name: Setup Swift on Linux
if: matrix.os == 'ubuntu-latest'
- name: Setup Swift
uses: vapor/[email protected]
with:
toolchain: ${{ matrix.swift-version }}
- name: Setup Swift on macOS
if: matrix.os == 'macos-latest'
uses: swift-actions/setup-swift@v2
with:
swift-version: ${{ matrix.swift-version }}

- name: Build
run: swift build -v

- name: Run tests
run: swift test -v

build-for-alpine:
name: Build for Alpine (Ubuntu, Swift 6.1)
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Swift
uses: vapor/[email protected]
with:
toolchain: 6.1.0

- name: Install Static Linux SDK
run: |
# Install the static Linux SDK for musl target
# https://www.swift.org/install/linux/debian/12/#versions
swift sdk install https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 111c6f7d280a651208b8c74c0521dd99365d785c1976a6e23162f55f65379ac6

# Verify installation
swift sdk list

- name: Build for x86_64-musl
run: |
swift build --swift-sdk x86_64-swift-linux-musl -v
swift test --swift-sdk x86_64-swift-linux-musl -v
# List contents to verify test binary location
find .build/x86_64-swift-linux-musl -name "*Test*" -type f | sort
ls -la .build/x86_64-swift-linux-musl/debug

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: alpine-binaries-6.1.0
path: .build/x86_64-swift-linux-musl/debug

test-alpine:
name: Test (Alpine, Swift 6.1)
needs: [setup, build-for-alpine]
runs-on: ubuntu-latest
timeout-minutes: 5
container: alpine:latest
steps:
- uses: actions/checkout@v4

- name: Install system dependencies
run: apk add --no-cache bash

- name: Download compiled binaries
uses: actions/download-artifact@v4
with:
name: alpine-binaries-6.1.0
path: .build/debug

- name: Set permissions
shell: bash
run: |
chmod +x .build/debug/*
ls -la .build/debug

- name: Run tests
shell: bash
run: |
# Try to find and run the test executable
TEST_EXEC=$(find .build/debug -name "*Test*" -type f | head -1)
if [ -n "$TEST_EXEC" ]; then
echo "Running test executable: $TEST_EXEC"
chmod +x "$TEST_EXEC"
$TEST_EXEC
else
echo "Test executable not found!"
ls -la .build/debug
exit 1
fi
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -833,15 +833,13 @@ The Swift SDK has the following platform requirements:
| watchOS | 9.0+ |
| tvOS | 16.0+ |
| visionOS | 1.0+ |
| Linux | Distributions with `glibc` |
| Linux | Distributions with `glibc` or `musl` |

While the core library works on any platform supporting Swift 6
(including Linux and Windows),
running a client or server requires a compatible transport.

We're actively working to expand platform support:
- [Alpine Linux support](https://github.com/modelcontextprotocol/swift-sdk/pull/64)
- [Windows support](https://github.com/modelcontextprotocol/swift-sdk/pull/64)
We're actively working to add [Windows support](https://github.com/modelcontextprotocol/swift-sdk/pull/64).

## Debugging and Logging

Expand Down
6 changes: 5 additions & 1 deletion Sources/MCP/Base/Transports/StdioTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import struct Foundation.Data
import Darwin.POSIX
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Musl)
import Musl
#endif

#if canImport(Darwin) || canImport(Glibc)
#if canImport(Darwin) || canImport(Glibc) || canImport(Musl)
/// An implementation of the MCP stdio transport protocol.
///
/// This transport implements the [stdio transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#stdio)
Expand Down Expand Up @@ -100,6 +102,8 @@ import struct Foundation.Data
Task {
await readLoop()
}

messageContinuation.finish()
}

/// Configures a file descriptor for non-blocking I/O
Expand Down
Loading