mirror of
https://github.com/BloopAI/dev-manager-mcp.git
synced 2026-08-23 11:58:33 +00:00
Implement CI and build releases (vibe-kanban 2ef3e91a)
Implement CI and build releases Please copy the pre-release and logic that allows us to use JS + NPX to distribute the rust binary, with code signing on mac. You can view some examples in a different repo at /Users/lkw/Documents/repos/vibe-kanban - .github/workflows/pre-release.yml - .github/workflows/publish.yml - npx-cli/bin/cli.js - npx-cli/package.json
This commit is contained in:
36
.github/workflows/pre-release.yml
vendored
36
.github/workflows/pre-release.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
||||
- name: Determine and update versions
|
||||
id: version
|
||||
run: |
|
||||
latest_npm_version=$(npm view mcp-dev-manager version 2>/dev/null || echo "0.0.0")
|
||||
latest_npm_version=$(npm view dev-manager-mcp version 2>/dev/null || echo "0.0.0")
|
||||
echo "Latest npm version: $latest_npm_version"
|
||||
|
||||
timestamp=$(date +%Y%m%d%H%M%S)
|
||||
@@ -168,9 +168,9 @@ jobs:
|
||||
run: |
|
||||
mkdir -p dist
|
||||
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
|
||||
cp target/${{ matrix.target }}/release/mcp-dev-manager.exe dist/mcp-dev-manager-${{ matrix.name }}.exe
|
||||
cp target/${{ matrix.target }}/release/dev-manager-mcp.exe dist/dev-manager-mcp-${{ matrix.name }}.exe
|
||||
else
|
||||
cp target/${{ matrix.target }}/release/mcp-dev-manager dist/mcp-dev-manager-${{ matrix.name }}
|
||||
cp target/${{ matrix.target }}/release/dev-manager-mcp dist/dev-manager-mcp-${{ matrix.name }}
|
||||
fi
|
||||
|
||||
- name: Prepare Apple certificate (macOS)
|
||||
@@ -182,8 +182,8 @@ jobs:
|
||||
if: runner.os == 'macOS'
|
||||
uses: indygreg/apple-code-sign-action@v1
|
||||
with:
|
||||
input_path: target/${{ matrix.target }}/release/mcp-dev-manager
|
||||
output_path: mcp-dev-manager
|
||||
input_path: target/${{ matrix.target }}/release/dev-manager-mcp
|
||||
output_path: dev-manager-mcp
|
||||
p12_file: certificate.p12
|
||||
p12_password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
sign: true
|
||||
@@ -191,13 +191,13 @@ jobs:
|
||||
|
||||
- name: Package binary (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: zip mcp-dev-manager.zip mcp-dev-manager
|
||||
run: zip dev-manager-mcp.zip dev-manager-mcp
|
||||
|
||||
- name: Prepare signed binaries (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
mkdir -p dist
|
||||
cp mcp-dev-manager.zip dist/mcp-dev-manager-${{ matrix.name }}.zip
|
||||
cp dev-manager-mcp.zip dist/dev-manager-mcp-${{ matrix.name }}.zip
|
||||
|
||||
- name: Clean up certificates (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
@@ -218,22 +218,22 @@ jobs:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
name: linux-x64
|
||||
binary: mcp-dev-manager
|
||||
binary: dev-manager-mcp
|
||||
- target: x86_64-pc-windows-msvc
|
||||
name: windows-x64
|
||||
binary: mcp-dev-manager.exe
|
||||
binary: dev-manager-mcp.exe
|
||||
- target: x86_64-apple-darwin
|
||||
name: macos-x64
|
||||
binary: mcp-dev-manager
|
||||
binary: dev-manager-mcp
|
||||
- target: aarch64-apple-darwin
|
||||
name: macos-arm64
|
||||
binary: mcp-dev-manager
|
||||
binary: dev-manager-mcp
|
||||
- target: aarch64-pc-windows-msvc
|
||||
name: windows-arm64
|
||||
binary: mcp-dev-manager.exe
|
||||
binary: dev-manager-mcp.exe
|
||||
- target: aarch64-unknown-linux-musl
|
||||
name: linux-arm64
|
||||
binary: mcp-dev-manager
|
||||
binary: dev-manager-mcp
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -249,17 +249,17 @@ jobs:
|
||||
if: matrix.name != 'macos-arm64' && matrix.name != 'macos-x64'
|
||||
run: |
|
||||
mkdir -p npx-cli/dist/${{ matrix.name }}
|
||||
mkdir mcp-dev-manager-${{ matrix.name }}
|
||||
mkdir dev-manager-mcp-${{ matrix.name }}
|
||||
|
||||
cp dist/mcp-dev-manager-${{ matrix.name }}* mcp-dev-manager-${{ matrix.name }}/${{ matrix.binary }}
|
||||
cp dist/dev-manager-mcp-${{ matrix.name }}* dev-manager-mcp-${{ matrix.name }}/${{ matrix.binary }}
|
||||
|
||||
zip -j npx-cli/dist/${{ matrix.name }}/mcp-dev-manager.zip mcp-dev-manager-${{ matrix.name }}/${{ matrix.binary }}
|
||||
zip -j npx-cli/dist/${{ matrix.name }}/dev-manager-mcp.zip dev-manager-mcp-${{ matrix.name }}/${{ matrix.binary }}
|
||||
|
||||
- name: Create platform package (macOS)
|
||||
if: matrix.name == 'macos-arm64' || matrix.name == 'macos-x64'
|
||||
run: |
|
||||
mkdir -p npx-cli/dist/${{ matrix.name }}
|
||||
cp dist/mcp-dev-manager-${{ matrix.name }}* npx-cli/dist/${{ matrix.name }}/mcp-dev-manager.zip
|
||||
cp dist/dev-manager-mcp-${{ matrix.name }}* npx-cli/dist/${{ matrix.name }}/dev-manager-mcp.zip
|
||||
|
||||
- name: Upload platform package artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -301,4 +301,4 @@ jobs:
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
npx-cli/mcp-dev-manager-*.tgz
|
||||
npx-cli/dev-manager-mcp-*.tgz
|
||||
|
||||
32
Cargo.lock
generated
32
Cargo.lock
generated
@@ -289,6 +289,22 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dev-manager-mcp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"clap",
|
||||
"libc",
|
||||
"rand 0.8.5",
|
||||
"rmcp",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
@@ -767,22 +783,6 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||
|
||||
[[package]]
|
||||
name = "mcp-dev-manager"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"clap",
|
||||
"libc",
|
||||
"rand 0.8.5",
|
||||
"rmcp",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "mcp-dev-manager"
|
||||
name = "dev-manager-mcp"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "mcp-dev-manager"
|
||||
name = "dev-manager-mcp"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
||||
20
README.md
20
README.md
@@ -17,7 +17,7 @@ A daemon process that runs continuously and accepts multiple concurrent MCP clie
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The binary will be at `target/release/mcp-dev-manager`.
|
||||
The binary will be at `target/release/dev-manager-mcp`.
|
||||
|
||||
## Running
|
||||
|
||||
@@ -25,17 +25,17 @@ The binary will be at `target/release/mcp-dev-manager`.
|
||||
|
||||
```bash
|
||||
# Foreground (default mode)
|
||||
./target/release/mcp-dev-manager
|
||||
./target/release/dev-manager-mcp
|
||||
# or explicitly:
|
||||
./target/release/mcp-dev-manager daemon
|
||||
./target/release/dev-manager-mcp daemon
|
||||
|
||||
# Background
|
||||
./target/release/mcp-dev-manager daemon &
|
||||
./target/release/dev-manager-mcp daemon &
|
||||
|
||||
# Custom port
|
||||
./target/release/mcp-dev-manager daemon --port 3010
|
||||
./target/release/dev-manager-mcp daemon --port 3010
|
||||
# or via environment variable:
|
||||
PORT=3010 ./target/release/mcp-dev-manager daemon
|
||||
PORT=3010 ./target/release/dev-manager-mcp daemon
|
||||
```
|
||||
|
||||
The daemon will listen on `http://127.0.0.1:3009` by default.
|
||||
@@ -50,7 +50,7 @@ For Claude Desktop (`claude_desktop_config.json`):
|
||||
{
|
||||
"mcpServers": {
|
||||
"dev-manager": {
|
||||
"command": "mcp-dev-manager",
|
||||
"command": "dev-manager-mcp",
|
||||
"args": ["stdio"]
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ The STDIO proxy connects to the daemon at `http://127.0.0.1:3009/sse` by default
|
||||
{
|
||||
"mcpServers": {
|
||||
"dev-manager": {
|
||||
"command": "mcp-dev-manager",
|
||||
"command": "dev-manager-mcp",
|
||||
"args": ["stdio", "--daemon-url", "http://127.0.0.1:3010/sse"]
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ Or use the environment variable:
|
||||
{
|
||||
"mcpServers": {
|
||||
"dev-manager": {
|
||||
"command": "mcp-dev-manager",
|
||||
"command": "dev-manager-mcp",
|
||||
"args": ["stdio"],
|
||||
"env": {
|
||||
"MCP_DAEMON_URL": "http://127.0.0.1:3009/sse"
|
||||
@@ -207,7 +207,7 @@ Get stdout/stderr logs for a development server session.
|
||||
|
||||
## Testing Multi-Client Behavior
|
||||
|
||||
1. Start daemon: `./target/release/mcp-dev-manager`
|
||||
1. Start daemon: `./target/release/dev-manager-mcp`
|
||||
2. Connect Client A and start a server session
|
||||
3. Connect Client B and query status - should see Client A's session
|
||||
4. Client B can stop Client A's session
|
||||
|
||||
@@ -56,7 +56,7 @@ function getPlatformDir() {
|
||||
}
|
||||
|
||||
function getBinaryName() {
|
||||
return platform === "win32" ? "mcp-dev-manager.exe" : "mcp-dev-manager";
|
||||
return platform === "win32" ? "dev-manager-mcp.exe" : "dev-manager-mcp";
|
||||
}
|
||||
|
||||
const platformDir = getPlatformDir();
|
||||
@@ -67,7 +67,7 @@ fs.mkdirSync(extractDir, { recursive: true });
|
||||
function extractAndRun() {
|
||||
const binName = getBinaryName();
|
||||
const binPath = path.join(extractDir, binName);
|
||||
const zipName = "mcp-dev-manager.zip";
|
||||
const zipName = "dev-manager-mcp.zip";
|
||||
const zipPath = path.join(extractDir, zipName);
|
||||
|
||||
if (fs.existsSync(binPath)) fs.unlinkSync(binPath);
|
||||
@@ -82,8 +82,8 @@ function extractAndRun() {
|
||||
const zip = new AdmZip(zipPath);
|
||||
zip.extractAllTo(extractDir, true);
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to extract mcp-dev-manager archive:", err.message);
|
||||
if (process.env.MCP_DEV_MANAGER_DEBUG) {
|
||||
console.error("❌ Failed to extract dev-manager-mcp archive:", err.message);
|
||||
if (process.env.DEV_MANAGER_MCP_DEBUG) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
@@ -101,14 +101,14 @@ function extractAndRun() {
|
||||
} catch { }
|
||||
}
|
||||
|
||||
console.log(`🚀 Launching mcp-dev-manager...`);
|
||||
console.log(`🚀 Launching dev-manager-mcp...`);
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const proc = spawn(binPath, args, { stdio: "inherit" });
|
||||
|
||||
proc.on("exit", (code) => process.exit(code || 0));
|
||||
proc.on("error", (err) => {
|
||||
console.error("❌ Failed to start mcp-dev-manager:", err.message);
|
||||
console.error("❌ Failed to start dev-manager-mcp:", err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
||||
31
npx-cli/package-lock.json
generated
Normal file
31
npx-cli/package-lock.json
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "dev-manager-mcp",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "dev-manager-mcp",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.5.16"
|
||||
},
|
||||
"bin": {
|
||||
"dev-manager-mcp": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/adm-zip": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
|
||||
"integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "mcp-dev-manager",
|
||||
"name": "dev-manager-mcp",
|
||||
"private": false,
|
||||
"version": "0.1.0",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
"mcp-dev-manager": "bin/cli.js"
|
||||
"dev-manager-mcp": "bin/cli.js"
|
||||
},
|
||||
"keywords": [
|
||||
"mcp",
|
||||
|
||||
52
scripts/README.md
Normal file
52
scripts/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Manual Release Scripts
|
||||
|
||||
## manual-release.sh
|
||||
|
||||
Creates a single-platform npm package for testing or manual publishing.
|
||||
|
||||
### Usage
|
||||
|
||||
```bash
|
||||
./scripts/manual-release.sh
|
||||
```
|
||||
|
||||
This script will:
|
||||
1. Detect your current platform (macOS/Linux/Windows, x64/ARM64)
|
||||
2. Install the Rust target if needed
|
||||
3. Build the release binary
|
||||
4. Create the dist structure
|
||||
5. Zip the binary
|
||||
6. Install npm dependencies
|
||||
7. Create a .tgz package
|
||||
|
||||
### Testing Locally
|
||||
|
||||
After running the script:
|
||||
|
||||
```bash
|
||||
# Install globally to test
|
||||
npm install -g npx-cli/dev-manager-mcp-*.tgz
|
||||
|
||||
# Run it
|
||||
dev-manager-mcp --help
|
||||
|
||||
# Uninstall when done
|
||||
npm uninstall -g dev-manager-mcp
|
||||
```
|
||||
|
||||
### Publishing Manually
|
||||
|
||||
```bash
|
||||
cd npx-cli
|
||||
npm login
|
||||
npm publish dev-manager-mcp-*.tgz --access public
|
||||
```
|
||||
|
||||
### Important Notes
|
||||
|
||||
- This creates a **single-platform** package (only your current platform)
|
||||
- For production releases with **all platforms**, use GitHub Actions
|
||||
- The manual script is useful for:
|
||||
- Local testing before setting up CI/CD
|
||||
- Quick iterations during development
|
||||
- Publishing platform-specific test versions
|
||||
111
scripts/manual-release.sh
Executable file
111
scripts/manual-release.sh
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🚀 Manual Release Script for dev-manager-mcp"
|
||||
echo ""
|
||||
|
||||
# Detect platform
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# Map to our platform naming
|
||||
if [[ "$OS" == "darwin" ]]; then
|
||||
if [[ "$ARCH" == "arm64" ]]; then
|
||||
PLATFORM="macos-arm64"
|
||||
TARGET="aarch64-apple-darwin"
|
||||
else
|
||||
PLATFORM="macos-x64"
|
||||
TARGET="x86_64-apple-darwin"
|
||||
fi
|
||||
BINARY_NAME="dev-manager-mcp"
|
||||
elif [[ "$OS" == "linux" ]]; then
|
||||
if [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
|
||||
PLATFORM="linux-arm64"
|
||||
TARGET="aarch64-unknown-linux-musl"
|
||||
else
|
||||
PLATFORM="linux-x64"
|
||||
TARGET="x86_64-unknown-linux-musl"
|
||||
fi
|
||||
BINARY_NAME="dev-manager-mcp"
|
||||
elif [[ "$OS" =~ "mingw" || "$OS" =~ "msys" || "$OS" =~ "cygwin" ]]; then
|
||||
if [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
|
||||
PLATFORM="windows-arm64"
|
||||
TARGET="aarch64-pc-windows-msvc"
|
||||
else
|
||||
PLATFORM="windows-x64"
|
||||
TARGET="x86_64-pc-windows-msvc"
|
||||
fi
|
||||
BINARY_NAME="dev-manager-mcp.exe"
|
||||
else
|
||||
echo "❌ Unsupported platform: $OS-$ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Detected platform: $PLATFORM"
|
||||
echo "🎯 Target: $TARGET"
|
||||
echo ""
|
||||
|
||||
# Check if rustup target is installed
|
||||
if ! rustup target list --installed | grep -q "$TARGET"; then
|
||||
echo "📥 Installing Rust target: $TARGET"
|
||||
rustup target add "$TARGET"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Build the binary
|
||||
echo "🔨 Building release binary..."
|
||||
cargo build --release --target "$TARGET"
|
||||
echo ""
|
||||
|
||||
# Create npx-cli dist structure
|
||||
echo "📁 Creating dist structure..."
|
||||
mkdir -p npx-cli/dist/"$PLATFORM"
|
||||
echo ""
|
||||
|
||||
# Copy and zip the binary
|
||||
BINARY_PATH="target/$TARGET/release/$BINARY_NAME"
|
||||
if [[ ! -f "$BINARY_PATH" ]]; then
|
||||
echo "❌ Binary not found at: $BINARY_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Zipping binary..."
|
||||
if command -v zip &> /dev/null; then
|
||||
zip -j npx-cli/dist/"$PLATFORM"/dev-manager-mcp.zip "$BINARY_PATH"
|
||||
else
|
||||
echo "❌ 'zip' command not found. Please install zip."
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Install npm dependencies if needed
|
||||
if [[ ! -d "npx-cli/node_modules" ]]; then
|
||||
echo "📥 Installing npm dependencies..."
|
||||
cd npx-cli
|
||||
npm install
|
||||
cd ..
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Pack the npm package
|
||||
echo "📦 Creating npm package..."
|
||||
cd npx-cli
|
||||
npm pack
|
||||
cd ..
|
||||
echo ""
|
||||
|
||||
# Find the created tarball
|
||||
TARBALL=$(ls npx-cli/dev-manager-mcp-*.tgz | head -n1)
|
||||
|
||||
echo "✅ Package created successfully!"
|
||||
echo ""
|
||||
echo "📦 Package: $TARBALL"
|
||||
echo "🏷️ Platform: $PLATFORM"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Test locally: npm install -g $TARBALL"
|
||||
echo " 2. Login to npm: cd npx-cli && npm login"
|
||||
echo " 3. Publish: npm publish --access public"
|
||||
echo ""
|
||||
echo "⚠️ Note: This package only contains the $PLATFORM binary."
|
||||
echo " For multi-platform support, use GitHub Actions CI/CD."
|
||||
@@ -1,7 +1,7 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "mcp-dev-manager")]
|
||||
#[command(name = "dev-manager-mcp")]
|
||||
#[command(about = "MCP development server manager with shared session state")]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
@@ -31,7 +31,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command.unwrap_or(Command::Daemon { port: 3009 }) {
|
||||
Command::Daemon { port } => mcp_dev_manager::run_daemon(port).await,
|
||||
Command::Stdio { daemon_url } => mcp_dev_manager::run_stdio_proxy(&daemon_url).await,
|
||||
Command::Daemon { port } => dev_manager_mcp::run_daemon(port).await,
|
||||
Command::Stdio { daemon_url } => dev_manager_mcp::run_stdio_proxy(&daemon_url).await,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user