ado_package_install
Install Stata ado packages from SSC, GitHub, or net sources to access third-party commands.
Instructions
Install a Stata ado package from SSC, GitHub, or net sources. Use before running commands that require third-party packages.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| package | Yes | ||
| source | No | ssc | |
| is_replace | No | ||
| package_source_from | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/stata_mcp/api/ado_install.py:24-65 (handler)Primary handler: Installs ado packages from SSC, net, or GitHub. On Unix uses installer classes (SSC_Install, NET_Install, GITHUB_Install); on Windows writes a dofile and executes via stata_do. Supports replace, timeout, and config_file parameters.
def ado_package_install( package: str, source: str = "ssc", is_replace: bool = True, package_source_from: str = None, config_file: str | Path | None = None, timeout: int = 300, ) -> str: """Install an ado package from SSC, net, or GitHub.""" runtime = create_runtime_context(config_file=config_file, require_stata=True) source = source.lower() if runtime.is_unix: installer_cls = SOURCE_MAPPING.get(source, SSC_Install) install_args = [package, package_source_from] if source == "net" else [package] install_message = installer_cls(runtime.stata_cli, is_replace, timeout=timeout).install(*install_args) if not installer_cls.check_installed_from_msg(install_message): error_summary = installer_cls.extract_error_summary(install_message) install_message += ( f"\nError: Failed to install package '{package}' from source '{source}'. " f"Details: {error_summary}" ) if source == "github": install_message += ( "\nPlease check the GitHub repository URL, verify case sensitivity, " "and ensure the github command is installed in Stata." ) else: try: from ..mcp_servers import _load_help_cls _load_help_cls().help(package, replace=True) except Exception: pass return install_message from_message = f"from({package_source_from})" if (package_source_from and source == "net") else "" replace_flag = "replace" if is_replace else "" command = f"{source} install {package}, {replace_flag} {from_message}".strip() dofile_path = write_dofile(command, config_file=config_file) return str(stata_do(dofile_path, read_log_when_error=False, config_file=config_file).get("log_content", {})) - src/stata_mcp/mcp_servers.py:308-372 (handler)Legacy handler in mcp_servers.py (used before API refactor). Duplicates logic: on Unix uses installer classes with direct config, on Windows writes dofile. Wraps the old config singleton instead of runtime context.
def ado_package_install( package: str, source: str = "ssc", is_replace: bool = True, package_source_from: str = None ) -> str: """ Install a Stata package from SSC, GitHub, or net. Args: package (str): Package name. For GitHub, use "user/repo" format. source (str): "ssc" (default), "github", or "net". is_replace (bool): Force reinstallation if already present. package_source_from (str): Directory or URL (required only for source="net"). Returns: str: Stata installation log as a string. Examples: >>> ado_package_install(package="outreg2") >>> ado_package_install(package="SepineTam/TexIV", source="github") Notes: SSC installs can be slow; skip if the package is likely already installed. """ source = source.lower() if config.IS_UNIX: from .stata import GITHUB_Install, NET_Install, SSC_Install SOURCE_MAPPING: Dict = { "github": GITHUB_Install, "net": NET_Install, "ssc": SSC_Install } installer = SOURCE_MAPPING.get(source, SSC_Install) logging.info(f"Try to use {installer.__name__} to install {package}.") # set the args for the special cases args = [package, package_source_from] if source == "net" else [package] install_msg = installer(config.STATA_CLI, is_replace, timeout=300).install(*args) if installer.check_installed_from_msg(install_msg): logging.info(f"{package} is installed successfully.") else: error_summary = installer.extract_error_summary(install_msg) install_msg += ( f"\nError: Failed to install package '{package}' from source '{source}'. " f"Details: {error_summary}" ) if source == "github": install_msg += ( "\nPlease check the GitHub repo URL, verify case sensitivity, " "and ensure the GitHub command is installed in Stata" ) logging.error(f"{package} installation failed.") logging.debug(f"Full installation message: {install_msg}") return install_msg else: from_message = f"from({package_source_from})" if (package_source_from and source == "net") else "" replace_str = "replace" if is_replace else "" tmp_file = write_dofile(f"{source} install {package}, {replace_str} {from_message}") return stata_do(tmp_file, read_log_when_error=False).get("log_content") - src/stata_mcp/mcp_servers.py:626-633 (registration)Tool registration entry in _TOOL_REGISTRY dict mapping 'ado_package_install' to its description and function reference (with 'all' profile).
"ado_package_install": { "description": ( "Install a Stata ado package from SSC, GitHub, or net sources. " "Use before running commands that require third-party packages." ), "func": ado_package_install, "profiles": {"all"}, }, - src/stata_mcp/mcp_servers.py:645-672 (registration)register_tools function that iterates _TOOL_REGISTRY and calls server.tool() to register each tool with FastMCP.
def register_tools(server: FastMCP, profile: str = "all") -> None: """Register tools and resources based on a selected profile.""" global _registered_profile if profile not in {"core", "all"}: raise ValueError(f"Unsupported profile: {profile}") if _registered_profile == profile: return if _registered_profile is not None and _registered_profile != profile: raise RuntimeError( "Tools are already registered with a different profile. " "Create a new process to switch profile." ) for name, meta in _TOOL_REGISTRY.items(): if meta.get("unix_only") and not config.IS_UNIX: continue if meta.get("deprecated") and not config.ENABLE_WRITE_DOFILE: continue if profile not in meta["profiles"]: continue tool_func: ToolFunc | None = meta.get("func") if tool_func is None: logging.warning("Skipping tool '%s' because its registry entry has no callable func.", name) continue server.tool(name=name, description=meta["description"])(tool_func) - CLI handler for 'ado-install' action that invokes ado_package_install from the API module with parsed CLI arguments.
def handle_tool(args: Namespace) -> int: """Handle the tool subcommand.""" from ..api import ado_package_install, get_data_info, read_log, stata_do, stata_help try: if args.tool_action == "ado-install": result = ado_package_install( package=args.package_name, source=args.source, is_replace=args.is_replace, package_source_from=args.package_source_from, ) elif args.tool_action == "do": result = stata_do( dofile_path=args.dofile_path, log_file_name=args.log_file_name, read_log_when_error=args.is_read_log, is_replace_log=args.is_replace_log, enable_smcl=args.enable_smcl, ) elif args.tool_action == "help": result = stata_help( cmd=args.stata_command, enable_smcl=args.enable_smcl, ) elif args.tool_action == "data-info": result = get_data_info( data_path=args.data_path, vars_list=args.vars_list, encoding=args.encoding, ) elif args.tool_action == "read-log": result = read_log( file_path=args.file_path, encoding=args.encoding, output_format=args.output_format, ) else: return 2 except Exception as error: print(error, file=sys.stderr) return 1 print_cli_result(result) return 0