Skip to content
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
20 changes: 14 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
env::set_var("DEBUG", "TRUE");
}

// Parse arguments before initializing logging: MCP mode speaks JSON-RPC over
// stdout, so the subscriber has to be pointed at stderr before it writes its
// first line. Anything on stdout that isn't a JSON-RPC message corrupts the
// stream and the client fails to parse the response.
let args = Args::parse();

// Initialize logging with more detailed format
tracing_subscriber::fmt()
let subscriber = tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env()
.add_directive("tinker=debug".parse()?)
.add_directive("wry=debug".parse()?))
.with_file(true)
.with_line_number(true)
.with_thread_ids(true)
.with_target(true)
.init();
.with_target(true);

info!("Starting Tinker Workshop...");
if args.mcp {
subscriber.with_writer(std::io::stderr).init();
} else {
subscriber.init();
}

// Parse command line arguments
let args = Args::parse();
info!("Starting Tinker Workshop...");

// Create broadcast channels for API server or MCP server if enabled
let (api_event_tx, api_event_rx) = if args.api || args.mcp {
Expand Down
28 changes: 12 additions & 16 deletions tests/mcp_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
use serde_json::json;
use std::io::{BufRead, BufReader, Write};
use std::process::{Command, Stdio};
use std::time::Duration;

#[test]
#[ignore] // Ignore by default since it requires building the binary
fn test_mcp_server_initialize() {
let mut child = Command::new("cargo")
.args(&["run", "--", "--mcp", "--url", "https://example.com"])
let mut child = Command::new(env!("CARGO_BIN_EXE_tinker"))
.args(&["--mcp", "--url", "https://example.com"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
Expand All @@ -20,8 +18,8 @@ fn test_mcp_server_initialize() {
let stdout = child.stdout.take().expect("Failed to open stdout");
let mut reader = BufReader::new(stdout);

// Give the server time to start
std::thread::sleep(Duration::from_secs(2));
// No startup wait needed: the binary is already built, and the server reads
// stdin as soon as it starts. The request below simply queues until then.

// Send initialize request
let request = json!({
Expand Down Expand Up @@ -60,10 +58,9 @@ fn test_mcp_server_initialize() {
}

#[test]
#[ignore] // Ignore by default since it requires building the binary
fn test_mcp_server_tools_list() {
let mut child = Command::new("cargo")
.args(&["run", "--", "--mcp", "--url", "https://example.com"])
let mut child = Command::new(env!("CARGO_BIN_EXE_tinker"))
.args(&["--mcp", "--url", "https://example.com"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
Expand All @@ -74,8 +71,8 @@ fn test_mcp_server_tools_list() {
let stdout = child.stdout.take().expect("Failed to open stdout");
let mut reader = BufReader::new(stdout);

// Give the server time to start
std::thread::sleep(Duration::from_secs(2));
// No startup wait needed: the binary is already built, and the server reads
// stdin as soon as it starts. The request below simply queues until then.

// Send tools/list request
let request = json!({
Expand Down Expand Up @@ -118,10 +115,9 @@ fn test_mcp_server_tools_list() {
}

#[test]
#[ignore] // Ignore by default since it requires building the binary
fn test_mcp_server_invalid_request() {
let mut child = Command::new("cargo")
.args(&["run", "--", "--mcp", "--url", "https://example.com"])
let mut child = Command::new(env!("CARGO_BIN_EXE_tinker"))
.args(&["--mcp", "--url", "https://example.com"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
Expand All @@ -132,8 +128,8 @@ fn test_mcp_server_invalid_request() {
let stdout = child.stdout.take().expect("Failed to open stdout");
let mut reader = BufReader::new(stdout);

// Give the server time to start
std::thread::sleep(Duration::from_secs(2));
// No startup wait needed: the binary is already built, and the server reads
// stdin as soon as it starts. The request below simply queues until then.

// Send invalid JSON
writeln!(stdin, "{{invalid json}}").expect("Failed to write request");
Expand Down