Skip to content

Commit 40f2102

Browse files
committed
add --auth/--no-auth router config
1 parent a9c942a commit 40f2102

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

.cursor/rules/pytest.mdc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ description:
33
globs: *.py
44
alwaysApply: false
55
---
6-
always run pytest at the end of a major change
6+
always run pytest at the end of a major change
7+
always run ruff lint at then end of any code changes

src/mcpm/commands/router.py

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def is_process_running(pid):
4141
except Exception:
4242
return False
4343

44+
4445
def is_port_listening(host, port) -> bool:
4546
"""
4647
Check if the specified (host, port) is being listened on.
@@ -133,10 +134,18 @@ def start_router(verbose):
133134
return
134135

135136
# get router config
136-
config = ConfigManager().get_router_config()
137+
config_manager = ConfigManager()
138+
config = config_manager.get_router_config()
137139
host = config["host"]
138140
port = config["port"]
139141

142+
# Check if we have an API key, if not, create one
143+
share_config = config_manager.read_share_config()
144+
if share_config.get("api_key") is None:
145+
api_key = secrets.token_urlsafe(32)
146+
config_manager.save_share_config(api_key=api_key)
147+
console.print("[bold green]Created API key for router authentication[/]")
148+
140149
# prepare uvicorn command
141150
uvicorn_cmd = [
142151
sys.executable,
@@ -185,9 +194,29 @@ def start_router(verbose):
185194
pid = process.pid
186195
write_pid_file(pid)
187196

197+
# Display router started information
188198
console.print(f"[bold green]MCPRouter started[/] at http://{host}:{port} (PID: {pid})")
189199
console.print(f"Log file: {log_file}")
190-
console.print("Use 'mcpm router off' to stop the router.")
200+
201+
# Display connection instructions
202+
console.print("\n[bold cyan]Connection Information:[/]")
203+
204+
# Get API key if available
205+
api_key = config_manager.read_share_config().get("api_key")
206+
207+
# Show URL with or without authentication based on API key availability
208+
if api_key:
209+
# Show authenticated URL
210+
console.print(f"SSE Server URL: [green]http://{host}:{port}/sse?s={api_key}[/]")
211+
console.print("\n[bold cyan]To use a specific profile with authentication:[/]")
212+
console.print(f"[green]http://{host}:{port}/sse?s={api_key}&profile=<profile_name>[/]")
213+
else:
214+
# Show URL without authentication
215+
console.print(f"SSE Server URL: [green]http://{host}:{port}/sse[/]")
216+
console.print("\n[bold cyan]To use a specific profile:[/]")
217+
console.print(f"[green]http://{host}:{port}/sse?profile=<profile_name>[/]")
218+
219+
console.print("\n[yellow]Use 'mcpm router off' to stop the router.[/]")
191220

192221
except Exception as e:
193222
console.print(f"[bold red]Error:[/] Failed to start MCPRouter: {e}")
@@ -197,17 +226,22 @@ def start_router(verbose):
197226
@click.option("-H", "--host", type=str, help="Host to bind the SSE server to")
198227
@click.option("-p", "--port", type=int, help="Port to bind the SSE server to")
199228
@click.option("-a", "--address", type=str, help="Remote address to share the router")
229+
@click.option(
230+
"--auth/--no-auth", default=True, is_flag=True, help="Enable/disable API key authentication (default: enabled)"
231+
)
200232
@click.help_option("-h", "--help")
201-
def set_router_config(host, port, address):
233+
def set_router_config(host, port, address, auth):
202234
"""Set MCPRouter global configuration.
203235
204236
Example:
205237
mcpm router set -H localhost -p 8888
206238
mcpm router set --host 127.0.0.1 --port 9000
239+
mcpm router set --no-auth # disable authentication
240+
mcpm router set --auth # enable authentication
207241
"""
208-
if not host and not port and not address:
242+
if not host and not port and not address and auth is None:
209243
console.print(
210-
"[yellow]No changes were made. Please specify at least one option (--host, --port, or --address)[/]"
244+
"[yellow]No changes were made. Please specify at least one option (--host, --port, --address, --auth/--no-auth)[/]"
211245
)
212246
return
213247

@@ -220,7 +254,32 @@ def set_router_config(host, port, address):
220254
port = port or current_config["port"]
221255
share_address = address or current_config["share_address"]
222256

223-
# save config
257+
# Handle authentication setting
258+
share_config = config_manager.read_share_config()
259+
current_api_key = share_config.get("api_key")
260+
261+
if auth:
262+
# Enable authentication
263+
if current_api_key is None:
264+
# Generate a new API key if authentication is enabled but no key exists
265+
api_key = secrets.token_urlsafe(32)
266+
config_manager.save_share_config(
267+
share_url=share_config.get("url"), share_pid=share_config.get("pid"), api_key=api_key
268+
)
269+
console.print("[bold green]API key authentication enabled.[/] Generated new API key.")
270+
else:
271+
console.print("[bold green]API key authentication enabled.[/] Using existing API key.")
272+
else:
273+
# Disable authentication by clearing the API key
274+
if current_api_key is not None:
275+
config_manager.save_share_config(
276+
share_url=share_config.get("url"), share_pid=share_config.get("pid"), api_key=None
277+
)
278+
console.print("[bold yellow]API key authentication disabled.[/]")
279+
else:
280+
console.print("[bold yellow]API key authentication was already disabled.[/]")
281+
282+
# save router config
224283
if config_manager.save_router_config(host, port, share_address):
225284
console.print(
226285
f"[bold green]Router configuration updated:[/] host={host}, port={port}, share_address={share_address}"

0 commit comments

Comments
 (0)