1- """ Launches the jac-mcp server as a background subprocess on import."""
1+ """ Launches the jac-mcp server in a background thread on import.
22
3- import from subprocess { Popen , PIPE , STDOUT }
4- import shutil ;
5- import atexit ;
6- import sys ;
3+ Uses direct Python import instead of subprocess to avoid venv PATH issues
4+ in Kubernetes deployments (jac install puts jac-mcp in .jac/venv/ which
5+ the system jac binary can't access as a CLI plugin).
6+ """
7+
8+ import threading ;
79import time ;
810import urllib .request ;
911
1012def _start_mcp_server () -> Any {
11- jac_path = shutil.which(" jac" );
12- if not jac_path {
13- print (" [jac-mcp] 'jac' command not found in PATH, skipping MCP server launch." );
13+ try {
14+ import from jac_mcp .server { JacMcpServer }
15+ } except ImportError as e {
16+ print (f " [jac-mcp] jac-mcp not installed, skipping: { e} " );
1417 return None ;
1518 }
16- print (f " [jac-mcp] Found jac at: { jac_path} " );
19+
20+ print (" [jac-mcp] Starting built-in MCP server..." );
1721
1822 try {
19- proc = Popen(
20- [" jac" , " mcp" , " --transport" , " streamable-http" , " --port" , " 3002" , " --host" , " 127.0.0.1" ],
21- stdout = sys.stderr,
22- stderr = STDOUT
23- );
23+ server = JacMcpServer(transport = " streamable-http" , port = 3002 , host = " 127.0.0.1" );
2424
25- # Wait briefly and check if process is still alive
26- time.sleep(2 );
27- exit_code = proc.poll();
28- if exit_code is not None {
29- print (f " [jac-mcp] Server exited immediately with code { exit_code} . " );
30- return None ;
31- }
25+ # Run server in a daemon thread so it doesn't block app startup
26+ thread = threading.Thread(target = server.start, daemon = True );
27+ thread.start();
3228
3329 # Wait for server to be ready (up to 15 seconds)
3430 ready = False ;
3531 for i in range (15 ) {
32+ time.sleep(1 );
3633 try {
3734 req = urllib.request.Request(
3835 " http://127.0.0.1:3002/mcp/" ,
@@ -41,26 +38,20 @@ def _start_mcp_server() -> Any {
4138 method = " POST"
4239 );
4340 with urllib .request .urlopen (req , timeout = 2 ) as resp {
44- print (f " [jac-mcp] Server is ready on http://127.0.0.1:3002/mcp/ (took { i+ 2 } s) " );
41+ print (f " [jac-mcp] Server is ready on http://127.0.0.1:3002/mcp/ (took { i+ 1 } s) " );
4542 ready = True ;
4643 break ;
4744 }
4845 } except Exception {
49- time.sleep( 1 ) ;
46+ 0 ;
5047 }
5148 }
5249
5350 if not ready {
5451 print (" [jac-mcp] Server started but not responding on port 3002 after 15s." );
5552 }
5653
57- def _cleanup () -> None {
58- if proc and proc.poll() is None {
59- proc.terminate();
60- }
61- }
62- atexit.register(_cleanup);
63- return proc;
54+ return thread;
6455 } except Exception as e {
6556 print (f " [jac-mcp] Failed to start built-in MCP server: { e} " );
6657 }
0 commit comments