Skip to content
Open
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
20 changes: 19 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,28 @@ jobs:
name: Windows-rbx-studio-mcp
path: output/rbx-studio-mcp.exe

build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: |
cargo install cargo-edit
cargo set-version --workspace "$CARGO_PKG_VERSION"
cargo build --release
mkdir -p output
cp target/release/rbx-studio-mcp output/
cd output && zip rbx-studio-mcp-linux.zip rbx-studio-mcp
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: Linux-rbx-studio-mcp
path: output/rbx-studio-mcp-linux.zip

release:
runs-on: ubuntu-latest
if: ${{ github.ref_name == github.event.repository.default_branch }}
needs: [build-macos, build-windows]
needs: [build-macos, build-windows, build-linux]
steps:
- run: mkdir -p output
- uses: actions/download-artifact@v4
Expand Down
42 changes: 38 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::sync::Arc;
use tokio::sync::Mutex;
use tracing_subscriber::{self, EnvFilter};
mod error;
#[cfg(any(target_os = "windows", target_os = "macos"))]
mod install;
mod rbx_studio_server;

Expand All @@ -20,6 +21,10 @@ struct Args {
/// Run as MCP server on stdio
#[arg(short, long)]
stdio: bool,

/// Run HTTP server only (no MCP stdio, for use with /proxy endpoint)
#[arg(long)]
http_only: bool,
}

#[tokio::main]
Expand All @@ -33,19 +38,48 @@ async fn main() -> Result<()> {
.init();

let args = Args::parse();
if !args.stdio {
return install::install().await;
if !args.stdio && !args.http_only {
#[cfg(any(target_os = "windows", target_os = "macos"))]
{
return install::install().await;
}
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
{
eprintln!("Auto-install not supported on Linux.");
eprintln!("Use --stdio for MCP mode or --http-only for HTTP server mode.");
std::process::exit(1);
}
}

tracing::debug!("Debug MCP tracing enabled");

let server_state = Arc::new(Mutex::new(AppState::new()));

let (close_tx, close_rx) = tokio::sync::oneshot::channel();

let listener =
tokio::net::TcpListener::bind((Ipv4Addr::new(127, 0, 0, 1), STUDIO_PLUGIN_PORT)).await;

if args.http_only {
// HTTP-only mode: just run the HTTP server without MCP stdio
if let Ok(listener) = listener {
let app = axum::Router::new()
.route("/request", get(request_handler))
.route("/response", post(response_handler))
.route("/proxy", post(proxy_handler))
.with_state(server_state);
tracing::info!("HTTP-only server listening on port {STUDIO_PLUGIN_PORT}");
eprintln!("MCP HTTP server running on http://127.0.0.1:{STUDIO_PLUGIN_PORT}");
eprintln!("Press Ctrl+C to stop");
axum::serve(listener, app).await.unwrap();
} else {
eprintln!("Error: Port {STUDIO_PLUGIN_PORT} already in use");
std::process::exit(1);
}
return Ok(());
}

// Standard MCP mode with stdio
let (close_tx, close_rx) = tokio::sync::oneshot::channel();

let server_state_clone = Arc::clone(&server_state);
let server_handle = if let Ok(listener) = listener {
let app = axum::Router::new()
Expand Down