Refactor CLI argument parsers for API and MCP modes

Refactor CLI argument parsing for API and MCP modes, enhancing help descriptions and maintaining backward compatibility for deprecated flags.
This commit is contained in:
ayushman bosu roy
2025-11-30 02:53:59 +05:30
committed by GitHub
parent d76e56a66f
commit e7a7dbbe70

View File

@@ -1,8 +1,21 @@
from __future__ import annotations
"""
This module defines the command-line interface (CLI) entrypoint for g4f,
including:
- API server mode
- GUI mode
- Client mode
- MCP (Model Context Protocol) mode
It provides argument parsers for each mode and executes the appropriate
runtime function depending on the CLI arguments.
"""
import argparse
from argparse import ArgumentParser
# Local imports (within g4f package)
from .client import get_parser, run_client_args
from ..requests import BrowserConfig
from ..gui.run import gui_parser, run_gui_args
@@ -10,42 +23,168 @@ from ..config import DEFAULT_PORT, DEFAULT_TIMEOUT, DEFAULT_STREAM_TIMEOUT
from .. import Provider
from .. import cookies
def get_api_parser():
# --------------------------------------------------------------
# API PARSER
# --------------------------------------------------------------
def get_api_parser() -> ArgumentParser:
"""
Creates and returns the argument parser used for:
g4f api ...
"""
api_parser = ArgumentParser(description="Run the API and GUI")
api_parser.add_argument("--bind", default=None, help=f"The bind string. (Default: 0.0.0.0:{DEFAULT_PORT})")
api_parser.add_argument("--port", "-p", default=None, help=f"Change the port of the server. (Default: {DEFAULT_PORT})")
api_parser.add_argument("--debug", "-d", action="store_true", help="Enable verbose logging.")
api_parser.add_argument("--gui", "-g", default=None, action="store_true", help="(deprecated)")
api_parser.add_argument("--no-gui", "-ng", default=False, action="store_true", help="Start without the gui.")
api_parser.add_argument("--model", default=None, help="Default model for chat completion. (incompatible with --reload and --workers)")
api_parser.add_argument("--provider", choices=[provider.__name__ for provider in Provider.__providers__ if provider.working],
default=None, help="Default provider for chat completion. (incompatible with --reload and --workers)")
api_parser.add_argument("--media-provider", choices=[provider.__name__ for provider in Provider.__providers__ if provider.working and bool(getattr(provider, "image_models", False))],
default=None, help="Default provider for image generation. (incompatible with --reload and --workers)"),
api_parser.add_argument("--proxy", default=None, help="Default used proxy. (incompatible with --reload and --workers)")
api_parser.add_argument("--workers", type=int, default=None, help="Number of workers.")
api_parser.add_argument("--disable-colors", action="store_true", help="Don't use colors.")
api_parser.add_argument("--ignore-cookie-files", action="store_true", help="Don't read .har and cookie files. (incompatible with --reload and --workers)")
api_parser.add_argument("--g4f-api-key", type=str, default=None, help="Sets an authentication key for your API. (incompatible with --reload and --workers)")
api_parser.add_argument("--ignored-providers", nargs="+", choices=[provider.__name__ for provider in Provider.__providers__ if provider.working],
default=[], help="List of providers to ignore when processing request. (incompatible with --reload and --workers)")
api_parser.add_argument("--cookie-browsers", nargs="+", choices=[browser.__name__ for browser in cookies.BROWSERS],
default=[], help="List of browsers to access or retrieve cookies from. (incompatible with --reload and --workers)")
api_parser.add_argument("--reload", action="store_true", help="Enable reloading.")
api_parser.add_argument(
"--bind",
default=None,
help=f"The bind address (default: 0.0.0.0:{DEFAULT_PORT})."
)
api_parser.add_argument(
"--port", "-p",
default=None,
help=f"Port for the API server (default: {DEFAULT_PORT})."
)
api_parser.add_argument(
"--debug", "-d",
action="store_true",
help="Enable verbose logging."
)
# Deprecated GUI flag but kept for compatibility
api_parser.add_argument(
"--gui", "-g",
default=None,
action="store_true",
help="(deprecated) Use --no-gui instead."
)
api_parser.add_argument(
"--no-gui", "-ng",
default=False,
action="store_true",
help="Run API without the GUI."
)
api_parser.add_argument(
"--model",
default=None,
help="Default model for chat completion (incompatible with reload/workers)."
)
# Providers for chat completion
api_parser.add_argument(
"--provider",
choices=[p.__name__ for p in Provider.__providers__ if p.working],
default=None,
help="Default provider for chat completion."
)
# Providers for image generation
api_parser.add_argument(
"--media-provider",
choices=[
p.__name__ for p in Provider.__providers__
if p.working and bool(getattr(p, "image_models", False))
],
default=None,
help="Default provider for image generation."
)
api_parser.add_argument(
"--proxy",
default=None,
help="Default HTTP proxy."
)
api_parser.add_argument(
"--workers",
type=int,
default=None,
help="Number of worker processes."
)
api_parser.add_argument(
"--disable-colors",
action="store_true",
help="Disable colorized output."
)
api_parser.add_argument(
"--ignore-cookie-files",
action="store_true",
help="Do not read .har or cookie files."
)
api_parser.add_argument(
"--g4f-api-key",
type=str,
default=None,
help="Authentication key for your API."
)
api_parser.add_argument(
"--ignored-providers",
nargs="+",
choices=[p.__name__ for p in Provider.__providers__ if p.working],
default=[],
help="Providers to ignore during request processing."
)
api_parser.add_argument(
"--cookie-browsers",
nargs="+",
choices=[browser.__name__ for browser in cookies.BROWSERS],
default=[],
help="Browsers to fetch cookies from."
)
api_parser.add_argument("--reload", action="store_true", help="Enable hot reload.")
api_parser.add_argument("--demo", action="store_true", help="Enable demo mode.")
api_parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT, help="Default timeout for requests in seconds. (incompatible with --reload and --workers)")
api_parser.add_argument("--stream-timeout", type=int, default=DEFAULT_STREAM_TIMEOUT, help="Default timeout for streaming requests in seconds. (incompatible with --reload and --workers)")
api_parser.add_argument("--ssl-keyfile", type=str, default=None, help="Path to SSL key file for HTTPS.")
api_parser.add_argument("--ssl-certfile", type=str, default=None, help="Path to SSL certificate file for HTTPS.")
api_parser.add_argument("--log-config", type=str, default=None, help="Custom log config.")
api_parser.add_argument("--browser-port", type=int, help="Port for the browser automation tool.")
api_parser.add_argument("--browser-host", type=str, default="127.0.0.1", help="Host for the browser automation tool.")
api_parser.add_argument(
"--timeout",
type=int,
default=DEFAULT_TIMEOUT,
help="Default request timeout in seconds."
)
api_parser.add_argument(
"--stream-timeout",
type=int,
default=DEFAULT_STREAM_TIMEOUT,
help="Default streaming timeout in seconds."
)
api_parser.add_argument("--ssl-keyfile", type=str, default=None, help="SSL key file.")
api_parser.add_argument("--ssl-certfile", type=str, default=None, help="SSL cert file.")
api_parser.add_argument("--log-config", type=str, default=None, help="Path to log config.")
api_parser.add_argument(
"--browser-port",
type=int,
help="Port for browser automation tool."
)
api_parser.add_argument(
"--browser-host",
type=str,
default="127.0.0.1",
help="Host for browser automation tool."
)
return api_parser
# --------------------------------------------------------------
# API RUNNER
# --------------------------------------------------------------
def run_api_args(args):
"""
Runs the API server using the parsed CLI arguments.
"""
from g4f.api import AppConfig, run_api
# Apply configuration
AppConfig.set_config(
ignore_cookie_files=args.ignore_cookie_files,
ignored_providers=args.ignored_providers,
@@ -60,12 +199,16 @@ def run_api_args(args):
stream_timeout=args.stream_timeout
)
# Browser automation config
if args.browser_port:
BrowserConfig.port = args.browser_port
BrowserConfig.host = args.browser_host
if args.cookie_browsers:
cookies.BROWSERS = [cookies[browser] for browser in args.cookie_browsers]
# Custom cookie browsers
if args.cookie_browsers:
cookies.BROWSERS = [cookies[b] for b in args.cookie_browsers]
# Launch server
run_api(
bind=args.bind,
port=args.port,
@@ -78,22 +221,49 @@ def run_api_args(args):
log_config=args.log_config,
)
def get_mcp_parser():
# --------------------------------------------------------------
# MCP PARSER
# --------------------------------------------------------------
def get_mcp_parser() -> ArgumentParser:
"""
Parser for:
g4f mcp ...
"""
mcp_parser = ArgumentParser(description="Run the MCP (Model Context Protocol) server")
mcp_parser.add_argument("--debug", "-d", action="store_true", help="Enable verbose logging.")
mcp_parser.add_argument("--http", action="store_true", help="Use HTTP transport instead of stdio.")
mcp_parser.add_argument("--host", default="0.0.0.0", help="Host to bind HTTP server to (default: 0.0.0.0)")
mcp_parser.add_argument("--port", type=int, default=8765, help="Port to bind HTTP server to (default: 8765)")
mcp_parser.add_argument("--origin", type=str, default=None, help="Origin URL for CORS (default: None)")
mcp_parser.add_argument("--http", action="store_true", help="Use HTTP instead of stdio.")
mcp_parser.add_argument("--host", default="0.0.0.0", help="HTTP server host.")
mcp_parser.add_argument("--port", type=int, default=8765, help="HTTP server port.")
mcp_parser.add_argument("--origin", type=str, default=None, help="CORS origin.")
return mcp_parser
def run_mcp_args(args):
from ..mcp.server import main as mcp_main
mcp_main(http=args.http, host=args.host, port=args.port, origin=args.origin)
def run_mcp_args(args):
"""
Runs the MCP server with the chosen transport method.
"""
from ..mcp.server import main as mcp_main
mcp_main(
http=args.http,
host=args.host,
port=args.port,
origin=args.origin
)
# --------------------------------------------------------------
# MAIN ENTRYPOINT
# --------------------------------------------------------------
def main():
"""
Main entry function exposed via CLI (e.g. g4f).
Handles selecting: api / gui / client / mcp
"""
parser = argparse.ArgumentParser(description="Run gpt4free", exit_on_error=False)
subparsers = parser.add_subparsers(dest="mode", help="Mode to run the g4f in.")
# Create sub-commands
subparsers = parser.add_subparsers(dest="mode", help="Mode to run g4f in.")
subparsers.add_parser("api", parents=[get_api_parser()], add_help=False)
subparsers.add_parser("gui", parents=[gui_parser()], add_help=False)
subparsers.add_parser("client", parents=[get_parser()], add_help=False)
@@ -101,6 +271,8 @@ def main():
try:
args = parser.parse_args()
# Mode routing
if args.mode == "api":
run_api_args(args)
elif args.mode == "gui":
@@ -110,9 +282,20 @@ def main():
elif args.mode == "mcp":
run_mcp_args(args)
else:
raise argparse.ArgumentError(None, "No valid mode specified. Use 'api', 'gui', 'client', or 'mcp'.")
# No mode provided
raise argparse.ArgumentError(
None,
"No valid mode specified. Use 'api', 'gui', 'client', or 'mcp'."
)
except argparse.ArgumentError:
# Fallback chain:
# 1. Try client mode
try:
run_client_args(get_parser(exit_on_error=False).parse_args(), exit_on_error=False)
run_client_args(
get_parser(exit_on_error=False).parse_args(),
exit_on_error=False
)
except argparse.ArgumentError:
run_api_args(get_api_parser().parse_args())
# 2. Try API mode with default arguments
run_api_args(get_api_parser().parse_args())