Skip to content

Commit f30784c

Browse files
committed
feat: enhance CLI with comprehensive argument support
- Add --version/-V flag with version information display - Implement mode selection with --stdio, --sse, and --cli flags - Add comprehensive CLI configuration options for mock generation - Include authentication, webhooks, admin UI, and storage toggles - Add port configuration for mock and admin APIs - Implement logging and debug options with --verbose, --quiet, --log-level - Improve argument parsing with organized argument groups - Add enhanced help documentation and usage examples - Maintain backward compatibility with existing CLI usage - Auto-detect stdio mode for MCP client integration
1 parent 9898b11 commit f30784c

1 file changed

Lines changed: 216 additions & 16 deletions

File tree

src/mockloop_mcp/main.py

Lines changed: 216 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,39 +1745,234 @@ async def run_tool_from_cli(args):
17451745
sys.exit(1)
17461746

17471747

1748+
async def run_tool_from_cli_enhanced(
1749+
spec_source: str,
1750+
output_name: str | None = None,
1751+
auth_enabled: bool = True,
1752+
webhooks_enabled: bool = True,
1753+
admin_ui_enabled: bool = True,
1754+
storage_enabled: bool = True,
1755+
business_port: int = 8000,
1756+
admin_port: int | None = None,
1757+
):
1758+
"""Enhanced CLI helper with full configuration options."""
1759+
result = await generate_mock_api_tool(
1760+
spec_url_or_path=spec_source,
1761+
output_dir_name=output_name,
1762+
auth_enabled=auth_enabled,
1763+
webhooks_enabled=webhooks_enabled,
1764+
admin_ui_enabled=admin_ui_enabled,
1765+
storage_enabled=storage_enabled,
1766+
business_port=business_port,
1767+
admin_port=admin_port,
1768+
)
1769+
print(result)
1770+
1771+
if "Error" in result:
1772+
sys.exit(1)
1773+
1774+
17481775
def main_cli():
1776+
# Handle imports for different execution contexts
1777+
if __package__ is None or __package__ == "":
1778+
from __init__ import __version__
1779+
else:
1780+
from . import __version__
1781+
17491782
parser = argparse.ArgumentParser(
1750-
description="MockLoop API Mock Generator (CLI Test Utility for Tool Logic)"
1783+
prog="mockloop-mcp",
1784+
description="MockLoop MCP Server - Generate and manage mock API servers from specifications",
1785+
epilog="For more information, visit: https://github.com/mockloop/mockloop-mcp",
1786+
formatter_class=argparse.RawDescriptionHelpFormatter,
17511787
)
1788+
1789+
# Add version argument
17521790
parser.add_argument(
1753-
"spec_source", help="URL or local file path to the API specification."
1791+
"--version", "-V",
1792+
action="version",
1793+
version=f"%(prog)s {__version__}",
1794+
help="Show version information and exit"
17541795
)
1755-
parser.add_argument(
1756-
"-o",
1757-
"--output-name",
1758-
help="Optional name for the generated mock server directory.",
1796+
1797+
# Add mode selection arguments
1798+
mode_group = parser.add_mutually_exclusive_group()
1799+
mode_group.add_argument(
1800+
"--stdio",
1801+
action="store_true",
1802+
help="Run in stdio mode for MCP client communication"
1803+
)
1804+
mode_group.add_argument(
1805+
"--sse",
1806+
action="store_true",
1807+
help="Run in Server-Sent Events mode (default)"
1808+
)
1809+
mode_group.add_argument(
1810+
"--cli",
1811+
action="store_true",
1812+
help="Run in CLI mode for direct API generation"
1813+
)
1814+
1815+
# CLI-specific arguments (only used when --cli is specified)
1816+
cli_group = parser.add_argument_group("CLI mode options")
1817+
cli_group.add_argument(
1818+
"spec_source",
1819+
nargs="?",
1820+
help="URL or local file path to the API specification (required for CLI mode)"
1821+
)
1822+
cli_group.add_argument(
1823+
"-o", "--output-name",
1824+
help="Optional name for the generated mock server directory",
17591825
default=None,
17601826
)
1761-
# output_base_dir is handled by the generator.py, not passed to tool directly
1827+
cli_group.add_argument(
1828+
"--auth-enabled",
1829+
action="store_true",
1830+
default=True,
1831+
help="Enable authentication middleware (default: enabled)"
1832+
)
1833+
cli_group.add_argument(
1834+
"--no-auth",
1835+
action="store_true",
1836+
help="Disable authentication middleware"
1837+
)
1838+
cli_group.add_argument(
1839+
"--webhooks-enabled",
1840+
action="store_true",
1841+
default=True,
1842+
help="Enable webhook support (default: enabled)"
1843+
)
1844+
cli_group.add_argument(
1845+
"--no-webhooks",
1846+
action="store_true",
1847+
help="Disable webhook support"
1848+
)
1849+
cli_group.add_argument(
1850+
"--admin-ui-enabled",
1851+
action="store_true",
1852+
default=True,
1853+
help="Enable admin UI (default: enabled)"
1854+
)
1855+
cli_group.add_argument(
1856+
"--no-admin-ui",
1857+
action="store_true",
1858+
help="Disable admin UI"
1859+
)
1860+
cli_group.add_argument(
1861+
"--storage-enabled",
1862+
action="store_true",
1863+
default=True,
1864+
help="Enable storage functionality (default: enabled)"
1865+
)
1866+
cli_group.add_argument(
1867+
"--no-storage",
1868+
action="store_true",
1869+
help="Disable storage functionality"
1870+
)
1871+
cli_group.add_argument(
1872+
"--mock-port",
1873+
type=int,
1874+
default=8000,
1875+
help="Port for the mock API (default: 8000)"
1876+
)
1877+
cli_group.add_argument(
1878+
"--admin-port",
1879+
type=int,
1880+
help="Port for the admin API (if different from business port)"
1881+
)
1882+
1883+
# Logging and debug options
1884+
debug_group = parser.add_argument_group("debug and logging options")
1885+
debug_group.add_argument(
1886+
"-v", "--verbose",
1887+
action="store_true",
1888+
help="Enable verbose output"
1889+
)
1890+
debug_group.add_argument(
1891+
"-q", "--quiet",
1892+
action="store_true",
1893+
help="Suppress non-error output"
1894+
)
1895+
debug_group.add_argument(
1896+
"--log-level",
1897+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
1898+
default="INFO",
1899+
help="Set logging level (default: INFO)"
1900+
)
1901+
17621902
args = parser.parse_args()
17631903

1764-
import asyncio
1904+
# Configure logging based on arguments
1905+
log_level = getattr(logging, args.log_level.upper())
1906+
if args.verbose:
1907+
log_level = logging.DEBUG
1908+
elif args.quiet:
1909+
log_level = logging.ERROR
1910+
1911+
logging.basicConfig(
1912+
level=log_level,
1913+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
1914+
)
1915+
1916+
# Handle CLI mode
1917+
if args.cli or args.spec_source:
1918+
if not args.spec_source:
1919+
parser.error("spec_source is required when using CLI mode")
1920+
1921+
# Process boolean flags
1922+
auth_enabled = args.auth_enabled and not args.no_auth
1923+
webhooks_enabled = args.webhooks_enabled and not args.no_webhooks
1924+
admin_ui_enabled = args.admin_ui_enabled and not args.no_admin_ui
1925+
storage_enabled = args.storage_enabled and not args.no_storage
17651926

1766-
asyncio.run(run_tool_from_cli(args))
1927+
import asyncio
1928+
asyncio.run(run_tool_from_cli_enhanced(
1929+
args.spec_source,
1930+
args.output_name,
1931+
auth_enabled,
1932+
webhooks_enabled,
1933+
admin_ui_enabled,
1934+
storage_enabled,
1935+
args.mock_port,
1936+
args.admin_port
1937+
))
1938+
else:
1939+
# Default behavior - show help if no mode specified
1940+
parser.print_help()
1941+
sys.exit(0)
17671942

17681943

17691944
def main():
17701945
"""Main entry point for the mockloop-mcp CLI command."""
17711946
import sys
17721947
import os
17731948

1949+
# Handle version and help early for better UX
1950+
if "--version" in sys.argv or "-V" in sys.argv:
1951+
# Handle imports for different execution contexts
1952+
if __package__ is None or __package__ == "":
1953+
from __init__ import __version__
1954+
else:
1955+
from . import __version__
1956+
print(f"mockloop-mcp {__version__}")
1957+
sys.exit(0)
1958+
1959+
if "--help" in sys.argv or "-h" in sys.argv:
1960+
main_cli()
1961+
return
1962+
17741963
# Auto-detect stdio mode when run by Claude or other MCP clients
17751964
# This happens when stdin is not a terminal (piped) and no explicit flags are given
17761965
is_stdin_piped = not sys.stdin.isatty()
17771966
has_explicit_flags = any(arg.startswith("-") for arg in sys.argv[1:])
17781967

1779-
# Check for explicit --stdio flag or auto-detect stdio mode
1780-
if "--stdio" in sys.argv or (is_stdin_piped and not has_explicit_flags):
1968+
# Check for explicit mode flags
1969+
has_stdio_flag = "--stdio" in sys.argv
1970+
has_sse_flag = "--sse" in sys.argv
1971+
has_cli_flag = "--cli" in sys.argv
1972+
has_positional_args = any(not arg.startswith("-") for arg in sys.argv[1:])
1973+
1974+
# Determine mode based on flags and context
1975+
if has_stdio_flag or (is_stdin_piped and not has_explicit_flags and not has_positional_args):
17811976
# Remove --stdio from sys.argv if present
17821977
if "--stdio" in sys.argv:
17831978
sys.argv.remove("--stdio")
@@ -1791,13 +1986,18 @@ def main():
17911986

17921987
import asyncio
17931988
asyncio.run(run_stdio_server())
1794-
elif "--cli" in sys.argv:
1795-
# Remove --cli from sys.argv so argparse doesn't see it
1796-
sys.argv.remove("--cli")
1989+
elif has_cli_flag or has_positional_args:
1990+
# CLI mode - either explicit --cli flag or positional arguments provided
17971991
main_cli()
1798-
else:
1799-
# Start the MCP server in SSE mode (existing behavior)
1992+
elif has_sse_flag:
1993+
# Remove --sse from sys.argv if present
1994+
if "--sse" in sys.argv:
1995+
sys.argv.remove("--sse")
1996+
# Start the MCP server in SSE mode
18001997
server.run()
1998+
else:
1999+
# Default behavior - show help
2000+
main_cli()
18012001

18022002

18032003
# To run the MCP server:

0 commit comments

Comments
 (0)