# Google Cloud Activation Guide

Canonical page: https://www.kuudo.com/docs/cloud/gcp-activation-guide/


This guide explains how to prepare Google Cloud so the in-app **environment wizard** (Configuration → Credentials → Validation → Review & create) can create infrastructure successfully.

**Core idea:** prepare GCP first (usually with the `gcloud` CLI), then copy the project ID, region, and service account key into the product. Validation checks credential and project access, then provisioning verifies Cloud Run access and prepares Artifact Registry.

---

## Quick path

1. Sign in with your Google account and select the correct project ([§ Sign in and select the project](#sign-in-and-select-the-project)).
2. Enable the required APIs: **Cloud Run**, **Artifact Registry**, **Cloud Resource Manager** ([§ Enable APIs](#enable-required-apis)).
3. Create or reuse a service account and grant it the right roles ([§ Service account](#create-or-reuse-a-service-account)).
4. Create a JSON key for the service account and save the file ([§ Service account key](#create-a-service-account-key)).
5. Verify the key works against your project ([§ Verify the service account](#verify-the-service-account)).
6. Open the wizard: **Configuration** → **Credentials** → run **Validation** → **Review & create** ([§ Complete the wizard](#complete-the-wizard-in-the-app)).
7. If something fails, use [§ Common issues](#common-issues).

---

## Prerequisites

- Access to the target Google Cloud project.
- Permission to grant IAM roles (for example **Owner** or **IAM Admin**) when binding roles to the service account.
- Billing **enabled** on the project (Cloud Run and Artifact Registry require it, even at $0 usage).
- [`gcloud` CLI](https://docs.cloud.google.com/sdk/docs/install-sdk) installed locally, or [Cloud Shell](https://docs.cloud.google.com/shell/docs) from the GCP console.

The CLI is recommended because console labels and layout change more often than command-line flows.

---

## Field reference

The wizard matches GCP outputs like this:

| What you do in GCP                                 | Output to copy                           | Wizard field                   |
| -------------------------------------------------- | ---------------------------------------- | ------------------------------ |
| Project picker / `gcloud config get-value project` | Project ID (not the project number/name) | **Project ID**                 |
| Your choice of deploy location                     | Cloud Run region, e.g. `us-central1`     | **Region** (Credentials step)  |
| IAM & Admin → Service Accounts → Keys → Add Key    | Downloaded **JSON file contents**        | **Service Account Key (JSON)** |
| (your label only)                                  | Any name                                 | **Environment Name**           |

**Project ID vs project number vs project name:** the wizard wants the **Project ID** (e.g. `my-mcp-project-481923`), which is a lowercase string with optional digits/dashes — not the numeric project number and not the human-readable display name.

**Region:** use a valid Cloud Run region identifier (lowercase with hyphens). List supported regions:

```bash
gcloud run regions list
```

**Service Account Key (JSON):** paste the **entire contents** of the downloaded JSON file, including the `{ ... }` braces. The wizard validates that it has `type: "service_account"`, a PEM-formatted `private_key`, and a `client_email` ending in `.iam.gserviceaccount.com`. Google recommends avoiding user-managed service account keys when a safer alternative is available; use this key flow only when the deployment wizard requires a JSON key.

---

## Prepare GCP with the CLI

Run the steps below as **your GCP user/admin** unless noted. Replace placeholders such as `<PROJECT_ID>` and `<SA_NAME>` with your values.

### Sign in and select the project

```bash
gcloud auth login
gcloud projects list
gcloud config set project <PROJECT_ID>
gcloud config get-value project
```

Record the value of `gcloud config get-value project` — this becomes the wizard's **Project ID**.

### Enable required APIs

These APIs are required for the MCP deployment path described here:

- `run.googleapis.com` — Cloud Run (runtime)
- `artifactregistry.googleapis.com` — Artifact Registry (private image storage)
- `cloudresourcemanager.googleapis.com` — Resource Manager (used by validation to fetch project metadata)

```bash
gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudresourcemanager.googleapis.com \
  --project <PROJECT_ID>
```

Verify (each should appear in the list):

```bash
gcloud services list --enabled --project <PROJECT_ID> \
  --filter="config.name:(run.googleapis.com OR artifactregistry.googleapis.com OR cloudresourcemanager.googleapis.com)" \
  --format="value(config.name)"
```

API enablement can take a minute or two to propagate. If validation fails immediately after enabling, wait and retry.

### Create or reuse a service account

Reuse an existing service account if you already have one with the right roles.

**Option A — new service account (quick setup):**

```bash
gcloud iam service-accounts create <SA_NAME> \
  --display-name "MCP Deployment Service Account" \
  --project <PROJECT_ID>
```

The full email becomes `<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com`.

**Option B — console:** **IAM & Admin** → **Service Accounts** → **Create service account**.

### Grant IAM roles

Validation needs the service account to read project metadata; provisioning needs permission to manage Cloud Run services and Artifact Registry repositories. Grant these roles at **project scope**:

| Role                                       | Why                                                             |
| ------------------------------------------ | --------------------------------------------------------------- |
| `roles/run.developer`                      | Create, update, and delete Cloud Run services                   |
| `roles/artifactregistry.admin`             | First-run repository creation + image push in Artifact Registry |
| `roles/iam.serviceAccountUser`             | Allow Cloud Run to act as the runtime service account           |
| `roles/serviceusage.serviceUsageConsumer`  | Commonly required in org policies for service usage checks      |
| `roles/viewer` (or equivalent read access) | Read project metadata (`cloudresourcemanager.projects.get`)     |

```bash
SA_EMAIL=<SA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com

for ROLE in \
  roles/run.developer \
  roles/artifactregistry.admin \
  roles/iam.serviceAccountUser \
  roles/serviceusage.serviceUsageConsumer \
  roles/viewer
do
  gcloud projects add-iam-policy-binding <PROJECT_ID> \
    --member "serviceAccount:$SA_EMAIL" \
    --role "$ROLE"
done
```

Verify:

```bash
gcloud projects get-iam-policy <PROJECT_ID> \
  --flatten="bindings[].members" \
  --filter="bindings.members:$SA_EMAIL" \
  --format="value(bindings.role)"
```

You should see these roles listed for that service account.

> **Least privilege note**
> For tighter scoping, replace `roles/artifactregistry.admin` with `roles/artifactregistry.writer` **after** the repository has been created the first time. Initial provisioning may need repository-create permissions.

> **Public endpoint note**
> If deployments succeed but your endpoint still requires authentication, add `roles/run.admin` so the deploy flow can set the Cloud Run service IAM policy and grant `roles/run.invoker` to `allUsers`.

### Create a service account key

```bash
gcloud iam service-accounts keys create ./mcp-sa-key.json \
  --iam-account "$SA_EMAIL" \
  --project <PROJECT_ID>
```

This writes a JSON file. Open it and copy the **entire contents** when filling out the wizard. Treat this file as secret — anyone with it can act as the service account.

> **Key rotation**
> GCP service account keys do not expire by default but should be rotated periodically. List existing keys with `gcloud iam service-accounts keys list --iam-account "$SA_EMAIL"`, create a new one, update the wizard, then delete the old key with `gcloud iam service-accounts keys delete <KEY_ID> --iam-account "$SA_EMAIL"`.

### Verify the service account

This separates GCP misconfiguration from product issues. Activate the key and run a few read-only calls.

```bash
gcloud auth activate-service-account --key-file ./mcp-sa-key.json
gcloud config set project <PROJECT_ID>

# 1. Project is readable (matches the wizard's validation call)
gcloud projects describe <PROJECT_ID>

# 2. Cloud Run API is enabled and listable
gcloud run services list --region <REGION>

# 3. Artifact Registry is accessible
gcloud artifacts repositories list --location <REGION>
```

If all three calls succeed, authentication, project access, and the required APIs are working.

Switch back to your user account when done:

```bash
gcloud auth login
gcloud config set account <YOUR_EMAIL>
```

---

## Complete the wizard in the app

Use the [Field reference](#field-reference) for definitions.

### Configuration

- **Environment Name** — label in your app (for example `gcp`).
- **Project ID** — GCP project ID from [§ Sign in](#sign-in-and-select-the-project).
- **Region** — Cloud Run region, e.g. `us-central1`.

### Credentials

- **Service Account Key (JSON)** — paste the full contents of the JSON file from [§ Service account key](#create-a-service-account-key).

### Validation

Run validation in the UI. It should succeed when the key parses cleanly and the service account can read the project via Resource Manager.

Cloud Run API access checks and Artifact Registry repository preparation happen during provisioning right after **Review & create**.

### Review & create

After validation succeeds, finish creating the environment.

---

## Common issues

| Symptom or error                                                                                | Likely cause                                                      | What to do                                                                                                                         |
| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `Missing required field: <field>` from validation                                               | Pasted only part of the JSON, or pasted a non-key file            | Re-paste the **entire** JSON file contents, including `{` and `}`.                                                                 |
| `Invalid private key format. Expected PEM format.`                                              | Newlines mangled when copy/pasting (e.g. `\n` literals replaced)  | Re-download or re-open the original JSON file and paste it exactly — do not edit.                                                  |
| `Invalid service account email format`                                                          | Pasted a user OAuth credential, not a service account key         | Create a key under **IAM & Admin → Service Accounts**, not **APIs & Services → Credentials**.                                      |
| Validation succeeds, but provisioning fails with `Cloud Run API is not enabled`                 | `run.googleapis.com` is disabled on the project                   | `gcloud services enable run.googleapis.com` ([§ Enable APIs](#enable-required-apis)). Wait 1–2 minutes and retry.                  |
| Validation succeeds, but provisioning fails with `PERMISSION_DENIED` listing Cloud Run services | Service account is missing **Cloud Run Developer**                | Add `roles/run.developer` ([§ IAM roles](#grant-iam-roles)).                                                                       |
| Validation succeeds, but provisioning fails creating Artifact Registry repository               | Service account is missing repository-create permission           | Add `roles/artifactregistry.admin` for first run, then consider downgrading to `roles/artifactregistry.writer`.                    |
| Deployment works but service URL requires auth                                                  | Service account cannot set IAM policy for unauthenticated invoker | Add `roles/run.admin` and redeploy so `roles/run.invoker` can be granted to `allUsers`.                                            |
| `Permission 'resourcemanager.projects.get' denied`                                              | Project ID is wrong, or the SA can't read the project             | Confirm `gcloud config get-value project` matches **Project ID**; ensure the SA has any role on the project (e.g. `roles/viewer`). |
| `Billing has not been enabled`                                                                  | Project has no billing account attached                           | Link a billing account in the GCP console (**Billing → Link a billing account**), then retry.                                      |
| Pasted the **project number** (e.g. `483921047215`) instead of the Project ID                   | Wrong identifier                                                  | Use the lowercase string from `gcloud config get-value project`, not the numeric project number.                                   |
| Region rejected or `Cloud Run not available in <region>`                                        | Region typo or unsupported region                                 | Pick a value from `gcloud run regions list`.                                                                                       |
| Key recently created but validation still fails with auth errors                                | IAM/key propagation delay                                         | Wait ~60 seconds and retry; GCP IAM is eventually consistent.                                                                      |

## Official references

- [Cloud Run IAM roles](https://docs.cloud.google.com/run/docs/reference/iam/roles)
- [Cloud Run regions](https://docs.cloud.google.com/run/docs/locations)
- [Artifact Registry roles and permissions](https://docs.cloud.google.com/artifact-registry/docs/access-control)
- [Best practices for managing service account keys](https://docs.cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys)
- [Install the Google Cloud CLI](https://docs.cloud.google.com/sdk/docs/install-sdk)

---

## Appendix: Copy-paste activation script

The block below repeats [Prepare GCP with the CLI](#prepare-gcp-with-the-cli) in one place for convenience. Replace placeholders before running.

```bash
# --- As your GCP user ---

PROJECT_ID=<PROJECT_ID>
REGION=<REGION>           # e.g. us-central1
SA_NAME=<SA_NAME>         # e.g. mcp-deployer
SA_EMAIL="$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"

gcloud auth login
gcloud config set project "$PROJECT_ID"

# Enable APIs
gcloud services enable \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudresourcemanager.googleapis.com \
  --project "$PROJECT_ID"

# Create service account
gcloud iam service-accounts create "$SA_NAME" \
  --display-name "MCP Deployment Service Account" \
  --project "$PROJECT_ID"

# Grant roles
for ROLE in \
  roles/run.developer \
  roles/artifactregistry.admin \
  roles/iam.serviceAccountUser \
  roles/serviceusage.serviceUsageConsumer \
  roles/viewer
do
  gcloud projects add-iam-policy-binding "$PROJECT_ID" \
    --member "serviceAccount:$SA_EMAIL" \
    --role "$ROLE"
done

# Create JSON key (treat as secret)
gcloud iam service-accounts keys create ./mcp-sa-key.json \
  --iam-account "$SA_EMAIL" \
  --project "$PROJECT_ID"

# --- Test as the service account ---

gcloud auth activate-service-account --key-file ./mcp-sa-key.json
gcloud config set project "$PROJECT_ID"

gcloud projects describe "$PROJECT_ID"
gcloud run services list --region "$REGION"
gcloud artifacts repositories list --location "$REGION"
```

After this succeeds, fill the wizard using the [Field reference](#field-reference) and complete [§ Complete the wizard](#complete-the-wizard-in-the-app).

