@google-cloud/cloud-run-mcp 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,6 +18,7 @@ import {
18
18
  listBillingAccounts,
19
19
  attachProjectToBillingAccount,
20
20
  } from './billing.js';
21
+ import { getProjectsClient } from '../clients.js';
21
22
 
22
23
  /**
23
24
  * Lists all accessible Google Cloud Platform projects.
@@ -26,8 +27,7 @@ import {
26
27
  * @returns {Promise<Array<{id: string}>>} A promise that resolves to an array of project objects, each with an 'id' property. Returns an empty array on error.
27
28
  */
28
29
  export async function listProjects() {
29
- const { ProjectsClient } = await import('@google-cloud/resource-manager');
30
- const client = new ProjectsClient();
30
+ const client = await getProjectsClient();
31
31
  try {
32
32
  const [projects] = await client.searchProjects();
33
33
  return projects.map((project) => ({
@@ -72,8 +72,7 @@ export function generateProjectId() {
72
72
  * @returns {Promise<{projectId: string}|null>} A promise that resolves to an object containing the new project's ID.
73
73
  */
74
74
  export async function createProject(projectId, parent) {
75
- const { ProjectsClient } = await import('@google-cloud/resource-manager');
76
- const client = new ProjectsClient();
75
+ const client = await getProjectsClient();
77
76
  let projectIdToUse = projectId;
78
77
 
79
78
  if (!projectIdToUse) {
@@ -173,8 +172,7 @@ export async function createProjectAndAttachBilling(projectIdParam, parent) {
173
172
  * @returns {Promise<void>} A promise that resolves when the delete operation is initiated.
174
173
  */
175
174
  export async function deleteProject(projectId) {
176
- const { ProjectsClient } = await import('@google-cloud/resource-manager');
177
- const client = new ProjectsClient();
175
+ const client = await getProjectsClient();
178
176
  try {
179
177
  console.log(`Attempting to delete project with ID: ${projectId}`);
180
178
  await client.deleteProject({ name: `projects/${projectId}` });
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
16
 
17
+ import { getArtifactRegistryClient } from '../clients.js';
17
18
  import { callWithRetry } from './helpers.js';
18
19
  import { logAndProgress } from '../util/helpers.js';
19
20
 
@@ -22,7 +23,6 @@ import { logAndProgress } from '../util/helpers.js';
22
23
  * If the repository does not exist, it attempts to create it with the specified format.
23
24
  *
24
25
  * @async
25
- * @param {object} context - The context object containing clients and other parameters.
26
26
  * @param {string} projectId - The Google Cloud project ID.
27
27
  * @param {string} location - The Google Cloud region for the repository.
28
28
  * @param {string} repositoryId - The ID for the Artifact Registry repository.
@@ -32,15 +32,15 @@ import { logAndProgress } from '../util/helpers.js';
32
32
  * @throws {Error} If there's an error checking or creating the repository.
33
33
  */
34
34
  export async function ensureArtifactRegistryRepoExists(
35
- context,
36
35
  projectId,
37
36
  location,
38
37
  repositoryId,
39
38
  format = 'DOCKER',
40
39
  progressCallback
41
40
  ) {
41
+ const artifactRegistryClient = await getArtifactRegistryClient(projectId);
42
42
  const parent = `projects/${projectId}/locations/${location}`;
43
- const repoPath = context.artifactRegistryClient.repositoryPath(
43
+ const repoPath = artifactRegistryClient.repositoryPath(
44
44
  projectId,
45
45
  location,
46
46
  repositoryId
@@ -48,7 +48,7 @@ export async function ensureArtifactRegistryRepoExists(
48
48
 
49
49
  try {
50
50
  const [repository] = await callWithRetry(
51
- () => context.artifactRegistryClient.getRepository({ name: repoPath }),
51
+ () => artifactRegistryClient.getRepository({ name: repoPath }),
52
52
  `artifactRegistry.getRepository ${repositoryId}`
53
53
  );
54
54
  await logAndProgress(
@@ -68,7 +68,7 @@ export async function ensureArtifactRegistryRepoExists(
68
68
 
69
69
  const [operation] = await callWithRetry(
70
70
  () =>
71
- context.artifactRegistryClient.createRepository({
71
+ artifactRegistryClient.createRepository({
72
72
  parent: parent,
73
73
  repository: repositoryToCreate,
74
74
  repositoryId: repositoryId,
@@ -15,13 +15,14 @@ limitations under the License.
15
15
  */
16
16
 
17
17
  import protofiles from 'google-proto-files';
18
+ import {
19
+ getRunClient,
20
+ getServiceUsageClient,
21
+ getLoggingClient,
22
+ } from '../clients.js';
18
23
  import { callWithRetry, ensureApisEnabled } from './helpers.js';
19
24
  import { logAndProgress } from '../util/helpers.js';
20
25
 
21
- let runClient;
22
- let serviceUsageClient;
23
- let loggingClient;
24
-
25
26
  async function listCloudRunLocations(projectId) {
26
27
  const listLocationsRequest = {
27
28
  name: `projects/${projectId}`,
@@ -29,6 +30,7 @@ async function listCloudRunLocations(projectId) {
29
30
 
30
31
  const availableLocations = [];
31
32
  try {
33
+ const runClient = await getRunClient(projectId);
32
34
  console.log('Listing Cloud Run supported locations:');
33
35
  const iterable = runClient.listLocationsAsync(listLocationsRequest);
34
36
  for await (const location of iterable) {
@@ -50,18 +52,9 @@ async function listCloudRunLocations(projectId) {
50
52
  * @returns {Promise<object>} - A promise that resolves to an object mapping region to list of service objects in that region.
51
53
  */
52
54
  export async function listServices(projectId) {
53
- if (!runClient) {
54
- const { v2 } = await import('@google-cloud/run');
55
- const { ServicesClient } = v2;
56
- const { ServiceUsageClient } = await import('@google-cloud/service-usage');
57
- runClient = new ServicesClient({ projectId });
58
- serviceUsageClient = new ServiceUsageClient({ projectId });
59
- }
60
- const context = {
61
- runClient: runClient,
62
- serviceUsageClient: serviceUsageClient,
63
- };
64
- await ensureApisEnabled(context, projectId, ['run.googleapis.com']);
55
+ const runClient = await getRunClient(projectId);
56
+
57
+ await ensureApisEnabled(projectId, ['run.googleapis.com']);
65
58
  const locations = await listCloudRunLocations(projectId);
66
59
 
67
60
  const allServices = {};
@@ -93,11 +86,7 @@ export async function listServices(projectId) {
93
86
  * @returns {Promise<object>} - A promise that resolves to the service object.
94
87
  */
95
88
  export async function getService(projectId, location, serviceId) {
96
- if (!runClient) {
97
- const { v2 } = await import('@google-cloud/run');
98
- const { ServicesClient } = v2;
99
- runClient = new ServicesClient({ projectId });
100
- }
89
+ const runClient = await getRunClient(projectId);
101
90
 
102
91
  const servicePath = runClient.servicePath(projectId, location, serviceId);
103
92
 
@@ -138,10 +127,7 @@ export async function getServiceLogs(
138
127
  serviceId,
139
128
  requestOptions
140
129
  ) {
141
- if (!loggingClient) {
142
- const { Logging } = await import('@google-cloud/logging');
143
- loggingClient = new Logging({ projectId });
144
- }
130
+ const loggingClient = await getLoggingClient(projectId);
145
131
 
146
132
  try {
147
133
  const LOG_SEVERITY = 'DEFAULT'; // e.g., 'DEFAULT', 'INFO', 'WARNING', 'ERROR'
@@ -237,21 +223,16 @@ function formatLogEntry(entry) {
237
223
  * @throws {Error} If there's an error checking the service (other than not found).
238
224
  */
239
225
  export async function checkCloudRunServiceExists(
240
- context,
241
226
  projectId,
242
227
  location,
243
228
  serviceId,
244
229
  progressCallback
245
230
  ) {
246
- const parent = context.runClient.locationPath(projectId, location);
247
- const servicePath = context.runClient.servicePath(
248
- projectId,
249
- location,
250
- serviceId
251
- );
231
+ const runClient = await getRunClient(projectId);
232
+ const servicePath = runClient.servicePath(projectId, location, serviceId);
252
233
  try {
253
234
  await callWithRetry(
254
- () => context.runClient.getService({ name: servicePath }),
235
+ () => runClient.getService({ name: servicePath }),
255
236
  `getService ${serviceId}`
256
237
  );
257
238
  await logAndProgress(
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */
16
16
 
17
+ import { getStorageClient } from '../clients.js';
17
18
  import { callWithRetry } from './helpers.js';
18
19
  import { logAndProgress } from '../util/helpers.js';
19
20
 
@@ -22,7 +23,7 @@ import { logAndProgress } from '../util/helpers.js';
22
23
  * If the bucket does not exist, it attempts to create it in the specified location.
23
24
  *
24
25
  * @async
25
- * @param {object} context - The context object containing clients and other parameters.
26
+ * @param {string} projectId - The Google Cloud project ID.
26
27
  * @param {string} bucketName - The name of the storage bucket.
27
28
  * @param {string} [location='us'] - The location to create the bucket in if it doesn't exist. Defaults to 'us'.
28
29
  * @param {function(object): void} [progressCallback] - Optional callback for progress updates.
@@ -30,12 +31,13 @@ import { logAndProgress } from '../util/helpers.js';
30
31
  * @throws {Error} If there's an error checking or creating the bucket.
31
32
  */
32
33
  export async function ensureStorageBucketExists(
33
- context,
34
+ projectId,
34
35
  bucketName,
35
36
  location = 'us',
36
37
  progressCallback
37
38
  ) {
38
- const bucket = context.storage.bucket(bucketName);
39
+ const storage = await getStorageClient(projectId);
40
+ const bucket = storage.bucket(bucketName);
39
41
  try {
40
42
  const [exists] = await callWithRetry(
41
43
  () => bucket.exists(),
@@ -54,8 +56,7 @@ export async function ensureStorageBucketExists(
54
56
  );
55
57
  try {
56
58
  const [createdBucket] = await callWithRetry(
57
- () =>
58
- context.storage.createBucket(bucketName, { location: location }),
59
+ () => storage.createBucket(bucketName, { location: location }),
59
60
  `storage.createBucket ${bucketName}`
60
61
  );
61
62
  await logAndProgress(
@@ -85,7 +86,6 @@ export async function ensureStorageBucketExists(
85
86
  * Uploads a buffer to a specified Google Cloud Storage bucket and blob name.
86
87
  *
87
88
  * @async
88
- * @param {object} context - The context object containing clients and other parameters.
89
89
  * @param {import('@google-cloud/storage').Bucket} bucket - The Google Cloud Storage bucket object.
90
90
  * @param {Buffer} buffer - The buffer containing the data to upload.
91
91
  * @param {string} destinationBlobName - The name for the blob in the bucket.
@@ -94,7 +94,6 @@ export async function ensureStorageBucketExists(
94
94
  * @throws {Error} If the upload fails.
95
95
  */
96
96
  export async function uploadToStorageBucket(
97
- context,
98
97
  bucket,
99
98
  buffer,
100
99
  destinationBlobName,
@@ -0,0 +1,54 @@
1
+ /*
2
+ Copyright 2025 Google LLC
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ export const DEPLOYMENT_CONFIG = {
18
+ REPO_NAME: 'mcp-cloud-run-deployments',
19
+ ZIP_FILE_NAME: 'source.zip',
20
+ TARGZ_FILE_NAME: 'source.tar.gz',
21
+ IMAGE_TAG: 'latest',
22
+ LABEL_CREATED_BY: 'cloud-run-mcp',
23
+ DEFAULT_NODE_BASE_IMAGE: 'nodejs22',
24
+ NO_BUILD_IMAGE_TYPE: 'scratch',
25
+ };
26
+
27
+ export const TEMP_PATHS = {
28
+ BASE: '.cloud-run-mcp',
29
+ SUBDIR: 'source',
30
+ };
31
+
32
+ export const REQUIRED_APIS = {
33
+ SOURCE_DEPLOY: [
34
+ 'serviceusage.googleapis.com',
35
+ 'iam.googleapis.com',
36
+ 'storage.googleapis.com',
37
+ 'cloudbuild.googleapis.com',
38
+ 'artifactregistry.googleapis.com',
39
+ 'run.googleapis.com',
40
+ ],
41
+ IMAGE_DEPLOY: ['serviceusage.googleapis.com', 'run.googleapis.com'],
42
+ };
43
+
44
+ export const DEPLOYMENT_TYPES = {
45
+ NO_BUILD: 'no-build',
46
+ IMAGE: 'image',
47
+ WITH_BUILD: 'with-build',
48
+ };
49
+
50
+ export const RUNTIMES = {
51
+ NODEJS: 'nodejs',
52
+ };
53
+
54
+ export const MAX_ALLOWED_DIRECT_SOURCE_SIZE_BYTES = 250 * 1024 * 1024; // 250 MiB