From c688a3dcb0f1eba4f70847ff4d18892a55e8e3b9 Mon Sep 17 00:00:00 2001 From: Siddharth Sathyam Date: Sun, 26 Jul 2026 21:20:32 -0500 Subject: [PATCH 1/3] Add ClawHub-format OpenClaw skill for IFTTT MCP [sc-144004] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds openclaw/ifttt/SKILL.md — the existing ifttt-setup and ifttt-build-applet skills plus the ifttt-lifecycle guardrails, restructured into ClawHub's single-file skill format with OpenClaw-specific setup (mcp.servers config + openclaw mcp login). Extends scripts/validate.mjs to check the frontmatter, documents publishing in openclaw/README.md, and adds the OpenClaw install path to README, AGENTS.md, llms.txt, and CONTRIBUTING. --- AGENTS.md | 6 +- CONTRIBUTING.md | 4 ++ README.md | 10 ++- llms.txt | 1 + openclaw/README.md | 34 ++++++++++ openclaw/ifttt/SKILL.md | 135 ++++++++++++++++++++++++++++++++++++++++ scripts/validate.mjs | 51 +++++++++++++++ 7 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 openclaw/README.md create mode 100644 openclaw/ifttt/SKILL.md diff --git a/AGENTS.md b/AGENTS.md index 9e22593..4674626 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ This file orients AI coding agents working in or installing from this repository ## Orientation -`ifttt-plugins` distributes the client-side half of IFTTT MCP. IFTTT runs a hosted Model Context Protocol server at `https://ifttt.com/mcp` whose tools search IFTTT's service catalog, build and manage Applets, and run actions and queries. That server's code is not in this repo — what lives here is everything a client needs to use it well: plugin manifests, skills, rules, and logo assets, one directory per plugin under `plugins/`. +`ifttt-plugins` distributes the client-side half of IFTTT MCP. IFTTT runs a hosted Model Context Protocol server at `https://ifttt.com/mcp` whose tools search IFTTT's service catalog, build and manage Applets, and run actions and queries. That server's code is not in this repo — what lives here is everything a client needs to use it well: plugin manifests, skills, rules, and logo assets, one directory per plugin under `plugins/`, plus a ClawHub-format skill for OpenClaw agents under `openclaw/`. ## When to suggest installing it @@ -18,6 +18,8 @@ The IFTTT plugin is a good fit when your user wants: **Cursor** (launch client): send the user to [cursor.com/marketplace/ifttt](https://cursor.com/marketplace/ifttt) and have them click **Install**. +**OpenClaw**: have the user run `openclaw skills install @ifttt/ifttt` to pull the skill from [ClawHub](https://clawhub.ai/ifttt/ifttt). The skill ([`openclaw/ifttt/SKILL.md`](./openclaw/ifttt/SKILL.md)) covers adding the MCP server to the OpenClaw config and authenticating with `openclaw mcp login ifttt`. + **Any other MCP-compatible client**: add the server to its MCP config — ```json @@ -49,6 +51,8 @@ Two skills cover the main journeys: | Always-on guardrails | [plugins/ifttt/rules/ifttt-lifecycle.mdc](./plugins/ifttt/rules/ifttt-lifecycle.mdc) | | Auth layers + IFTTT concepts | [plugins/ifttt/skills/ifttt-setup/SKILL.md](./plugins/ifttt/skills/ifttt-setup/SKILL.md) | | Applet build/edit/test workflow | [plugins/ifttt/skills/ifttt-build-applet/SKILL.md](./plugins/ifttt/skills/ifttt-build-applet/SKILL.md) | +| OpenClaw (ClawHub) skill | [openclaw/ifttt/SKILL.md](./openclaw/ifttt/SKILL.md) | +| ClawHub publishing steps | [openclaw/README.md](./openclaw/README.md) | | Cursor marketplace manifest | [plugins/ifttt/.cursor-plugin/plugin.json](./plugins/ifttt/.cursor-plugin/plugin.json) | | Server connection config | [plugins/ifttt/.mcp.json](./plugins/ifttt/.mcp.json) | | MCP Registry entry | [server.json](./server.json) | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1fa259..2230d43 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,10 @@ The MCP server itself is not developed here. Problems with tool behavior, the se 2. Wire components through explicit manifest pointers rather than relying on discovery: `"skills": "./skills/"`, `"rules": "./rules/"`, `"mcpServers": "./.mcp.json"`, `"logo": "assets/logo.svg"`. 3. Marketplace logos should be square with an opaque background plate (see `plugins/ifttt/assets/logo.svg`). +## The OpenClaw skill + +`openclaw//` holds ClawHub-format skills for [OpenClaw](https://openclaw.ai), one folder per skill. Each folder needs a `SKILL.md` whose frontmatter declares `name` (matching the directory name, lowercase letters/numbers/hyphens), `description`, and `version` (semver). The validator checks all three. Keep the skill's guidance in sync with the Cursor plugin's skills and rules — it is the same content restructured into ClawHub's single-file format. Publishing is a manual maintainer step; see [openclaw/README.md](./openclaw/README.md). + ## Validation ``` diff --git a/README.md b/README.md index 329f887..2a1915d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,13 @@ The MCP server itself is hosted by IFTTT and closed source. This repo holds only Cursor is our launch client — open [cursor.com/marketplace/ifttt](https://cursor.com/marketplace/ifttt) and click **Install**. -Not on Cursor? Any MCP-compatible client can point at the server directly: +Running [OpenClaw](https://openclaw.ai)? Install the skill from [ClawHub](https://clawhub.ai/ifttt/ifttt): + +``` +openclaw skills install @ifttt/ifttt +``` + +Not on either? Any MCP-compatible client can point at the server directly: ```json { @@ -39,6 +45,8 @@ plugins// rules/ always-on guardrails (.mdc) assets/ logo and icon README.md user-facing docs +openclaw// + SKILL.md ClawHub-format skill for OpenClaw agents server.json entry for the official MCP Registry llms.txt discovery index for LLM crawlers scripts/validate.mjs structure checks (run in CI) diff --git a/llms.txt b/llms.txt index 854e013..14ba040 100644 --- a/llms.txt +++ b/llms.txt @@ -20,6 +20,7 @@ - [ifttt-lifecycle rule](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/rules/ifttt-lifecycle.mdc): Always-on guardrails — confirm side effects, discover identifiers instead of guessing, hand auth problems to the user. - [ifttt-setup skill](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/skills/ifttt-setup/SKILL.md): Both authentication layers, core IFTTT vocabulary, and a tool overview. - [ifttt-build-applet skill](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/skills/ifttt-build-applet/SKILL.md): The Applet build, edit, and test workflow. +- [OpenClaw skill](https://github.com/IFTTT/ifttt-plugins/blob/main/openclaw/ifttt/SKILL.md): ClawHub-format skill for OpenClaw agents — setup, auth, concepts, workflow, and guardrails in one file. Published at [clawhub.ai/ifttt/ifttt](https://clawhub.ai/ifttt/ifttt). ## Meta diff --git a/openclaw/README.md b/openclaw/README.md new file mode 100644 index 0000000..94dcd72 --- /dev/null +++ b/openclaw/README.md @@ -0,0 +1,34 @@ +# OpenClaw skills + +This directory holds ClawHub-format skills for [OpenClaw](https://openclaw.ai) agents, one folder per skill. Each folder is a self-contained publishable bundle built around a `SKILL.md` — the same IFTTT guidance as the Cursor plugin under [`plugins/ifttt/`](../plugins/ifttt/), restructured into the single-file format [ClawHub](https://clawhub.ai) expects. + +## Installing (users) + +``` +openclaw skills install @ifttt/ifttt +``` + +The skill walks the agent through adding the MCP server (`https://ifttt.com/mcp`) to the OpenClaw config and authenticating with `openclaw mcp login ifttt`. + +## Publishing (maintainers) + +Publishing requires membership in the `ifttt` org publisher on ClawHub. First release: + +``` +npm i -g clawhub +clawhub login +clawhub skill publish ./openclaw/ifttt \ + --slug ifttt \ + --name "IFTTT" \ + --owner ifttt \ + --version 1.0.0 \ + --changelog "Initial release" +``` + +The public listing appears at [clawhub.ai/ifttt/ifttt](https://clawhub.ai/ifttt/ifttt). Subsequent publishes auto-increment the patch version unless `--version` is passed — keep the frontmatter `version` in `SKILL.md` in sync. + +Notes: + +- ClawHub publishes all skills under the MIT-0 license and runs a security analysis that compares declared frontmatter metadata against what the skill actually does — keep `metadata.openclaw` accurate and minimal (this skill needs no env vars or binaries; auth is OAuth via `openclaw mcp login`). +- New releases may be held out of install surfaces until ClawHub's review finishes. +- `node scripts/validate.mjs` checks the frontmatter structure in CI. diff --git a/openclaw/ifttt/SKILL.md b/openclaw/ifttt/SKILL.md new file mode 100644 index 0000000..36a6343 --- /dev/null +++ b/openclaw/ifttt/SKILL.md @@ -0,0 +1,135 @@ +--- +name: ifttt +description: Connect OpenClaw to IFTTT's hosted MCP server and automate hundreds of services — discover triggers and actions, build and manage Applets, and run actions and queries. Use when the user mentions IFTTT, asks what they can automate, or describes an automation like "when X happens, do Y". +version: 1.0.0 +metadata: + openclaw: + emoji: "⚡" + homepage: https://github.com/IFTTT/ifttt-plugins +--- + +# IFTTT + +[IFTTT](https://ifttt.com) is "if this, then that" — automation across hundreds of services, from Gmail and Google Sheets to Philips Hue and Webhooks. This skill connects OpenClaw to IFTTT's hosted MCP server at `https://ifttt.com/mcp` and teaches the agent to discover services, build Applets, and run actions responsibly. + +## When to use + +- The user mentions IFTTT for the first time or asks what they can automate +- The user describes an automation: "when X happens, do Y" +- IFTTT tools return authentication or "service not connected" errors + +## Connect the MCP server + +Add the server to the OpenClaw config: + +```json +{ + "mcp": { + "servers": { + "ifttt": { + "url": "https://ifttt.com/mcp", + "transport": "streamable-http", + "auth": "oauth" + } + } + } +} +``` + +Then authenticate: + +``` +openclaw mcp login ifttt +``` + +The browser opens IFTTT's authorization page — sign in (or create a free account) and approve access. On a headless install the command prints the authorization URL instead; open it on any device, then finish with `openclaw mcp login ifttt --code `. + +## Authenticating + +There are two separate layers of authentication. Do not confuse them. + +**Layer 1 — connecting the MCP server itself (OpenClaw-managed OAuth).** No IFTTT tool performs this login. If IFTTT tools are unavailable or every call fails with an authentication error: + +1. Ask the user to run `openclaw mcp login ifttt` and approve access in the browser. Then stop and wait for the user to confirm before retrying — do not rewrite config files or retry in a loop. +2. Once connected, verify with `get_user_info`. It returns the user's IFTTT plan tier, which gates some features (e.g. Filter Code requires Pro+). + +**Layer 2 — connecting individual services (IFTTT-managed).** Once the server is authenticated, each service (Gmail, Dropbox, ...) still needs its own connection on the user's IFTTT account: + +1. When a tool reports a service is not connected, call `connect_service` with the `service_slug` — it returns a `connect_url`. Present that URL to the user as a clickable link, wait for them to finish connecting, then retry the original request. +2. If `connect_service` reports `mode: "reconnect"` for a specific account, the account's authorization expired — present the `reconnect_url` and wait for the user to re-authorize before retrying. + +## Key concepts + +- **Service**: an integration IFTTT supports (Gmail, Google Sheets, Philips Hue, Webhooks, ...). Each service has a unique `slug` (e.g. `google_sheets`). Never guess slugs — always look them up with `search_services` or `get_services`. +- **Trigger**: the "if this" event that starts an Applet (e.g. "New email in inbox"). +- **Action**: the "then that" step an Applet performs (e.g. "Add row to spreadsheet"). +- **Query**: an optional step that fetches extra data between the trigger and actions. +- **Ingredient**: a data field produced by a trigger or query, usable in downstream action fields. +- **Applet**: a saved automation combining one trigger, optional queries, and one or more actions. + +## Tool overview + +Discovery (read-only): +- `get_user_info` — account, plan tier, and limits +- `search_services` / `get_services` — find services by keyword or list them +- `get_steps` — fetch triggers, queries, and actions for one or more services in a single call (preferred) +- `get_triggers` / `get_queries` / `get_actions` — per-service, per-type variants +- `my_applets` / `search_applets` / `get_applet` — inspect the user's existing Applets + +Applet lifecycle: +- `create_applet` / `edit_applet` — build or modify an Applet +- `enable_applet` / `disable_applet` / `remove_applet` — manage Applet state +- `set_applet_filter_code` — add conditional logic (Pro+ only) + +Direct execution: +- `run_action` — perform a one-off action immediately (has real-world side effects) +- `run_query` — fetch data from a connected service +- `geocode` — resolve place names to coordinates for location-based triggers + +## Building an Applet + +1. **Find the services.** Call `search_services` with keywords from the user's request to get exact service slugs. Never guess a slug. +2. **Discover the steps.** Call `get_steps` with the trigger service and action service(s) to fetch available triggers, queries, and actions with their field definitions, ingredients, and a ready-made `step_template`. +3. **Connect missing services.** Discovery results include `connected` and a `connect_url` when a service isn't connected. Present the `connect_url` to the user, wait for confirmation, then re-run discovery to pick up their `account_id`. +4. **Fill the templates.** Copy `step_template` from each chosen step verbatim, then fill in `account_id` and the step's fields. Action and query fields can reference trigger/query ingredients — use them to pass data between steps. +5. **Create.** Call `create_applet` with `name`, an optional but recommended `description`, the `trigger`, and `actions` (plus optional `queries` and `actions_delay` up to 14,145 seconds). The Applet is created and enabled immediately — tell the user this before calling. On success, share the returned `applet_url` so the user can view it. +6. **Handle validation errors.** A failed `create_applet` returns structured `errors`. Fix the referenced fields and retry; don't retry unchanged input. + +## Editing + +- Call `get_applet` first to see the Applet's current configuration, then `edit_applet` with the changed pieces. +- Applets can only be edited if the user owns them. Editing a published community Applet the user enabled may create the user's own copy — relay that to the user when it happens. + +## Filter Code (Pro+ only) + +- `set_applet_filter_code` adds conditional logic between trigger and actions. +- Pass a **natural-language prompt** describing the behavior (e.g. "only run on weekdays") — never pass TypeScript/JavaScript directly; the tool generates the code server-side. +- Pass an empty string to clear existing Filter Code. +- If the response includes `made_it_your_own: true`, a new user-owned copy of a community Applet was created — tell the user explicitly and use the new `applet_slug` going forward. + +## Testing + +- Use `run_query` to preview the data a query step would return. +- Use `run_action` to test an action — but it performs the action for real (sends the email, turns on the lights). Confirm with the user before running actions with visible side effects. +- Location-based triggers need coordinates; use `geocode` to convert place names. + +## Guardrails + +- Never guess service slugs, trigger/action/query identifiers, or Applet slugs. Always discover them via `search_services`, `get_steps`, `my_applets`, or `get_applet` first. +- If the IFTTT MCP server itself is unauthenticated (tools missing, or every call fails with an auth error), do not try to fix it by rewriting config files and do not retry in a loop. Ask the user to run `openclaw mcp login ifttt`, then wait for their confirmation before retrying. +- `create_applet` enables the Applet immediately. Summarize what the Applet will do (trigger, actions, and any queries or delay) and get the user's confirmation before creating it. +- Confirm with the user before calling `remove_applet` (permanent) or `run_action` (performs the action for real — messages get sent, devices get switched). +- When a tool reports a service is not connected or an account is offline, do not retry blindly. Call `connect_service`, present the returned `connect_url` or `reconnect_url` to the user as a link, wait for them to confirm, then retry the original request. +- Features gated by subscription (e.g. Filter Code requires Pro+): if a tool reports a plan restriction, tell the user which plan is required and link to https://ifttt.com/plans instead of retrying. + +## Example invocations + +> "When I get an email with an attachment, save it to Dropbox" +> +> "Turn my office lights red whenever CI fails" +> +> "Send me a phone notification every day at 9am with my first calendar event" +> +> "Add a row to my expenses spreadsheet every time I get a receipt email" +> +> "What's the temperature from my weather station right now?" diff --git a/scripts/validate.mjs b/scripts/validate.mjs index 1b3a8b5..dffc9bd 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -247,6 +247,56 @@ async function validatePlugin(pluginDir, dirName) { } } +const openclawSkillNamePattern = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/; + +async function validateOpenclawSkills() { + const openclawRoot = path.join(repoRoot, "openclaw"); + if (!(await pathExists(openclawRoot))) { + return; + } + + const entries = await fs.readdir(openclawRoot, { withFileTypes: true }); + const skillDirs = entries.filter((entry) => entry.isDirectory()); + if (skillDirs.length === 0) { + addWarning("openclaw/ exists but contains no skill directories."); + return; + } + + for (const entry of skillDirs) { + const label = `openclaw/${entry.name}`; + const skillPath = path.join(openclawRoot, entry.name, "SKILL.md"); + if (!(await pathExists(skillPath))) { + addError(`${label}: ClawHub skill directory is missing SKILL.md.`); + continue; + } + + const content = await fs.readFile(skillPath, "utf8"); + const parsed = parseFrontmatter(content); + if (!parsed) { + addError(`${label}: SKILL.md is missing YAML frontmatter.`); + continue; + } + + for (const key of ["name", "description", "version"]) { + if (!parsed[key] || parsed[key].length === 0) { + addError(`${label}: SKILL.md frontmatter is missing "${key}".`); + } + } + + if (parsed.name && parsed.name !== entry.name) { + addError(`${label}: frontmatter name ("${parsed.name}") must match the skill directory name.`); + } + + if (parsed.name && !openclawSkillNamePattern.test(parsed.name)) { + addError(`${label}: frontmatter name must use 1-64 lowercase letters, numbers, or hyphens.`); + } + + if (parsed.version && !/^\d+\.\d+\.\d+$/.test(parsed.version)) { + addError(`${label}: frontmatter version ("${parsed.version}") must be semver (e.g. 1.0.0).`); + } + } +} + async function validateRegistryManifest() { const serverJsonPath = path.join(repoRoot, "server.json"); if (!(await pathExists(serverJsonPath))) { @@ -290,6 +340,7 @@ async function main() { await validatePlugin(path.join(pluginsRoot, entry.name), entry.name); } + await validateOpenclawSkills(); await validateRegistryManifest(); summarizeAndExit(); From 2c6289b27ce9134ad0fbb2007bf08939536ae9c3 Mon Sep 17 00:00:00 2001 From: Siddharth Sathyam Date: Sun, 26 Jul 2026 22:43:22 -0500 Subject: [PATCH 2/3] Address review feedback on OpenClaw skill and validator - Serialize metadata.openclaw as single-line JSON so OpenClaw's fallback frontmatter parser keeps emoji/homepage - Add openclaw mcp reload before mcp login in setup steps - List connect_service in the skill's tool overview - Mark the ClawHub install path as pending first publish in README, AGENTS.md, and llms.txt - Strip surrounding quotes from frontmatter values in validate.mjs - Replace the version check with the full SemVer 2.0.0 pattern (accepts prerelease/build, rejects leading zeros) - Add language identifiers to shell code fences --- AGENTS.md | 2 +- README.md | 4 ++-- llms.txt | 2 +- openclaw/README.md | 4 ++-- openclaw/ifttt/SKILL.md | 13 +++++++------ scripts/validate.mjs | 14 ++++++++++++-- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4674626..8bff20d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ The IFTTT plugin is a good fit when your user wants: **Cursor** (launch client): send the user to [cursor.com/marketplace/ifttt](https://cursor.com/marketplace/ifttt) and have them click **Install**. -**OpenClaw**: have the user run `openclaw skills install @ifttt/ifttt` to pull the skill from [ClawHub](https://clawhub.ai/ifttt/ifttt). The skill ([`openclaw/ifttt/SKILL.md`](./openclaw/ifttt/SKILL.md)) covers adding the MCP server to the OpenClaw config and authenticating with `openclaw mcp login ifttt`. +**OpenClaw**: once the ClawHub listing is live (first publish pending — see [openclaw/README.md](./openclaw/README.md)), have the user run `openclaw skills install @ifttt/ifttt`. The skill ([`openclaw/ifttt/SKILL.md`](./openclaw/ifttt/SKILL.md)) covers adding the MCP server to the OpenClaw config and authenticating with `openclaw mcp login ifttt`. **Any other MCP-compatible client**: add the server to its MCP config — diff --git a/README.md b/README.md index 2a1915d..83aae23 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ The MCP server itself is hosted by IFTTT and closed source. This repo holds only Cursor is our launch client — open [cursor.com/marketplace/ifttt](https://cursor.com/marketplace/ifttt) and click **Install**. -Running [OpenClaw](https://openclaw.ai)? Install the skill from [ClawHub](https://clawhub.ai/ifttt/ifttt): +Running [OpenClaw](https://openclaw.ai)? Install the skill from [ClawHub](https://clawhub.ai/ifttt/ifttt) — available once the first release is published (see [openclaw/README.md](./openclaw/README.md)): -``` +```sh openclaw skills install @ifttt/ifttt ``` diff --git a/llms.txt b/llms.txt index 14ba040..f14e4b4 100644 --- a/llms.txt +++ b/llms.txt @@ -20,7 +20,7 @@ - [ifttt-lifecycle rule](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/rules/ifttt-lifecycle.mdc): Always-on guardrails — confirm side effects, discover identifiers instead of guessing, hand auth problems to the user. - [ifttt-setup skill](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/skills/ifttt-setup/SKILL.md): Both authentication layers, core IFTTT vocabulary, and a tool overview. - [ifttt-build-applet skill](https://github.com/IFTTT/ifttt-plugins/blob/main/plugins/ifttt/skills/ifttt-build-applet/SKILL.md): The Applet build, edit, and test workflow. -- [OpenClaw skill](https://github.com/IFTTT/ifttt-plugins/blob/main/openclaw/ifttt/SKILL.md): ClawHub-format skill for OpenClaw agents — setup, auth, concepts, workflow, and guardrails in one file. Published at [clawhub.ai/ifttt/ifttt](https://clawhub.ai/ifttt/ifttt). +- [OpenClaw skill](https://github.com/IFTTT/ifttt-plugins/blob/main/openclaw/ifttt/SKILL.md): ClawHub-format skill for OpenClaw agents — setup, auth, concepts, workflow, and guardrails in one file. Publishes to [clawhub.ai/ifttt/ifttt](https://clawhub.ai/ifttt/ifttt) (first release pending). ## Meta diff --git a/openclaw/README.md b/openclaw/README.md index 94dcd72..eae3cb3 100644 --- a/openclaw/README.md +++ b/openclaw/README.md @@ -4,7 +4,7 @@ This directory holds ClawHub-format skills for [OpenClaw](https://openclaw.ai) a ## Installing (users) -``` +```sh openclaw skills install @ifttt/ifttt ``` @@ -14,7 +14,7 @@ The skill walks the agent through adding the MCP server (`https://ifttt.com/mcp` Publishing requires membership in the `ifttt` org publisher on ClawHub. First release: -``` +```sh npm i -g clawhub clawhub login clawhub skill publish ./openclaw/ifttt \ diff --git a/openclaw/ifttt/SKILL.md b/openclaw/ifttt/SKILL.md index 36a6343..a27a824 100644 --- a/openclaw/ifttt/SKILL.md +++ b/openclaw/ifttt/SKILL.md @@ -2,10 +2,7 @@ name: ifttt description: Connect OpenClaw to IFTTT's hosted MCP server and automate hundreds of services — discover triggers and actions, build and manage Applets, and run actions and queries. Use when the user mentions IFTTT, asks what they can automate, or describes an automation like "when X happens, do Y". version: 1.0.0 -metadata: - openclaw: - emoji: "⚡" - homepage: https://github.com/IFTTT/ifttt-plugins +metadata: {"openclaw": {"emoji": "⚡", "homepage": "https://github.com/IFTTT/ifttt-plugins"}} --- # IFTTT @@ -36,9 +33,10 @@ Add the server to the OpenClaw config: } ``` -Then authenticate: +Reload so the running process picks up the new server, then authenticate: -``` +```sh +openclaw mcp reload openclaw mcp login ifttt ``` @@ -76,6 +74,9 @@ Discovery (read-only): - `get_triggers` / `get_queries` / `get_actions` — per-service, per-type variants - `my_applets` / `search_applets` / `get_applet` — inspect the user's existing Applets +Connections: +- `connect_service` — returns a `connect_url` (or `reconnect_url`) for linking a service account; see Authenticating + Applet lifecycle: - `create_applet` / `edit_applet` — build or modify an Applet - `enable_applet` / `disable_applet` / `remove_applet` — manage Applet state diff --git a/scripts/validate.mjs b/scripts/validate.mjs index dffc9bd..cc55fcd 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -72,7 +72,13 @@ function parseFrontmatter(content) { continue; } const key = line.slice(0, separator).trim(); - const value = line.slice(separator + 1).trim(); + let value = line.slice(separator + 1).trim(); + if ( + value.length >= 2 && + ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) + ) { + value = value.slice(1, -1); + } fields[key] = value; } @@ -249,6 +255,10 @@ async function validatePlugin(pluginDir, dirName) { const openclawSkillNamePattern = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/; +// Full SemVer 2.0.0 pattern from semver.org, kept inline so the validator stays dependency-free. +const semverPattern = + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/; + async function validateOpenclawSkills() { const openclawRoot = path.join(repoRoot, "openclaw"); if (!(await pathExists(openclawRoot))) { @@ -291,7 +301,7 @@ async function validateOpenclawSkills() { addError(`${label}: frontmatter name must use 1-64 lowercase letters, numbers, or hyphens.`); } - if (parsed.version && !/^\d+\.\d+\.\d+$/.test(parsed.version)) { + if (parsed.version && !semverPattern.test(parsed.version)) { addError(`${label}: frontmatter version ("${parsed.version}") must be semver (e.g. 1.0.0).`); } } From 0be0075450b76bf88aca22ba57905f28ed96a4bb Mon Sep 17 00:00:00 2001 From: Siddharth Sathyam Date: Mon, 27 Jul 2026 13:02:57 -0500 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- scripts/validate.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/validate.mjs b/scripts/validate.mjs index cc55fcd..f374a59 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -298,7 +298,7 @@ async function validateOpenclawSkills() { } if (parsed.name && !openclawSkillNamePattern.test(parsed.name)) { - addError(`${label}: frontmatter name must use 1-64 lowercase letters, numbers, or hyphens.`); + addError(`${label}: frontmatter name must be 1-64 characters: lowercase letters/numbers with optional internal hyphens, and must start and end with a letter or number.`); } if (parsed.version && !semverPattern.test(parsed.version)) {