Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/skills-validate-fallback.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: lint

on:
push:
paths-ignore:
- "skills/**"
pull_request:
paths-ignore:
- "skills/**"
pull_request_target:
types: [labeled]
paths-ignore:
- "skills/**"
workflow_dispatch:

jobs:
skills-validate:
runs-on: ubuntu-latest
steps:
- name: Skip Skill Validation
run: |
echo "No changes detected in 'skills/' directory. Skipping validation."
echo "This job ensures the required 'skills-validate' status check passes."
56 changes: 56 additions & 0 deletions .github/workflows/skills-validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Validate Skills

on:
push:
paths:
- "skills/**"
pull_request:
paths:
- "skills/**"
pull_request_target:
types: [labeled]
paths:
- "skills/**"

jobs:
skills-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.11"

- name: Install skills-ref
run: |
pip install "git+https://github.com/agentskills/agentskills.git#subdirectory=skills-ref"

- name: Validate Skills
run: |
failed=0
for skill_dir in skills/*/; do
if [ -d "$skill_dir" ]; then
echo "Validating $skill_dir..."
if ! skills-ref validate "$skill_dir"; then
echo "Validation failed for $skill_dir"
failed=1
fi
fi
done
exit $failed
18 changes: 0 additions & 18 deletions gemini-extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,6 @@
"name": "cloud-sql-sqlserver",
"version": "0.1.8",
"description": "Connect to Cloud SQL for SQL Server",
"mcpServers": {
"cloud_sql_sqlserver_admin": {
"command": "${extensionPath}${/}toolbox",
"args": [
"--prebuilt",
"cloud-sql-mssql-admin",
"--stdio"
]
},
"cloud_sql_sqlserver": {
"command": "${extensionPath}${/}toolbox",
"args": [
"--prebuilt",
"cloud-sql-mssql",
"--stdio"
]
}
},
"contextFileName": "CLOUD-SQL-SQLSERVER.md",
"settings": [
{
Expand Down
125 changes: 125 additions & 0 deletions skills/cloud-sql-sqlserver-admin/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
name: cloud-sql-sqlserver-admin
description: Use these skills when you need to provision new Cloud SQL for SQL Server instances, create databases and users, clone existing environments, and monitor the progress of long-running operations.
---

## Usage

All scripts can be executed using Node.js. Replace `<param_name>` and `<param_value>` with actual values.

**Bash:**
`node <skill_dir>/scripts/<script_name>.js '{"<param_name>": "<param_value>"}'`

**PowerShell:**
`node <skill_dir>/scripts/<script_name>.js '{\"<param_name>\": \"<param_value>\"}'`

Note: The scripts automatically load the environment variables from various .env files. Do not ask the user to set vars unless skill executions fails due to env var absence.


## Scripts


### create_database



#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| instance | string | The ID of the instance where the database will be created. | Yes | |
| name | string | The name for the new database. Must be unique within the instance. | Yes | |


---

### create_instance



#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| name | string | The name of the instance | Yes | |
| databaseVersion | string | The database version for SQL Server. If not specified, defaults to SQLSERVER_2022_STANDARD. | No | `SQLSERVER_2022_STANDARD` |
| rootPassword | string | The root password for the instance | Yes | |
| editionPreset | string | The edition of the instance. Can be `Production` or `Development`. This determines the default machine type and availability. Defaults to `Development`. | No | `Development` |


---

### create_user



#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| instance | string | The ID of the instance where the user will be created. | Yes | |
| name | string | The name for the new user. Must be unique within the instance. | Yes | |
| password | string | A secure password for the new user. Not required for IAM users. | No | |
| iamUser | boolean | Set to true to create a Cloud IAM user. | Yes | |


---

### get_instance



#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| projectId | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| instanceId | string | The instance ID | Yes | |


---

### list_databases

Lists all databases for a Cloud SQL instance.

#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| instance | string | The instance ID | Yes | |


---

### list_instances

Lists all type of Cloud SQL instances for a project.

#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |


---

### wait_for_operation



#### Parameters

| Name | Type | Description | Required | Default |
| :--- | :--- | :--- | :--- | :--- |
| project | string | The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one. | No | |
| operation | string | The operation ID | Yes | |


---

103 changes: 103 additions & 0 deletions skills/cloud-sql-sqlserver-admin/scripts/create_database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env node

// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const { spawn, execSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');

const toolName = "create_database";
const configArgs = ["--prebuilt", "cloud-sql-mssql"];

const OPTIONAL_VARS_TO_OMIT_IF_EMPTY = [
'CLOUD_SQL_MSSQL_IP_TYPE',
];


function mergeEnvVars(env) {
if (process.env.GEMINI_CLI === '1') {
const envPath = path.resolve(__dirname, '../../../.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf-8');
envContent.split('\n').forEach(line => {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith('#')) {
const splitIdx = trimmed.indexOf('=');
if (splitIdx !== -1) {
const key = trimmed.slice(0, splitIdx).trim();
let value = trimmed.slice(splitIdx + 1).trim();
value = value.replace(/(^['"]|['"]$)/g, '');
if (env[key] === undefined) {
env[key] = value;
}
}
}
});
}
} else if (process.env.CLAUDECODE === '1') {
const prefix = 'CLAUDE_PLUGIN_OPTION_';
for (const key in process.env) {
if (key.startsWith(prefix)) {
env[key.substring(prefix.length)] = process.env[key];
}
}
}
}

function prepareEnvironment() {
let env = { ...process.env };
let userAgent = "skills";
if (process.env.GEMINI_CLI === '1') {
userAgent = "skills-geminicli";
} else if (process.env.CLAUDECODE === '1') {
userAgent = "skills-claudecode";
} else if (process.env.CODEX_CI === '1') {
userAgent = "skills-codex";
}
mergeEnvVars(env);

OPTIONAL_VARS_TO_OMIT_IF_EMPTY.forEach(varName => {
if (env[varName] === '') {
delete env[varName];
}
});


return { env, userAgent };
}

function main() {
const { env, userAgent } = prepareEnvironment();
const args = process.argv.slice(2);

const command = os.platform() === 'win32' ? 'npx.cmd' : 'npx';
const processedArgs = os.platform() === 'win32' ? args.map(arg => arg.includes('"') ? '"' + arg.replace(/"/g, '""') + '"' : arg) : args;
const npxArgs = ["--yes", "@toolbox-sdk/server@1.1.0", "--log-level", "error", ...configArgs, "invoke", toolName, "--user-agent-metadata", userAgent, ...processedArgs];

const child = spawn(command, npxArgs, { shell: os.platform() === 'win32', stdio: 'inherit', env });


child.on('close', (code) => {
process.exit(code);
});

child.on('error', (err) => {
console.error("Error executing toolbox:", err);
process.exit(1);
});
}

main();
Loading
Loading