{
  "slug": "com-pulsemcp-gcs",
  "name": "com.pulsemcp/gcs",
  "title": "gcs",
  "description": "MCP server for Google Cloud Storage with fine-grained tool access control.",
  "version": "0.1.14",
  "publishedAt": "2026-06-17T03:55:50.855481Z",
  "updatedAt": "2026-06-17T03:55:50.855481Z",
  "repoUrl": "https://github.com/pulsemcp/mcp-servers",
  "websiteUrl": null,
  "namespace": {
    "type": "domain",
    "owner": "pulsemcp.com"
  },
  "kind": "local",
  "packages": [
    {
      "registryType": "npm",
      "identifier": "gcs-google-mcp-server",
      "version": "0.1.14",
      "transport": "stdio",
      "runtimeHint": "npx"
    }
  ],
  "remotes": [],
  "envVars": [
    {
      "name": "GCS_PROJECT_ID",
      "isSecret": false,
      "isRequired": true,
      "description": "Google Cloud project ID."
    },
    {
      "name": "GCS_SERVICE_ACCOUNT_KEY_FILE",
      "isSecret": true,
      "isRequired": false,
      "description": "Path to service account key JSON file."
    },
    {
      "name": "GCS_SERVICE_ACCOUNT_KEY_JSON",
      "isSecret": true,
      "isRequired": false,
      "description": "Service account key JSON contents (inline)."
    },
    {
      "name": "GCS_BUCKET",
      "isSecret": false,
      "isRequired": false,
      "description": "Constrain all operations to a single bucket (hides bucket-level tools)."
    },
    {
      "name": "GCS_ENABLED_TOOLGROUPS",
      "isSecret": false,
      "isRequired": false,
      "description": "Comma-separated tool groups to enable (readonly, readwrite, delete)."
    },
    {
      "name": "GCS_ENABLED_TOOLS",
      "isSecret": false,
      "isRequired": false,
      "description": "Comma-separated list of specific tools to enable (overrides groups)."
    },
    {
      "name": "GCS_DISABLED_TOOLS",
      "isSecret": false,
      "isRequired": false,
      "description": "Comma-separated list of specific tools to disable."
    },
    {
      "name": "SKIP_HEALTH_CHECKS",
      "isSecret": false,
      "isRequired": false,
      "description": "Skip health checks on startup."
    }
  ],
  "category": "cloud-infra",
  "subcategory": "providers",
  "company": "",
  "categoryAuto": true,
  "checks": [
    {
      "id": "source-linked",
      "label": "Source repository linked",
      "result": "pass",
      "detail": "https://github.com/pulsemcp/mcp-servers"
    },
    {
      "id": "version-pinned",
      "label": "Version pinned",
      "result": "pass",
      "detail": "Every package has an explicit version"
    },
    {
      "id": "secrets-requested",
      "label": "Secrets requested",
      "result": "info",
      "detail": "Asks for 2 secrets: GCS_SERVICE_ACCOUNT_KEY_FILE, GCS_SERVICE_ACCOUNT_KEY_JSON"
    },
    {
      "id": "known-registry",
      "label": "Known package registry",
      "result": "pass",
      "detail": "All packages come from npm, PyPI, OCI, NuGet or MCPB"
    },
    {
      "id": "namespace",
      "label": "Namespace ownership",
      "result": "info",
      "detail": "Name verified via domain pulsemcp.com"
    },
    {
      "id": "meta-text",
      "label": "Registry text aimed at the AI",
      "result": "pass",
      "detail": "Description and settings contain no hidden characters or instructions to the AI"
    },
    {
      "id": "install-scripts",
      "label": "Install scripts",
      "result": "pass",
      "detail": "gcs-google-mcp-server@0.1.14 runs nothing at install"
    },
    {
      "id": "code-flags",
      "label": "Code red flags",
      "result": "pass",
      "detail": "Read 49 files in gcs-google-mcp-server@0.1.14: no obfuscation, encoded execution, credential reads or data-collection endpoints found"
    },
    {
      "id": "ai-text",
      "label": "Text aimed at the AI",
      "result": "pass",
      "detail": "No hidden characters or instructions to the AI in 49 files, including comments and the README"
    }
  ],
  "scannedAt": "2026-10-29",
  "level": "Scanned",
  "install": [
    {
      "label": "Claude Desktop (npm)",
      "kind": "claude_desktop_json",
      "text": "{\n  \"mcpServers\": {\n    \"gcs\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"gcs-google-mcp-server@0.1.14\"\n      ],\n      \"env\": {\n        \"GCS_PROJECT_ID\": \"<your value>\"\n      }\n    }\n  }\n}"
    }
  ],
  "curated": true,
  "stars": 81,
  "archived": false,
  "pushedAt": "2026-10-09T17:32:15Z",
  "review": {
    "package": "gcs-google-mcp-server",
    "version": "0.1.14",
    "at": "2026-10-31",
    "files": 47,
    "lines": 3038,
    "verdict": "pass-with-notes",
    "summary": "Lets an AI assistant browse, read, upload, copy and delete files in your Google Cloud Storage buckets. It talks only to Google Cloud using the credentials you configure, checking them once at startup; there is no telemetry. Be aware it can upload any file on your computer to a bucket and save downloads to any path, and delete tools are on by default; use GCS_ENABLED_TOOLGROUPS=readonly or GCS_DISABLED_TOOLS to limit it.",
    "hosts": [
      {
        "host": "storage.googleapis.com (via @google-cloud/storage)",
        "when": "At startup (health check: listBuckets, or listObjects on GCS_BUCKET, unless SKIP_HEALTH_CHECKS=true) and whenever a tool is called",
        "sends": "Google credentials/access token, bucket and object names, object contents you put or upload (including local files read by put_object_from_path / upload_prefix)"
      },
      {
        "host": "oauth2.googleapis.com / Google metadata server (via @google-cloud/storage auth)",
        "when": "When an access token is needed",
        "sends": "Service-account signed JWT or Application Default Credentials"
      }
    ],
    "env": [
      {
        "name": "GCS_PROJECT_ID",
        "sent_to": "Google Cloud Storage API (project parameter); also shown in the gcs://config resource"
      },
      {
        "name": "GCS_SERVICE_ACCOUNT_KEY_FILE",
        "sent_to": "not sent; path read locally by the Google SDK to sign tokens (masked in gcs://config)"
      },
      {
        "name": "GCS_SERVICE_ACCOUNT_KEY_JSON",
        "sent_to": "not sent directly; used by the Google SDK to sign tokens for Google OAuth (masked in gcs://config)"
      },
      {
        "name": "GCS_BUCKET",
        "sent_to": "Google Cloud Storage API; forces the bucket parameter on object tools"
      },
      {
        "name": "GCS_ENABLED_TOOLGROUPS / GCS_ENABLED_TOOLS / GCS_DISABLED_TOOLS / SKIP_HEALTH_CHECKS",
        "sent_to": "not sent; local config"
      },
      {
        "name": "NODE_ENV / DEBUG",
        "sent_to": "not sent; debug logging"
      },
      {
        "name": "GCS_MOCK_DATA",
        "sent_to": "not sent; test entry only"
      }
    ],
    "local": "Broad, by design, and driven by tool input: put_object_from_path reads ANY local file path the AI supplies and uploads it; upload_prefix recursively reads ANY local directory (following symlinks to files) and uploads it; download_object writes to ANY destinationPath the AI supplies (can overwrite files); download_prefix writes into ANY destinationDir (object keys escaping that dir are blocked). Default download locations are under os.tmpdir() with traversal checks. Also reads its own package.json, and the key file via the Google SDK.",
    "exec": "None. No child_process, eval or Function.",
    "telemetry": "None. The only startup network call is the credential health check to Google (skippable with SKIP_HEALTH_CHECKS=true).",
    "tools": [
      "list_buckets",
      "list_objects",
      "get_object",
      "download_object",
      "download_prefix",
      "head_bucket",
      "put_object",
      "put_object_from_path",
      "upload_prefix",
      "copy_object",
      "create_bucket",
      "delete_object",
      "delete_bucket"
    ],
    "toolText": "clean",
    "deps": [
      "@modelcontextprotocol/sdk",
      "zod",
      "@google-cloud/storage"
    ],
    "findings": [
      {
        "severity": "note",
        "at": "shared/tools/put-object-from-path.js:57-65; shared/tools/upload-prefix.js:121-136",
        "what": "Local-file exfiltration surface: the AI can upload any file or folder the process can read (SSH keys, .env files, browser profiles) to any bucket the credentials can write to. No path allow-list; GCS_BUCKET limits the destination bucket but not the source path. Clearly described in the tool text. Disable with GCS_DISABLED_TOOLS=put_object_from_path,upload_prefix or GCS_ENABLED_TOOLGROUPS=readonly."
      },
      {
        "severity": "note",
        "at": "shared/tools/download-object.js:43-58",
        "what": "download_object writes to any destinationPath supplied by the AI with no restriction, so it can overwrite arbitrary local files (shell profile, startup scripts) with bucket contents."
      },
      {
        "severity": "note",
        "at": "shared/tools.js:16-64",
        "what": "All groups including 'delete' (delete_object, delete_bucket) and the write tools are enabled by default; deletions are immediate with no confirmation."
      },
      {
        "severity": "info",
        "at": "build/index.js:97-125",
        "what": "Makes one Google API call at startup to validate credentials (listBuckets, or listObjects on GCS_BUCKET). Skippable via SKIP_HEALTH_CHECKS=true."
      },
      {
        "severity": "info",
        "at": "shared/tools/download-prefix.js:90-93",
        "what": "With no destinationDir, the default folder name includes the unvalidated bucket string and mkdir runs before the bucket is checked, so a bucket value containing '../' can create an empty directory outside the temp folder. Low impact."
      },
      {
        "severity": "info",
        "at": "shared/resources.js:21-52",
        "what": "gcs://config resource exposes project ID, bucket constraint and tool filters; key file path/JSON are masked as ***configured***. It reports a hard-coded version '0.0.0'."
      },
      {
        "severity": "info",
        "at": "shared/tools.js:129-132",
        "what": "GCS_ENABLED_TOOLS is documented as overriding groups but only narrows within enabled groups. Cosmetic."
      },
      {
        "severity": "info",
        "at": "(package)",
        "what": "package.json was not part of the review set; the dependency list is inferred from imports, and install scripts (if any) could not be checked."
      }
    ]
  },
  "health": {
    "score": 64,
    "parts": {
      "popularity": 0.42249727076826255,
      "activity": 0.6674452394758004,
      "issues": 0.7096774193548387,
      "security": 1
    },
    "fail": 0,
    "warn": 0,
    "raw": {
      "stars": 81,
      "forks": 10,
      "downloads": 131,
      "hn": {
        "n": 0,
        "pts": 0,
        "t": []
      },
      "issuesOpen": 27,
      "issuesClosed": 66,
      "prsMerged": 491,
      "commits90": 1,
      "release": "2025-07-03T16:10:39Z",
      "pushed": "2026-10-09T17:32:15Z",
      "growth": null,
      "growthDays": null,
      "archived": false
    },
    "at": "2026-10-31T07:42:38.200Z"
  }
}
