get_step_log_artifact
Check whether a managed step log artifact exists for a given build step. Uses deterministic artifact ID; does not fetch from Codemagic.
Instructions
Check whether a managed step log artifact exists for a build step.
This tool only inspects the local managed artifact created by get_step_logs(..., delivery="file"). It does not fetch from Codemagic, recreate missing files, or return log contents inline.
The returned artifact metadata includes a deterministic artifact_id: artifact_<build_id>_<step_id>
Args: build_id: The Codemagic build ID. step_id: The step ID (from get_build_logs output).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| build_id | Yes | ||
| step_id | Yes |
Implementation Reference
- codemagic_mcp/client.py:392-393 (handler)Client-side handler that delegates to _inspect_step_log_artifact to check if a step log file exists locally and return its metadata or a 'missing' status.
def get_step_log_artifact(self, build_id: str, step_id: str) -> dict[str, Any]: return self._inspect_step_log_artifact(build_id, step_id) - codemagic_mcp/client.py:353-381 (schema)Internal inspection logic that checks file existence, expiration, and returns the artifact metadata schema (available or missing status, artifact_id, file_path, bytes, line_count, expires_at).
def _inspect_step_log_artifact(self, build_id: str, step_id: str) -> dict[str, Any]: destination = self._build_log_file_path(build_id, step_id) if not destination.exists(): return self._build_missing_step_log_artifact_response(build_id, step_id) try: modified_at = datetime.fromtimestamp(destination.stat().st_mtime, tz=UTC) except FileNotFoundError: return self._build_missing_step_log_artifact_response(build_id, step_id) expires_at = self._get_expiration_time(modified_at) if expires_at <= datetime.now(UTC): try: destination.unlink() except FileNotFoundError: pass return self._build_missing_step_log_artifact_response(build_id, step_id) with destination.open("r", encoding="utf-8") as log_file: line_count = sum(1 for _ in log_file) return { "status": "available", "artifact_id": self._get_step_log_artifact_id(build_id, step_id), "file_path": str(destination), "bytes": destination.stat().st_size, "line_count": line_count, "expires_at": expires_at.isoformat().replace("+00:00", "Z"), } - codemagic_mcp/tools/builds.py:125-141 (registration)MCP tool registration via @mcp.tool() decorator inside the builds module's register() function. The tool is registered under the name 'get_step_log_artifact'.
@mcp.tool() async def get_step_log_artifact(build_id: str, step_id: str) -> Any: """Check whether a managed step log artifact exists for a build step. This tool only inspects the local managed artifact created by get_step_logs(..., delivery="file"). It does not fetch from Codemagic, recreate missing files, or return log contents inline. The returned artifact metadata includes a deterministic artifact_id: artifact_<build_id>_<step_id> Args: build_id: The Codemagic build ID. step_id: The step ID (from get_build_logs output). """ async with CodemagicClient() as client: return client.get_step_log_artifact(build_id, step_id) - codemagic_mcp/client.py:257-258 (helper)Helper that generates the deterministic artifact ID in the format artifact_<build_id>_<step_id>.
def _get_step_log_artifact_id(self, build_id: str, step_id: str) -> str: return f"artifact_{build_id}_{step_id}" - codemagic_mcp/client.py:324-337 (helper)Helper that builds the 'missing' response dict when a step log artifact file does not exist or has expired.
def _build_missing_step_log_artifact_response( self, build_id: str, step_id: str, ) -> dict[str, str]: return { "status": "missing", "artifact_id": self._get_step_log_artifact_id(build_id, step_id), "reason": "not_generated_or_expired", "message": ( "The step log artifact was not found. " "It may not have been generated, or it may have expired and been deleted." ), }