diff --git a/flux/vscode/README.md b/flux/vscode/README.md index 831eb8c..72c1167 100644 --- a/flux/vscode/README.md +++ b/flux/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `flux` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a image task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a image task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Flux MCP: Set Ace Data Cloud API Key** +- **Flux MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://flux.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -53,7 +58,23 @@ From $0.025 per image. Free trial credit on sign-up. See full pricing at [https: ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.flux +Server label: Flux MCP +Server URL : https://flux.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -68,21 +89,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -99,12 +116,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-flux-pro`](https://pypi.org/project/mcp-flux-pro/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/flux/vscode/extension.js b/flux/vscode/extension.js new file mode 100644 index 0000000..0f12c24 --- /dev/null +++ b/flux/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "flux" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "flux.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.flux.setApiToken +// - acedatacloud.flux.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.flux"; +const SERVER_LABEL = "Flux MCP"; +const SERVER_URL = "https://flux.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.flux.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.flux.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "flux.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/flux/vscode/package.json b/flux/vscode/package.json index d0af8a3..f0b888c 100644 --- a/flux/vscode/package.json +++ b/flux/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-flux", "displayName": "Flux MCP", "description": "Flux image generation by Black Forest Labs — dev, pro, ultra, and kontext editing.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/FluxMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "flux": { - "type": "http", - "url": "https://flux.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.flux", + "label": "Flux MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.flux.setApiToken", + "title": "Flux MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.flux.clearApiToken", + "title": "Flux MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/hailuo/vscode/README.md b/hailuo/vscode/README.md index f15cfbe..420258c 100644 --- a/hailuo/vscode/README.md +++ b/hailuo/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `hailuo` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Hailuo MCP: Set Ace Data Cloud API Key** +- **Hailuo MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://hailuo.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -49,7 +54,23 @@ From $0.20 per clip. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.hailuo +Server label: Hailuo MCP +Server URL : https://hailuo.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -64,21 +85,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -95,12 +112,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-hailuo`](https://pypi.org/project/mcp-hailuo/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/hailuo/vscode/extension.js b/hailuo/vscode/extension.js new file mode 100644 index 0000000..a7f747b --- /dev/null +++ b/hailuo/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "hailuo" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "hailuo.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.hailuo.setApiToken +// - acedatacloud.hailuo.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.hailuo"; +const SERVER_LABEL = "Hailuo MCP"; +const SERVER_URL = "https://hailuo.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.hailuo.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.hailuo.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "hailuo.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/hailuo/vscode/package.json b/hailuo/vscode/package.json index da93896..beb5119 100644 --- a/hailuo/vscode/package.json +++ b/hailuo/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-hailuo", "displayName": "Hailuo MCP", "description": "Hailuo (MiniMax) AI video — text-to-video and image-to-video with director mode.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -36,22 +36,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/HailuoMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "hailuo": { - "type": "http", - "url": "https://hailuo.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.hailuo", + "label": "Hailuo MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.hailuo.setApiToken", + "title": "Hailuo MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.hailuo.clearApiToken", + "title": "Hailuo MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/kling/vscode/README.md b/kling/vscode/README.md index 7f3150a..ec226d2 100644 --- a/kling/vscode/README.md +++ b/kling/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `kling` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Kling MCP: Set Ace Data Cloud API Key** +- **Kling MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://kling.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -51,7 +56,23 @@ From $0.20 per 5s clip. Free trial credit on sign-up. See full pricing at [https ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.kling +Server label: Kling MCP +Server URL : https://kling.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -66,21 +87,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -97,12 +114,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-kling`](https://pypi.org/project/mcp-kling/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/kling/vscode/extension.js b/kling/vscode/extension.js new file mode 100644 index 0000000..4c7c546 --- /dev/null +++ b/kling/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "kling" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "kling.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.kling.setApiToken +// - acedatacloud.kling.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.kling"; +const SERVER_LABEL = "Kling MCP"; +const SERVER_URL = "https://kling.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.kling.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.kling.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "kling.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/kling/vscode/package.json b/kling/vscode/package.json index d7a9863..987d596 100644 --- a/kling/vscode/package.json +++ b/kling/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-kling", "displayName": "Kling MCP", "description": "Kuaishou Kling video generation — text-to-video, image-to-video, extend, motion.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -36,22 +36,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/KlingMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "kling": { - "type": "http", - "url": "https://kling.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.kling", + "label": "Kling MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.kling.setApiToken", + "title": "Kling MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.kling.clearApiToken", + "title": "Kling MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/luma/vscode/README.md b/luma/vscode/README.md index fc16ea3..cdf60d0 100644 --- a/luma/vscode/README.md +++ b/luma/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `luma` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Luma MCP: Set Ace Data Cloud API Key** +- **Luma MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://luma.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -51,7 +56,23 @@ From $0.35 per 5s clip. Free trial credit on sign-up. See full pricing at [https ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.luma +Server label: Luma MCP +Server URL : https://luma.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -66,21 +87,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -97,12 +114,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-luma`](https://pypi.org/project/mcp-luma/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/luma/vscode/extension.js b/luma/vscode/extension.js new file mode 100644 index 0000000..ce22bbc --- /dev/null +++ b/luma/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "luma" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "luma.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.luma.setApiToken +// - acedatacloud.luma.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.luma"; +const SERVER_LABEL = "Luma MCP"; +const SERVER_URL = "https://luma.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.luma.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.luma.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "luma.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/luma/vscode/package.json b/luma/vscode/package.json index b092972..ebebf7b 100644 --- a/luma/vscode/package.json +++ b/luma/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-luma", "displayName": "Luma MCP", "description": "AI video generation with Luma Dream Machine — text-to-video, image-to-video, extend.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/LumaMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "luma": { - "type": "http", - "url": "https://luma.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.luma", + "label": "Luma MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.luma.setApiToken", + "title": "Luma MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.luma.clearApiToken", + "title": "Luma MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/midjourney/vscode/README.md b/midjourney/vscode/README.md index aa29add..e80400a 100644 --- a/midjourney/vscode/README.md +++ b/midjourney/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `midjourney` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a image task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a image task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Midjourney MCP: Set Ace Data Cloud API Key** +- **Midjourney MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://midjourney.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -63,7 +68,23 @@ From $0.04 per /imagine job. Free trial credit on sign-up. See full pricing at [ ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.midjourney +Server label: Midjourney MCP +Server URL : https://midjourney.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -78,21 +99,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -109,12 +126,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-midjourney`](https://pypi.org/project/mcp-midjourney/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/midjourney/vscode/extension.js b/midjourney/vscode/extension.js new file mode 100644 index 0000000..fb48cbc --- /dev/null +++ b/midjourney/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "midjourney" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "midjourney.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.midjourney.setApiToken +// - acedatacloud.midjourney.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.midjourney"; +const SERVER_LABEL = "Midjourney MCP"; +const SERVER_URL = "https://midjourney.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.midjourney.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.midjourney.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "midjourney.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/midjourney/vscode/package.json b/midjourney/vscode/package.json index 3a7244b..8d2f321 100644 --- a/midjourney/vscode/package.json +++ b/midjourney/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-midjourney", "displayName": "Midjourney MCP", "description": "AI image generation with Midjourney — imagine, edit, blend, upscale, describe.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/MidjourneyMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "midjourney": { - "type": "http", - "url": "https://midjourney.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.midjourney", + "label": "Midjourney MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.midjourney.setApiToken", + "title": "Midjourney MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.midjourney.clearApiToken", + "title": "Midjourney MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/nanobanana/vscode/README.md b/nanobanana/vscode/README.md index 7ea00fa..6afce85 100644 --- a/nanobanana/vscode/README.md +++ b/nanobanana/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `nanobanana` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a image task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a image task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **NanoBanana MCP: Set Ace Data Cloud API Key** +- **NanoBanana MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://nanobanana.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -51,7 +56,23 @@ From $0.015 per image. Free trial credit on sign-up. See full pricing at [https: ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.nanobanana +Server label: NanoBanana MCP +Server URL : https://nanobanana.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -66,21 +87,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -97,12 +114,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-nanobanana-pro`](https://pypi.org/project/mcp-nanobanana-pro/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/nanobanana/vscode/extension.js b/nanobanana/vscode/extension.js new file mode 100644 index 0000000..dde6be9 --- /dev/null +++ b/nanobanana/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "nanobanana" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "nanobanana.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.nanobanana.setApiToken +// - acedatacloud.nanobanana.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.nanobanana"; +const SERVER_LABEL = "NanoBanana MCP"; +const SERVER_URL = "https://nanobanana.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.nanobanana.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.nanobanana.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "nanobanana.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/nanobanana/vscode/package.json b/nanobanana/vscode/package.json index 358405b..e407420 100644 --- a/nanobanana/vscode/package.json +++ b/nanobanana/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-nanobanana", "displayName": "NanoBanana MCP", "description": "Gemini-powered NanoBanana — generate and edit images via natural language.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/NanoBananaMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "nanobanana": { - "type": "http", - "url": "https://nanobanana.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.nanobanana", + "label": "NanoBanana MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.nanobanana.setApiToken", + "title": "NanoBanana MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.nanobanana.clearApiToken", + "title": "NanoBanana MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/producer/vscode/README.md b/producer/vscode/README.md index 692eda3..99c7c59 100644 --- a/producer/vscode/README.md +++ b/producer/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `producer` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a music task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a music task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Producer MCP: Set Ace Data Cloud API Key** +- **Producer MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://producer.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -65,7 +70,23 @@ From $0.05 per song. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.producer +Server label: Producer MCP +Server URL : https://producer.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -80,21 +101,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -111,12 +128,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-producer`](https://pypi.org/project/mcp-producer/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/producer/vscode/extension.js b/producer/vscode/extension.js new file mode 100644 index 0000000..8163a41 --- /dev/null +++ b/producer/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "producer" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "producer.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.producer.setApiToken +// - acedatacloud.producer.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.producer"; +const SERVER_LABEL = "Producer MCP"; +const SERVER_URL = "https://producer.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.producer.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.producer.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "producer.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/producer/vscode/package.json b/producer/vscode/package.json index a63f178..4e9454e 100644 --- a/producer/vscode/package.json +++ b/producer/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-producer", "displayName": "Producer MCP", "description": "AI music with Producer (FUZZ) — songs, lyrics, covers, vocal/instrument swap, section replace.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -38,22 +38,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/ProducerMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "producer": { - "type": "http", - "url": "https://producer.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.producer", + "label": "Producer MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.producer.setApiToken", + "title": "Producer MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.producer.clearApiToken", + "title": "Producer MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/scripts/build_vscode_extensions.py b/scripts/build_vscode_extensions.py index ad9fca5..b23fdc1 100644 --- a/scripts/build_vscode_extensions.py +++ b/scripts/build_vscode_extensions.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 """ -Regenerate `/vscode/{package.json, README.md, .vscodeignore}` for -every MCP listed in `scripts/vscode_extensions.yaml`. +Regenerate `/vscode/{package.json, extension.js, README.md, .vscodeignore}` +for every MCP listed in `scripts/vscode_extensions.yaml`. -Primary configuration is a hosted streamable-HTTP endpoint at -`https://.mcp.acedata.cloud/mcp` with a Bearer token sourced from -a VS Code `inputs` prompt (so the user gets a password field instead of a -silent 401). README documents the local stdio fallback (`uvx mcp-`) -and the manual mcp.json snippet for OAuth. +The extension registers an HTTP MCP server via the proper VS Code API +(`contributes.mcpServerDefinitionProviders` + `vscode.lm.registerMcp\ +ServerDefinitionProvider`). On first use it prompts for an Ace Data Cloud +API key via `vscode.window.showInputBox` and persists it through +`SecretStorage`. Two commands (`: Set/Clear API Key`) let users +rotate or remove the key from the command palette. Usage: python3 scripts/build_vscode_extensions.py # all services @@ -57,6 +58,20 @@ class Service: def hosted_url(self) -> str: return f"https://{self.alias}.mcp.acedata.cloud/mcp" + @property + def provider_id(self) -> str: + # ID exposed to VS Code's MCP machinery. Keep it stable per service so + # bookmarks / Configure-Tools state survive reinstalls. + return f"acedatacloud.{self.alias}" + + @property + def set_token_cmd(self) -> str: + return f"acedatacloud.{self.alias}.setApiToken" + + @property + def clear_token_cmd(self) -> str: + return f"acedatacloud.{self.alias}.clearApiToken" + @property def repo_url(self) -> str: return f"https://github.com/AceDataCloud/{self.repo}" @@ -152,7 +167,7 @@ def render_package_json(svc: Service) -> str: "name": svc.ext_name, "displayName": svc.display_name, "description": svc.tagline, - "version": "0.2.0", + "version": "0.3.0", "publisher": svc.publisher, "icon": "icon.png", "license": "MIT", @@ -163,25 +178,25 @@ def render_package_json(svc: Service) -> str: "homepage": svc.repo_url, "repository": {"type": "git", "url": svc.repo_url}, "bugs": {"url": f"{svc.repo_url}/issues"}, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - svc.alias: { - "type": "http", - "url": svc.hosted_url, - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - }, + "mcpServerDefinitionProviders": [ + { + "id": svc.provider_id, + "label": svc.display_name, }, - }, - "inputs": [ + ], + "commands": [ { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": ( - f"Ace Data Cloud API token. Sign in at {svc.signup_url} " - "and create a token in 'API Keys'. Stored securely by VS Code." - ), - "password": True, + "command": svc.set_token_cmd, + "title": f"{svc.display_name}: Set Ace Data Cloud API Key", + "category": "MCP", + }, + { + "command": svc.clear_token_cmd, + "title": f"{svc.display_name}: Clear Ace Data Cloud API Key", + "category": "MCP", }, ], }, @@ -190,6 +205,102 @@ def render_package_json(svc: Service) -> str: return json.dumps(pkg, indent=2, ensure_ascii=False) + "\n" +def render_extension_js(svc: Service) -> str: + return f"""// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "{svc.alias}" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "{svc.alias}.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - {svc.set_token_cmd} +// - {svc.clear_token_cmd} + +const vscode = require("vscode"); + +const PROVIDER_ID = "{svc.provider_id}"; +const SERVER_LABEL = "{svc.display_name}"; +const SERVER_URL = "{svc.hosted_url}"; +const SET_TOKEN_CMD = "{svc.set_token_cmd}"; +const CLEAR_TOKEN_CMD = "{svc.clear_token_cmd}"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "{svc.alias}.apiToken"; +const SIGNUP_URL = "{svc.signup_url}"; + +async function readToken(context) {{ + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +}} + +async function promptForToken(context) {{ + const token = await vscode.window.showInputBox({{ + title: `${{SERVER_LABEL}} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${{SIGNUP_URL}}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }}); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +}} + +function activate(context) {{ + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => {{ + const t = await promptForToken(context); + if (t) {{ + vscode.window.showInformationMessage(`${{SERVER_LABEL}}: API key saved.`); + onDidChange.fire(); + }} + }}), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => {{ + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${{SERVER_LABEL}}: API key cleared.`); + onDidChange.fire(); + }}), + context.secrets.onDidChange((e) => {{ + if (e.key === SECRET_KEY) onDidChange.fire(); + }}), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, {{ + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => {{ + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) {{ + throw new Error( + `${{SERVER_LABEL}} needs an Ace Data Cloud API key. ` + + `Run "${{SERVER_LABEL}}: Set Ace Data Cloud API Key" from the command palette.` + ); + }} + return new vscode.McpHttpServerDefinition(server.label, server.uri, {{ + Authorization: `Bearer ${{token}}`, + }}); + }}, + }}) + ); +}} + +function deactivate() {{}} + +module.exports = {{ activate, deactivate }}; +""" + + def render_readme(svc: Service, tools: list[tuple[str, str]]) -> str: badge_line = ( f"[![VS Code Marketplace]" @@ -240,8 +351,13 @@ def render_readme(svc: Service, tools: list[tuple[str, str]]) -> str: ## Quick Start 1. **Install this extension.** VS Code registers the `{svc.alias}` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud]({svc.signup_url}) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a {svc.domain} task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud]({svc.signup_url}/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a {svc.domain} task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **{svc.display_name}: Set Ace Data Cloud API Key** +- **{svc.display_name}: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `{svc.hosted_url}` — no Python, no `uvx`, no local install needed. @@ -266,7 +382,23 @@ def render_readme(svc: Service, tools: list[tuple[str, str]]) -> str: ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : {svc.provider_id} +Server label: {svc.display_name} +Server URL : {svc.hosted_url} +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc {{ @@ -281,21 +413,17 @@ def render_readme(svc: Service, tools: list[tuple[str, str]]) -> str: {{ "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true }} ] }} ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc {{ @@ -312,12 +440,6 @@ def render_readme(svc: Service, tools: list[tuple[str, str]]) -> str: `uvx` will download and run the latest [`{svc.pypi_pkg}`]({svc.pypi_url}) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links @@ -364,10 +486,13 @@ def process(svc: Service, *, dry_run: bool) -> list[str]: tools = extract_tools(ROOT / svc.alias / "README.md") pkg_text = render_package_json(svc) + ext_text = render_extension_js(svc) readme_text = render_readme(svc, tools) if write_if_changed(vscode_dir / "package.json", pkg_text, dry_run=dry_run): changes.append(f" {svc.alias}/vscode/package.json") + if write_if_changed(vscode_dir / "extension.js", ext_text, dry_run=dry_run): + changes.append(f" {svc.alias}/vscode/extension.js") if write_if_changed(vscode_dir / "README.md", readme_text, dry_run=dry_run): changes.append(f" {svc.alias}/vscode/README.md") if write_if_changed(vscode_dir / ".vscodeignore", VSCODEIGNORE, dry_run=dry_run): diff --git a/scripts/vscode_extensions.yaml b/scripts/vscode_extensions.yaml index 76b7770..a9d49e8 100644 --- a/scripts/vscode_extensions.yaml +++ b/scripts/vscode_extensions.yaml @@ -16,7 +16,9 @@ defaults: publisher: acedatacloud signup_url: https://platform.acedata.cloud docs_url: https://docs.acedata.cloud - vscode_engine: "^1.99.0" + # 1.101.0 is the first stable release with vscode.lm.registerMcpServerDefinitionProvider + # + McpHttpServerDefinition (matches Context7 + microsoft/vscode d.ts). + vscode_engine: "^1.101.0" common_categories: ["AI", "Chat"] common_keywords: - mcp diff --git a/seedance/vscode/README.md b/seedance/vscode/README.md index e003cf3..f79715f 100644 --- a/seedance/vscode/README.md +++ b/seedance/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `seedance` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Seedance MCP: Set Ace Data Cloud API Key** +- **Seedance MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://seedance.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -50,7 +55,23 @@ From $0.15 per clip. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.seedance +Server label: Seedance MCP +Server URL : https://seedance.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -65,21 +86,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -96,12 +113,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-seedance`](https://pypi.org/project/mcp-seedance/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/seedance/vscode/extension.js b/seedance/vscode/extension.js new file mode 100644 index 0000000..e1f8524 --- /dev/null +++ b/seedance/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "seedance" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "seedance.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.seedance.setApiToken +// - acedatacloud.seedance.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.seedance"; +const SERVER_LABEL = "Seedance MCP"; +const SERVER_URL = "https://seedance.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.seedance.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.seedance.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "seedance.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/seedance/vscode/package.json b/seedance/vscode/package.json index 4be299c..3c2dc57 100644 --- a/seedance/vscode/package.json +++ b/seedance/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-seedance", "displayName": "Seedance MCP", "description": "ByteDance Seedance — dance and motion video generation from text or image.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/SeedanceMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "seedance": { - "type": "http", - "url": "https://seedance.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.seedance", + "label": "Seedance MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.seedance.setApiToken", + "title": "Seedance MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.seedance.clearApiToken", + "title": "Seedance MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/seedream/vscode/README.md b/seedream/vscode/README.md index dac4427..a8c87cc 100644 --- a/seedream/vscode/README.md +++ b/seedream/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `seedream` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a image task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a image task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Seedream MCP: Set Ace Data Cloud API Key** +- **Seedream MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://seedream.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -53,7 +58,23 @@ From $0.02 per image. Free trial credit on sign-up. See full pricing at [https:/ ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.seedream +Server label: Seedream MCP +Server URL : https://seedream.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -68,21 +89,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -99,12 +116,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-seedream-pro`](https://pypi.org/project/mcp-seedream-pro/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/seedream/vscode/extension.js b/seedream/vscode/extension.js new file mode 100644 index 0000000..8adeb9b --- /dev/null +++ b/seedream/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "seedream" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "seedream.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.seedream.setApiToken +// - acedatacloud.seedream.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.seedream"; +const SERVER_LABEL = "Seedream MCP"; +const SERVER_URL = "https://seedream.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.seedream.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.seedream.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "seedream.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/seedream/vscode/package.json b/seedream/vscode/package.json index fc1a27c..77e0b2e 100644 --- a/seedream/vscode/package.json +++ b/seedream/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-seedream", "displayName": "Seedream MCP", "description": "Seedream by ByteDance — text-to-image and SeedEdit instruction-based editing.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/SeedreamMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "seedream": { - "type": "http", - "url": "https://seedream.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.seedream", + "label": "Seedream MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.seedream.setApiToken", + "title": "Seedream MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.seedream.clearApiToken", + "title": "Seedream MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/serp/vscode/README.md b/serp/vscode/README.md index c4e44a2..dc0ece4 100644 --- a/serp/vscode/README.md +++ b/serp/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `serp` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a search task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a search task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Serp MCP: Set Ace Data Cloud API Key** +- **Serp MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://serp.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -55,7 +60,23 @@ From $0.003 per query. Free trial credit on sign-up. See full pricing at [https: ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.serp +Server label: Serp MCP +Server URL : https://serp.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -70,21 +91,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -101,12 +118,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-serp`](https://pypi.org/project/mcp-serp/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/serp/vscode/extension.js b/serp/vscode/extension.js new file mode 100644 index 0000000..7e15e7d --- /dev/null +++ b/serp/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "serp" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "serp.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.serp.setApiToken +// - acedatacloud.serp.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.serp"; +const SERVER_LABEL = "Serp MCP"; +const SERVER_URL = "https://serp.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.serp.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.serp.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "serp.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/serp/vscode/package.json b/serp/vscode/package.json index ad141fe..ad9a1ee 100644 --- a/serp/vscode/package.json +++ b/serp/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-serp", "displayName": "Serp MCP", "description": "Google Search via Ace Data Cloud — web, images, news, maps, local, video.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -38,22 +38,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/SerpMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "serp": { - "type": "http", - "url": "https://serp.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.serp", + "label": "Serp MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.serp.setApiToken", + "title": "Serp MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.serp.clearApiToken", + "title": "Serp MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/shorturl/vscode/README.md b/shorturl/vscode/README.md index 410a884..ac278a3 100644 --- a/shorturl/vscode/README.md +++ b/shorturl/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `shorturl` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a utility task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a utility task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Short URL MCP: Set Ace Data Cloud API Key** +- **Short URL MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://shorturl.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -47,7 +52,23 @@ Free tier available. Higher quotas with paid plans. See full pricing at [https:/ ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.shorturl +Server label: Short URL MCP +Server URL : https://shorturl.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -62,21 +83,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -93,12 +110,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-shorturl`](https://pypi.org/project/mcp-shorturl/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/shorturl/vscode/extension.js b/shorturl/vscode/extension.js new file mode 100644 index 0000000..3bc3549 --- /dev/null +++ b/shorturl/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "shorturl" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "shorturl.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.shorturl.setApiToken +// - acedatacloud.shorturl.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.shorturl"; +const SERVER_LABEL = "Short URL MCP"; +const SERVER_URL = "https://shorturl.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.shorturl.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.shorturl.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "shorturl.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/shorturl/vscode/package.json b/shorturl/vscode/package.json index 021a2e2..d0144d7 100644 --- a/shorturl/vscode/package.json +++ b/shorturl/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-shorturl", "displayName": "Short URL MCP", "description": "Create short URLs (surl.id) — single or batch, with custom slugs and expiration.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -36,22 +36,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/ShortURLMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "shorturl": { - "type": "http", - "url": "https://shorturl.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.shorturl", + "label": "Short URL MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.shorturl.setApiToken", + "title": "Short URL MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.shorturl.clearApiToken", + "title": "Short URL MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/sora/vscode/README.md b/sora/vscode/README.md index dd62384..67dd4e1 100644 --- a/sora/vscode/README.md +++ b/sora/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `sora` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Sora MCP: Set Ace Data Cloud API Key** +- **Sora MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://sora.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -57,7 +62,23 @@ From $0.50 per clip. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.sora +Server label: Sora MCP +Server URL : https://sora.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -72,21 +93,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -103,12 +120,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-sora`](https://pypi.org/project/mcp-sora/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/sora/vscode/extension.js b/sora/vscode/extension.js new file mode 100644 index 0000000..bc17d6d --- /dev/null +++ b/sora/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "sora" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "sora.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.sora.setApiToken +// - acedatacloud.sora.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.sora"; +const SERVER_LABEL = "Sora MCP"; +const SERVER_URL = "https://sora.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.sora.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.sora.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "sora.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/sora/vscode/package.json b/sora/vscode/package.json index 918db5c..b029a8b 100644 --- a/sora/vscode/package.json +++ b/sora/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-sora", "displayName": "Sora MCP", "description": "OpenAI Sora video generation — text-to-video, image-to-video, character references.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -36,22 +36,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/SoraMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "sora": { - "type": "http", - "url": "https://sora.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.sora", + "label": "Sora MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.sora.setApiToken", + "title": "Sora MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.sora.clearApiToken", + "title": "Sora MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/suno/vscode/README.md b/suno/vscode/README.md index 0d34ee2..8d48ada 100644 --- a/suno/vscode/README.md +++ b/suno/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `suno` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a music task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a music task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Suno MCP: Set Ace Data Cloud API Key** +- **Suno MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://suno.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -75,7 +80,23 @@ From $0.05 per song. New users get free trial credit at sign-up. See full pricin ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.suno +Server label: Suno MCP +Server URL : https://suno.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -90,21 +111,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -121,12 +138,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-suno`](https://pypi.org/project/mcp-suno/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/suno/vscode/extension.js b/suno/vscode/extension.js new file mode 100644 index 0000000..09026e2 --- /dev/null +++ b/suno/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "suno" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "suno.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.suno.setApiToken +// - acedatacloud.suno.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.suno"; +const SERVER_LABEL = "Suno MCP"; +const SERVER_URL = "https://suno.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.suno.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.suno.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "suno.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/suno/vscode/package.json b/suno/vscode/package.json index 6201df7..406b093 100644 --- a/suno/vscode/package.json +++ b/suno/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-suno", "displayName": "Suno MCP", "description": "AI music generation with Suno — songs, lyrics, covers, stems, and more.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -38,22 +38,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/SunoMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "suno": { - "type": "http", - "url": "https://suno.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.suno", + "label": "Suno MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.suno.setApiToken", + "title": "Suno MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.suno.clearApiToken", + "title": "Suno MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/veo/vscode/README.md b/veo/vscode/README.md index 573dbd0..7bf3489 100644 --- a/veo/vscode/README.md +++ b/veo/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `veo` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Veo MCP: Set Ace Data Cloud API Key** +- **Veo MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://veo.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -55,7 +60,23 @@ From $0.30 per clip. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.veo +Server label: Veo MCP +Server URL : https://veo.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -70,21 +91,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -101,12 +118,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-veo`](https://pypi.org/project/mcp-veo/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/veo/vscode/extension.js b/veo/vscode/extension.js new file mode 100644 index 0000000..a4eb90d --- /dev/null +++ b/veo/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "veo" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "veo.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.veo.setApiToken +// - acedatacloud.veo.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.veo"; +const SERVER_LABEL = "Veo MCP"; +const SERVER_URL = "https://veo.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.veo.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.veo.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "veo.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/veo/vscode/package.json b/veo/vscode/package.json index 2fff4c6..a9ef826 100644 --- a/veo/vscode/package.json +++ b/veo/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-veo", "displayName": "Veo MCP", "description": "Google Veo video generation — Veo 2, Veo 3, Veo 3.1 (incl. fast variants and upscale).", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -36,22 +36,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/VeoMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "veo": { - "type": "http", - "url": "https://veo.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.veo", + "label": "Veo MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.veo.setApiToken", + "title": "Veo MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.veo.clearApiToken", + "title": "Veo MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] } diff --git a/wan/vscode/README.md b/wan/vscode/README.md index cb41131..08d6ab5 100644 --- a/wan/vscode/README.md +++ b/wan/vscode/README.md @@ -15,8 +15,13 @@ can call it directly from chat. ## Quick Start 1. **Install this extension.** VS Code registers the `wan` MCP server automatically. -2. **Get an API token** from [Ace Data Cloud](https://platform.acedata.cloud) → *API Keys*. New accounts include free trial credit. -3. **Open Copilot Chat** in agent mode and ask for a video task — VS Code will prompt for the token the first time and store it securely. +2. **Get an API key** from [Ace Data Cloud](https://platform.acedata.cloud/console/applications) (Applications → API Key). New accounts include free trial credit. +3. **Open Copilot Chat** in agent mode and ask for a video task — the extension prompts for the API key the first time and stores it in the OS keychain via VS Code's `SecretStorage`. + +You can rotate or remove the API key any time from the command palette: + +- **Wan MCP: Set Ace Data Cloud API Key** +- **Wan MCP: Clear Ace Data Cloud API Key** > The default config talks to the **hosted streamable-HTTP endpoint** at > `https://wan.mcp.acedata.cloud/mcp` — no Python, no `uvx`, no local install needed. @@ -50,7 +55,23 @@ From $0.18 per clip. Free trial credit on sign-up. See full pricing at [https:// ## Configuration -This extension contributes the following entry to your VS Code MCP config: +This extension implements the `mcpServerDefinitionProviders` contribution point +and registers a single hosted server with VS Code: + +```text +Provider id : acedatacloud.wan +Server label: Wan MCP +Server URL : https://wan.mcp.acedata.cloud/mcp +Transport : Streamable HTTP +Auth : Bearer API key from VS Code SecretStorage (or $ACEDATACLOUD_API_TOKEN) +``` + +You don't need to edit `mcp.json` — the extension handles registration and +token handling automatically. If you'd rather configure things by hand, the +sections below show equivalent `mcp.json` snippets you can use **instead of** +this extension. + +### Alternative: manual `mcp.json` (hosted) ```jsonc { @@ -65,21 +86,17 @@ This extension contributes the following entry to your VS Code MCP config: { "type": "promptString", "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token", + "description": "Ace Data Cloud API key", "password": true } ] } ``` -VS Code will prompt for the token on first use and persist it in the OS -secret store (Keychain / Credential Manager / libsecret). - ### Alternative: local stdio (no network roundtrip) -If you prefer running the server locally — for offline dev, air-gapped -environments, or to pin to a specific PyPI version — install -[`uv`](https://docs.astral.sh/uv/) and replace your `mcp.json` entry with: +For offline dev, air-gapped environments, or pinning to a specific PyPI +version, install [`uv`](https://docs.astral.sh/uv/) and use: ```jsonc { @@ -96,12 +113,6 @@ environments, or to pin to a specific PyPI version — install `uvx` will download and run the latest [`mcp-wan`](https://pypi.org/project/mcp-wan/) on demand. -### Alternative: OAuth via Dynamic Client Registration - -The hosted endpoint also accepts OAuth 2.1 with [DCR](https://datatracker.ietf.org/doc/html/rfc7591). -Drop the `headers` and `inputs` blocks and VS Code will run the auth flow on -first use (redirect URL `http://127.0.0.1:33418` or `https://vscode.dev/redirect`). - --- ## Links diff --git a/wan/vscode/extension.js b/wan/vscode/extension.js new file mode 100644 index 0000000..e919716 --- /dev/null +++ b/wan/vscode/extension.js @@ -0,0 +1,92 @@ +// Auto-generated by scripts/build_vscode_extensions.py — DO NOT EDIT BY HAND. +// +// Registers the hosted Ace Data Cloud "wan" MCP server with VS Code +// via the stable `vscode.lm.registerMcpServerDefinitionProvider` API. The +// Bearer API key is read from (in order): +// 1. process.env.ACEDATACLOUD_API_TOKEN +// 2. VS Code SecretStorage (key "wan.apiToken") +// 3. An interactive showInputBox prompt on first use +// +// Two commands are exposed for managing the API key from the command palette: +// - acedatacloud.wan.setApiToken +// - acedatacloud.wan.clearApiToken + +const vscode = require("vscode"); + +const PROVIDER_ID = "acedatacloud.wan"; +const SERVER_LABEL = "Wan MCP"; +const SERVER_URL = "https://wan.mcp.acedata.cloud/mcp"; +const SET_TOKEN_CMD = "acedatacloud.wan.setApiToken"; +const CLEAR_TOKEN_CMD = "acedatacloud.wan.clearApiToken"; +// Per-extension SecretStorage namespace; we keep one key per service so +// rotating one API key doesn't affect siblings. +const SECRET_KEY = "wan.apiToken"; +const SIGNUP_URL = "https://platform.acedata.cloud"; + +async function readToken(context) { + const env = process.env.ACEDATACLOUD_API_TOKEN; + if (env && env.trim()) return env.trim(); + const stored = await context.secrets.get(SECRET_KEY); + return stored ? stored.trim() : undefined; +} + +async function promptForToken(context) { + const token = await vscode.window.showInputBox({ + title: `${SERVER_LABEL} — Ace Data Cloud API key`, + prompt: `Paste an API key from ${SIGNUP_URL}/console/applications (Applications -> API Key). Stored in the OS keychain.`, + placeHolder: "API key from /console/applications", + password: true, + ignoreFocusOut: true, + }); + if (!token) return undefined; + const trimmed = token.trim(); + if (!trimmed) return undefined; + await context.secrets.store(SECRET_KEY, trimmed); + return trimmed; +} + +function activate(context) { + const onDidChange = new vscode.EventEmitter(); + + context.subscriptions.push( + onDidChange, + vscode.commands.registerCommand(SET_TOKEN_CMD, async () => { + const t = await promptForToken(context); + if (t) { + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key saved.`); + onDidChange.fire(); + } + }), + vscode.commands.registerCommand(CLEAR_TOKEN_CMD, async () => { + await context.secrets.delete(SECRET_KEY); + vscode.window.showInformationMessage(`${SERVER_LABEL}: API key cleared.`); + onDidChange.fire(); + }), + context.secrets.onDidChange((e) => { + if (e.key === SECRET_KEY) onDidChange.fire(); + }), + vscode.lm.registerMcpServerDefinitionProvider(PROVIDER_ID, { + onDidChangeMcpServerDefinitions: onDidChange.event, + provideMcpServerDefinitions: () => [ + new vscode.McpHttpServerDefinition(SERVER_LABEL, vscode.Uri.parse(SERVER_URL)), + ], + resolveMcpServerDefinition: async (server) => { + let token = await readToken(context); + if (!token) token = await promptForToken(context); + if (!token) { + throw new Error( + `${SERVER_LABEL} needs an Ace Data Cloud API key. ` + + `Run "${SERVER_LABEL}: Set Ace Data Cloud API Key" from the command palette.` + ); + } + return new vscode.McpHttpServerDefinition(server.label, server.uri, { + Authorization: `Bearer ${token}`, + }); + }, + }) + ); +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/wan/vscode/package.json b/wan/vscode/package.json index db8320a..4990352 100644 --- a/wan/vscode/package.json +++ b/wan/vscode/package.json @@ -2,12 +2,12 @@ "name": "mcp-wan", "displayName": "Wan MCP", "description": "Alibaba Wan video generation — text-to-video, image-to-video, reference video transfer.", - "version": "0.2.0", + "version": "0.3.0", "publisher": "acedatacloud", "icon": "icon.png", "license": "MIT", "engines": { - "vscode": "^1.99.0" + "vscode": "^1.101.0" }, "categories": [ "AI", @@ -37,22 +37,25 @@ "bugs": { "url": "https://github.com/AceDataCloud/WanMCP/issues" }, + "activationEvents": [], + "main": "./extension.js", "contributes": { - "mcpServers": { - "wan": { - "type": "http", - "url": "https://wan.mcp.acedata.cloud/mcp", - "headers": { - "Authorization": "Bearer ${input:acedatacloud_api_token}" - } + "mcpServerDefinitionProviders": [ + { + "id": "acedatacloud.wan", + "label": "Wan MCP" } - }, - "inputs": [ + ], + "commands": [ + { + "command": "acedatacloud.wan.setApiToken", + "title": "Wan MCP: Set Ace Data Cloud API Key", + "category": "MCP" + }, { - "type": "promptString", - "id": "acedatacloud_api_token", - "description": "Ace Data Cloud API token. Sign in at https://platform.acedata.cloud and create a token in 'API Keys'. Stored securely by VS Code.", - "password": true + "command": "acedatacloud.wan.clearApiToken", + "title": "Wan MCP: Clear Ace Data Cloud API Key", + "category": "MCP" } ] }