From 414b07816bb1108c5e520d3d893d324171a108cd Mon Sep 17 00:00:00 2001 From: aliciatang07 Date: Thu, 5 Feb 2026 18:55:16 +0000 Subject: [PATCH 1/7] add new tool for getting state --- .../cloudrun/client/cloudrunclient.go | 10 ++++++++++ devops-mcp-server/cloudrun/cloudrun.go | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/devops-mcp-server/cloudrun/client/cloudrunclient.go b/devops-mcp-server/cloudrun/client/cloudrunclient.go index 2b11664..b604d57 100644 --- a/devops-mcp-server/cloudrun/client/cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/cloudrunclient.go @@ -47,6 +47,7 @@ func ContextWithClient(ctx context.Context, client CloudRunClient) context.Conte // CloudRunClient is an interface for interacting with the Cloud Run API. type CloudRunClient interface { GetService(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Service, error) + GetStatus(ctx context.Context, projectID, location, serviceName string) (State, error) ListServices(ctx context.Context, projectID, location string) ([]*cloudrunpb.Service, error) CreateService(ctx context.Context, projectID, location, serviceName, imageURL string, port int32) (*cloudrunpb.Service, error) UpdateService(ctx context.Context, projectID, location, serviceName, imageURL, revisionName string, port int32, service *cloudrunpb.Service) (*cloudrunpb.Service, error) @@ -144,6 +145,15 @@ func (c *CloudRunClientImpl) GetService(ctx context.Context, projectID, location return service, nil } +func (c *CloudRunClientImpl) GetStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { + service, err:= c.GetService(ctx, projectID, location, serviceName) + if err!=nil { + return nil, fmt.Errorf("failed to get service: %w", err) + } + terminalCondition:= service.GetTerminalCondition() + return terminalCondition.State, nil +} + func (c *CloudRunClientImpl) GetRevision(ctx context.Context, service *cloudrunpb.Service) (*cloudrunpb.Revision, error) { // Get the latest revision latestRevision, err := c.revisionsClient.GetRevision(ctx, &cloudrunpb.GetRevisionRequest{Name: service.LatestReadyRevision}) diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index a174223..8e5a500 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -36,6 +36,7 @@ func (h *Handler) Register(server *mcp.Server) { addListServicesTool(server, h.CrClient) addDeployToCloudRunFromImageTool(server, h.CrClient) addDeployToCloudRunFromSourceTool(server, h.CrClient) + addGetServiceStatus(server, h.CrClient) } type ListServicesArgs struct { @@ -134,3 +135,19 @@ func addDeployToCloudRunFromSourceTool(server *mcp.Server, crClient cloudrunclie } mcp.AddTool(server, &mcp.Tool{Name: "cloudrun.deploy_to_cloud_run_from_source", Description: "Creates a new Cloud Run service or updates an existing one from source. This tool may take a couple minutes to finish running."}, deployToCloudRunFromSourceToolFunc) } + +type GetServiceStatusArgs struct{ + ProjectID string `json:"project_id" jsonschema:"The Google Cloud project ID."` + Location string `json:"location" jsonschema:"The Google Cloud location."` + ServiceName string `json: service_name jsonschema:"The Cloud Run service name"` +} + +func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { + getServiceStatusToolFunc = func(ctx context.Context, req* mcp.CallToolRequest, args GetServiceStatusArgs){ + state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) + if err != nil { + return &mcp.CallToolResult{}, nil, fmt.Errorf("failed to get service state: %w", err) + } + return &mcp.CallToolResult{}, state, nil + } +} From 7cdfa0de06f7fa55b1d88ec876f844b768004a05 Mon Sep 17 00:00:00 2001 From: "Xuejie(Alicia) Tang" Date: Mon, 9 Feb 2026 13:38:50 -0500 Subject: [PATCH 2/7] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- devops-mcp-server/cloudrun/client/cloudrunclient.go | 10 +++++----- devops-mcp-server/cloudrun/cloudrun.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/devops-mcp-server/cloudrun/client/cloudrunclient.go b/devops-mcp-server/cloudrun/client/cloudrunclient.go index b604d57..0768d8f 100644 --- a/devops-mcp-server/cloudrun/client/cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/cloudrunclient.go @@ -47,7 +47,7 @@ func ContextWithClient(ctx context.Context, client CloudRunClient) context.Conte // CloudRunClient is an interface for interacting with the Cloud Run API. type CloudRunClient interface { GetService(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Service, error) - GetStatus(ctx context.Context, projectID, location, serviceName string) (State, error) + GetStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) ListServices(ctx context.Context, projectID, location string) ([]*cloudrunpb.Service, error) CreateService(ctx context.Context, projectID, location, serviceName, imageURL string, port int32) (*cloudrunpb.Service, error) UpdateService(ctx context.Context, projectID, location, serviceName, imageURL, revisionName string, port int32, service *cloudrunpb.Service) (*cloudrunpb.Service, error) @@ -146,12 +146,12 @@ func (c *CloudRunClientImpl) GetService(ctx context.Context, projectID, location } func (c *CloudRunClientImpl) GetStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { - service, err:= c.GetService(ctx, projectID, location, serviceName) - if err!=nil { + service, err := c.GetService(ctx, projectID, location, serviceName) + if err != nil { return nil, fmt.Errorf("failed to get service: %w", err) } - terminalCondition:= service.GetTerminalCondition() - return terminalCondition.State, nil + terminalCondition := service.GetTerminalCondition() + return &terminalCondition.State, nil } func (c *CloudRunClientImpl) GetRevision(ctx context.Context, service *cloudrunpb.Service) (*cloudrunpb.Revision, error) { diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index 8e5a500..40d7d10 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -139,7 +139,7 @@ func addDeployToCloudRunFromSourceTool(server *mcp.Server, crClient cloudrunclie type GetServiceStatusArgs struct{ ProjectID string `json:"project_id" jsonschema:"The Google Cloud project ID."` Location string `json:"location" jsonschema:"The Google Cloud location."` - ServiceName string `json: service_name jsonschema:"The Cloud Run service name"` + ServiceName string `json:"service_name" jsonschema:"The Cloud Run service name"` } func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { From cbef7fa51b55d054b275e3fcab8dd42f57db87e8 Mon Sep 17 00:00:00 2001 From: aliciatang07 Date: Tue, 10 Feb 2026 16:26:21 +0000 Subject: [PATCH 3/7] fix method parameter --- devops-mcp-server/cloudrun/client/cloudrunclient.go | 4 ++-- devops-mcp-server/cloudrun/cloudrun.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/devops-mcp-server/cloudrun/client/cloudrunclient.go b/devops-mcp-server/cloudrun/client/cloudrunclient.go index 0768d8f..d73c9f9 100644 --- a/devops-mcp-server/cloudrun/client/cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/cloudrunclient.go @@ -47,7 +47,6 @@ func ContextWithClient(ctx context.Context, client CloudRunClient) context.Conte // CloudRunClient is an interface for interacting with the Cloud Run API. type CloudRunClient interface { GetService(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Service, error) - GetStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) ListServices(ctx context.Context, projectID, location string) ([]*cloudrunpb.Service, error) CreateService(ctx context.Context, projectID, location, serviceName, imageURL string, port int32) (*cloudrunpb.Service, error) UpdateService(ctx context.Context, projectID, location, serviceName, imageURL, revisionName string, port int32, service *cloudrunpb.Service) (*cloudrunpb.Service, error) @@ -55,6 +54,7 @@ type CloudRunClient interface { DeployFromSource(ctx context.Context, projectID, location, serviceName, source string, port int32, allowPublicAccess bool) error DeleteService(ctx context.Context, projectID, location, serviceName string) error SetServiceAccess(ctx context.Context, serviceName string, allowPublicAccess bool) error + GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) } // NewCloudRunClient creates a new CloudRunClient. @@ -145,7 +145,7 @@ func (c *CloudRunClientImpl) GetService(ctx context.Context, projectID, location return service, nil } -func (c *CloudRunClientImpl) GetStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { +func (c *CloudRunClientImpl) GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { service, err := c.GetService(ctx, projectID, location, serviceName) if err != nil { return nil, fmt.Errorf("failed to get service: %w", err) diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index 40d7d10..d8bfd38 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -36,7 +36,7 @@ func (h *Handler) Register(server *mcp.Server) { addListServicesTool(server, h.CrClient) addDeployToCloudRunFromImageTool(server, h.CrClient) addDeployToCloudRunFromSourceTool(server, h.CrClient) - addGetServiceStatus(server, h.CrClient) + addGetServiceStatusTool(server, h.CrClient) } type ListServicesArgs struct { From b7692ec6975fcd5085bfb8a2b198d2c0f0ab375b Mon Sep 17 00:00:00 2001 From: aliciatang07 Date: Tue, 10 Feb 2026 16:42:04 +0000 Subject: [PATCH 4/7] update mock client --- .../cloudrun/client/mocks/mock_cloudrunclient.go | 6 ++++++ devops-mcp-server/cloudrun/cloudrun.go | 1 + 2 files changed, 7 insertions(+) diff --git a/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go b/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go index fdb6cd1..f2d9f03 100644 --- a/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go @@ -30,6 +30,7 @@ type MockCloudRunClient struct { DeployFromSourceFunc func(ctx context.Context, projectID, location, serviceName, source string, port int32, allowPublicAccess bool) error DeleteServiceFunc func(ctx context.Context, projectID, location, serviceName string) error SetServiceAccessFunc func(ctx context.Context, serviceName string, allowPublicAccess bool) error + GetServiceStatusFunc func(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) } // DeleteService mocks the DeleteService method. @@ -70,3 +71,8 @@ func (m *MockCloudRunClient) DeployFromSource(ctx context.Context, projectID, lo func (m *MockCloudRunClient) SetServiceAccess(ctx context.Context, serviceName string, allowPublicAccess bool) error { return m.SetServiceAccessFunc(ctx, serviceName, allowPublicAccess) } + +// GetServiceStatus mocks the GetServiceStatus method. +func (m *MockCloudRunClient) GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { + return m.GetServiceStatusFunc(ctx, projectID, location, serviceName) +} diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index d8bfd38..f8552fd 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -150,4 +150,5 @@ func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRu } return &mcp.CallToolResult{}, state, nil } + mcp.AddTool(server, &mcp.Tool{Name: "cloudrun.service_status", Description: "Gets the current status of a Cloud Run service."}, getServiceStatusToolFunc) } From 46272577b9972e5a90848b0177767e08e34d0543 Mon Sep 17 00:00:00 2001 From: aliciatang07 Date: Tue, 10 Feb 2026 16:52:49 +0000 Subject: [PATCH 5/7] fix bug --- devops-mcp-server/cloudrun/cloudrun.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index f8552fd..0e580f7 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -142,8 +142,10 @@ type GetServiceStatusArgs struct{ ServiceName string `json:"service_name" jsonschema:"The Cloud Run service name"` } +var getServiceStatusToolFunc func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) + func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { - getServiceStatusToolFunc = func(ctx context.Context, req* mcp.CallToolRequest, args GetServiceStatusArgs){ + getServiceStatusToolFunc = func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs){ state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) if err != nil { return &mcp.CallToolResult{}, nil, fmt.Errorf("failed to get service state: %w", err) From f694197f310c8853289d7965bbb7c0db5dde123e Mon Sep 17 00:00:00 2001 From: aliciatang07 Date: Tue, 10 Feb 2026 17:04:11 +0000 Subject: [PATCH 6/7] fix bug --- devops-mcp-server/cloudrun/cloudrun.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index 0e580f7..447abfa 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -145,7 +145,7 @@ type GetServiceStatusArgs struct{ var getServiceStatusToolFunc func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { - getServiceStatusToolFunc = func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs){ + getServiceStatusToolFunc = func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) { state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) if err != nil { return &mcp.CallToolResult{}, nil, fmt.Errorf("failed to get service state: %w", err) From ebdc3d63ddc83a5e404a076f30acdef5da271f8b Mon Sep 17 00:00:00 2001 From: "Xuejie(Alicia) Tang" Date: Tue, 10 Feb 2026 12:53:00 -0500 Subject: [PATCH 7/7] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- devops-mcp-server/cloudrun/client/cloudrunclient.go | 3 +++ devops-mcp-server/cloudrun/cloudrun.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/devops-mcp-server/cloudrun/client/cloudrunclient.go b/devops-mcp-server/cloudrun/client/cloudrunclient.go index d73c9f9..be9a550 100644 --- a/devops-mcp-server/cloudrun/client/cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/cloudrunclient.go @@ -151,6 +151,9 @@ func (c *CloudRunClientImpl) GetServiceStatus(ctx context.Context, projectID, lo return nil, fmt.Errorf("failed to get service: %w", err) } terminalCondition := service.GetTerminalCondition() + if terminalCondition == nil { + return nil, fmt.Errorf("service %q does not have a terminal condition", service.Name) + } return &terminalCondition.State, nil } diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index 447abfa..1f5761f 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -146,11 +146,11 @@ var getServiceStatusToolFunc func(ctx context.Context, req *mcp.CallToolRequest, func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { getServiceStatusToolFunc = func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) { - state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) + state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) if err != nil { return &mcp.CallToolResult{}, nil, fmt.Errorf("failed to get service state: %w", err) } - return &mcp.CallToolResult{}, state, nil + return &mcp.CallToolResult{}, state, nil } mcp.AddTool(server, &mcp.Tool{Name: "cloudrun.service_status", Description: "Gets the current status of a Cloud Run service."}, getServiceStatusToolFunc) }