Skip to content

Commit 8e83e12

Browse files
committed
Add CLI interface module
1 parent 622346c commit 8e83e12

File tree

1 file changed

+115
-0
lines changed
  • src/perplexity_advanced_mcp

1 file changed

+115
-0
lines changed

src/perplexity_advanced_mcp/cli.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
CLI Interface Module
3+
4+
Defines the command-line interface for the perplexity-advanced-mcp package,
5+
providing API key configuration and server management functionality.
6+
"""
7+
8+
import logging
9+
import signal
10+
import sys
11+
from typing import NoReturn
12+
13+
import typer
14+
15+
from perplexity_advanced_mcp.types import ProviderType
16+
17+
from .config import PROVIDER_CONFIG, get_api_keys
18+
from .search_tool import mcp
19+
20+
logger = logging.getLogger(__name__)
21+
22+
app = typer.Typer()
23+
24+
# Global flag for graceful shutdown
25+
shutdown_requested = False
26+
27+
28+
def handle_shutdown(signum: int, frame: object) -> None:
29+
"""
30+
Signal handler for graceful shutdown.
31+
32+
Args:
33+
signum: Signal number received
34+
frame: Current stack frame (unused)
35+
"""
36+
global shutdown_requested
37+
signal_name = signal.Signals(signum).name
38+
logger.warning("Received %s signal. Initiating graceful shutdown...", signal_name)
39+
shutdown_requested = True
40+
41+
42+
def cleanup() -> None:
43+
"""Perform cleanup operations before shutdown."""
44+
logger.info("Cleaning up resources...")
45+
# Add any necessary cleanup operations here
46+
# For example:
47+
# - Close API connections
48+
# - Save state if needed
49+
# - Release any acquired resources
50+
logger.info("Cleanup completed. Exiting...")
51+
52+
53+
def setup_signal_handlers() -> None:
54+
"""Configure signal handlers for graceful shutdown."""
55+
signal.signal(signal.SIGTERM, handle_shutdown)
56+
signal.signal(signal.SIGINT, handle_shutdown)
57+
58+
59+
def exit_gracefully() -> NoReturn:
60+
"""Perform cleanup and exit."""
61+
cleanup()
62+
sys.exit(0)
63+
64+
65+
@app.command()
66+
def main(
67+
ctx: typer.Context,
68+
openrouter_key: str | None = typer.Option(
69+
None,
70+
"--openrouter-api-key",
71+
"-o",
72+
help="OpenRouter API key",
73+
envvar="OPENROUTER_API_KEY",
74+
),
75+
perplexity_key: str | None = typer.Option(
76+
None,
77+
"--perplexity-api-key",
78+
"-p",
79+
help="Perplexity API key",
80+
envvar="PERPLEXITY_API_KEY",
81+
),
82+
) -> None:
83+
logger.info("Starting MCP server...")
84+
openrouter_key_val, perplexity_key_val = get_api_keys(openrouter_key, perplexity_key)
85+
PROVIDER_CONFIG["openrouter"]["key"] = openrouter_key_val
86+
PROVIDER_CONFIG["perplexity"]["key"] = perplexity_key_val
87+
88+
provider: ProviderType
89+
if openrouter_key_val:
90+
provider = "openrouter"
91+
elif perplexity_key_val:
92+
provider = "perplexity"
93+
else:
94+
raise typer.Abort()
95+
96+
logger.info("Using %s as the provider", provider)
97+
98+
# Set up signal handlers for graceful shutdown
99+
setup_signal_handlers()
100+
101+
while not shutdown_requested:
102+
try:
103+
mcp.run()
104+
except Exception as e:
105+
if shutdown_requested:
106+
logger.info("Shutdown requested during error recovery")
107+
break
108+
logger.error("MCP server error occurred: %s", str(e))
109+
logger.info("Restarting MCP server...")
110+
111+
exit_gracefully()
112+
113+
114+
if __name__ == "__main__":
115+
app()

0 commit comments

Comments
 (0)