@@ -32,7 +32,9 @@ def find_installed_server(server_name):
3232 return None , None
3333
3434
35- async def run_server_with_fastmcp (server_config , server_name , http_mode = False , port = None , host = "127.0.0.1" ):
35+ async def run_server_with_fastmcp (
36+ server_config , server_name , http_mode = False , sse_mode = False , port = None , host = "127.0.0.1"
37+ ):
3638 """Run server using FastMCP proxy (stdio or HTTP)."""
3739 try :
3840 # Use default port if none specified
@@ -41,11 +43,17 @@ async def run_server_with_fastmcp(server_config, server_name, http_mode=False, p
4143 # Note: Usage tracking is handled by proxy middleware
4244
4345 # Create FastMCP proxy for single server
44- action = "run_http" if http_mode else "run"
46+ if sse_mode :
47+ action = "run_sse"
48+ elif http_mode :
49+ action = "run_http"
50+ else :
51+ action = "run"
52+
4553 proxy = await create_mcpm_proxy (
4654 servers = [server_config ],
4755 name = f"mcpm-run-{ server_name } " ,
48- stdio_mode = not http_mode , # stdio_mode=False for HTTP
56+ stdio_mode = not ( http_mode or sse_mode ) , # stdio_mode=False for HTTP/SSE
4957 action = action ,
5058 )
5159
@@ -55,25 +63,35 @@ async def run_server_with_fastmcp(server_config, server_name, http_mode=False, p
5563 # Re-suppress library logging after FastMCP initialization
5664 ensure_dependency_logging_suppressed ()
5765
58- if http_mode :
66+ if http_mode or sse_mode :
5967 # Try to find an available port if the requested one is taken
6068 actual_port = await find_available_port (port )
6169 if actual_port != port :
6270 logger .debug (f"Port { port } is busy, using port { actual_port } instead" )
6371
6472 # Display server information in a nice panel
65- http_url = f"http://{ host } :{ actual_port } /mcp/"
66- panel_content = f"[bold]Server:[/] { server_name } \n [bold]URL:[/] [cyan]{ http_url } [/cyan]\n \n [dim]Press Ctrl+C to stop the server[/]"
67- panel = Panel (
68- panel_content , title = "🌐 Local Server Running" , title_align = "left" , border_style = "green" , padding = (1 , 2 )
69- )
73+ if sse_mode :
74+ server_url = f"http://{ host } :{ actual_port } /sse/"
75+ title = "📡 SSE Server Running"
76+ else :
77+ server_url = f"http://{ host } :{ actual_port } /mcp/"
78+ title = "🌐 Local Server Running"
79+
80+ panel_content = f"[bold]Server:[/] { server_name } \n [bold]URL:[/] [cyan]{ server_url } [/cyan]\n \n [dim]Press Ctrl+C to stop the server[/]"
81+ panel = Panel (panel_content , title = title , title_align = "left" , border_style = "green" , padding = (1 , 2 ))
7082 console .print (panel )
7183
72- logger .debug (f"Starting FastMCP proxy for server '{ server_name } ' on { host } :{ actual_port } " )
84+ mode = "SSE" if sse_mode else "HTTP"
85+ logger .debug (f"Starting FastMCP proxy for server '{ server_name } ' in { mode } mode on { host } :{ actual_port } " )
7386
74- # Run FastMCP proxy in HTTP mode with uvicorn logging control
87+ # Run FastMCP proxy in HTTP/SSE mode with uvicorn logging control
88+ transport = "sse" if sse_mode else "http"
7589 await proxy .run_http_async (
76- host = host , port = actual_port , show_banner = False , uvicorn_config = {"log_level" : get_uvicorn_log_level ()}
90+ host = host ,
91+ port = actual_port ,
92+ show_banner = False ,
93+ transport = transport ,
94+ uvicorn_config = {"log_level" : get_uvicorn_log_level ()},
7795 )
7896 else :
7997 # Run FastMCP proxy in stdio mode (default)
@@ -84,7 +102,7 @@ async def run_server_with_fastmcp(server_config, server_name, http_mode=False, p
84102
85103 except KeyboardInterrupt :
86104 logger .info ("Server execution interrupted" )
87- if http_mode :
105+ if http_mode or sse_mode :
88106 logger .warning ("\n Server execution interrupted" )
89107 return 130
90108 except Exception as e :
@@ -114,19 +132,23 @@ async def find_available_port(preferred_port, max_attempts=10):
114132@click .command ()
115133@click .argument ("server_name" )
116134@click .option ("--http" , is_flag = True , help = "Run server over HTTP instead of stdio" )
117- @click .option ("--port" , type = int , default = DEFAULT_PORT , help = f"Port for HTTP mode (default: { DEFAULT_PORT } )" )
118- @click .option ("--host" , type = str , default = "127.0.0.1" , help = "Host address for HTTP mode (default: 127.0.0.1)" )
135+ @click .option ("--sse" , is_flag = True , help = "Run server over SSE instead of stdio" )
136+ @click .option ("--port" , type = int , default = DEFAULT_PORT , help = f"Port for HTTP / SSE mode (default: { DEFAULT_PORT } )" )
137+ @click .option ("--host" , type = str , default = "127.0.0.1" , help = "Host address for HTTP / SSE mode (default: 127.0.0.1)" )
119138@click .help_option ("-h" , "--help" )
120- def run (server_name , http , port , host ):
121- """Execute a server from global configuration over stdio or HTTP .
139+ def run (server_name , http , sse , port , host ):
140+ """Execute a server from global configuration over stdio, HTTP, or SSE .
122141
123142 Runs an installed MCP server from the global configuration. By default
124- runs over stdio for client communication, but can run over HTTP with --http.
143+ runs over stdio for client communication, but can run over HTTP with --http
144+ or over SSE with --sse.
125145
126146 Examples:
127147 mcpm run mcp-server-browse # Run over stdio (default)
128148 mcpm run --http mcp-server-browse # Run over HTTP on 127.0.0.1:6276
149+ mcpm run --sse mcp-server-browse # Run over SSE on 127.0.0.1:6276
129150 mcpm run --http --port 9000 filesystem # Run over HTTP on 127.0.0.1:9000
151+ mcpm run --sse --port 9000 filesystem # Run over SSE on 127.0.0.1:9000
130152 mcpm run --http --host 0.0.0.0 filesystem # Run over HTTP on 0.0.0.0:6276
131153
132154 Note: stdio mode is typically used in MCP client configurations:
@@ -164,20 +186,31 @@ def run(server_name, http, port, host):
164186 if server_config .headers :
165187 logger .debug (f"Headers: { list (server_config .headers .keys ())} " )
166188
167- logger .debug (f"Mode: { 'HTTP' if http else 'stdio' } " )
168- if http :
189+ # Validate mutually exclusive options
190+ if http and sse :
191+ logger .error ("Error: Cannot use both --http and --sse flags together" )
192+ sys .exit (1 )
193+
194+ mode = "SSE" if sse else "HTTP" if http else "stdio"
195+ logger .debug (f"Mode: { mode } " )
196+ if http or sse :
169197 logger .debug (f"Port: { port } " )
170198
171199 # Choose execution method
172200 if http :
173201 # Use FastMCP proxy for HTTP mode
174202 exit_code = asyncio .run (
175- run_server_with_fastmcp (server_config , server_name , http_mode = True , port = port , host = host )
203+ run_server_with_fastmcp (server_config , server_name , http_mode = True , sse_mode = False , port = port , host = host )
204+ )
205+ elif sse :
206+ # Use FastMCP proxy for SSE mode
207+ exit_code = asyncio .run (
208+ run_server_with_fastmcp (server_config , server_name , http_mode = False , sse_mode = True , port = port , host = host )
176209 )
177210 else :
178211 # Use FastMCP proxy for stdio mode (enables middleware and usage tracking)
179212 exit_code = asyncio .run (
180- run_server_with_fastmcp (server_config , server_name , http_mode = False , port = port , host = host )
213+ run_server_with_fastmcp (server_config , server_name , http_mode = False , sse_mode = False , port = port , host = host )
181214 )
182215
183216 sys .exit (exit_code )
0 commit comments