{
  "slug": "io-github-snowflake-labs-mcp",
  "name": "io.github.Snowflake-Labs/mcp",
  "title": "OSS Snowflake MCP Server",
  "description": "MCP Server for Snowflake from Snowflake Labs",
  "version": "1.3.5",
  "publishedAt": "2025-10-28T15:19:33.176334Z",
  "updatedAt": "2025-10-28T15:19:33.176334Z",
  "repoUrl": "https://github.com/Snowflake-Labs/mcp",
  "websiteUrl": null,
  "namespace": {
    "type": "github",
    "owner": "Snowflake-Labs"
  },
  "kind": "local",
  "packages": [
    {
      "registryType": "pypi",
      "identifier": "snowflake-labs-mcp",
      "version": "1.3.5",
      "transport": "stdio",
      "runtimeHint": null
    }
  ],
  "remotes": [],
  "envVars": [
    {
      "name": "SNOWFLAKE_ACCOUNT",
      "isSecret": false,
      "isRequired": false,
      "description": "Account identifier (e.g. xy12345.us-east-1)"
    },
    {
      "name": "SNOWFLAKE_HOST",
      "isSecret": false,
      "isRequired": false,
      "description": "Snowflake host URL"
    },
    {
      "name": "SNOWFLAKE_USER",
      "isSecret": false,
      "isRequired": false,
      "description": "Username for authentication"
    },
    {
      "name": "SNOWFLAKE_PASSWORD",
      "isSecret": true,
      "isRequired": false,
      "description": "Password or programmatic access token"
    },
    {
      "name": "SNOWFLAKE_ROLE",
      "isSecret": false,
      "isRequired": false,
      "description": "Role to use for connection"
    },
    {
      "name": "SNOWFLAKE_WAREHOUSE",
      "isSecret": false,
      "isRequired": false,
      "description": "Warehouse to use for queries"
    },
    {
      "name": "SNOWFLAKE_PASSCODE",
      "isSecret": false,
      "isRequired": false,
      "description": "MFA passcode for authentication"
    },
    {
      "name": "SNOWFLAKE_PRIVATE_KEY",
      "isSecret": true,
      "isRequired": false,
      "description": "Private key for key pair authentication"
    },
    {
      "name": "SNOWFLAKE_PRIVATE_KEY_FILE",
      "isSecret": false,
      "isRequired": false,
      "description": "Path to private key file"
    },
    {
      "name": "SNOWFLAKE_PRIVATE_KEY_FILE_PWD",
      "isSecret": false,
      "isRequired": false,
      "description": "Password for encrypted private key"
    },
    {
      "name": "SNOWFLAKE_MCP_HOST",
      "isSecret": false,
      "isRequired": false,
      "description": "Host address to bind the server to (default: 0.0.0.0)"
    },
    {
      "name": "SNOWFLAKE_MCP_PORT",
      "isSecret": false,
      "isRequired": false,
      "description": "Port number for the server to listen on (default: 9000)"
    },
    {
      "name": "SNOWFLAKE_MCP_ENDPOINT",
      "isSecret": false,
      "isRequired": false,
      "description": "Endpoint path for the MCP server (default: /mcp)"
    }
  ],
  "category": "databases",
  "subcategory": "sql",
  "company": "snowflake",
  "categoryAuto": true,
  "checks": [
    {
      "id": "source-linked",
      "label": "Source repository linked",
      "result": "pass",
      "detail": "https://github.com/Snowflake-Labs/mcp"
    },
    {
      "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: SNOWFLAKE_PASSWORD, SNOWFLAKE_PRIVATE_KEY"
    },
    {
      "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 GitHub account Snowflake-Labs"
    },
    {
      "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": "snowflake-labs-mcp 1.3.5 has no setup.py; nothing runs at install"
    },
    {
      "id": "code-flags",
      "label": "Code red flags",
      "result": "pass",
      "detail": "Read 28 files in snowflake-labs-mcp 1.3.5: 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 28 files, including comments and the README"
    }
  ],
  "scannedAt": "2026-10-29",
  "level": "Scanned",
  "install": [
    {
      "label": "Claude Desktop (pypi)",
      "kind": "claude_desktop_json",
      "text": "{\n  \"mcpServers\": {\n    \"mcp\": {\n      \"command\": \"uvx\",\n      \"args\": [\n        \"snowflake-labs-mcp==1.3.5\"\n      ]\n    }\n  }\n}"
    }
  ],
  "curated": true,
  "stars": 303,
  "archived": false,
  "pushedAt": "2026-05-15T16:30:51Z",
  "review": {
    "package": "snowflake-labs-mcp",
    "version": "1.3.5",
    "at": "2026-10-31",
    "files": 15,
    "lines": 3415,
    "verdict": "pass-with-notes",
    "summary": "Official Snowflake server that lets an AI query and manage your Snowflake account, including Cortex Search/Analyst/Agent. Everything it sends goes only to your own Snowflake account (with a usage tag Snowflake uses to count MCP traffic). It can run SQL and create or drop objects, so set the sql_statement_permissions list carefully (it refuses everything by default) and do not expose the HTTP mode on a network, as it has no login.",
    "hosts": [
      {
        "host": "<account>.snowflakecomputing.com (or SNOWFLAKE_HOST / --host)",
        "when": "at startup (connect + a zero-compute 'SELECT 'MCP Server Snowflake'' query) and on every tool call",
        "sends": "Snowflake credentials via the official connector; SQL statements; Cortex Search/Analyst/Agent REST calls with the user's query text; a QUERY_TAG {origin:sf_sit,name:mcp_server,version} on every session so Snowflake can count MCP usage"
      }
    ],
    "env": [
      {
        "name": "SNOWFLAKE_ACCOUNT / SNOWFLAKE_HOST / SNOWFLAKE_USER",
        "sent_to": "Snowflake (connection)"
      },
      {
        "name": "SNOWFLAKE_PASSWORD / SNOWFLAKE_PAT (deprecated)",
        "sent_to": "Snowflake login only"
      },
      {
        "name": "SNOWFLAKE_ROLE / SNOWFLAKE_WAREHOUSE / SNOWFLAKE_PASSCODE",
        "sent_to": "Snowflake login only"
      },
      {
        "name": "SNOWFLAKE_PRIVATE_KEY / SNOWFLAKE_PRIVATE_KEY_FILE / SNOWFLAKE_PRIVATE_KEY_FILE_PWD",
        "sent_to": "used locally by the connector for key-pair auth"
      },
      {
        "name": "SNOWFLAKE_DEFAULT_CONNECTION_NAME",
        "sent_to": "local (picks a connection from the Snowflake config file)"
      },
      {
        "name": "SERVICE_CONFIG_FILE",
        "sent_to": "local (path of the YAML tool config)"
      },
      {
        "name": "SNOWFLAKE_MCP_HOST / SNOWFLAKE_MCP_PORT / SNOWFLAKE_MCP_ENDPOINT",
        "sent_to": "local (HTTP bind settings)"
      },
      {
        "name": "/snowflake/session/token (file, SPCS containers only)",
        "sent_to": "Snowflake as an OAuth bearer token"
      }
    ],
    "local": "Reads the YAML service config file (path from --service-config-file / SERVICE_CONFIG_FILE) and exposes it as an MCP resource; reads /snowflake/session/token when running inside Snowpark Container Services; the connector may read a private-key file or Snowflake connections file named in config. No other file reads or writes. No path from tool input touches the file system.",
    "exec": "None. No subprocess, os.system, eval or exec. Only SQL sent to Snowflake.",
    "telemetry": "No third-party telemetry. Every Snowflake session is tagged QUERY_TAG {\"origin\":\"sf_sit\",\"name\":\"mcp_server\",\"version\":{major:1,minor:3}} (server.py:49-53, 'Used to quantify Snowflake usage'); this goes only to the user's own Snowflake account and cannot be switched off without editing code.",
    "tools": [
      "create_object",
      "drop_object",
      "create_or_alter_object",
      "describe_object",
      "list_objects",
      "run_snowflake_query",
      "list_semantic_views",
      "describe_semantic_view",
      "show_semantic_dimensions",
      "show_semantic_metrics",
      "get_semantic_view_ddl",
      "write_semantic_view_query_tool",
      "query_semantic_view",
      "cortex_agent",
      "cortex_search",
      "cortex_analyst"
    ],
    "toolText": "clean (descriptions are plain and on-task; cortex tool descriptions embed the user's own YAML service list)",
    "deps": [
      "fastmcp",
      "snowflake-connector-python",
      "snowflake-core (snowflake.core)",
      "pyyaml",
      "requests",
      "pydantic",
      "typing_extensions",
      "sqlglot"
    ],
    "findings": [
      {
        "severity": "note",
        "at": "query_manager/tools.py:53-64",
        "what": "run_snowflake_query runs any SQL the AI writes. A middleware allow/deny list (sql_statement_permissions in the YAML) gates it, and with no permissions configured every statement is refused (default-deny). Users who set 'all: true' give the AI full DML/DDL."
      },
      {
        "severity": "note",
        "at": "object_manager/tools.py:211-247",
        "what": "create_object / drop_object / create_or_alter_object can create, replace and drop databases, warehouses, users, roles etc. Gated only by 'create'/'drop' in sql_statement_permissions; no per-call confirmation. mode='replace' does CREATE OR REPLACE."
      },
      {
        "severity": "note",
        "at": "semantic_manager/tools.py:218-222",
        "what": "query_semantic_view appends where_clause and order_by as raw SQL text and is NOT checked by the permission middleware (server_utils.py only checks run_snowflake_query and create*/drop*). Snowflake runs one statement per execute, so this cannot chain a DROP, but it lets the AI run arbitrary read subqueries even when SELECT is not allowed."
      },
      {
        "severity": "note",
        "at": "utils.py:249-254",
        "what": "cortex_analyst executes the SQL that Cortex Analyst generates without passing it through the SQL permission check."
      },
      {
        "severity": "note",
        "at": "query_manager/tools.py:67-82",
        "what": "Statement type is taken from sqlglot.parse_one (first statement only); multi-statement bypass is blocked in practice by the connector's single-statement default, not by this check."
      },
      {
        "severity": "note",
        "at": "server.py:484-489",
        "what": "With --transport http/sse/streamable-http the server binds 0.0.0.0:9000 by default with no authentication on the MCP endpoint, so anyone on the network can drive the user's Snowflake session. stdio (the default) is not affected."
      },
      {
        "severity": "info",
        "at": "object_manager/tools.py:137-140",
        "what": "starts_with is concatenated into a quoted literal after stripping single quotes only (SHOW statements cannot bind). Single-statement execution limits the impact to a syntax error."
      },
      {
        "severity": "info",
        "at": "cortex_services/tools.py:71-74",
        "what": "database/schema/service names from tool input are put into REST API paths unencoded; the host is fixed to the user's Snowflake account, so this is not SSRF."
      },
      {
        "severity": "info",
        "at": "semantic_manager/tools.py:268-288",
        "what": "validate_semantic_view_tool is dead code (never called)."
      },
      {
        "severity": "info",
        "at": "package",
        "what": "No pyproject.toml/METADATA in the reviewed copy; dependencies listed are those imported by the code. No install hooks, obfuscation, encoded payloads, dynamic imports, disabled TLS or hard-coded secrets found."
      },
      {
        "severity": "info",
        "at": "manifest.tsv",
        "what": "lines_read (3415) is the real line count of every file (Read tool / splitlines). The manifest's 3430 counts one extra empty 'line' after the trailing newline of 15 files; no file or line was skipped."
      }
    ]
  },
  "health": {
    "score": 65,
    "parts": {
      "popularity": 0.668419447001719,
      "activity": 0.33,
      "issues": 0.6811594202898551,
      "security": 1
    },
    "fail": 0,
    "warn": 0,
    "raw": {
      "stars": 303,
      "forks": 109,
      "downloads": 10628,
      "hn": {
        "n": 0,
        "pts": 0,
        "t": []
      },
      "issuesOpen": 22,
      "issuesClosed": 47,
      "prsMerged": 98,
      "commits90": 0,
      "release": "2026-05-15T16:30:51Z",
      "pushed": "2026-05-15T16:30:51Z",
      "growth": null,
      "growthDays": null,
      "archived": false
    },
    "at": "2026-10-31T07:42:38.200Z"
  },
  "icon": "/icons/co/snowflake.jpg"
}
