diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 1229ff9..eb16a47 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -1,5 +1,6 @@ { "name": "voiceflow-plugins", "interface": { "displayName": "Voiceflow" }, "plugins": [{ "name": "voiceflow", "source": { "source": "local", "path": "./voiceflow" }, - "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" } }] + "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, + "category": "Developer Tools" }] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c585b..f355de1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,15 @@ from `https://mcp.voiceflow.com/mcp?version=2` to provisional until the docs server ships the option. - Send only the package, skill, and stage tag in the docs `why` field, with no task, symptom, or setup-state sentence. +- Add a plugin README that explains setup, the services the plugin contacts, + and what each one receives. Anthropic's directory shows it as the listing. +- Add directory listing metadata: display name, links, keywords, the + `Developer Tools` category, starter prompts, and `voiceflow-setup` as the + onboarding skill. The listing icon is still missing. +- Add `skills.sh.json` so `npx skills add voiceflow/agent-plugins` finds every + skill under `voiceflow/skills`. +- Add MCP Registry entries for the account and docs servers. They are not + published. - Refuse a `vf_*` name that v3 does not serve, and every older `voiceflow_` name, in the skill reference checks. - Add the Optimize playbooks skill: condense long instructions, or move a job diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index feb1f3e..999e01e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,6 +28,8 @@ python3 scripts/build.py | `tests/fixtures/voiceflow-surface.json` | MCP and CLI names the skill checks accept; not packaged | | `evals/` | Behavioral cases, protocols, and sanitized evidence | | `docs/` | Compatibility, release, provenance, and measurement guidance | +| `skills.sh.json` | Tells the skills CLI where the skills live; not packaged | +| `mcp-registry/` | MCP Registry entries for the two remote servers; not packaged or published | | `dist/` | Generated output; do not commit it | | `package-files.txt` | Reviewed list of files allowed into published packages | | `AGENTS.md` and `CLAUDE.md` | Shared contributor rules and Claude Code entrypoint | diff --git a/docs/releasing.md b/docs/releasing.md index 9b118bc..d131ec4 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -155,5 +155,11 @@ plugin name `voiceflow`, marketplace name `voiceflow-plugins`, and skill names stable. Do not recreate the repository at its previous location: that removes GitHub's redirect. Marketplace submission is independent of repository publication. +Directory listings read the plugin manifests and `voiceflow/README.md`. +`scripts/validate.py` checks that the manifests share their links, keywords, +category, and onboarding skill. Anthropic's portal may take the listing icon +only from the first save or submission, so add the official icon first. +Submitting to a directory is an owner decision, like publishing a release. + Package docs connections turn off Knowledge MCP logging, as explained in [measurement](measurement.md); releases do not add a separate analytics service. diff --git a/mcp-registry/README.md b/mcp-registry/README.md new file mode 100644 index 0000000..3ca030f --- /dev/null +++ b/mcp-registry/README.md @@ -0,0 +1,20 @@ +# MCP Registry entries + +These files describe Voiceflow's two remote MCP servers for the official +[MCP Registry](https://registry.modelcontextprotocol.io). They are not part of +the plugin package, and nothing in this repository publishes them. + +| Folder | Server | URL | +| --- | --- | --- | +| `voiceflow/` | Voiceflow account MCP, OAuth | `https://mcp.voiceflow.com/mcp` | +| `knowledge/` | Voiceflow Knowledge docs MCP, no sign-in | The public docs MCP URL, without the package's `logging=off` option | + +The docs entry has no `logging=off` option. People who add the server from the +registry are treated like people who add it by hand, so the docs server can log +their requests. + +Publishing needs an owner decision on the server names, because a published +name is hard to change. The `com.voiceflow/` namespace also needs DNS or HTTP +verification of `voiceflow.com`. See the registry's +[authentication guide](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx). +Each published version needs a new `version` value. diff --git a/mcp-registry/knowledge/server.json b/mcp-registry/knowledge/server.json new file mode 100644 index 0000000..4cce99a --- /dev/null +++ b/mcp-registry/knowledge/server.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "com.voiceflow/knowledge", + "title": "Voiceflow Knowledge", + "description": "Answers Voiceflow product, API, and CLI questions from the public docs. No sign-in.", + "version": "2.1.2", + "websiteUrl": "https://www.voiceflow.com/docs/mcp/knowledge", + "remotes": [ + { + "type": "streamable-http", + "url": "https://www.voiceflow.com/docs/mcp" + } + ] +} diff --git a/mcp-registry/voiceflow/server.json b/mcp-registry/voiceflow/server.json new file mode 100644 index 0000000..3554b13 --- /dev/null +++ b/mcp-registry/voiceflow/server.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "com.voiceflow/voiceflow", + "title": "Voiceflow", + "description": "Build, test, and manage Voiceflow agents in your workspace. Sign in with OAuth.", + "version": "3.0.0", + "websiteUrl": "https://www.voiceflow.com/docs", + "remotes": [ + { + "type": "streamable-http", + "url": "https://mcp.voiceflow.com/mcp" + } + ] +} diff --git a/package-files.txt b/package-files.txt index 379c900..891ad14 100644 --- a/package-files.txt +++ b/package-files.txt @@ -3,6 +3,7 @@ voiceflow/.codex-plugin/plugin.json voiceflow/.cursor-plugin/plugin.json voiceflow/.mcp.json voiceflow/LICENSE +voiceflow/README.md voiceflow/mcp.json voiceflow/plugin.json voiceflow/skills/voiceflow-build/LICENSE diff --git a/scripts/validate.py b/scripts/validate.py index c753492..48473e9 100644 --- a/scripts/validate.py +++ b/scripts/validate.py @@ -23,6 +23,18 @@ DOCS_MCP_URL = "https://www.voiceflow.com/docs/mcp?logging=off" DOCS_MCP_ENDPOINT = re.compile(r"https://www\.voiceflow\.com/docs/mcp(?![\w/-])(?:\?[\w=&%-]+)?") DOCS_URL_SCOPE = ("voiceflow/**/*", "*.md", "docs/*.md", "evals/*.md", "scripts/*.py", "tests/*.py") +ACCOUNT_MCP_URL = "https://mcp.voiceflow.com/mcp" +REGISTRY_SCHEMA = "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json" +SKILLS_SH_SCHEMA = "https://skills.sh/schemas/skills.sh.schema.json" +KEYWORD = re.compile(r"[a-z0-9]+(?:-[a-z0-9]+)*") +SEMVER = re.compile(r"\d+\.\d+\.\d+") +# Limits from developers.openai.com/plugins/deploy/submission (listing metadata). +INTERFACE_LIMITS = {"displayName": 30, "shortDescription": 30, "longDescription": 4000, "developerName": 80, + "category": 80, "websiteURL": 1024, "supportURL": 1024, "privacyPolicyURL": 1024, + "termsOfServiceURL": 1024} +# Anthropic's directory reads these from .claude-plugin/plugin.json; each matches an OpenAI interface field. +CLAUDE_LISTING = {"supportUrl": "supportURL", "privacyPolicyUrl": "privacyPolicyURL", + "termsOfServiceUrl": "termsOfServiceURL"} class ReferenceProblems(AssertionError): @@ -54,6 +66,68 @@ def docs_url_problems(root): return problems +def prose_words(text): + """Count words outside fenced code, as Anthropic's directory counts README words.""" + words, is_fenced = 0, False + for line in text.splitlines(): + if line.lstrip().startswith(("```", "~~~")): + is_fenced = not is_fenced + elif not is_fenced: + words += len(line.split()) + return words + + +def validate_listings(root=ROOT): + """Check the directory listing metadata: manifests, plugin README, skills.sh, and MCP Registry entries.""" + plugin = root / "voiceflow" + portable = json.loads((plugin / "plugin.json").read_text(encoding="utf-8")) + claude, codex, cursor = (json.loads((plugin / folder / "plugin.json").read_text(encoding="utf-8")) + for folder in (".claude-plugin", ".codex-plugin", ".cursor-plugin")) + for manifest in (portable, claude, codex, cursor): + for field in ("homepage", "repository", "keywords"): + assert manifest.get(field) == portable[field], f"Listing field differs between manifests: {field}" + assert portable["homepage"].startswith("https://") and portable["repository"].startswith("https://github.com/") + assert portable["keywords"] and all(KEYWORD.fullmatch(word) for word in portable["keywords"]), "Keywords must be lowercase-hyphenated" + openai = portable["extensions"]["com.openai"] + interface = openai["interface"] + for field, limit in INTERFACE_LIMITS.items(): + assert isinstance(interface.get(field), str) and 0 < len(interface[field]) <= limit, f"Invalid interface.{field}" + if field.endswith("URL"): + assert interface[field].startswith("https://"), f"interface.{field} must be https" + capabilities, prompts = interface["capabilities"], interface["defaultPrompt"] + assert len(capabilities) <= 20 and all(0 < len(item) <= 120 for item in capabilities), "Invalid capabilities" + assert 0 < len(prompts) <= 3 and len(set(prompts)) == len(prompts), "Use one to three unique default prompts" + assert all(0 < len(prompt) <= 128 and "@" not in prompt for prompt in prompts), "Invalid default prompt" + onboarding = openai["onboardingSkill"] + assert onboarding.startswith("./") and (plugin / onboarding).is_file(), "Onboarding skill missing" + assert codex["interface"] == interface, "Codex interface differs from plugin.json" + assert codex["extensions"]["com.openai"]["onboardingSkill"] == onboarding, "Codex onboarding skill differs" + assert claude["displayName"] == interface["displayName"], "Claude displayName differs" + assert claude["documentationUrl"].startswith("https://"), "documentationUrl must be https" + for field, openai_field in CLAUDE_LISTING.items(): + assert claude[field] == interface[openai_field], f"Claude {field} differs from interface.{openai_field}" + icons = [claude.get("icon"), cursor.get("logo"), interface.get("logo"), interface.get("composerIcon")] + for icon in filter(None, icons): + assert (plugin / icon).is_file() and icon.endswith((".png", ".jpg", ".jpeg")), f"Icon file missing: {icon}" + market = json.loads((root / ".agents/plugins/marketplace.json").read_text(encoding="utf-8")) + assert market["plugins"][0]["category"] == interface["category"], "Marketplace category differs" + readme = plugin / "README.md" + assert readme.is_file() and prose_words(readme.read_text(encoding="utf-8")) >= 40, "Plugin README needs 40+ words" + skills_sh = json.loads((root / "skills.sh.json").read_text(encoding="utf-8")) + assert skills_sh == {"$schema": SKILLS_SH_SCHEMA, "paths": ["./voiceflow/skills"]}, "skills.sh.json drift" + # Registry users add the docs server themselves, so its entry omits the package's logging option. + expected = {ACCOUNT_MCP_URL, DOCS_MCP_URL.split("?")[0]} + entries = [json.loads(path.read_text(encoding="utf-8")) + for path in sorted((root / "mcp-registry").glob("*/server.json"))] + assert {remote["url"] for entry in entries for remote in entry["remotes"]} == expected, "Registry URLs differ" + assert len({entry["name"] for entry in entries}) == len(entries) == len(expected), "One registry entry per server" + for entry in entries: + assert entry["$schema"] == REGISTRY_SCHEMA and SEMVER.fullmatch(entry["version"]) + assert re.fullmatch(r"com\.voiceflow/[a-z0-9-]+", entry["name"]), "Registry names use com.voiceflow/" + assert 0 < len(entry["description"]) <= 100 and 0 < len(entry["title"]) <= 100 + assert [remote["type"] for remote in entry["remotes"]] == ["streamable-http"] + + def validate(root=ROOT): plugin = root / "voiceflow" manifests = [plugin / "plugin.json"] + [ @@ -70,7 +144,7 @@ def validate(root=ROOT): assert knowledge.startswith("---\n"), "Missing skill package metadata" record = dict(line.split(": ", 1) for line in knowledge.split("---", 2)[1].strip().splitlines()) assert record == {"package": data[0]["name"], "version": data[0]["version"]}, "Skill package version differs" - assert len(data[0]["extensions"]["com.openai"]["interface"]["shortDescription"]) <= 30 + validate_listings(root) portable = json.loads((plugin / "mcp.json").read_text(encoding="utf-8")) legacy = json.loads((plugin / ".mcp.json").read_text(encoding="utf-8")) assert portable["$schema"] == "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json" diff --git a/skills.sh.json b/skills.sh.json new file mode 100644 index 0000000..03dd511 --- /dev/null +++ b/skills.sh.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://skills.sh/schemas/skills.sh.schema.json", + "paths": ["./voiceflow/skills"] +} diff --git a/tests/test_repository.py b/tests/test_repository.py index a21602f..db71190 100644 --- a/tests/test_repository.py +++ b/tests/test_repository.py @@ -351,6 +351,55 @@ def test_docs_mcp_url_must_turn_off_logging(self): self.assertEqual(validator.docs_url_problems(root), [problem, problem]) +class ListingTests(unittest.TestCase): + def setUp(self): + scratch = tempfile.TemporaryDirectory() + self.addCleanup(scratch.cleanup) + self.root = Path(scratch.name) + for name in ("voiceflow", ".agents", "mcp-registry"): + shutil.copytree(ROOT / name, self.root / name, ignore=shutil.ignore_patterns("__pycache__")) + shutil.copyfile(ROOT / "skills.sh.json", self.root / "skills.sh.json") + + def test_current_listing_metadata_passes(self): + validator.validate_listings(self.root) + + def test_listing_drift_is_rejected(self): + def interface(data): + return data["extensions"]["com.openai"]["interface"] + + cases = [ + ("voiceflow/.codex-plugin/plugin.json", + lambda data: data["interface"].update(category="Development"), "Codex interface differs"), + ("voiceflow/.claude-plugin/plugin.json", + lambda data: data.update(privacyPolicyUrl="https://example.invalid/privacy"), "privacyPolicyUrl"), + ("voiceflow/plugin.json", + lambda data: interface(data)["defaultPrompt"].__setitem__(0, "x" * 129), "default prompt"), + ("voiceflow/plugin.json", + lambda data: interface(data).update(shortDescription="x" * 31), "shortDescription"), + ("voiceflow/.cursor-plugin/plugin.json", lambda data: data.pop("keywords"), "keywords"), + ("voiceflow/.claude-plugin/plugin.json", lambda data: data.update(icon="./icon.png"), "Icon file missing"), + ("mcp-registry/knowledge/server.json", + lambda data: data["remotes"][0].update(url=validator.DOCS_MCP_URL), "Registry URLs differ"), + ("skills.sh.json", lambda data: data.update(paths=["./skills"]), "skills.sh.json"), + ] + for name, change, message in cases: + with self.subTest(name=name, message=message): + path = self.root / name + original = path.read_bytes() + data = json.loads(original) + change(data) + path.write_text(json.dumps(data), encoding="utf-8") + with self.assertRaisesRegex(AssertionError, message): + validator.validate_listings(self.root) + path.write_bytes(original) + + def test_plugin_readme_counts_prose_words_only(self): + readme = self.root / "voiceflow/README.md" + readme.write_text("# Voiceflow\n\nShort intro.\n\n```text\n" + "word " * 60 + "\n```\n", encoding="utf-8") + with self.assertRaisesRegex(AssertionError, "40\\+ words"): + validator.validate_listings(self.root) + + class ReleaseTests(unittest.TestCase): def setUp(self): self.scratch = tempfile.TemporaryDirectory() diff --git a/tests/test_skill_references.py b/tests/test_skill_references.py index b7a00e0..abadecc 100644 --- a/tests/test_skill_references.py +++ b/tests/test_skill_references.py @@ -210,9 +210,9 @@ def test_validate_lists_every_problem_and_exits_nonzero(self): with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) / "repo" for folder in ("voiceflow", "scripts", "tests/fixtures", "docs", "evals", - ".claude-plugin", ".cursor-plugin", ".agents"): + ".claude-plugin", ".cursor-plugin", ".agents", "mcp-registry"): shutil.copytree(ROOT / folder, root / folder, ignore=shutil.ignore_patterns("__pycache__")) - for document in [*ROOT.glob("*.md"), ROOT / "LICENSE"]: + for document in [*ROOT.glob("*.md"), ROOT / "LICENSE", ROOT / "skills.sh.json"]: shutil.copyfile(document, root / document.name) skill = root / "voiceflow/skills/voiceflow-build/SKILL.md" lines = skill.read_text(encoding="utf-8").splitlines() diff --git a/voiceflow/.claude-plugin/plugin.json b/voiceflow/.claude-plugin/plugin.json index ff221c1..3db6819 100644 --- a/voiceflow/.claude-plugin/plugin.json +++ b/voiceflow/.claude-plugin/plugin.json @@ -1,9 +1,25 @@ { "name": "voiceflow", + "displayName": "Voiceflow", "version": "1.0.0", "description": "Connect to Voiceflow, then build and improve agents with shared product guidance.", "author": { "name": "Voiceflow, Inc." }, - "license": "MIT" + "homepage": "https://www.voiceflow.com/docs", + "repository": "https://github.com/voiceflow/agent-plugins", + "license": "MIT", + "keywords": [ + "voiceflow", + "agents", + "ai-agents", + "chatbots", + "voice", + "workflows", + "mcp" + ], + "documentationUrl": "https://www.voiceflow.com/docs", + "supportUrl": "https://github.com/voiceflow/agent-plugins/blob/main/SUPPORT.md", + "privacyPolicyUrl": "https://www.voiceflow.com/privacy", + "termsOfServiceUrl": "https://www.voiceflow.com/legal/terms" } diff --git a/voiceflow/.codex-plugin/plugin.json b/voiceflow/.codex-plugin/plugin.json index a1e1f56..721fba6 100644 --- a/voiceflow/.codex-plugin/plugin.json +++ b/voiceflow/.codex-plugin/plugin.json @@ -5,7 +5,43 @@ "author": { "name": "Voiceflow, Inc." }, + "homepage": "https://www.voiceflow.com/docs", + "repository": "https://github.com/voiceflow/agent-plugins", + "license": "MIT", + "keywords": [ + "voiceflow", + "agents", + "ai-agents", + "chatbots", + "voice", + "workflows", + "mcp" + ], "skills": "./skills/", "mcpServers": "./.mcp.json", - "license": "MIT" + "interface": { + "displayName": "Voiceflow", + "shortDescription": "Build with Voiceflow", + "longDescription": "Connect to Voiceflow, then build, debug, and improve agents using portable product skills. Setup connects your Voiceflow account through the Voiceflow CLI or the hosted Voiceflow MCP server, with browser sign-in, and adds the public Voiceflow docs server. Eighteen skills cover building agents, prompts and playbooks, workflows, functions, integrations, knowledge bases, messages, voice, phone numbers, the web chat widget, debugging, transcripts, evaluations, and environments. Changes to your account follow your requests and your assistant's approval prompts. You need a Voiceflow account, and your plan's limits apply.", + "developerName": "Voiceflow, Inc.", + "category": "Developer Tools", + "capabilities": [ + "Read", + "Write" + ], + "websiteURL": "https://www.voiceflow.com", + "supportURL": "https://github.com/voiceflow/agent-plugins/blob/main/SUPPORT.md", + "privacyPolicyURL": "https://www.voiceflow.com/privacy", + "termsOfServiceURL": "https://www.voiceflow.com/legal/terms", + "defaultPrompt": [ + "Connect me to Voiceflow and check that my account works.", + "Find out why my Voiceflow agent answers twice after a playbook.", + "Add the Voiceflow chat widget to my website." + ] + }, + "extensions": { + "com.openai": { + "onboardingSkill": "./skills/voiceflow-setup/SKILL.md" + } + } } diff --git a/voiceflow/.cursor-plugin/plugin.json b/voiceflow/.cursor-plugin/plugin.json index c3fa5b7..4a3f266 100644 --- a/voiceflow/.cursor-plugin/plugin.json +++ b/voiceflow/.cursor-plugin/plugin.json @@ -5,6 +5,17 @@ "author": { "name": "Voiceflow, Inc." }, - "skills": "./skills/", - "license": "MIT" + "homepage": "https://www.voiceflow.com/docs", + "repository": "https://github.com/voiceflow/agent-plugins", + "license": "MIT", + "keywords": [ + "voiceflow", + "agents", + "ai-agents", + "chatbots", + "voice", + "workflows", + "mcp" + ], + "skills": "./skills/" } diff --git a/voiceflow/README.md b/voiceflow/README.md new file mode 100644 index 0000000..82046c4 --- /dev/null +++ b/voiceflow/README.md @@ -0,0 +1,73 @@ +# Voiceflow + +This plugin connects your AI assistant to your Voiceflow account. It then helps +you build, test, debug, and improve Voiceflow agents. It works in Claude Code, +Codex, Cursor, and chat assistants that can connect remote MCP servers. + +## What it includes + +- Eighteen skills. They cover setup, agent building, prompts and playbooks, + workflows, functions, integrations, knowledge bases, messages, voice, phone + numbers, the web chat widget, debugging, transcripts, evaluations, and + environments. +- A connection to the public Voiceflow docs server. The assistant uses it to + look up current product guidance before it answers or changes anything. + +## Install + +In Claude Code 2.1.275 or later, run: + +```text +/plugin install voiceflow --marketplace voiceflow/agent-plugins +``` + +For Codex, Cursor, other Claude Code versions, and standalone skills, follow +the [client guide](skills/voiceflow-setup/references/clients.md). + +## How setup works + +Ask your assistant to connect you to Voiceflow. The `voiceflow-setup` skill +checks what your assistant can do, then takes one of two paths. + +- **An assistant with a terminal** uses the Voiceflow CLI. If the CLI is + missing, setup can download version 0.287.0 from the official release at + [github.com/voiceflow/cli](https://github.com/voiceflow/cli/releases). Before + it installs anything, it checks the download against SHA-256 checksums pinned + in this plugin. It never replaces a CLI that is already installed. You then + sign in through your browser. +- **An assistant with remote MCP** connects the hosted Voiceflow MCP server. + You sign in through your browser. + +Setup is done when one account read works and one docs question gets an answer. +Setup does not create a project or publish anything. After that, the assistant +asks what you want to build or improve. + +If you ask for a standalone install, a setup script copies the skills into your +assistant's skills folder. It records the files it manages and refuses to +overwrite files you have edited. + +## Data and services + +- **Voiceflow MCP server**, `https://mcp.voiceflow.com/mcp`. It uses OAuth and + asks for workspace read and write access. Setup only reads. Later changes + follow your requests and your assistant's approval prompts. +- **Voiceflow docs MCP**, `https://www.voiceflow.com/docs/mcp?logging=off`. This + plugin bundles it. It is public and needs no sign-in. Each docs request sends + your question and a short tag with the plugin version, the active skill, and + the stage: setup, troubleshooting, or usage. The bundled connection runs with + logging turned off. The skills tell the assistant to keep credentials, + customer data, and private code out of every question. +- **Voiceflow CLI**, downloaded as described above. It runs on your machine and + keeps its own sign-in. + +The plugin stores no credentials and sends no separate analytics. Your +assistant provider has its own data policies. + +## Links + +- License: [MIT](LICENSE), copyright Voiceflow, Inc. +- Support: [help and support](https://github.com/voiceflow/agent-plugins/blob/main/SUPPORT.md) +- Privacy: [Voiceflow Privacy Policy](https://www.voiceflow.com/privacy) +- Terms: [Voiceflow Terms of Service](https://www.voiceflow.com/legal/terms) +- Source: [voiceflow/agent-plugins](https://github.com/voiceflow/agent-plugins) +- Product docs: [Voiceflow documentation](https://www.voiceflow.com/docs) diff --git a/voiceflow/plugin.json b/voiceflow/plugin.json index b62b0f1..d899b6d 100644 --- a/voiceflow/plugin.json +++ b/voiceflow/plugin.json @@ -12,17 +12,34 @@ "keywords": [ "voiceflow", "agents", + "ai-agents", + "chatbots", + "voice", "workflows", - "voice" + "mcp" ], "extensions": { "com.openai": { + "onboardingSkill": "./skills/voiceflow-setup/SKILL.md", "interface": { "displayName": "Voiceflow", "shortDescription": "Build with Voiceflow", - "longDescription": "Connect to Voiceflow, then build, debug, and improve agents using portable product skills.", + "longDescription": "Connect to Voiceflow, then build, debug, and improve agents using portable product skills. Setup connects your Voiceflow account through the Voiceflow CLI or the hosted Voiceflow MCP server, with browser sign-in, and adds the public Voiceflow docs server. Eighteen skills cover building agents, prompts and playbooks, workflows, functions, integrations, knowledge bases, messages, voice, phone numbers, the web chat widget, debugging, transcripts, evaluations, and environments. Changes to your account follow your requests and your assistant's approval prompts. You need a Voiceflow account, and your plan's limits apply.", "developerName": "Voiceflow, Inc.", - "category": "Development" + "category": "Developer Tools", + "capabilities": [ + "Read", + "Write" + ], + "websiteURL": "https://www.voiceflow.com", + "supportURL": "https://github.com/voiceflow/agent-plugins/blob/main/SUPPORT.md", + "privacyPolicyURL": "https://www.voiceflow.com/privacy", + "termsOfServiceURL": "https://www.voiceflow.com/legal/terms", + "defaultPrompt": [ + "Connect me to Voiceflow and check that my account works.", + "Find out why my Voiceflow agent answers twice after a playbook.", + "Add the Voiceflow chat widget to my website." + ] } } }