diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index be3f5fc7..b01929dd 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -39,6 +39,18 @@ "authentication": "ON_INSTALL" }, "category": "Developer Tools" + }, + { + "name": "google-dev-kit", + "source": { + "source": "local", + "path": "./plugins/google-dev-kit" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Developer Tools" } ] } diff --git a/.github/workflows/google-dev-kit.yml b/.github/workflows/google-dev-kit.yml new file mode 100644 index 00000000..85c2e267 --- /dev/null +++ b/.github/workflows/google-dev-kit.yml @@ -0,0 +1,36 @@ +name: Google Dev Kit + +on: + pull_request: + paths: + - "plugins/google-dev-kit/**" + - ".agents/plugins/marketplace.json" + - ".github/workflows/google-dev-kit.yml" + push: + branches: [main] + paths: + - "plugins/google-dev-kit/**" + - ".agents/plugins/marketplace.json" + - ".github/workflows/google-dev-kit.yml" + workflow_dispatch: + +permissions: + contents: read + +jobs: + package: + runs-on: ubuntu-slim + timeout-minutes: 10 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + persist-credentials: false + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 + with: + python-version: "3.12" + - name: Install validation dependency + run: python -m pip install -r plugins/google-dev-kit/requirements.txt + - name: Validate and test package + run: python -m unittest discover -s plugins/google-dev-kit/tests -v + - name: Build portable archive + run: python plugins/google-dev-kit/scripts/package_plugin.py "$RUNNER_TEMP/google-dev-kit-0.1.0.zip" diff --git a/README.md b/README.md index 517431db..f14c8bbf 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ | 🛸 **SpaceMolt** | [`spacemolt/`](spacemolt/) · [`smx`](spacemolt/smx/) · [agent plugin](spacemolt/plugin/) | Official v2 CLI companion, game skill, and the full gameplay and documentation MCP servers. | | 📱 **Xiaomi ADB Tools** | [`xiaomi-adb-tools/`](xiaomi-adb-tools/) · [download](https://github.com/travnie/twojstar/releases/latest/download/xiaomi-adb-tools.zip) | Maintained desktop ADB/Fastboot utility with platform-specific JavaFX builds. | | 🧩 **OpenAI Dev Kit** | [`plugins/openai-dev-kit/`](plugins/openai-dev-kit/) | Two developer skills, Plugin Builder artwork, and the official read-only OpenAI docs MCP. | +| ☁️ **Google Dev Kit** | [`plugins/google-dev-kit/`](plugins/google-dev-kit/) | Seven deduplicated Google Cloud/Gemini workflows backed by ten Google MCP endpoints and live docs. | | 🎨 **Paint.NET plugins** | [`plugins/paintdotnet/`](plugins/paintdotnet/) · [`ICO`](plugins/paintdotnet/ico/) · [`AI Restore`](plugins/paintdotnet/ai/) | ICO import/export plus local AI Restore, DeJPEG and Denoise effects. | | 🎚️ **Audacity plugins** | [`plugins/audacity/`](plugins/audacity/) · [`VST3`](plugins/audacity/vst3/) · [Windows](https://github.com/travnie/twojstar/releases/latest/download/audacity-auto-declip-windows.zip) · [Linux](https://github.com/travnie/twojstar/releases/latest/download/audacity-auto-declip-linux.zip) | Local-first audio restoration and workflow effects, starting with Auto Declip. | | ⌨️ **Intent Keyboard** | [`intent-keyboard/`](intent-keyboard/) | Multiplatform semantic input experiment: rough intent in, natural text out, with tone, translation and protected facts. | diff --git a/plugins/google-dev-kit/LICENSE.google-skills.txt b/plugins/google-dev-kit/LICENSE.google-skills.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/plugins/google-dev-kit/LICENSE.google-skills.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/plugins/google-dev-kit/LICENSE.txt b/plugins/google-dev-kit/LICENSE.txt new file mode 100644 index 00000000..288d92d5 --- /dev/null +++ b/plugins/google-dev-kit/LICENSE.txt @@ -0,0 +1,8 @@ +ISC License +https://spdx.org/licenses/ISC +============= +Copyright © 2026 trvny + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/plugins/google-dev-kit/README.md b/plugins/google-dev-kit/README.md new file mode 100644 index 00000000..050330c1 --- /dev/null +++ b/plugins/google-dev-kit/README.md @@ -0,0 +1,36 @@ +# Google Dev Kit + +Personal Google Cloud and Gemini developer plugin for ChatGPT/Codex. Seven compact workflow skills sit on top of ten remote MCP endpoints. The source skills are adapted from Google's public `google/skills` repository and deduplicated so volatile commands, model names, and API details come from live documentation instead of bloating every skill. + +## Included skills + +- `google-dev` — official documentation retrieval, product routing, and MCP catalog. +- `gcloud` — leaf-command validation, scope, output reduction, and mutation guardrails. +- `google-cloud-storage` — merged GCS operations plus production bucket architecture. +- `cloud-run` — services, jobs, worker pools, deployment, and troubleshooting. +- `gemini-api` — current Google Gen AI SDK and Gemini feature routing. +- `gemini-agents-api` — managed Agent Platform control-plane resources. +- `application-design-center` — local-first Terraform design, assessment, import, deploy, and repair. + +## MCP endpoints + +`mcp.json` declares Developer Knowledge, Cloud CLI, Cloud Storage, Application Design Center, Android Management, Cloud Run, API Keys, Gemini Cloud Assist, IAM, and Gemini API Docs MCP servers. + +Several endpoints require Google authentication, project permissions, API enablement, or preview access. Gemini Cloud Assist may require private-preview access. A server declaration is not proof that a ChatGPT account has a registered/authorized connection. + +The plugin exposes write capability because several servers can mutate cloud resources. Skills keep reads/planning lightweight, require exact scope, and gate security-sensitive or destructive writes. + +## Package + +```sh +python -m pip install -r plugins/google-dev-kit/requirements.txt +python plugins/google-dev-kit/scripts/package_plugin.py /tmp/google-dev-kit-0.1.0.zip +``` + +Packaging validates Agent Plugins 1.0 manifests, MCP endpoints, skill metadata, assets, and `[CHAT, CODEX]` policy. It generates `.codex-plugin/plugin.json` and `.mcp.json` compatibility files. + +Private ChatGPT installation can still require registering remote MCP endpoints in developer mode and binding resulting Apps. The source intentionally contains no account-specific App IDs. + +## Provenance + +Adapted from `google/skills` at commit `1d77046ad3670d62227f50a8f53286f6c6cde08b`. See `THIRD_PARTY_NOTICES.md`. Google-derived skill material remains Apache-2.0; repository packaging code is ISC. This is a personal toolkit maintained by travnie, not an official Google plugin. diff --git a/plugins/google-dev-kit/THIRD_PARTY_NOTICES.md b/plugins/google-dev-kit/THIRD_PARTY_NOTICES.md new file mode 100644 index 00000000..3139441b --- /dev/null +++ b/plugins/google-dev-kit/THIRD_PARTY_NOTICES.md @@ -0,0 +1,23 @@ +# Third-party notices + +## Google skills + +This plugin contains condensed and modified derivatives of Apache-2.0 material from `google/skills`, pinned for provenance at commit `1d77046ad3670d62227f50a8f53286f6c6cde08b`: + +- `skills/developers/retrieving-developer-knowledge` +- `skills/developers/finding-google-skills` +- `skills/cloud/gcloud` +- `skills/cloud/google-cloud-storage-basics` +- `skills/cloud/google-cloud-storage-bucket-architect` +- `skills/cloud/cloud-run-basics` +- `skills/cloud/gemini-api` +- `skills/cloud/gemini-agents-api` +- `skills/cloud/application-design-center-design-deploy` + +The derivatives were reorganized, deduplicated, shortened, and moved toward live documentation/MCP lookup. See `LICENSE.google-skills.txt`. + +## Google Cloud product icons + +Skill icons originate from `GoogleCloudPlatform/devrel-demos`, under `app-dev/party-game/public/google-cloud-icons/`: `cloud_apis.svg`, `cloud_run.svg`, `cloud_storage.svg`, and `vertexai.svg`. + +Only dimensions/markup were normalized for safe plugin packaging. Trademarks remain with Google LLC. See `assets/ICON-NOTICE.txt`. diff --git a/plugins/google-dev-kit/assets/ICON-NOTICE.txt b/plugins/google-dev-kit/assets/ICON-NOTICE.txt new file mode 100644 index 00000000..709b329a --- /dev/null +++ b/plugins/google-dev-kit/assets/ICON-NOTICE.txt @@ -0,0 +1,5 @@ +The root Google Dev Kit icon is an original repository asset using the Google product color palette for descriptive context. It is not a Google logo. + +Skill icons are adapted only by normalizing dimensions and markup from Google Cloud product icons published in GoogleCloudPlatform/devrel-demos: Cloud APIs, Cloud Run, Cloud Storage, and Vertex AI. + +Google, Google Cloud, Gemini, Vertex AI, and related marks remain trademarks of Google LLC. Their inclusion identifies covered products and does not imply endorsement or affiliation. diff --git a/plugins/google-dev-kit/assets/icon.svg b/plugins/google-dev-kit/assets/icon.svg new file mode 100644 index 00000000..0a48e138 --- /dev/null +++ b/plugins/google-dev-kit/assets/icon.svg @@ -0,0 +1 @@ +Google Dev Kit custom icon \ No newline at end of file diff --git a/plugins/google-dev-kit/mcp.json b/plugins/google-dev-kit/mcp.json new file mode 100644 index 00000000..412e3a57 --- /dev/null +++ b/plugins/google-dev-kit/mcp.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json", + "mcpServers": { + "googleDeveloperKnowledge": { + "type": "streamable-http", + "url": "https://developerknowledge.googleapis.com/mcp" + }, + "googleCloudCli": { + "type": "streamable-http", + "url": "https://cloudcli.googleapis.com/mcp" + }, + "googleCloudStorage": { + "type": "streamable-http", + "url": "https://storage.googleapis.com/storage/mcp" + }, + "googleApplicationDesignCenter": { + "type": "streamable-http", + "url": "https://design.googleapis.com/mcp" + }, + "googleAndroidManagement": { + "type": "streamable-http", + "url": "https://androidmanagement.googleapis.com/mcp" + }, + "googleCloudRun": { + "type": "streamable-http", + "url": "https://run.googleapis.com/mcp" + }, + "googleApiKeys": { + "type": "streamable-http", + "url": "https://apikeys.googleapis.com/mcp" + }, + "googleCloudAssist": { + "type": "streamable-http", + "url": "https://geminicloudassist.googleapis.com/mcp" + }, + "googleIam": { + "type": "streamable-http", + "url": "https://iam.googleapis.com/mcp" + }, + "geminiApiDocs": { + "type": "streamable-http", + "url": "https://gemini-api-docs-mcp.dev" + } + } +} diff --git a/plugins/google-dev-kit/plugin.json b/plugins/google-dev-kit/plugin.json new file mode 100644 index 00000000..4bebba66 --- /dev/null +++ b/plugins/google-dev-kit/plugin.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "google-dev-kit", + "version": "0.1.0", + "description": "Google Cloud and Gemini developer workflows paired with official Google MCP servers and live documentation.", + "author": { + "name": "travnie", + "url": "https://github.com/travnie" + }, + "homepage": "https://github.com/travnie/twojstar/tree/main/plugins/google-dev-kit", + "repository": "https://github.com/travnie/twojstar", + "license": "Apache-2.0 AND ISC", + "keywords": [ + "google-cloud", + "gemini", + "gcloud", + "cloud-run", + "cloud-storage", + "mcp", + "developer-docs" + ], + "extensions": { + "com.openai": { + "interface": { + "displayName": "Google Dev Kit", + "shortDescription": "Google Cloud + Gemini dev", + "longDescription": "Build and operate Google Cloud and Gemini integrations with compact workflows backed by Google developer documentation and official Google MCP endpoints. Includes gcloud guardrails, Cloud Storage, Cloud Run, Gemini API, managed agents, and Application Design Center. Personal toolkit maintained by travnie; not an official Google plugin.", + "developerName": "travnie", + "category": "Developer Tools", + "capabilities": [ + "Read", + "Write" + ], + "websiteURL": "https://github.com/travnie/twojstar/tree/main/plugins/google-dev-kit", + "defaultPrompt": [ + "Use Google Dev Kit to find the current official Google guidance and build the smallest safe solution.", + "Use Google Dev Kit to review this Google Cloud or Gemini integration and verify commands against live documentation." + ], + "brandColor": "#4285F4", + "composerIcon": "./assets/icon.svg", + "logo": "./assets/icon.svg" + } + } + } +} diff --git a/plugins/google-dev-kit/requirements.txt b/plugins/google-dev-kit/requirements.txt new file mode 100644 index 00000000..4c98fbfd --- /dev/null +++ b/plugins/google-dev-kit/requirements.txt @@ -0,0 +1,2 @@ +PyYAML==6.0.3 +defusedxml==0.7.1 diff --git a/plugins/google-dev-kit/scripts/package_plugin.py b/plugins/google-dev-kit/scripts/package_plugin.py new file mode 100644 index 00000000..9d4590af --- /dev/null +++ b/plugins/google-dev-kit/scripts/package_plugin.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import re +import stat +import tempfile +import zipfile +from pathlib import Path + +import yaml +from defusedxml import ElementTree as DefusedElementTree + +ROOT = Path(__file__).resolve().parents[1] +FIXED_TIME = (1980, 1, 1, 0, 0, 0) +EXPECTED_SERVERS = { + "googleDeveloperKnowledge": "https://developerknowledge.googleapis.com/mcp", + "googleCloudCli": "https://cloudcli.googleapis.com/mcp", + "googleCloudStorage": "https://storage.googleapis.com/storage/mcp", + "googleApplicationDesignCenter": "https://design.googleapis.com/mcp", + "googleAndroidManagement": "https://androidmanagement.googleapis.com/mcp", + "googleCloudRun": "https://run.googleapis.com/mcp", + "googleApiKeys": "https://apikeys.googleapis.com/mcp", + "googleCloudAssist": "https://geminicloudassist.googleapis.com/mcp", + "googleIam": "https://iam.googleapis.com/mcp", + "geminiApiDocs": "https://gemini-api-docs-mcp.dev", +} +EXPECTED_SKILLS = { + "google-dev", + "gcloud", + "google-cloud-storage", + "cloud-run", + "gemini-api", + "gemini-agents-api", + "application-design-center", +} + + +class StrictLoader(yaml.SafeLoader): + def construct_mapping(self, node, deep=False): + if isinstance(node, yaml.MappingNode): + seen = set() + for key, _ in node.value: + if ( + not isinstance(key, yaml.ScalarNode) + or key.tag != "tag:yaml.org,2002:str" + ): + raise ValueError("metadata keys must be plain strings") + if key.value in seen or key.value == "<<": + raise ValueError(f"duplicate/merged metadata key: {key.value}") + seen.add(key.value) + return super().construct_mapping(node, deep=deep) + + +def parse_yaml(text: str) -> dict: + loader = StrictLoader(text) + try: + value = loader.get_single_data() + finally: + loader.dispose() + if not isinstance(value, dict): + raise ValueError("expected YAML mapping") + return value + + +def load_yaml(path: Path) -> dict: + try: + return parse_yaml(path.read_text(encoding="utf-8")) + except ValueError as exc: + raise ValueError(f"invalid YAML mapping: {path}") from exc + + +def frontmatter(path: Path) -> dict: + match = re.match( + r"\A---\n(.*?)\n---\n", + path.read_text(encoding="utf-8"), + re.S, + ) + if not match: + raise ValueError(f"missing frontmatter: {path}") + try: + return parse_yaml(match.group(1)) + except ValueError as exc: + raise ValueError(f"invalid frontmatter: {path}") from exc + + +def safe_asset_path( + root: Path, + value: object, + *, + require_dot_prefix: bool = False, +) -> Path: + if not isinstance(value, str): + raise ValueError(f"unsafe asset path: {value}") + if require_dot_prefix and not value.startswith("./"): + raise ValueError(f"unsafe asset path: {value}") + if value.startswith(("/", "\\")) or "\\" in value or ".." in value.split("/"): + raise ValueError(f"unsafe asset path: {value}") + relative = value[2:] if value.startswith("./") else value + path = root / relative + if not path.is_file() or path.is_symlink(): + raise ValueError(f"missing asset: {path}") + return path + + +def validate_svg(path: Path) -> None: + root = DefusedElementTree.fromstring(path.read_text(encoding="utf-8")) + if root.tag.split("}")[-1] != "svg": + raise ValueError(f"invalid SVG: {path}") + width = float(root.attrib["width"]) + height = float(root.attrib["height"]) + if not math.isfinite(width) or width <= 0 or width != height: + raise ValueError(f"SVG must be square: {path}") + for element in root.iter(): + if element.tag.split("}")[-1] in {"script", "foreignObject", "image", "use"}: + raise ValueError(f"active SVG element: {path}") + for key, value in element.attrib.items(): + leaf = key.split("}")[-1].lower() + if ( + leaf.startswith("on") + or leaf == "href" + or "url(" in value.lower() + ): + raise ValueError(f"external SVG reference: {path}") + + +def validate(root: Path): + manifest = json.loads((root / "plugin.json").read_text(encoding="utf-8")) + if ( + manifest.get("$schema") + != "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" + ): + raise ValueError("expected Agent Plugins 1.0") + if manifest.get("name") != "google-dev-kit" or not re.fullmatch( + r"\d+\.\d+\.\d+", + manifest.get("version", ""), + ): + raise ValueError("invalid plugin identity/version") + + ui = manifest["extensions"]["com.openai"]["interface"] + if len(ui["shortDescription"]) > 30: + raise ValueError("shortDescription too long") + for key in ("logo", "composerIcon"): + validate_svg( + safe_asset_path( + root, + ui[key], + require_dot_prefix=True, + ) + ) + + config = json.loads((root / "mcp.json").read_text(encoding="utf-8")) + actual = config.get("mcpServers", {}) + if set(actual) != set(EXPECTED_SERVERS): + raise ValueError("unexpected MCP server set") + for name, url in EXPECTED_SERVERS.items(): + if actual[name] != {"type": "streamable-http", "url": url}: + raise ValueError(f"unexpected MCP config: {name}") + + names = set() + for child in sorted((root / "skills").iterdir()): + if not child.is_dir() or child.is_symlink(): + raise ValueError(f"invalid skill directory: {child}") + meta = frontmatter(child / "SKILL.md") + skill_name = meta.get("name") + if skill_name != child.name or skill_name in names: + raise ValueError(f"invalid/duplicate skill: {child.name}") + names.add(skill_name) + + openai = load_yaml(child / "agents/openai.yaml") + if openai.get("policy", {}).get("products") != ["CHAT", "CODEX"]: + raise ValueError(f"skill must target CHAT and CODEX: {skill_name}") + validate_svg(safe_asset_path(child, openai["interface"]["icon_small"])) + + for tool in openai.get("dependencies", {}).get("tools", []): + alias_value = tool.get("value") + if not isinstance(alias_value, str): + raise ValueError( + f"dependency alias must be a string: {skill_name}" + ) + alias = alias_value + if alias not in EXPECTED_SERVERS: + raise ValueError(f"unknown dependency: {alias}") + if ( + tool.get("transport") != "streamable_http" + or tool.get("url") != EXPECTED_SERVERS[alias] + ): + raise ValueError( + f"dependency mismatch: {skill_name}/{alias}" + ) + + if names != EXPECTED_SKILLS: + raise ValueError("missing intended skills") + return manifest, config + + +def stage(source: Path, target: Path) -> None: + for path in sorted(source.rglob("*")): + rel = path.relative_to(source) + if path.is_symlink(): + raise ValueError(f"symlink: {rel}") + if ( + path.is_dir() + or "tests" in rel.parts + or any( + part in {"__pycache__", ".git", "node_modules"} + for part in rel.parts + ) + ): + continue + if path.name.startswith(".env") or path.suffix in {".pyc", ".pem", ".key"}: + raise ValueError(f"unsafe package member: {rel}") + dest = target / rel + dest.parent.mkdir(parents=True, exist_ok=True) + dest.write_bytes(path.read_bytes()) + + manifest, config = validate(target) + overlay = { + key: value + for key, value in manifest.items() + if key not in {"$schema", "extensions"} + } + overlay.update(manifest["extensions"]["com.openai"]) + overlay.update(skills="./skills/", mcpServers="./.mcp.json") + (target / ".codex-plugin").mkdir() + (target / ".codex-plugin/plugin.json").write_text( + json.dumps(overlay, indent=2) + "\n", + encoding="utf-8", + ) + legacy = { + "mcpServers": { + name: {"url": item["url"]} + for name, item in config["mcpServers"].items() + } + } + (target / ".mcp.json").write_text( + json.dumps(legacy, indent=2) + "\n", + encoding="utf-8", + ) + + +def package(output: Path) -> dict: + output = output.resolve() + if output.is_relative_to(ROOT.resolve()): + raise ValueError("archive must live outside plugin source") + output.parent.mkdir(parents=True, exist_ok=True) + + with tempfile.TemporaryDirectory() as directory: + staged = Path(directory) / "google-dev-kit" + staged.mkdir() + stage(ROOT, staged) + + with zipfile.ZipFile( + output, + "w", + zipfile.ZIP_DEFLATED, + compresslevel=9, + ) as archive: + for path in sorted(staged.rglob("*")): + if not path.is_file(): + continue + name = ( + "google-dev-kit/" + + path.relative_to(staged).as_posix() + ) + info = zipfile.ZipInfo(name, FIXED_TIME) + info.create_system = 3 + info.external_attr = (stat.S_IFREG | 0o644) << 16 + archive.writestr( + info, + path.read_bytes(), + compress_type=zipfile.ZIP_DEFLATED, + compresslevel=9, + ) + + return { + "sha256": hashlib.sha256(output.read_bytes()).hexdigest(), + "bytes": output.stat().st_size, + } + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("output", type=Path) + args = parser.parse_args() + print(json.dumps(package(args.output), indent=2)) diff --git a/plugins/google-dev-kit/skills/application-design-center/SKILL.md b/plugins/google-dev-kit/skills/application-design-center/SKILL.md new file mode 100644 index 00000000..a83acd9b --- /dev/null +++ b/plugins/google-dev-kit/skills/application-design-center/SKILL.md @@ -0,0 +1,17 @@ +--- +name: application-design-center +description: Designs and deploys Google Cloud infrastructure through Application Design Center using local Terraform as the editable source of truth. Use for ADC designs, plan assessment, template import, deployment, or deployment troubleshooting. +--- + +# Application Design Center + +Keep local Terraform/HCL as the maintained source. Use Design MCP for ADC-specific operations and Developer Knowledge for current contracts. + +1. Confirm project/location; discover the active ADC space. +2. Design and validate Terraform locally. Keep secrets out of HCL/tfvars and local validation state separate from ADC-managed deployment state. +3. Produce a plan and run current ADC assessment before import. Fix high-impact findings locally, then revalidate. +4. Verify target template and current import constraints before importing IaC. +5. Deploy only when authorized. Monitor the returned operation and do not duplicate deployments after ambiguous timeouts. +6. On failure, inspect live operation/resource state, remediate locally, reassess, re-import, then redeploy. + +Read [workflow.md](references/workflow.md). diff --git a/plugins/google-dev-kit/skills/application-design-center/agents/openai.yaml b/plugins/google-dev-kit/skills/application-design-center/agents/openai.yaml new file mode 100644 index 00000000..0b94b459 --- /dev/null +++ b/plugins/google-dev-kit/skills/application-design-center/agents/openai.yaml @@ -0,0 +1,27 @@ +interface: + display_name: Application Design Center + short_description: ADC Terraform design/deploy + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $application-design-center to keep Terraform local-first, assess it, import to ADC, deploy safely, and troubleshoot from live state. +dependencies: + tools: + - type: mcp + value: googleApplicationDesignCenter + description: Application Design Center design and deployment + transport: streamable_http + url: https://design.googleapis.com/mcp + - type: mcp + value: googleDeveloperKnowledge + description: Current ADC and Terraform guidance + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp + - type: mcp + value: googleCloudAssist + description: Gemini Cloud Assist when account access permits + transport: streamable_http + url: https://geminicloudassist.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/application-design-center/assets/icon.svg b/plugins/google-dev-kit/skills/application-design-center/assets/icon.svg new file mode 100644 index 00000000..31064eee --- /dev/null +++ b/plugins/google-dev-kit/skills/application-design-center/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud APIs product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/application-design-center/references/workflow.md b/plugins/google-dev-kit/skills/application-design-center/references/workflow.md new file mode 100644 index 00000000..d7fc0b76 --- /dev/null +++ b/plugins/google-dev-kit/skills/application-design-center/references/workflow.md @@ -0,0 +1,15 @@ +# ADC workflow + +This condenses Google's `application-design-center-design-deploy` skill while moving volatile command syntax behind live docs/MCP. + +**Local design:** analyze requirements/code, generate modular Terraform, run formatting/validation/plan. No plaintext secrets; no remote backend solely for scratch validation. + +**Assessment:** export the current plan in the format ADC requires, run best-practice assessment, resolve high/critical findings or document trade-offs, then re-plan. + +**Template import:** discover active ADC space, verify/create template only when authorized, and fetch current parser constraints before altering HCL. + +**Deployment:** use the current Design MCP contract, capture operation/resource identifiers, and do not retry a timeout until state proves the first attempt failed. + +**Troubleshooting:** separate local Terraform errors from cloud deployment errors. Apply fixes to local HCL, revalidate/reassess/re-import. + +**Verification:** fetch deployed state/outputs and test only endpoints/actions requested by the user. diff --git a/plugins/google-dev-kit/skills/cloud-run/SKILL.md b/plugins/google-dev-kit/skills/cloud-run/SKILL.md new file mode 100644 index 00000000..1ebe1f48 --- /dev/null +++ b/plugins/google-dev-kit/skills/cloud-run/SKILL.md @@ -0,0 +1,17 @@ +--- +name: cloud-run +description: Deploys and manages Cloud Run services, jobs, and worker pools. Use for HTTP services, scheduled or batch jobs, pull-based workers, runtime configuration, deployment, troubleshooting, or Cloud Run architecture. +--- + +# Cloud Run + +Classify the workload as a service, job, or worker pool. Prefer Cloud Run MCP for resource inspection/operations and Developer Knowledge for current limits/configuration. + +Before deployment: +1. Confirm project and region. +2. Confirm source/image and runtime contract. HTTP containers must listen on the injected port and externally reachable interface. +3. Inspect current state before changing an existing resource. +4. Validate any gcloud fallback through `$gcloud`. +5. Treat IAM changes, unauthenticated exposure, secret wiring, traffic migration, and deletion as security-sensitive mutations. + +Read [workflow.md](references/workflow.md). diff --git a/plugins/google-dev-kit/skills/cloud-run/agents/openai.yaml b/plugins/google-dev-kit/skills/cloud-run/agents/openai.yaml new file mode 100644 index 00000000..c360f0b4 --- /dev/null +++ b/plugins/google-dev-kit/skills/cloud-run/agents/openai.yaml @@ -0,0 +1,27 @@ +interface: + display_name: Cloud Run + short_description: Services, jobs, worker pools + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $cloud-run to choose the right Cloud Run resource, inspect live state, retrieve current docs, and deploy or troubleshoot with scoped changes. +dependencies: + tools: + - type: mcp + value: googleCloudRun + description: Cloud Run resource management + transport: streamable_http + url: https://run.googleapis.com/mcp + - type: mcp + value: googleDeveloperKnowledge + description: Current Cloud Run documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp + - type: mcp + value: googleCloudCli + description: Validated gcloud fallback + transport: streamable_http + url: https://cloudcli.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/cloud-run/assets/icon.svg b/plugins/google-dev-kit/skills/cloud-run/assets/icon.svg new file mode 100644 index 00000000..144e490b --- /dev/null +++ b/plugins/google-dev-kit/skills/cloud-run/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud Run product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/cloud-run/references/workflow.md b/plugins/google-dev-kit/skills/cloud-run/references/workflow.md new file mode 100644 index 00000000..2e77c5f8 --- /dev/null +++ b/plugins/google-dev-kit/skills/cloud-run/references/workflow.md @@ -0,0 +1,9 @@ +# Cloud Run workflow + +**Services:** HTTP/event endpoints. Verify ingress, auth, service identity, secrets, scaling, resources, and traffic strategy when relevant. + +**Jobs:** finite batch/scheduled work. Check tasks, parallelism, retries, timeout, identity, and trigger. Starting execution is a mutation. + +**Worker pools:** continuously running pull-based workers. Check image/source, scaling, connection behavior, and graceful shutdown. + +On failure, retrieve the smallest relevant status/logs first. Common classes are startup/port errors, image access, IAM/service identity, quota/location, and build dependency failures. Ground remediation in current docs. diff --git a/plugins/google-dev-kit/skills/gcloud/SKILL.md b/plugins/google-dev-kit/skills/gcloud/SKILL.md new file mode 100644 index 00000000..d8361539 --- /dev/null +++ b/plugins/google-dev-kit/skills/gcloud/SKILL.md @@ -0,0 +1,16 @@ +--- +name: gcloud +description: Safely plans and executes gcloud CLI work with exact leaf-command help validation, explicit project and location scope, reduced output, and approval gates. Use whenever a response proposes, explains, or runs gcloud commands. +--- + +# gcloud Guardrails + +Treat remembered CLI syntax as stale. + +1. Validate the exact leaf command before proposing or executing it. With Cloud CLI MCP, use command help; otherwise run `gcloud help ` locally. +2. Preserve user-specified project and flags. Resource commands should be explicit about project and required region/zone/location. +3. Keep discovery output bounded with `--limit`, `--filter`, or `--format`. +4. Execute one command at a time. Prefer non-interactive commands and preview/validation modes when verified leaf help supports them. +5. Do not autonomously enable APIs, change IAM, billing, organization policy, KMS, or delete resources. Present the exact change and obtain authorization. + +Read [safety.md](references/safety.md) before mutation and [mcp.md](references/mcp.md) for Cloud CLI MCP specifics. diff --git a/plugins/google-dev-kit/skills/gcloud/agents/openai.yaml b/plugins/google-dev-kit/skills/gcloud/agents/openai.yaml new file mode 100644 index 00000000..394fcb45 --- /dev/null +++ b/plugins/google-dev-kit/skills/gcloud/agents/openai.yaml @@ -0,0 +1,22 @@ +interface: + display_name: gcloud Guardrails + short_description: Validated, scoped gcloud work + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $gcloud to validate the exact leaf command, scope it to the intended project and location, reduce output, and gate risky changes. +dependencies: + tools: + - type: mcp + value: googleCloudCli + description: Validated Google Cloud CLI execution + transport: streamable_http + url: https://cloudcli.googleapis.com/mcp + - type: mcp + value: googleDeveloperKnowledge + description: Current Google Cloud documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/gcloud/assets/icon.svg b/plugins/google-dev-kit/skills/gcloud/assets/icon.svg new file mode 100644 index 00000000..31064eee --- /dev/null +++ b/plugins/google-dev-kit/skills/gcloud/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud APIs product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/gcloud/references/mcp.md b/plugins/google-dev-kit/skills/gcloud/references/mcp.md new file mode 100644 index 00000000..45a75cf5 --- /dev/null +++ b/plugins/google-dev-kit/skills/gcloud/references/mcp.md @@ -0,0 +1,7 @@ +# Cloud CLI MCP + +Server: `googleCloudCli`. + +The MCP request's `project` identifies the project used for Cloud CLI Execution API access; it does not replace the target command's own project or billing flags. Keep both scopes explicit when required. + +The executing principal is the Google identity used by the server. Apply least privilege and distinguish tool availability from permission to change a resource. diff --git a/plugins/google-dev-kit/skills/gcloud/references/safety.md b/plugins/google-dev-kit/skills/gcloud/references/safety.md new file mode 100644 index 00000000..2695678e --- /dev/null +++ b/plugins/google-dev-kit/skills/gcloud/references/safety.md @@ -0,0 +1,7 @@ +# gcloud safety + +Leaf help is authoritative for command names, positional arguments, flags, and flag values. Parent-group help is discovery only. + +Before mutation: validate leaf syntax, verify project/location scope, check for dry-run or validate-only support, and present security/data-sensitive changes when the user has not already authorized that exact action. + +Never run an unconstrained list when a small limit, focused filter, or projection can answer the question. Require explicit authorization for IAM changes, API enablement, deletes, billing, organization-level changes, KMS changes, and destructive infrastructure application. diff --git a/plugins/google-dev-kit/skills/gemini-agents-api/SKILL.md b/plugins/google-dev-kit/skills/gemini-agents-api/SKILL.md new file mode 100644 index 00000000..64544ed9 --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-agents-api/SKILL.md @@ -0,0 +1,16 @@ +--- +name: gemini-agents-api +description: Manages stateful custom Agent resources on Gemini Enterprise Agent Platform. Use for creating, inspecting, updating, listing, or deleting managed agents, including mounted files/skills and configured tools before conversations run. +--- + +# Gemini Managed Agents + +This is the **control-plane** workflow for persistent Agent resources. Do not conflate it with ordinary Gemini model calls or the interaction/data plane. + +1. Fetch current Agents API docs before constructing resource names, payloads, versions, or base-agent identifiers. +2. Confirm project/location and inspect the existing agent when changing one. +3. For create/update/delete, show the intended resource delta and obtain authorization when not already explicit. +4. Treat mounted storage, external MCP headers, network allowlists, and service identities as security-sensitive. +5. Track long-running operations to completion when required. After ambiguous timeout, inspect operation/resource state before retrying. + +Read [control-plane.md](references/control-plane.md). diff --git a/plugins/google-dev-kit/skills/gemini-agents-api/agents/openai.yaml b/plugins/google-dev-kit/skills/gemini-agents-api/agents/openai.yaml new file mode 100644 index 00000000..56b3ce3a --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-agents-api/agents/openai.yaml @@ -0,0 +1,27 @@ +interface: + display_name: Gemini Managed Agents + short_description: Managed agent control plane + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $gemini-agents-api to manage persistent Agent Platform resources with live API docs, explicit state inspection, and safe long-running-operation handling. +dependencies: + tools: + - type: mcp + value: geminiApiDocs + description: Current Gemini and Agent Platform docs + transport: streamable_http + url: https://gemini-api-docs-mcp.dev + - type: mcp + value: googleDeveloperKnowledge + description: Current Google Cloud control-plane documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp + - type: mcp + value: googleCloudStorage + description: Mounted storage inspection when relevant + transport: streamable_http + url: https://storage.googleapis.com/storage/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/gemini-agents-api/assets/icon.svg b/plugins/google-dev-kit/skills/gemini-agents-api/assets/icon.svg new file mode 100644 index 00000000..ac1bfdbd --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-agents-api/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud Vertex AI product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/gemini-agents-api/references/control-plane.md b/plugins/google-dev-kit/skills/gemini-agents-api/references/control-plane.md new file mode 100644 index 00000000..52a56b79 --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-agents-api/references/control-plane.md @@ -0,0 +1,9 @@ +# Managed Agents control plane + +The upstream `gemini-agents-api` skill covers persistent Agent resources: create, get, list, update, delete, and long-running-operation inspection. + +Agents can include system instructions, workspace inputs, mounted Cloud Storage or skill-registry sources, network configuration, and tools such as code execution or remote MCP servers. Treat authentication material as sensitive. + +Conversation execution belongs to the interaction/data plane. Fetch current Interactions API docs or a matching Google skill rather than improvising those payloads. + +API versions and base-agent identifiers are preview-sensitive. Always fetch current docs before emitting exact endpoints or identifiers. diff --git a/plugins/google-dev-kit/skills/gemini-api/SKILL.md b/plugins/google-dev-kit/skills/gemini-api/SKILL.md new file mode 100644 index 00000000..3d15463d --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-api/SKILL.md @@ -0,0 +1,16 @@ +--- +name: gemini-api +description: Builds with the current Gemini API and Google Gen AI SDK across supported languages. Use for Gemini generation, multimodal input, tools, structured output, embeddings, media, caching, batch, live/realtime, safety, or SDK migration. +--- + +# Gemini API + +Use the current Google Gen AI SDK, not legacy Gemini or Vertex generative clients. Retrieve current model IDs, feature support, limits, and examples from `geminiApiDocs` instead of freezing them here. + +1. Determine backend: Gemini Developer API/API-key flow or Google Cloud Agent Platform/enterprise flow. +2. Determine language and current Gen AI SDK package. +3. Query Gemini docs for the requested feature and current model availability. +4. Keep credentials outside source. Prefer environment/application-default mechanisms appropriate to the backend. +5. Return the smallest runnable example and call out preview or backend-specific behavior. + +Read [sdk-routing.md](references/sdk-routing.md). diff --git a/plugins/google-dev-kit/skills/gemini-api/agents/openai.yaml b/plugins/google-dev-kit/skills/gemini-api/agents/openai.yaml new file mode 100644 index 00000000..aa857cac --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-api/agents/openai.yaml @@ -0,0 +1,22 @@ +interface: + display_name: Gemini API + short_description: Current Gen AI SDK workflows + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $gemini-api to select the right Gemini backend, fetch current model and SDK docs, and produce a minimal modern implementation. +dependencies: + tools: + - type: mcp + value: geminiApiDocs + description: Current Gemini API documentation and examples + transport: streamable_http + url: https://gemini-api-docs-mcp.dev + - type: mcp + value: googleDeveloperKnowledge + description: Google Cloud and Agent Platform documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/gemini-api/assets/icon.svg b/plugins/google-dev-kit/skills/gemini-api/assets/icon.svg new file mode 100644 index 00000000..cce37a13 --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-api/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud Vertex AI product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/gemini-api/references/sdk-routing.md b/plugins/google-dev-kit/skills/gemini-api/references/sdk-routing.md new file mode 100644 index 00000000..903a4394 --- /dev/null +++ b/plugins/google-dev-kit/skills/gemini-api/references/sdk-routing.md @@ -0,0 +1,9 @@ +# Gemini SDK routing + +Prefer the Google Gen AI SDK family: Python `google-genai`, JavaScript/TypeScript `@google/genai`, Go `google.golang.org/genai`, Java `com.google.genai:google-genai`, and .NET `Google.GenAI`. + +Avoid new integrations with superseded Gemini/Vertex generative SDKs when Gen AI SDK supports the feature. + +Gemini Developer API is typically API-key based. Google Cloud Agent Platform/enterprise uses project/location and Google authentication, normally Application Default Credentials. + +Do not hardcode a favorite model list. Fetch current model names and feature matrices from `geminiApiDocs` or Developer Knowledge whenever the exact model matters. diff --git a/plugins/google-dev-kit/skills/google-cloud-storage/SKILL.md b/plugins/google-dev-kit/skills/google-cloud-storage/SKILL.md new file mode 100644 index 00000000..6877d477 --- /dev/null +++ b/plugins/google-dev-kit/skills/google-cloud-storage/SKILL.md @@ -0,0 +1,16 @@ +--- +name: google-cloud-storage +description: Designs and operates Google Cloud Storage buckets and objects. Use for bucket architecture or creation, uploads/downloads, access, lifecycle, retention, signed URLs, storage classes, transfers, or other GCS tasks. +--- + +# Google Cloud Storage + +Prefer Cloud Storage MCP when structured tools are connected. Fall back to validated gcloud/API/SDK/Terraform only when needed. + +Choose a mode: +- **Bucket architecture** for new production buckets: inspect workload, security, durability, location, class, lifecycle, and recovery before creation. +- **Storage operations** for existing buckets/objects: perform the narrow requested read/write/transfer/configuration task. + +For new production buckets, present the intended configuration before creation. For access-control, retention-lock, destructive, or public-access changes, require clear authorization and explain irreversible or exposure impact. + +Read [workflows.md](references/workflows.md) and [safety.md](references/safety.md). diff --git a/plugins/google-dev-kit/skills/google-cloud-storage/agents/openai.yaml b/plugins/google-dev-kit/skills/google-cloud-storage/agents/openai.yaml new file mode 100644 index 00000000..a4888bdb --- /dev/null +++ b/plugins/google-dev-kit/skills/google-cloud-storage/agents/openai.yaml @@ -0,0 +1,27 @@ +interface: + display_name: Cloud Storage + short_description: GCS design and operations + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $google-cloud-storage to design a bucket or operate GCS with Storage MCP first, current docs second, and explicit gates for risky changes. +dependencies: + tools: + - type: mcp + value: googleCloudStorage + description: Google Cloud Storage operations + transport: streamable_http + url: https://storage.googleapis.com/storage/mcp + - type: mcp + value: googleDeveloperKnowledge + description: Current Cloud Storage documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp + - type: mcp + value: googleIam + description: IAM inspection when storage access depends on IAM + transport: streamable_http + url: https://iam.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/google-cloud-storage/assets/icon.svg b/plugins/google-dev-kit/skills/google-cloud-storage/assets/icon.svg new file mode 100644 index 00000000..547106c2 --- /dev/null +++ b/plugins/google-dev-kit/skills/google-cloud-storage/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud Storage product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/google-cloud-storage/references/safety.md b/plugins/google-dev-kit/skills/google-cloud-storage/references/safety.md new file mode 100644 index 00000000..f0e6b741 --- /dev/null +++ b/plugins/google-dev-kit/skills/google-cloud-storage/references/safety.md @@ -0,0 +1,7 @@ +# Storage safety + +Treat deletion, retention or Bucket Lock changes, public access, IAM/ACL changes, encryption key changes, lifecycle deletion rules, and unsafe overwrites as sensitive mutations. + +Inspect current state, describe the intended delta, and obtain authorization unless the user explicitly requested that exact mutation. Prefer uniform bucket-level access for new designs unless requirements say otherwise. + +The upstream Google skills include telemetry attribution conventions. This condensed derivative does not invent or persist telemetry configuration; fetch the current upstream skill or official docs when exact Google tooling attribution is required. diff --git a/plugins/google-dev-kit/skills/google-cloud-storage/references/workflows.md b/plugins/google-dev-kit/skills/google-cloud-storage/references/workflows.md new file mode 100644 index 00000000..acfc5c9e --- /dev/null +++ b/plugins/google-dev-kit/skills/google-cloud-storage/references/workflows.md @@ -0,0 +1,11 @@ +# Storage workflows + +This consolidates Google's `google-cloud-storage-basics` and `google-cloud-storage-bucket-architect` skills. + +## New bucket + +Identify workload and data sensitivity, confirm project/geography, choose location, class or Autoclass, uniform bucket-level access, public access prevention, recovery, retention, encryption, and lifecycle. Check constraints and name availability read-only. Present the plan and requested provisioning form. Create only when the request already authorizes creation or after confirmation. + +## Existing storage + +Route uploads, downloads, listings, metadata, lifecycle, signed URLs, transfers, and object management through Storage MCP where possible. Keep listings bounded. Retrieve current Storage docs instead of carrying a static command cookbook. diff --git a/plugins/google-dev-kit/skills/google-dev/SKILL.md b/plugins/google-dev-kit/skills/google-dev/SKILL.md new file mode 100644 index 00000000..cdd0a961 --- /dev/null +++ b/plugins/google-dev-kit/skills/google-dev/SKILL.md @@ -0,0 +1,16 @@ +--- +name: google-dev +description: Finds current official Google developer documentation and routes Google platform tasks to the right workflow or MCP. Use for Google Cloud, Gemini, Android, Firebase, Chrome, Flutter, Go, or other Google developer questions when live docs, product choice, API details, IAM permissions, or a Google skill are relevant. +--- + +# Google Developer Router + +Use official, current Google material before recalled syntax. + +1. For conceptual guidance or comparisons, query Developer Knowledge. Prefer conceptual QA; on quota errors, fall back to focused document search. +2. For exact syntax, permissions, fields, or flags, search and fetch the relevant document instead of guessing. +3. If the request maps to one of this plugin's focused skills, use it. Otherwise route to the narrowest MCP from [the endpoint catalog](references/mcp-catalog.md). +4. Treat authentication, permission, quota, empty-result, or transport errors as failed lookups. Never present memory as successful retrieval. +5. For broader Google skill discovery, consult the live `google/skills` catalog only for the current request. Do not persist a catalog snapshot. + +Read [documentation-routing.md](references/documentation-routing.md) for retrieval and catalog rules. diff --git a/plugins/google-dev-kit/skills/google-dev/agents/openai.yaml b/plugins/google-dev-kit/skills/google-dev/agents/openai.yaml new file mode 100644 index 00000000..697d6260 --- /dev/null +++ b/plugins/google-dev-kit/skills/google-dev/agents/openai.yaml @@ -0,0 +1,17 @@ +interface: + display_name: Google Developer + short_description: Live docs and product routing + icon_small: assets/icon.svg + icon_large: assets/icon.svg + brand_color: '#4285F4' + default_prompt: Use $google-dev to retrieve current official Google guidance, route to the narrowest workflow, and avoid stale API or CLI syntax. +dependencies: + tools: + - type: mcp + value: googleDeveloperKnowledge + description: Official Google developer documentation + transport: streamable_http + url: https://developerknowledge.googleapis.com/mcp +policy: + products: [CHAT, CODEX] + allow_implicit_invocation: true diff --git a/plugins/google-dev-kit/skills/google-dev/assets/icon.svg b/plugins/google-dev-kit/skills/google-dev/assets/icon.svg new file mode 100644 index 00000000..31064eee --- /dev/null +++ b/plugins/google-dev-kit/skills/google-dev/assets/icon.svg @@ -0,0 +1 @@ +Google Cloud APIs product icon \ No newline at end of file diff --git a/plugins/google-dev-kit/skills/google-dev/references/documentation-routing.md b/plugins/google-dev-kit/skills/google-dev/references/documentation-routing.md new file mode 100644 index 00000000..7523a09e --- /dev/null +++ b/plugins/google-dev-kit/skills/google-dev/references/documentation-routing.md @@ -0,0 +1,17 @@ +# Documentation routing + +## Developer Knowledge + +Preferred server: `googleDeveloperKnowledge`. + +- Use conceptual QA for architecture, product choice, and multi-step guidance. +- Use focused search for command syntax, API fields, IAM permissions, and exact names. +- Fetch the source document when an answer depends on a specific page or exact wording. +- On generative QA quota exhaustion, retry with focused search rather than ungrounded memory. +- If MCP tools are unavailable, the REST API is a fallback only when valid Google credentials or an API key already exist. + +## Google skills catalog + +The upstream catalog is generated at `https://raw.githubusercontent.com/google/skills/main/index.json`. + +For an uncovered workflow: fetch the current catalog, match at most three descriptions, fetch only those entrypoints, follow the fetched skill, then discard the snapshot. Never invent entries or reuse a stale catalog across sessions. diff --git a/plugins/google-dev-kit/skills/google-dev/references/mcp-catalog.md b/plugins/google-dev-kit/skills/google-dev/references/mcp-catalog.md new file mode 100644 index 00000000..fa8239df --- /dev/null +++ b/plugins/google-dev-kit/skills/google-dev/references/mcp-catalog.md @@ -0,0 +1,18 @@ +# Google MCP catalog + +Use the narrowest server that owns the requested resource. A URL in `mcp.json` does not prove the current account can authenticate or has preview access. + +| Alias | Primary use | Risk note | +| --- | --- | --- | +| `googleDeveloperKnowledge` | Official Google developer docs | Read-oriented | +| `googleCloudCli` | Validated gcloud execution | Can mutate cloud resources | +| `googleCloudStorage` | Buckets and objects | Can write/delete data | +| `googleApplicationDesignCenter` | Application Design Center | Preview; deployment mutates resources | +| `googleAndroidManagement` | Android Management | Preview; policy changes mutate devices | +| `googleCloudRun` | Cloud Run resources | Can deploy/modify services | +| `googleApiKeys` | API key lifecycle | Sensitive secrets and destructive operations | +| `googleCloudAssist` | Gemini Cloud Assist | Access may be private preview | +| `googleIam` | IAM roles and deny policies | Security-sensitive writes | +| `geminiApiDocs` | Gemini API docs/examples | Read-oriented | + +For API Keys, IAM, Android Management, and other security-sensitive control-plane changes, inspect first and require clear authorization before mutation. diff --git a/plugins/google-dev-kit/tests/test_package.py b/plugins/google-dev-kit/tests/test_package.py new file mode 100644 index 00000000..b0e938b7 --- /dev/null +++ b/plugins/google-dev-kit/tests/test_package.py @@ -0,0 +1,73 @@ +import importlib.util +import json +import tempfile +import unittest +import zipfile +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +SPEC = importlib.util.spec_from_file_location( + "pack", + ROOT / "scripts/package_plugin.py", +) +PACK = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(PACK) + + +class PackageTests(unittest.TestCase): + def test_source(self): + manifest, config = PACK.validate(ROOT) + self.assertEqual(manifest["name"], "google-dev-kit") + self.assertEqual(len(config["mcpServers"]), 10) + + def test_stage(self): + with tempfile.TemporaryDirectory() as directory: + target = Path(directory) / "google-dev-kit" + target.mkdir() + PACK.stage(ROOT, target) + overlay = json.loads( + (target / ".codex-plugin/plugin.json").read_text(), + ) + self.assertEqual(overlay["skills"], "./skills/") + self.assertEqual(overlay["mcpServers"], "./.mcp.json") + + def test_archive_contains_compatibility_manifests(self): + with tempfile.TemporaryDirectory() as directory: + archive_path = Path(directory) / "plugin.zip" + PACK.package(archive_path) + with zipfile.ZipFile(archive_path) as archive: + names = set(archive.namelist()) + self.assertIn("google-dev-kit/.mcp.json", names) + self.assertIn( + "google-dev-kit/.codex-plugin/plugin.json", + names, + ) + + def test_reproducible(self): + with tempfile.TemporaryDirectory() as directory: + first = Path(directory) / "a.zip" + second = Path(directory) / "b.zip" + self.assertEqual( + PACK.package(first)["sha256"], + PACK.package(second)["sha256"], + ) + self.assertEqual(first.read_bytes(), second.read_bytes()) + + def test_bad_product_policy(self): + with tempfile.TemporaryDirectory() as directory: + target = Path(directory) / "google-dev-kit" + target.mkdir() + PACK.stage(ROOT, target) + path = target / "skills/google-dev/agents/openai.yaml" + path.write_text( + path.read_text().replace( + "[CHAT, CODEX]", + "[chatgpt, codex]", + ), + ) + with self.assertRaisesRegex(ValueError, "CHAT and CODEX"): + PACK.validate(target) + + +if __name__ == "__main__": + unittest.main()