@@ -584,6 +584,10 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to
584584 mcp .WithBoolean ("return_content" ,
585585 mcp .Description ("Returns actual log content instead of URLs" ),
586586 ),
587+ mcp .WithNumber ("tail_lines" ,
588+ mcp .Description ("Number of lines to return from the end of the log" ),
589+ mcp .DefaultNumber (50 ),
590+ ),
587591 ),
588592 func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
589593 owner , err := RequiredParam [string ](request , "owner" )
@@ -612,6 +616,14 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to
612616 if err != nil {
613617 return mcp .NewToolResultError (err .Error ()), nil
614618 }
619+ tailLines , err := OptionalIntParam (request , "tail_lines" )
620+ if err != nil {
621+ return mcp .NewToolResultError (err .Error ()), nil
622+ }
623+ // Default to 50 lines if not specified
624+ if tailLines == 0 {
625+ tailLines = 50
626+ }
615627
616628 client , err := getClient (ctx )
617629 if err != nil {
@@ -628,18 +640,18 @@ func GetJobLogs(getClient GetClientFn, t translations.TranslationHelperFunc) (to
628640
629641 if failedOnly && runID > 0 {
630642 // Handle failed-only mode: get logs for all failed jobs in the workflow run
631- return handleFailedJobLogs (ctx , client , owner , repo , int64 (runID ), returnContent )
643+ return handleFailedJobLogs (ctx , client , owner , repo , int64 (runID ), returnContent , tailLines )
632644 } else if jobID > 0 {
633645 // Handle single job mode
634- return handleSingleJobLogs (ctx , client , owner , repo , int64 (jobID ), returnContent )
646+ return handleSingleJobLogs (ctx , client , owner , repo , int64 (jobID ), returnContent , tailLines )
635647 }
636648
637649 return mcp .NewToolResultError ("Either job_id must be provided for single job logs, or run_id with failed_only=true for failed job logs" ), nil
638650 }
639651}
640652
641653// handleFailedJobLogs gets logs for all failed jobs in a workflow run
642- func handleFailedJobLogs (ctx context.Context , client * github.Client , owner , repo string , runID int64 , returnContent bool ) (* mcp.CallToolResult , error ) {
654+ func handleFailedJobLogs (ctx context.Context , client * github.Client , owner , repo string , runID int64 , returnContent bool , tailLines int ) (* mcp.CallToolResult , error ) {
643655 // First, get all jobs for the workflow run
644656 jobs , resp , err := client .Actions .ListWorkflowJobs (ctx , owner , repo , runID , & github.ListWorkflowJobsOptions {
645657 Filter : "latest" ,
@@ -671,7 +683,7 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo
671683 // Collect logs for all failed jobs
672684 var logResults []map [string ]any
673685 for _ , job := range failedJobs {
674- jobResult , resp , err := getJobLogData (ctx , client , owner , repo , job .GetID (), job .GetName (), returnContent )
686+ jobResult , resp , err := getJobLogData (ctx , client , owner , repo , job .GetID (), job .GetName (), returnContent , tailLines )
675687 if err != nil {
676688 // Continue with other jobs even if one fails
677689 jobResult = map [string ]any {
@@ -704,8 +716,8 @@ func handleFailedJobLogs(ctx context.Context, client *github.Client, owner, repo
704716}
705717
706718// handleSingleJobLogs gets logs for a single job
707- func handleSingleJobLogs (ctx context.Context , client * github.Client , owner , repo string , jobID int64 , returnContent bool ) (* mcp.CallToolResult , error ) {
708- jobResult , resp , err := getJobLogData (ctx , client , owner , repo , jobID , "" , returnContent )
719+ func handleSingleJobLogs (ctx context.Context , client * github.Client , owner , repo string , jobID int64 , returnContent bool , tailLines int ) (* mcp.CallToolResult , error ) {
720+ jobResult , resp , err := getJobLogData (ctx , client , owner , repo , jobID , "" , returnContent , tailLines )
709721 if err != nil {
710722 return ghErrors .NewGitHubAPIErrorResponse (ctx , "failed to get job logs" , resp , err ), nil
711723 }
@@ -719,7 +731,7 @@ func handleSingleJobLogs(ctx context.Context, client *github.Client, owner, repo
719731}
720732
721733// getJobLogData retrieves log data for a single job, either as URL or content
722- func getJobLogData (ctx context.Context , client * github.Client , owner , repo string , jobID int64 , jobName string , returnContent bool ) (map [string ]any , * github.Response , error ) {
734+ func getJobLogData (ctx context.Context , client * github.Client , owner , repo string , jobID int64 , jobName string , returnContent bool , tailLines int ) (map [string ]any , * github.Response , error ) {
723735 // Get the download URL for the job logs
724736 url , resp , err := client .Actions .GetWorkflowJobLogs (ctx , owner , repo , jobID , 1 )
725737 if err != nil {
@@ -736,7 +748,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin
736748
737749 if returnContent {
738750 // Download and return the actual log content
739- content , httpResp , err := downloadLogContent (url .String ()) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp
751+ content , httpResp , err := downloadLogContent (url .String (), tailLines ) //nolint:bodyclose // Response body is closed in downloadLogContent, but we need to return httpResp
740752 if err != nil {
741753 // To keep the return value consistent wrap the response as a GitHub Response
742754 ghRes := & github.Response {
@@ -757,7 +769,7 @@ func getJobLogData(ctx context.Context, client *github.Client, owner, repo strin
757769}
758770
759771// downloadLogContent downloads the actual log content from a GitHub logs URL
760- func downloadLogContent (logURL string ) (string , * http.Response , error ) {
772+ func downloadLogContent (logURL string , tailLines int ) (string , * http.Response , error ) {
761773 httpResp , err := http .Get (logURL ) //nolint:gosec // URLs are provided by GitHub API and are safe
762774 if err != nil {
763775 return "" , httpResp , fmt .Errorf ("failed to download logs: %w" , err )
@@ -775,6 +787,16 @@ func downloadLogContent(logURL string) (string, *http.Response, error) {
775787
776788 // Clean up and format the log content for better readability
777789 logContent := strings .TrimSpace (string (content ))
790+
791+ // Truncate to tail_lines if specified
792+ if tailLines > 0 {
793+ lines := strings .Split (logContent , "\n " )
794+ if len (lines ) > tailLines {
795+ lines = lines [len (lines )- tailLines :]
796+ logContent = strings .Join (lines , "\n " )
797+ }
798+ }
799+
778800 return logContent , httpResp , nil
779801}
780802
0 commit comments