diff --git a/README.md b/README.md index 0a62afe..25a7af1 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ If you receive the email, Claude is now connected to 500+ apps. - [Productivity & Organization](#productivity--organization) - [Collaboration & Project Management](#collaboration--project-management) - [Security & Systems](#security--systems) + - [App Automation via Composio](#app-automation-via-composio) - [Getting Started](#getting-started) - [Creating Skills](#creating-skills) - [Contributing](#contributing) @@ -194,6 +195,122 @@ Claude Skills are customizable workflows that teach Claude how to perform specif - [metadata-extraction](https://github.com/mhattingpete/claude-skills-marketplace/tree/main/computer-forensics-skills/skills/metadata-extraction) - Extract and analyze file metadata for forensic purposes. - [threat-hunting-with-sigma-rules](https://github.com/jthack/threat-hunting-with-sigma-rules-skill) - Use Sigma detection rules to hunt for threats and analyze security events. +### App Automation via Composio + +Pre-built workflow skills for 78 SaaS apps via [Rube MCP (Composio)](https://composio.dev). Each skill includes tool sequences, parameter guidance, known pitfalls, and quick reference tables — all using real tool slugs discovered from Composio's API. + +**CRM & Sales** +- [Close Automation](./close-automation/) - Automate Close CRM: leads, contacts, opportunities, activities, and pipelines. +- [HubSpot Automation](./hubspot-automation/) - Automate HubSpot CRM: contacts, deals, companies, tickets, and email engagement. +- [Pipedrive Automation](./pipedrive-automation/) - Automate Pipedrive: deals, contacts, organizations, activities, and pipelines. +- [Salesforce Automation](./salesforce-automation/) - Automate Salesforce: objects, records, SOQL queries, and bulk operations. +- [Zoho CRM Automation](./zoho-crm-automation/) - Automate Zoho CRM: leads, contacts, deals, accounts, and modules. + +**Project Management** +- [Asana Automation](./asana-automation/) - Automate Asana: tasks, projects, sections, assignments, and workspaces. +- [Basecamp Automation](./basecamp-automation/) - Automate Basecamp: to-do lists, messages, people, groups, and projects. +- [ClickUp Automation](./clickup-automation/) - Automate ClickUp: tasks, lists, spaces, goals, and time tracking. +- [Jira Automation](./jira-automation/) - Automate Jira: issues, projects, boards, sprints, and JQL queries. +- [Linear Automation](./linear-automation/) - Automate Linear: issues, projects, cycles, teams, and workflows. +- [Monday Automation](./monday-automation/) - Automate Monday.com: boards, items, columns, groups, and workspaces. +- [Notion Automation](./notion-automation/) - Automate Notion: pages, databases, blocks, comments, and search. +- [Todoist Automation](./todoist-automation/) - Automate Todoist: tasks, projects, sections, labels, and filters. +- [Trello Automation](./trello-automation/) - Automate Trello: boards, cards, lists, members, and checklists. +- [Wrike Automation](./wrike-automation/) - Automate Wrike: tasks, folders, projects, comments, and workflows. + +**Communication** +- [Discord Automation](./discord-automation/) - Automate Discord: messages, channels, servers, roles, and reactions. +- [Intercom Automation](./intercom-automation/) - Automate Intercom: conversations, contacts, companies, tickets, and articles. +- [Microsoft Teams Automation](./microsoft-teams-automation/) - Automate Teams: messages, channels, teams, chats, and meetings. +- [Slack Automation](./slack-automation/) - Automate Slack: messages, channels, search, reactions, threads, and scheduling. +- [Telegram Automation](./telegram-automation/) - Automate Telegram: messages, chats, media, groups, and bots. +- [WhatsApp Automation](./whatsapp-automation/) - Automate WhatsApp: messages, media, templates, groups, and business profiles. + +**Email** +- [Gmail Automation](./gmail-automation/) - Automate Gmail: send/reply, search, labels, drafts, and attachments. +- [Outlook Automation](./outlook-automation/) - Automate Outlook: emails, folders, contacts, and calendar integration. +- [Postmark Automation](./postmark-automation/) - Automate Postmark: transactional emails, templates, servers, and delivery stats. +- [SendGrid Automation](./sendgrid-automation/) - Automate SendGrid: emails, templates, contacts, lists, and campaign stats. + +**Code & DevOps** +- [Bitbucket Automation](./bitbucket-automation/) - Automate Bitbucket: repos, PRs, branches, issues, and workspaces. +- [CircleCI Automation](./circleci-automation/) - Automate CircleCI: pipelines, workflows, jobs, and project configuration. +- [Datadog Automation](./datadog-automation/) - Automate Datadog: monitors, dashboards, metrics, incidents, and alerts. +- [GitHub Automation](./github-automation/) - Automate GitHub: issues, PRs, repos, branches, actions, and code search. +- [GitLab Automation](./gitlab-automation/) - Automate GitLab: issues, MRs, projects, pipelines, and branches. +- [PagerDuty Automation](./pagerduty-automation/) - Automate PagerDuty: incidents, services, schedules, escalation policies, and on-call. +- [Render Automation](./render-automation/) - Automate Render: services, deploys, and project management. +- [Sentry Automation](./sentry-automation/) - Automate Sentry: issues, events, projects, releases, and alerts. +- [Supabase Automation](./supabase-automation/) - Automate Supabase: SQL queries, table schemas, edge functions, and storage. +- [Vercel Automation](./vercel-automation/) - Automate Vercel: deployments, projects, domains, environment variables, and logs. + +**Storage & Files** +- [Box Automation](./box-automation/) - Automate Box: files, folders, search, sharing, collaborations, and sign requests. +- [Dropbox Automation](./dropbox-automation/) - Automate Dropbox: files, folders, search, sharing, and batch operations. +- [Google Drive Automation](./google-drive-automation/) - Automate Google Drive: upload, download, search, share, and organize files. +- [OneDrive Automation](./one-drive-automation/) - Automate OneDrive: files, folders, search, sharing, permissions, and versioning. + +**Spreadsheets & Databases** +- [Airtable Automation](./airtable-automation/) - Automate Airtable: records, tables, bases, views, and field management. +- [Coda Automation](./coda-automation/) - Automate Coda: docs, tables, rows, formulas, and automations. +- [Google Sheets Automation](./googlesheets-automation/) - Automate Google Sheets: read/write cells, formatting, formulas, and batch operations. + +**Calendar & Scheduling** +- [Cal.com Automation](./cal-com-automation/) - Automate Cal.com: event types, bookings, availability, and scheduling. +- [Calendly Automation](./calendly-automation/) - Automate Calendly: events, invitees, event types, scheduling links, and availability. +- [Google Calendar Automation](./google-calendar-automation/) - Automate Google Calendar: events, attendees, free/busy, and recurring schedules. +- [Outlook Calendar Automation](./outlook-calendar-automation/) - Automate Outlook Calendar: events, attendees, reminders, and recurring schedules. + +**Social Media** +- [Instagram Automation](./instagram-automation/) - Automate Instagram: posts, stories, comments, media, and business insights. +- [LinkedIn Automation](./linkedin-automation/) - Automate LinkedIn: posts, profiles, companies, images, and comments. +- [Reddit Automation](./reddit-automation/) - Automate Reddit: posts, comments, subreddits, voting, and moderation. +- [TikTok Automation](./tiktok-automation/) - Automate TikTok: video uploads, queries, and creator management. +- [Twitter Automation](./twitter-automation/) - Automate Twitter/X: tweets, search, users, lists, and engagement. +- [YouTube Automation](./youtube-automation/) - Automate YouTube: videos, channels, playlists, comments, and subscriptions. + +**Marketing & Email Marketing** +- [ActiveCampaign Automation](./activecampaign-automation/) - Automate ActiveCampaign: contacts, deals, campaigns, lists, and automations. +- [Brevo Automation](./brevo-automation/) - Automate Brevo: contacts, email campaigns, transactional emails, and lists. +- [ConvertKit Automation](./convertkit-automation/) - Automate ConvertKit (Kit): subscribers, tags, sequences, broadcasts, and forms. +- [Klaviyo Automation](./klaviyo-automation/) - Automate Klaviyo: profiles, lists, segments, campaigns, and events. +- [Mailchimp Automation](./mailchimp-automation/) - Automate Mailchimp: audiences, campaigns, templates, segments, and reports. + +**Support & Helpdesk** +- [Freshdesk Automation](./freshdesk-automation/) - Automate Freshdesk: tickets, contacts, agents, groups, and canned responses. +- [Freshservice Automation](./freshservice-automation/) - Automate Freshservice: tickets, assets, changes, problems, and service catalog. +- [Help Scout Automation](./helpdesk-automation/) - Automate Help Scout: conversations, customers, mailboxes, and tags. +- [Zendesk Automation](./zendesk-automation/) - Automate Zendesk: tickets, users, organizations, search, and macros. + +**E-commerce & Payments** +- [Shopify Automation](./shopify-automation/) - Automate Shopify: products, orders, customers, inventory, and GraphQL queries. +- [Square Automation](./square-automation/) - Automate Square: payments, customers, catalog, orders, and locations. +- [Stripe Automation](./stripe-automation/) - Automate Stripe: charges, customers, products, subscriptions, and refunds. + +**Design & Collaboration** +- [Canva Automation](./canva-automation/) - Automate Canva: designs, templates, assets, folders, and brand kits. +- [Confluence Automation](./confluence-automation/) - Automate Confluence: pages, spaces, search, CQL, labels, and versions. +- [DocuSign Automation](./docusign-automation/) - Automate DocuSign: envelopes, templates, signing, and document management. +- [Figma Automation](./figma-automation/) - Automate Figma: files, components, comments, projects, and team management. +- [Miro Automation](./miro-automation/) - Automate Miro: boards, sticky notes, shapes, connectors, and items. +- [Webflow Automation](./webflow-automation/) - Automate Webflow: CMS collections, items, sites, publishing, and assets. + +**Analytics & Data** +- [Amplitude Automation](./amplitude-automation/) - Automate Amplitude: events, cohorts, user properties, and analytics queries. +- [Google Analytics Automation](./google-analytics-automation/) - Automate Google Analytics: reports, dimensions, metrics, and property management. +- [Mixpanel Automation](./mixpanel-automation/) - Automate Mixpanel: events, funnels, cohorts, annotations, and JQL queries. +- [PostHog Automation](./posthog-automation/) - Automate PostHog: events, persons, feature flags, insights, and annotations. +- [Segment Automation](./segment-automation/) - Automate Segment: sources, destinations, tracking, and warehouse connections. + +**HR & People** +- [BambooHR Automation](./bamboohr-automation/) - Automate BambooHR: employees, time off, reports, and directory management. + +**Automation Platforms** +- [Make Automation](./make-automation/) - Automate Make (Integromat): scenarios, connections, and execution management. + +**Zoom & Meetings** +- [Zoom Automation](./zoom-automation/) - Automate Zoom: meetings, recordings, participants, webinars, and reports. + ## Getting Started ### Using Skills in Claude.ai diff --git a/activecampaign-automation/SKILL.md b/activecampaign-automation/SKILL.md new file mode 100644 index 0000000..49d315f --- /dev/null +++ b/activecampaign-automation/SKILL.md @@ -0,0 +1,206 @@ +--- +name: activecampaign-automation +description: Automate ActiveCampaign tasks via Rube MCP (Composio): manage contacts, tags, list subscriptions, automation enrollment, and tasks. Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# ActiveCampaign Automation via Rube MCP + +Automate ActiveCampaign CRM and marketing automation operations through Composio's ActiveCampaign toolkit via Rube MCP. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active ActiveCampaign connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `active_campaign` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `active_campaign` +3. If connection is not ACTIVE, follow the returned auth link to complete ActiveCampaign authentication +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. Create and Find Contacts + +**When to use**: User wants to create new contacts or look up existing ones + +**Tool sequence**: +1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Search for an existing contact [Optional] +2. `ACTIVE_CAMPAIGN_CREATE_CONTACT` - Create a new contact [Required] + +**Key parameters for find**: +- `email`: Search by email address +- `id`: Search by ActiveCampaign contact ID +- `phone`: Search by phone number + +**Key parameters for create**: +- `email`: Contact email address (required) +- `first_name`: Contact first name +- `last_name`: Contact last name +- `phone`: Contact phone number +- `organization_name`: Contact's organization +- `job_title`: Contact's job title +- `tags`: Comma-separated list of tags to apply + +**Pitfalls**: +- `email` is the only required field for contact creation +- Phone search uses a general search parameter internally; it may return partial matches +- When combining `email` and `phone` in FIND_CONTACT, results are filtered client-side +- Tags provided during creation are applied immediately +- Creating a contact with an existing email may update the existing contact + +### 2. Manage Contact Tags + +**When to use**: User wants to add or remove tags from contacts + +**Tool sequence**: +1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find contact by email or ID [Prerequisite] +2. `ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG` - Add or remove tags [Required] + +**Key parameters**: +- `action`: 'Add' or 'Remove' (required) +- `tags`: Tag names as comma-separated string or array of strings (required) +- `contact_id`: Contact ID (provide this or contact_email) +- `contact_email`: Contact email address (alternative to contact_id) + +**Pitfalls**: +- `action` values are capitalized: 'Add' or 'Remove' (not lowercase) +- Tags can be a comma-separated string ('tag1, tag2') or an array (['tag1', 'tag2']) +- Either `contact_id` or `contact_email` must be provided; `contact_id` takes precedence +- Adding a tag that does not exist creates it automatically +- Removing a non-existent tag is a no-op (does not error) + +### 3. Manage List Subscriptions + +**When to use**: User wants to subscribe or unsubscribe contacts from lists + +**Tool sequence**: +1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find the contact [Prerequisite] +2. `ACTIVE_CAMPAIGN_MANAGE_LIST_SUBSCRIPTION` - Subscribe or unsubscribe [Required] + +**Key parameters**: +- `action`: 'subscribe' or 'unsubscribe' (required) +- `list_id`: Numeric list ID string (required) +- `email`: Contact email address (provide this or contact_id) +- `contact_id`: Numeric contact ID string (alternative to email) + +**Pitfalls**: +- `action` values are lowercase: 'subscribe' or 'unsubscribe' +- `list_id` is a numeric string (e.g., '2'), not the list name +- List IDs can be retrieved via the GET /api/3/lists endpoint (not available as a Composio tool; use the ActiveCampaign UI) +- If both `email` and `contact_id` are provided, `contact_id` takes precedence +- Unsubscribing changes status to '2' (unsubscribed) but the relationship record persists + +### 4. Add Contacts to Automations + +**When to use**: User wants to enroll a contact in an automation workflow + +**Tool sequence**: +1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Verify contact exists [Prerequisite] +2. `ACTIVE_CAMPAIGN_ADD_CONTACT_TO_AUTOMATION` - Enroll contact in automation [Required] + +**Key parameters**: +- `contact_email`: Email of the contact to enroll (required) +- `automation_id`: ID of the target automation (required) + +**Pitfalls**: +- The contact must already exist in ActiveCampaign +- Automations can only be created through the ActiveCampaign UI, not via API +- `automation_id` must reference an existing, active automation +- The tool performs a two-step process: lookup contact by email, then enroll +- Automation IDs can be found in the ActiveCampaign UI or via GET /api/3/automations + +### 5. Create Contact Tasks + +**When to use**: User wants to create follow-up tasks associated with contacts + +**Tool sequence**: +1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find the contact to associate the task with [Prerequisite] +2. `ACTIVE_CAMPAIGN_CREATE_CONTACT_TASK` - Create the task [Required] + +**Key parameters**: +- `relid`: Contact ID to associate the task with (required) +- `duedate`: Due date in ISO 8601 format with timezone (required, e.g., '2025-01-15T14:30:00-05:00') +- `dealTasktype`: Task type ID based on available types (required) +- `title`: Task title +- `note`: Task description/content +- `assignee`: User ID to assign the task to +- `edate`: End date in ISO 8601 format (must be later than duedate) +- `status`: 0 for incomplete, 1 for complete + +**Pitfalls**: +- `duedate` must be a valid ISO 8601 datetime with timezone offset; do NOT use placeholder values +- `edate` must be later than `duedate` +- `dealTasktype` is a string ID referencing task types configured in ActiveCampaign +- `relid` is the numeric contact ID, not the email address +- `assignee` is a user ID; resolve user names to IDs via the ActiveCampaign UI + +## Common Patterns + +### Contact Lookup Flow + +``` +1. Call ACTIVE_CAMPAIGN_FIND_CONTACT with email +2. If found, extract contact ID for subsequent operations +3. If not found, create contact with ACTIVE_CAMPAIGN_CREATE_CONTACT +4. Use contact ID for tags, subscriptions, or automations +``` + +### Bulk Contact Tagging + +``` +1. For each contact, call ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG +2. Use contact_email to avoid separate lookup calls +3. Batch with reasonable delays to respect rate limits +``` + +### ID Resolution + +**Contact email -> Contact ID**: +``` +1. Call ACTIVE_CAMPAIGN_FIND_CONTACT with email +2. Extract id from the response +``` + +## Known Pitfalls + +**Action Capitalization**: +- Tag actions: 'Add', 'Remove' (capitalized) +- Subscription actions: 'subscribe', 'unsubscribe' (lowercase) +- Mixing up capitalization causes errors + +**ID Types**: +- Contact IDs: numeric strings (e.g., '123') +- List IDs: numeric strings +- Automation IDs: numeric strings +- All IDs should be passed as strings, not integers + +**Automations**: +- Automations cannot be created via API; only enrollment is possible +- Automation must be active to accept new contacts +- Enrolling a contact already in the automation may have no effect + +**Rate Limits**: +- ActiveCampaign API has rate limits per account +- Implement backoff on 429 responses +- Batch operations should be spaced appropriately + +**Response Parsing**: +- Response data may be nested under `data` or `data.data` +- Parse defensively with fallback patterns +- Contact search may return multiple results; match by email for accuracy + +## Quick Reference + +| Task | Tool Slug | Key Params | +|------|-----------|------------| +| Find contact | ACTIVE_CAMPAIGN_FIND_CONTACT | email, id, phone | +| Create contact | ACTIVE_CAMPAIGN_CREATE_CONTACT | email, first_name, last_name, tags | +| Add/remove tags | ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG | action, tags, contact_email | +| Subscribe/unsubscribe | ACTIVE_CAMPAIGN_MANAGE_LIST_SUBSCRIPTION | action, list_id, email | +| Add to automation | ACTIVE_CAMPAIGN_ADD_CONTACT_TO_AUTOMATION | contact_email, automation_id | +| Create task | ACTIVE_CAMPAIGN_CREATE_CONTACT_TASK | relid, duedate, dealTasktype, title | diff --git a/airtable-automation/SKILL.md b/airtable-automation/SKILL.md new file mode 100644 index 0000000..31fdec4 --- /dev/null +++ b/airtable-automation/SKILL.md @@ -0,0 +1,167 @@ +--- +name: airtable-automation +description: Automate Airtable tasks via Rube MCP (Composio): records, bases, tables, fields, views. Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# Airtable Automation via Rube MCP + +Automate Airtable operations through Composio's Airtable toolkit via Rube MCP. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active Airtable connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `airtable` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `airtable` +3. If connection is not ACTIVE, follow the returned auth link to complete Airtable auth +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. Create and Manage Records + +**When to use**: User wants to create, read, update, or delete records + +**Tool sequence**: +1. `AIRTABLE_LIST_BASES` - Discover available bases [Prerequisite] +2. `AIRTABLE_GET_BASE_SCHEMA` - Inspect table structure [Prerequisite] +3. `AIRTABLE_LIST_RECORDS` - List/filter records [Optional] +4. `AIRTABLE_CREATE_RECORD` / `AIRTABLE_CREATE_RECORDS` - Create records [Optional] +5. `AIRTABLE_UPDATE_RECORD` / `AIRTABLE_UPDATE_MULTIPLE_RECORDS` - Update records [Optional] +6. `AIRTABLE_DELETE_RECORD` / `AIRTABLE_DELETE_MULTIPLE_RECORDS` - Delete records [Optional] + +**Key parameters**: +- `baseId`: Base ID (starts with 'app', e.g., 'appXXXXXXXXXXXXXX') +- `tableIdOrName`: Table ID (starts with 'tbl') or table name +- `fields`: Object mapping field names to values +- `recordId`: Record ID (starts with 'rec') for updates/deletes +- `filterByFormula`: Airtable formula for filtering +- `typecast`: Set true for automatic type conversion + +**Pitfalls**: +- pageSize capped at 100; uses offset pagination; changing filters between pages can skip/duplicate rows +- CREATE_RECORDS hard limit of 10 records per request; chunk larger imports +- Field names are CASE-SENSITIVE and must match schema exactly +- 422 UNKNOWN_FIELD_NAME when field names are wrong; 403 for permission issues +- INVALID_MULTIPLE_CHOICE_OPTIONS may require typecast=true + +### 2. Search and Filter Records + +**When to use**: User wants to find specific records using formulas + +**Tool sequence**: +1. `AIRTABLE_GET_BASE_SCHEMA` - Verify field names and types [Prerequisite] +2. `AIRTABLE_LIST_RECORDS` - Query with filterByFormula [Required] +3. `AIRTABLE_GET_RECORD` - Get full record details [Optional] + +**Key parameters**: +- `filterByFormula`: Airtable formula (e.g., `{Status}='Done'`) +- `sort`: Array of sort objects +- `fields`: Array of field names to return +- `maxRecords`: Max total records across all pages +- `offset`: Pagination cursor from previous response + +**Pitfalls**: +- Field names in formulas must be wrapped in `{}` and match schema exactly +- String values must be quoted: `{Status}='Active'` not `{Status}=Active` +- 422 INVALID_FILTER_BY_FORMULA for bad syntax or non-existent fields +- Airtable rate limit: ~5 requests/second per base; handle 429 with Retry-After + +### 3. Manage Fields and Schema + +**When to use**: User wants to create or modify table fields + +**Tool sequence**: +1. `AIRTABLE_GET_BASE_SCHEMA` - Inspect current schema [Prerequisite] +2. `AIRTABLE_CREATE_FIELD` - Create a new field [Optional] +3. `AIRTABLE_UPDATE_FIELD` - Rename/describe a field [Optional] +4. `AIRTABLE_UPDATE_TABLE` - Update table metadata [Optional] + +**Key parameters**: +- `name`: Field name +- `type`: Field type (singleLineText, number, singleSelect, etc.) +- `options`: Type-specific options (choices for select, precision for number) +- `description`: Field description + +**Pitfalls**: +- UPDATE_FIELD only changes name/description, NOT type/options; create a replacement field and migrate +- Computed fields (formula, rollup, lookup) cannot be created via API +- 422 when type options are missing or malformed + +### 4. Manage Comments + +**When to use**: User wants to view or add comments on records + +**Tool sequence**: +1. `AIRTABLE_LIST_COMMENTS` - List comments on a record [Required] + +**Key parameters**: +- `baseId`: Base ID +- `tableIdOrName`: Table identifier +- `recordId`: Record ID (17 chars, starts with 'rec') +- `pageSize`: Comments per page (max 100) + +**Pitfalls**: +- Record IDs must be exactly 17 characters starting with 'rec' + +## Common Patterns + +### Airtable Formula Syntax + +**Comparison**: +- `{Status}='Done'` - Equals +- `{Priority}>1` - Greater than +- `{Name}!=''` - Not empty + +**Functions**: +- `AND({A}='x', {B}='y')` - Both conditions +- `OR({A}='x', {A}='y')` - Either condition +- `FIND('test', {Name})>0` - Contains text +- `IS_BEFORE({Due Date}, TODAY())` - Date comparison + +**Escape rules**: +- Single quotes in values: double them (`{Name}='John''s Company'`) + +### Pagination + +- Set `pageSize` (max 100) +- Check response for `offset` string +- Pass `offset` to next request unchanged +- Keep filters/sorts/view stable between pages + +## Known Pitfalls + +**ID Formats**: +- Base IDs: `appXXXXXXXXXXXXXX` (17 chars) +- Table IDs: `tblXXXXXXXXXXXXXX` (17 chars) +- Record IDs: `recXXXXXXXXXXXXXX` (17 chars) +- Field IDs: `fldXXXXXXXXXXXXXX` (17 chars) + +**Batch Limits**: +- CREATE_RECORDS: max 10 per request +- UPDATE_MULTIPLE_RECORDS: max 10 per request +- DELETE_MULTIPLE_RECORDS: max 10 per request + +## Quick Reference + +| Task | Tool Slug | Key Params | +|------|-----------|------------| +| List bases | AIRTABLE_LIST_BASES | (none) | +| Get schema | AIRTABLE_GET_BASE_SCHEMA | baseId | +| List records | AIRTABLE_LIST_RECORDS | baseId, tableIdOrName | +| Get record | AIRTABLE_GET_RECORD | baseId, tableIdOrName, recordId | +| Create record | AIRTABLE_CREATE_RECORD | baseId, tableIdOrName, fields | +| Create records | AIRTABLE_CREATE_RECORDS | baseId, tableIdOrName, records | +| Update record | AIRTABLE_UPDATE_RECORD | baseId, tableIdOrName, recordId, fields | +| Update records | AIRTABLE_UPDATE_MULTIPLE_RECORDS | baseId, tableIdOrName, records | +| Delete record | AIRTABLE_DELETE_RECORD | baseId, tableIdOrName, recordId | +| Create field | AIRTABLE_CREATE_FIELD | baseId, tableIdOrName, name, type | +| Update field | AIRTABLE_UPDATE_FIELD | baseId, tableIdOrName, fieldId | +| Update table | AIRTABLE_UPDATE_TABLE | baseId, tableIdOrName, name | +| List comments | AIRTABLE_LIST_COMMENTS | baseId, tableIdOrName, recordId | diff --git a/amplitude-automation/SKILL.md b/amplitude-automation/SKILL.md new file mode 100644 index 0000000..f38301c --- /dev/null +++ b/amplitude-automation/SKILL.md @@ -0,0 +1,213 @@ +--- +name: amplitude-automation +description: Automate Amplitude tasks via Rube MCP (Composio): events, user activity, cohorts, user identification. Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# Amplitude Automation via Rube MCP + +Automate Amplitude product analytics through Composio's Amplitude toolkit via Rube MCP. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active Amplitude connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `amplitude` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `amplitude` +3. If connection is not ACTIVE, follow the returned auth link to complete Amplitude authentication +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. Send Events + +**When to use**: User wants to track events or send event data to Amplitude + +**Tool sequence**: +1. `AMPLITUDE_SEND_EVENTS` - Send one or more events to Amplitude [Required] + +**Key parameters**: +- `events`: Array of event objects, each containing: + - `event_type`: Name of the event (e.g., 'page_view', 'purchase') + - `user_id`: Unique user identifier (required if no `device_id`) + - `device_id`: Device identifier (required if no `user_id`) + - `event_properties`: Object with custom event properties + - `user_properties`: Object with user properties to set + - `time`: Event timestamp in milliseconds since epoch + +**Pitfalls**: +- At least one of `user_id` or `device_id` is required per event +- `event_type` is required for every event; cannot be empty +- `time` must be in milliseconds (13-digit epoch), not seconds +- Batch limit applies; check schema for maximum events per request +- Events are processed asynchronously; successful API response does not mean data is immediately queryable + +### 2. Get User Activity + +**When to use**: User wants to view event history for a specific user + +**Tool sequence**: +1. `AMPLITUDE_FIND_USER` - Find user by ID or property [Prerequisite] +2. `AMPLITUDE_GET_USER_ACTIVITY` - Retrieve user's event stream [Required] + +**Key parameters**: +- `user`: Amplitude internal user ID (from FIND_USER) +- `offset`: Pagination offset for event list +- `limit`: Maximum number of events to return + +**Pitfalls**: +- `user` parameter requires Amplitude's internal user ID, NOT your application's user_id +- Must call FIND_USER first to resolve your user_id to Amplitude's internal ID +- Activity is returned in reverse chronological order by default +- Large activity histories require pagination via `offset` + +### 3. Find and Identify Users + +**When to use**: User wants to look up users or set user properties + +**Tool sequence**: +1. `AMPLITUDE_FIND_USER` - Search for a user by various identifiers [Required] +2. `AMPLITUDE_IDENTIFY` - Set or update user properties [Optional] + +**Key parameters**: +- For FIND_USER: + - `user`: Search term (user_id, email, or Amplitude ID) +- For IDENTIFY: + - `user_id`: Your application's user identifier + - `device_id`: Device identifier (alternative to user_id) + - `user_properties`: Object with `$set`, `$unset`, `$add`, `$append` operations + +**Pitfalls**: +- FIND_USER searches across user_id, device_id, and Amplitude ID +- IDENTIFY uses special property operations (`$set`, `$unset`, `$add`, `$append`) +- `$set` overwrites existing values; `$setOnce` only sets if not already set +- At least one of `user_id` or `device_id` is required for IDENTIFY +- User property changes are eventually consistent; not immediate + +### 4. Manage Cohorts + +**When to use**: User wants to list cohorts, view cohort details, or update cohort membership + +**Tool sequence**: +1. `AMPLITUDE_LIST_COHORTS` - List all saved cohorts [Required] +2. `AMPLITUDE_GET_COHORT` - Get detailed cohort information [Optional] +3. `AMPLITUDE_UPDATE_COHORT_MEMBERSHIP` - Add/remove users from a cohort [Optional] +4. `AMPLITUDE_CHECK_COHORT_STATUS` - Check async cohort operation status [Optional] + +**Key parameters**: +- For LIST_COHORTS: No required parameters +- For GET_COHORT: `cohort_id` (from list results) +- For UPDATE_COHORT_MEMBERSHIP: + - `cohort_id`: Target cohort ID + - `memberships`: Object with `add` and/or `remove` arrays of user IDs +- For CHECK_COHORT_STATUS: `request_id` from update response + +**Pitfalls**: +- Cohort IDs are required for all cohort-specific operations +- UPDATE_COHORT_MEMBERSHIP is asynchronous; use CHECK_COHORT_STATUS to verify +- `request_id` from the update response is needed for status checking +- Maximum membership changes per request may be limited; chunk large updates +- Only behavioral cohorts support API membership updates + +### 5. Browse Event Categories + +**When to use**: User wants to discover available event types and categories in Amplitude + +**Tool sequence**: +1. `AMPLITUDE_GET_EVENT_CATEGORIES` - List all event categories [Required] + +**Key parameters**: +- No required parameters; returns all configured event categories + +**Pitfalls**: +- Categories are configured in Amplitude UI; API provides read access +- Event names within categories are case-sensitive +- Use these categories to validate event_type values before sending events + +## Common Patterns + +### ID Resolution + +**Application user_id -> Amplitude internal ID**: +``` +1. Call AMPLITUDE_FIND_USER with user=your_user_id +2. Extract Amplitude's internal user ID from response +3. Use internal ID for GET_USER_ACTIVITY +``` + +**Cohort name -> Cohort ID**: +``` +1. Call AMPLITUDE_LIST_COHORTS +2. Find cohort by name in results +3. Extract id for cohort operations +``` + +### User Property Operations + +Amplitude IDENTIFY supports these property operations: +- `$set`: Set property value (overwrites existing) +- `$setOnce`: Set only if property not already set +- `$add`: Increment numeric property +- `$append`: Append to list property +- `$unset`: Remove property entirely + +Example structure: +```json +{ + "user_properties": { + "$set": {"plan": "premium", "company": "Acme"}, + "$add": {"login_count": 1} + } +} +``` + +### Async Operation Pattern + +For cohort membership updates: +``` +1. Call AMPLITUDE_UPDATE_COHORT_MEMBERSHIP -> get request_id +2. Call AMPLITUDE_CHECK_COHORT_STATUS with request_id +3. Repeat step 2 until status is 'complete' or 'error' +``` + +## Known Pitfalls + +**User IDs**: +- Amplitude has its own internal user IDs separate from your application's +- FIND_USER resolves your IDs to Amplitude's internal IDs +- GET_USER_ACTIVITY requires Amplitude's internal ID, not your user_id + +**Event Timestamps**: +- Must be in milliseconds since epoch (13 digits) +- Seconds (10 digits) will be interpreted as very old dates +- Omitting timestamp uses server receive time + +**Rate Limits**: +- Event ingestion has throughput limits per project +- Batch events where possible to reduce API calls +- Cohort membership updates have async processing limits + +**Response Parsing**: +- Response data may be nested under `data` key +- User activity returns events in reverse chronological order +- Cohort lists may include archived cohorts; check status field +- Parse defensively with fallbacks for optional fields + +## Quick Reference + +| Task | Tool Slug | Key Params | +|------|-----------|------------| +| Send events | AMPLITUDE_SEND_EVENTS | events (array) | +| Find user | AMPLITUDE_FIND_USER | user | +| Get user activity | AMPLITUDE_GET_USER_ACTIVITY | user, offset, limit | +| Identify user | AMPLITUDE_IDENTIFY | user_id, user_properties | +| List cohorts | AMPLITUDE_LIST_COHORTS | (none) | +| Get cohort | AMPLITUDE_GET_COHORT | cohort_id | +| Update cohort members | AMPLITUDE_UPDATE_COHORT_MEMBERSHIP | cohort_id, memberships | +| Check cohort status | AMPLITUDE_CHECK_COHORT_STATUS | request_id | +| List event categories | AMPLITUDE_GET_EVENT_CATEGORIES | (none) | diff --git a/asana-automation/SKILL.md b/asana-automation/SKILL.md new file mode 100644 index 0000000..c64d899 --- /dev/null +++ b/asana-automation/SKILL.md @@ -0,0 +1,168 @@ +--- +name: asana-automation +description: Automate Asana tasks via Rube MCP (Composio): tasks, projects, sections, teams, workspaces. Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# Asana Automation via Rube MCP + +Automate Asana operations through Composio's Asana toolkit via Rube MCP. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active Asana connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `asana` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `asana` +3. If connection is not ACTIVE, follow the returned auth link to complete Asana OAuth +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. Manage Tasks + +**When to use**: User wants to create, search, list, or organize tasks + +**Tool sequence**: +1. `ASANA_GET_MULTIPLE_WORKSPACES` - Get workspace ID [Prerequisite] +2. `ASANA_SEARCH_TASKS_IN_WORKSPACE` - Search tasks [Optional] +3. `ASANA_GET_TASKS_FROM_A_PROJECT` - List project tasks [Optional] +4. `ASANA_CREATE_A_TASK` - Create a new task [Optional] +5. `ASANA_GET_A_TASK` - Get task details [Optional] +6. `ASANA_CREATE_SUBTASK` - Create a subtask [Optional] +7. `ASANA_GET_TASK_SUBTASKS` - List subtasks [Optional] + +**Key parameters**: +- `workspace`: Workspace GID (required for search/creation) +- `projects`: Array of project GIDs to add task to +- `name`: Task name +- `notes`: Task description +- `assignee`: Assignee (user GID or email) +- `due_on`: Due date (YYYY-MM-DD) + +**Pitfalls**: +- Workspace GID is required for most operations; get it first +- Task GIDs are returned as strings, not integers +- Search is workspace-scoped, not project-scoped + +### 2. Manage Projects and Sections + +**When to use**: User wants to create projects, manage sections, or organize tasks + +**Tool sequence**: +1. `ASANA_GET_WORKSPACE_PROJECTS` - List workspace projects [Optional] +2. `ASANA_GET_A_PROJECT` - Get project details [Optional] +3. `ASANA_CREATE_A_PROJECT` - Create a new project [Optional] +4. `ASANA_GET_SECTIONS_IN_PROJECT` - List sections [Optional] +5. `ASANA_CREATE_SECTION_IN_PROJECT` - Create a new section [Optional] +6. `ASANA_ADD_TASK_TO_SECTION` - Move task to section [Optional] +7. `ASANA_GET_TASKS_FROM_A_SECTION` - List tasks in section [Optional] + +**Key parameters**: +- `project_gid`: Project GID +- `name`: Project or section name +- `workspace`: Workspace GID for creation +- `task`: Task GID for section assignment +- `section`: Section GID + +**Pitfalls**: +- Projects belong to workspaces; workspace GID is needed for creation +- Sections are ordered within a project +- DUPLICATE_PROJECT creates a copy with optional task inclusion + +### 3. Manage Teams and Users + +**When to use**: User wants to list teams, team members, or workspace users + +**Tool sequence**: +1. `ASANA_GET_TEAMS_IN_WORKSPACE` - List workspace teams [Optional] +2. `ASANA_GET_USERS_FOR_TEAM` - List team members [Optional] +3. `ASANA_GET_USERS_FOR_WORKSPACE` - List all workspace users [Optional] +4. `ASANA_GET_CURRENT_USER` - Get authenticated user [Optional] +5. `ASANA_GET_MULTIPLE_USERS` - Get multiple user details [Optional] + +**Key parameters**: +- `workspace_gid`: Workspace GID +- `team_gid`: Team GID + +**Pitfalls**: +- Users are workspace-scoped +- Team membership requires the team GID + +### 4. Parallel Operations + +**When to use**: User needs to perform bulk operations efficiently + +**Tool sequence**: +1. `ASANA_SUBMIT_PARALLEL_REQUESTS` - Execute multiple API calls in parallel [Required] + +**Key parameters**: +- `actions`: Array of action objects with method, path, and data + +**Pitfalls**: +- Each action must be a valid Asana API call +- Failed individual requests do not roll back successful ones + +## Common Patterns + +### ID Resolution + +**Workspace name -> GID**: +``` +1. Call ASANA_GET_MULTIPLE_WORKSPACES +2. Find workspace by name +3. Extract gid field +``` + +**Project name -> GID**: +``` +1. Call ASANA_GET_WORKSPACE_PROJECTS with workspace GID +2. Find project by name +3. Extract gid field +``` + +### Pagination + +- Asana uses cursor-based pagination with `offset` parameter +- Check for `next_page` in response +- Pass `offset` from `next_page.offset` for next request + +## Known Pitfalls + +**GID Format**: +- All Asana IDs are strings (GIDs), not integers +- GIDs are globally unique identifiers + +**Workspace Scoping**: +- Most operations require a workspace context +- Tasks, projects, and users are workspace-scoped + +## Quick Reference + +| Task | Tool Slug | Key Params | +|------|-----------|------------| +| List workspaces | ASANA_GET_MULTIPLE_WORKSPACES | (none) | +| Search tasks | ASANA_SEARCH_TASKS_IN_WORKSPACE | workspace, text | +| Create task | ASANA_CREATE_A_TASK | workspace, name, projects | +| Get task | ASANA_GET_A_TASK | task_gid | +| Create subtask | ASANA_CREATE_SUBTASK | parent, name | +| List subtasks | ASANA_GET_TASK_SUBTASKS | task_gid | +| Project tasks | ASANA_GET_TASKS_FROM_A_PROJECT | project_gid | +| List projects | ASANA_GET_WORKSPACE_PROJECTS | workspace | +| Create project | ASANA_CREATE_A_PROJECT | workspace, name | +| Get project | ASANA_GET_A_PROJECT | project_gid | +| Duplicate project | ASANA_DUPLICATE_PROJECT | project_gid | +| List sections | ASANA_GET_SECTIONS_IN_PROJECT | project_gid | +| Create section | ASANA_CREATE_SECTION_IN_PROJECT | project_gid, name | +| Add to section | ASANA_ADD_TASK_TO_SECTION | section, task | +| Section tasks | ASANA_GET_TASKS_FROM_A_SECTION | section_gid | +| List teams | ASANA_GET_TEAMS_IN_WORKSPACE | workspace_gid | +| Team members | ASANA_GET_USERS_FOR_TEAM | team_gid | +| Workspace users | ASANA_GET_USERS_FOR_WORKSPACE | workspace_gid | +| Current user | ASANA_GET_CURRENT_USER | (none) | +| Parallel requests | ASANA_SUBMIT_PARALLEL_REQUESTS | actions | diff --git a/bamboohr-automation/SKILL.md b/bamboohr-automation/SKILL.md new file mode 100644 index 0000000..c28aaff --- /dev/null +++ b/bamboohr-automation/SKILL.md @@ -0,0 +1,217 @@ +--- +name: bamboohr-automation +description: Automate BambooHR tasks via Rube MCP (Composio): employees, time-off, benefits, dependents, employee updates. Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# BambooHR Automation via Rube MCP + +Automate BambooHR human resources operations through Composio's BambooHR toolkit via Rube MCP. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active BambooHR connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `bamboohr` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `bamboohr` +3. If connection is not ACTIVE, follow the returned auth link to complete BambooHR authentication +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. List and Search Employees + +**When to use**: User wants to find employees or get the full employee directory + +**Tool sequence**: +1. `BAMBOOHR_GET_ALL_EMPLOYEES` - Get the employee directory [Required] +2. `BAMBOOHR_GET_EMPLOYEE` - Get detailed info for a specific employee [Optional] + +**Key parameters**: +- For GET_ALL_EMPLOYEES: No required parameters; returns directory +- For GET_EMPLOYEE: + - `id`: Employee ID (numeric) + - `fields`: Comma-separated list of fields to return (e.g., 'firstName,lastName,department,jobTitle') + +**Pitfalls**: +- Employee IDs are numeric integers +- GET_ALL_EMPLOYEES returns basic directory info; use GET_EMPLOYEE for full details +- The `fields` parameter controls which fields are returned; omitting it may return minimal data +- Common fields: firstName, lastName, department, division, jobTitle, workEmail, status +- Inactive/terminated employees may be included; check `status` field + +### 2. Track Employee Changes + +**When to use**: User wants to detect recent employee data changes for sync or auditing + +**Tool sequence**: +1. `BAMBOOHR_EMPLOYEE_GET_CHANGED` - Get employees with recent changes [Required] + +**Key parameters**: +- `since`: ISO 8601 datetime string for change detection threshold +- `type`: Type of changes to check (e.g., 'inserted', 'updated', 'deleted') + +**Pitfalls**: +- `since` parameter is required; use ISO 8601 format (e.g., '2024-01-15T00:00:00Z') +- Returns IDs of changed employees, not full employee data +- Must call GET_EMPLOYEE separately for each changed employee's details +- Useful for incremental sync workflows; cache the last sync timestamp + +### 3. Manage Time-Off + +**When to use**: User wants to view time-off balances, request time off, or manage requests + +**Tool sequence**: +1. `BAMBOOHR_GET_META_TIME_OFF_TYPES` - List available time-off types [Prerequisite] +2. `BAMBOOHR_GET_TIME_OFF_BALANCES` - Check current balances [Optional] +3. `BAMBOOHR_GET_TIME_OFF_REQUESTS` - List existing requests [Optional] +4. `BAMBOOHR_CREATE_TIME_OFF_REQUEST` - Submit a new request [Optional] +5. `BAMBOOHR_UPDATE_TIME_OFF_REQUEST` - Modify or approve/deny a request [Optional] + +**Key parameters**: +- For balances: `employeeId`, time-off type ID +- For requests: `start`, `end` (date range), `employeeId` +- For creation: + - `employeeId`: Employee to request for + - `timeOffTypeId`: Type ID from GET_META_TIME_OFF_TYPES + - `start`: Start date (YYYY-MM-DD) + - `end`: End date (YYYY-MM-DD) + - `amount`: Number of days/hours + - `notes`: Optional notes for the request +- For update: `requestId`, `status` ('approved', 'denied', 'cancelled') + +**Pitfalls**: +- Time-off type IDs are numeric; resolve via GET_META_TIME_OFF_TYPES first +- Date format is 'YYYY-MM-DD' for start and end dates +- Balances may be in hours or days depending on company configuration +- Request status updates require appropriate permissions (manager/admin) +- Creating a request does NOT auto-approve it; separate approval step needed + +### 4. Update Employee Information + +**When to use**: User wants to modify employee profile data + +**Tool sequence**: +1. `BAMBOOHR_GET_EMPLOYEE` - Get current employee data [Prerequisite] +2. `BAMBOOHR_UPDATE_EMPLOYEE` - Update employee fields [Required] + +**Key parameters**: +- `id`: Employee ID (numeric, required) +- Field-value pairs for the fields to update (e.g., `department`, `jobTitle`, `workPhone`) + +**Pitfalls**: +- Only fields included in the request are updated; others remain unchanged +- Some fields are read-only and cannot be updated via API +- Field names must match BambooHR's expected field names exactly +- Updates are audited; changes appear in the employee's change history +- Verify current values with GET_EMPLOYEE before updating to avoid overwriting + +### 5. Manage Dependents and Benefits + +**When to use**: User wants to view employee dependents or benefit coverage + +**Tool sequence**: +1. `BAMBOOHR_DEPENDENTS_GET_ALL` - List all dependents [Required] +2. `BAMBOOHR_BENEFIT_GET_COVERAGES` - Get benefit coverage details [Optional] + +**Key parameters**: +- For dependents: Optional `employeeId` filter +- For benefits: Depends on schema; check RUBE_SEARCH_TOOLS for current parameters + +**Pitfalls**: +- Dependent data includes sensitive PII; handle with appropriate care +- Benefit coverages may include multiple plan types per employee +- Not all BambooHR plans include benefits administration; check account features +- Data access depends on API key permissions + +## Common Patterns + +### ID Resolution + +**Employee name -> Employee ID**: +``` +1. Call BAMBOOHR_GET_ALL_EMPLOYEES +2. Find employee by name in directory results +3. Extract id (numeric) for detailed operations +``` + +**Time-off type name -> Type ID**: +``` +1. Call BAMBOOHR_GET_META_TIME_OFF_TYPES +2. Find type by name (e.g., 'Vacation', 'Sick Leave') +3. Extract id for time-off requests +``` + +### Incremental Sync Pattern + +For keeping external systems in sync with BambooHR: +``` +1. Store last_sync_timestamp +2. Call BAMBOOHR_EMPLOYEE_GET_CHANGED with since=last_sync_timestamp +3. For each changed employee ID, call BAMBOOHR_GET_EMPLOYEE +4. Process updates in external system +5. Update last_sync_timestamp +``` + +### Time-Off Workflow + +``` +1. GET_META_TIME_OFF_TYPES -> find type ID +2. GET_TIME_OFF_BALANCES -> verify available balance +3. CREATE_TIME_OFF_REQUEST -> submit request +4. UPDATE_TIME_OFF_REQUEST -> approve/deny (manager action) +``` + +## Known Pitfalls + +**Employee IDs**: +- Always numeric integers +- Resolve names to IDs via GET_ALL_EMPLOYEES +- Terminated employees retain their IDs + +**Date Formats**: +- Time-off dates: 'YYYY-MM-DD' +- Change detection: ISO 8601 with timezone +- Inconsistent formats between endpoints; check each endpoint's schema + +**Permissions**: +- API key permissions determine accessible fields and operations +- Some operations require admin or manager-level access +- Time-off approvals require appropriate role permissions + +**Sensitive Data**: +- Employee data includes PII (names, addresses, SSN, etc.) +- Handle all responses with appropriate security measures +- Dependent data is especially sensitive + +**Rate Limits**: +- BambooHR API has rate limits per API key +- Bulk operations should be throttled +- GET_ALL_EMPLOYEES is more efficient than individual GET_EMPLOYEE calls + +**Response Parsing**: +- Response data may be nested under `data` key +- Employee fields vary based on `fields` parameter +- Empty fields may be omitted or returned as null +- Parse defensively with fallbacks + +## Quick Reference + +| Task | Tool Slug | Key Params | +|------|-----------|------------| +| List all employees | BAMBOOHR_GET_ALL_EMPLOYEES | (none) | +| Get employee details | BAMBOOHR_GET_EMPLOYEE | id, fields | +| Track changes | BAMBOOHR_EMPLOYEE_GET_CHANGED | since, type | +| Time-off types | BAMBOOHR_GET_META_TIME_OFF_TYPES | (none) | +| Time-off balances | BAMBOOHR_GET_TIME_OFF_BALANCES | employeeId | +| List time-off requests | BAMBOOHR_GET_TIME_OFF_REQUESTS | start, end, employeeId | +| Create time-off request | BAMBOOHR_CREATE_TIME_OFF_REQUEST | employeeId, timeOffTypeId, start, end | +| Update time-off request | BAMBOOHR_UPDATE_TIME_OFF_REQUEST | requestId, status | +| Update employee | BAMBOOHR_UPDATE_EMPLOYEE | id, (field updates) | +| List dependents | BAMBOOHR_DEPENDENTS_GET_ALL | employeeId | +| Benefit coverages | BAMBOOHR_BENEFIT_GET_COVERAGES | (check schema) | diff --git a/basecamp-automation/SKILL.md b/basecamp-automation/SKILL.md new file mode 100644 index 0000000..206e8e9 --- /dev/null +++ b/basecamp-automation/SKILL.md @@ -0,0 +1,231 @@ +--- +name: basecamp-automation +description: Automate Basecamp project management, to-dos, messages, people, and to-do list organization via Rube MCP (Composio). Always search tools first for current schemas. +requires: + mcp: [rube] +--- + +# Basecamp Automation via Rube MCP + +Automate Basecamp operations including project management, to-do list creation, task management, message board posting, people management, and to-do group organization through Composio's Basecamp toolkit. + +## Prerequisites + +- Rube MCP must be connected (RUBE_SEARCH_TOOLS available) +- Active Basecamp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `basecamp` +- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas + +## Setup + +1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds +2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `basecamp` +3. If connection is not ACTIVE, follow the returned auth link to complete Basecamp OAuth +4. Confirm connection status shows ACTIVE before running any workflows + +## Core Workflows + +### 1. Manage To-Do Lists and Tasks + +**When to use**: User wants to create to-do lists, add tasks, or organize work within a Basecamp project + +**Tool sequence**: +1. `BASECAMP_GET_PROJECTS` - List projects to find the target bucket_id [Prerequisite] +2. `BASECAMP_GET_BUCKETS_TODOSETS` - Get the to-do set within a project [Prerequisite] +3. `BASECAMP_GET_BUCKETS_TODOSETS_TODOLISTS` - List existing to-do lists to avoid duplicates [Optional] +4. `BASECAMP_POST_BUCKETS_TODOSETS_TODOLISTS` - Create a new to-do list in a to-do set [Required for list creation] +5. `BASECAMP_GET_BUCKETS_TODOLISTS` - Get details of a specific to-do list [Optional] +6. `BASECAMP_POST_BUCKETS_TODOLISTS_TODOS` - Create a to-do item in a to-do list [Required for task creation] +7. `BASECAMP_CREATE_TODO` - Alternative tool for creating individual to-dos [Alternative] +8. `BASECAMP_GET_BUCKETS_TODOLISTS_TODOS` - List to-dos within a to-do list [Optional] + +**Key parameters for creating to-do lists**: +- `bucket_id`: Integer project/bucket ID (from GET_PROJECTS) +- `todoset_id`: Integer to-do set ID (from GET_BUCKETS_TODOSETS) +- `name`: Title of the to-do list (required) +- `description`: HTML-formatted description (supports Rich text) + +**Key parameters for creating to-dos**: +- `bucket_id`: Integer project/bucket ID +- `todolist_id`: Integer to-do list ID +- `content`: What the to-do is for (required) +- `description`: HTML details about the to-do +- `assignee_ids`: Array of integer person IDs +- `due_on`: Due date in `YYYY-MM-DD` format +- `starts_on`: Start date in `YYYY-MM-DD` format +- `notify`: Boolean to notify assignees (defaults to false) +- `completion_subscriber_ids`: Person IDs notified upon completion + +**Pitfalls**: +- A project (bucket) can contain multiple to-do sets; selecting the wrong `todoset_id` creates lists in the wrong section +- Always check existing to-do lists before creating to avoid near-duplicate names +- Success payloads include user-facing URLs (`app_url`, `app_todos_url`); prefer returning these over raw IDs +- All IDs (`bucket_id`, `todoset_id`, `todolist_id`) are integers, not strings +- Descriptions support HTML formatting only, not Markdown + +### 2. Post and Manage Messages + +**When to use**: User wants to post messages to a project message board or update existing messages + +**Tool sequence**: +1. `BASECAMP_GET_PROJECTS` - Find the target project and bucket_id [Prerequisite] +2. `BASECAMP_GET_MESSAGE_BOARD` - Get the message board ID for the project [Prerequisite] +3. `BASECAMP_CREATE_MESSAGE` - Create a new message on the board [Required] +4. `BASECAMP_POST_BUCKETS_MESSAGE_BOARDS_MESSAGES` - Alternative message creation tool [Fallback] +5. `BASECAMP_GET_MESSAGE` - Read a specific message by ID [Optional] +6. `BASECAMP_PUT_BUCKETS_MESSAGES` - Update an existing message [Optional] + +**Key parameters**: +- `bucket_id`: Integer project/bucket ID +- `message_board_id`: Integer message board ID (from GET_MESSAGE_BOARD) +- `subject`: Message title (required) +- `content`: HTML body of the message +- `status`: Set to `"active"` to publish immediately +- `category_id`: Message type classification (optional) +- `subscriptions`: Array of person IDs to notify; omit to notify all project members + +**Pitfalls**: +- `status="draft"` can produce HTTP 400; use `status="active"` as the reliable option +- `bucket_id` and `message_board_id` must belong to the same project; mismatches fail or misroute +- Message content supports HTML tags only; not Markdown +- Updates via `PUT_BUCKETS_MESSAGES` replace the entire body -- include the full corrected content, not just a diff +- Prefer `app_url` from the response for user-facing confirmation links +- Both `CREATE_MESSAGE` and `POST_BUCKETS_MESSAGE_BOARDS_MESSAGES` do the same thing; use CREATE_MESSAGE first and fall back to POST if it fails + +### 3. Manage People and Access + +**When to use**: User wants to list people, manage project access, or add new users + +**Tool sequence**: +1. `BASECAMP_GET_PEOPLE` - List all people visible to the current user [Required] +2. `BASECAMP_GET_PROJECTS` - Find the target project [Prerequisite] +3. `BASECAMP_LIST_PROJECT_PEOPLE` - List people on a specific project [Required] +4. `BASECAMP_GET_PROJECTS_PEOPLE` - Alternative to list project members [Alternative] +5. `BASECAMP_PUT_PROJECTS_PEOPLE_USERS` - Grant or revoke project access [Required for access changes] + +**Key parameters for PUT_PROJECTS_PEOPLE_USERS**: +- `project_id`: Integer project ID +- `grant`: Array of integer person IDs to add to the project +- `revoke`: Array of integer person IDs to remove from the project +- `create`: Array of objects with `name`, `email_address`, and optional `company_name`, `title` for new users +- At least one of `grant`, `revoke`, or `create` must be provided + +**Pitfalls**: +- Person IDs are integers; always resolve names to IDs via GET_PEOPLE first +- `project_id` for people management is the same as `bucket_id` for other operations +- `LIST_PROJECT_PEOPLE` and `GET_PROJECTS_PEOPLE` are near-identical; use either +- Creating users via `create` also grants them project access in one step + +### 4. Organize To-Dos with Groups + +**When to use**: User wants to organize to-dos within a list into color-coded groups + +**Tool sequence**: +1. `BASECAMP_GET_PROJECTS` - Find the target project [Prerequisite] +2. `BASECAMP_GET_BUCKETS_TODOLISTS` - Get the to-do list details [Prerequisite] +3. `BASECAMP_GET_TODOLIST_GROUPS` - List existing groups in a to-do list [Optional] +4. `BASECAMP_GET_BUCKETS_TODOLISTS_GROUPS` - Alternative group listing [Alternative] +5. `BASECAMP_POST_BUCKETS_TODOLISTS_GROUPS` - Create a new group in a to-do list [Required] +6. `BASECAMP_CREATE_TODOLIST_GROUP` - Alternative group creation tool [Alternative] + +**Key parameters**: +- `bucket_id`: Integer project/bucket ID +- `todolist_id`: Integer to-do list ID +- `name`: Group title (required) +- `color`: Visual color identifier -- one of: `white`, `red`, `orange`, `yellow`, `green`, `blue`, `aqua`, `purple`, `gray`, `pink`, `brown` +- `status`: Filter for listing -- `"archived"` or `"trashed"` (omit for active groups) + +**Pitfalls**: +- `POST_BUCKETS_TODOLISTS_GROUPS` and `CREATE_TODOLIST_GROUP` are near-identical; use either +- Color values must be from the fixed palette; arbitrary hex/rgb values are not supported +- Groups are sub-sections within a to-do list, not standalone entities + +### 5. Browse and Inspect Projects + +**When to use**: User wants to list projects, get project details, or explore project structure + +**Tool sequence**: +1. `BASECAMP_GET_PROJECTS` - List all active projects [Required] +2. `BASECAMP_GET_PROJECT` - Get comprehensive details for a specific project [Optional] +3. `BASECAMP_GET_PROJECTS_BY_PROJECT_ID` - Alternative project detail retrieval [Alternative] + +**Key parameters**: +- `status`: Filter by `"archived"` or `"trashed"`; omit for active projects +- `project_id`: Integer project ID for detailed retrieval + +**Pitfalls**: +- Projects are sorted by most recently created first +- The response includes a `dock` array with tools (todoset, message_board, etc.) and their IDs +- Use the dock tool IDs to find `todoset_id`, `message_board_id`, etc. for downstream operations + +## Common Patterns + +### ID Resolution +Basecamp uses a hierarchical ID structure. Always resolve top-down: +- **Project (bucket_id)**: `BASECAMP_GET_PROJECTS` -- find by name, capture the `id` +- **To-do set (todoset_id)**: Found in project dock or via `BASECAMP_GET_BUCKETS_TODOSETS` +- **Message board (message_board_id)**: Found in project dock or via `BASECAMP_GET_MESSAGE_BOARD` +- **To-do list (todolist_id)**: `BASECAMP_GET_BUCKETS_TODOSETS_TODOLISTS` +- **People (person_id)**: `BASECAMP_GET_PEOPLE` or `BASECAMP_LIST_PROJECT_PEOPLE` +- Note: `bucket_id` and `project_id` refer to the same entity in different contexts + +### Pagination +Basecamp uses page-based pagination on list endpoints: +- Response headers or body may indicate more pages available +- `GET_PROJECTS`, `GET_BUCKETS_TODOSETS_TODOLISTS`, and list endpoints return paginated results +- Continue fetching until no more results are returned + +### Content Formatting +- All rich text fields use HTML, not Markdown +- Wrap content in `
`, `
`, ``, ``, `- `
+- Tables: `
` / ` ` structure
+- Macros: `` for code blocks, etc.
+- Always wrap content in proper XHTML tags
+
+## Known Pitfalls
+
+### ID Formats
+- Space IDs are numeric (e.g., `557060`); space keys are short strings (e.g., `DOCS`)
+- Page IDs are numeric long values for GET_PAGE_BY_ID; some tools accept UUID format
+- `GET_SPACE_BY_ID` requires numeric ID, not the space key
+- `GET_PAGE_BY_ID` takes an integer, not a string
+
+### Rate Limits
+- HTTP 429 can occur on search endpoints; honor Retry-After header
+- Throttle to ~2 requests/second with exponential backoff and jitter
+- Body expansion in CQL_SEARCH reduces result limits to 25-50
+
+### Content Format
+- Content must be Confluence storage format (XHTML), not Markdown or plain text
+- Invalid XHTML will cause page creation/update to fail
+- `CREATE_PAGE` nests body under `body.storage.value`; `UPDATE_PAGE` uses `body.value` + `body.representation`
+
+### Version Conflicts
+- Updates require exact next version number (current + 1)
+- Concurrent edits can cause version conflicts; always fetch current version immediately before updating
+- Title changes during update must still be unique within the space
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List spaces | `CONFLUENCE_GET_SPACES` | `type`, `status`, `limit` |
+| Get space by ID | `CONFLUENCE_GET_SPACE_BY_ID` | `id` |
+| Create space | `CONFLUENCE_CREATE_SPACE` | `key`, `name`, `type` |
+| Space contents | `CONFLUENCE_GET_SPACE_CONTENTS` | `spaceKey`, `type`, `status` |
+| Space properties | `CONFLUENCE_GET_SPACE_PROPERTIES` | `id`, `key` |
+| Search content | `CONFLUENCE_SEARCH_CONTENT` | `query`, `spaceKey`, `limit` |
+| CQL search | `CONFLUENCE_CQL_SEARCH` | `cql`, `expand`, `limit` |
+| List pages | `CONFLUENCE_GET_PAGES` | `spaceId`, `sort`, `limit` |
+| Get page by ID | `CONFLUENCE_GET_PAGE_BY_ID` | `id` (integer) |
+| Create page | `CONFLUENCE_CREATE_PAGE` | `title`, `spaceId`, `body` |
+| Update page | `CONFLUENCE_UPDATE_PAGE` | `id`, `title`, `body`, `version` |
+| Delete page | `CONFLUENCE_DELETE_PAGE` | `id` |
+| Child pages | `CONFLUENCE_GET_CHILD_PAGES` | `id`, `limit`, `sort` |
+| Page ancestors | `CONFLUENCE_GET_PAGE_ANCESTORS` | `id` |
+| Page labels | `CONFLUENCE_GET_LABELS_FOR_PAGE` | `id` |
+| Add label | `CONFLUENCE_ADD_CONTENT_LABEL` | content ID, label |
+| Page versions | `CONFLUENCE_GET_PAGE_VERSIONS` | `id` |
+| Space labels | `CONFLUENCE_GET_LABELS_FOR_SPACE` | space ID |
diff --git a/convertkit-automation/SKILL.md b/convertkit-automation/SKILL.md
new file mode 100644
index 0000000..595a92f
--- /dev/null
+++ b/convertkit-automation/SKILL.md
@@ -0,0 +1,192 @@
+---
+name: convertkit-automation
+description: Automate ConvertKit (Kit) tasks via Rube MCP (Composio): manage subscribers, tags, broadcasts, and broadcast stats. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# ConvertKit (Kit) Automation via Rube MCP
+
+Automate ConvertKit (now known as Kit) email marketing operations through Composio's Kit toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Kit connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `kit`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `kit`
+3. If connection is not ACTIVE, follow the returned auth link to complete Kit authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Search Subscribers
+
+**When to use**: User wants to browse, search, or filter email subscribers
+
+**Tool sequence**:
+1. `KIT_LIST_SUBSCRIBERS` - List subscribers with filters and pagination [Required]
+
+**Key parameters**:
+- `status`: Filter by status ('active' or 'inactive')
+- `email_address`: Exact email to search for
+- `created_after`/`created_before`: Date range filter (YYYY-MM-DD)
+- `updated_after`/`updated_before`: Date range filter (YYYY-MM-DD)
+- `sort_field`: Sort by 'id', 'cancelled_at', or 'updated_at'
+- `sort_order`: 'asc' or 'desc'
+- `per_page`: Results per page (min 1)
+- `after`/`before`: Cursor strings for pagination
+- `include_total_count`: Set to 'true' to get total subscriber count
+
+**Pitfalls**:
+- If `sort_field` is 'cancelled_at', the `status` must be set to 'cancelled'
+- Date filters use YYYY-MM-DD format (no time component)
+- `email_address` is an exact match; partial email search is not supported
+- Pagination uses cursor-based approach with `after`/`before` cursor strings
+- `include_total_count` is a string 'true', not a boolean
+
+### 2. Manage Subscriber Tags
+
+**When to use**: User wants to tag subscribers for segmentation
+
+**Tool sequence**:
+1. `KIT_LIST_SUBSCRIBERS` - Find subscriber ID by email [Prerequisite]
+2. `KIT_TAG_SUBSCRIBER` - Associate a subscriber with a tag [Required]
+3. `KIT_LIST_TAG_SUBSCRIBERS` - List subscribers for a specific tag [Optional]
+
+**Key parameters for tagging**:
+- `tag_id`: Numeric tag ID (required)
+- `subscriber_id`: Numeric subscriber ID (required)
+
+**Pitfalls**:
+- Both `tag_id` and `subscriber_id` must be positive integers
+- Tag IDs must reference existing tags; tags are created via the Kit web UI
+- Tagging an already-tagged subscriber is idempotent (no error)
+- Subscriber IDs are returned from LIST_SUBSCRIBERS; use `email_address` filter to find specific subscribers
+
+### 3. Unsubscribe a Subscriber
+
+**When to use**: User wants to unsubscribe a subscriber from all communications
+
+**Tool sequence**:
+1. `KIT_LIST_SUBSCRIBERS` - Find subscriber ID [Prerequisite]
+2. `KIT_DELETE_SUBSCRIBER` - Unsubscribe the subscriber [Required]
+
+**Key parameters**:
+- `id`: Subscriber ID (required, positive integer)
+
+**Pitfalls**:
+- This permanently unsubscribes the subscriber from ALL email communications
+- The subscriber's historical data is retained but they will no longer receive emails
+- Operation is idempotent; unsubscribing an already-unsubscribed subscriber succeeds without error
+- Returns empty response (HTTP 204 No Content) on success
+- Subscriber ID must exist; non-existent IDs return 404
+
+### 4. List and View Broadcasts
+
+**When to use**: User wants to browse email broadcasts or get details of a specific one
+
+**Tool sequence**:
+1. `KIT_LIST_BROADCASTS` - List all broadcasts with pagination [Required]
+2. `KIT_GET_BROADCAST` - Get detailed information for a specific broadcast [Optional]
+3. `KIT_GET_BROADCAST_STATS` - Get performance statistics for a broadcast [Optional]
+
+**Key parameters for listing**:
+- `per_page`: Results per page (1-500)
+- `after`/`before`: Cursor strings for pagination
+- `include_total_count`: Set to 'true' for total count
+
+**Key parameters for details**:
+- `id`: Broadcast ID (required, positive integer)
+
+**Pitfalls**:
+- `per_page` max is 500 for broadcasts
+- Broadcast stats are only available for sent broadcasts
+- Draft broadcasts will not have stats
+- Broadcast IDs are numeric integers
+
+### 5. Delete a Broadcast
+
+**When to use**: User wants to permanently remove a broadcast
+
+**Tool sequence**:
+1. `KIT_LIST_BROADCASTS` - Find the broadcast to delete [Prerequisite]
+2. `KIT_GET_BROADCAST` - Verify it is the correct broadcast [Optional]
+3. `KIT_DELETE_BROADCAST` - Permanently delete the broadcast [Required]
+
+**Key parameters**:
+- `id`: Broadcast ID (required)
+
+**Pitfalls**:
+- Deletion is permanent and cannot be undone
+- Deleting a sent broadcast removes it but does not unsend the emails
+- Confirm the broadcast ID before deleting
+
+## Common Patterns
+
+### Subscriber Lookup by Email
+
+```
+1. Call KIT_LIST_SUBSCRIBERS with email_address='user@example.com'
+2. Extract subscriber ID from the response
+3. Use ID for tagging, unsubscribing, or other operations
+```
+
+### Pagination
+
+Kit uses cursor-based pagination:
+- Check response for `after` cursor value
+- Pass cursor as `after` parameter in next request
+- Continue until no more cursor is returned
+- Use `include_total_count: 'true'` to track progress
+
+### Tag-Based Segmentation
+
+```
+1. Create tags in Kit web UI
+2. Use KIT_TAG_SUBSCRIBER to assign tags to subscribers
+3. Use KIT_LIST_TAG_SUBSCRIBERS to view subscribers per tag
+```
+
+## Known Pitfalls
+
+**ID Formats**:
+- Subscriber IDs: positive integers (e.g., 3887204736)
+- Tag IDs: positive integers
+- Broadcast IDs: positive integers
+- All IDs are numeric, not strings
+
+**Status Values**:
+- Subscriber statuses: 'active', 'inactive', 'cancelled'
+- Some operations are restricted by status (e.g., sorting by cancelled_at requires status='cancelled')
+
+**String vs Boolean Parameters**:
+- `include_total_count` is a string 'true', not a boolean true
+- `sort_order` is a string enum: 'asc' or 'desc'
+
+**Rate Limits**:
+- Kit API has per-account rate limits
+- Implement backoff on 429 responses
+- Bulk operations should be paced appropriately
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Cursor values are opaque strings; use exactly as returned
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List subscribers | KIT_LIST_SUBSCRIBERS | status, email_address, per_page |
+| Tag subscriber | KIT_TAG_SUBSCRIBER | tag_id, subscriber_id |
+| List tag subscribers | KIT_LIST_TAG_SUBSCRIBERS | tag_id |
+| Unsubscribe | KIT_DELETE_SUBSCRIBER | id |
+| List broadcasts | KIT_LIST_BROADCASTS | per_page, after |
+| Get broadcast | KIT_GET_BROADCAST | id |
+| Get broadcast stats | KIT_GET_BROADCAST_STATS | id |
+| Delete broadcast | KIT_DELETE_BROADCAST | id |
diff --git a/datadog-automation/SKILL.md b/datadog-automation/SKILL.md
new file mode 100644
index 0000000..8ad4bb9
--- /dev/null
+++ b/datadog-automation/SKILL.md
@@ -0,0 +1,232 @@
+---
+name: datadog-automation
+description: Automate Datadog tasks via Rube MCP (Composio): query metrics, search logs, manage monitors/dashboards, create events and downtimes. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Datadog Automation via Rube MCP
+
+Automate Datadog monitoring and observability operations through Composio's Datadog toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Datadog connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `datadog`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `datadog`
+3. If connection is not ACTIVE, follow the returned auth link to complete Datadog authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Query and Explore Metrics
+
+**When to use**: User wants to query metric data or list available metrics
+
+**Tool sequence**:
+1. `DATADOG_LIST_METRICS` - List available metric names [Optional]
+2. `DATADOG_QUERY_METRICS` - Query metric time series data [Required]
+
+**Key parameters**:
+- `query`: Datadog metric query string (e.g., `avg:system.cpu.user{host:web01}`)
+- `from`: Start timestamp (Unix epoch seconds)
+- `to`: End timestamp (Unix epoch seconds)
+- `q`: Search string for listing metrics
+
+**Pitfalls**:
+- Query syntax follows Datadog's metric query format: `aggregation:metric_name{tag_filters}`
+- `from` and `to` are Unix epoch timestamps in seconds, not milliseconds
+- Valid aggregations: `avg`, `sum`, `min`, `max`, `count`
+- Tag filters use curly braces: `{host:web01,env:prod}`
+- Time range should not exceed Datadog's retention limits for the metric type
+
+### 2. Search and Analyze Logs
+
+**When to use**: User wants to search log entries or list log indexes
+
+**Tool sequence**:
+1. `DATADOG_LIST_LOG_INDEXES` - List available log indexes [Optional]
+2. `DATADOG_SEARCH_LOGS` - Search logs with query and filters [Required]
+
+**Key parameters**:
+- `query`: Log search query using Datadog log query syntax
+- `from`: Start time (ISO 8601 or Unix timestamp)
+- `to`: End time (ISO 8601 or Unix timestamp)
+- `sort`: Sort order ('asc' or 'desc')
+- `limit`: Number of log entries to return
+
+**Pitfalls**:
+- Log queries use Datadog's log search syntax: `service:web status:error`
+- Search is limited to retained logs within the configured retention period
+- Large result sets require pagination; check for cursor/page tokens
+- Log indexes control routing and retention; filter by index if known
+
+### 3. Manage Monitors
+
+**When to use**: User wants to create, update, mute, or inspect monitors
+
+**Tool sequence**:
+1. `DATADOG_LIST_MONITORS` - List all monitors with filters [Required]
+2. `DATADOG_GET_MONITOR` - Get specific monitor details [Optional]
+3. `DATADOG_CREATE_MONITOR` - Create a new monitor [Optional]
+4. `DATADOG_UPDATE_MONITOR` - Update monitor configuration [Optional]
+5. `DATADOG_MUTE_MONITOR` - Silence a monitor temporarily [Optional]
+6. `DATADOG_UNMUTE_MONITOR` - Re-enable a muted monitor [Optional]
+
+**Key parameters**:
+- `monitor_id`: Numeric monitor ID
+- `name`: Monitor display name
+- `type`: Monitor type ('metric alert', 'service check', 'log alert', 'query alert', etc.)
+- `query`: Monitor query defining the alert condition
+- `message`: Notification message with @mentions
+- `tags`: Array of tag strings
+- `thresholds`: Alert threshold values (`critical`, `warning`, `ok`)
+
+**Pitfalls**:
+- Monitor `type` must match the query type; mismatches cause creation failures
+- `message` supports @mentions for notifications (e.g., `@slack-channel`, `@pagerduty`)
+- Thresholds vary by monitor type; metric monitors need `critical` at minimum
+- Muting a monitor suppresses notifications but the monitor still evaluates
+- Monitor IDs are numeric integers
+
+### 4. Manage Dashboards
+
+**When to use**: User wants to list, view, update, or delete dashboards
+
+**Tool sequence**:
+1. `DATADOG_LIST_DASHBOARDS` - List all dashboards [Required]
+2. `DATADOG_GET_DASHBOARD` - Get full dashboard definition [Optional]
+3. `DATADOG_UPDATE_DASHBOARD` - Update dashboard layout or widgets [Optional]
+4. `DATADOG_DELETE_DASHBOARD` - Remove a dashboard (irreversible) [Optional]
+
+**Key parameters**:
+- `dashboard_id`: Dashboard identifier string
+- `title`: Dashboard title
+- `layout_type`: 'ordered' (grid) or 'free' (freeform positioning)
+- `widgets`: Array of widget definition objects
+- `description`: Dashboard description
+
+**Pitfalls**:
+- Dashboard IDs are alphanumeric strings (e.g., 'abc-def-ghi'), not numeric
+- `layout_type` cannot be changed after creation; must recreate the dashboard
+- Widget definitions are complex nested objects; get existing dashboard first to understand structure
+- DELETE is permanent; there is no undo
+
+### 5. Create Events and Manage Downtimes
+
+**When to use**: User wants to post events or schedule maintenance downtimes
+
+**Tool sequence**:
+1. `DATADOG_LIST_EVENTS` - List existing events [Optional]
+2. `DATADOG_CREATE_EVENT` - Post a new event [Required]
+3. `DATADOG_CREATE_DOWNTIME` - Schedule a maintenance downtime [Optional]
+
+**Key parameters for events**:
+- `title`: Event title
+- `text`: Event body text (supports markdown)
+- `alert_type`: Event severity ('error', 'warning', 'info', 'success')
+- `tags`: Array of tag strings
+
+**Key parameters for downtimes**:
+- `scope`: Tag scope for the downtime (e.g., `host:web01`)
+- `start`: Start time (Unix epoch)
+- `end`: End time (Unix epoch; omit for indefinite)
+- `message`: Downtime description
+- `monitor_id`: Specific monitor to downtime (optional, omit for scope-based)
+
+**Pitfalls**:
+- Event `text` supports Datadog's markdown format including @mentions
+- Downtimes scope uses tag syntax: `host:web01`, `env:staging`
+- Omitting `end` creates an indefinite downtime; always set an end time for maintenance
+- Downtime `monitor_id` narrows to a single monitor; scope applies to all matching monitors
+
+### 6. Manage Hosts and Traces
+
+**When to use**: User wants to list infrastructure hosts or inspect distributed traces
+
+**Tool sequence**:
+1. `DATADOG_LIST_HOSTS` - List all reporting hosts [Required]
+2. `DATADOG_GET_TRACE_BY_ID` - Get a specific distributed trace [Optional]
+
+**Key parameters**:
+- `filter`: Host search filter string
+- `sort_field`: Sort hosts by field (e.g., 'name', 'apps', 'cpu')
+- `sort_dir`: Sort direction ('asc' or 'desc')
+- `trace_id`: Distributed trace ID for trace lookup
+
+**Pitfalls**:
+- Host list includes all hosts reporting to Datadog within the retention window
+- Trace IDs are long numeric strings; ensure exact match
+- Hosts that stop reporting are retained for a configured period before removal
+
+## Common Patterns
+
+### Monitor Query Syntax
+
+**Metric alerts**:
+```
+avg(last_5m):avg:system.cpu.user{env:prod} > 90
+```
+
+**Log alerts**:
+```
+logs("service:web status:error").index("main").rollup("count").last("5m") > 10
+```
+
+### Tag Filtering
+
+- Tags use `key:value` format: `host:web01`, `env:prod`, `service:api`
+- Multiple tags: `{host:web01,env:prod}` (AND logic)
+- Wildcard: `host:web*`
+
+### Pagination
+
+- Use `page` and `page_size` or offset-based pagination depending on endpoint
+- Check response for total count to determine if more pages exist
+- Continue until all results are retrieved
+
+## Known Pitfalls
+
+**Timestamps**:
+- Most endpoints use Unix epoch seconds (not milliseconds)
+- Some endpoints accept ISO 8601; check tool schema
+- Time ranges should be reasonable (not years of data)
+
+**Query Syntax**:
+- Metric queries: `aggregation:metric{tags}`
+- Log queries: `field:value` pairs
+- Monitor queries vary by type; check Datadog documentation
+
+**Rate Limits**:
+- Datadog API has per-endpoint rate limits
+- Implement backoff on 429 responses
+- Batch operations where possible
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Query metrics | DATADOG_QUERY_METRICS | query, from, to |
+| List metrics | DATADOG_LIST_METRICS | q |
+| Search logs | DATADOG_SEARCH_LOGS | query, from, to, limit |
+| List log indexes | DATADOG_LIST_LOG_INDEXES | (none) |
+| List monitors | DATADOG_LIST_MONITORS | tags |
+| Get monitor | DATADOG_GET_MONITOR | monitor_id |
+| Create monitor | DATADOG_CREATE_MONITOR | name, type, query, message |
+| Update monitor | DATADOG_UPDATE_MONITOR | monitor_id |
+| Mute monitor | DATADOG_MUTE_MONITOR | monitor_id |
+| Unmute monitor | DATADOG_UNMUTE_MONITOR | monitor_id |
+| List dashboards | DATADOG_LIST_DASHBOARDS | (none) |
+| Get dashboard | DATADOG_GET_DASHBOARD | dashboard_id |
+| Update dashboard | DATADOG_UPDATE_DASHBOARD | dashboard_id, title, widgets |
+| Delete dashboard | DATADOG_DELETE_DASHBOARD | dashboard_id |
+| List events | DATADOG_LIST_EVENTS | start, end |
+| Create event | DATADOG_CREATE_EVENT | title, text, alert_type |
+| Create downtime | DATADOG_CREATE_DOWNTIME | scope, start, end |
+| List hosts | DATADOG_LIST_HOSTS | filter, sort_field |
+| Get trace | DATADOG_GET_TRACE_BY_ID | trace_id |
diff --git a/discord-automation/SKILL.md b/discord-automation/SKILL.md
new file mode 100644
index 0000000..cacaa5f
--- /dev/null
+++ b/discord-automation/SKILL.md
@@ -0,0 +1,184 @@
+---
+name: discord-automation
+description: Automate Discord tasks via Rube MCP (Composio): messages, channels, roles, webhooks, reactions. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Discord Automation via Rube MCP
+
+Automate Discord operations through Composio's Discord/Discordbot toolkits via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Discord connection via `RUBE_MANAGE_CONNECTIONS` with toolkits `discord` and `discordbot`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `discordbot` (bot operations) or `discord` (user operations)
+3. If connection is not ACTIVE, follow the returned auth link to complete Discord auth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send Messages
+
+**When to use**: User wants to send messages to channels or DMs
+
+**Tool sequence**:
+1. `DISCORD_LIST_MY_GUILDS` - List guilds the bot belongs to [Prerequisite]
+2. `DISCORDBOT_LIST_GUILD_CHANNELS` - List channels in a guild [Prerequisite]
+3. `DISCORDBOT_CREATE_MESSAGE` - Send a message [Required]
+4. `DISCORDBOT_UPDATE_MESSAGE` - Edit a sent message [Optional]
+
+**Key parameters**:
+- `channel_id`: Channel snowflake ID
+- `content`: Message text (max 2000 characters)
+- `embeds`: Array of embed objects for rich content
+- `guild_id`: Guild ID for channel listing
+
+**Pitfalls**:
+- Bot must have SEND_MESSAGES permission in the channel
+- High-frequency sends can hit per-route rate limits; respect Retry-After headers
+- Only messages sent by the same bot can be edited
+
+### 2. Send Direct Messages
+
+**When to use**: User wants to DM a Discord user
+
+**Tool sequence**:
+1. `DISCORDBOT_CREATE_DM` - Create or get DM channel [Required]
+2. `DISCORDBOT_CREATE_MESSAGE` - Send message to DM channel [Required]
+
+**Key parameters**:
+- `recipient_id`: User snowflake ID for DM
+- `channel_id`: DM channel ID from CREATE_DM
+
+**Pitfalls**:
+- Cannot DM users who have DMs disabled or have blocked the bot
+- CREATE_DM returns existing channel if one already exists
+
+### 3. Manage Roles
+
+**When to use**: User wants to create, assign, or remove roles
+
+**Tool sequence**:
+1. `DISCORDBOT_CREATE_GUILD_ROLE` - Create a new role [Optional]
+2. `DISCORDBOT_ADD_GUILD_MEMBER_ROLE` - Assign role to member [Optional]
+3. `DISCORDBOT_DELETE_GUILD_ROLE` - Delete a role [Optional]
+4. `DISCORDBOT_GET_GUILD_MEMBER` - Get member details [Optional]
+5. `DISCORDBOT_UPDATE_GUILD_MEMBER` - Update member (roles, nick, etc.) [Optional]
+
+**Key parameters**:
+- `guild_id`: Guild snowflake ID
+- `user_id`: User snowflake ID
+- `role_id`: Role snowflake ID
+- `name`: Role name
+- `permissions`: Bitwise permission value
+- `color`: RGB color integer
+
+**Pitfalls**:
+- Role assignment requires MANAGE_ROLES permission
+- Target role must be lower in hierarchy than bot's highest role
+- DELETE permanently removes the role from all members
+
+### 4. Manage Webhooks
+
+**When to use**: User wants to create or use webhooks for external integrations
+
+**Tool sequence**:
+1. `DISCORDBOT_GET_GUILD_WEBHOOKS` / `DISCORDBOT_LIST_CHANNEL_WEBHOOKS` - List webhooks [Optional]
+2. `DISCORDBOT_CREATE_WEBHOOK` - Create a new webhook [Optional]
+3. `DISCORDBOT_EXECUTE_WEBHOOK` - Send message via webhook [Optional]
+4. `DISCORDBOT_UPDATE_WEBHOOK` - Update webhook settings [Optional]
+
+**Key parameters**:
+- `webhook_id`: Webhook ID
+- `webhook_token`: Webhook secret token
+- `channel_id`: Channel for webhook creation
+- `name`: Webhook name
+- `content`/`embeds`: Message content for execution
+
+**Pitfalls**:
+- Webhook tokens are secrets; handle securely
+- Webhooks can post with custom username and avatar per message
+- MANAGE_WEBHOOKS permission required for creation
+
+### 5. Manage Reactions
+
+**When to use**: User wants to view or manage message reactions
+
+**Tool sequence**:
+1. `DISCORDBOT_LIST_MESSAGE_REACTIONS_BY_EMOJI` - List users who reacted [Optional]
+2. `DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS` - Remove all reactions [Optional]
+3. `DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS_BY_EMOJI` - Remove specific emoji reactions [Optional]
+4. `DISCORDBOT_DELETE_USER_MESSAGE_REACTION` - Remove specific user's reaction [Optional]
+
+**Key parameters**:
+- `channel_id`: Channel ID
+- `message_id`: Message snowflake ID
+- `emoji_name`: URL-encoded emoji or `name:id` for custom emojis
+- `user_id`: User ID for specific reaction removal
+
+**Pitfalls**:
+- Unicode emojis must be URL-encoded (e.g., '%F0%9F%91%8D' for thumbs up)
+- Custom emojis use `name:id` format
+- DELETE_ALL requires MANAGE_MESSAGES permission
+
+## Common Patterns
+
+### Snowflake IDs
+
+Discord uses snowflake IDs (64-bit integers as strings) for all entities:
+- Guilds, channels, users, roles, messages, webhooks
+
+### Permission Bitfields
+
+Permissions are combined using bitwise OR:
+- SEND_MESSAGES = 0x800
+- MANAGE_ROLES = 0x10000000
+- MANAGE_MESSAGES = 0x2000
+- ADMINISTRATOR = 0x8
+
+### Pagination
+
+- Most list endpoints support `limit`, `before`, `after` parameters
+- Messages: max 100 per request
+- Reactions: max 100 per request, use `after` for pagination
+
+## Known Pitfalls
+
+**Bot vs User Tokens**:
+- `discordbot` toolkit uses bot tokens; `discord` uses user OAuth
+- Bot operations are preferred for automation
+
+**Rate Limits**:
+- Discord enforces per-route rate limits
+- Respect `Retry-After` headers on 429 responses
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List guilds | DISCORD_LIST_MY_GUILDS | (none) |
+| List channels | DISCORDBOT_LIST_GUILD_CHANNELS | guild_id |
+| Send message | DISCORDBOT_CREATE_MESSAGE | channel_id, content |
+| Edit message | DISCORDBOT_UPDATE_MESSAGE | channel_id, message_id |
+| Get messages | DISCORDBOT_LIST_MESSAGES | channel_id, limit |
+| Create DM | DISCORDBOT_CREATE_DM | recipient_id |
+| Create role | DISCORDBOT_CREATE_GUILD_ROLE | guild_id, name |
+| Assign role | DISCORDBOT_ADD_GUILD_MEMBER_ROLE | guild_id, user_id, role_id |
+| Delete role | DISCORDBOT_DELETE_GUILD_ROLE | guild_id, role_id |
+| Get member | DISCORDBOT_GET_GUILD_MEMBER | guild_id, user_id |
+| Update member | DISCORDBOT_UPDATE_GUILD_MEMBER | guild_id, user_id |
+| Get guild | DISCORDBOT_GET_GUILD | guild_id |
+| Create webhook | DISCORDBOT_CREATE_WEBHOOK | channel_id, name |
+| Execute webhook | DISCORDBOT_EXECUTE_WEBHOOK | webhook_id, webhook_token |
+| List webhooks | DISCORDBOT_GET_GUILD_WEBHOOKS | guild_id |
+| Get reactions | DISCORDBOT_LIST_MESSAGE_REACTIONS_BY_EMOJI | channel_id, message_id, emoji_name |
+| Clear reactions | DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS | channel_id, message_id |
+| Test auth | DISCORDBOT_TEST_AUTH | (none) |
+| Get channel | DISCORDBOT_GET_CHANNEL | channel_id |
diff --git a/docusign-automation/SKILL.md b/docusign-automation/SKILL.md
new file mode 100644
index 0000000..95e32b0
--- /dev/null
+++ b/docusign-automation/SKILL.md
@@ -0,0 +1,205 @@
+---
+name: docusign-automation
+description: Automate DocuSign tasks via Rube MCP (Composio): templates, envelopes, signatures, document management. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# DocuSign Automation via Rube MCP
+
+Automate DocuSign e-signature workflows through Composio's DocuSign toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active DocuSign connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `docusign`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `docusign`
+3. If connection is not ACTIVE, follow the returned auth link to complete DocuSign OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Browse and Select Templates
+
+**When to use**: User wants to find available document templates for sending
+
+**Tool sequence**:
+1. `DOCUSIGN_LIST_ALL_TEMPLATES` - List all available templates [Required]
+2. `DOCUSIGN_GET_TEMPLATE` - Get detailed template information [Optional]
+
+**Key parameters**:
+- For listing: Optional search/filter parameters
+- For details: `templateId` (from list results)
+- Response includes template `templateId`, `name`, `description`, roles, and fields
+
+**Pitfalls**:
+- Template IDs are GUIDs (e.g., '12345678-abcd-1234-efgh-123456789012')
+- Templates define recipient roles with signing tabs; understand roles before creating envelopes
+- Large template libraries require pagination; check for continuation tokens
+- Template access depends on account permissions
+
+### 2. Create and Send Envelopes from Templates
+
+**When to use**: User wants to send documents for signature using a pre-built template
+
+**Tool sequence**:
+1. `DOCUSIGN_LIST_ALL_TEMPLATES` - Find the template to use [Prerequisite]
+2. `DOCUSIGN_GET_TEMPLATE` - Review template roles and fields [Optional]
+3. `DOCUSIGN_CREATE_ENVELOPE_FROM_TEMPLATE` - Create the envelope [Required]
+4. `DOCUSIGN_SEND_ENVELOPE` - Send the envelope for signing [Required]
+
+**Key parameters**:
+- For CREATE_ENVELOPE_FROM_TEMPLATE:
+ - `templateId`: Template to use
+ - `templateRoles`: Array of role assignments with `roleName`, `name`, `email`
+ - `status`: 'created' (draft) or 'sent' (send immediately)
+ - `emailSubject`: Custom subject line for the signing email
+ - `emailBlurb`: Custom message in the signing email
+- For SEND_ENVELOPE:
+ - `envelopeId`: Envelope ID from creation response
+
+**Pitfalls**:
+- `templateRoles` must match the role names defined in the template exactly (case-sensitive)
+- Setting `status` to 'sent' during creation sends immediately; use 'created' for drafts
+- If status is 'sent' at creation, no need to call SEND_ENVELOPE separately
+- Each role requires at minimum `roleName`, `name`, and `email`
+- `emailSubject` overrides the template's default email subject
+
+### 3. Monitor Envelope Status
+
+**When to use**: User wants to check the status of sent envelopes or track signing progress
+
+**Tool sequence**:
+1. `DOCUSIGN_GET_ENVELOPE` - Get envelope details and status [Required]
+
+**Key parameters**:
+- `envelopeId`: Envelope identifier (GUID)
+- Response includes `status`, `recipients`, `sentDateTime`, `completedDateTime`
+
+**Pitfalls**:
+- Envelope statuses: 'created', 'sent', 'delivered', 'signed', 'completed', 'declined', 'voided'
+- 'delivered' means the email was opened, not that the document was signed
+- 'completed' means all recipients have signed
+- Recipients array shows individual signing status per recipient
+- Envelope IDs are GUIDs; always resolve from creation or search results
+
+### 4. Add Templates to Existing Envelopes
+
+**When to use**: User wants to add additional documents or templates to an existing envelope
+
+**Tool sequence**:
+1. `DOCUSIGN_GET_ENVELOPE` - Verify envelope exists and is in draft state [Prerequisite]
+2. `DOCUSIGN_ADD_TEMPLATES_TO_DOCUMENT_IN_ENVELOPE` - Add template to envelope [Required]
+
+**Key parameters**:
+- `envelopeId`: Target envelope ID
+- `documentId`: Document ID within the envelope
+- `templateId`: Template to add
+
+**Pitfalls**:
+- Envelope must be in 'created' (draft) status to add templates
+- Cannot add templates to already-sent envelopes
+- Document IDs are sequential within an envelope (starting from '1')
+- Adding a template merges its fields and roles into the existing envelope
+
+### 5. Manage Envelope Lifecycle
+
+**When to use**: User wants to send, void, or manage draft envelopes
+
+**Tool sequence**:
+1. `DOCUSIGN_GET_ENVELOPE` - Check current envelope status [Prerequisite]
+2. `DOCUSIGN_SEND_ENVELOPE` - Send a draft envelope [Optional]
+
+**Key parameters**:
+- `envelopeId`: Envelope to manage
+- For sending: envelope must be in 'created' status with all required recipients
+
+**Pitfalls**:
+- Only 'created' (draft) envelopes can be sent
+- Sent envelopes cannot be unsent; they can only be voided
+- Voiding an envelope notifies all recipients
+- All required recipients must have valid email addresses before sending
+
+## Common Patterns
+
+### ID Resolution
+
+**Template name -> Template ID**:
+```
+1. Call DOCUSIGN_LIST_ALL_TEMPLATES
+2. Find template by name in results
+3. Extract templateId (GUID format)
+```
+
+**Envelope tracking**:
+```
+1. Store envelopeId from CREATE_ENVELOPE_FROM_TEMPLATE response
+2. Call DOCUSIGN_GET_ENVELOPE periodically to check status
+3. Check recipient-level status for individual signing progress
+```
+
+### Template Role Mapping
+
+When creating an envelope from a template:
+```
+1. Call DOCUSIGN_GET_TEMPLATE to see defined roles
+2. Map each role to actual recipients:
+ {
+ "roleName": "Signer 1", // Must match template role name exactly
+ "name": "John Smith",
+ "email": "john@example.com"
+ }
+3. Include ALL required roles in templateRoles array
+```
+
+### Envelope Status Flow
+
+```
+created (draft) -> sent -> delivered -> signed -> completed
+ \-> declined
+ \-> voided (by sender)
+```
+
+## Known Pitfalls
+
+**Template Roles**:
+- Role names are case-sensitive; must match template definition exactly
+- All required roles must be assigned when creating an envelope
+- Missing role assignments cause envelope creation to fail
+
+**Envelope Status**:
+- 'delivered' means email opened, NOT document signed
+- 'completed' is the final successful state (all parties signed)
+- Status transitions are one-way; cannot revert to previous states
+
+**GUIDs**:
+- All DocuSign IDs (templates, envelopes) are GUID format
+- Always resolve names to GUIDs via list/search endpoints
+- Do not hardcode GUIDs; they are unique per account
+
+**Rate Limits**:
+- DocuSign API has per-account rate limits
+- Bulk envelope creation should be throttled
+- Polling envelope status should use reasonable intervals (30-60 seconds)
+
+**Response Parsing**:
+- Response data may be nested under `data` key
+- Recipient information is nested within envelope response
+- Date fields use ISO 8601 format
+- Parse defensively with fallbacks for optional fields
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List templates | DOCUSIGN_LIST_ALL_TEMPLATES | (optional filters) |
+| Get template | DOCUSIGN_GET_TEMPLATE | templateId |
+| Create envelope | DOCUSIGN_CREATE_ENVELOPE_FROM_TEMPLATE | templateId, templateRoles, status |
+| Send envelope | DOCUSIGN_SEND_ENVELOPE | envelopeId |
+| Get envelope status | DOCUSIGN_GET_ENVELOPE | envelopeId |
+| Add template to envelope | DOCUSIGN_ADD_TEMPLATES_TO_DOCUMENT_IN_ENVELOPE | envelopeId, documentId, templateId |
diff --git a/dropbox-automation/SKILL.md b/dropbox-automation/SKILL.md
new file mode 100644
index 0000000..3daf25e
--- /dev/null
+++ b/dropbox-automation/SKILL.md
@@ -0,0 +1,227 @@
+---
+name: dropbox-automation
+description: Automate Dropbox file management, sharing, search, uploads, downloads, and folder operations via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Dropbox Automation via Rube MCP
+
+Automate Dropbox operations including file upload/download, search, folder management, sharing links, batch operations, and metadata retrieval through Composio's Dropbox toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Dropbox connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `dropbox`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `dropbox`
+3. If connection is not ACTIVE, follow the returned auth link to complete Dropbox OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search for Files and Folders
+
+**When to use**: User wants to find files or folders by name, content, or type
+
+**Tool sequence**:
+1. `DROPBOX_SEARCH_FILE_OR_FOLDER` - Search by query string with optional path scope and filters [Required]
+2. `DROPBOX_SEARCH_CONTINUE` - Paginate through additional results using cursor [Required if has_more]
+3. `DROPBOX_GET_METADATA` - Validate and get canonical path for a search result [Optional]
+4. `DROPBOX_READ_FILE` - Read file content to verify it is the intended document [Optional]
+
+**Key parameters**:
+- `query`: Search string (case-insensitive, 1+ non-whitespace characters)
+- `options.path`: Scope search to a folder (e.g., `"/Documents"`); empty string for root
+- `options.file_categories`: Filter by type (`"image"`, `"document"`, `"pdf"`, `"folder"`, etc.)
+- `options.file_extensions`: Filter by extension (e.g., `["jpg", "png"]`)
+- `options.filename_only`: Set `true` to match filenames only (not content)
+- `options.max_results`: Results per page (default 100, max 1000)
+
+**Pitfalls**:
+- Search returns `has_more: true` with a `cursor` when more results exist; MUST continue to avoid silently missing matches
+- Maximum 10,000 matches total across all pages of search + search_continue
+- `DROPBOX_GET_METADATA` returned `path_display` may differ in casing from user input; always use the returned canonical path
+- File content from `DROPBOX_READ_FILE` may be returned as base64-encoded `file_content_bytes`; decode before parsing
+
+### 2. Upload and Download Files
+
+**When to use**: User wants to upload files to Dropbox or download files from it
+
+**Tool sequence**:
+1. `DROPBOX_UPLOAD_FILE` - Upload a file to a specified path [Required for upload]
+2. `DROPBOX_READ_FILE` - Download/read a file from Dropbox [Required for download]
+3. `DROPBOX_DOWNLOAD_ZIP` - Download an entire folder as a zip file [Optional]
+4. `DROPBOX_SAVE_URL` - Save a file from a public URL directly to Dropbox [Optional]
+5. `DROPBOX_GET_SHARED_LINK_FILE` - Download a file from a shared link URL [Optional]
+6. `DROPBOX_EXPORT_FILE` - Export non-downloadable files like Dropbox Paper to markdown/HTML [Optional]
+
+**Key parameters**:
+- `path`: Dropbox path (must start with `/`, e.g., `"/Documents/report.pdf"`)
+- `mode`: `"add"` (default, fail on conflict) or `"overwrite"` for uploads
+- `autorename`: `true` to auto-rename on conflict instead of failing
+- `content`: FileUploadable object with `s3key`, `mimetype`, and `name` for uploads
+- `url`: Public URL for `DROPBOX_SAVE_URL`
+- `export_format`: `"markdown"`, `"html"`, or `"plain_text"` for Paper docs
+
+**Pitfalls**:
+- `DROPBOX_SAVE_URL` is asynchronous and may take up to 15 minutes for large files
+- `DROPBOX_DOWNLOAD_ZIP` folder must be under 20 GB with no single file over 4 GB and fewer than 10,000 entries
+- `DROPBOX_READ_FILE` content may be base64-encoded; check response format
+- Shared link downloads via `DROPBOX_GET_SHARED_LINK_FILE` may require `link_password` for protected links
+
+### 3. Share Files and Manage Links
+
+**When to use**: User wants to create sharing links or manage existing shared links
+
+**Tool sequence**:
+1. `DROPBOX_GET_METADATA` - Confirm file/folder exists and get canonical path [Prerequisite]
+2. `DROPBOX_LIST_SHARED_LINKS` - Check for existing shared links to avoid duplicates [Prerequisite]
+3. `DROPBOX_CREATE_SHARED_LINK` - Create a new shared link [Required]
+4. `DROPBOX_GET_SHARED_LINK_METADATA` - Resolve a shared link URL to metadata [Optional]
+5. `DROPBOX_LIST_SHARED_FOLDERS` - List all shared folders the user has access to [Optional]
+
+**Key parameters**:
+- `path`: File or folder path for link creation
+- `settings.audience`: `"public"`, `"team"`, or `"no_one"`
+- `settings.access`: `"viewer"` or `"editor"`
+- `settings.expires`: ISO 8601 expiration date (e.g., `"2026-12-31T23:59:59Z"`)
+- `settings.require_password` / `settings.link_password`: Password protection
+- `settings.allow_download`: Boolean for download permission
+- `direct_only`: For `LIST_SHARED_LINKS`, set `true` to only return direct links (not parent folder links)
+
+**Pitfalls**:
+- `DROPBOX_CREATE_SHARED_LINK` fails with 409 Conflict if a shared link already exists for the path; check with `DROPBOX_LIST_SHARED_LINKS` first
+- Always validate path with `DROPBOX_GET_METADATA` before creating links to avoid `path/not_found` errors
+- Reuse existing links from `DROPBOX_LIST_SHARED_LINKS` instead of creating duplicates
+- `requested_visibility` is deprecated; use `audience` for newer implementations
+
+### 4. Manage Folders (Create, Move, Delete)
+
+**When to use**: User wants to create, move, rename, or delete files and folders
+
+**Tool sequence**:
+1. `DROPBOX_CREATE_FOLDER` - Create a single folder [Required for create]
+2. `DROPBOX_CREATE_FOLDER_BATCH` - Create multiple folders at once [Optional]
+3. `DROPBOX_MOVE_FILE_OR_FOLDER` - Move or rename a single file/folder [Required for move]
+4. `DROPBOX_MOVE_BATCH` - Move multiple items at once [Optional]
+5. `DROPBOX_DELETE_FILE_OR_FOLDER` - Delete a single file or folder [Required for delete]
+6. `DROPBOX_DELETE_BATCH` - Delete multiple items at once [Optional]
+7. `DROPBOX_COPY_FILE_OR_FOLDER` - Copy a file or folder to a new location [Optional]
+8. `DROPBOX_CHECK_MOVE_BATCH` / `DROPBOX_CHECK_FOLDER_BATCH` - Poll async batch job status [Required for batch ops]
+
+**Key parameters**:
+- `path`: Target path (must start with `/`, case-sensitive)
+- `from_path` / `to_path`: Source and destination for move/copy operations
+- `autorename`: `true` to auto-rename on conflict
+- `entries`: Array of `{from_path, to_path}` for batch moves; array of paths for batch creates
+- `allow_shared_folder`: Set `true` to allow moving shared folders
+- `allow_ownership_transfer`: Set `true` if move changes ownership
+
+**Pitfalls**:
+- All paths are case-sensitive and must start with `/`
+- Paths must NOT end with `/` or whitespace
+- Batch operations may be asynchronous; poll with `DROPBOX_CHECK_MOVE_BATCH` or `DROPBOX_CHECK_FOLDER_BATCH`
+- `DROPBOX_FILES_MOVE_BATCH` (v1) has "all or nothing" behavior - if any entry fails, entire batch fails
+- `DROPBOX_MOVE_BATCH` (v2) is preferred over `DROPBOX_FILES_MOVE_BATCH` (v1)
+- Maximum 1000 entries per batch delete/move; 10,000 paths per batch folder create
+- Case-only renaming is not supported in batch move operations
+
+### 5. List Folder Contents
+
+**When to use**: User wants to browse or enumerate files in a Dropbox folder
+
+**Tool sequence**:
+1. `DROPBOX_LIST_FILES_IN_FOLDER` - List contents of a folder [Required]
+2. `DROPBOX_LIST_FOLDERS` - Alternative folder listing with deleted entries support [Optional]
+3. `DROPBOX_GET_METADATA` - Get details for a specific item [Optional]
+
+**Key parameters**:
+- `path`: Folder path (empty string `""` for root)
+- `recursive`: `true` to list all nested contents
+- `limit`: Max results per request (default/max 2000)
+- `include_deleted`: `true` to include deleted but recoverable items
+- `include_media_info`: `true` to get photo/video metadata
+
+**Pitfalls**:
+- Use empty string `""` for root folder, not `"/"`
+- Recursive listings can be very large; use `limit` to control page size
+- Results may paginate via cursor even with small limits
+- `DROPBOX_LIST_FILES_IN_FOLDER` returns 409 Conflict with `path/not_found` for incorrect paths
+
+## Common Patterns
+
+### ID Resolution
+- **Path-based**: Most Dropbox tools use path strings (e.g., `"/Documents/file.pdf"`)
+- **ID-based**: Some tools accept `id:...` format (e.g., `"id:4g0reWVRsAAAAAAAAAAAQ"`)
+- **Canonical path**: Always use `path_display` or `path_lower` from `DROPBOX_GET_METADATA` responses for subsequent calls
+- **Shared link URL**: Use `DROPBOX_GET_SHARED_LINK_METADATA` to resolve URLs to paths/IDs
+
+### Pagination
+Dropbox uses cursor-based pagination across most endpoints:
+- Search: Follow `has_more` + `cursor` with `DROPBOX_SEARCH_CONTINUE` (max 10,000 total matches)
+- Folder listing: Follow cursor from response until no more pages
+- Shared links: Follow `has_more` + `cursor` in `DROPBOX_LIST_SHARED_LINKS`
+- Batch job status: Poll with `DROPBOX_CHECK_MOVE_BATCH` / `DROPBOX_CHECK_FOLDER_BATCH`
+
+### Async Operations
+Several Dropbox operations run asynchronously:
+- `DROPBOX_SAVE_URL` - returns job ID; poll or set `wait: true` (up to 120s default)
+- `DROPBOX_MOVE_BATCH` / `DROPBOX_FILES_MOVE_BATCH` - may return job ID
+- `DROPBOX_CREATE_FOLDER_BATCH` - may return job ID
+- `DROPBOX_DELETE_BATCH` - returns job ID
+
+## Known Pitfalls
+
+### Path Formats
+- All paths must start with `/` (except empty string for root in some endpoints)
+- Paths must NOT end with `/` or contain trailing whitespace
+- Paths are case-sensitive for write operations
+- `path_display` from API may differ in casing from user input; always prefer API-returned paths
+
+### Rate Limits
+- Dropbox API has per-endpoint rate limits; batch operations help reduce call count
+- Search is limited to 10,000 total matches across all pagination
+- `DROPBOX_SAVE_URL` has a 15-minute timeout for large files
+
+### File Content
+- `DROPBOX_READ_FILE` may return content as base64-encoded `file_content_bytes`
+- Non-downloadable files (Dropbox Paper, Google Docs) require `DROPBOX_EXPORT_FILE` instead
+- Download URLs from shared links require proper authentication headers
+
+### Sharing
+- Creating a shared link when one already exists returns a 409 Conflict error
+- Always check `DROPBOX_LIST_SHARED_LINKS` before creating new links
+- Shared folder access may not appear in standard path listings; use `DROPBOX_LIST_SHARED_FOLDERS`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search files | `DROPBOX_SEARCH_FILE_OR_FOLDER` | `query`, `options.path` |
+| Continue search | `DROPBOX_SEARCH_CONTINUE` | `cursor` |
+| List folder | `DROPBOX_LIST_FILES_IN_FOLDER` | `path`, `recursive`, `limit` |
+| List folders | `DROPBOX_LIST_FOLDERS` | `path`, `recursive` |
+| Get metadata | `DROPBOX_GET_METADATA` | `path` |
+| Read/download file | `DROPBOX_READ_FILE` | `path` |
+| Upload file | `DROPBOX_UPLOAD_FILE` | `path`, `content`, `mode` |
+| Save URL to Dropbox | `DROPBOX_SAVE_URL` | `path`, `url` |
+| Download folder zip | `DROPBOX_DOWNLOAD_ZIP` | `path` |
+| Export Paper doc | `DROPBOX_EXPORT_FILE` | `path`, `export_format` |
+| Download shared link | `DROPBOX_GET_SHARED_LINK_FILE` | `url` |
+| Create shared link | `DROPBOX_CREATE_SHARED_LINK` | `path`, `settings` |
+| List shared links | `DROPBOX_LIST_SHARED_LINKS` | `path`, `direct_only` |
+| Shared link metadata | `DROPBOX_GET_SHARED_LINK_METADATA` | `url` |
+| List shared folders | `DROPBOX_LIST_SHARED_FOLDERS` | `limit` |
+| Create folder | `DROPBOX_CREATE_FOLDER` | `path` |
+| Create folders batch | `DROPBOX_CREATE_FOLDER_BATCH` | `paths` |
+| Move file/folder | `DROPBOX_MOVE_FILE_OR_FOLDER` | `from_path`, `to_path` |
+| Move batch | `DROPBOX_MOVE_BATCH` | `entries` |
+| Delete file/folder | `DROPBOX_DELETE_FILE_OR_FOLDER` | `path` |
+| Delete batch | `DROPBOX_DELETE_BATCH` | `entries` |
+| Copy file/folder | `DROPBOX_COPY_FILE_OR_FOLDER` | `from_path`, `to_path` |
+| Check batch status | `DROPBOX_CHECK_MOVE_BATCH` | `async_job_id` |
diff --git a/figma-automation/SKILL.md b/figma-automation/SKILL.md
new file mode 100644
index 0000000..02a8119
--- /dev/null
+++ b/figma-automation/SKILL.md
@@ -0,0 +1,178 @@
+---
+name: figma-automation
+description: Automate Figma tasks via Rube MCP (Composio): files, components, design tokens, comments, exports. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Figma Automation via Rube MCP
+
+Automate Figma operations through Composio's Figma toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Figma connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `figma`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `figma`
+3. If connection is not ACTIVE, follow the returned auth link to complete Figma auth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Get File Data and Components
+
+**When to use**: User wants to inspect Figma design files or extract component information
+
+**Tool sequence**:
+1. `FIGMA_DISCOVER_FIGMA_RESOURCES` - Extract IDs from Figma URLs [Prerequisite]
+2. `FIGMA_GET_FILE_JSON` - Get file data (simplified by default) [Required]
+3. `FIGMA_GET_FILE_NODES` - Get specific node data [Optional]
+4. `FIGMA_GET_FILE_COMPONENTS` - List published components [Optional]
+5. `FIGMA_GET_FILE_COMPONENT_SETS` - List component sets [Optional]
+
+**Key parameters**:
+- `file_key`: File key from URL (e.g., 'abc123XYZ' from figma.com/design/abc123XYZ/...)
+- `ids`: Comma-separated node IDs (NOT an array)
+- `depth`: Tree traversal depth (2 for pages and top-level children)
+- `simplify`: True for AI-friendly format (70%+ size reduction)
+
+**Pitfalls**:
+- Only supports Design files; FigJam boards and Slides return 400 errors
+- `ids` must be a comma-separated string, not an array
+- Node IDs may be dash-formatted (1-541) in URLs but need colon format (1:541) for API
+- Broad ids/depth can trigger oversized payloads (413); narrow scope or reduce depth
+- Response data may be in `data_preview` instead of `data`
+
+### 2. Export and Render Images
+
+**When to use**: User wants to export design assets as images
+
+**Tool sequence**:
+1. `FIGMA_GET_FILE_JSON` - Find node IDs to export [Prerequisite]
+2. `FIGMA_RENDER_IMAGES_OF_FILE_NODES` - Render nodes as images [Required]
+3. `FIGMA_DOWNLOAD_FIGMA_IMAGES` - Download rendered images [Optional]
+4. `FIGMA_GET_IMAGE_FILLS` - Get image fill URLs [Optional]
+
+**Key parameters**:
+- `file_key`: File key
+- `ids`: Comma-separated node IDs to render
+- `format`: 'png', 'svg', 'jpg', or 'pdf'
+- `scale`: Scale factor (0.01-4.0) for PNG/JPG
+- `images`: Array of {node_id, file_name, format} for downloads
+
+**Pitfalls**:
+- Images return as node_id-to-URL map; some IDs may be null (failed renders)
+- URLs are temporary (valid ~30 days)
+- Images capped at 32 megapixels; larger requests auto-scaled down
+
+### 3. Extract Design Tokens
+
+**When to use**: User wants to extract design tokens for development
+
+**Tool sequence**:
+1. `FIGMA_EXTRACT_DESIGN_TOKENS` - Extract colors, typography, spacing [Required]
+2. `FIGMA_DESIGN_TOKENS_TO_TAILWIND` - Convert to Tailwind config [Optional]
+
+**Key parameters**:
+- `file_key`: File key
+- `include_local_styles`: Include local styles (default true)
+- `include_variables`: Include Figma variables
+- `tokens`: Full tokens object from extraction (for Tailwind conversion)
+
+**Pitfalls**:
+- Tailwind conversion requires the full tokens object including total_tokens and sources
+- Do not strip fields from the extraction response before passing to conversion
+
+### 4. Manage Comments and Versions
+
+**When to use**: User wants to view or add comments, or inspect version history
+
+**Tool sequence**:
+1. `FIGMA_GET_COMMENTS_IN_A_FILE` - List all file comments [Optional]
+2. `FIGMA_ADD_A_COMMENT_TO_A_FILE` - Add a comment [Optional]
+3. `FIGMA_GET_REACTIONS_FOR_A_COMMENT` - Get comment reactions [Optional]
+4. `FIGMA_GET_VERSIONS_OF_A_FILE` - Get version history [Optional]
+
+**Key parameters**:
+- `file_key`: File key
+- `as_md`: Return comments in Markdown format
+- `message`: Comment text
+- `comment_id`: Comment ID for reactions
+
+**Pitfalls**:
+- Comments can be positioned on specific nodes using client_meta
+- Reply comments cannot be nested (only one level of replies)
+
+### 5. Browse Projects and Teams
+
+**When to use**: User wants to list team projects or files
+
+**Tool sequence**:
+1. `FIGMA_GET_PROJECTS_IN_A_TEAM` - List team projects [Optional]
+2. `FIGMA_GET_FILES_IN_A_PROJECT` - List project files [Optional]
+3. `FIGMA_GET_TEAM_STYLES` - List team published styles [Optional]
+
+**Key parameters**:
+- `team_id`: Team ID from URL (figma.com/files/team/TEAM_ID/...)
+- `project_id`: Project ID
+
+**Pitfalls**:
+- Team ID cannot be obtained programmatically; extract from Figma URL
+- Only published styles/components are returned by team endpoints
+
+## Common Patterns
+
+### URL Parsing
+
+Extract IDs from Figma URLs:
+```
+1. Call FIGMA_DISCOVER_FIGMA_RESOURCES with figma_url
+2. Extract file_key, node_id, team_id from response
+3. Convert dash-format node IDs (1-541) to colon format (1:541)
+```
+
+### Node Traversal
+
+```
+1. Call FIGMA_GET_FILE_JSON with depth=2 for overview
+2. Identify target nodes from the response
+3. Call again with specific ids and higher depth for details
+```
+
+## Known Pitfalls
+
+**File Type Support**:
+- GET_FILE_JSON only supports Design files (figma.com/design/ or figma.com/file/)
+- FigJam boards (figma.com/board/) and Slides (figma.com/slides/) are NOT supported
+
+**Node ID Formats**:
+- URLs use dash format: `node-id=1-541`
+- API uses colon format: `1:541`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Parse URL | FIGMA_DISCOVER_FIGMA_RESOURCES | figma_url |
+| Get file JSON | FIGMA_GET_FILE_JSON | file_key, ids, depth |
+| Get nodes | FIGMA_GET_FILE_NODES | file_key, ids |
+| Render images | FIGMA_RENDER_IMAGES_OF_FILE_NODES | file_key, ids, format |
+| Download images | FIGMA_DOWNLOAD_FIGMA_IMAGES | file_key, images |
+| Get component | FIGMA_GET_COMPONENT | file_key, node_id |
+| File components | FIGMA_GET_FILE_COMPONENTS | file_key |
+| Component sets | FIGMA_GET_FILE_COMPONENT_SETS | file_key |
+| Design tokens | FIGMA_EXTRACT_DESIGN_TOKENS | file_key |
+| Tokens to Tailwind | FIGMA_DESIGN_TOKENS_TO_TAILWIND | tokens |
+| File comments | FIGMA_GET_COMMENTS_IN_A_FILE | file_key |
+| Add comment | FIGMA_ADD_A_COMMENT_TO_A_FILE | file_key, message |
+| File versions | FIGMA_GET_VERSIONS_OF_A_FILE | file_key |
+| Team projects | FIGMA_GET_PROJECTS_IN_A_TEAM | team_id |
+| Project files | FIGMA_GET_FILES_IN_A_PROJECT | project_id |
+| Team styles | FIGMA_GET_TEAM_STYLES | team_id |
+| File styles | FIGMA_GET_FILE_STYLES | file_key |
+| Image fills | FIGMA_GET_IMAGE_FILLS | file_key |
diff --git a/freshdesk-automation/SKILL.md b/freshdesk-automation/SKILL.md
new file mode 100644
index 0000000..80bb98b
--- /dev/null
+++ b/freshdesk-automation/SKILL.md
@@ -0,0 +1,216 @@
+---
+name: freshdesk-automation
+description: Automate Freshdesk helpdesk operations including tickets, contacts, companies, notes, and replies via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Freshdesk Automation via Rube MCP
+
+Automate Freshdesk customer support workflows including ticket management, contact and company operations, notes, replies, and ticket search through Composio's Freshdesk toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Freshdesk connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `freshdesk`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `freshdesk`
+3. If connection is not ACTIVE, follow the returned auth link to complete Freshdesk authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Tickets
+
+**When to use**: User wants to create a new support ticket, update an existing ticket, or view ticket details.
+
+**Tool sequence**:
+1. `FRESHDESK_SEARCH_CONTACTS` - Find requester by email to get requester_id [Optional]
+2. `FRESHDESK_LIST_TICKET_FIELDS` - Check available custom fields and statuses [Optional]
+3. `FRESHDESK_CREATE_TICKET` - Create a new ticket with subject, description, requester info [Required]
+4. `FRESHDESK_UPDATE_TICKET` - Modify ticket status, priority, assignee, or other fields [Optional]
+5. `FRESHDESK_VIEW_TICKET` - Retrieve full ticket details by ID [Optional]
+
+**Key parameters for FRESHDESK_CREATE_TICKET**:
+- `subject`: Ticket subject (required)
+- `description`: HTML content of the ticket (required)
+- `email`: Requester email (at least one requester identifier required)
+- `requester_id`: User ID of requester (alternative to email)
+- `status`: 2=Open, 3=Pending, 4=Resolved, 5=Closed (default 2)
+- `priority`: 1=Low, 2=Medium, 3=High, 4=Urgent (default 1)
+- `source`: 1=Email, 2=Portal, 3=Phone, 7=Chat (default 2)
+- `responder_id`: Agent ID to assign the ticket to
+- `group_id`: Group to assign the ticket to
+- `tags`: Array of tag strings
+- `custom_fields`: Object with `cf_` keys
+
+**Pitfalls**:
+- At least one requester identifier is required: `requester_id`, `email`, `phone`, `facebook_id`, `twitter_id`, or `unique_external_id`
+- If `phone` is provided without `email`, then `name` becomes mandatory
+- `description` supports HTML formatting
+- `attachments` field expects multipart/form-data format, not file paths or URLs
+- Custom field keys must be prefixed with `cf_` (e.g., `cf_reference_number`)
+- Status and priority are integers, not strings
+
+### 2. Search and Filter Tickets
+
+**When to use**: User wants to find tickets by status, priority, date range, agent, or custom fields.
+
+**Tool sequence**:
+1. `FRESHDESK_GET_TICKETS` - List tickets with simple filters (status, priority, agent) [Required]
+2. `FRESHDESK_GET_SEARCH` - Advanced ticket search with query syntax [Required]
+3. `FRESHDESK_VIEW_TICKET` - Get full details for specific tickets from results [Optional]
+4. `FRESHDESK_LIST_TICKET_FIELDS` - Check available fields for search queries [Optional]
+
+**Key parameters for FRESHDESK_GET_TICKETS**:
+- `status`: Filter by status integer (2=Open, 3=Pending, 4=Resolved, 5=Closed)
+- `priority`: Filter by priority integer (1-4)
+- `agent_id`: Filter by assigned agent
+- `requester_id`: Filter by requester
+- `email`: Filter by requester email
+- `created_since`: ISO 8601 timestamp
+- `page` / `per_page`: Pagination (default 30 per page)
+- `sort_by` / `sort_order`: Sort field and direction
+
+**Key parameters for FRESHDESK_GET_SEARCH**:
+- `query`: Query string like `"status:2 AND priority:3"` or `"(created_at:>'2024-01-01' AND tag:'urgent')"`
+- `page`: Page number (1-10, max 300 total results)
+
+**Pitfalls**:
+- `FRESHDESK_GET_SEARCH` query must be enclosed in double quotes
+- Query string limited to 512 characters
+- Maximum 10 pages (300 results) from search endpoints
+- Date fields in queries use UTC format YYYY-MM-DD
+- Use `null` keyword to find tickets with empty fields (e.g., `"agent_id:null"`)
+- `FRESHDESK_LIST_ALL_TICKETS` takes no parameters and returns all tickets (use GET_TICKETS for filtering)
+
+### 3. Reply to and Add Notes on Tickets
+
+**When to use**: User wants to send a reply to a customer, add internal notes, or view conversation history.
+
+**Tool sequence**:
+1. `FRESHDESK_VIEW_TICKET` - Verify ticket exists and check current state [Prerequisite]
+2. `FRESHDESK_REPLY_TO_TICKET` - Send a public reply to the requester [Required]
+3. `FRESHDESK_ADD_NOTE_TO_TICKET` - Add a private or public note [Required]
+4. `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS` - View all messages and notes on a ticket [Optional]
+5. `FRESHDESK_UPDATE_CONVERSATIONS` - Edit an existing note [Optional]
+
+**Key parameters for FRESHDESK_REPLY_TO_TICKET**:
+- `ticket_id`: Ticket ID (integer, required)
+- `body`: Reply content, supports HTML (required)
+- `cc_emails` / `bcc_emails`: Additional recipients (max 50 total across to/cc/bcc)
+- `from_email`: Override sender email if multiple support emails configured
+- `user_id`: Agent ID to reply on behalf of
+
+**Key parameters for FRESHDESK_ADD_NOTE_TO_TICKET**:
+- `ticket_id`: Ticket ID (integer, required)
+- `body`: Note content, supports HTML (required)
+- `private`: true for agent-only visibility, false for public (default true)
+- `notify_emails`: Only accepts agent email addresses, not external contacts
+
+**Pitfalls**:
+- There are two reply tools: `FRESHDESK_REPLY_TO_TICKET` (more features) and `FRESHDESK_REPLY_TICKET` (simpler); both work
+- `FRESHDESK_ADD_NOTE_TO_TICKET` defaults to private (agent-only); set `private: false` for public notes
+- `notify_emails` in notes only accepts agent emails, not customer emails
+- Only notes can be edited via `FRESHDESK_UPDATE_CONVERSATIONS`; incoming replies cannot be edited
+
+### 4. Manage Contacts and Companies
+
+**When to use**: User wants to create, search, or manage customer contacts and company records.
+
+**Tool sequence**:
+1. `FRESHDESK_SEARCH_CONTACTS` - Search contacts by email, phone, or company [Required]
+2. `FRESHDESK_GET_CONTACTS` - List contacts with filters [Optional]
+3. `FRESHDESK_IMPORT_CONTACT` - Bulk import contacts from CSV [Optional]
+4. `FRESHDESK_SEARCH_COMPANIES` - Search companies by custom fields [Required]
+5. `FRESHDESK_GET_COMPANIES` - List all companies [Optional]
+6. `FRESHDESK_CREATE_COMPANIES` - Create a new company [Optional]
+7. `FRESHDESK_UPDATE_COMPANIES` - Update company details [Optional]
+8. `FRESHDESK_LIST_COMPANY_FIELDS` - Check available company fields [Optional]
+
+**Key parameters for FRESHDESK_SEARCH_CONTACTS**:
+- `query`: Search string like `"email:'user@example.com'"` (required)
+- `page`: Pagination (1-10, max 30 per page)
+
+**Key parameters for FRESHDESK_CREATE_COMPANIES**:
+- `name`: Company name (required)
+- `domains`: Array of domain strings for auto-association with contacts
+- `health_score`: "Happy", "Doing okay", or "At risk"
+- `account_tier`: "Basic", "Premium", or "Enterprise"
+- `industry`: Standard industry classification
+
+**Pitfalls**:
+- `FRESHDESK_SEARCH_CONTACTS` requires exact matches; partial/regex searches are not supported
+- `FRESHDESK_SEARCH_COMPANIES` cannot search by standard `name` field; use custom fields or `created_at`
+- Company custom fields do NOT use the `cf_` prefix (unlike ticket custom fields)
+- `domains` on companies enables automatic contact-to-company association by email domain
+- Contact search queries require string values in single quotes inside double-quoted query
+
+## Common Patterns
+
+### ID Resolution
+Always resolve display values to IDs before operations:
+- **Requester email -> requester_id**: `FRESHDESK_SEARCH_CONTACTS` with `"email:'user@example.com'"`
+- **Company name -> company_id**: `FRESHDESK_GET_COMPANIES` and match by name (search by name not supported)
+- **Agent name -> agent_id**: Not directly available; use agent_id from ticket responses or admin configuration
+
+### Pagination
+Freshdesk uses page-based pagination:
+- `FRESHDESK_GET_TICKETS`: `page` (starting at 1) and `per_page` (max 100)
+- `FRESHDESK_GET_SEARCH`: `page` (1-10, 30 results per page, max 300 total)
+- `FRESHDESK_SEARCH_CONTACTS`: `page` (1-10, 30 per page)
+- `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS`: `page` and `per_page` (max 100)
+
+## Known Pitfalls
+
+### ID Formats
+- Ticket IDs, contact IDs, company IDs, agent IDs, and group IDs are all integers
+- There are no string-based IDs in Freshdesk
+
+### Rate Limits
+- Freshdesk enforces per-account API rate limits based on plan tier
+- Bulk operations should be paced to avoid 429 responses
+- Search endpoints are limited to 300 total results (10 pages of 30)
+
+### Parameter Quirks
+- Status values: 2=Open, 3=Pending, 4=Resolved, 5=Closed (integers, not strings)
+- Priority values: 1=Low, 2=Medium, 3=High, 4=Urgent (integers, not strings)
+- Source values: 1=Email, 2=Portal, 3=Phone, 7=Chat, 9=Feedback Widget, 10=Outbound Email
+- Ticket custom fields use `cf_` prefix; company custom fields do NOT
+- `description` in tickets supports HTML formatting
+- Search query strings must be in double quotes with string values in single quotes
+- `FRESHDESK_LIST_ALL_TICKETS` returns all tickets with no filter parameters
+
+### Response Structure
+- Ticket details include nested objects for requester, assignee, and conversation data
+- Search results are paginated with a maximum of 300 results across 10 pages
+- Conversation lists include both replies and notes in chronological order
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create ticket | `FRESHDESK_CREATE_TICKET` | `subject`, `description`, `email`, `priority` |
+| Update ticket | `FRESHDESK_UPDATE_TICKET` | `ticket_id`, `status`, `priority` |
+| View ticket | `FRESHDESK_VIEW_TICKET` | `ticket_id` |
+| List tickets | `FRESHDESK_GET_TICKETS` | `status`, `priority`, `page`, `per_page` |
+| List all tickets | `FRESHDESK_LIST_ALL_TICKETS` | (none) |
+| Search tickets | `FRESHDESK_GET_SEARCH` | `query`, `page` |
+| Reply to ticket | `FRESHDESK_REPLY_TO_TICKET` | `ticket_id`, `body`, `cc_emails` |
+| Reply (simple) | `FRESHDESK_REPLY_TICKET` | `ticket_id`, `body` |
+| Add note | `FRESHDESK_ADD_NOTE_TO_TICKET` | `ticket_id`, `body`, `private` |
+| List conversations | `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS` | `ticket_id`, `page` |
+| Update note | `FRESHDESK_UPDATE_CONVERSATIONS` | `conversation_id`, `body` |
+| Search contacts | `FRESHDESK_SEARCH_CONTACTS` | `query`, `page` |
+| List contacts | `FRESHDESK_GET_CONTACTS` | `email`, `company_id`, `page` |
+| Import contacts | `FRESHDESK_IMPORT_CONTACT` | `file`, `name_column_index`, `email_column_index` |
+| Create company | `FRESHDESK_CREATE_COMPANIES` | `name`, `domains`, `industry` |
+| Update company | `FRESHDESK_UPDATE_COMPANIES` | `company_id`, `name`, `domains` |
+| Search companies | `FRESHDESK_SEARCH_COMPANIES` | `query`, `page` |
+| List companies | `FRESHDESK_GET_COMPANIES` | `page` |
+| List ticket fields | `FRESHDESK_LIST_TICKET_FIELDS` | (none) |
+| List company fields | `FRESHDESK_LIST_COMPANY_FIELDS` | (none) |
diff --git a/freshservice-automation/SKILL.md b/freshservice-automation/SKILL.md
new file mode 100644
index 0000000..c77f2db
--- /dev/null
+++ b/freshservice-automation/SKILL.md
@@ -0,0 +1,210 @@
+---
+name: freshservice-automation
+description: Automate Freshservice ITSM tasks via Rube MCP (Composio): create/update tickets, bulk operations, service requests, and outbound emails. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Freshservice Automation via Rube MCP
+
+Automate Freshservice IT Service Management operations through Composio's Freshservice toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Freshservice connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `freshservice`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `freshservice`
+3. If connection is not ACTIVE, follow the returned auth link to complete Freshservice authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Search Tickets
+
+**When to use**: User wants to find, list, or search for tickets
+
+**Tool sequence**:
+1. `FRESHSERVICE_LIST_TICKETS` - List tickets with optional filtering and pagination [Required]
+2. `FRESHSERVICE_GET_TICKET` - Get detailed information for a specific ticket [Optional]
+
+**Key parameters for listing**:
+- `filter`: Predefined filter ('all_tickets', 'deleted', 'spam', 'watching')
+- `updated_since`: ISO 8601 timestamp to get tickets updated after this time
+- `order_by`: Sort field ('created_at', 'updated_at', 'status', 'priority')
+- `order_type`: Sort direction ('asc' or 'desc')
+- `page`: Page number (1-indexed)
+- `per_page`: Results per page (1-100, default 30)
+- `include`: Additional fields ('requester', 'stats', 'description', 'conversations', 'assets')
+
+**Key parameters for get**:
+- `ticket_id`: Unique ticket ID or display_id
+- `include`: Additional fields to include
+
+**Pitfalls**:
+- By default, only tickets created within the past 30 days are returned
+- Use `updated_since` to retrieve older tickets
+- Each `include` value consumes additional API credits
+- `page` is 1-indexed; minimum value is 1
+- `per_page` max is 100; default is 30
+- Ticket IDs can be the internal ID or the display_id shown in the UI
+
+### 2. Create a Ticket
+
+**When to use**: User wants to log a new incident or request
+
+**Tool sequence**:
+1. `FRESHSERVICE_CREATE_TICKET` - Create a new ticket [Required]
+
+**Key parameters**:
+- `subject`: Ticket subject line (required)
+- `description`: HTML description of the ticket (required)
+- `status`: Ticket status - 2 (Open), 3 (Pending), 4 (Resolved), 5 (Closed) (required)
+- `priority`: Ticket priority - 1 (Low), 2 (Medium), 3 (High), 4 (Urgent) (required)
+- `email`: Requester's email address (provide either email or requester_id)
+- `requester_id`: User ID of the requester
+- `type`: Ticket type ('Incident' or 'Service Request')
+- `source`: Channel - 1 (Email), 2 (Portal), 3 (Phone), 4 (Chat), 5 (Twitter), 6 (Facebook)
+- `impact`: Impact level - 1 (Low), 2 (Medium), 3 (High)
+- `urgency`: Urgency level - 1 (Low), 2 (Medium), 3 (High), 4 (Critical)
+
+**Pitfalls**:
+- `subject`, `description`, `status`, and `priority` are all required
+- Either `email` or `requester_id` must be provided to identify the requester
+- Status and priority use numeric codes, not string names
+- Description supports HTML formatting
+- If email does not match an existing contact, a new contact is created
+
+### 3. Bulk Update Tickets
+
+**When to use**: User wants to update multiple tickets at once
+
+**Tool sequence**:
+1. `FRESHSERVICE_LIST_TICKETS` - Find tickets to update [Prerequisite]
+2. `FRESHSERVICE_BULK_UPDATE_TICKETS` - Update multiple tickets [Required]
+
+**Key parameters**:
+- `ids`: Array of ticket IDs to update (required)
+- `update_fields`: Dictionary of fields to update (required)
+ - Allowed keys: 'subject', 'description', 'status', 'priority', 'responder_id', 'group_id', 'type', 'tags', 'custom_fields'
+
+**Pitfalls**:
+- Bulk update performs sequential updates internally; large batches may take time
+- All specified tickets receive the same field updates
+- If one ticket update fails, others may still succeed; check response for individual results
+- Cannot selectively update different fields per ticket in a single call
+- Custom fields must use their internal field names, not display names
+
+### 4. Create Ticket via Outbound Email
+
+**When to use**: User wants to create a ticket by sending an outbound email notification
+
+**Tool sequence**:
+1. `FRESHSERVICE_CREATE_TICKET_OUTBOUND_EMAIL` - Create ticket with email notification [Required]
+
+**Key parameters**:
+- `email`: Requester's email address (required)
+- `subject`: Email subject / ticket subject (required)
+- `description`: HTML email body content
+- `status`: Ticket status (2=Open, 3=Pending, 4=Resolved, 5=Closed)
+- `priority`: Ticket priority (1=Low, 2=Medium, 3=High, 4=Urgent)
+- `cc_emails`: Array of CC email addresses
+- `email_config_id`: Email configuration ID for the sender address
+- `name`: Requester name
+
+**Pitfalls**:
+- This creates a standard ticket via the /api/v2/tickets endpoint while sending an email
+- If the email does not match an existing contact, a new contact is created with the provided name
+- `email_config_id` determines which email address the notification appears to come from
+
+### 5. Create Service Requests
+
+**When to use**: User wants to submit a service catalog request
+
+**Tool sequence**:
+1. `FRESHSERVICE_CREATE_SERVICE_REQUEST` - Create a service request for a catalog item [Required]
+
+**Key parameters**:
+- `item_display_id`: Display ID of the catalog item (required)
+- `email`: Requester's email address
+- `quantity`: Number of items to request (default: 1)
+- `custom_fields`: Custom field values for the service item form
+- `parent_ticket_id`: Display ID of a parent ticket (for child requests)
+
+**Pitfalls**:
+- `item_display_id` can be found in Admin > Service Catalog > item URL (e.g., /service_catalog/items/1)
+- Custom fields keys must match the service item form field names
+- Quantity defaults to 1 if not specified
+- Service requests follow the approval workflow defined for the catalog item
+
+## Common Patterns
+
+### Status Code Reference
+
+| Code | Status |
+|------|--------|
+| 2 | Open |
+| 3 | Pending |
+| 4 | Resolved |
+| 5 | Closed |
+
+### Priority Code Reference
+
+| Code | Priority |
+|------|----------|
+| 1 | Low |
+| 2 | Medium |
+| 3 | High |
+| 4 | Urgent |
+
+### Pagination
+
+- Use `page` (1-indexed) and `per_page` (max 100) parameters
+- Increment `page` by 1 each request
+- Continue until returned results count < `per_page`
+- Default page size is 30
+
+### Finding Tickets by Date Range
+
+```
+1. Call FRESHSERVICE_LIST_TICKETS with updated_since='2024-01-01T00:00:00Z'
+2. Optionally add order_by='updated_at' and order_type='desc'
+3. Paginate through results
+```
+
+## Known Pitfalls
+
+**Numeric Codes**:
+- Status and priority use numeric values, not strings
+- Source channel uses numeric codes (1-6)
+- Impact and urgency use numeric codes (1-3 or 1-4)
+
+**Date Filtering**:
+- Default returns only tickets from the last 30 days
+- Use `updated_since` parameter for older tickets
+- Date format is ISO 8601 (e.g., '2024-01-01T00:00:00Z')
+
+**Rate Limits**:
+- Freshservice API has per-account rate limits
+- Each `include` option consumes additional API credits
+- Implement backoff on 429 responses
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Ticket IDs are numeric integers
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List tickets | FRESHSERVICE_LIST_TICKETS | filter, updated_since, page, per_page |
+| Get ticket | FRESHSERVICE_GET_TICKET | ticket_id, include |
+| Create ticket | FRESHSERVICE_CREATE_TICKET | subject, description, status, priority, email |
+| Bulk update | FRESHSERVICE_BULK_UPDATE_TICKETS | ids, update_fields |
+| Outbound email ticket | FRESHSERVICE_CREATE_TICKET_OUTBOUND_EMAIL | email, subject, description |
+| Service request | FRESHSERVICE_CREATE_SERVICE_REQUEST | item_display_id, email, quantity |
diff --git a/github-automation/SKILL.md b/github-automation/SKILL.md
new file mode 100644
index 0000000..a4883ad
--- /dev/null
+++ b/github-automation/SKILL.md
@@ -0,0 +1,224 @@
+---
+name: github-automation
+description: Automate GitHub repositories, issues, pull requests, branches, CI/CD, and permissions via Rube MCP (Composio). Manage code workflows, review PRs, search code, and handle deployments programmatically.
+requires:
+ mcp: [rube]
+---
+
+# GitHub Automation via Rube MCP
+
+Automate GitHub repository management, issue tracking, pull request workflows, branch operations, and CI/CD through Composio's GitHub toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active GitHub connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `github`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `github`
+3. If connection is not ACTIVE, follow the returned auth link to complete GitHub OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Issues
+
+**When to use**: User wants to create, list, or manage GitHub issues
+
+**Tool sequence**:
+1. `GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER` - Find target repo if unknown [Prerequisite]
+2. `GITHUB_LIST_REPOSITORY_ISSUES` - List existing issues (includes PRs) [Required]
+3. `GITHUB_CREATE_AN_ISSUE` - Create a new issue [Required]
+4. `GITHUB_CREATE_AN_ISSUE_COMMENT` - Add comments to an issue [Optional]
+5. `GITHUB_SEARCH_ISSUES_AND_PULL_REQUESTS` - Search across repos by keyword [Optional]
+
+**Key parameters**:
+- `owner`: Repository owner (username or org), case-insensitive
+- `repo`: Repository name without .git extension
+- `title`: Issue title (required for creation)
+- `body`: Issue description (supports Markdown)
+- `labels`: Array of label names
+- `assignees`: Array of GitHub usernames
+- `state`: 'open', 'closed', or 'all' for filtering
+
+**Pitfalls**:
+- `GITHUB_LIST_REPOSITORY_ISSUES` returns both issues AND pull requests; check `pull_request` field to distinguish
+- Only users with push access can set assignees, labels, and milestones; they are silently dropped otherwise
+- Pagination: `per_page` max 100; iterate pages until empty
+
+### 2. Manage Pull Requests
+
+**When to use**: User wants to create, review, or merge pull requests
+
+**Tool sequence**:
+1. `GITHUB_FIND_PULL_REQUESTS` - Search and filter PRs [Required]
+2. `GITHUB_GET_A_PULL_REQUEST` - Get detailed PR info including mergeable status [Required]
+3. `GITHUB_LIST_PULL_REQUESTS_FILES` - Review changed files [Optional]
+4. `GITHUB_CREATE_A_PULL_REQUEST` - Create a new PR [Required]
+5. `GITHUB_CREATE_AN_ISSUE_COMMENT` - Post review comments [Optional]
+6. `GITHUB_LIST_CHECK_RUNS_FOR_A_REF` - Verify CI status before merge [Optional]
+7. `GITHUB_MERGE_A_PULL_REQUEST` - Merge after explicit user approval [Required]
+
+**Key parameters**:
+- `head`: Source branch with changes (must exist; for cross-repo: 'username:branch')
+- `base`: Target branch to merge into (e.g., 'main')
+- `title`: PR title (required unless `issue` number provided)
+- `merge_method`: 'merge', 'squash', or 'rebase'
+- `state`: 'open', 'closed', or 'all'
+
+**Pitfalls**:
+- `GITHUB_CREATE_A_PULL_REQUEST` fails with 422 if base/head are invalid, identical, or already merged
+- `GITHUB_MERGE_A_PULL_REQUEST` can be rejected if PR is draft, closed, or branch protection applies
+- Always verify mergeable status with `GITHUB_GET_A_PULL_REQUEST` immediately before merging
+- Require explicit user confirmation before calling MERGE
+
+### 3. Manage Repositories and Branches
+
+**When to use**: User wants to create repos, manage branches, or update repo settings
+
+**Tool sequence**:
+1. `GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER` - List user's repos [Required]
+2. `GITHUB_GET_A_REPOSITORY` - Get detailed repo info [Optional]
+3. `GITHUB_CREATE_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER` - Create personal repo [Required]
+4. `GITHUB_CREATE_AN_ORGANIZATION_REPOSITORY` - Create org repo [Alternative]
+5. `GITHUB_LIST_BRANCHES` - List branches [Required]
+6. `GITHUB_CREATE_A_REFERENCE` - Create new branch from SHA [Required]
+7. `GITHUB_UPDATE_A_REPOSITORY` - Update repo settings [Optional]
+
+**Key parameters**:
+- `name`: Repository name
+- `private`: Boolean for visibility
+- `ref`: Full reference path (e.g., 'refs/heads/new-branch')
+- `sha`: Commit SHA to point the new reference to
+- `default_branch`: Default branch name
+
+**Pitfalls**:
+- `GITHUB_CREATE_A_REFERENCE` only creates NEW references; use `GITHUB_UPDATE_A_REFERENCE` for existing ones
+- `ref` must start with 'refs/' and contain at least two slashes
+- `GITHUB_LIST_BRANCHES` paginates via `page`/`per_page`; iterate until empty page
+- `GITHUB_DELETE_A_REPOSITORY` is permanent and irreversible; requires admin privileges
+
+### 4. Search Code and Commits
+
+**When to use**: User wants to find code, files, or commits across repositories
+
+**Tool sequence**:
+1. `GITHUB_SEARCH_CODE` - Search file contents and paths [Required]
+2. `GITHUB_SEARCH_CODE_ALL_PAGES` - Multi-page code search [Alternative]
+3. `GITHUB_SEARCH_COMMITS_BY_AUTHOR` - Search commits by author/date/org [Required]
+4. `GITHUB_LIST_COMMITS` - List commits for a specific repo [Alternative]
+5. `GITHUB_GET_A_COMMIT` - Get detailed commit info [Optional]
+6. `GITHUB_GET_REPOSITORY_CONTENT` - Get file content [Optional]
+
+**Key parameters**:
+- `q`: Search query with qualifiers (`language:python`, `repo:owner/repo`, `extension:js`)
+- `owner`/`repo`: For repo-specific commit listing
+- `author`: Filter by commit author
+- `since`/`until`: ISO 8601 date range for commits
+
+**Pitfalls**:
+- Code search only indexes files under 384KB on default branch
+- Maximum 1000 results returned from code search
+- `GITHUB_SEARCH_COMMITS_BY_AUTHOR` requires keywords in addition to qualifiers; qualifier-only queries are not allowed
+- `GITHUB_LIST_COMMITS` returns 409 on empty repos
+
+### 5. Manage CI/CD and Deployments
+
+**When to use**: User wants to view workflows, check CI status, or manage deployments
+
+**Tool sequence**:
+1. `GITHUB_LIST_REPOSITORY_WORKFLOWS` - List GitHub Actions workflows [Required]
+2. `GITHUB_GET_A_WORKFLOW` - Get workflow details by ID or filename [Optional]
+3. `GITHUB_CREATE_A_WORKFLOW_DISPATCH_EVENT` - Manually trigger a workflow [Required]
+4. `GITHUB_LIST_CHECK_RUNS_FOR_A_REF` - Check CI status for a commit/branch [Required]
+5. `GITHUB_LIST_DEPLOYMENTS` - List deployments [Optional]
+6. `GITHUB_GET_A_DEPLOYMENT_STATUS` - Get deployment status [Optional]
+
+**Key parameters**:
+- `workflow_id`: Numeric ID or filename (e.g., 'ci.yml')
+- `ref`: Git reference (branch/tag) for workflow dispatch
+- `inputs`: JSON string of workflow inputs matching `on.workflow_dispatch.inputs`
+- `environment`: Filter deployments by environment name
+
+**Pitfalls**:
+- `GITHUB_CREATE_A_WORKFLOW_DISPATCH_EVENT` requires the workflow to have `workflow_dispatch` trigger configured
+- Full path `.github/workflows/main.yml` is auto-stripped to just `main.yml`
+- Inputs max 10 key-value pairs; must match workflow's `on.workflow_dispatch.inputs` definitions
+
+### 6. Manage Users and Permissions
+
+**When to use**: User wants to check collaborators, permissions, or branch protection
+
+**Tool sequence**:
+1. `GITHUB_LIST_REPOSITORY_COLLABORATORS` - List repo collaborators [Required]
+2. `GITHUB_GET_REPOSITORY_PERMISSIONS_FOR_A_USER` - Check specific user's access [Optional]
+3. `GITHUB_GET_BRANCH_PROTECTION` - Inspect branch protection rules [Required]
+4. `GITHUB_UPDATE_BRANCH_PROTECTION` - Update protection settings [Optional]
+5. `GITHUB_ADD_A_REPOSITORY_COLLABORATOR` - Add/update collaborator [Optional]
+
+**Key parameters**:
+- `affiliation`: 'outside', 'direct', or 'all' for collaborator filtering
+- `permission`: Filter by 'pull', 'triage', 'push', 'maintain', 'admin'
+- `branch`: Branch name for protection rules
+- `enforce_admins`: Whether protection applies to admins
+
+**Pitfalls**:
+- `GITHUB_GET_BRANCH_PROTECTION` returns 404 for unprotected branches; treat as no protection rules
+- Determine push ability from `permissions.push` or `role_name`, not display labels
+- `GITHUB_LIST_REPOSITORY_COLLABORATORS` paginates; iterate all pages
+- `GITHUB_GET_REPOSITORY_PERMISSIONS_FOR_A_USER` may be inconclusive for non-collaborators
+
+## Common Patterns
+
+### ID Resolution
+- **Repo name -> owner/repo**: `GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER`
+- **PR number -> PR details**: `GITHUB_FIND_PULL_REQUESTS` then `GITHUB_GET_A_PULL_REQUEST`
+- **Branch name -> SHA**: `GITHUB_GET_A_BRANCH`
+- **Workflow name -> ID**: `GITHUB_LIST_REPOSITORY_WORKFLOWS`
+
+### Pagination
+All list endpoints use page-based pagination:
+- `page`: Page number (starts at 1)
+- `per_page`: Results per page (max 100)
+- Iterate until response returns fewer results than `per_page`
+
+### Safety
+- Always verify PR mergeable status before merge
+- Require explicit user confirmation for destructive operations (merge, delete)
+- Check CI status with `GITHUB_LIST_CHECK_RUNS_FOR_A_REF` before merging
+
+## Known Pitfalls
+
+- **Issues vs PRs**: `GITHUB_LIST_REPOSITORY_ISSUES` returns both; check `pull_request` field
+- **Pagination limits**: `per_page` max 100; always iterate pages until empty
+- **Branch creation**: `GITHUB_CREATE_A_REFERENCE` fails with 422 if reference already exists
+- **Merge guards**: Merge can fail due to branch protection, failing checks, or draft status
+- **Code search limits**: Only files <384KB on default branch; max 1000 results
+- **Commit search**: Requires search text keywords alongside qualifiers
+- **Destructive actions**: Repo deletion is irreversible; merge cannot be undone
+- **Silent permission drops**: Labels, assignees, milestones silently dropped without push access
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List repos | `GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER` | `type`, `sort`, `per_page` |
+| Get repo | `GITHUB_GET_A_REPOSITORY` | `owner`, `repo` |
+| Create issue | `GITHUB_CREATE_AN_ISSUE` | `owner`, `repo`, `title`, `body` |
+| List issues | `GITHUB_LIST_REPOSITORY_ISSUES` | `owner`, `repo`, `state` |
+| Find PRs | `GITHUB_FIND_PULL_REQUESTS` | `repo`, `state`, `author` |
+| Create PR | `GITHUB_CREATE_A_PULL_REQUEST` | `owner`, `repo`, `head`, `base`, `title` |
+| Merge PR | `GITHUB_MERGE_A_PULL_REQUEST` | `owner`, `repo`, `pull_number`, `merge_method` |
+| List branches | `GITHUB_LIST_BRANCHES` | `owner`, `repo` |
+| Create branch | `GITHUB_CREATE_A_REFERENCE` | `owner`, `repo`, `ref`, `sha` |
+| Search code | `GITHUB_SEARCH_CODE` | `q` |
+| List commits | `GITHUB_LIST_COMMITS` | `owner`, `repo`, `author`, `since` |
+| Search commits | `GITHUB_SEARCH_COMMITS_BY_AUTHOR` | `q` |
+| List workflows | `GITHUB_LIST_REPOSITORY_WORKFLOWS` | `owner`, `repo` |
+| Trigger workflow | `GITHUB_CREATE_A_WORKFLOW_DISPATCH_EVENT` | `owner`, `repo`, `workflow_id`, `ref` |
+| Check CI | `GITHUB_LIST_CHECK_RUNS_FOR_A_REF` | `owner`, `repo`, ref |
+| List collaborators | `GITHUB_LIST_REPOSITORY_COLLABORATORS` | `owner`, `repo` |
+| Branch protection | `GITHUB_GET_BRANCH_PROTECTION` | `owner`, `repo`, `branch` |
diff --git a/gitlab-automation/SKILL.md b/gitlab-automation/SKILL.md
new file mode 100644
index 0000000..9950f46
--- /dev/null
+++ b/gitlab-automation/SKILL.md
@@ -0,0 +1,251 @@
+---
+name: gitlab-automation
+description: Automate GitLab project management, issues, merge requests, pipelines, branches, and user operations via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# GitLab Automation via Rube MCP
+
+Automate GitLab operations including project management, issue tracking, merge request workflows, CI/CD pipeline monitoring, branch management, and user administration through Composio's GitLab toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active GitLab connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `gitlab`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `gitlab`
+3. If connection is not ACTIVE, follow the returned auth link to complete GitLab OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Issues
+
+**When to use**: User wants to create, update, list, or search issues in a GitLab project
+
+**Tool sequence**:
+1. `GITLAB_GET_PROJECTS` - Find the target project and get its ID [Prerequisite]
+2. `GITLAB_LIST_PROJECT_ISSUES` - List and filter issues for a project [Required]
+3. `GITLAB_CREATE_PROJECT_ISSUE` - Create a new issue [Required for create]
+4. `GITLAB_UPDATE_PROJECT_ISSUE` - Update an existing issue (title, labels, state, assignees) [Required for update]
+5. `GITLAB_LIST_PROJECT_USERS` - Find user IDs for assignment [Optional]
+
+**Key parameters**:
+- `id`: Project ID (integer) or URL-encoded path (e.g., `"my-group/my-project"`)
+- `title`: Issue title (required for creation)
+- `description`: Issue body text (max 1,048,576 characters)
+- `labels`: Comma-separated label names (e.g., `"bug,critical"`)
+- `add_labels` / `remove_labels`: Add or remove labels without replacing all
+- `state`: Filter by `"all"`, `"opened"`, or `"closed"`
+- `state_event`: `"close"` or `"reopen"` to change issue state
+- `assignee_ids`: Array of user IDs; use `[0]` to unassign all
+- `issue_iid`: Internal issue ID within the project (required for updates)
+- `milestone`: Filter by milestone title
+- `search`: Search in title and description
+- `scope`: `"created_by_me"`, `"assigned_to_me"`, or `"all"`
+- `page` / `per_page`: Pagination (default per_page: 20)
+
+**Pitfalls**:
+- `id` accepts either integer project ID or URL-encoded path; wrong IDs yield 4xx errors
+- `issue_iid` is the project-internal ID (shown as #42), different from the global issue ID
+- Labels in `labels` field replace ALL existing labels; use `add_labels`/`remove_labels` for incremental changes
+- Setting `assignee_ids` to empty array does NOT unassign; use `[0]` instead
+- `updated_at` field requires administrator or project/group owner rights
+
+### 2. Manage Merge Requests
+
+**When to use**: User wants to list, filter, or review merge requests in a project
+
+**Tool sequence**:
+1. `GITLAB_GET_PROJECT` - Get project details and verify access [Prerequisite]
+2. `GITLAB_GET_PROJECT_MERGE_REQUESTS` - List and filter merge requests [Required]
+3. `GITLAB_GET_REPOSITORY_BRANCHES` - Verify source/target branches [Optional]
+4. `GITLAB_LIST_ALL_PROJECT_MEMBERS` - Find reviewers/assignees [Optional]
+
+**Key parameters**:
+- `id`: Project ID or URL-encoded path
+- `state`: `"opened"`, `"closed"`, `"locked"`, `"merged"`, or `"all"`
+- `scope`: `"created_by_me"` (default), `"assigned_to_me"`, or `"all"`
+- `source_branch` / `target_branch`: Filter by branch names
+- `author_id` / `author_username`: Filter by MR author
+- `assignee_id`: Filter by assignee (use `None` for unassigned, `Any` for assigned)
+- `reviewer_id` / `reviewer_username`: Filter by reviewer
+- `labels`: Comma-separated label filter
+- `search`: Search in title and description
+- `wip`: `"yes"` for draft MRs, `"no"` for non-draft
+- `order_by`: `"created_at"` (default), `"title"`, `"merged_at"`, `"updated_at"`
+- `view`: `"simple"` for minimal fields
+- `iids[]`: Filter by specific MR internal IDs
+
+**Pitfalls**:
+- Default `scope` is `"created_by_me"` which limits results; use `"all"` for complete listings
+- `author_id` and `author_username` are mutually exclusive
+- `reviewer_id` and `reviewer_username` are mutually exclusive
+- `approved` filter requires the `mr_approved_filter` feature flag (disabled by default)
+- Large MR histories can be noisy; use filters and moderate `per_page` values
+
+### 3. Manage Projects and Repositories
+
+**When to use**: User wants to list projects, create new projects, or manage branches
+
+**Tool sequence**:
+1. `GITLAB_GET_PROJECTS` - List all accessible projects with filters [Required]
+2. `GITLAB_GET_PROJECT` - Get detailed info for a specific project [Optional]
+3. `GITLAB_LIST_USER_PROJECTS` - List projects owned by a specific user [Optional]
+4. `GITLAB_CREATE_PROJECT` - Create a new project [Required for create]
+5. `GITLAB_GET_REPOSITORY_BRANCHES` - List branches in a project [Required for branch ops]
+6. `GITLAB_CREATE_REPOSITORY_BRANCH` - Create a new branch [Optional]
+7. `GITLAB_GET_REPOSITORY_BRANCH` - Get details of a specific branch [Optional]
+8. `GITLAB_LIST_REPOSITORY_COMMITS` - View commit history [Optional]
+9. `GITLAB_GET_PROJECT_LANGUAGES` - Get language breakdown [Optional]
+
+**Key parameters**:
+- `name` / `path`: Project name and URL-friendly path (both required for creation)
+- `visibility`: `"private"`, `"internal"`, or `"public"`
+- `namespace_id`: Group or user ID for project placement
+- `search`: Case-insensitive substring search for projects
+- `membership`: `true` to limit to projects user is a member of
+- `owned`: `true` to limit to user-owned projects
+- `project_id`: Project ID for branch operations
+- `branch_name`: Name for new branch
+- `ref`: Source branch or commit SHA for new branch creation
+- `order_by`: `"id"`, `"name"`, `"path"`, `"created_at"`, `"updated_at"`, `"star_count"`, `"last_activity_at"`
+
+**Pitfalls**:
+- `GITLAB_GET_PROJECTS` pagination is required for complete coverage; stopping at first page misses projects
+- Some responses place items under `data.details`; parse the actual returned list structure
+- Most follow-up calls depend on correct `project_id`; verify with `GITLAB_GET_PROJECT` first
+- Invalid `branch_name`/`ref`/`sha` causes client errors; verify branch existence via `GITLAB_GET_REPOSITORY_BRANCHES` first
+- Both `name` and `path` are required for `GITLAB_CREATE_PROJECT`
+
+### 4. Monitor CI/CD Pipelines
+
+**When to use**: User wants to check pipeline status, list jobs, or monitor CI/CD runs
+
+**Tool sequence**:
+1. `GITLAB_GET_PROJECT` - Verify project access [Prerequisite]
+2. `GITLAB_LIST_PROJECT_PIPELINES` - List pipelines with filters [Required]
+3. `GITLAB_GET_SINGLE_PIPELINE` - Get detailed info for a specific pipeline [Optional]
+4. `GITLAB_LIST_PIPELINE_JOBS` - List jobs within a pipeline [Optional]
+
+**Key parameters**:
+- `id`: Project ID or URL-encoded path
+- `status`: Filter by `"created"`, `"waiting_for_resource"`, `"preparing"`, `"pending"`, `"running"`, `"success"`, `"failed"`, `"canceled"`, `"skipped"`, `"manual"`, `"scheduled"`
+- `scope`: `"running"`, `"pending"`, `"finished"`, `"branches"`, `"tags"`
+- `ref`: Branch or tag name
+- `sha`: Specific commit SHA
+- `source`: Pipeline source (use `"parent_pipeline"` for child pipelines)
+- `order_by`: `"id"` (default), `"status"`, `"ref"`, `"updated_at"`, `"user_id"`
+- `created_after` / `created_before`: ISO 8601 date filters
+- `pipeline_id`: Specific pipeline ID for job listing
+- `include_retried`: `true` to include retried jobs (default `false`)
+
+**Pitfalls**:
+- Large pipeline histories can be noisy; use `status`, `ref`, and date filters to narrow results
+- Use moderate `per_page` values to keep output manageable
+- Pipeline job `scope` accepts single status string or array of statuses
+- `yaml_errors: true` returns only pipelines with invalid configurations
+
+### 5. Manage Users and Members
+
+**When to use**: User wants to find users, list project members, or check user status
+
+**Tool sequence**:
+1. `GITLAB_GET_USERS` - Search and list GitLab users [Required]
+2. `GITLAB_GET_USER` - Get details for a specific user by ID [Optional]
+3. `GITLAB_GET_USERS_ID_STATUS` - Get user status message and availability [Optional]
+4. `GITLAB_LIST_ALL_PROJECT_MEMBERS` - List all project members (direct + inherited) [Required for member listing]
+5. `GITLAB_LIST_PROJECT_USERS` - List project users with search filter [Optional]
+
+**Key parameters**:
+- `search`: Search by name, username, or public email
+- `username`: Get specific user by username
+- `active` / `blocked`: Filter by user state
+- `id`: Project ID for member listing
+- `query`: Filter members by name, email, or username
+- `state`: Filter members by `"awaiting"` or `"active"` (Premium/Ultimate)
+- `user_ids`: Filter by specific user IDs
+
+**Pitfalls**:
+- Many user filters (admins, auditors, extern_uid, two_factor) are admin-only
+- `GITLAB_LIST_ALL_PROJECT_MEMBERS` includes direct, inherited, and invited members
+- User search is case-insensitive but may not match partial email domains
+- Premium/Ultimate features (state filter, seat info) are not available on free plans
+
+## Common Patterns
+
+### ID Resolution
+GitLab uses two identifier formats for projects:
+- **Numeric ID**: Integer project ID (e.g., `123`)
+- **URL-encoded path**: Namespace/project format (e.g., `"my-group%2Fmy-project"` or `"my-group/my-project"`)
+- **Issue IID vs ID**: `issue_iid` is the project-internal number (#42); the global `id` is different
+- **User ID**: Numeric; resolve via `GITLAB_GET_USERS` with `search` or `username`
+
+### Pagination
+GitLab uses offset-based pagination:
+- Set `page` (starting at 1) and `per_page` (1-100, default 20)
+- Continue incrementing `page` until response returns fewer items than `per_page` or is empty
+- Total count may be available in response headers (`X-Total`, `X-Total-Pages`)
+- Always paginate to completion for accurate results
+
+### URL-Encoded Paths
+When using project paths as identifiers:
+- Forward slashes must be URL-encoded: `my-group/my-project` becomes `my-group%2Fmy-project`
+- Some tools accept unencoded paths; check schema for each tool
+- Prefer numeric IDs when available for reliability
+
+## Known Pitfalls
+
+### ID Formats
+- Project `id` field accepts both integer and string (URL-encoded path)
+- Issue `issue_iid` is project-scoped; do not confuse with global issue ID
+- Pipeline IDs are project-scoped integers
+- User IDs are global integers across the GitLab instance
+
+### Rate Limits
+- GitLab has per-user rate limits (typically 300-2000 requests/minute depending on plan)
+- Large pipeline/issue histories should use date and status filters to reduce result sets
+- Paginate responsibly with moderate `per_page` values
+
+### Parameter Quirks
+- `labels` field replaces ALL labels; use `add_labels`/`remove_labels` for incremental changes
+- `assignee_ids: [0]` unassigns all; empty array does nothing
+- `scope` defaults vary: `"created_by_me"` for MRs, `"all"` for issues
+- `author_id` and `author_username` are mutually exclusive in MR filters
+- Date parameters use ISO 8601 format: `"2024-01-15T10:30:00Z"`
+
+### Plan Restrictions
+- Some features require Premium/Ultimate: `epic_id`, `weight`, `iteration_id`, `approved_by_ids`, member `state` filter
+- Admin-only features: user management filters, `updated_at` override, custom attributes
+- The `mr_approved_filter` feature flag is disabled by default
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List projects | `GITLAB_GET_PROJECTS` | `search`, `membership`, `visibility` |
+| Get project details | `GITLAB_GET_PROJECT` | `id` |
+| User's projects | `GITLAB_LIST_USER_PROJECTS` | `id`, `search`, `owned` |
+| Create project | `GITLAB_CREATE_PROJECT` | `name`, `path`, `visibility` |
+| List issues | `GITLAB_LIST_PROJECT_ISSUES` | `id`, `state`, `labels`, `search` |
+| Create issue | `GITLAB_CREATE_PROJECT_ISSUE` | `id`, `title`, `description`, `labels` |
+| Update issue | `GITLAB_UPDATE_PROJECT_ISSUE` | `id`, `issue_iid`, `state_event` |
+| List merge requests | `GITLAB_GET_PROJECT_MERGE_REQUESTS` | `id`, `state`, `scope`, `labels` |
+| List branches | `GITLAB_GET_REPOSITORY_BRANCHES` | `project_id`, `search` |
+| Get branch | `GITLAB_GET_REPOSITORY_BRANCH` | `project_id`, `branch_name` |
+| Create branch | `GITLAB_CREATE_REPOSITORY_BRANCH` | `project_id`, `branch_name`, `ref` |
+| List commits | `GITLAB_LIST_REPOSITORY_COMMITS` | project ID, branch ref |
+| Project languages | `GITLAB_GET_PROJECT_LANGUAGES` | project ID |
+| List pipelines | `GITLAB_LIST_PROJECT_PIPELINES` | `id`, `status`, `ref` |
+| Get pipeline | `GITLAB_GET_SINGLE_PIPELINE` | `project_id`, `pipeline_id` |
+| List pipeline jobs | `GITLAB_LIST_PIPELINE_JOBS` | `id`, `pipeline_id`, `scope` |
+| Search users | `GITLAB_GET_USERS` | `search`, `username`, `active` |
+| Get user | `GITLAB_GET_USER` | user ID |
+| User status | `GITLAB_GET_USERS_ID_STATUS` | user ID |
+| List project members | `GITLAB_LIST_ALL_PROJECT_MEMBERS` | `id`, `query`, `state` |
+| List project users | `GITLAB_LIST_PROJECT_USERS` | `id`, `search` |
diff --git a/gmail-automation/SKILL.md b/gmail-automation/SKILL.md
new file mode 100644
index 0000000..68d69b1
--- /dev/null
+++ b/gmail-automation/SKILL.md
@@ -0,0 +1,267 @@
+---
+name: gmail-automation
+description: Automate Gmail tasks via Rube MCP (Composio): send/reply, search, labels, drafts, attachments. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Gmail Automation via Rube MCP
+
+Automate Gmail operations through Composio's Gmail toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Gmail connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `gmail`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `gmail`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send an Email
+
+**When to use**: User wants to compose and send a new email
+
+**Tool sequence**:
+1. `GMAIL_SEARCH_PEOPLE` - Resolve contact name to email address [Optional]
+2. `GMAIL_SEND_EMAIL` - Send the email [Required]
+
+**Key parameters**:
+- `recipient_email`: Email address or 'me' for self
+- `subject`: Email subject line
+- `body`: Email content (plain text or HTML)
+- `is_html`: Must be `true` if body contains HTML markup
+- `cc`/`bcc`: Arrays of email addresses
+- `attachment`: Object with `{s3key, mimetype, name}` from prior download
+
+**Pitfalls**:
+- At least one of `recipient_email`, `cc`, or `bcc` required
+- At least one of `subject` or `body` required
+- Attachment `mimetype` MUST contain '/' (e.g., 'application/pdf', not 'pdf')
+- Total message size limit ~25MB after base64 encoding
+- Use `from_email` only for verified aliases in Gmail 'Send mail as' settings
+
+### 2. Reply to a Thread
+
+**When to use**: User wants to reply to an existing email conversation
+
+**Tool sequence**:
+1. `GMAIL_FETCH_EMAILS` - Find the email/thread to reply to [Prerequisite]
+2. `GMAIL_REPLY_TO_THREAD` - Send reply within the thread [Required]
+
+**Key parameters**:
+- `thread_id`: Hex string from FETCH_EMAILS (e.g., '169eefc8138e68ca')
+- `message_body`: Reply content
+- `recipient_email`: Reply recipient
+- `is_html`: Set `true` for HTML content
+
+**Pitfalls**:
+- `thread_id` must be hex string; prefixes like 'msg-f:' are auto-stripped
+- Legacy Gmail web UI IDs (e.g., 'FMfcgz...') are NOT supported
+- Subject is inherited from original thread; setting it creates a new thread instead
+- Do NOT include subject parameter to stay within thread
+
+### 3. Search and Filter Emails
+
+**When to use**: User wants to find specific emails by sender, subject, date, label, etc.
+
+**Tool sequence**:
+1. `GMAIL_FETCH_EMAILS` - Search with Gmail query syntax [Required]
+2. `GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID` - Get full message details for selected results [Optional]
+
+**Key parameters**:
+- `query`: Gmail search syntax (from:, to:, subject:, is:unread, has:attachment, after:YYYY/MM/DD, before:YYYY/MM/DD)
+- `max_results`: 1-500 messages per page
+- `label_ids`: System IDs like 'INBOX', 'UNREAD'
+- `include_payload`: Set `true` to get full message content
+- `ids_only`: Set `true` for just message IDs
+- `page_token`: For pagination (from `nextPageToken`)
+
+**Pitfalls**:
+- Returns max ~500 per page; follow `nextPageToken` via `page_token` until absent
+- `resultSizeEstimate` is approximate, not exact count
+- Use 'is:' for states (is:unread, is:snoozed, is:starred)
+- Use 'label:' ONLY for user-created labels
+- Common mistake: 'label:snoozed' is WRONG — use 'is:snoozed'
+- `include_payload=true` on broad searches creates huge responses; default to metadata
+- Custom labels require label ID (e.g., 'Label_123'), NOT label name
+
+### 4. Manage Labels
+
+**When to use**: User wants to create, modify, or organize labels
+
+**Tool sequence**:
+1. `GMAIL_LIST_LABELS` - List all labels to find IDs and detect conflicts [Required]
+2. `GMAIL_CREATE_LABEL` - Create a new label [Optional]
+3. `GMAIL_PATCH_LABEL` - Rename or change label colors/visibility [Optional]
+4. `GMAIL_DELETE_LABEL` - Delete a user-created label (irreversible) [Optional]
+
+**Key parameters**:
+- `label_name`: Max 225 chars, no commas, '/' for nesting (e.g., 'Work/Projects')
+- `background_color`/`text_color`: Hex values from Gmail's predefined palette
+- `id`: Label ID for PATCH/DELETE operations
+
+**Pitfalls**:
+- 400/409 error if name is blank, duplicate, or reserved (INBOX, SPAM, CATEGORY_*)
+- Color specs must use Gmail's predefined palette of 102 hex values
+- DELETE is permanent and removes label from all messages
+- Cannot delete system labels (INBOX, SENT, DRAFT, etc.)
+
+### 5. Apply/Remove Labels on Messages
+
+**When to use**: User wants to label, archive, or mark emails as read/unread
+
+**Tool sequence**:
+1. `GMAIL_LIST_LABELS` - Get label IDs for custom labels [Prerequisite]
+2. `GMAIL_FETCH_EMAILS` - Find target messages [Prerequisite]
+3. `GMAIL_BATCH_MODIFY_MESSAGES` - Bulk add/remove labels (up to 1000 messages) [Required]
+4. `GMAIL_ADD_LABEL_TO_EMAIL` - Single-message label changes [Fallback]
+
+**Key parameters**:
+- `messageIds`: Array of message IDs (max 1000)
+- `addLabelIds`: Array of label IDs to add
+- `removeLabelIds`: Array of label IDs to remove
+- `message_id`: 15-16 char hex string for single operations
+
+**Pitfalls**:
+- Max 1000 messageIds per BATCH call; chunk larger sets
+- Use 'CATEGORY_UPDATES' not 'UPDATES'; full prefix required for category labels
+- SENT, DRAFT, CHAT are immutable — cannot be added/removed
+- To mark as read: REMOVE 'UNREAD'. To archive: REMOVE 'INBOX'
+- `message_id` must be 15-16 char hex, NOT UUIDs or web UI IDs
+
+### 6. Handle Drafts and Attachments
+
+**When to use**: User wants to create, edit, or send email drafts, possibly with attachments
+
+**Tool sequence**:
+1. `GMAIL_CREATE_EMAIL_DRAFT` - Create a new draft [Required]
+2. `GMAIL_UPDATE_DRAFT` - Edit draft content [Optional]
+3. `GMAIL_LIST_DRAFTS` - List existing drafts [Optional]
+4. `GMAIL_SEND_DRAFT` - Send a draft (requires explicit user approval) [Optional]
+5. `GMAIL_GET_ATTACHMENT` - Download attachment from existing message [Optional]
+
+**Key parameters**:
+- `recipient_email`: Draft recipient
+- `subject`: Draft subject (omit for reply drafts to stay in thread)
+- `body`: Draft content
+- `is_html`: Set `true` for HTML content
+- `attachment`: Object with `{s3key, mimetype, name}`
+- `thread_id`: For reply drafts (leave subject empty to stay in thread)
+
+**Pitfalls**:
+- Response includes `data.id` (draft_id) AND `data.message.id`; use `data.id` for draft operations
+- Setting subject on a thread reply draft creates a NEW thread instead
+- Attachment capped at ~25MB; base64 overhead can push near-limit files over
+- UPDATE_DRAFT replaces entire content, not patches; include all fields you want to keep
+- HTTP 429 on bulk draft creation; use exponential backoff
+
+## Common Patterns
+
+### ID Resolution
+
+**Label name → Label ID**:
+```
+1. Call GMAIL_LIST_LABELS
+2. Find label by name in response
+3. Extract id field (e.g., 'Label_123')
+```
+
+**Contact name → Email**:
+```
+1. Call GMAIL_SEARCH_PEOPLE with query=contact_name
+2. Extract emailAddresses from response
+```
+
+**Thread ID from search**:
+```
+1. Call GMAIL_FETCH_EMAILS or GMAIL_LIST_THREADS
+2. Extract threadId (15-16 char hex string)
+```
+
+### Pagination
+
+- Set `max_results` up to 500 per page
+- Check response for `nextPageToken`
+- Pass token as `page_token` in next request
+- Continue until `nextPageToken` is absent or empty string
+- `resultSizeEstimate` is approximate, not exact
+
+### Gmail Query Syntax
+
+**Operators**:
+- `from:sender@example.com` - Emails from sender
+- `to:recipient@example.com` - Emails to recipient
+- `subject:"exact phrase"` - Subject contains exact phrase
+- `is:unread` - Unread messages
+- `is:starred` - Starred messages
+- `is:snoozed` - Snoozed messages
+- `has:attachment` - Has attachments
+- `after:2024/01/01` - After date (YYYY/MM/DD)
+- `before:2024/12/31` - Before date
+- `label:custom_label` - User-created label (use label ID)
+- `in:sent` - In sent folder
+- `category:primary` - Primary category
+
+**Combinators**:
+- `AND` - Both conditions (default)
+- `OR` - Either condition
+- `NOT` - Exclude condition
+- `()` - Group conditions
+
+**Examples**:
+- `from:boss@company.com is:unread` - Unread emails from boss
+- `subject:invoice has:attachment after:2024/01/01` - Invoices with attachments this year
+- `(from:alice OR from:bob) is:starred` - Starred emails from Alice or Bob
+
+## Known Pitfalls
+
+**ID Formats**:
+- Custom label operations require label IDs (e.g., 'Label_123'), not display names
+- Always call LIST_LABELS first to resolve names to IDs
+- Message IDs are 15-16 char hex strings
+- Do NOT use UUIDs, web UI IDs, or 'thread-f:' prefixes
+
+**Query Syntax**:
+- Use 'is:' for states (unread, snoozed, starred)
+- Use 'label:' ONLY for user-created labels
+- System labels use 'is:' or 'in:' (e.g., 'is:sent', 'in:inbox')
+
+**Rate Limits**:
+- BATCH_MODIFY_MESSAGES max 1000 messages per call
+- Heavy use triggers 403/429 rate limits
+- Implement exponential backoff for bulk operations
+
+**Response Parsing**:
+- Response data may be nested under `data_preview` or `data.messages`
+- Parse defensively with fallbacks
+- Timestamp `messageTimestamp` uses RFC3339 with 'Z' suffix
+- Normalize to '+00:00' for parsing if needed
+
+**Attachments**:
+- Attachment `s3key` from prior download may expire
+- Use promptly after retrieval
+- Mimetype must include '/' separator
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Send email | GMAIL_SEND_EMAIL | recipient_email, subject, body, is_html |
+| Reply to thread | GMAIL_REPLY_TO_THREAD | thread_id, message_body, recipient_email |
+| Search emails | GMAIL_FETCH_EMAILS | query, max_results, label_ids, page_token |
+| Get message details | GMAIL_FETCH_MESSAGE_BY_MESSAGE_ID | message_id |
+| List labels | GMAIL_LIST_LABELS | (none) |
+| Create label | GMAIL_CREATE_LABEL | label_name, background_color, text_color |
+| Modify labels bulk | GMAIL_BATCH_MODIFY_MESSAGES | messageIds, addLabelIds, removeLabelIds |
+| Create draft | GMAIL_CREATE_EMAIL_DRAFT | recipient_email, subject, body, thread_id |
+| Send draft | GMAIL_SEND_DRAFT | draft_id |
+| Get attachment | GMAIL_GET_ATTACHMENT | message_id, attachment_id |
+| Search contacts | GMAIL_SEARCH_PEOPLE | query |
+| Get profile | GMAIL_GET_PROFILE | (none) |
\ No newline at end of file
diff --git a/google-analytics-automation/SKILL.md b/google-analytics-automation/SKILL.md
new file mode 100644
index 0000000..1a3e716
--- /dev/null
+++ b/google-analytics-automation/SKILL.md
@@ -0,0 +1,224 @@
+---
+name: google-analytics-automation
+description: Automate Google Analytics tasks via Rube MCP (Composio): run reports, list accounts/properties, funnels, pivots, key events. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Google Analytics Automation via Rube MCP
+
+Automate Google Analytics 4 (GA4) reporting and property management through Composio's Google Analytics toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Google Analytics connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `google_analytics`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `google_analytics`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List Accounts and Properties
+
+**When to use**: User wants to discover available GA4 accounts and properties
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_ACCOUNTS` - List all accessible GA4 accounts [Required]
+2. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - List properties under an account [Required]
+
+**Key parameters**:
+- `pageSize`: Number of results per page
+- `pageToken`: Pagination token from previous response
+- `filter`: Filter expression for properties (e.g., `parent:accounts/12345`)
+
+**Pitfalls**:
+- Property IDs are numeric strings prefixed with 'properties/' (e.g., 'properties/123456')
+- Account IDs are prefixed with 'accounts/' (e.g., 'accounts/12345')
+- Always list accounts first, then properties under each account
+- Pagination required for organizations with many properties
+
+### 2. Run Standard Reports
+
+**When to use**: User wants to query metrics and dimensions from GA4 data
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - Get property ID [Prerequisite]
+2. `GOOGLE_ANALYTICS_GET_METADATA` - Discover available dimensions and metrics [Optional]
+3. `GOOGLE_ANALYTICS_CHECK_COMPATIBILITY` - Verify dimension/metric compatibility [Optional]
+4. `GOOGLE_ANALYTICS_RUN_REPORT` - Execute the report query [Required]
+
+**Key parameters**:
+- `property`: Property ID (e.g., 'properties/123456')
+- `dateRanges`: Array of date range objects with `startDate` and `endDate`
+- `dimensions`: Array of dimension objects with `name` field
+- `metrics`: Array of metric objects with `name` field
+- `dimensionFilter` / `metricFilter`: Filter expressions
+- `orderBys`: Sort order configuration
+- `limit`: Maximum rows to return
+- `offset`: Row offset for pagination
+
+**Pitfalls**:
+- Date format is 'YYYY-MM-DD' or relative values like 'today', 'yesterday', '7daysAgo', '30daysAgo'
+- Not all dimensions and metrics are compatible; use CHECK_COMPATIBILITY first
+- Use GET_METADATA to discover valid dimension and metric names
+- Maximum 9 dimensions per report request
+- Row limit defaults vary; set explicitly for large datasets
+- `offset` is for result pagination, not date pagination
+
+### 3. Run Batch Reports
+
+**When to use**: User needs multiple different reports from the same property in one call
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - Get property ID [Prerequisite]
+2. `GOOGLE_ANALYTICS_BATCH_RUN_REPORTS` - Execute multiple reports at once [Required]
+
+**Key parameters**:
+- `property`: Property ID (required)
+- `requests`: Array of individual report request objects (same structure as RUN_REPORT)
+
+**Pitfalls**:
+- Maximum 5 report requests per batch call
+- All reports in a batch must target the same property
+- Each individual report has the same dimension/metric limits as RUN_REPORT
+- Batch errors may affect all reports; check individual report responses
+
+### 4. Run Pivot Reports
+
+**When to use**: User wants cross-tabulated data (rows vs columns) like pivot tables
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - Get property ID [Prerequisite]
+2. `GOOGLE_ANALYTICS_RUN_PIVOT_REPORT` - Execute pivot report [Required]
+
+**Key parameters**:
+- `property`: Property ID (required)
+- `dateRanges`: Date range objects
+- `dimensions`: All dimensions used in any pivot
+- `metrics`: Metrics to aggregate
+- `pivots`: Array of pivot definitions with `fieldNames`, `limit`, and `orderBys`
+
+**Pitfalls**:
+- Dimensions used in pivots must also be listed in top-level `dimensions`
+- Pivot `fieldNames` reference dimension names from the top-level list
+- Complex pivots with many dimensions can produce very large result sets
+- Each pivot has its own independent `limit` and `orderBys`
+
+### 5. Run Funnel Reports
+
+**When to use**: User wants to analyze conversion funnels and drop-off rates
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - Get property ID [Prerequisite]
+2. `GOOGLE_ANALYTICS_RUN_FUNNEL_REPORT` - Execute funnel analysis [Required]
+
+**Key parameters**:
+- `property`: Property ID (required)
+- `dateRanges`: Date range objects
+- `funnel`: Funnel definition with `steps` array
+- `funnelBreakdown`: Optional dimension to break down funnel by
+
+**Pitfalls**:
+- Funnel steps are ordered; each step defines a condition users must meet
+- Steps use filter expressions similar to dimension/metric filters
+- Open funnels allow entry at any step; closed funnels require sequential progression
+- Funnel reports may take longer to process than standard reports
+
+### 6. Manage Key Events
+
+**When to use**: User wants to view or manage conversion events (key events) in GA4
+
+**Tool sequence**:
+1. `GOOGLE_ANALYTICS_LIST_PROPERTIES` - Get property ID [Prerequisite]
+2. `GOOGLE_ANALYTICS_LIST_KEY_EVENTS` - List all key events for the property [Required]
+
+**Key parameters**:
+- `parent`: Property resource name (e.g., 'properties/123456')
+- `pageSize`: Number of results per page
+- `pageToken`: Pagination token
+
+**Pitfalls**:
+- Key events were previously called "conversions" in GA4
+- Property must have key events configured to return results
+- Key event names correspond to GA4 event names
+
+## Common Patterns
+
+### ID Resolution
+
+**Account name -> Account ID**:
+```
+1. Call GOOGLE_ANALYTICS_LIST_ACCOUNTS
+2. Find account by displayName
+3. Extract name field (e.g., 'accounts/12345')
+```
+
+**Property name -> Property ID**:
+```
+1. Call GOOGLE_ANALYTICS_LIST_PROPERTIES with filter
+2. Find property by displayName
+3. Extract name field (e.g., 'properties/123456')
+```
+
+### Dimension/Metric Discovery
+
+```
+1. Call GOOGLE_ANALYTICS_GET_METADATA with property ID
+2. Browse available dimensions and metrics
+3. Call GOOGLE_ANALYTICS_CHECK_COMPATIBILITY to verify combinations
+4. Use verified dimensions/metrics in RUN_REPORT
+```
+
+### Pagination
+
+- Reports: Use `offset` and `limit` for row pagination
+- Accounts/Properties: Use `pageToken` from response
+- Continue until `pageToken` is absent or `rowCount` reached
+
+### Common Dimensions and Metrics
+
+**Dimensions**: `date`, `city`, `country`, `deviceCategory`, `sessionSource`, `sessionMedium`, `pagePath`, `pageTitle`, `eventName`
+
+**Metrics**: `activeUsers`, `sessions`, `screenPageViews`, `eventCount`, `conversions`, `totalRevenue`, `bounceRate`, `averageSessionDuration`
+
+## Known Pitfalls
+
+**Property IDs**:
+- Always use full resource name format: 'properties/123456'
+- Numeric ID alone will cause errors
+- Resolve property names to IDs via LIST_PROPERTIES
+
+**Date Ranges**:
+- Format: 'YYYY-MM-DD' or relative ('today', 'yesterday', '7daysAgo', '30daysAgo')
+- Data processing delay means today's data may be incomplete
+- Maximum date range varies by property configuration
+
+**Compatibility**:
+- Not all dimensions work with all metrics
+- Always verify with CHECK_COMPATIBILITY before complex reports
+- Custom dimensions/metrics have specific naming patterns
+
+**Response Parsing**:
+- Report data is nested in `rows` array with `dimensionValues` and `metricValues`
+- Values are returned as strings; parse numbers explicitly
+- Empty reports return no `rows` key (not an empty array)
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List accounts | GOOGLE_ANALYTICS_LIST_ACCOUNTS | pageSize, pageToken |
+| List properties | GOOGLE_ANALYTICS_LIST_PROPERTIES | filter, pageSize |
+| Get metadata | GOOGLE_ANALYTICS_GET_METADATA | property |
+| Check compatibility | GOOGLE_ANALYTICS_CHECK_COMPATIBILITY | property, dimensions, metrics |
+| Run report | GOOGLE_ANALYTICS_RUN_REPORT | property, dateRanges, dimensions, metrics |
+| Batch reports | GOOGLE_ANALYTICS_BATCH_RUN_REPORTS | property, requests |
+| Pivot report | GOOGLE_ANALYTICS_RUN_PIVOT_REPORT | property, dateRanges, pivots |
+| Funnel report | GOOGLE_ANALYTICS_RUN_FUNNEL_REPORT | property, dateRanges, funnel |
+| List key events | GOOGLE_ANALYTICS_LIST_KEY_EVENTS | parent, pageSize |
diff --git a/google-calendar-automation/SKILL.md b/google-calendar-automation/SKILL.md
new file mode 100644
index 0000000..c4f2018
--- /dev/null
+++ b/google-calendar-automation/SKILL.md
@@ -0,0 +1,173 @@
+---
+name: google-calendar-automation
+description: Automate Google Calendar events, scheduling, availability checks, and attendee management via Rube MCP (Composio). Create events, find free slots, manage attendees, and list calendars programmatically.
+requires:
+ mcp: [rube]
+---
+
+# Google Calendar Automation via Rube MCP
+
+Automate Google Calendar workflows including event creation, scheduling, availability checks, attendee management, and calendar browsing through Composio's Google Calendar toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Google Calendar connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `googlecalendar`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `googlecalendar`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Events
+
+**When to use**: User wants to create, update, or delete calendar events
+
+**Tool sequence**:
+1. `GOOGLECALENDAR_LIST_CALENDARS` - Identify target calendar ID [Prerequisite]
+2. `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` - Get current time with proper timezone [Optional]
+3. `GOOGLECALENDAR_FIND_FREE_SLOTS` - Check availability before booking [Optional]
+4. `GOOGLECALENDAR_CREATE_EVENT` - Create the event [Required]
+5. `GOOGLECALENDAR_PATCH_EVENT` - Update specific fields of an existing event [Alternative]
+6. `GOOGLECALENDAR_UPDATE_EVENT` - Full replacement update of an event [Alternative]
+7. `GOOGLECALENDAR_DELETE_EVENT` - Delete an event [Optional]
+
+**Key parameters**:
+- `calendar_id`: Use 'primary' for main calendar, or specific calendar ID
+- `start_datetime`: ISO 8601 format 'YYYY-MM-DDTHH:MM:SS' (NOT natural language)
+- `timezone`: IANA timezone name (e.g., 'America/New_York', NOT 'EST' or 'PST')
+- `event_duration_hour`: Hours (0+)
+- `event_duration_minutes`: Minutes (0-59 only; NEVER use 60+)
+- `summary`: Event title
+- `attendees`: Array of email addresses (NOT names)
+- `location`: Free-form text for event location
+
+**Pitfalls**:
+- `start_datetime` must be ISO 8601; natural language like 'tomorrow' is rejected
+- `event_duration_minutes` max is 59; use `event_duration_hour=1` instead of `event_duration_minutes=60`
+- `timezone` must be IANA identifier; abbreviations like 'EST', 'PST' are NOT valid
+- `attendees` only accepts email addresses, not names; resolve names first
+- Google Meet link creation defaults to true; may fail on personal Gmail accounts (graceful fallback)
+- Organizer is auto-added as attendee unless `exclude_organizer=true`
+
+### 2. List and Search Events
+
+**When to use**: User wants to find or browse events on their calendar
+
+**Tool sequence**:
+1. `GOOGLECALENDAR_LIST_CALENDARS` - Get available calendars [Prerequisite]
+2. `GOOGLECALENDAR_FIND_EVENT` - Search by title/keyword with time bounds [Required]
+3. `GOOGLECALENDAR_EVENTS_LIST` - List events in a time range [Alternative]
+4. `GOOGLECALENDAR_EVENTS_INSTANCES` - List instances of a recurring event [Optional]
+
+**Key parameters**:
+- `query` / `q`: Free-text search (matches summary, description, location, attendees)
+- `timeMin`: Lower bound (RFC3339 with timezone offset, e.g., '2024-01-01T00:00:00-08:00')
+- `timeMax`: Upper bound (RFC3339 with timezone offset)
+- `singleEvents`: true to expand recurring events into instances
+- `orderBy`: 'startTime' (requires singleEvents=true) or 'updated'
+- `maxResults`: Results per page (max 2500)
+
+**Pitfalls**:
+- **Timezone warning**: UTC timestamps (ending in 'Z') don't align with local dates; use local timezone offsets instead
+- Example: '2026-01-19T00:00:00Z' covers 2026-01-18 4pm to 2026-01-19 4pm in PST
+- Omitting `timeMin`/`timeMax` scans the full calendar and can be slow
+- `pageToken` in response means more results; paginate until absent
+- `orderBy='startTime'` requires `singleEvents=true`
+
+### 3. Manage Attendees and Invitations
+
+**When to use**: User wants to add, remove, or update event attendees
+
+**Tool sequence**:
+1. `GOOGLECALENDAR_FIND_EVENT` or `GOOGLECALENDAR_EVENTS_LIST` - Find the event [Prerequisite]
+2. `GOOGLECALENDAR_PATCH_EVENT` - Add attendees (replaces entire attendees list) [Required]
+3. `GOOGLECALENDAR_REMOVE_ATTENDEE` - Remove a specific attendee by email [Required]
+
+**Key parameters**:
+- `event_id`: Unique event identifier (opaque string, NOT the event title)
+- `attendees`: Full list of attendee emails (PATCH replaces entire list)
+- `attendee_email`: Email to remove
+- `send_updates`: 'all', 'externalOnly', or 'none'
+
+**Pitfalls**:
+- `event_id` is a technical identifier, NOT the event title; always search first to get the ID
+- `PATCH_EVENT` attendees field replaces the entire list; include existing attendees to avoid removing them
+- Attendee names cannot be resolved; always use email addresses
+- Use `GMAIL_SEARCH_PEOPLE` to resolve names to emails before managing attendees
+
+### 4. Check Availability and Free/Busy Status
+
+**When to use**: User wants to find available time slots or check busy periods
+
+**Tool sequence**:
+1. `GOOGLECALENDAR_LIST_CALENDARS` - Identify calendars to check [Prerequisite]
+2. `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` - Get current time with timezone [Optional]
+3. `GOOGLECALENDAR_FIND_FREE_SLOTS` - Find free intervals across calendars [Required]
+4. `GOOGLECALENDAR_FREE_BUSY_QUERY` - Get raw busy periods for computing gaps [Fallback]
+5. `GOOGLECALENDAR_CREATE_EVENT` - Book a confirmed slot [Required]
+
+**Key parameters**:
+- `items`: List of calendar IDs to check (e.g., ['primary'])
+- `time_min`/`time_max`: Query interval (defaults to current day if omitted)
+- `timezone`: IANA timezone for interpreting naive timestamps
+- `calendarExpansionMax`: Max calendars (1-50)
+- `groupExpansionMax`: Max members per group (1-100)
+
+**Pitfalls**:
+- Maximum span ~90 days per Google Calendar freeBusy API limit
+- Very long ranges or inaccessible calendars yield empty/invalid results
+- Only calendars with at least freeBusyReader access are visible
+- Free slots responses may normalize to UTC ('Z'); check offsets
+- `GOOGLECALENDAR_FREE_BUSY_QUERY` requires RFC3339 timestamps with timezone
+
+## Common Patterns
+
+### ID Resolution
+- **Calendar name -> calendar_id**: `GOOGLECALENDAR_LIST_CALENDARS` to enumerate all calendars
+- **Event title -> event_id**: `GOOGLECALENDAR_FIND_EVENT` or `GOOGLECALENDAR_EVENTS_LIST`
+- **Attendee name -> email**: `GMAIL_SEARCH_PEOPLE`
+
+### Timezone Handling
+- Always use IANA timezone identifiers (e.g., 'America/Los_Angeles')
+- Use `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` to get current time in user's timezone
+- When querying events for a local date, use timestamps with local offset, NOT UTC
+- Example: '2026-01-19T00:00:00-08:00' for PST, NOT '2026-01-19T00:00:00Z'
+
+### Pagination
+- `GOOGLECALENDAR_EVENTS_LIST` returns `nextPageToken`; iterate until absent
+- `GOOGLECALENDAR_LIST_CALENDARS` also paginates; use `page_token`
+
+## Known Pitfalls
+
+- **Natural language dates**: NOT supported; all dates must be ISO 8601 or RFC3339
+- **Timezone mismatch**: UTC timestamps don't align with local dates for filtering
+- **Duration limits**: `event_duration_minutes` max 59; use hours for longer durations
+- **IANA timezones only**: 'EST', 'PST', etc. are NOT valid; use 'America/New_York'
+- **Event IDs are opaque**: Always search to get event_id; never guess or construct
+- **Attendees as emails**: Names cannot be used; resolve with GMAIL_SEARCH_PEOPLE
+- **PATCH replaces attendees**: Include all desired attendees in the array, not just new ones
+- **Conference limitations**: Google Meet may fail on personal accounts (graceful fallback)
+- **Rate limits**: High-volume searches can trigger 403/429; throttle between calls
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List calendars | `GOOGLECALENDAR_LIST_CALENDARS` | `max_results` |
+| Create event | `GOOGLECALENDAR_CREATE_EVENT` | `start_datetime`, `timezone`, `summary` |
+| Update event | `GOOGLECALENDAR_PATCH_EVENT` | `calendar_id`, `event_id`, fields to update |
+| Delete event | `GOOGLECALENDAR_DELETE_EVENT` | `calendar_id`, `event_id` |
+| Search events | `GOOGLECALENDAR_FIND_EVENT` | `query`, `timeMin`, `timeMax` |
+| List events | `GOOGLECALENDAR_EVENTS_LIST` | `calendarId`, `timeMin`, `timeMax` |
+| Recurring instances | `GOOGLECALENDAR_EVENTS_INSTANCES` | `calendarId`, `eventId` |
+| Find free slots | `GOOGLECALENDAR_FIND_FREE_SLOTS` | `items`, `time_min`, `time_max`, `timezone` |
+| Free/busy query | `GOOGLECALENDAR_FREE_BUSY_QUERY` | `timeMin`, `timeMax`, `items` |
+| Remove attendee | `GOOGLECALENDAR_REMOVE_ATTENDEE` | `event_id`, `attendee_email` |
+| Get current time | `GOOGLECALENDAR_GET_CURRENT_DATE_TIME` | `timezone` |
+| Get calendar | `GOOGLECALENDAR_GET_CALENDAR` | `calendar_id` |
diff --git a/google-drive-automation/SKILL.md b/google-drive-automation/SKILL.md
new file mode 100644
index 0000000..2173410
--- /dev/null
+++ b/google-drive-automation/SKILL.md
@@ -0,0 +1,190 @@
+---
+name: google-drive-automation
+description: Automate Google Drive file operations (upload, download, search, share, organize) via Rube MCP (Composio). Upload/download files, manage folders, share with permissions, and search across drives programmatically.
+requires:
+ mcp: [rube]
+---
+
+# Google Drive Automation via Rube MCP
+
+Automate Google Drive workflows including file upload/download, search, folder management, sharing/permissions, and organization through Composio's Google Drive toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Google Drive connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `googledrive`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `googledrive`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Upload and Download Files
+
+**When to use**: User wants to upload files to or download files from Google Drive
+
+**Tool sequence**:
+1. `GOOGLEDRIVE_FIND_FILE` - Locate target folder for upload [Prerequisite]
+2. `GOOGLEDRIVE_UPLOAD_FILE` - Upload a file (max 5MB) [Required]
+3. `GOOGLEDRIVE_RESUMABLE_UPLOAD` - Upload large files [Fallback]
+4. `GOOGLEDRIVE_DOWNLOAD_FILE` - Download a file by ID [Required]
+5. `GOOGLEDRIVE_DOWNLOAD_FILE_OPERATION` - Track long-running downloads [Fallback]
+6. `GOOGLEDRIVE_GET_FILE_METADATA` - Verify file after upload/download [Optional]
+
+**Key parameters**:
+- `file_to_upload`: Object with `name`, `mimetype`, and `s3key` (file must be in internal storage)
+- `folder_to_upload_to`: Target folder ID (optional; uploads to root if omitted)
+- `file_id`: ID of file to download
+- `mime_type`: Export format for Google Workspace files only (omit for native files)
+
+**Pitfalls**:
+- `GOOGLEDRIVE_UPLOAD_FILE` requires `file_to_upload.s3key`; files must already be in internal storage
+- For non-Google formats (Excel, PDF), do NOT set `mime_type`; it causes errors for native files
+- Download responses provide a temporary URL at `data.downloaded_file_content.s3url`, not inline bytes
+- Use `GOOGLEDRIVE_RESUMABLE_UPLOAD` for files >5MB or when basic uploads fail
+
+### 2. Search and List Files
+
+**When to use**: User wants to find specific files or browse Drive contents
+
+**Tool sequence**:
+1. `GOOGLEDRIVE_FIND_FILE` - Search by name, content, type, date, or folder [Required]
+2. `GOOGLEDRIVE_LIST_FILES` - Browse files with folder scoping [Alternative]
+3. `GOOGLEDRIVE_LIST_SHARED_DRIVES` - Enumerate shared drives [Optional]
+4. `GOOGLEDRIVE_GET_FILE_METADATA` - Get detailed file info [Optional]
+5. `GOOGLEDRIVE_GET_ABOUT` - Check storage quota and supported formats [Optional]
+
+**Key parameters**:
+- `q`: Drive query string (e.g., "name contains 'report'", "mimeType = 'application/pdf'")
+- `corpora`: Search scope ('user', 'domain', 'drive', 'allDrives')
+- `fields`: Response fields to include (e.g., 'files(id,name,mimeType)')
+- `orderBy`: Sort key ('modifiedTime desc', 'name', 'quotaBytesUsed desc')
+- `pageSize`: Results per page (max 1000)
+- `pageToken`: Pagination cursor from `nextPageToken`
+- `folder_id`: Scope search to a specific folder
+
+**Pitfalls**:
+- 403 PERMISSION_DENIED if OAuth scopes insufficient for shared drives
+- Pagination required; files are in `response.data.files`; follow `nextPageToken` until exhausted
+- `corpora="domain"` may trigger 400; try `"allDrives"` with `includeItemsFromAllDrives=true`
+- Query complexity limits: >5-10 OR clauses may error "The query is too complex"
+- Wildcards (*) NOT supported in `name`; use `contains` for partial matching
+- 'My Drive' is NOT searchable by name; use `folder_id='root'` for root folder
+- User email searches: use `'user@example.com' in owners` (NOT `owner:user@example.com`)
+
+### 3. Share Files and Manage Permissions
+
+**When to use**: User wants to share files or manage access permissions
+
+**Tool sequence**:
+1. `GOOGLEDRIVE_FIND_FILE` - Locate the file to share [Prerequisite]
+2. `GOOGLEDRIVE_ADD_FILE_SHARING_PREFERENCE` - Set sharing permission [Required]
+3. `GOOGLEDRIVE_LIST_PERMISSIONS` - View current permissions [Optional]
+4. `GOOGLEDRIVE_GET_PERMISSION` - Inspect a specific permission [Optional]
+5. `GOOGLEDRIVE_UPDATE_PERMISSION` - Modify existing permission [Optional]
+6. `GOOGLEDRIVE_DELETE_PERMISSION` - Revoke access [Optional]
+
+**Key parameters**:
+- `file_id`: ID of file to share
+- `type`: 'user', 'group', 'domain', or 'anyone'
+- `role`: 'owner', 'organizer', 'fileOrganizer', 'writer', 'commenter', 'reader'
+- `email_address`: Required for type='user' or 'group'
+- `domain`: Required for type='domain'
+- `transfer_ownership`: Required when role='owner'
+
+**Pitfalls**:
+- Invalid type/email combinations trigger 4xx errors
+- Using `type='anyone'` or powerful roles is risky; get explicit user confirmation
+- Org policies may block certain sharing types, causing 403
+- Permission changes may take time to propagate
+- Use `GMAIL_SEARCH_PEOPLE` to resolve contact names to emails before sharing
+
+### 4. Create and Organize Folders
+
+**When to use**: User wants to create folder structures or move files between folders
+
+**Tool sequence**:
+1. `GOOGLEDRIVE_FIND_FILE` - Check if folder already exists [Prerequisite]
+2. `GOOGLEDRIVE_CREATE_FOLDER` - Create a new folder [Required]
+3. `GOOGLEDRIVE_GET_FILE_METADATA` - Verify created folder [Optional]
+4. `GOOGLEDRIVE_MOVE_FILE` - Move files between folders [Optional]
+5. `GOOGLEDRIVE_UPDATE_FILE_PUT` - Update file metadata/parents [Alternative]
+
+**Key parameters**:
+- `name`: Folder name
+- `parent_id`: Parent folder ID (NOT name); omit for root
+- `file_id`: File to move
+- `add_parents`: Destination folder ID for move
+- `remove_parents`: Source folder ID to remove from
+
+**Pitfalls**:
+- `GOOGLEDRIVE_CREATE_FOLDER` requires `parent_id` as an ID, not a folder name
+- Using `parent_id="root"` creates at top level; for nested paths, chain folder IDs
+- `GOOGLEDRIVE_FIND_FILE` returns ~100 items/page; follow `nextPageToken` for large drives
+- Move operations can leave items with multiple parents; use `remove_parents` for true moves
+- Always verify parent folder exists before creating children
+
+## Common Patterns
+
+### ID Resolution
+- **File/folder name -> ID**: `GOOGLEDRIVE_FIND_FILE` with `q` parameter
+- **Root folder**: Use `folder_id='root'` or `'root' in parents`
+- **Shared drive -> driveId**: `GOOGLEDRIVE_LIST_SHARED_DRIVES`
+- **Contact name -> email**: `GMAIL_SEARCH_PEOPLE` (for sharing)
+
+### Query Syntax
+Google Drive uses a specific query language:
+- Name search: `"name contains 'report'"` or `"name = 'exact.pdf'"`
+- Type filter: `"mimeType = 'application/pdf'"` or `"mimeType = 'application/vnd.google-apps.folder'"`
+- Folder scoping: `"'FOLDER_ID' in parents"`
+- Date filter: `"modifiedTime > '2024-01-01T00:00:00'"`
+- Combine with `and`/`or`/`not`: `"name contains 'report' and trashed = false"`
+- Boolean filters: `"sharedWithMe = true"`, `"starred = true"`, `"trashed = false"`
+
+### Pagination
+- Follow `nextPageToken` until absent for complete results
+- Set `pageSize` explicitly (default 100, max 1000)
+- De-duplicate results if running multiple searches
+
+### Export Formats
+For Google Workspace files, set `mime_type` to export:
+- **Docs**: `application/pdf`, `text/plain`, `text/html`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
+- **Sheets**: `text/csv`, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
+- **Slides**: `application/pdf`, `application/vnd.openxmlformats-officedocument.presentationml.presentation`
+
+## Known Pitfalls
+
+- **Internal storage required**: Upload requires files in internal S3 storage (s3key)
+- **Export vs download**: Set `mime_type` ONLY for Google Workspace files; omit for native files
+- **Temporary URLs**: Downloaded content via `s3url` is temporary; fetch promptly
+- **Query complexity**: >5-10 OR clauses may error; split complex searches into multiple queries
+- **Shared drive scoping**: Missing drive permissions yield empty results; verify access first
+- **No wildcards**: Use `contains` operator instead of `*` for partial name matching
+- **Folder creation chains**: Always pass folder IDs (not names) as `parent_id`
+- **Multiple parents**: Move operations may leave items with multiple parents; use `remove_parents`
+- **Rate limits**: Heavy searches/exports can trigger 403/429; implement backoff
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search files | `GOOGLEDRIVE_FIND_FILE` | `q`, `corpora`, `pageSize` |
+| List files | `GOOGLEDRIVE_LIST_FILES` | `folderId`, `q`, `orderBy` |
+| Upload file | `GOOGLEDRIVE_UPLOAD_FILE` | `file_to_upload`, `folder_to_upload_to` |
+| Resumable upload | `GOOGLEDRIVE_RESUMABLE_UPLOAD` | file data |
+| Download file | `GOOGLEDRIVE_DOWNLOAD_FILE` | `file_id`, `mime_type` (Workspace only) |
+| File metadata | `GOOGLEDRIVE_GET_FILE_METADATA` | `fileId`, `fields` |
+| Create folder | `GOOGLEDRIVE_CREATE_FOLDER` | `name`, `parent_id` |
+| Move file | `GOOGLEDRIVE_MOVE_FILE` | `file_id`, `add_parents`, `remove_parents` |
+| Share file | `GOOGLEDRIVE_ADD_FILE_SHARING_PREFERENCE` | `file_id`, `role`, `type`, `email_address` |
+| List permissions | `GOOGLEDRIVE_LIST_PERMISSIONS` | `fileId` |
+| Update permission | `GOOGLEDRIVE_UPDATE_PERMISSION` | file_id, permission_id |
+| Delete permission | `GOOGLEDRIVE_DELETE_PERMISSION` | file_id, permission_id |
+| List shared drives | `GOOGLEDRIVE_LIST_SHARED_DRIVES` | `pageSize` |
+| Drive info | `GOOGLEDRIVE_GET_ABOUT` | (none) |
+| Create shortcut | `GOOGLEDRIVE_CREATE_SHORTCUT_TO_FILE` | target file_id |
diff --git a/googlesheets-automation/SKILL.md b/googlesheets-automation/SKILL.md
new file mode 100644
index 0000000..b354885
--- /dev/null
+++ b/googlesheets-automation/SKILL.md
@@ -0,0 +1,194 @@
+---
+name: googlesheets-automation
+description: Automate Google Sheets operations (read, write, format, filter, manage spreadsheets) via Rube MCP (Composio). Read/write data, manage tabs, apply formatting, and search rows programmatically.
+requires:
+ mcp: [rube]
+---
+
+# Google Sheets Automation via Rube MCP
+
+Automate Google Sheets workflows including reading/writing data, managing spreadsheets and tabs, formatting cells, filtering rows, and upserting records through Composio's Google Sheets toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Google Sheets connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `googlesheets`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `googlesheets`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Read and Write Data
+
+**When to use**: User wants to read data from or write data to a Google Sheet
+
+**Tool sequence**:
+1. `GOOGLESHEETS_SEARCH_SPREADSHEETS` - Find spreadsheet by name if ID unknown [Prerequisite]
+2. `GOOGLESHEETS_GET_SHEET_NAMES` - Enumerate tab names to target the right sheet [Prerequisite]
+3. `GOOGLESHEETS_BATCH_GET` - Read data from one or more ranges [Required]
+4. `GOOGLESHEETS_BATCH_UPDATE` - Write data to a range or append rows [Required]
+5. `GOOGLESHEETS_VALUES_UPDATE` - Update a single specific range [Alternative]
+6. `GOOGLESHEETS_SPREADSHEETS_VALUES_APPEND` - Append rows to end of table [Alternative]
+
+**Key parameters**:
+- `spreadsheet_id`: Alphanumeric ID from the spreadsheet URL (between '/d/' and '/edit')
+- `ranges`: A1 notation array (e.g., 'Sheet1!A1:Z1000'); always use bounded ranges
+- `sheet_name`: Tab name (case-insensitive matching supported)
+- `values`: 2D array where each inner array is a row
+- `first_cell_location`: Starting cell in A1 notation (omit to append)
+- `valueInputOption`: 'USER_ENTERED' (parsed) or 'RAW' (literal)
+
+**Pitfalls**:
+- Mis-cased or non-existent tab names error "Sheet 'X' not found"
+- Empty ranges may omit `valueRanges[i].values`; treat missing as empty array
+- `GOOGLESHEETS_BATCH_UPDATE` values must be a 2D array (list of lists), even for a single row
+- Unbounded ranges like 'A:Z' on sheets with >10,000 rows may cause timeouts; always bound with row limits
+- Append follows the detected `tableRange`; use returned `updatedRange` to verify placement
+
+### 2. Create and Manage Spreadsheets
+
+**When to use**: User wants to create a new spreadsheet or manage tabs within one
+
+**Tool sequence**:
+1. `GOOGLESHEETS_CREATE_GOOGLE_SHEET1` - Create a new spreadsheet [Required]
+2. `GOOGLESHEETS_ADD_SHEET` - Add a new tab/worksheet [Required]
+3. `GOOGLESHEETS_UPDATE_SHEET_PROPERTIES` - Rename, hide, reorder, or color tabs [Optional]
+4. `GOOGLESHEETS_GET_SPREADSHEET_INFO` - Get full spreadsheet metadata [Optional]
+5. `GOOGLESHEETS_FIND_WORKSHEET_BY_TITLE` - Check if a specific tab exists [Optional]
+
+**Key parameters**:
+- `title`: Spreadsheet or sheet tab name
+- `spreadsheetId`: Target spreadsheet ID
+- `forceUnique`: Auto-append suffix if tab name exists (default true)
+- `properties.gridProperties`: Set row/column counts, frozen rows
+
+**Pitfalls**:
+- Sheet names must be unique within a spreadsheet
+- Default sheet names are locale-dependent ('Sheet1' in English, 'Hoja 1' in Spanish)
+- Don't use `index` when creating multiple sheets in parallel (causes 'index too high' errors)
+- `GOOGLESHEETS_GET_SPREADSHEET_INFO` can return 403 if account lacks access
+
+### 3. Search and Filter Rows
+
+**When to use**: User wants to find specific rows or apply filters to sheet data
+
+**Tool sequence**:
+1. `GOOGLESHEETS_LOOKUP_SPREADSHEET_ROW` - Find first row matching exact cell value [Required]
+2. `GOOGLESHEETS_SET_BASIC_FILTER` - Apply filter/sort to a range [Alternative]
+3. `GOOGLESHEETS_CLEAR_BASIC_FILTER` - Remove existing filter [Optional]
+4. `GOOGLESHEETS_BATCH_GET` - Read filtered results [Optional]
+
+**Key parameters**:
+- `query`: Exact text value to match (matches entire cell content)
+- `range`: A1 notation range to search within
+- `case_sensitive`: Boolean for case-sensitive matching (default false)
+- `filter.range`: Grid range with sheet_id for basic filter
+- `filter.criteria`: Column-based filter conditions
+- `filter.sortSpecs`: Sort specifications
+
+**Pitfalls**:
+- `GOOGLESHEETS_LOOKUP_SPREADSHEET_ROW` matches entire cell content, not substrings
+- Sheet names with spaces must be single-quoted in ranges (e.g., "'My Sheet'!A:Z")
+- Bare sheet names without ranges are not supported for lookup; always specify a range
+
+### 4. Upsert Rows by Key
+
+**When to use**: User wants to update existing rows or insert new ones based on a unique key column
+
+**Tool sequence**:
+1. `GOOGLESHEETS_UPSERT_ROWS` - Update matching rows or append new ones [Required]
+
+**Key parameters**:
+- `spreadsheetId`: Target spreadsheet ID
+- `sheetName`: Tab name
+- `keyColumn`: Column header name used as unique identifier (e.g., 'Email', 'SKU')
+- `headers`: List of column names for the data
+- `rows`: 2D array of data rows
+- `strictMode`: Error on mismatched column counts (default true)
+
+**Pitfalls**:
+- `keyColumn` must be an actual header name, NOT a column letter (e.g., 'Email' not 'A')
+- If `headers` is NOT provided, first row of `rows` is treated as headers
+- With `strictMode=true`, rows with more values than headers cause an error
+- Auto-adds missing columns to the sheet
+
+### 5. Format Cells
+
+**When to use**: User wants to apply formatting (bold, colors, font size) to cells
+
+**Tool sequence**:
+1. `GOOGLESHEETS_GET_SPREADSHEET_INFO` - Get numeric sheetId for target tab [Prerequisite]
+2. `GOOGLESHEETS_FORMAT_CELL` - Apply formatting to a range [Required]
+3. `GOOGLESHEETS_UPDATE_SHEET_PROPERTIES` - Change frozen rows, column widths [Optional]
+
+**Key parameters**:
+- `spreadsheet_id`: Spreadsheet ID
+- `worksheet_id`: Numeric sheetId (NOT tab name); get from GET_SPREADSHEET_INFO
+- `range`: A1 notation (e.g., 'A1:F1') - preferred over index fields
+- `bold`, `italic`, `underline`, `strikethrough`: Boolean formatting options
+- `red`, `green`, `blue`: Background color as 0.0-1.0 floats (NOT 0-255 ints)
+- `fontSize`: Font size in points
+
+**Pitfalls**:
+- Requires numeric `worksheet_id`, not tab title; get from spreadsheet metadata
+- Color channels are 0-1 floats (e.g., 1.0 for full red), NOT 0-255 integers
+- Responses may return empty reply objects ([{}]); verify formatting via readback
+- Format one range per call; batch formatting requires separate calls
+
+## Common Patterns
+
+### ID Resolution
+- **Spreadsheet name -> ID**: `GOOGLESHEETS_SEARCH_SPREADSHEETS` with `query`
+- **Tab name -> sheetId**: `GOOGLESHEETS_GET_SPREADSHEET_INFO`, extract from sheets metadata
+- **Tab existence check**: `GOOGLESHEETS_FIND_WORKSHEET_BY_TITLE`
+
+### Rate Limits
+Google Sheets enforces strict rate limits:
+- Max 60 reads/minute and 60 writes/minute
+- Exceeding limits causes errors; batch operations where possible
+- Use `GOOGLESHEETS_BATCH_GET` and `GOOGLESHEETS_BATCH_UPDATE` for efficiency
+
+### Data Patterns
+- Always read before writing to understand existing layout
+- Use `GOOGLESHEETS_UPSERT_ROWS` for CRM syncs, inventory updates, and dedup scenarios
+- Append mode (omit `first_cell_location`) is safest for adding new records
+- Use `GOOGLESHEETS_CLEAR_VALUES` to clear content while preserving formatting
+
+## Known Pitfalls
+
+- **Tab names**: Locale-dependent defaults; 'Sheet1' may not exist in non-English accounts
+- **Range notation**: Sheet names with spaces need single quotes in A1 notation
+- **Unbounded ranges**: Can timeout on large sheets; always specify row bounds (e.g., 'A1:Z10000')
+- **2D arrays**: All value parameters must be list-of-lists, even for single rows
+- **Color values**: Floats 0.0-1.0, not integers 0-255
+- **Formatting IDs**: `FORMAT_CELL` needs numeric sheetId, not tab title
+- **Rate limits**: 60 reads/min and 60 writes/min; batch to stay within limits
+- **Delete dimension**: `GOOGLESHEETS_DELETE_DIMENSION` is irreversible; double-check bounds
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search spreadsheets | `GOOGLESHEETS_SEARCH_SPREADSHEETS` | `query`, `search_type` |
+| Create spreadsheet | `GOOGLESHEETS_CREATE_GOOGLE_SHEET1` | `title` |
+| List tabs | `GOOGLESHEETS_GET_SHEET_NAMES` | `spreadsheet_id` |
+| Add tab | `GOOGLESHEETS_ADD_SHEET` | `spreadsheetId`, `title` |
+| Read data | `GOOGLESHEETS_BATCH_GET` | `spreadsheet_id`, `ranges` |
+| Read single range | `GOOGLESHEETS_VALUES_GET` | `spreadsheet_id`, `range` |
+| Write data | `GOOGLESHEETS_BATCH_UPDATE` | `spreadsheet_id`, `sheet_name`, `values` |
+| Update range | `GOOGLESHEETS_VALUES_UPDATE` | `spreadsheet_id`, `range`, `values` |
+| Append rows | `GOOGLESHEETS_SPREADSHEETS_VALUES_APPEND` | `spreadsheetId`, `range`, `values` |
+| Upsert rows | `GOOGLESHEETS_UPSERT_ROWS` | `spreadsheetId`, `sheetName`, `keyColumn`, `rows` |
+| Lookup row | `GOOGLESHEETS_LOOKUP_SPREADSHEET_ROW` | `spreadsheet_id`, `query` |
+| Format cells | `GOOGLESHEETS_FORMAT_CELL` | `spreadsheet_id`, `worksheet_id`, `range` |
+| Set filter | `GOOGLESHEETS_SET_BASIC_FILTER` | `spreadsheetId`, `filter` |
+| Clear values | `GOOGLESHEETS_CLEAR_VALUES` | `spreadsheet_id`, range |
+| Delete rows/cols | `GOOGLESHEETS_DELETE_DIMENSION` | `spreadsheet_id`, `sheet_name`, dimension |
+| Spreadsheet info | `GOOGLESHEETS_GET_SPREADSHEET_INFO` | `spreadsheet_id` |
+| Update tab props | `GOOGLESHEETS_UPDATE_SHEET_PROPERTIES` | `spreadsheetId`, properties |
diff --git a/helpdesk-automation/SKILL.md b/helpdesk-automation/SKILL.md
new file mode 100644
index 0000000..d9c5b05
--- /dev/null
+++ b/helpdesk-automation/SKILL.md
@@ -0,0 +1,163 @@
+---
+name: helpdesk-automation
+description: Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# HelpDesk Automation via Rube MCP
+
+Automate HelpDesk ticketing operations through Composio's HelpDesk toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active HelpDesk connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `helpdesk`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `helpdesk`
+3. If connection is not ACTIVE, follow the returned auth link to complete HelpDesk authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Browse Tickets
+
+**When to use**: User wants to retrieve, browse, or paginate through support tickets
+
+**Tool sequence**:
+1. `HELPDESK_LIST_TICKETS` - List tickets with sorting and pagination [Required]
+
+**Key parameters**:
+- `silo`: Ticket folder - 'tickets', 'archive', 'trash', or 'spam' (default: 'tickets')
+- `sortBy`: Sort field - 'createdAt', 'updatedAt', or 'lastMessageAt' (default: 'createdAt')
+- `order`: Sort direction - 'asc' or 'desc' (default: 'desc')
+- `pageSize`: Results per page, 1-100 (default: 20)
+- `next.value`: Timestamp cursor for forward pagination
+- `next.ID`: ID cursor for forward pagination
+- `prev.value`: Timestamp cursor for backward pagination
+- `prev.ID`: ID cursor for backward pagination
+
+**Pitfalls**:
+- Pagination uses cursor-based approach with timestamp + ID pairs
+- Forward pagination requires both `next.value` and `next.ID` from previous response
+- Backward pagination requires both `prev.value` and `prev.ID`
+- `silo` determines which folder to list from; default is active tickets
+- `pageSize` max is 100; default is 20
+- Archived and trashed tickets are in separate silos
+
+### 2. Manage Ticket Views
+
+**When to use**: User wants to see saved agent views for organizing tickets
+
+**Tool sequence**:
+1. `HELPDESK_LIST_VIEWS` - List all agent views [Required]
+
+**Key parameters**: (none required)
+
+**Pitfalls**:
+- Views are predefined saved filters configured by agents in the HelpDesk UI
+- View definitions include filter criteria that can be used to understand ticket organization
+- Views cannot be created or modified via API; they are managed in the HelpDesk UI
+
+### 3. Use Canned Responses
+
+**When to use**: User wants to list available canned (template) responses for tickets
+
+**Tool sequence**:
+1. `HELPDESK_LIST_CANNED_RESPONSES` - Retrieve all predefined reply templates [Required]
+
+**Key parameters**: (none required)
+
+**Pitfalls**:
+- Canned responses are predefined templates for common replies
+- They may include placeholder variables that need to be filled in
+- Canned responses are managed through the HelpDesk UI
+- Response content may include HTML formatting
+
+### 4. Inspect Custom Fields
+
+**When to use**: User wants to view custom field definitions for the account
+
+**Tool sequence**:
+1. `HELPDESK_LIST_CUSTOM_FIELDS` - List all custom field definitions [Required]
+
+**Key parameters**: (none required)
+
+**Pitfalls**:
+- Custom fields extend the default ticket schema with organization-specific data
+- Field definitions include field type, name, and validation rules
+- Custom fields are configured in the HelpDesk admin panel
+- Field values appear on tickets when the field has been populated
+
+## Common Patterns
+
+### Ticket Browsing Pattern
+
+```
+1. Call HELPDESK_LIST_TICKETS with desired silo and sortBy
+2. Process the returned page of tickets
+3. Extract next.value and next.ID from the response
+4. Call HELPDESK_LIST_TICKETS with those cursor values for next page
+5. Continue until no more cursor values are returned
+```
+
+### Ticket Folder Navigation
+
+```
+Active tickets: silo='tickets'
+Archived: silo='archive'
+Trashed: silo='trash'
+Spam: silo='spam'
+```
+
+### Cursor-Based Pagination
+
+```
+Forward pagination:
+ - Use next.value (timestamp) and next.ID from response
+ - Pass as next.value and next.ID parameters in next call
+
+Backward pagination:
+ - Use prev.value (timestamp) and prev.ID from response
+ - Pass as prev.value and prev.ID parameters in next call
+```
+
+## Known Pitfalls
+
+**Cursor Pagination**:
+- Both timestamp and ID are required for cursor navigation
+- Cursor values are timestamps in ISO 8601 date-time format
+- Mixing forward and backward cursors in the same request is undefined behavior
+
+**Silo Filtering**:
+- Tickets are physically separated into silos (folders)
+- Moving tickets between silos is done in the HelpDesk UI
+- Each silo query is independent; there is no cross-silo search
+
+**Read-Only Operations**:
+- Current Composio toolkit provides list/read operations
+- Ticket creation, update, and reply operations may require additional tools
+- Check RUBE_SEARCH_TOOLS for any newly available tools
+
+**Rate Limits**:
+- HelpDesk API has per-account rate limits
+- Implement backoff on 429 responses
+- Keep page sizes reasonable to avoid timeouts
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Ticket IDs are strings
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List tickets | HELPDESK_LIST_TICKETS | silo, sortBy, order, pageSize |
+| List views | HELPDESK_LIST_VIEWS | (none) |
+| List canned responses | HELPDESK_LIST_CANNED_RESPONSES | (none) |
+| List custom fields | HELPDESK_LIST_CUSTOM_FIELDS | (none) |
diff --git a/hubspot-automation/SKILL.md b/hubspot-automation/SKILL.md
new file mode 100644
index 0000000..2bfa77e
--- /dev/null
+++ b/hubspot-automation/SKILL.md
@@ -0,0 +1,175 @@
+---
+name: hubspot-automation
+description: Automate HubSpot CRM operations (contacts, companies, deals, tickets, properties) via Rube MCP using Composio integration.
+requires:
+ mcp: [rube]
+---
+
+# HubSpot CRM Automation via Rube MCP
+
+Automate HubSpot CRM workflows including contact/company management, deal pipeline tracking, ticket search, and custom property creation through Composio's HubSpot toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active HubSpot connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `hubspot`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `hubspot`
+3. If connection is not ACTIVE, follow the returned auth link to complete HubSpot OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Contacts
+
+**When to use**: User wants to create new contacts or update existing ones in HubSpot CRM
+
+**Tool sequence**:
+1. `HUBSPOT_GET_ACCOUNT_INFO` - Verify connection and permissions (Prerequisite)
+2. `HUBSPOT_SEARCH_CONTACTS_BY_CRITERIA` - Search for existing contacts to avoid duplicates (Prerequisite)
+3. `HUBSPOT_READ_A_CRM_PROPERTY_BY_NAME` - Check property metadata for constrained values (Optional)
+4. `HUBSPOT_CREATE_CONTACT` - Create a single contact (Required)
+5. `HUBSPOT_CREATE_CONTACTS` - Batch create contacts up to 100 (Alternative)
+
+**Key parameters**:
+- `HUBSPOT_CREATE_CONTACT`: `properties` object with `email`, `firstname`, `lastname`, `phone`, `company`
+- `HUBSPOT_CREATE_CONTACTS`: `inputs` array of `{properties}` objects, max 100 per batch
+- `HUBSPOT_SEARCH_CONTACTS_BY_CRITERIA`: `filterGroups` array with `{filters: [{propertyName, operator, value}]}`, `properties` array of fields to return
+
+**Pitfalls**:
+- Max 100 records per batch; chunk larger imports
+- 400 'Property values were not valid' if using incorrect property names or enum values
+- Always search before creating to avoid duplicates
+- Auth errors from GET_ACCOUNT_INFO mean all subsequent calls will fail
+
+### 2. Manage Companies
+
+**When to use**: User wants to create, search, or update company records
+
+**Tool sequence**:
+1. `HUBSPOT_SEARCH_COMPANIES` - Search existing companies (Prerequisite)
+2. `HUBSPOT_CREATE_COMPANIES` - Batch create companies, max 100 (Required)
+3. `HUBSPOT_UPDATE_COMPANIES` - Batch update existing companies (Alternative)
+4. `HUBSPOT_GET_COMPANY` - Get single company details (Optional)
+5. `HUBSPOT_BATCH_READ_COMPANIES_BY_PROPERTIES` - Bulk read companies by property values (Optional)
+
+**Key parameters**:
+- `HUBSPOT_CREATE_COMPANIES`: `inputs` array of `{properties}` objects, max 100
+- `HUBSPOT_SEARCH_COMPANIES`: `filterGroups`, `properties`, `sorts`, `limit`, `after` (pagination cursor)
+
+**Pitfalls**:
+- Max 100 per batch; chunk larger sets
+- Store returned IDs immediately for downstream operations
+- Property values must match exact internal names, not display labels
+
+### 3. Manage Deals and Pipeline
+
+**When to use**: User wants to search deals, view pipeline stages, or track deal progress
+
+**Tool sequence**:
+1. `HUBSPOT_RETRIEVE_ALL_PIPELINES_FOR_SPECIFIED_OBJECT_TYPE` - Map pipeline and stage IDs/names (Prerequisite)
+2. `HUBSPOT_SEARCH_DEALS` - Search deals with filters (Required)
+3. `HUBSPOT_RETRIEVE_PIPELINE_STAGES` - Get stage details for one pipeline (Optional)
+4. `HUBSPOT_RETRIEVE_OWNERS` - Get owner/rep details (Optional)
+5. `HUBSPOT_GET_DEAL` - Get single deal details (Optional)
+6. `HUBSPOT_LIST_DEALS` - List all deals without filters (Fallback)
+
+**Key parameters**:
+- `HUBSPOT_SEARCH_DEALS`: `filterGroups` with filters on `pipeline`, `dealstage`, `createdate`, `closedate`, `hubspot_owner_id`; `properties`, `sorts`, `limit`, `after`
+- `HUBSPOT_RETRIEVE_ALL_PIPELINES_FOR_SPECIFIED_OBJECT_TYPE`: `objectType` set to `'deals'`
+
+**Pitfalls**:
+- Results nested under `response.data.results`; properties are often strings (amounts, dates)
+- Stage IDs may be readable strings or opaque numeric IDs; use `label` field for display
+- Filters must use internal property names (`pipeline`, `dealstage`, `createdate`), not display names
+- Paginate via `paging.next.after` until absent
+
+### 4. Search and Filter Tickets
+
+**When to use**: User wants to find support tickets by status, date, or criteria
+
+**Tool sequence**:
+1. `HUBSPOT_SEARCH_TICKETS` - Search with filterGroups (Required)
+2. `HUBSPOT_READ_ALL_PROPERTIES_FOR_OBJECT_TYPE` - Discover available property names (Fallback)
+3. `HUBSPOT_GET_TICKET` - Get single ticket details (Optional)
+4. `HUBSPOT_GET_TICKETS` - Bulk fetch tickets by IDs (Optional)
+
+**Key parameters**:
+- `HUBSPOT_SEARCH_TICKETS`: `filterGroups`, `properties` (only listed fields are returned), `sorts`, `limit`, `after`
+
+**Pitfalls**:
+- Incorrect `propertyName`/`operator` returns zero results without errors
+- Date filtering may require epoch-ms bounds; mixing formats causes mismatches
+- Only fields in the `properties` array are returned; missing ones break downstream logic
+- Use READ_ALL_PROPERTIES to discover exact internal property names
+
+### 5. Create and Manage Custom Properties
+
+**When to use**: User wants to add custom fields to CRM objects
+
+**Tool sequence**:
+1. `HUBSPOT_READ_ALL_PROPERTIES_FOR_OBJECT_TYPE` - List existing properties (Prerequisite)
+2. `HUBSPOT_READ_PROPERTY_GROUPS_FOR_OBJECT_TYPE` - List property groups (Optional)
+3. `HUBSPOT_CREATE_PROPERTY_FOR_SPECIFIED_OBJECT_TYPE` - Create a single property (Required)
+4. `HUBSPOT_CREATE_BATCH_OF_PROPERTIES` - Batch create properties (Alternative)
+5. `HUBSPOT_UPDATE_SPECIFIC_CRM_PROPERTY` - Update existing property definition (Optional)
+
+**Key parameters**:
+- `HUBSPOT_CREATE_PROPERTY_FOR_SPECIFIED_OBJECT_TYPE`: `objectType`, `name`, `label`, `type` (string/number/date/enumeration), `fieldType`, `groupName`, `options` (for enumerations)
+
+**Pitfalls**:
+- Property names are immutable after creation; choose carefully
+- Enumeration options must be pre-defined with `value` and `label`
+- Group must exist before assigning properties to it
+
+## Common Patterns
+
+### ID Resolution
+- **Property display name → internal name**: Use `HUBSPOT_READ_ALL_PROPERTIES_FOR_OBJECT_TYPE`
+- **Pipeline name → pipeline ID**: Use `HUBSPOT_RETRIEVE_ALL_PIPELINES_FOR_SPECIFIED_OBJECT_TYPE`
+- **Stage name → stage ID**: Extract from pipeline stages response
+- **Owner name → owner ID**: Use `HUBSPOT_RETRIEVE_OWNERS`
+
+### Pagination
+- Search endpoints use cursor-based pagination
+- Follow `paging.next.after` until absent
+- Typical limit: 100 records per page
+- Pass `after` value from previous response to get next page
+
+### Batch Operations
+- Most create/update endpoints support batching with max 100 records per call
+- For larger datasets, chunk into groups of 100
+- Store returned IDs from each batch before proceeding
+- Use batch endpoints (`CREATE_CONTACTS`, `CREATE_COMPANIES`, `UPDATE_COMPANIES`) instead of single-record endpoints for efficiency
+
+## Known Pitfalls
+
+- **Property names**: All search/filter endpoints use internal property names, NOT display labels. Always call `READ_ALL_PROPERTIES_FOR_OBJECT_TYPE` to discover correct names
+- **Batch limits**: Max 100 records per batch operation. Larger sets must be chunked
+- **Response structure**: Search results are nested under `response.data.results` with properties as string values
+- **Date formats**: Date properties may be epoch-ms or ISO strings depending on endpoint. Parse defensively
+- **Immutable names**: Property names cannot be changed after creation. Plan naming conventions carefully
+- **Cursor pagination**: Use `paging.next.after` cursor, not page numbers. Continue until `after` is absent
+- **Duplicate prevention**: Always search before creating contacts/companies to avoid duplicates
+- **Auth verification**: Run `HUBSPOT_GET_ACCOUNT_INFO` first; auth failures cascade to all subsequent calls
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create contact | `HUBSPOT_CREATE_CONTACT` | `properties: {email, firstname, lastname}` |
+| Batch create contacts | `HUBSPOT_CREATE_CONTACTS` | `inputs: [{properties}]` (max 100) |
+| Search contacts | `HUBSPOT_SEARCH_CONTACTS_BY_CRITERIA` | `filterGroups, properties, limit, after` |
+| Create companies | `HUBSPOT_CREATE_COMPANIES` | `inputs: [{properties}]` (max 100) |
+| Search companies | `HUBSPOT_SEARCH_COMPANIES` | `filterGroups, properties, after` |
+| Search deals | `HUBSPOT_SEARCH_DEALS` | `filterGroups, properties, after` |
+| Get pipelines | `HUBSPOT_RETRIEVE_ALL_PIPELINES_FOR_SPECIFIED_OBJECT_TYPE` | `objectType: 'deals'` |
+| Search tickets | `HUBSPOT_SEARCH_TICKETS` | `filterGroups, properties, after` |
+| List properties | `HUBSPOT_READ_ALL_PROPERTIES_FOR_OBJECT_TYPE` | `objectType` |
+| Create property | `HUBSPOT_CREATE_PROPERTY_FOR_SPECIFIED_OBJECT_TYPE` | `objectType, name, label, type, fieldType` |
+| Get owners | `HUBSPOT_RETRIEVE_OWNERS` | None |
+| Verify connection | `HUBSPOT_GET_ACCOUNT_INFO` | None |
\ No newline at end of file
diff --git a/instagram-automation/SKILL.md b/instagram-automation/SKILL.md
new file mode 100644
index 0000000..99fdd87
--- /dev/null
+++ b/instagram-automation/SKILL.md
@@ -0,0 +1,189 @@
+---
+name: instagram-automation
+description: Automate Instagram tasks via Rube MCP (Composio): create posts, carousels, manage media, get insights, and publishing limits. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Instagram Automation via Rube MCP
+
+Automate Instagram operations through Composio's Instagram toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Instagram connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `instagram`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+- Instagram Business or Creator account required (personal accounts not supported)
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `instagram`
+3. If connection is not ACTIVE, follow the returned auth link to complete Instagram/Facebook OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create a Single Image/Video Post
+
+**When to use**: User wants to publish a single photo or video to Instagram
+
+**Tool sequence**:
+1. `INSTAGRAM_GET_USER_INFO` - Get Instagram user ID [Prerequisite]
+2. `INSTAGRAM_CREATE_MEDIA_CONTAINER` - Create a media container with the image/video URL [Required]
+3. `INSTAGRAM_GET_POST_STATUS` - Check if the media container is ready [Optional]
+4. `INSTAGRAM_CREATE_POST` or `INSTAGRAM_POST_IG_USER_MEDIA_PUBLISH` - Publish the container [Required]
+
+**Key parameters**:
+- `image_url`: Public URL of the image to post
+- `video_url`: Public URL of the video to post
+- `caption`: Post caption text
+- `ig_user_id`: Instagram Business account user ID
+
+**Pitfalls**:
+- Media URLs must be publicly accessible; private/authenticated URLs will fail
+- Video containers may take time to process; poll GET_POST_STATUS before publishing
+- Caption supports hashtags and mentions but has a 2200 character limit
+- Publishing a container that is not yet finished processing returns an error
+
+### 2. Create a Carousel Post
+
+**When to use**: User wants to publish multiple images/videos in a single carousel post
+
+**Tool sequence**:
+1. `INSTAGRAM_CREATE_MEDIA_CONTAINER` - Create individual containers for each media item [Required, repeat per item]
+2. `INSTAGRAM_CREATE_CAROUSEL_CONTAINER` - Create the carousel container referencing all media containers [Required]
+3. `INSTAGRAM_GET_POST_STATUS` - Check carousel container readiness [Optional]
+4. `INSTAGRAM_POST_IG_USER_MEDIA_PUBLISH` - Publish the carousel [Required]
+
+**Key parameters**:
+- `children`: Array of media container IDs for the carousel
+- `caption`: Carousel post caption
+- `ig_user_id`: Instagram Business account user ID
+
+**Pitfalls**:
+- Carousels require 2-10 media items; fewer or more will fail
+- Each child container must be created individually before the carousel container
+- All child containers must be fully processed before creating the carousel
+- Mixed media (images + videos) is supported in carousels
+
+### 3. Get Media and Insights
+
+**When to use**: User wants to view their posts or analyze post performance
+
+**Tool sequence**:
+1. `INSTAGRAM_GET_IG_USER_MEDIA` or `INSTAGRAM_GET_USER_MEDIA` - List user's media [Required]
+2. `INSTAGRAM_GET_IG_MEDIA` - Get details for a specific post [Optional]
+3. `INSTAGRAM_GET_POST_INSIGHTS` or `INSTAGRAM_GET_IG_MEDIA_INSIGHTS` - Get metrics for a post [Optional]
+4. `INSTAGRAM_GET_USER_INSIGHTS` - Get account-level insights [Optional]
+
+**Key parameters**:
+- `ig_user_id`: Instagram Business account user ID
+- `media_id`: ID of the specific media post
+- `metric`: Metrics to retrieve (e.g., impressions, reach, engagement)
+- `period`: Time period for insights (e.g., day, week, lifetime)
+
+**Pitfalls**:
+- Insights are only available for Business/Creator accounts
+- Some metrics require minimum follower counts
+- Insight data may have a delay of up to 48 hours
+- The `period` parameter must match the metric type
+
+### 4. Check Publishing Limits
+
+**When to use**: User wants to verify they can publish before attempting a post
+
+**Tool sequence**:
+1. `INSTAGRAM_GET_IG_USER_CONTENT_PUBLISHING_LIMIT` - Check remaining publishing quota [Required]
+
+**Key parameters**:
+- `ig_user_id`: Instagram Business account user ID
+
+**Pitfalls**:
+- Instagram enforces a 25 posts per 24-hour rolling window limit
+- Publishing limit resets on a rolling basis, not at midnight
+- Check limits before bulk posting operations to avoid failures
+
+### 5. Get Media Comments and Children
+
+**When to use**: User wants to view comments on a post or children of a carousel
+
+**Tool sequence**:
+1. `INSTAGRAM_GET_IG_MEDIA_COMMENTS` - List comments on a media post [Required]
+2. `INSTAGRAM_GET_IG_MEDIA_CHILDREN` - List children of a carousel post [Optional]
+
+**Key parameters**:
+- `media_id`: ID of the media post
+- `ig_media_id`: Alternative media ID parameter
+
+**Pitfalls**:
+- Comments may be paginated; follow pagination cursors for complete results
+- Carousel children are returned as individual media objects
+- Comment moderation settings on the account affect what is returned
+
+## Common Patterns
+
+### ID Resolution
+
+**Instagram User ID**:
+```
+1. Call INSTAGRAM_GET_USER_INFO
+2. Extract ig_user_id from response
+3. Use in all subsequent API calls
+```
+
+**Media Container Status Check**:
+```
+1. Call INSTAGRAM_CREATE_MEDIA_CONTAINER
+2. Extract container_id from response
+3. Poll INSTAGRAM_GET_POST_STATUS with container_id
+4. Wait until status is 'FINISHED' before publishing
+```
+
+### Two-Phase Publishing
+
+- Phase 1: Create media container(s) with content URLs
+- Phase 2: Publish the container after it finishes processing
+- Always check container status between phases for video content
+- For carousels, all children must complete Phase 1 before creating the carousel container
+
+## Known Pitfalls
+
+**Media URLs**:
+- All image/video URLs must be publicly accessible HTTPS URLs
+- URLs behind authentication, CDN restrictions, or that require cookies will fail
+- Temporary URLs (pre-signed S3, etc.) may expire before processing completes
+
+**Rate Limits**:
+- 25 posts per 24-hour rolling window
+- API rate limits apply separately from publishing limits
+- Implement exponential backoff for 429 responses
+
+**Account Requirements**:
+- Only Business or Creator Instagram accounts are supported
+- Personal accounts cannot use the Instagram Graph API
+- The account must be connected to a Facebook Page
+
+**Response Parsing**:
+- Media IDs are numeric strings
+- Insights data may be nested under different response keys
+- Pagination uses cursor-based tokens
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Get user info | INSTAGRAM_GET_USER_INFO | (none) |
+| Create media container | INSTAGRAM_CREATE_MEDIA_CONTAINER | image_url/video_url, caption |
+| Create carousel | INSTAGRAM_CREATE_CAROUSEL_CONTAINER | children, caption |
+| Publish post | INSTAGRAM_CREATE_POST | ig_user_id, creation_id |
+| Publish media | INSTAGRAM_POST_IG_USER_MEDIA_PUBLISH | ig_user_id, creation_id |
+| Check post status | INSTAGRAM_GET_POST_STATUS | ig_container_id |
+| List user media | INSTAGRAM_GET_IG_USER_MEDIA | ig_user_id |
+| Get media details | INSTAGRAM_GET_IG_MEDIA | ig_media_id |
+| Get post insights | INSTAGRAM_GET_POST_INSIGHTS | media_id, metric |
+| Get user insights | INSTAGRAM_GET_USER_INSIGHTS | ig_user_id, metric, period |
+| Get publishing limit | INSTAGRAM_GET_IG_USER_CONTENT_PUBLISHING_LIMIT | ig_user_id |
+| Get media comments | INSTAGRAM_GET_IG_MEDIA_COMMENTS | ig_media_id |
+| Get carousel children | INSTAGRAM_GET_IG_MEDIA_CHILDREN | ig_media_id |
diff --git a/intercom-automation/SKILL.md b/intercom-automation/SKILL.md
new file mode 100644
index 0000000..3c9d918
--- /dev/null
+++ b/intercom-automation/SKILL.md
@@ -0,0 +1,245 @@
+---
+name: intercom-automation
+description: Automate Intercom tasks via Rube MCP (Composio): conversations, contacts, companies, segments, admins. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Intercom Automation via Rube MCP
+
+Automate Intercom operations through Composio's Intercom toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Intercom connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `intercom`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `intercom`
+3. If connection is not ACTIVE, follow the returned auth link to complete Intercom OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Conversations
+
+**When to use**: User wants to create, list, search, or manage support conversations
+
+**Tool sequence**:
+1. `INTERCOM_LIST_ALL_ADMINS` - Get admin IDs for assignment [Prerequisite]
+2. `INTERCOM_LIST_CONVERSATIONS` - List all conversations [Optional]
+3. `INTERCOM_SEARCH_CONVERSATIONS` - Search with filters [Optional]
+4. `INTERCOM_GET_CONVERSATION` - Get conversation details [Optional]
+5. `INTERCOM_CREATE_CONVERSATION` - Create a new conversation [Optional]
+
+**Key parameters**:
+- `from`: Object with `type` ('user'/'lead') and `id` for conversation creator
+- `body`: Message body (HTML supported)
+- `id`: Conversation ID for retrieval
+- `query`: Search query object with `field`, `operator`, `value`
+
+**Pitfalls**:
+- CREATE_CONVERSATION requires a contact (user/lead) as the `from` field, not an admin
+- Conversation bodies support HTML; plain text is auto-wrapped in `` tags
+- Search query uses structured filter objects, not free-text search
+- Conversation IDs are numeric strings
+
+### 2. Reply and Manage Conversation State
+
+**When to use**: User wants to reply to, close, reopen, or assign conversations
+
+**Tool sequence**:
+1. `INTERCOM_GET_CONVERSATION` - Get current state [Prerequisite]
+2. `INTERCOM_REPLY_TO_CONVERSATION` - Add a reply [Optional]
+3. `INTERCOM_ASSIGN_CONVERSATION` - Assign to admin/team [Optional]
+4. `INTERCOM_CLOSE_CONVERSATION` - Close conversation [Optional]
+5. `INTERCOM_REOPEN_CONVERSATION` - Reopen closed conversation [Optional]
+
+**Key parameters**:
+- `conversation_id` / `id`: Conversation ID
+- `body`: Reply message body (HTML supported)
+- `type`: Reply type ('admin' or 'user')
+- `admin_id`: Admin ID for replies from admin, assignment, and close/reopen
+- `assignee_id`: Admin or team ID for assignment
+- `message_type`: 'comment' (default) or 'note' (internal)
+
+**Pitfalls**:
+- `admin_id` is REQUIRED for admin replies, close, reopen, and assignment operations
+- Always fetch admin IDs first with LIST_ALL_ADMINS or IDENTIFY_AN_ADMIN
+- Duplicate sends can occur on retry; implement idempotency checks
+- Internal notes use `message_type: 'note'`; visible only to workspace members
+- Closing requires an admin_id and optional body message
+
+### 3. Manage Contacts
+
+**When to use**: User wants to search, view, or manage contacts (users and leads)
+
+**Tool sequence**:
+1. `INTERCOM_SEARCH_CONTACTS` - Search contacts with filters [Required]
+2. `INTERCOM_GET_A_CONTACT` - Get specific contact [Optional]
+3. `INTERCOM_SHOW_CONTACT_BY_EXTERNAL_ID` - Look up by external ID [Optional]
+4. `INTERCOM_LIST_CONTACTS` - List all contacts [Optional]
+5. `INTERCOM_LIST_TAGS_ATTACHED_TO_A_CONTACT` - Get contact tags [Optional]
+6. `INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_CONTACT` - Get contact segments [Optional]
+7. `INTERCOM_DETACH_A_CONTACT` - Remove contact from company [Optional]
+
+**Key parameters**:
+- `contact_id`: Contact ID for retrieval
+- `external_id`: External system ID for lookup
+- `query`: Search filter object with `field`, `operator`, `value`
+- `pagination`: Object with `per_page` and `starting_after` cursor
+
+**Pitfalls**:
+- SEARCH_CONTACTS uses structured query filters, not free-text; format: `{field, operator, value}`
+- Supported operators: `=`, `!=`, `>`, `<`, `~` (contains), `!~` (not contains), `IN`, `NIN`
+- Contact types are 'user' (identified) or 'lead' (anonymous)
+- LIST_CONTACTS returns paginated results; use `starting_after` cursor for pagination
+- External IDs are case-sensitive
+
+### 4. Manage Admins and Teams
+
+**When to use**: User wants to list workspace admins or identify specific admins
+
+**Tool sequence**:
+1. `INTERCOM_LIST_ALL_ADMINS` - List all admins and teams [Required]
+2. `INTERCOM_IDENTIFY_AN_ADMIN` - Get specific admin details [Optional]
+
+**Key parameters**:
+- `admin_id`: Admin ID for identification
+
+**Pitfalls**:
+- LIST_ALL_ADMINS returns both admins and teams
+- Admin IDs are required for conversation replies, assignment, close, and reopen
+- Teams appear in the admins list with `type: 'team'`
+
+### 5. View Segments and Counts
+
+**When to use**: User wants to view segments or get aggregate counts
+
+**Tool sequence**:
+1. `INTERCOM_LIST_SEGMENTS` - List all segments [Optional]
+2. `INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_CONTACT` - Segments for a contact [Optional]
+3. `INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_COMPANIES` - Segments for a company [Optional]
+4. `INTERCOM_GET_COUNTS` - Get aggregate counts [Optional]
+
+**Key parameters**:
+- `contact_id`: Contact ID for segment lookup
+- `company_id`: Company ID for segment lookup
+- `type`: Count type ('conversation', 'company', 'user', 'tag', 'segment')
+- `count`: Sub-count type
+
+**Pitfalls**:
+- GET_COUNTS returns approximate counts, not exact numbers
+- Segment membership is computed; changes may not reflect immediately
+
+### 6. Manage Companies
+
+**When to use**: User wants to list companies or manage company-contact relationships
+
+**Tool sequence**:
+1. `INTERCOM_LIST_ALL_COMPANIES` - List all companies [Required]
+2. `INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_COMPANIES` - Get company segments [Optional]
+3. `INTERCOM_DETACH_A_CONTACT` - Remove contact from company [Optional]
+
+**Key parameters**:
+- `company_id`: Company ID
+- `contact_id`: Contact ID for detachment
+- `page`: Page number for pagination
+- `per_page`: Results per page
+
+**Pitfalls**:
+- Company-contact relationships are managed through contact endpoints
+- DETACH_A_CONTACT removes the contact-company association, not the contact itself
+
+## Common Patterns
+
+### Search Query Filters
+
+**Single filter**:
+```json
+{
+ "field": "email",
+ "operator": "=",
+ "value": "user@example.com"
+}
+```
+
+**Multiple filters (AND)**:
+```json
+{
+ "operator": "AND",
+ "value": [
+ {"field": "role", "operator": "=", "value": "user"},
+ {"field": "created_at", "operator": ">", "value": 1672531200}
+ ]
+}
+```
+
+**Supported fields for contacts**: email, name, role, created_at, updated_at, signed_up_at, last_seen_at, external_id
+
+**Supported fields for conversations**: created_at, updated_at, source.type, state, open, read
+
+### Pagination
+
+- Most list endpoints use cursor-based pagination
+- Check response for `pages.next` with `starting_after` cursor
+- Pass cursor in `pagination.starting_after` for next page
+- Continue until `pages.next` is null
+
+### Admin ID Resolution
+
+```
+1. Call INTERCOM_LIST_ALL_ADMINS to get all admins
+2. Find the desired admin by name or email
+3. Use admin.id for replies, assignments, and state changes
+```
+
+## Known Pitfalls
+
+**Admin ID Requirement**:
+- Admin ID is required for: reply (as admin), assign, close, reopen
+- Always resolve admin IDs first with LIST_ALL_ADMINS
+
+**HTML Content**:
+- Conversation bodies are HTML
+- Plain text is auto-wrapped in paragraph tags
+- Sanitize HTML input to prevent rendering issues
+
+**Idempotency**:
+- Replies and conversation creation are not idempotent
+- Duplicate sends can occur on retry or timeout
+- Track message IDs to prevent duplicates
+
+**Rate Limits**:
+- Default: ~1000 requests per minute (varies by plan)
+- 429 responses include rate limit headers
+- Implement exponential backoff for retries
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List conversations | INTERCOM_LIST_CONVERSATIONS | (pagination) |
+| Search conversations | INTERCOM_SEARCH_CONVERSATIONS | query |
+| Get conversation | INTERCOM_GET_CONVERSATION | id |
+| Create conversation | INTERCOM_CREATE_CONVERSATION | from, body |
+| Reply to conversation | INTERCOM_REPLY_TO_CONVERSATION | conversation_id, body, admin_id |
+| Assign conversation | INTERCOM_ASSIGN_CONVERSATION | conversation_id, admin_id, assignee_id |
+| Close conversation | INTERCOM_CLOSE_CONVERSATION | id, admin_id |
+| Reopen conversation | INTERCOM_REOPEN_CONVERSATION | id, admin_id |
+| Search contacts | INTERCOM_SEARCH_CONTACTS | query |
+| Get contact | INTERCOM_GET_A_CONTACT | contact_id |
+| Contact by external ID | INTERCOM_SHOW_CONTACT_BY_EXTERNAL_ID | external_id |
+| List contacts | INTERCOM_LIST_CONTACTS | (pagination) |
+| Contact tags | INTERCOM_LIST_TAGS_ATTACHED_TO_A_CONTACT | contact_id |
+| Contact segments | INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_CONTACT | contact_id |
+| Detach contact | INTERCOM_DETACH_A_CONTACT | contact_id, company_id |
+| List admins | INTERCOM_LIST_ALL_ADMINS | (none) |
+| Identify admin | INTERCOM_IDENTIFY_AN_ADMIN | admin_id |
+| List segments | INTERCOM_LIST_SEGMENTS | (none) |
+| Company segments | INTERCOM_LIST_ATTACHED_SEGMENTS_FOR_COMPANIES | company_id |
+| Get counts | INTERCOM_GET_COUNTS | type, count |
+| List companies | INTERCOM_LIST_ALL_COMPANIES | page, per_page |
diff --git a/jira-automation/SKILL.md b/jira-automation/SKILL.md
new file mode 100644
index 0000000..42e4b2c
--- /dev/null
+++ b/jira-automation/SKILL.md
@@ -0,0 +1,182 @@
+---
+name: jira-automation
+description: Automate Jira tasks via Rube MCP (Composio): issues, projects, sprints, boards, comments, users. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Jira Automation via Rube MCP
+
+Automate Jira operations through Composio's Jira toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Jira connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `jira`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `jira`
+3. If connection is not ACTIVE, follow the returned auth link to complete Jira OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search and Filter Issues
+
+**When to use**: User wants to find issues using JQL or browse project issues
+
+**Tool sequence**:
+1. `JIRA_SEARCH_FOR_ISSUES_USING_JQL_POST` - Search with JQL query [Required]
+2. `JIRA_GET_ISSUE` - Get full details of a specific issue [Optional]
+
+**Key parameters**:
+- `jql`: JQL query string (e.g., `project = PROJ AND status = "In Progress"`)
+- `maxResults`: Max results per page (default 50, max 100)
+- `startAt`: Pagination offset
+- `fields`: Array of field names to return
+- `issueIdOrKey`: Issue key like 'PROJ-123' for GET_ISSUE
+
+**Pitfalls**:
+- JQL field names are case-sensitive and must match Jira configuration
+- Custom fields use IDs like `customfield_10001`, not display names
+- Results are paginated; check `total` vs `startAt + maxResults` to continue
+
+### 2. Create and Edit Issues
+
+**When to use**: User wants to create new issues or update existing ones
+
+**Tool sequence**:
+1. `JIRA_GET_ALL_PROJECTS` - List projects to find project key [Prerequisite]
+2. `JIRA_GET_FIELDS` - Get available fields and their IDs [Prerequisite]
+3. `JIRA_CREATE_ISSUE` - Create a new issue [Required]
+4. `JIRA_EDIT_ISSUE` - Update fields on an existing issue [Optional]
+5. `JIRA_ASSIGN_ISSUE` - Assign issue to a user [Optional]
+
+**Key parameters**:
+- `project`: Project key (e.g., 'PROJ')
+- `issuetype`: Issue type name (e.g., 'Bug', 'Story', 'Task')
+- `summary`: Issue title
+- `description`: Issue description (Atlassian Document Format or plain text)
+- `issueIdOrKey`: Issue key for edits
+
+**Pitfalls**:
+- Issue types and required fields vary by project; use GET_FIELDS to check
+- Custom fields require exact field IDs, not display names
+- Description may need Atlassian Document Format (ADF) for rich content
+
+### 3. Manage Sprints and Boards
+
+**When to use**: User wants to work with agile boards, sprints, and backlogs
+
+**Tool sequence**:
+1. `JIRA_LIST_BOARDS` - List all boards [Prerequisite]
+2. `JIRA_LIST_SPRINTS` - List sprints for a board [Required]
+3. `JIRA_MOVE_ISSUE_TO_SPRINT` - Move issue to a sprint [Optional]
+4. `JIRA_CREATE_SPRINT` - Create a new sprint [Optional]
+
+**Key parameters**:
+- `boardId`: Board ID from LIST_BOARDS
+- `sprintId`: Sprint ID for move operations
+- `name`: Sprint name for creation
+- `startDate`/`endDate`: Sprint dates in ISO format
+
+**Pitfalls**:
+- Boards and sprints are specific to Jira Software (not Jira Core)
+- Only one sprint can be active at a time per board
+
+### 4. Manage Comments
+
+**When to use**: User wants to add or view comments on issues
+
+**Tool sequence**:
+1. `JIRA_LIST_ISSUE_COMMENTS` - List existing comments [Optional]
+2. `JIRA_ADD_COMMENT` - Add a comment to an issue [Required]
+
+**Key parameters**:
+- `issueIdOrKey`: Issue key like 'PROJ-123'
+- `body`: Comment body (supports ADF for rich text)
+
+**Pitfalls**:
+- Comments support ADF (Atlassian Document Format) for formatting
+- Mentions use account IDs, not usernames
+
+### 5. Manage Projects and Users
+
+**When to use**: User wants to list projects, find users, or manage project roles
+
+**Tool sequence**:
+1. `JIRA_GET_ALL_PROJECTS` - List all projects [Optional]
+2. `JIRA_GET_PROJECT` - Get project details [Optional]
+3. `JIRA_FIND_USERS` / `JIRA_GET_ALL_USERS` - Search for users [Optional]
+4. `JIRA_GET_PROJECT_ROLES` - List project roles [Optional]
+5. `JIRA_ADD_USERS_TO_PROJECT_ROLE` - Add user to role [Optional]
+
+**Key parameters**:
+- `projectIdOrKey`: Project key
+- `query`: Search text for FIND_USERS
+- `roleId`: Role ID for role operations
+
+**Pitfalls**:
+- User operations use account IDs (not email or display name)
+- Project roles differ from global permissions
+
+## Common Patterns
+
+### JQL Syntax
+
+**Common operators**:
+- `project = "PROJ"` - Filter by project
+- `status = "In Progress"` - Filter by status
+- `assignee = currentUser()` - Current user's issues
+- `created >= -7d` - Created in last 7 days
+- `labels = "bug"` - Filter by label
+- `priority = High` - Filter by priority
+- `ORDER BY created DESC` - Sort results
+
+**Combinators**:
+- `AND` - Both conditions
+- `OR` - Either condition
+- `NOT` - Negate condition
+
+### Pagination
+
+- Use `startAt` and `maxResults` parameters
+- Check `total` in response to determine remaining pages
+- Continue until `startAt + maxResults >= total`
+
+## Known Pitfalls
+
+**Field Names**:
+- Custom fields use IDs like `customfield_10001`
+- Use JIRA_GET_FIELDS to discover field IDs and names
+- Field names in JQL may differ from API field names
+
+**Authentication**:
+- Jira Cloud uses account IDs, not usernames
+- Site URL must be configured correctly in the connection
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search issues (JQL) | JIRA_SEARCH_FOR_ISSUES_USING_JQL_POST | jql, maxResults |
+| Get issue | JIRA_GET_ISSUE | issueIdOrKey |
+| Create issue | JIRA_CREATE_ISSUE | project, issuetype, summary |
+| Edit issue | JIRA_EDIT_ISSUE | issueIdOrKey, fields |
+| Assign issue | JIRA_ASSIGN_ISSUE | issueIdOrKey, accountId |
+| Add comment | JIRA_ADD_COMMENT | issueIdOrKey, body |
+| List comments | JIRA_LIST_ISSUE_COMMENTS | issueIdOrKey |
+| List projects | JIRA_GET_ALL_PROJECTS | (none) |
+| Get project | JIRA_GET_PROJECT | projectIdOrKey |
+| List boards | JIRA_LIST_BOARDS | (none) |
+| List sprints | JIRA_LIST_SPRINTS | boardId |
+| Move to sprint | JIRA_MOVE_ISSUE_TO_SPRINT | sprintId, issues |
+| Create sprint | JIRA_CREATE_SPRINT | name, boardId |
+| Find users | JIRA_FIND_USERS | query |
+| Get fields | JIRA_GET_FIELDS | (none) |
+| List filters | JIRA_LIST_FILTERS | (none) |
+| Project roles | JIRA_GET_PROJECT_ROLES | projectIdOrKey |
+| Project versions | JIRA_GET_PROJECT_VERSIONS | projectIdOrKey |
diff --git a/klaviyo-automation/SKILL.md b/klaviyo-automation/SKILL.md
new file mode 100644
index 0000000..1038fb7
--- /dev/null
+++ b/klaviyo-automation/SKILL.md
@@ -0,0 +1,187 @@
+---
+name: klaviyo-automation
+description: Automate Klaviyo tasks via Rube MCP (Composio): manage email/SMS campaigns, inspect campaign messages, track tags, and monitor send jobs. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Klaviyo Automation via Rube MCP
+
+Automate Klaviyo email and SMS marketing operations through Composio's Klaviyo toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Klaviyo connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `klaviyo`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `klaviyo`
+3. If connection is not ACTIVE, follow the returned auth link to complete Klaviyo authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Filter Campaigns
+
+**When to use**: User wants to browse, search, or filter marketing campaigns
+
+**Tool sequence**:
+1. `KLAVIYO_GET_CAMPAIGNS` - List campaigns with channel and status filters [Required]
+
+**Key parameters**:
+- `channel`: Campaign channel - 'email' or 'sms' (required by Klaviyo API)
+- `filter`: Additional filter string (e.g., `equals(status,"draft")`)
+- `sort`: Sort field with optional `-` prefix for descending (e.g., '-created_at', 'name')
+- `page_cursor`: Pagination cursor for next page
+- `include_archived`: Include archived campaigns (default: false)
+
+**Pitfalls**:
+- `channel` is required; omitting it can produce incomplete or unexpected results
+- Pagination is mandatory for full coverage; a single call returns only one page (default ~10)
+- Follow `page_cursor` until exhausted to get all campaigns
+- Status filtering via `filter` (e.g., `equals(status,"draft")`) can return mixed statuses; always validate `data[].attributes.status` client-side
+- Status strings are case-sensitive and can be compound (e.g., 'Cancelled: No Recipients')
+- Response shape is nested: `response.data.data` with status at `data[].attributes.status`
+
+### 2. Get Campaign Details
+
+**When to use**: User wants detailed information about a specific campaign
+
+**Tool sequence**:
+1. `KLAVIYO_GET_CAMPAIGNS` - Find campaign to get its ID [Prerequisite]
+2. `KLAVIYO_GET_CAMPAIGN` - Retrieve full campaign details [Required]
+
+**Key parameters**:
+- `campaign_id`: Campaign ID string (e.g., '01GDDKASAP8TKDDA2GRZDSVP4H')
+- `include_messages`: Include campaign messages in response
+- `include_tags`: Include tags in response
+
+**Pitfalls**:
+- Campaign IDs are alphanumeric strings, not numeric
+- `include_messages` and `include_tags` add related data to the response via Klaviyo's include mechanism
+- Campaign details include audiences, send strategy, tracking options, and scheduling info
+
+### 3. Inspect Campaign Messages
+
+**When to use**: User wants to view the email/SMS content of a campaign
+
+**Tool sequence**:
+1. `KLAVIYO_GET_CAMPAIGN` - Find campaign and its message IDs [Prerequisite]
+2. `KLAVIYO_GET_CAMPAIGN_MESSAGE` - Get message content details [Required]
+
+**Key parameters**:
+- `id`: Message ID string
+- `fields__campaign__message`: Sparse fieldset for message attributes (e.g., 'content.subject', 'content.from_email', 'content.body')
+- `fields__campaign`: Sparse fieldset for campaign attributes
+- `fields__template`: Sparse fieldset for template attributes
+- `include`: Related resources to include ('campaign', 'template')
+
+**Pitfalls**:
+- Message IDs are separate from campaign IDs; extract from campaign response
+- Sparse fieldset syntax uses dot notation for nested fields: 'content.subject', 'content.from_email'
+- Email messages have content fields: subject, preview_text, from_email, from_label, reply_to_email
+- SMS messages have content fields: body
+- Including 'template' provides the HTML/text content of the email
+
+### 4. Manage Campaign Tags
+
+**When to use**: User wants to view tags associated with campaigns for organization
+
+**Tool sequence**:
+1. `KLAVIYO_GET_CAMPAIGN_RELATIONSHIPS_TAGS` - Get tag IDs for a campaign [Required]
+
+**Key parameters**:
+- `id`: Campaign ID string
+
+**Pitfalls**:
+- Returns only tag IDs, not tag names/details
+- Tag IDs can be used with Klaviyo's tag endpoints for full details
+- Rate limit: 3/s burst, 60/m steady (stricter than other endpoints)
+
+### 5. Monitor Campaign Send Jobs
+
+**When to use**: User wants to check the status of a campaign send operation
+
+**Tool sequence**:
+1. `KLAVIYO_GET_CAMPAIGN_SEND_JOB` - Check send job status [Required]
+
+**Key parameters**:
+- `id`: Send job ID
+
+**Pitfalls**:
+- Send job IDs are returned when a campaign send is initiated
+- Job statuses indicate whether the send is queued, in progress, complete, or failed
+- Rate limit: 10/s burst, 150/m steady
+
+## Common Patterns
+
+### Campaign Discovery Pattern
+
+```
+1. Call KLAVIYO_GET_CAMPAIGNS with channel='email'
+2. Paginate through all results via page_cursor
+3. Filter by status client-side for accuracy
+4. Extract campaign IDs for detailed inspection
+```
+
+### Sparse Fieldset Pattern
+
+Klaviyo supports sparse fieldsets to reduce response size:
+```
+fields__campaign__message=['content.subject', 'content.from_email', 'send_times']
+fields__campaign=['name', 'status', 'send_time']
+fields__template=['name', 'html', 'text']
+```
+
+### Pagination
+
+- Klaviyo uses cursor-based pagination
+- Check response for `page_cursor` in the pagination metadata
+- Pass cursor as `page_cursor` in next request
+- Default page size is ~10 campaigns
+- Continue until no more cursor is returned
+
+### Filter Syntax
+
+```
+- equals(status,"draft") - Campaigns in draft status
+- equals(name,"Newsletter") - Campaign named "Newsletter"
+- greater-than(created_at,"2024-01-01T00:00:00Z") - Created after date
+```
+
+## Known Pitfalls
+
+**API Version**:
+- Klaviyo API uses versioned endpoints (e.g., v2024-07-15)
+- Response schemas may change between API versions
+- Tool responses follow the version configured in the Composio integration
+
+**Response Nesting**:
+- Data is nested: `response.data.data[].attributes`
+- Campaign status at `data[].attributes.status`
+- Mis-parsing the nesting yields empty or incorrect results
+- Always navigate through the full path defensively
+
+**Rate Limits**:
+- Burst: 10/s (3/s for tag endpoints)
+- Steady: 150/m (60/m for tag endpoints)
+- Required scope: campaigns:read
+- Implement backoff on 429 responses
+
+**Status Values**:
+- Status strings are case-sensitive
+- Compound statuses exist (e.g., 'Cancelled: No Recipients')
+- Server-side filtering may return mixed statuses; always validate client-side
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List campaigns | KLAVIYO_GET_CAMPAIGNS | channel, filter, sort, page_cursor |
+| Get campaign details | KLAVIYO_GET_CAMPAIGN | campaign_id, include_messages, include_tags |
+| Get campaign message | KLAVIYO_GET_CAMPAIGN_MESSAGE | id, fields__campaign__message |
+| Get campaign tags | KLAVIYO_GET_CAMPAIGN_RELATIONSHIPS_TAGS | id |
+| Get send job status | KLAVIYO_GET_CAMPAIGN_SEND_JOB | id |
diff --git a/linear-automation/SKILL.md b/linear-automation/SKILL.md
new file mode 100644
index 0000000..9f2f066
--- /dev/null
+++ b/linear-automation/SKILL.md
@@ -0,0 +1,175 @@
+---
+name: linear-automation
+description: Automate Linear tasks via Rube MCP (Composio): issues, projects, cycles, teams, labels. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Linear Automation via Rube MCP
+
+Automate Linear operations through Composio's Linear toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Linear connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `linear`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `linear`
+3. If connection is not ACTIVE, follow the returned auth link to complete Linear OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Issues
+
+**When to use**: User wants to create, search, update, or list Linear issues
+
+**Tool sequence**:
+1. `LINEAR_GET_ALL_LINEAR_TEAMS` - Get team IDs [Prerequisite]
+2. `LINEAR_LIST_LINEAR_STATES` - Get workflow states for a team [Prerequisite]
+3. `LINEAR_CREATE_LINEAR_ISSUE` - Create a new issue [Optional]
+4. `LINEAR_SEARCH_ISSUES` / `LINEAR_LIST_LINEAR_ISSUES` - Find issues [Optional]
+5. `LINEAR_GET_LINEAR_ISSUE` - Get issue details [Optional]
+6. `LINEAR_UPDATE_ISSUE` - Update issue properties [Optional]
+
+**Key parameters**:
+- `team_id`: Team ID (required for creation)
+- `title`: Issue title
+- `description`: Issue description (Markdown supported)
+- `state_id`: Workflow state ID
+- `assignee_id`: Assignee user ID
+- `priority`: 0 (none), 1 (urgent), 2 (high), 3 (medium), 4 (low)
+- `label_ids`: Array of label IDs
+
+**Pitfalls**:
+- Team ID is required when creating issues; use GET_ALL_LINEAR_TEAMS first
+- State IDs are team-specific; use LIST_LINEAR_STATES with the correct team
+- Priority uses integer values 0-4, not string names
+
+### 2. Manage Projects
+
+**When to use**: User wants to create or update Linear projects
+
+**Tool sequence**:
+1. `LINEAR_LIST_LINEAR_PROJECTS` - List existing projects [Optional]
+2. `LINEAR_CREATE_LINEAR_PROJECT` - Create a new project [Optional]
+3. `LINEAR_UPDATE_LINEAR_PROJECT` - Update project details [Optional]
+
+**Key parameters**:
+- `name`: Project name
+- `description`: Project description
+- `team_ids`: Array of team IDs associated with the project
+- `state`: Project state (e.g., 'planned', 'started', 'completed')
+
+**Pitfalls**:
+- Projects span teams; they can be associated with multiple teams
+
+### 3. Manage Cycles
+
+**When to use**: User wants to work with Linear cycles (sprints)
+
+**Tool sequence**:
+1. `LINEAR_GET_ALL_LINEAR_TEAMS` - Get team ID [Prerequisite]
+2. `LINEAR_GET_CYCLES_BY_TEAM_ID` / `LINEAR_LIST_LINEAR_CYCLES` - List cycles [Required]
+
+**Key parameters**:
+- `team_id`: Team ID for cycle operations
+- `number`: Cycle number
+
+**Pitfalls**:
+- Cycles are team-specific; always scope by team_id
+
+### 4. Manage Labels and Comments
+
+**When to use**: User wants to create labels or comment on issues
+
+**Tool sequence**:
+1. `LINEAR_CREATE_LINEAR_LABEL` - Create a new label [Optional]
+2. `LINEAR_CREATE_LINEAR_COMMENT` - Comment on an issue [Optional]
+3. `LINEAR_UPDATE_LINEAR_COMMENT` - Edit a comment [Optional]
+
+**Key parameters**:
+- `name`: Label name
+- `color`: Label color (hex)
+- `issue_id`: Issue ID for comments
+- `body`: Comment body (Markdown)
+
+**Pitfalls**:
+- Labels can be team-scoped or workspace-scoped
+- Comment body supports Markdown formatting
+
+### 5. Custom GraphQL Queries
+
+**When to use**: User needs advanced queries not covered by standard tools
+
+**Tool sequence**:
+1. `LINEAR_RUN_QUERY_OR_MUTATION` - Execute custom GraphQL [Required]
+
+**Key parameters**:
+- `query`: GraphQL query or mutation string
+- `variables`: Variables for the query
+
+**Pitfalls**:
+- Requires knowledge of Linear's GraphQL schema
+- Rate limits apply to GraphQL queries
+
+## Common Patterns
+
+### ID Resolution
+
+**Team name -> Team ID**:
+```
+1. Call LINEAR_GET_ALL_LINEAR_TEAMS
+2. Find team by name in response
+3. Extract id field
+```
+
+**State name -> State ID**:
+```
+1. Call LINEAR_LIST_LINEAR_STATES with team_id
+2. Find state by name
+3. Extract id field
+```
+
+### Pagination
+
+- Linear tools return paginated results
+- Check for pagination cursors in responses
+- Pass cursor to next request for additional pages
+
+## Known Pitfalls
+
+**Team Scoping**:
+- Issues, states, and cycles are team-specific
+- Always resolve team_id before creating issues
+
+**Priority Values**:
+- 0 = No priority, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low
+- Use integer values, not string names
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List teams | LINEAR_GET_ALL_LINEAR_TEAMS | (none) |
+| Create issue | LINEAR_CREATE_LINEAR_ISSUE | team_id, title, description |
+| Search issues | LINEAR_SEARCH_ISSUES | query |
+| List issues | LINEAR_LIST_LINEAR_ISSUES | team_id, filters |
+| Get issue | LINEAR_GET_LINEAR_ISSUE | issue_id |
+| Update issue | LINEAR_UPDATE_ISSUE | issue_id, fields |
+| List states | LINEAR_LIST_LINEAR_STATES | team_id |
+| List projects | LINEAR_LIST_LINEAR_PROJECTS | (none) |
+| Create project | LINEAR_CREATE_LINEAR_PROJECT | name, team_ids |
+| Update project | LINEAR_UPDATE_LINEAR_PROJECT | project_id, fields |
+| List cycles | LINEAR_LIST_LINEAR_CYCLES | team_id |
+| Get cycles | LINEAR_GET_CYCLES_BY_TEAM_ID | team_id |
+| Create label | LINEAR_CREATE_LINEAR_LABEL | name, color |
+| Create comment | LINEAR_CREATE_LINEAR_COMMENT | issue_id, body |
+| Update comment | LINEAR_UPDATE_LINEAR_COMMENT | comment_id, body |
+| List users | LINEAR_LIST_LINEAR_USERS | (none) |
+| Current user | LINEAR_GET_CURRENT_USER | (none) |
+| Run GraphQL | LINEAR_RUN_QUERY_OR_MUTATION | query, variables |
diff --git a/linkedin-automation/SKILL.md b/linkedin-automation/SKILL.md
new file mode 100644
index 0000000..a7aaf69
--- /dev/null
+++ b/linkedin-automation/SKILL.md
@@ -0,0 +1,172 @@
+---
+name: linkedin-automation
+description: Automate LinkedIn tasks via Rube MCP (Composio): create posts, manage profile, company info, comments, and image uploads. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# LinkedIn Automation via Rube MCP
+
+Automate LinkedIn operations through Composio's LinkedIn toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active LinkedIn connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `linkedin`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `linkedin`
+3. If connection is not ACTIVE, follow the returned auth link to complete LinkedIn OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create a LinkedIn Post
+
+**When to use**: User wants to publish a text post on LinkedIn
+
+**Tool sequence**:
+1. `LINKEDIN_GET_MY_INFO` - Get authenticated user's profile info [Prerequisite]
+2. `LINKEDIN_REGISTER_IMAGE_UPLOAD` - Register image upload if post includes an image [Optional]
+3. `LINKEDIN_CREATE_LINKED_IN_POST` - Publish the post [Required]
+
+**Key parameters**:
+- `text`: Post content text
+- `visibility`: 'PUBLIC' or 'CONNECTIONS'
+- `media_title`: Title for attached media
+- `media_description`: Description for attached media
+
+**Pitfalls**:
+- Must retrieve user profile URN via GET_MY_INFO before creating a post
+- Image uploads require a two-step process: register upload first, then include the asset in the post
+- Post text has character limits enforced by LinkedIn API
+- Visibility defaults may vary; always specify explicitly
+
+### 2. Get Profile Information
+
+**When to use**: User wants to retrieve their LinkedIn profile or company details
+
+**Tool sequence**:
+1. `LINKEDIN_GET_MY_INFO` - Get authenticated user's profile [Required]
+2. `LINKEDIN_GET_COMPANY_INFO` - Get company page details [Optional]
+
+**Key parameters**:
+- No parameters needed for GET_MY_INFO (uses authenticated user)
+- `organization_id`: Company/organization ID for GET_COMPANY_INFO
+
+**Pitfalls**:
+- GET_MY_INFO returns the authenticated user only; cannot look up other users
+- Company info requires the numeric organization ID, not the company name or vanity URL
+- Some profile fields may be restricted based on OAuth scopes granted
+
+### 3. Manage Post Images
+
+**When to use**: User wants to upload and attach images to LinkedIn posts
+
+**Tool sequence**:
+1. `LINKEDIN_REGISTER_IMAGE_UPLOAD` - Register an image upload with LinkedIn [Required]
+2. Upload the image binary to the returned upload URL [Required]
+3. `LINKEDIN_GET_IMAGES` - Verify uploaded image status [Optional]
+4. `LINKEDIN_CREATE_LINKED_IN_POST` - Create post with the image asset [Required]
+
+**Key parameters**:
+- `owner`: URN of the image owner (user or organization)
+- `image_id`: ID of the uploaded image for GET_IMAGES
+
+**Pitfalls**:
+- The upload is a two-phase process: register then upload binary
+- Image asset URN from registration must be used when creating the post
+- Supported formats typically include JPG, PNG, and GIF
+- Large images may take time to process before they are available
+
+### 4. Comment on Posts
+
+**When to use**: User wants to comment on an existing LinkedIn post
+
+**Tool sequence**:
+1. `LINKEDIN_CREATE_COMMENT_ON_POST` - Add a comment to a post [Required]
+
+**Key parameters**:
+- `post_id`: The URN or ID of the post to comment on
+- `text`: Comment content
+- `actor`: URN of the commenter (user or organization)
+
+**Pitfalls**:
+- Post ID must be a valid LinkedIn URN format
+- The actor URN must match the authenticated user or a managed organization
+- Rate limits apply to comment creation; avoid rapid-fire comments
+
+### 5. Delete a Post
+
+**When to use**: User wants to remove a previously published LinkedIn post
+
+**Tool sequence**:
+1. `LINKEDIN_DELETE_LINKED_IN_POST` - Delete the specified post [Required]
+
+**Key parameters**:
+- `post_id`: The URN or ID of the post to delete
+
+**Pitfalls**:
+- Deletion is permanent and cannot be undone
+- Only the post author or organization admin can delete a post
+- The post_id must be the exact URN returned when the post was created
+
+## Common Patterns
+
+### ID Resolution
+
+**User URN from profile**:
+```
+1. Call LINKEDIN_GET_MY_INFO
+2. Extract user URN (e.g., 'urn:li:person:XXXXXXXXXX')
+3. Use URN as actor/owner in subsequent calls
+```
+
+**Organization ID from company**:
+```
+1. Call LINKEDIN_GET_COMPANY_INFO with organization_id
+2. Extract organization URN for posting as a company page
+```
+
+### Image Upload Flow
+
+- Call REGISTER_IMAGE_UPLOAD to get upload URL and asset URN
+- Upload the binary image to the provided URL
+- Use the asset URN when creating a post with media
+- Verify with GET_IMAGES if upload status is uncertain
+
+## Known Pitfalls
+
+**Authentication**:
+- LinkedIn OAuth tokens have limited scopes; ensure required permissions are granted
+- Tokens expire; re-authenticate if API calls return 401 errors
+
+**URN Formats**:
+- LinkedIn uses URN identifiers (e.g., 'urn:li:person:ABC123')
+- Always use the full URN format, not just the alphanumeric ID portion
+- Organization URNs differ from person URNs
+
+**Rate Limits**:
+- LinkedIn API has strict daily rate limits on post creation and comments
+- Implement backoff strategies for bulk operations
+- Monitor 429 responses and respect Retry-After headers
+
+**Content Restrictions**:
+- Posts have character limits enforced by the API
+- Some content types (polls, documents) may require additional API features
+- HTML markup in post text is not supported
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Get my profile | LINKEDIN_GET_MY_INFO | (none) |
+| Create post | LINKEDIN_CREATE_LINKED_IN_POST | text, visibility |
+| Get company info | LINKEDIN_GET_COMPANY_INFO | organization_id |
+| Register image upload | LINKEDIN_REGISTER_IMAGE_UPLOAD | owner |
+| Get uploaded images | LINKEDIN_GET_IMAGES | image_id |
+| Delete post | LINKEDIN_DELETE_LINKED_IN_POST | post_id |
+| Comment on post | LINKEDIN_CREATE_COMMENT_ON_POST | post_id, text, actor |
diff --git a/mailchimp-automation/SKILL.md b/mailchimp-automation/SKILL.md
new file mode 100644
index 0000000..3a858a6
--- /dev/null
+++ b/mailchimp-automation/SKILL.md
@@ -0,0 +1,228 @@
+---
+name: mailchimp-automation
+description: Automate Mailchimp email marketing including campaigns, audiences, subscribers, segments, and analytics via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Mailchimp Automation via Rube MCP
+
+Automate Mailchimp email marketing workflows including campaign creation and sending, audience/list management, subscriber operations, segmentation, and performance analytics through Composio's Mailchimp toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Mailchimp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `mailchimp`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `mailchimp`
+3. If connection is not ACTIVE, follow the returned auth link to complete Mailchimp OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Send Email Campaigns
+
+**When to use**: User wants to create, configure, test, and send an email campaign.
+
+**Tool sequence**:
+1. `MAILCHIMP_GET_LISTS_INFO` - List available audiences and get list_id [Prerequisite]
+2. `MAILCHIMP_ADD_CAMPAIGN` - Create a new campaign with type, audience, subject, from name [Required]
+3. `MAILCHIMP_SET_CAMPAIGN_CONTENT` - Set HTML content for the campaign [Required]
+4. `MAILCHIMP_SEND_TEST_EMAIL` - Send preview to reviewers before live send [Optional]
+5. `MAILCHIMP_SEND_CAMPAIGN` - Send the campaign immediately [Required]
+6. `MAILCHIMP_SCHEDULE_CAMPAIGN` - Schedule for future delivery instead of immediate send [Optional]
+
+**Key parameters for MAILCHIMP_ADD_CAMPAIGN**:
+- `type`: "regular", "plaintext", "rss", or "variate" (required)
+- `recipients__list__id`: Audience/list ID for recipients
+- `settings__subject__line`: Email subject line
+- `settings__from__name`: Sender display name
+- `settings__reply__to`: Reply-to email address (required for sending)
+- `settings__title`: Internal campaign title
+- `settings__preview__text`: Preview text shown in inbox
+
+**Key parameters for MAILCHIMP_SET_CAMPAIGN_CONTENT**:
+- `campaign_id`: Campaign ID from creation step (required)
+- `html`: Raw HTML content for the email
+- `plain_text`: Plain-text version (auto-generated if omitted)
+- `template__id`: Use a pre-built template instead of raw HTML
+
+**Pitfalls**:
+- `MAILCHIMP_SEND_CAMPAIGN` is irreversible; always send a test email first and get explicit user approval
+- Campaign must be in "save" (draft) status with valid audience, subject, from name, verified email, and content before sending
+- `MAILCHIMP_SCHEDULE_CAMPAIGN` requires a valid future datetime; past timestamps fail
+- Templates and HTML content must include compliant footer/unsubscribe merge tags
+- Mailchimp uses double-underscore notation for nested params (e.g., `settings__subject__line`)
+
+### 2. Manage Audiences and Subscribers
+
+**When to use**: User wants to view audiences, list subscribers, or check subscriber details.
+
+**Tool sequence**:
+1. `MAILCHIMP_GET_LISTS_INFO` - List all audiences with member counts [Required]
+2. `MAILCHIMP_GET_LIST_INFO` - Get details for a specific audience [Optional]
+3. `MAILCHIMP_LIST_MEMBERS_INFO` - List members with status filter and pagination [Required]
+4. `MAILCHIMP_SEARCH_MEMBERS` - Search by email or name across lists [Optional]
+5. `MAILCHIMP_GET_MEMBER_INFO` - Get detailed profile for a specific subscriber [Optional]
+6. `MAILCHIMP_LIST_SEGMENTS` - List segments within an audience [Optional]
+
+**Key parameters for MAILCHIMP_LIST_MEMBERS_INFO**:
+- `list_id`: Audience ID (required)
+- `status`: "subscribed", "unsubscribed", "cleaned", "pending", "transactional", "archived"
+- `count`: Records per page (default 10, max 1000)
+- `offset`: Pagination offset (default 0)
+- `sort_field`: "timestamp_opt", "timestamp_signup", or "last_changed"
+- `fields`: Comma-separated list to limit response size
+
+**Pitfalls**:
+- `stats.avg_open_rate` and `stats.avg_click_rate` are 0-1 fractions, NOT 0-100 percentages
+- Always use `status="subscribed"` to filter active subscribers; omitting returns all statuses
+- Must paginate using `count` and `offset` until collected members match `total_items`
+- Large list responses may be truncated; data is under `response.data.members`
+
+### 3. Add and Update Subscribers
+
+**When to use**: User wants to add new subscribers, update existing ones, or bulk-manage list membership.
+
+**Tool sequence**:
+1. `MAILCHIMP_GET_LIST_INFO` - Validate target audience exists [Prerequisite]
+2. `MAILCHIMP_SEARCH_MEMBERS` - Check if contact already exists [Optional]
+3. `MAILCHIMP_ADD_OR_UPDATE_LIST_MEMBER` - Upsert subscriber (create or update) [Required]
+4. `MAILCHIMP_ADD_MEMBER_TO_LIST` - Add new subscriber (create only) [Optional]
+5. `MAILCHIMP_BATCH_ADD_OR_REMOVE_MEMBERS` - Bulk manage segment membership [Optional]
+
+**Key parameters for MAILCHIMP_ADD_OR_UPDATE_LIST_MEMBER**:
+- `list_id`: Audience ID (required)
+- `subscriber_hash`: MD5 hash of lowercase email (required)
+- `email_address`: Subscriber email (required)
+- `status_if_new`: Status for new subscribers: "subscribed", "pending", etc. (required)
+- `status`: Status for existing subscribers
+- `merge_fields`: Object with merge tag keys (e.g., `{"FNAME": "John", "LNAME": "Doe"}`)
+- `tags`: Array of tag strings
+
+**Key parameters for MAILCHIMP_ADD_MEMBER_TO_LIST**:
+- `list_id`: Audience ID (required)
+- `email_address`: Subscriber email (required)
+- `status`: "subscribed", "pending", "unsubscribed", "cleaned", "transactional" (required)
+
+**Pitfalls**:
+- `subscriber_hash` must be MD5 of the **lowercase** email; incorrect casing causes 404s or duplicates
+- Use `MAILCHIMP_ADD_OR_UPDATE_LIST_MEMBER` (upsert) instead of `MAILCHIMP_ADD_MEMBER_TO_LIST` to avoid duplicate errors
+- `status_if_new` determines status only for new contacts; existing contacts use `status`
+- Use `skip_merge_validation: true` to bypass required merge field validation
+- `MAILCHIMP_BATCH_ADD_OR_REMOVE_MEMBERS` manages static segment membership, not list membership
+
+### 4. View Campaign Reports and Analytics
+
+**When to use**: User wants to review campaign performance, open rates, click rates, or subscriber engagement.
+
+**Tool sequence**:
+1. `MAILCHIMP_LIST_CAMPAIGNS` - List sent campaigns with report summaries [Required]
+2. `MAILCHIMP_SEARCH_CAMPAIGNS` - Find campaigns by name, subject, or content [Optional]
+3. `MAILCHIMP_GET_CAMPAIGN_REPORT` - Get detailed performance report for a campaign [Required]
+4. `MAILCHIMP_LIST_CAMPAIGN_REPORTS` - Bulk fetch reports across multiple campaigns [Optional]
+5. `MAILCHIMP_LIST_CAMPAIGN_DETAILS` - Get link-level click statistics [Optional]
+6. `MAILCHIMP_GET_CAMPAIGN_LINK_DETAILS` - Drill into specific link click data [Optional]
+7. `MAILCHIMP_LIST_CLICKED_LINK_SUBSCRIBERS` - See who clicked a specific link [Optional]
+8. `MAILCHIMP_GET_SUBSCRIBER_EMAIL_ACTIVITY` - Get per-subscriber campaign activity [Optional]
+9. `MAILCHIMP_GET_CAMPAIGN_CONTENT` - Retrieve campaign HTML content [Optional]
+
+**Key parameters for MAILCHIMP_LIST_CAMPAIGNS**:
+- `status`: "save", "paused", "schedule", "sending", "sent"
+- `count` / `offset`: Pagination (default 10, max 1000)
+- `since_send_time` / `before_send_time`: ISO 8601 date range filter
+- `sort_field`: "create_time" or "send_time"
+- `fields`: Limit response fields for performance
+
+**Key parameters for MAILCHIMP_GET_CAMPAIGN_REPORT**:
+- `campaign_id`: Campaign ID (required)
+- Returns: opens, clicks, bounces, unsubscribes, timeseries, industry_stats
+
+**Pitfalls**:
+- `MAILCHIMP_LIST_CAMPAIGNS` only returns high-level `report_summary`; use `MAILCHIMP_GET_CAMPAIGN_REPORT` for detailed metrics
+- Draft/unsent campaigns lack meaningful report data
+- When using `fields` parameter on LIST_CAMPAIGNS, explicitly request `send_time` and `report_summary` subfields
+- Pagination defaults are low (10 records); iterate with `count` and `offset` until `total_items` is covered
+- `send_time` is ISO 8601 with timezone; parse carefully
+
+## Common Patterns
+
+### ID Resolution
+Always resolve names to IDs before operations:
+- **Audience name -> list_id**: `MAILCHIMP_GET_LISTS_INFO` and match by name
+- **Subscriber email -> subscriber_hash**: Compute MD5 of lowercase email in code
+- **Campaign name -> campaign_id**: `MAILCHIMP_SEARCH_CAMPAIGNS` with query
+- **Segment name -> segment_id**: `MAILCHIMP_LIST_SEGMENTS` with list_id
+
+### Pagination
+Mailchimp uses offset-based pagination:
+- Use `count` (page size, max 1000) and `offset` (skip N records)
+- Continue until collected records match `total_items` from the response
+- Default `count` is 10; always set explicitly for bulk operations
+- Search endpoints max at 10 pages (300 results for 30/page)
+
+### Subscriber Hash
+Many endpoints require `subscriber_hash` (MD5 of lowercase email):
+```
+import hashlib
+subscriber_hash = hashlib.md5(email.lower().encode()).hexdigest()
+```
+
+## Known Pitfalls
+
+### ID Formats
+- `list_id` (audience ID) is a short alphanumeric string (e.g., "abc123def4")
+- `campaign_id` is an alphanumeric string
+- `subscriber_hash` is an MD5 hex string (32 characters)
+- Segment IDs are integers
+
+### Rate Limits
+- Mailchimp enforces API rate limits; use batching for bulk subscriber operations
+- High-volume use of GET_MEMBER_INFO and ADD_OR_UPDATE_LIST_MEMBER can trigger throttling
+- Use `MAILCHIMP_BATCH_ADD_OR_REMOVE_MEMBERS` for bulk segment operations
+
+### Parameter Quirks
+- Nested parameters use double-underscore notation: `settings__subject__line`, `recipients__list__id`
+- `avg_open_rate` and `avg_click_rate` are 0-1 fractions, not percentages
+- `status_if_new` only applies to new contacts in upsert operations
+- `subscriber_hash` must be MD5 of lowercase email; wrong casing creates phantom records
+- Campaign `type` is required for creation; most common is "regular"
+- `MAILCHIMP_SEND_CAMPAIGN` returns HTTP 204 on success (no body)
+
+### Content and Compliance
+- Campaign HTML must include unsubscribe link and physical address (merge tags)
+- Content must be set via `MAILCHIMP_SET_CAMPAIGN_CONTENT` before sending
+- Test emails require campaign to have content already set
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List audiences | `MAILCHIMP_GET_LISTS_INFO` | `count`, `offset` |
+| Get audience details | `MAILCHIMP_GET_LIST_INFO` | `list_id` |
+| Create campaign | `MAILCHIMP_ADD_CAMPAIGN` | `type`, `recipients__list__id`, `settings__subject__line` |
+| Set campaign content | `MAILCHIMP_SET_CAMPAIGN_CONTENT` | `campaign_id`, `html` |
+| Send test email | `MAILCHIMP_SEND_TEST_EMAIL` | `campaign_id`, `test_emails` |
+| Send campaign | `MAILCHIMP_SEND_CAMPAIGN` | `campaign_id` |
+| Schedule campaign | `MAILCHIMP_SCHEDULE_CAMPAIGN` | `campaign_id`, `schedule_time` |
+| Get campaign info | `MAILCHIMP_GET_CAMPAIGN_INFO` | `campaign_id` |
+| Search campaigns | `MAILCHIMP_SEARCH_CAMPAIGNS` | `query` |
+| List campaigns | `MAILCHIMP_LIST_CAMPAIGNS` | `status`, `count`, `offset` |
+| Replicate campaign | `MAILCHIMP_REPLICATE_CAMPAIGN` | `campaign_id` |
+| List subscribers | `MAILCHIMP_LIST_MEMBERS_INFO` | `list_id`, `status`, `count`, `offset` |
+| Search members | `MAILCHIMP_SEARCH_MEMBERS` | `query`, `list_id` |
+| Get member info | `MAILCHIMP_GET_MEMBER_INFO` | `list_id`, `subscriber_hash` |
+| Add subscriber | `MAILCHIMP_ADD_MEMBER_TO_LIST` | `list_id`, `email_address`, `status` |
+| Upsert subscriber | `MAILCHIMP_ADD_OR_UPDATE_LIST_MEMBER` | `list_id`, `subscriber_hash`, `email_address`, `status_if_new` |
+| Batch members | `MAILCHIMP_BATCH_ADD_OR_REMOVE_MEMBERS` | `list_id`, `segment_id` |
+| List segments | `MAILCHIMP_LIST_SEGMENTS` | `list_id` |
+| Campaign report | `MAILCHIMP_GET_CAMPAIGN_REPORT` | `campaign_id` |
+| All reports | `MAILCHIMP_LIST_CAMPAIGN_REPORTS` | `count`, `offset` |
+| Link click details | `MAILCHIMP_LIST_CAMPAIGN_DETAILS` | `campaign_id`, `count` |
+| Subscriber activity | `MAILCHIMP_GET_SUBSCRIBER_EMAIL_ACTIVITY` | `campaign_id`, `subscriber_hash` |
+| Member recent activity | `MAILCHIMP_VIEW_RECENT_ACTIVITY` | `list_id`, `subscriber_hash` |
+| Campaign content | `MAILCHIMP_GET_CAMPAIGN_CONTENT` | `campaign_id` |
diff --git a/make-automation/SKILL.md b/make-automation/SKILL.md
new file mode 100644
index 0000000..25206df
--- /dev/null
+++ b/make-automation/SKILL.md
@@ -0,0 +1,198 @@
+---
+name: make-automation
+description: Automate Make (Integromat) tasks via Rube MCP (Composio): operations, enums, language and timezone lookups. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Make Automation via Rube MCP
+
+Automate Make (formerly Integromat) operations through Composio's Make toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Make connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `make`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `make`
+3. If connection is not ACTIVE, follow the returned auth link to complete Make authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Get Operations Data
+
+**When to use**: User wants to retrieve operation logs or usage data from Make scenarios
+
+**Tool sequence**:
+1. `MAKE_GET_OPERATIONS` - Retrieve operation records [Required]
+
+**Key parameters**:
+- Check current schema via RUBE_SEARCH_TOOLS for available filters
+- May include date range, scenario ID, or status filters
+
+**Pitfalls**:
+- Operations data may be paginated; check for pagination tokens
+- Date filters must match expected format from schema
+- Large result sets should be filtered by date range or scenario
+
+### 2. List Available Languages
+
+**When to use**: User wants to see supported languages for Make scenarios or interfaces
+
+**Tool sequence**:
+1. `MAKE_LIST_ENUMS_LANGUAGES` - Get all supported language codes [Required]
+
+**Key parameters**:
+- No required parameters; returns complete language list
+
+**Pitfalls**:
+- Language codes follow standard locale format (e.g., 'en', 'fr', 'de')
+- List is static and rarely changes; cache results when possible
+
+### 3. List Available Timezones
+
+**When to use**: User wants to see supported timezones for scheduling Make scenarios
+
+**Tool sequence**:
+1. `MAKE_LIST_ENUMS_TIMEZONES` - Get all supported timezone identifiers [Required]
+
+**Key parameters**:
+- No required parameters; returns complete timezone list
+
+**Pitfalls**:
+- Timezone identifiers use IANA format (e.g., 'America/New_York', 'Europe/London')
+- List is static and rarely changes; cache results when possible
+- Use these exact timezone strings when configuring scenario schedules
+
+### 4. Scenario Configuration Lookup
+
+**When to use**: User needs to configure scenarios with correct language and timezone values
+
+**Tool sequence**:
+1. `MAKE_LIST_ENUMS_LANGUAGES` - Get valid language codes [Required]
+2. `MAKE_LIST_ENUMS_TIMEZONES` - Get valid timezone identifiers [Required]
+
+**Key parameters**:
+- No parameters needed for either call
+
+**Pitfalls**:
+- Always verify language and timezone values against these enums before using in configuration
+- Using invalid values in scenario configuration will cause errors
+
+## Common Patterns
+
+### Enum Validation
+
+Before configuring any Make scenario properties that accept language or timezone:
+```
+1. Call MAKE_LIST_ENUMS_LANGUAGES or MAKE_LIST_ENUMS_TIMEZONES
+2. Verify the desired value exists in the returned list
+3. Use the exact string value from the enum list
+```
+
+### Operations Monitoring
+
+```
+1. Call MAKE_GET_OPERATIONS with date range filters
+2. Analyze operation counts, statuses, and error rates
+3. Identify failed operations for troubleshooting
+```
+
+### Caching Strategy for Enums
+
+Since language and timezone lists are static:
+```
+1. Call MAKE_LIST_ENUMS_LANGUAGES once at workflow start
+2. Store results in memory or local cache
+3. Validate user inputs against cached values
+4. Refresh cache only when starting a new session
+```
+
+### Operations Analysis Workflow
+
+For scenario health monitoring:
+```
+1. Call MAKE_GET_OPERATIONS with recent date range
+2. Group operations by scenario ID
+3. Calculate success/failure ratios per scenario
+4. Identify scenarios with high error rates
+5. Report findings to user or notification channel
+```
+
+### Integration with Other Toolkits
+
+Make workflows often connect to other apps. Compose multi-tool workflows:
+```
+1. Call RUBE_SEARCH_TOOLS to find tools for the target app
+2. Connect required toolkits via RUBE_MANAGE_CONNECTIONS
+3. Use Make operations data to understand workflow execution patterns
+4. Execute equivalent workflows directly via individual app toolkits
+```
+
+## Known Pitfalls
+
+**Limited Toolkit**:
+- The Make toolkit in Composio currently has limited tools (operations, languages, timezones)
+- For full scenario management (creating, editing, running scenarios), consider using Make's native API
+- Always call RUBE_SEARCH_TOOLS to check for newly available tools
+- The toolkit may be expanded over time; re-check periodically
+
+**Operations Data**:
+- Operation records may have significant volume for active accounts
+- Always filter by date range to avoid fetching excessive data
+- Operation counts relate to Make's pricing tiers and quota usage
+- Failed operations should be investigated; they may indicate scenario configuration issues
+
+**Response Parsing**:
+- Response data may be nested under `data` key
+- Enum lists return arrays of objects with code and label fields
+- Operations data includes nested metadata about scenario execution
+- Parse defensively with fallbacks for optional fields
+
+**Rate Limits**:
+- Make API has rate limits per API token
+- Avoid rapid repeated calls to the same endpoint
+- Cache enum results (languages, timezones) as they rarely change
+- Operations queries should use targeted date ranges
+
+**Authentication**:
+- Make API uses token-based authentication
+- Tokens may have different permission scopes
+- Some operations data may be restricted based on token scope
+- Check that the authenticated user has access to the target organization
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Get operations | MAKE_GET_OPERATIONS | (check schema for filters) |
+| List languages | MAKE_LIST_ENUMS_LANGUAGES | (none) |
+| List timezones | MAKE_LIST_ENUMS_TIMEZONES | (none) |
+
+## Additional Notes
+
+### Alternative Approaches
+
+Since the Make toolkit has limited tools, consider these alternatives for common Make use cases:
+
+| Make Use Case | Alternative Approach |
+|--------------|---------------------|
+| Trigger a scenario | Use Make's native webhook or API endpoint directly |
+| Create a scenario | Use Make's scenario management API directly |
+| Schedule execution | Use RUBE_MANAGE_RECIPE_SCHEDULE with composed workflows |
+| Multi-app workflow | Compose individual toolkit tools via RUBE_MULTI_EXECUTE_TOOL |
+| Data transformation | Use RUBE_REMOTE_WORKBENCH for complex processing |
+
+### Composing Equivalent Workflows
+
+Instead of relying solely on Make's toolkit, build equivalent automation directly:
+1. Identify the apps involved in your Make scenario
+2. Search for each app's tools via RUBE_SEARCH_TOOLS
+3. Connect all required toolkits
+4. Build the workflow step-by-step using individual app tools
+5. Save as a recipe via RUBE_CREATE_UPDATE_RECIPE for reuse
diff --git a/microsoft-teams-automation/SKILL.md b/microsoft-teams-automation/SKILL.md
new file mode 100644
index 0000000..8f9aecf
--- /dev/null
+++ b/microsoft-teams-automation/SKILL.md
@@ -0,0 +1,208 @@
+---
+name: microsoft-teams-automation
+description: Automate Microsoft Teams tasks via Rube MCP (Composio): send messages, manage channels, create meetings, handle chats, and search messages. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Microsoft Teams Automation via Rube MCP
+
+Automate Microsoft Teams operations through Composio's Microsoft Teams toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Microsoft Teams connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `microsoft_teams`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `microsoft_teams`
+3. If connection is not ACTIVE, follow the returned auth link to complete Microsoft OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send Channel Messages
+
+**When to use**: User wants to post a message to a Teams channel
+
+**Tool sequence**:
+1. `MICROSOFT_TEAMS_TEAMS_LIST` - List teams to find target team [Prerequisite]
+2. `MICROSOFT_TEAMS_TEAMS_LIST_CHANNELS` - List channels in the team [Prerequisite]
+3. `MICROSOFT_TEAMS_TEAMS_POST_CHANNEL_MESSAGE` - Post the message [Required]
+
+**Key parameters**:
+- `team_id`: UUID of the team (from TEAMS_LIST)
+- `channel_id`: Channel ID (from LIST_CHANNELS, format: '19:...@thread.tacv2')
+- `content`: Message text or HTML
+- `content_type`: 'text' or 'html'
+
+**Pitfalls**:
+- team_id must be a valid UUID format
+- channel_id must be in thread format (e.g., '19:abc@thread.tacv2')
+- TEAMS_LIST may paginate (~100 items/page); follow @odata.nextLink to find all teams
+- LIST_CHANNELS can return 403 if user lacks access to the team
+- Messages over ~28KB can trigger 400/413 errors; split long content
+- Throttling may return 429; use exponential backoff (1s/2s/4s)
+
+### 2. Send Chat Messages
+
+**When to use**: User wants to send a direct or group chat message
+
+**Tool sequence**:
+1. `MICROSOFT_TEAMS_CHATS_GET_ALL_CHATS` - List existing chats [Optional]
+2. `MICROSOFT_TEAMS_LIST_USERS` - Find users for new chats [Optional]
+3. `MICROSOFT_TEAMS_TEAMS_CREATE_CHAT` - Create a new chat [Optional]
+4. `MICROSOFT_TEAMS_TEAMS_POST_CHAT_MESSAGE` - Send the message [Required]
+
+**Key parameters**:
+- `chat_id`: Chat ID (from GET_ALL_CHATS or CREATE_CHAT)
+- `content`: Message content
+- `content_type`: 'text' or 'html'
+- `chatType`: 'oneOnOne' or 'group' (for CREATE_CHAT)
+- `members`: Array of member objects (for CREATE_CHAT)
+
+**Pitfalls**:
+- CREATE_CHAT requires the authenticated user as one of the members
+- oneOnOne chats return existing chat if one already exists between the two users
+- group chats require at least one member with 'owner' role
+- member user_odata_bind must use full Microsoft Graph URL format
+- Chat filter support is very limited; filter client-side when needed
+
+### 3. Create Online Meetings
+
+**When to use**: User wants to schedule a Microsoft Teams meeting
+
+**Tool sequence**:
+1. `MICROSOFT_TEAMS_LIST_USERS` - Find participant user IDs [Optional]
+2. `MICROSOFT_TEAMS_CREATE_MEETING` - Create the meeting [Required]
+
+**Key parameters**:
+- `subject`: Meeting title
+- `start_date_time`: ISO 8601 start time (e.g., '2024-08-15T10:00:00Z')
+- `end_date_time`: ISO 8601 end time (must be after start)
+- `participants`: Array of user objects with user_id and role
+
+**Pitfalls**:
+- end_date_time must be strictly after start_date_time
+- Participants require valid Microsoft user_id (GUID) values, not emails
+- This creates a standalone meeting not linked to a calendar event
+- For calendar-linked meetings, use OUTLOOK_CALENDAR_CREATE_EVENT with is_online_meeting=true
+
+### 4. Manage Teams and Channels
+
+**When to use**: User wants to list, create, or manage teams and channels
+
+**Tool sequence**:
+1. `MICROSOFT_TEAMS_TEAMS_LIST` - List all accessible teams [Required]
+2. `MICROSOFT_TEAMS_GET_TEAM` - Get details for a specific team [Optional]
+3. `MICROSOFT_TEAMS_TEAMS_LIST_CHANNELS` - List channels in a team [Optional]
+4. `MICROSOFT_TEAMS_GET_CHANNEL` - Get channel details [Optional]
+5. `MICROSOFT_TEAMS_TEAMS_CREATE_CHANNEL` - Create a new channel [Optional]
+6. `MICROSOFT_TEAMS_LIST_TEAM_MEMBERS` - List team members [Optional]
+7. `MICROSOFT_TEAMS_ADD_MEMBER_TO_TEAM` - Add a member to the team [Optional]
+
+**Key parameters**:
+- `team_id`: Team UUID
+- `channel_id`: Channel ID in thread format
+- `filter`: OData filter string (e.g., "startsWith(displayName,'Project')")
+- `select`: Comma-separated properties to return
+
+**Pitfalls**:
+- TEAMS_LIST pagination: follow @odata.nextLink in large tenants
+- Private/shared channels may be omitted unless permissions align
+- GET_CHANNEL returns 404 if team_id or channel_id is wrong
+- Always source IDs from list operations; do not guess ID formats
+
+### 5. Search Messages
+
+**When to use**: User wants to find messages across Teams chats and channels
+
+**Tool sequence**:
+1. `MICROSOFT_TEAMS_SEARCH_MESSAGES` - Search with KQL syntax [Required]
+
+**Key parameters**:
+- `query`: KQL search query (supports from:, sent:, attachments, boolean logic)
+
+**Pitfalls**:
+- Newly posted messages may take 30-60 seconds to appear in search
+- Search is eventually consistent; do not rely on it for immediate delivery confirmation
+- Use message listing tools for real-time message verification
+
+## Common Patterns
+
+### Team and Channel ID Resolution
+
+```
+1. Call MICROSOFT_TEAMS_TEAMS_LIST
+2. Find team by displayName
+3. Extract team id (UUID format)
+4. Call MICROSOFT_TEAMS_TEAMS_LIST_CHANNELS with team_id
+5. Find channel by displayName
+6. Extract channel id (19:...@thread.tacv2 format)
+```
+
+### User Resolution
+
+```
+1. Call MICROSOFT_TEAMS_LIST_USERS
+2. Filter by displayName or email
+3. Extract user id (UUID format)
+4. Use for meeting participants, chat members, or team operations
+```
+
+### Pagination
+
+- Teams/Users: Follow @odata.nextLink URL for next page
+- Chats: Auto-paginates up to limit; use top for page size (max 50)
+- Use `top` parameter to control page size
+- Continue until @odata.nextLink is absent
+
+## Known Pitfalls
+
+**Authentication and Permissions**:
+- Different operations require different Microsoft Graph permissions
+- 403 errors indicate insufficient permissions or team access
+- Some operations require admin consent in the Azure AD tenant
+
+**ID Formats**:
+- Team IDs: UUID format (e.g., '87b0560f-fc0d-4442-add8-b380ca926707')
+- Channel IDs: Thread format (e.g., '19:abc123@thread.tacv2')
+- Chat IDs: Various formats (e.g., '19:meeting_xxx@thread.v2')
+- User IDs: UUID format
+- Never guess IDs; always resolve from list operations
+
+**Rate Limits**:
+- Microsoft Graph enforces throttling
+- 429 responses include Retry-After header
+- Keep requests to a few per second
+- Batch operations help reduce total request count
+
+**Message Formatting**:
+- HTML content_type supports rich formatting
+- Adaptive cards require additional handling
+- Message size limit is approximately 28KB
+- Split long content into multiple messages
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List teams | MICROSOFT_TEAMS_TEAMS_LIST | filter, select, top |
+| Get team details | MICROSOFT_TEAMS_GET_TEAM | team_id |
+| List channels | MICROSOFT_TEAMS_TEAMS_LIST_CHANNELS | team_id, filter |
+| Get channel | MICROSOFT_TEAMS_GET_CHANNEL | team_id, channel_id |
+| Create channel | MICROSOFT_TEAMS_TEAMS_CREATE_CHANNEL | team_id, displayName |
+| Post to channel | MICROSOFT_TEAMS_TEAMS_POST_CHANNEL_MESSAGE | team_id, channel_id, content |
+| List chats | MICROSOFT_TEAMS_CHATS_GET_ALL_CHATS | user_id, limit |
+| Create chat | MICROSOFT_TEAMS_TEAMS_CREATE_CHAT | chatType, members, topic |
+| Post to chat | MICROSOFT_TEAMS_TEAMS_POST_CHAT_MESSAGE | chat_id, content |
+| Create meeting | MICROSOFT_TEAMS_CREATE_MEETING | subject, start_date_time, end_date_time |
+| List users | MICROSOFT_TEAMS_LIST_USERS | filter, select, top |
+| List team members | MICROSOFT_TEAMS_LIST_TEAM_MEMBERS | team_id |
+| Add team member | MICROSOFT_TEAMS_ADD_MEMBER_TO_TEAM | team_id, user_id |
+| Search messages | MICROSOFT_TEAMS_SEARCH_MESSAGES | query |
+| Get chat message | MICROSOFT_TEAMS_GET_CHAT_MESSAGE | chat_id, message_id |
+| List joined teams | MICROSOFT_TEAMS_LIST_USER_JOINED_TEAMS | (none) |
diff --git a/miro-automation/SKILL.md b/miro-automation/SKILL.md
new file mode 100644
index 0000000..3765b9a
--- /dev/null
+++ b/miro-automation/SKILL.md
@@ -0,0 +1,202 @@
+---
+name: miro-automation
+description: Automate Miro tasks via Rube MCP (Composio): boards, items, sticky notes, frames, sharing, connectors. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Miro Automation via Rube MCP
+
+Automate Miro whiteboard operations through Composio's Miro toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Miro connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `miro`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `miro`
+3. If connection is not ACTIVE, follow the returned auth link to complete Miro OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Browse Boards
+
+**When to use**: User wants to find boards or get board details
+
+**Tool sequence**:
+1. `MIRO_GET_BOARDS2` - List all accessible boards [Required]
+2. `MIRO_GET_BOARD` - Get detailed info for a specific board [Optional]
+
+**Key parameters**:
+- `query`: Search term to filter boards by name
+- `sort`: Sort by 'default', 'last_modified', 'last_opened', 'last_created', 'alphabetically'
+- `limit`: Number of results per page (max 50)
+- `offset`: Pagination offset
+- `board_id`: Specific board ID for detailed retrieval
+
+**Pitfalls**:
+- Pagination uses offset-based approach, not cursor-based
+- Maximum 50 boards per page; iterate with offset for full list
+- Board IDs are long alphanumeric strings; always resolve by search first
+
+### 2. Create Boards and Items
+
+**When to use**: User wants to create a new board or add items to an existing board
+
+**Tool sequence**:
+1. `MIRO_CREATE_BOARD` - Create a new empty board [Optional]
+2. `MIRO_CREATE_STICKY_NOTE_ITEM` - Add sticky notes to a board [Optional]
+3. `MIRO_CREATE_FRAME_ITEM2` - Add frames to organize content [Optional]
+4. `MIRO_CREATE_ITEMS_IN_BULK` - Add multiple items at once [Optional]
+
+**Key parameters**:
+- `name` / `description`: Board name and description (for CREATE_BOARD)
+- `board_id`: Target board ID (required for all item creation)
+- `data`: Content object with `content` field for sticky note text
+- `style`: Styling object with `fillColor` for sticky note color
+- `position`: Object with `x` and `y` coordinates
+- `geometry`: Object with `width` and `height`
+
+**Pitfalls**:
+- `board_id` is required for ALL item operations; resolve via GET_BOARDS2 first
+- Sticky note colors use hex codes (e.g., '#FF0000') in the `fillColor` field
+- Position coordinates use the board's coordinate system (origin at center)
+- BULK create has a maximum items-per-request limit; check current schema
+- Frame items require `geometry` with both width and height
+
+### 3. Browse and Manage Board Items
+
+**When to use**: User wants to view, find, or organize items on a board
+
+**Tool sequence**:
+1. `MIRO_GET_BOARD_ITEMS` - List all items on a board [Required]
+2. `MIRO_GET_CONNECTORS2` - List connections between items [Optional]
+
+**Key parameters**:
+- `board_id`: Target board ID (required)
+- `type`: Filter by item type ('sticky_note', 'shape', 'text', 'frame', 'image', 'card')
+- `limit`: Number of items per page
+- `cursor`: Pagination cursor from previous response
+
+**Pitfalls**:
+- Results are paginated; follow `cursor` until absent for complete item list
+- Item types must match Miro's predefined types exactly
+- Large boards may have thousands of items; use type filtering to narrow results
+- Connectors are separate from items; use GET_CONNECTORS2 for relationship data
+
+### 4. Share and Collaborate on Boards
+
+**When to use**: User wants to share a board with team members or manage access
+
+**Tool sequence**:
+1. `MIRO_GET_BOARDS2` - Find the board to share [Prerequisite]
+2. `MIRO_SHARE_BOARD` - Share the board with users [Required]
+3. `MIRO_GET_BOARD_MEMBERS` - Verify current board members [Optional]
+
+**Key parameters**:
+- `board_id`: Board to share (required)
+- `emails`: Array of email addresses to invite
+- `role`: Access level ('viewer', 'commenter', 'editor')
+- `message`: Optional invitation message
+
+**Pitfalls**:
+- Email addresses must be valid; invalid emails cause the entire request to fail
+- Role must be one of the predefined values; case-sensitive
+- Sharing with users outside the organization may require admin approval
+- GET_BOARD_MEMBERS returns all members including the owner
+
+### 5. Create Visual Connections
+
+**When to use**: User wants to connect items on a board with lines or arrows
+
+**Tool sequence**:
+1. `MIRO_GET_BOARD_ITEMS` - Find items to connect [Prerequisite]
+2. `MIRO_GET_CONNECTORS2` - View existing connections [Optional]
+
+**Key parameters**:
+- `board_id`: Target board ID
+- `startItem`: Object with `id` of the source item
+- `endItem`: Object with `id` of the target item
+- `style`: Connector style (line type, color, arrows)
+
+**Pitfalls**:
+- Both start and end items must exist on the same board
+- Item IDs are required for connections; resolve via GET_BOARD_ITEMS first
+- Connector styles vary; check available options in schema
+- Self-referencing connections (same start and end) are not allowed
+
+## Common Patterns
+
+### ID Resolution
+
+**Board name -> Board ID**:
+```
+1. Call MIRO_GET_BOARDS2 with query=board_name
+2. Find board by name in results
+3. Extract id field
+```
+
+**Item lookup on board**:
+```
+1. Call MIRO_GET_BOARD_ITEMS with board_id and optional type filter
+2. Find item by content or position
+3. Extract item id for further operations
+```
+
+### Pagination
+
+- Boards: Use `offset` and `limit` (offset-based)
+- Board items: Use `cursor` and `limit` (cursor-based)
+- Continue until no more results or cursor is absent
+- Default page sizes vary by endpoint
+
+### Coordinate System
+
+- Board origin (0,0) is at the center
+- Positive X is right, positive Y is down
+- Items positioned by their center point
+- Use `position: {x: 0, y: 0}` for center of board
+- Frames define bounded areas; items inside inherit frame position
+
+## Known Pitfalls
+
+**Board IDs**:
+- Board IDs are required for virtually all operations
+- Always resolve board names to IDs via GET_BOARDS2 first
+- Do not hardcode board IDs; they vary by account
+
+**Item Creation**:
+- Each item type has different required fields
+- Sticky notes need `data.content` for text
+- Frames need `geometry.width` and `geometry.height`
+- Position defaults to (0,0) if not specified; items may overlap
+
+**Rate Limits**:
+- Miro API has rate limits per token
+- Bulk operations preferred over individual item creation
+- Use MIRO_CREATE_ITEMS_IN_BULK for multiple items
+
+**Response Parsing**:
+- Response data may be nested under `data` key
+- Item types determine which fields are present in response
+- Parse defensively; optional fields may be absent
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List boards | MIRO_GET_BOARDS2 | query, sort, limit, offset |
+| Get board details | MIRO_GET_BOARD | board_id |
+| Create board | MIRO_CREATE_BOARD | name, description |
+| Add sticky note | MIRO_CREATE_STICKY_NOTE_ITEM | board_id, data, style, position |
+| Add frame | MIRO_CREATE_FRAME_ITEM2 | board_id, data, geometry, position |
+| Bulk add items | MIRO_CREATE_ITEMS_IN_BULK | board_id, items |
+| Get board items | MIRO_GET_BOARD_ITEMS | board_id, type, cursor |
+| Share board | MIRO_SHARE_BOARD | board_id, emails, role |
+| Get members | MIRO_GET_BOARD_MEMBERS | board_id |
+| Get connectors | MIRO_GET_CONNECTORS2 | board_id |
diff --git a/mixpanel-automation/SKILL.md b/mixpanel-automation/SKILL.md
new file mode 100644
index 0000000..2885bff
--- /dev/null
+++ b/mixpanel-automation/SKILL.md
@@ -0,0 +1,221 @@
+---
+name: mixpanel-automation
+description: Automate Mixpanel tasks via Rube MCP (Composio): events, segmentation, funnels, cohorts, user profiles, JQL queries. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Mixpanel Automation via Rube MCP
+
+Automate Mixpanel product analytics through Composio's Mixpanel toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Mixpanel connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `mixpanel`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `mixpanel`
+3. If connection is not ACTIVE, follow the returned auth link to complete Mixpanel authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Aggregate Event Data
+
+**When to use**: User wants to count events, get totals, or track event trends over time
+
+**Tool sequence**:
+1. `MIXPANEL_GET_ALL_PROJECTS` - List projects to get project ID [Prerequisite]
+2. `MIXPANEL_AGGREGATE_EVENT_COUNTS` - Get event counts and aggregations [Required]
+
+**Key parameters**:
+- `event`: Event name or array of event names to aggregate
+- `from_date` / `to_date`: Date range in 'YYYY-MM-DD' format
+- `unit`: Time granularity ('minute', 'hour', 'day', 'week', 'month')
+- `type`: Aggregation type ('general', 'unique', 'average')
+- `where`: Filter expression for event properties
+
+**Pitfalls**:
+- Date format must be 'YYYY-MM-DD'; other formats cause errors
+- Event names are case-sensitive; use exact names from your Mixpanel project
+- `where` filter uses Mixpanel expression syntax (e.g., `properties["country"] == "US"`)
+- Maximum date range may be limited depending on your Mixpanel plan
+
+### 2. Run Segmentation Queries
+
+**When to use**: User wants to break down events by properties for detailed analysis
+
+**Tool sequence**:
+1. `MIXPANEL_QUERY_SEGMENTATION` - Run segmentation analysis [Required]
+
+**Key parameters**:
+- `event`: Event name to segment
+- `from_date` / `to_date`: Date range in 'YYYY-MM-DD' format
+- `on`: Property to segment by (e.g., `properties["country"]`)
+- `unit`: Time granularity
+- `type`: Count type ('general', 'unique', 'average')
+- `where`: Filter expression
+- `limit`: Maximum number of segments to return
+
+**Pitfalls**:
+- The `on` parameter uses Mixpanel property expression syntax
+- Property references must use `properties["prop_name"]` format
+- Segmentation on high-cardinality properties returns capped results; use `limit`
+- Results are grouped by the segmentation property and time unit
+
+### 3. Analyze Funnels
+
+**When to use**: User wants to track conversion funnels and identify drop-off points
+
+**Tool sequence**:
+1. `MIXPANEL_LIST_FUNNELS` - List saved funnels to find funnel ID [Prerequisite]
+2. `MIXPANEL_QUERY_FUNNEL` - Execute funnel analysis [Required]
+
+**Key parameters**:
+- `funnel_id`: ID of the saved funnel to query
+- `from_date` / `to_date`: Date range
+- `unit`: Time granularity
+- `where`: Filter expression
+- `on`: Property to segment funnel by
+- `length`: Conversion window in days
+
+**Pitfalls**:
+- `funnel_id` is required; resolve via LIST_FUNNELS first
+- Funnels must be created in Mixpanel UI first; API only queries existing funnels
+- Conversion window (`length`) defaults vary; set explicitly for accuracy
+- Large date ranges with segmentation can produce very large responses
+
+### 4. Manage User Profiles
+
+**When to use**: User wants to query or update user profiles in Mixpanel
+
+**Tool sequence**:
+1. `MIXPANEL_QUERY_PROFILES` - Search and filter user profiles [Required]
+2. `MIXPANEL_PROFILE_BATCH_UPDATE` - Update multiple user profiles [Optional]
+
+**Key parameters**:
+- `where`: Filter expression for profile properties (e.g., `properties["plan"] == "premium"`)
+- `output_properties`: Array of property names to include in results
+- `page`: Page number for pagination
+- `session_id`: Session ID for consistent pagination (from first response)
+- For batch update: array of profile updates with `$distinct_id` and property operations
+
+**Pitfalls**:
+- Profile queries return paginated results; use `session_id` from first response for consistent paging
+- `where` uses Mixpanel expression syntax for profile properties
+- BATCH_UPDATE applies operations (`$set`, `$unset`, `$add`, `$append`) to profiles
+- Batch update has a maximum number of profiles per request; chunk larger updates
+- Profile property names are case-sensitive
+
+### 5. Manage Cohorts
+
+**When to use**: User wants to list or analyze user cohorts
+
+**Tool sequence**:
+1. `MIXPANEL_COHORTS_LIST` - List all saved cohorts [Required]
+
+**Key parameters**:
+- No required parameters; returns all accessible cohorts
+- Response includes cohort `id`, `name`, `description`, `count`
+
+**Pitfalls**:
+- Cohorts are created and managed in Mixpanel UI; API provides read access
+- Cohort IDs are numeric; use exact ID from list results
+- Cohort counts may be approximate for very large cohorts
+- Cohorts can be used as filters in other queries via `where` expressions
+
+### 6. Run JQL and Insight Queries
+
+**When to use**: User wants to run custom JQL queries or insight analyses
+
+**Tool sequence**:
+1. `MIXPANEL_JQL_QUERY` - Execute a custom JQL (JavaScript Query Language) query [Optional]
+2. `MIXPANEL_QUERY_INSIGHT` - Run a saved insight query [Optional]
+
+**Key parameters**:
+- For JQL: `script` containing the JQL JavaScript code
+- For Insight: `bookmark_id` of the saved insight
+- `project_id`: Project context for the query
+
+**Pitfalls**:
+- JQL uses JavaScript-like syntax specific to Mixpanel
+- JQL queries have execution time limits; optimize for efficiency
+- Insight `bookmark_id` must reference an existing saved insight
+- JQL is a legacy feature; check Mixpanel documentation for current availability
+
+## Common Patterns
+
+### ID Resolution
+
+**Project name -> Project ID**:
+```
+1. Call MIXPANEL_GET_ALL_PROJECTS
+2. Find project by name in results
+3. Extract project id
+```
+
+**Funnel name -> Funnel ID**:
+```
+1. Call MIXPANEL_LIST_FUNNELS
+2. Find funnel by name
+3. Extract funnel_id
+```
+
+### Mixpanel Expression Syntax
+
+Used in `where` and `on` parameters:
+- Property reference: `properties["property_name"]`
+- Equality: `properties["country"] == "US"`
+- Comparison: `properties["age"] > 25`
+- Boolean: `properties["is_premium"] == true`
+- Contains: `"search_term" in properties["name"]`
+- AND/OR: `properties["country"] == "US" and properties["plan"] == "pro"`
+
+### Pagination
+
+- Event queries: Follow date-based pagination by adjusting date ranges
+- Profile queries: Use `page` number and `session_id` for consistent results
+- Funnel/cohort lists: Typically return complete results without pagination
+
+## Known Pitfalls
+
+**Date Formats**:
+- Always use 'YYYY-MM-DD' format
+- Date ranges are inclusive on both ends
+- Data freshness depends on Mixpanel ingestion delay (typically minutes)
+
+**Expression Syntax**:
+- Property references always use `properties["name"]` format
+- String values must be quoted: `properties["status"] == "active"`
+- Numeric values are unquoted: `properties["count"] > 10`
+- Boolean values: `true` / `false` (lowercase)
+
+**Rate Limits**:
+- Mixpanel API has rate limits per project
+- Large segmentation queries may time out; reduce date range or segments
+- Use batch operations where available to minimize API calls
+
+**Response Parsing**:
+- Response data may be nested under `data` key
+- Event data is typically grouped by date and segment
+- Numeric values may be returned as strings; parse explicitly
+- Empty date ranges return empty objects, not empty arrays
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List projects | MIXPANEL_GET_ALL_PROJECTS | (none) |
+| Aggregate events | MIXPANEL_AGGREGATE_EVENT_COUNTS | event, from_date, to_date, unit |
+| Segmentation | MIXPANEL_QUERY_SEGMENTATION | event, on, from_date, to_date |
+| List funnels | MIXPANEL_LIST_FUNNELS | (none) |
+| Query funnel | MIXPANEL_QUERY_FUNNEL | funnel_id, from_date, to_date |
+| Query profiles | MIXPANEL_QUERY_PROFILES | where, output_properties, page |
+| Batch update profiles | MIXPANEL_PROFILE_BATCH_UPDATE | (profile update objects) |
+| List cohorts | MIXPANEL_COHORTS_LIST | (none) |
+| JQL query | MIXPANEL_JQL_QUERY | script |
+| Query insight | MIXPANEL_QUERY_INSIGHT | bookmark_id |
diff --git a/monday-automation/SKILL.md b/monday-automation/SKILL.md
new file mode 100644
index 0000000..54b870f
--- /dev/null
+++ b/monday-automation/SKILL.md
@@ -0,0 +1,230 @@
+---
+name: monday-automation
+description: Automate Monday.com work management including boards, items, columns, groups, subitems, and updates via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Monday.com Automation via Rube MCP
+
+Automate Monday.com work management workflows including board creation, item management, column value updates, group organization, subitems, and update/comment threads through Composio's Monday toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Monday.com connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `monday`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `monday`
+3. If connection is not ACTIVE, follow the returned auth link to complete Monday.com OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Boards
+
+**When to use**: User wants to create a new board, list existing boards, or set up workspace structure.
+
+**Tool sequence**:
+1. `MONDAY_GET_WORKSPACES` - List available workspaces and resolve workspace ID [Prerequisite]
+2. `MONDAY_LIST_BOARDS` - List existing boards to check for duplicates [Optional]
+3. `MONDAY_CREATE_BOARD` - Create a new board with name, kind, and workspace [Required]
+4. `MONDAY_CREATE_COLUMN` - Add columns to the new board [Optional]
+5. `MONDAY_CREATE_GROUP` - Add groups to organize items [Optional]
+6. `MONDAY_BOARDS` - Retrieve detailed board metadata [Optional]
+
+**Key parameters**:
+- `board_name`: Name for the new board (required)
+- `board_kind`: "public", "private", or "share" (required)
+- `workspace_id`: Numeric workspace ID; omit for default workspace
+- `folder_id`: Folder ID; must be within `workspace_id` if both provided
+- `template_id`: ID of accessible template to clone
+
+**Pitfalls**:
+- `board_kind` is required and must be one of: "public", "private", "share"
+- If both `workspace_id` and `folder_id` are provided, the folder must exist within that workspace
+- `template_id` must reference a template the authenticated user can access
+- Board IDs are large integers; always use the exact value from API responses
+
+### 2. Create and Manage Items
+
+**When to use**: User wants to add tasks/items to a board, list existing items, or move items between groups.
+
+**Tool sequence**:
+1. `MONDAY_LIST_BOARDS` - Resolve board name to board ID [Prerequisite]
+2. `MONDAY_LIST_GROUPS` - List groups on the board to get group_id [Prerequisite]
+3. `MONDAY_LIST_COLUMNS` - Get column IDs and types for setting values [Prerequisite]
+4. `MONDAY_CREATE_ITEM` - Create a new item with name and column values [Required]
+5. `MONDAY_LIST_BOARD_ITEMS` - List all items on the board [Optional]
+6. `MONDAY_MOVE_ITEM_TO_GROUP` - Move an item to a different group [Optional]
+7. `MONDAY_ITEMS_PAGE` - Paginated item retrieval with filtering [Optional]
+
+**Key parameters**:
+- `board_id`: Board ID (required, integer)
+- `item_name`: Item name, max 256 characters (required)
+- `group_id`: Group ID string to place the item in (optional)
+- `column_values`: JSON object or string mapping column IDs to values
+
+**Pitfalls**:
+- `column_values` must use column IDs (not titles); get them from `MONDAY_LIST_COLUMNS`
+- Column value formats vary by type: status uses `{"index": 0}` or `{"label": "Done"}`, date uses `{"date": "YYYY-MM-DD"}`, people uses `{"personsAndTeams": [{"id": 123, "kind": "person"}]}`
+- `item_name` has a 256-character maximum
+- Subitem boards are NOT supported by `MONDAY_CREATE_ITEM`; use GraphQL via `MONDAY_CREATE_OBJECT`
+
+### 3. Update Item Column Values
+
+**When to use**: User wants to change status, date, text, or other column values on existing items.
+
+**Tool sequence**:
+1. `MONDAY_LIST_COLUMNS` or `MONDAY_COLUMNS` - Get column IDs and types [Prerequisite]
+2. `MONDAY_LIST_BOARD_ITEMS` or `MONDAY_ITEMS_PAGE` - Find the target item ID [Prerequisite]
+3. `MONDAY_CHANGE_SIMPLE_COLUMN_VALUE` - Update text, status, or dropdown with a string value [Required]
+4. `MONDAY_UPDATE_ITEM` - Update complex column types (timeline, people, date) with JSON [Required]
+
+**Key parameters for MONDAY_CHANGE_SIMPLE_COLUMN_VALUE**:
+- `board_id`: Board ID (integer, required)
+- `item_id`: Item ID (integer, required)
+- `column_id`: Column ID string (required)
+- `value`: Simple string value (e.g., "Done", "Working on it")
+- `create_labels_if_missing`: true to auto-create status/dropdown labels (default true)
+
+**Key parameters for MONDAY_UPDATE_ITEM**:
+- `board_id`: Board ID (integer, required)
+- `item_id`: Item ID (integer, required)
+- `column_id`: Column ID string (required)
+- `value`: JSON object matching the column type schema
+- `create_labels_if_missing`: false by default; set true for status/dropdown
+
+**Pitfalls**:
+- Use `MONDAY_CHANGE_SIMPLE_COLUMN_VALUE` for simple text/status/dropdown updates (string value)
+- Use `MONDAY_UPDATE_ITEM` for complex types like timeline, people, date (JSON value)
+- Column IDs are lowercase strings with underscores (e.g., "status_1", "date_2", "text"); get them from `MONDAY_LIST_COLUMNS`
+- Status values can be set by label name ("Done") or index number ("1")
+- `create_labels_if_missing` defaults differ: true for CHANGE_SIMPLE, false for UPDATE_ITEM
+
+### 4. Work with Groups and Board Structure
+
+**When to use**: User wants to organize items into groups, add columns, or inspect board structure.
+
+**Tool sequence**:
+1. `MONDAY_LIST_BOARDS` - Resolve board ID [Prerequisite]
+2. `MONDAY_LIST_GROUPS` - List all groups on a board [Required]
+3. `MONDAY_CREATE_GROUP` - Create a new group [Optional]
+4. `MONDAY_LIST_COLUMNS` or `MONDAY_COLUMNS` - Inspect column structure [Required]
+5. `MONDAY_CREATE_COLUMN` - Add a new column to the board [Optional]
+6. `MONDAY_MOVE_ITEM_TO_GROUP` - Reorganize items across groups [Optional]
+
+**Key parameters**:
+- `board_id`: Board ID (required for all group/column operations)
+- `group_name`: Name for new group (CREATE_GROUP)
+- `column_type`: Must be a valid GraphQL enum token in snake_case (e.g., "status", "text", "long_text", "numbers", "date", "dropdown", "people")
+- `title`: Column display title
+- `defaults`: JSON string for status/dropdown labels, e.g., `'{"labels": ["To Do", "In Progress", "Done"]}'`
+
+**Pitfalls**:
+- `column_type` must be exact snake_case values; "person" is NOT valid, use "people"
+- Group IDs are strings (e.g., "topics", "new_group_12345"), not integers
+- `MONDAY_COLUMNS` accepts an array of `board_ids` and returns column metadata including settings
+- `MONDAY_LIST_COLUMNS` is simpler and takes a single `board_id`
+
+### 5. Manage Subitems and Updates
+
+**When to use**: User wants to view subitems of a task or add comments/updates to items.
+
+**Tool sequence**:
+1. `MONDAY_LIST_BOARD_ITEMS` - Find parent item IDs [Prerequisite]
+2. `MONDAY_LIST_SUBITEMS_BY_PARENT` - Retrieve subitems with column values [Required]
+3. `MONDAY_CREATE_UPDATE` - Add a comment/update to an item [Optional]
+4. `MONDAY_CREATE_OBJECT` - Create subitems via GraphQL mutation [Optional]
+
+**Key parameters for MONDAY_LIST_SUBITEMS_BY_PARENT**:
+- `parent_item_ids`: Array of parent item IDs (integer array, required)
+- `include_column_values`: true to include column data (default true)
+- `include_parent_fields`: true to include parent item info (default true)
+
+**Key parameters for MONDAY_CREATE_OBJECT** (GraphQL):
+- `query`: Full GraphQL mutation string
+- `variables`: Optional variables object
+
+**Pitfalls**:
+- Subitems can only be queried through their parent items
+- To create subitems, use `MONDAY_CREATE_OBJECT` with a `create_subitem` GraphQL mutation
+- `MONDAY_CREATE_UPDATE` is for adding comments/updates to items (Monday's "updates" feature), not for modifying item values
+- `MONDAY_CREATE_OBJECT` is a raw GraphQL endpoint; ensure correct mutation syntax
+
+## Common Patterns
+
+### ID Resolution
+Always resolve display names to IDs before operations:
+- **Board name -> board_id**: `MONDAY_LIST_BOARDS` and match by name
+- **Group name -> group_id**: `MONDAY_LIST_GROUPS` with `board_id`
+- **Column title -> column_id**: `MONDAY_LIST_COLUMNS` with `board_id`
+- **Workspace name -> workspace_id**: `MONDAY_GET_WORKSPACES` and match by name
+- **Item name -> item_id**: `MONDAY_LIST_BOARD_ITEMS` or `MONDAY_ITEMS_PAGE`
+
+### Pagination
+Monday.com uses cursor-based pagination for items:
+- `MONDAY_ITEMS_PAGE` returns a `cursor` in the response for the next page
+- Pass the `cursor` to the next call; `board_id` and `query_params` are ignored when cursor is provided
+- Cursors are cached for 60 minutes
+- Maximum `limit` is 500 per page
+- `MONDAY_LIST_BOARDS` and `MONDAY_GET_WORKSPACES` use page-based pagination with `page` and `limit`
+
+### Column Value Formatting
+Different column types require different value formats:
+- **Status**: `{"index": 0}` or `{"label": "Done"}` or simple string "Done"
+- **Date**: `{"date": "YYYY-MM-DD"}`
+- **People**: `{"personsAndTeams": [{"id": 123, "kind": "person"}]}`
+- **Text/Numbers**: Plain string or number
+- **Timeline**: `{"from": "YYYY-MM-DD", "to": "YYYY-MM-DD"}`
+
+## Known Pitfalls
+
+### ID Formats
+- Board IDs and item IDs are large integers (e.g., 1234567890)
+- Group IDs are strings (e.g., "topics", "new_group_12345")
+- Column IDs are short strings (e.g., "status_1", "date4", "text")
+- Workspace IDs are integers
+
+### Rate Limits
+- Monday.com GraphQL API has complexity-based rate limits
+- Large boards with many columns increase query complexity
+- Use `limit` parameter to reduce items per request if hitting limits
+
+### Parameter Quirks
+- `column_type` for CREATE_COLUMN must be exact snake_case enum values; "people" not "person"
+- `column_values` in CREATE_ITEM accepts both JSON string and object formats
+- `MONDAY_CHANGE_SIMPLE_COLUMN_VALUE` auto-creates missing labels by default; `MONDAY_UPDATE_ITEM` does not
+- `MONDAY_CREATE_OBJECT` is a raw GraphQL interface; use it for operations without dedicated tools (e.g., create_subitem, delete_item, archive_board)
+
+### Response Structure
+- Board items are returned as arrays with `id`, `name`, and `state` fields
+- Column values include both raw `value` (JSON) and rendered `text` (display string)
+- Subitems are nested under parent items and cannot be queried independently
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List workspaces | `MONDAY_GET_WORKSPACES` | `kind`, `state`, `limit` |
+| Create workspace | `MONDAY_CREATE_WORKSPACE` | `name`, `kind` |
+| List boards | `MONDAY_LIST_BOARDS` | `limit`, `page`, `state` |
+| Create board | `MONDAY_CREATE_BOARD` | `board_name`, `board_kind`, `workspace_id` |
+| Get board metadata | `MONDAY_BOARDS` | `board_ids`, `board_kind` |
+| List groups | `MONDAY_LIST_GROUPS` | `board_id` |
+| Create group | `MONDAY_CREATE_GROUP` | `board_id`, `group_name` |
+| List columns | `MONDAY_LIST_COLUMNS` | `board_id` |
+| Get column metadata | `MONDAY_COLUMNS` | `board_ids`, `column_types` |
+| Create column | `MONDAY_CREATE_COLUMN` | `board_id`, `column_type`, `title` |
+| Create item | `MONDAY_CREATE_ITEM` | `board_id`, `item_name`, `column_values` |
+| List board items | `MONDAY_LIST_BOARD_ITEMS` | `board_id` |
+| Paginated items | `MONDAY_ITEMS_PAGE` | `board_id`, `limit`, `query_params` |
+| Update column (simple) | `MONDAY_CHANGE_SIMPLE_COLUMN_VALUE` | `board_id`, `item_id`, `column_id`, `value` |
+| Update column (complex) | `MONDAY_UPDATE_ITEM` | `board_id`, `item_id`, `column_id`, `value` |
+| Move item to group | `MONDAY_MOVE_ITEM_TO_GROUP` | `item_id`, `group_id` |
+| List subitems | `MONDAY_LIST_SUBITEMS_BY_PARENT` | `parent_item_ids` |
+| Add comment/update | `MONDAY_CREATE_UPDATE` | `item_id`, `body` |
+| Raw GraphQL mutation | `MONDAY_CREATE_OBJECT` | `query`, `variables` |
diff --git a/notion-automation/SKILL.md b/notion-automation/SKILL.md
new file mode 100644
index 0000000..361c8b1
--- /dev/null
+++ b/notion-automation/SKILL.md
@@ -0,0 +1,212 @@
+---
+name: notion-automation
+description: Automate Notion tasks via Rube MCP (Composio): pages, databases, blocks, comments, users. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Notion Automation via Rube MCP
+
+Automate Notion operations through Composio's Notion toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Notion connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `notion`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `notion`
+3. If connection is not ACTIVE, follow the returned auth link to complete Notion OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Pages
+
+**When to use**: User wants to create, update, or archive Notion pages
+
+**Tool sequence**:
+1. `NOTION_SEARCH_NOTION_PAGE` - Find parent page or existing page [Prerequisite]
+2. `NOTION_CREATE_NOTION_PAGE` - Create a new page under a parent [Optional]
+3. `NOTION_RETRIEVE_PAGE` - Get page metadata/properties [Optional]
+4. `NOTION_UPDATE_PAGE` - Update page properties, title, icon, cover [Optional]
+5. `NOTION_ARCHIVE_NOTION_PAGE` - Soft-delete (archive) a page [Optional]
+
+**Key parameters**:
+- `query`: Search text for SEARCH_NOTION_PAGE
+- `parent_id`: Parent page or database ID
+- `page_id`: Page ID for retrieval/update/archive
+- `properties`: Page property values matching parent schema
+
+**Pitfalls**:
+- RETRIEVE_PAGE returns only metadata/properties, NOT body content; use FETCH_BLOCK_CONTENTS for page body
+- ARCHIVE_NOTION_PAGE is a soft-delete (sets archived=true), not permanent deletion
+- Broad searches can look incomplete unless has_more/next_cursor is fully paginated
+
+### 2. Query and Manage Databases
+
+**When to use**: User wants to query database rows, insert entries, or update records
+
+**Tool sequence**:
+1. `NOTION_SEARCH_NOTION_PAGE` - Find the database by name [Prerequisite]
+2. `NOTION_FETCH_DATABASE` - Inspect schema and properties [Prerequisite]
+3. `NOTION_QUERY_DATABASE` / `NOTION_QUERY_DATABASE_WITH_FILTER` - Query rows [Required]
+4. `NOTION_INSERT_ROW_DATABASE` - Add new entries [Optional]
+5. `NOTION_UPDATE_ROW_DATABASE` - Update existing entries [Optional]
+
+**Key parameters**:
+- `database_id`: Database ID (from search or URL)
+- `filter`: Filter object matching Notion filter syntax
+- `sorts`: Array of sort objects
+- `start_cursor`: Pagination cursor from previous response
+- `properties`: Property values matching database schema for inserts/updates
+
+**Pitfalls**:
+- 404 object_not_found usually means wrong database_id or the database is not shared with the integration
+- Results are paginated; ignoring has_more/next_cursor silently truncates reads
+- Schema mismatches or missing required properties cause 400 validation_error
+- Formula and read-only fields cannot be set via INSERT_ROW_DATABASE
+- Property names in filters must match schema exactly (case-sensitive)
+
+### 3. Manage Blocks and Page Content
+
+**When to use**: User wants to read, append, or modify content blocks in a page
+
+**Tool sequence**:
+1. `NOTION_FETCH_BLOCK_CONTENTS` - Read child blocks of a page [Required]
+2. `NOTION_ADD_MULTIPLE_PAGE_CONTENT` - Append blocks to a page [Optional]
+3. `NOTION_APPEND_TEXT_BLOCKS` - Append text-only blocks [Optional]
+4. `NOTION_REPLACE_PAGE_CONTENT` - Replace all page content [Optional]
+5. `NOTION_DELETE_BLOCK` - Remove a specific block [Optional]
+
+**Key parameters**:
+- `block_id` / `page_id`: Target page or block ID
+- `content_blocks`: Array of block objects (NOT child_blocks)
+- `text`: Plain text content for APPEND_TEXT_BLOCKS
+
+**Pitfalls**:
+- Use `content_blocks` parameter, NOT `child_blocks` -- the latter fails validation
+- ADD_MULTIPLE_PAGE_CONTENT fails on archived pages; unarchive via UPDATE_PAGE first
+- Created blocks are in response.data.results; persist block IDs for later edits
+- DELETE_BLOCK is archival (archived=true), not permanent deletion
+
+### 4. Manage Database Schema
+
+**When to use**: User wants to create databases or modify their structure
+
+**Tool sequence**:
+1. `NOTION_FETCH_DATABASE` - Inspect current schema [Prerequisite]
+2. `NOTION_CREATE_DATABASE` - Create a new database [Optional]
+3. `NOTION_UPDATE_SCHEMA_DATABASE` - Modify database properties [Optional]
+
+**Key parameters**:
+- `parent_id`: Parent page ID for new databases
+- `title`: Database title
+- `properties`: Property definitions with types and options
+- `database_id`: Database ID for schema updates
+
+**Pitfalls**:
+- Cannot change property types via UPDATE_SCHEMA; must create new property and migrate data
+- Formula, rollup, and relation properties have complex configuration requirements
+
+### 5. Manage Users and Comments
+
+**When to use**: User wants to list workspace users or manage comments on pages
+
+**Tool sequence**:
+1. `NOTION_LIST_USERS` - List all workspace users [Optional]
+2. `NOTION_GET_ABOUT_ME` - Get current authenticated user [Optional]
+3. `NOTION_CREATE_COMMENT` - Add a comment to a page [Optional]
+4. `NOTION_FETCH_COMMENTS` - List comments on a page [Optional]
+
+**Key parameters**:
+- `page_id`: Page ID for comments (also called `discussion_id`)
+- `rich_text`: Comment content as rich text array
+
+**Pitfalls**:
+- Comments are linked to pages, not individual blocks
+- User IDs from LIST_USERS are needed for people-type property filters
+
+## Common Patterns
+
+### ID Resolution
+
+**Page/Database name -> ID**:
+```
+1. Call NOTION_SEARCH_NOTION_PAGE with query=name
+2. Paginate with has_more/next_cursor until found
+3. Extract id from matching result
+```
+
+**Database schema inspection**:
+```
+1. Call NOTION_FETCH_DATABASE with database_id
+2. Extract properties object for field names and types
+3. Use exact property names in queries and inserts
+```
+
+### Pagination
+
+- Set `page_size` for results per page (max 100)
+- Check response for `has_more` boolean
+- Pass `start_cursor` or `next_cursor` in next request
+- Continue until `has_more` is false
+
+### Notion Filter Syntax
+
+**Single filter**:
+```json
+{"property": "Status", "select": {"equals": "Done"}}
+```
+
+**Compound filter**:
+```json
+{"and": [
+ {"property": "Status", "select": {"equals": "In Progress"}},
+ {"property": "Assignee", "people": {"contains": "user-id"}}
+]}
+```
+
+## Known Pitfalls
+
+**Integration Sharing**:
+- Pages and databases must be shared with the Notion integration to be accessible
+- Title queries can return 0 when the item is not shared with the integration
+
+**Property Types**:
+- Property names are case-sensitive and must match schema exactly
+- Formula, rollup, and created_time fields are read-only
+- Select/multi-select values must match existing options unless creating new ones
+
+**Response Parsing**:
+- Response data may be nested under `data_preview` or `data.results`
+- Parse defensively with fallbacks for different nesting levels
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search pages/databases | NOTION_SEARCH_NOTION_PAGE | query |
+| Create page | NOTION_CREATE_NOTION_PAGE | parent_id, properties |
+| Get page metadata | NOTION_RETRIEVE_PAGE | page_id |
+| Update page | NOTION_UPDATE_PAGE | page_id, properties |
+| Archive page | NOTION_ARCHIVE_NOTION_PAGE | page_id |
+| Duplicate page | NOTION_DUPLICATE_PAGE | page_id |
+| Get page blocks | NOTION_FETCH_BLOCK_CONTENTS | block_id |
+| Append blocks | NOTION_ADD_MULTIPLE_PAGE_CONTENT | page_id, content_blocks |
+| Append text | NOTION_APPEND_TEXT_BLOCKS | page_id, text |
+| Replace content | NOTION_REPLACE_PAGE_CONTENT | page_id, content_blocks |
+| Delete block | NOTION_DELETE_BLOCK | block_id |
+| Query database | NOTION_QUERY_DATABASE | database_id, filter, sorts |
+| Query with filter | NOTION_QUERY_DATABASE_WITH_FILTER | database_id, filter |
+| Insert row | NOTION_INSERT_ROW_DATABASE | database_id, properties |
+| Update row | NOTION_UPDATE_ROW_DATABASE | page_id, properties |
+| Get database schema | NOTION_FETCH_DATABASE | database_id |
+| Create database | NOTION_CREATE_DATABASE | parent_id, title, properties |
+| Update schema | NOTION_UPDATE_SCHEMA_DATABASE | database_id, properties |
+| List users | NOTION_LIST_USERS | (none) |
+| Create comment | NOTION_CREATE_COMMENT | page_id, rich_text |
+| List comments | NOTION_FETCH_COMMENTS | page_id |
diff --git a/one-drive-automation/SKILL.md b/one-drive-automation/SKILL.md
new file mode 100644
index 0000000..b449884
--- /dev/null
+++ b/one-drive-automation/SKILL.md
@@ -0,0 +1,235 @@
+---
+name: one-drive-automation
+description: Automate OneDrive file management, search, uploads, downloads, sharing, permissions, and folder operations via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# OneDrive Automation via Rube MCP
+
+Automate OneDrive operations including file upload/download, search, folder management, sharing links, permissions management, and drive browsing through Composio's OneDrive toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active OneDrive connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `one_drive`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `one_drive`
+3. If connection is not ACTIVE, follow the returned auth link to complete Microsoft OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search and Browse Files
+
+**When to use**: User wants to find files or browse folder contents in OneDrive
+
+**Tool sequence**:
+1. `ONE_DRIVE_GET_DRIVE` - Verify drive access and get drive details [Prerequisite]
+2. `ONE_DRIVE_SEARCH_ITEMS` - Keyword search across filenames, metadata, and content [Required]
+3. `ONE_DRIVE_ONEDRIVE_LIST_ITEMS` - List all items in the root of a drive [Optional]
+4. `ONE_DRIVE_GET_ITEM` - Get detailed metadata for a specific item, expand children [Optional]
+5. `ONE_DRIVE_ONEDRIVE_FIND_FILE` - Find a specific file by exact name in a folder [Optional]
+6. `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` - Find a specific folder by name [Optional]
+7. `ONE_DRIVE_LIST_DRIVES` - List all accessible drives [Optional]
+
+**Key parameters**:
+- `q`: Search query (plain keywords only, NOT KQL syntax)
+- `search_scope`: `"root"` (folder hierarchy) or `"drive"` (includes shared items)
+- `top`: Max items per page (default 200)
+- `skip_token`: Pagination token from `@odata.nextLink`
+- `select`: Comma-separated fields to return (e.g., `"id,name,webUrl,size"`)
+- `orderby`: Sort order (e.g., `"name asc"`, `"name desc"`)
+- `item_id`: Item ID for `GET_ITEM`
+- `expand_relations`: Array like `["children"]` or `["thumbnails"]` for `GET_ITEM`
+- `user_id`: `"me"` (default) or specific user ID/email
+
+**Pitfalls**:
+- `ONE_DRIVE_SEARCH_ITEMS` does NOT support KQL operators (`folder:`, `file:`, `filetype:`, `path:`); these are treated as literal text
+- Wildcard characters (`*`, `?`) are NOT supported and are auto-removed; use file extension keywords instead (e.g., `"pdf"` not `"*.pdf"`)
+- `ONE_DRIVE_ONEDRIVE_LIST_ITEMS` returns only root-level contents; use recursive `ONE_DRIVE_GET_ITEM` with `expand_relations: ["children"]` for deeper levels
+- Large folders paginate; always follow `skip_token` / `@odata.nextLink` until exhausted
+- Some drive ID formats may return "ObjectHandle is Invalid" errors due to Microsoft Graph API limitations
+
+### 2. Upload and Download Files
+
+**When to use**: User wants to upload files to OneDrive or download files from it
+
+**Tool sequence**:
+1. `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` - Locate the target folder [Prerequisite]
+2. `ONE_DRIVE_ONEDRIVE_UPLOAD_FILE` - Upload a file to a specified folder [Required for upload]
+3. `ONE_DRIVE_DOWNLOAD_FILE` - Download a file by item ID [Required for download]
+4. `ONE_DRIVE_GET_ITEM` - Get file details before download [Optional]
+
+**Key parameters**:
+- `file`: FileUploadable object with `s3key`, `mimetype`, and `name` for uploads
+- `folder`: Destination path (e.g., `"/Documents/Reports"`) or folder ID for uploads
+- `item_id`: File's unique identifier for downloads
+- `file_name`: Desired filename with extension for downloads
+- `drive_id`: Specific drive ID (for SharePoint or OneDrive for Business)
+- `user_id`: `"me"` (default) or specific user identifier
+
+**Pitfalls**:
+- Upload automatically renames on conflict (no overwrite option by default)
+- Large files are automatically handled via chunking
+- `drive_id` overrides `user_id` when both are provided
+- Item IDs vary by platform: OneDrive for Business uses `01...` prefix, OneDrive Personal uses `HASH!NUMBER` format
+- Item IDs are case-sensitive; use exactly as returned from API
+
+### 3. Share Files and Manage Permissions
+
+**When to use**: User wants to share files/folders or manage who has access
+
+**Tool sequence**:
+1. `ONE_DRIVE_ONEDRIVE_FIND_FILE` or `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` - Locate the item [Prerequisite]
+2. `ONE_DRIVE_GET_ITEM_PERMISSIONS` - Check current permissions [Prerequisite]
+3. `ONE_DRIVE_INVITE_USER_TO_DRIVE_ITEM` - Grant access to specific users [Required]
+4. `ONE_DRIVE_CREATE_LINK` - Create a shareable link [Optional]
+5. `ONE_DRIVE_UPDATE_DRIVE_ITEM_METADATA` - Update item metadata [Optional]
+
+**Key parameters**:
+- `item_id`: The file or folder to share
+- `recipients`: Array of objects with `email` or `object_id`
+- `roles`: Array with `"read"` or `"write"`
+- `send_invitation`: `true` to send notification email, `false` for silent permission grant
+- `require_sign_in`: `true` to require authentication to access
+- `message`: Custom message for invitation (max 2000 characters)
+- `expiration_date_time`: ISO 8601 date for permission expiry
+- `retain_inherited_permissions`: `true` (default) to keep existing inherited permissions
+
+**Pitfalls**:
+- Using wrong `item_id` with `INVITE_USER_TO_DRIVE_ITEM` changes permissions on unintended items; always verify first
+- Write or higher roles are impactful; get explicit user confirmation before granting
+- `GET_ITEM_PERMISSIONS` returns inherited and owner entries; do not assume response only reflects recent changes
+- `permissions` cannot be expanded via `ONE_DRIVE_GET_ITEM`; use the separate permissions endpoint
+- At least one of `require_sign_in` or `send_invitation` must be `true`
+
+### 4. Manage Folders (Create, Move, Delete, Copy)
+
+**When to use**: User wants to create, move, rename, delete, or copy files and folders
+
+**Tool sequence**:
+1. `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` - Locate source and destination folders [Prerequisite]
+2. `ONE_DRIVE_ONEDRIVE_CREATE_FOLDER` - Create a new folder [Required for create]
+3. `ONE_DRIVE_MOVE_ITEM` - Move a file or folder to a new location [Required for move]
+4. `ONE_DRIVE_COPY_ITEM` - Copy a file or folder (async operation) [Required for copy]
+5. `ONE_DRIVE_DELETE_ITEM` - Move item to recycle bin [Required for delete]
+6. `ONE_DRIVE_UPDATE_DRIVE_ITEM_METADATA` - Rename or update item properties [Optional]
+
+**Key parameters**:
+- `name`: Folder name for creation or new name for rename/copy
+- `parent_folder`: Path (e.g., `"/Documents/Reports"`) or folder ID for creation
+- `itemId`: Item to move
+- `parentReference`: Object with `id` (destination folder ID) for moves: `{"id": "folder_id"}`
+- `item_id`: Item to copy or delete
+- `parent_reference`: Object with `id` and optional `driveId` for copy destination
+- `@microsoft.graph.conflictBehavior`: `"fail"`, `"replace"`, or `"rename"` for copies
+- `if_match`: ETag for optimistic concurrency on deletes
+
+**Pitfalls**:
+- `ONE_DRIVE_MOVE_ITEM` does NOT support cross-drive moves; use `ONE_DRIVE_COPY_ITEM` for cross-drive transfers
+- `parentReference` for moves requires folder ID (not folder name); resolve with `ONEDRIVE_FIND_FOLDER` first
+- `ONE_DRIVE_COPY_ITEM` is asynchronous; response provides a URL to monitor progress
+- `ONE_DRIVE_DELETE_ITEM` moves to recycle bin, not permanent deletion
+- Folder creation auto-renames on conflict (e.g., "New Folder" becomes "New Folder 1")
+- Provide either `name` or `parent_reference` (or both) for `ONE_DRIVE_COPY_ITEM`
+
+### 5. Track Changes and Drive Information
+
+**When to use**: User wants to monitor changes or get drive/quota information
+
+**Tool sequence**:
+1. `ONE_DRIVE_GET_DRIVE` - Get drive properties and metadata [Required]
+2. `ONE_DRIVE_GET_QUOTA` - Check storage quota (total, used, remaining) [Optional]
+3. `ONE_DRIVE_LIST_SITE_DRIVE_ITEMS_DELTA` - Track changes in SharePoint site drives [Optional]
+4. `ONE_DRIVE_GET_ITEM_VERSIONS` - Get version history of a file [Optional]
+
+**Key parameters**:
+- `drive_id`: Drive identifier (or `"me"` for personal drive)
+- `site_id`: SharePoint site identifier for delta tracking
+- `token`: Delta token (`"latest"` for current state, URL for next page, or timestamp)
+- `item_id`: File ID for version history
+
+**Pitfalls**:
+- Delta queries are only available for SharePoint site drives via `ONE_DRIVE_LIST_SITE_DRIVE_ITEMS_DELTA`
+- Token `"latest"` returns current delta token without items (useful as starting point)
+- Deep or large drives can take several minutes to crawl; use batching and resume logic
+
+## Common Patterns
+
+### ID Resolution
+- **User**: Use `"me"` for authenticated user or specific user email/GUID
+- **Item ID from find**: Use `ONE_DRIVE_ONEDRIVE_FIND_FILE` or `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` to get item IDs
+- **Item ID from search**: Extract from `ONE_DRIVE_SEARCH_ITEMS` results
+- **Drive ID**: Use `ONE_DRIVE_LIST_DRIVES` or `ONE_DRIVE_GET_DRIVE` to discover drives
+- **Folder path to ID**: Use `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` with path, then extract ID from response
+
+ID formats vary by platform:
+- OneDrive for Business/SharePoint: `01NKDM7HMOJTVYMDOSXFDK2QJDXCDI3WUK`
+- OneDrive Personal: `D4648F06C91D9D3D!54927`
+
+### Pagination
+OneDrive uses token-based pagination:
+- Follow `@odata.nextLink` or `skip_token` until no more pages
+- Set `top` for page size (varies by endpoint)
+- `ONE_DRIVE_ONEDRIVE_LIST_ITEMS` auto-handles pagination internally
+- Aggressive parallel requests can trigger HTTP 429; honor `Retry-After` headers
+
+### Path vs ID
+Most OneDrive tools accept either paths or IDs:
+- **Paths**: Start with `/` (e.g., `"/Documents/Reports"`)
+- **IDs**: Use unique item identifiers from API responses
+- **Item paths for permissions**: Use `:/path/to/item:/` format
+
+## Known Pitfalls
+
+### ID Formats
+- Item IDs are case-sensitive and platform-specific
+- Never use web URLs, sharing links, or manually constructed identifiers as item IDs
+- Always use IDs exactly as returned from Microsoft Graph API
+
+### Rate Limits
+- Aggressive parallel `ONE_DRIVE_GET_ITEM` calls can trigger HTTP 429 Too Many Requests
+- Honor `Retry-After` headers and implement throttling
+- Deep drive crawls should use batching with delays
+
+### Search Limitations
+- No KQL support; use plain keywords only
+- No wildcard characters; use extension keywords (e.g., `"pdf"` not `"*.pdf"`)
+- No path-based filtering in search; use folder listing instead
+- `q='*'` wildcard-only queries return HTTP 400 invalidRequest
+
+### Parameter Quirks
+- `drive_id` overrides `user_id` when both are provided
+- `permissions` cannot be expanded via `GET_ITEM`; use dedicated permissions endpoint
+- Move operations require folder IDs in `parentReference`, not folder names
+- Copy operations are asynchronous; response provides monitoring URL
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search files | `ONE_DRIVE_SEARCH_ITEMS` | `q`, `search_scope`, `top` |
+| List root items | `ONE_DRIVE_ONEDRIVE_LIST_ITEMS` | `user_id`, `select`, `top` |
+| Get item details | `ONE_DRIVE_GET_ITEM` | `item_id`, `expand_relations` |
+| Find file by name | `ONE_DRIVE_ONEDRIVE_FIND_FILE` | `name`, `folder` |
+| Find folder by name | `ONE_DRIVE_ONEDRIVE_FIND_FOLDER` | `name`, `folder` |
+| Upload file | `ONE_DRIVE_ONEDRIVE_UPLOAD_FILE` | `file`, `folder` |
+| Download file | `ONE_DRIVE_DOWNLOAD_FILE` | `item_id`, `file_name` |
+| Create folder | `ONE_DRIVE_ONEDRIVE_CREATE_FOLDER` | `name`, `parent_folder` |
+| Move item | `ONE_DRIVE_MOVE_ITEM` | `itemId`, `parentReference` |
+| Copy item | `ONE_DRIVE_COPY_ITEM` | `item_id`, `parent_reference`, `name` |
+| Delete item | `ONE_DRIVE_DELETE_ITEM` | `item_id` |
+| Share with users | `ONE_DRIVE_INVITE_USER_TO_DRIVE_ITEM` | `item_id`, `recipients`, `roles` |
+| Create share link | `ONE_DRIVE_CREATE_LINK` | `item_id`, link type |
+| Get permissions | `ONE_DRIVE_GET_ITEM_PERMISSIONS` | `item_id` |
+| Update metadata | `ONE_DRIVE_UPDATE_DRIVE_ITEM_METADATA` | `item_id`, fields |
+| Get drive info | `ONE_DRIVE_GET_DRIVE` | `drive_id` |
+| List drives | `ONE_DRIVE_LIST_DRIVES` | user/group/site scope |
+| Get quota | `ONE_DRIVE_GET_QUOTA` | (none) |
+| Track changes | `ONE_DRIVE_LIST_SITE_DRIVE_ITEMS_DELTA` | `site_id`, `token` |
+| Version history | `ONE_DRIVE_GET_ITEM_VERSIONS` | `item_id` |
diff --git a/outlook-automation/SKILL.md b/outlook-automation/SKILL.md
new file mode 100644
index 0000000..2d934a6
--- /dev/null
+++ b/outlook-automation/SKILL.md
@@ -0,0 +1,188 @@
+---
+name: outlook-automation
+description: Automate Outlook tasks via Rube MCP (Composio): emails, calendar, contacts, folders, attachments. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Outlook Automation via Rube MCP
+
+Automate Microsoft Outlook operations through Composio's Outlook toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Outlook connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `outlook`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `outlook`
+3. If connection is not ACTIVE, follow the returned auth link to complete Microsoft OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search and Filter Emails
+
+**When to use**: User wants to find specific emails across their mailbox
+
+**Tool sequence**:
+1. `OUTLOOK_SEARCH_MESSAGES` - Search with KQL syntax across all folders [Required]
+2. `OUTLOOK_GET_MESSAGE` - Get full message details [Optional]
+3. `OUTLOOK_LIST_OUTLOOK_ATTACHMENTS` - List message attachments [Optional]
+4. `OUTLOOK_DOWNLOAD_OUTLOOK_ATTACHMENT` - Download attachment [Optional]
+
+**Key parameters**:
+- `query`: KQL search string (from:, to:, subject:, received:, hasattachment:)
+- `from_index`: Pagination start (0-based)
+- `size`: Results per page (max 25)
+- `message_id`: Message ID (use hitId from search results)
+
+**Pitfalls**:
+- Only works with Microsoft 365/Enterprise accounts (not @hotmail.com/@outlook.com)
+- Pagination relies on hitsContainers[0].moreResultsAvailable; stop only when false
+- Use hitId from search results as message_id for downstream calls, not resource.id
+- Index latency: very recent emails may not appear immediately
+- Inline images appear as attachments; filter by mimetype for real documents
+
+### 2. Query Emails in a Folder
+
+**When to use**: User wants to list emails in a specific folder with OData filters
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_MAIL_FOLDERS` - List mail folders to get folder IDs [Prerequisite]
+2. `OUTLOOK_QUERY_EMAILS` - Query emails with structured filters [Required]
+
+**Key parameters**:
+- `folder`: Folder name ('inbox', 'sentitems', 'drafts') or folder ID
+- `filter`: OData filter (e.g., `isRead eq false and importance eq 'high'`)
+- `top`: Max results (1-1000)
+- `orderby`: Sort field and direction
+- `select`: Array of fields to return
+
+**Pitfalls**:
+- QUERY_EMAILS searches a SINGLE folder only; use SEARCH_MESSAGES for cross-folder search
+- Custom folders require folder IDs, not display names; use LIST_MAIL_FOLDERS
+- Always check response['@odata.nextLink'] for pagination
+- Cannot filter by recipient or body content; use SEARCH_MESSAGES for that
+
+### 3. Manage Calendar Events
+
+**When to use**: User wants to list, search, or inspect calendar events
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_EVENTS` - List events with filters [Optional]
+2. `OUTLOOK_GET_CALENDAR_VIEW` - Get events in a time window [Optional]
+3. `OUTLOOK_GET_EVENT` - Get specific event details [Optional]
+4. `OUTLOOK_LIST_CALENDARS` - List available calendars [Optional]
+5. `OUTLOOK_GET_SCHEDULE` - Get free/busy info [Optional]
+
+**Key parameters**:
+- `filter`: OData filter (use start/dateTime, NOT receivedDateTime)
+- `start_datetime`/`end_datetime`: ISO 8601 for calendar view
+- `timezone`: IANA timezone (e.g., 'America/New_York')
+- `calendar_id`: Optional non-primary calendar ID
+- `select`: Fields to return
+
+**Pitfalls**:
+- Use calendar event properties only (start/dateTime, end/dateTime), NOT email properties (receivedDateTime)
+- Calendar view requires start_datetime and end_datetime
+- Recurring events need `expand_recurring_events=true` to see individual occurrences
+- Decline status is per-attendee via attendees[].status.response
+
+### 4. Manage Contacts
+
+**When to use**: User wants to list, create, or organize contacts
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_CONTACTS` - List contacts [Optional]
+2. `OUTLOOK_CREATE_CONTACT` - Create a new contact [Optional]
+3. `OUTLOOK_GET_CONTACT_FOLDERS` - List contact folders [Optional]
+4. `OUTLOOK_CREATE_CONTACT_FOLDER` - Create contact folder [Optional]
+
+**Key parameters**:
+- `givenName`/`surname`: Contact name
+- `emailAddresses`: Array of email objects
+- `displayName`: Full display name
+- `contact_folder_id`: Optional folder for contacts
+
+**Pitfalls**:
+- Contact creation supports many fields but only givenName or surname is needed
+
+### 5. Manage Mail Folders
+
+**When to use**: User wants to organize mail folders
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_MAIL_FOLDERS` - List top-level folders [Required]
+2. `OUTLOOK_LIST_CHILD_MAIL_FOLDERS` - List subfolders [Optional]
+3. `OUTLOOK_CREATE_MAIL_FOLDER` - Create a new folder [Optional]
+
+**Key parameters**:
+- `parent_folder_id`: Well-known name or folder ID
+- `displayName`: New folder name
+- `include_hidden_folders`: Show hidden folders
+
+**Pitfalls**:
+- Well-known folder names: 'inbox', 'sentitems', 'drafts', 'deleteditems', 'junkemail', 'archive'
+- Custom folder operations require the folder ID, not display name
+
+## Common Patterns
+
+### KQL Search Syntax
+
+**Property filters**:
+- `from:user@example.com` - From sender
+- `to:recipient@example.com` - To recipient
+- `subject:invoice` - Subject contains
+- `received>=2025-01-01` - Date filter
+- `hasattachment:yes` - Has attachments
+
+**Combinators**:
+- `AND` - Both conditions
+- `OR` - Either condition
+- Parentheses for grouping
+
+### OData Filter Syntax
+
+**Email filters**:
+- `isRead eq false` - Unread emails
+- `importance eq 'high'` - High importance
+- `hasAttachments eq true` - Has attachments
+- `receivedDateTime ge 2025-01-01T00:00:00Z` - Date filter
+
+**Calendar filters**:
+- `start/dateTime ge '2025-01-01T00:00:00Z'` - Events after date
+- `contains(subject, 'Meeting')` - Subject contains text
+
+## Known Pitfalls
+
+**Account Types**:
+- SEARCH_MESSAGES requires Microsoft 365/Enterprise accounts
+- Personal accounts (@hotmail.com, @outlook.com) have limited API access
+
+**Field Confusion**:
+- Email properties (receivedDateTime) differ from calendar properties (start/dateTime)
+- Do NOT use email fields in calendar queries or vice versa
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search emails | OUTLOOK_SEARCH_MESSAGES | query, from_index, size |
+| Query folder | OUTLOOK_QUERY_EMAILS | folder, filter, top |
+| Get message | OUTLOOK_GET_MESSAGE | message_id |
+| List attachments | OUTLOOK_LIST_OUTLOOK_ATTACHMENTS | message_id |
+| Download attachment | OUTLOOK_DOWNLOAD_OUTLOOK_ATTACHMENT | message_id, attachment_id |
+| List folders | OUTLOOK_LIST_MAIL_FOLDERS | (none) |
+| Child folders | OUTLOOK_LIST_CHILD_MAIL_FOLDERS | parent_folder_id |
+| List events | OUTLOOK_LIST_EVENTS | filter, timezone |
+| Calendar view | OUTLOOK_GET_CALENDAR_VIEW | start_datetime, end_datetime |
+| Get event | OUTLOOK_GET_EVENT | event_id |
+| List calendars | OUTLOOK_LIST_CALENDARS | (none) |
+| Free/busy | OUTLOOK_GET_SCHEDULE | schedules, times |
+| List contacts | OUTLOOK_LIST_CONTACTS | top, filter |
+| Create contact | OUTLOOK_CREATE_CONTACT | givenName, emailAddresses |
+| Contact folders | OUTLOOK_GET_CONTACT_FOLDERS | (none) |
diff --git a/outlook-calendar-automation/SKILL.md b/outlook-calendar-automation/SKILL.md
new file mode 100644
index 0000000..69b8183
--- /dev/null
+++ b/outlook-calendar-automation/SKILL.md
@@ -0,0 +1,233 @@
+---
+name: outlook-calendar-automation
+description: Automate Outlook Calendar tasks via Rube MCP (Composio): create events, manage attendees, find meeting times, and handle invitations. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Outlook Calendar Automation via Rube MCP
+
+Automate Outlook Calendar operations through Composio's Outlook toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Outlook connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `outlook`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `outlook`
+3. If connection is not ACTIVE, follow the returned auth link to complete Microsoft OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create Calendar Events
+
+**When to use**: User wants to schedule a new event on their Outlook calendar
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_CALENDARS` - List available calendars [Optional]
+2. `OUTLOOK_CALENDAR_CREATE_EVENT` - Create the event [Required]
+
+**Key parameters**:
+- `subject`: Event title
+- `start_datetime`: ISO 8601 start time (e.g., '2025-01-03T10:00:00')
+- `end_datetime`: ISO 8601 end time (must be after start)
+- `time_zone`: IANA or Windows timezone (e.g., 'America/New_York', 'Pacific Standard Time')
+- `attendees_info`: Array of email strings or attendee objects
+- `body`: Event description (plain text or HTML)
+- `is_html`: Set true if body contains HTML
+- `location`: Physical location string
+- `is_online_meeting`: Set true for Teams meeting link
+- `online_meeting_provider`: 'teamsForBusiness' for Teams integration
+- `show_as`: 'free', 'tentative', 'busy', 'oof'
+
+**Pitfalls**:
+- start_datetime must be chronologically before end_datetime
+- time_zone is required and must be a valid IANA or Windows timezone name
+- Adding attendees can trigger invitation emails immediately
+- To generate a Teams meeting link, set BOTH is_online_meeting=true AND online_meeting_provider='teamsForBusiness'
+- user_id defaults to 'me'; use email or UUID for other users' calendars
+
+### 2. List and Search Events
+
+**When to use**: User wants to find events on their calendar
+
+**Tool sequence**:
+1. `OUTLOOK_GET_MAILBOX_SETTINGS` - Get user timezone for accurate queries [Prerequisite]
+2. `OUTLOOK_LIST_EVENTS` - Search events with filters [Required]
+3. `OUTLOOK_GET_EVENT` - Get full details for a specific event [Optional]
+4. `OUTLOOK_GET_CALENDAR_VIEW` - Get events active during a time window [Alternative]
+
+**Key parameters**:
+- `filter`: OData filter string (e.g., "start/dateTime ge '2024-07-01T00:00:00Z'")
+- `select`: Array of properties to return
+- `orderby`: Sort criteria (e.g., ['start/dateTime desc'])
+- `top`: Results per page (1-999)
+- `timezone`: Display timezone for results
+- `start_datetime`/`end_datetime`: For CALENDAR_VIEW time window (UTC with Z suffix)
+
+**Pitfalls**:
+- OData filter datetime values require single quotes and Z suffix
+- Use 'start/dateTime' for event start filtering, NOT 'receivedDateTime' (that is for emails)
+- 'createdDateTime' supports orderby/select but NOT filtering
+- Pagination: follow @odata.nextLink until all pages are collected
+- CALENDAR_VIEW is better for "what's on my calendar today" queries (includes spanning events)
+- LIST_EVENTS is better for keyword/category filtering
+- Response events have start/end nested as start.dateTime and end.dateTime
+
+### 3. Update Events
+
+**When to use**: User wants to modify an existing calendar event
+
+**Tool sequence**:
+1. `OUTLOOK_LIST_EVENTS` - Find the event to update [Prerequisite]
+2. `OUTLOOK_UPDATE_CALENDAR_EVENT` - Update the event [Required]
+
+**Key parameters**:
+- `event_id`: Unique event identifier (from LIST_EVENTS)
+- `subject`: New event title (optional)
+- `start_datetime`/`end_datetime`: New times (optional)
+- `time_zone`: Timezone for new times
+- `attendees`: Updated attendee list (replaces existing if provided)
+- `body`: Updated description with contentType and content
+- `location`: Updated location
+
+**Pitfalls**:
+- UPDATE merges provided fields with existing event; unspecified fields are preserved
+- Providing attendees replaces the ENTIRE attendee list; include all desired attendees
+- Providing categories replaces the ENTIRE category list
+- Updating times may trigger re-sends to attendees
+- event_id is required; obtain from LIST_EVENTS first
+
+### 4. Delete Events and Decline Invitations
+
+**When to use**: User wants to remove an event or decline a meeting invitation
+
+**Tool sequence**:
+1. `OUTLOOK_DELETE_EVENT` - Delete an event [Optional]
+2. `OUTLOOK_DECLINE_EVENT` - Decline a meeting invitation [Optional]
+
+**Key parameters**:
+- `event_id`: Event to delete or decline
+- `send_notifications`: Send cancellation notices to attendees (default true)
+- `comment`: Reason for declining (for DECLINE_EVENT)
+- `proposedNewTime`: Suggest alternative time when declining
+
+**Pitfalls**:
+- Deletion with send_notifications=true sends cancellation emails
+- Declining supports proposing a new time with start/end in ISO 8601 format
+- Deleting a recurring event master deletes all occurrences
+- sendResponse in DECLINE_EVENT controls whether the organizer is notified
+
+### 5. Find Available Meeting Times
+
+**When to use**: User wants to find optimal meeting slots across multiple people
+
+**Tool sequence**:
+1. `OUTLOOK_FIND_MEETING_TIMES` - Get meeting time suggestions [Required]
+2. `OUTLOOK_GET_SCHEDULE` - Check free/busy for specific people [Alternative]
+
+**Key parameters**:
+- `attendees`: Array of attendee objects with email and type
+- `meetingDuration`: ISO 8601 duration (e.g., 'PT1H' for 1 hour, 'PT30M' for 30 min)
+- `timeConstraint`: Time slots to search within
+- `minimumAttendeePercentage`: Minimum confidence threshold (0-100)
+- `Schedules`: Email array for GET_SCHEDULE
+- `StartTime`/`EndTime`: Time window for schedule lookup (max 62 days)
+
+**Pitfalls**:
+- FIND_MEETING_TIMES searches within work hours by default; use activityDomain='unrestricted' for 24/7
+- Time constraint time slots require dateTime and timeZone for both start and end
+- GET_SCHEDULE period cannot exceed 62 days
+- Meeting suggestions respect attendee availability but may return suboptimal times for complex groups
+
+## Common Patterns
+
+### Event ID Resolution
+
+```
+1. Call OUTLOOK_LIST_EVENTS with time-bound filter
+2. Find target event by subject or other criteria
+3. Extract event id (e.g., 'AAMkAGI2TAAA=')
+4. Use in UPDATE, DELETE, or GET_EVENT calls
+```
+
+### OData Filter Syntax for Calendar
+
+**Time range filter**:
+```
+filter: "start/dateTime ge '2024-07-01T00:00:00Z' and start/dateTime le '2024-07-31T23:59:59Z'"
+```
+
+**Subject contains**:
+```
+filter: "contains(subject, 'Project Review')"
+```
+
+**Combined**:
+```
+filter: "contains(subject, 'Review') and categories/any(c:c eq 'Work')"
+```
+
+### Timezone Handling
+
+- Get user timezone: `OUTLOOK_GET_MAILBOX_SETTINGS` with select=['timeZone']
+- Use consistent timezone in filter datetime values
+- Calendar View requires UTC timestamps with Z suffix
+- LIST_EVENTS filter accepts timezone in datetime values
+
+### Online Meeting Creation
+
+```
+1. Set is_online_meeting: true
+2. Set online_meeting_provider: 'teamsForBusiness'
+3. Create event with OUTLOOK_CALENDAR_CREATE_EVENT
+4. Teams join link available in response onlineMeeting field
+5. Or retrieve via OUTLOOK_GET_EVENT for the full join URL
+```
+
+## Known Pitfalls
+
+**DateTime Formats**:
+- ISO 8601 format required: '2025-01-03T10:00:00'
+- Calendar View requires UTC with Z: '2025-01-03T10:00:00Z'
+- Filter values need single quotes: "'2025-01-03T00:00:00Z'"
+- Timezone mismatches shift event boundaries; always resolve user timezone first
+
+**OData Filter Errors**:
+- 400 Bad Request usually indicates filter syntax issues
+- Not all event properties support filtering (createdDateTime does not)
+- Retry with adjusted syntax/bounds on 400 errors
+- Valid filter fields: start/dateTime, end/dateTime, subject, categories, isAllDay
+
+**Attendee Management**:
+- Adding attendees triggers invitation emails
+- Updating attendees replaces the full list; include all desired attendees
+- Attendee types: 'required', 'optional', 'resource'
+- Calendar delegation affects which calendars are accessible
+
+**Response Structure**:
+- Events nested at response.data.value
+- Event times at event.start.dateTime and event.end.dateTime
+- Calendar View may nest at data.results[i].response.data.value
+- Parse defensively with fallbacks for different nesting levels
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create event | OUTLOOK_CALENDAR_CREATE_EVENT | subject, start_datetime, end_datetime, time_zone |
+| List events | OUTLOOK_LIST_EVENTS | filter, select, top, timezone |
+| Get event details | OUTLOOK_GET_EVENT | event_id |
+| Calendar view | OUTLOOK_GET_CALENDAR_VIEW | start_datetime, end_datetime |
+| Update event | OUTLOOK_UPDATE_CALENDAR_EVENT | event_id, subject, start_datetime |
+| Delete event | OUTLOOK_DELETE_EVENT | event_id, send_notifications |
+| Decline event | OUTLOOK_DECLINE_EVENT | event_id, comment |
+| Find meeting times | OUTLOOK_FIND_MEETING_TIMES | attendees, meetingDuration |
+| Get schedule | OUTLOOK_GET_SCHEDULE | Schedules, StartTime, EndTime |
+| List calendars | OUTLOOK_LIST_CALENDARS | user_id |
+| Mailbox settings | OUTLOOK_GET_MAILBOX_SETTINGS | select |
diff --git a/pagerduty-automation/SKILL.md b/pagerduty-automation/SKILL.md
new file mode 100644
index 0000000..1625283
--- /dev/null
+++ b/pagerduty-automation/SKILL.md
@@ -0,0 +1,242 @@
+---
+name: pagerduty-automation
+description: Automate PagerDuty tasks via Rube MCP (Composio): manage incidents, services, schedules, escalation policies, and on-call rotations. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# PagerDuty Automation via Rube MCP
+
+Automate PagerDuty incident management and operations through Composio's PagerDuty toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active PagerDuty connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `pagerduty`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `pagerduty`
+3. If connection is not ACTIVE, follow the returned auth link to complete PagerDuty authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Incidents
+
+**When to use**: User wants to create, update, acknowledge, or resolve incidents
+
+**Tool sequence**:
+1. `PAGERDUTY_FETCH_INCIDENT_LIST` - List incidents with filters [Required]
+2. `PAGERDUTY_RETRIEVE_INCIDENT_BY_INCIDENT_ID` - Get specific incident details [Optional]
+3. `PAGERDUTY_CREATE_INCIDENT_RECORD` - Create a new incident [Optional]
+4. `PAGERDUTY_UPDATE_INCIDENT_BY_ID` - Update incident status or assignment [Optional]
+5. `PAGERDUTY_POST_INCIDENT_NOTE_USING_ID` - Add a note to an incident [Optional]
+6. `PAGERDUTY_SNOOZE_INCIDENT_BY_DURATION` - Snooze an incident for a period [Optional]
+
+**Key parameters**:
+- `statuses[]`: Filter by status ('triggered', 'acknowledged', 'resolved')
+- `service_ids[]`: Filter by service IDs
+- `urgencies[]`: Filter by urgency ('high', 'low')
+- `title`: Incident title (for creation)
+- `service`: Service object with `id` and `type` (for creation)
+- `status`: New status for update operations
+
+**Pitfalls**:
+- Incident creation requires a `service` object with both `id` and `type: 'service_reference'`
+- Status transitions follow: triggered -> acknowledged -> resolved
+- Cannot transition from resolved back to triggered directly
+- `PAGERDUTY_UPDATE_INCIDENT_BY_ID` requires the incident ID as a path parameter
+- Snooze duration is in seconds; the incident re-triggers after the snooze period
+
+### 2. Inspect Incident Alerts and Analytics
+
+**When to use**: User wants to review alerts within an incident or analyze incident metrics
+
+**Tool sequence**:
+1. `PAGERDUTY_GET_ALERTS_BY_INCIDENT_ID` - List alerts for an incident [Required]
+2. `PAGERDUTY_GET_INCIDENT_ALERT_DETAILS` - Get details of a specific alert [Optional]
+3. `PAGERDUTY_FETCH_INCIDENT_ANALYTICS_BY_ID` - Get incident analytics/metrics [Optional]
+
+**Key parameters**:
+- `incident_id`: The incident ID
+- `alert_id`: Specific alert ID within the incident
+- `statuses[]`: Filter alerts by status
+
+**Pitfalls**:
+- An incident can have multiple alerts; each alert has its own status
+- Alert IDs are scoped to the incident
+- Analytics data includes response times, engagement metrics, and resolution times
+
+### 3. Manage Services
+
+**When to use**: User wants to create, update, or list services
+
+**Tool sequence**:
+1. `PAGERDUTY_RETRIEVE_LIST_OF_SERVICES` - List all services [Required]
+2. `PAGERDUTY_RETRIEVE_SERVICE_BY_ID` - Get service details [Optional]
+3. `PAGERDUTY_CREATE_NEW_SERVICE` - Create a new technical service [Optional]
+4. `PAGERDUTY_UPDATE_SERVICE_BY_ID` - Update service configuration [Optional]
+5. `PAGERDUTY_CREATE_INTEGRATION_FOR_SERVICE` - Add an integration to a service [Optional]
+6. `PAGERDUTY_CREATE_BUSINESS_SERVICE` - Create a business service [Optional]
+7. `PAGERDUTY_UPDATE_BUSINESS_SERVICE_BY_ID` - Update a business service [Optional]
+
+**Key parameters**:
+- `name`: Service name
+- `escalation_policy`: Escalation policy object with `id` and `type`
+- `alert_creation`: Alert creation mode ('create_alerts_and_incidents' or 'create_incidents')
+- `status`: Service status ('active', 'warning', 'critical', 'maintenance', 'disabled')
+
+**Pitfalls**:
+- Creating a service requires an existing escalation policy
+- Business services are different from technical services; they represent business-level groupings
+- Service integrations define how alerts are created (email, API, events)
+- Disabling a service stops all incident creation for that service
+
+### 4. Manage Schedules and On-Call
+
+**When to use**: User wants to view or manage on-call schedules and rotations
+
+**Tool sequence**:
+1. `PAGERDUTY_GET_SCHEDULES` - List all schedules [Required]
+2. `PAGERDUTY_RETRIEVE_SCHEDULE_BY_ID` - Get specific schedule details [Optional]
+3. `PAGERDUTY_CREATE_NEW_SCHEDULE_LAYER` - Create a new schedule [Optional]
+4. `PAGERDUTY_UPDATE_SCHEDULE_BY_ID` - Update an existing schedule [Optional]
+5. `PAGERDUTY_RETRIEVE_ONCALL_LIST` - View who is currently on-call [Optional]
+6. `PAGERDUTY_CREATE_SCHEDULE_OVERRIDES_CONFIGURATION` - Create temporary overrides [Optional]
+7. `PAGERDUTY_DELETE_SCHEDULE_OVERRIDE_BY_ID` - Remove an override [Optional]
+8. `PAGERDUTY_RETRIEVE_USERS_BY_SCHEDULE_ID` - List users in a schedule [Optional]
+9. `PAGERDUTY_PREVIEW_SCHEDULE_OBJECT` - Preview schedule changes before saving [Optional]
+
+**Key parameters**:
+- `schedule_id`: Schedule identifier
+- `time_zone`: Schedule timezone (e.g., 'America/New_York')
+- `schedule_layers`: Array of rotation layer configurations
+- `since`/`until`: Date range for on-call queries (ISO 8601)
+- `override`: Override object with user, start, and end times
+
+**Pitfalls**:
+- Schedule layers define rotation order; multiple layers can overlap
+- Overrides are temporary and take precedence over the normal schedule
+- `since` and `until` are required for on-call queries to scope the time range
+- Time zones must be valid IANA timezone strings
+- Preview before saving complex schedule changes to verify correctness
+
+### 5. Manage Escalation Policies
+
+**When to use**: User wants to create or modify escalation policies
+
+**Tool sequence**:
+1. `PAGERDUTY_FETCH_ESCALATION_POLICES_LIST` - List all escalation policies [Required]
+2. `PAGERDUTY_GET_ESCALATION_POLICY_BY_ID` - Get policy details [Optional]
+3. `PAGERDUTY_CREATE_ESCALATION_POLICY` - Create a new policy [Optional]
+4. `PAGERDUTY_UPDATE_ESCALATION_POLICY_BY_ID` - Update an existing policy [Optional]
+5. `PAGERDUTY_AUDIT_ESCALATION_POLICY_RECORDS` - View audit trail for a policy [Optional]
+
+**Key parameters**:
+- `name`: Policy name
+- `escalation_rules`: Array of escalation rule objects
+- `num_loops`: Number of times to loop through rules before stopping (0 = no loop)
+- `escalation_delay_in_minutes`: Delay between escalation levels
+
+**Pitfalls**:
+- Each escalation rule requires at least one target (user, schedule, or team)
+- `escalation_delay_in_minutes` defines how long before escalating to the next level
+- Setting `num_loops` to 0 means the policy runs once and stops
+- Deleting a policy fails if services still reference it
+
+### 6. Manage Teams
+
+**When to use**: User wants to create or manage PagerDuty teams
+
+**Tool sequence**:
+1. `PAGERDUTY_CREATE_NEW_TEAM_WITH_DETAILS` - Create a new team [Required]
+
+**Key parameters**:
+- `name`: Team name
+- `description`: Team description
+
+**Pitfalls**:
+- Team names must be unique within the account
+- Teams are used to scope services, escalation policies, and schedules
+
+## Common Patterns
+
+### ID Resolution
+
+**Service name -> Service ID**:
+```
+1. Call PAGERDUTY_RETRIEVE_LIST_OF_SERVICES
+2. Find service by name in response
+3. Extract id field
+```
+
+**Schedule name -> Schedule ID**:
+```
+1. Call PAGERDUTY_GET_SCHEDULES
+2. Find schedule by name in response
+3. Extract id field
+```
+
+### Incident Lifecycle
+
+```
+1. Incident triggered (via API, integration, or manual creation)
+2. On-call user notified per escalation policy
+3. User acknowledges -> status: 'acknowledged'
+4. User resolves -> status: 'resolved'
+```
+
+### Pagination
+
+- PagerDuty uses offset-based pagination
+- Check response for `more` boolean field
+- Use `offset` and `limit` parameters
+- Continue until `more` is false
+
+## Known Pitfalls
+
+**ID Formats**:
+- All PagerDuty IDs are alphanumeric strings (e.g., 'P1234AB')
+- Service references require `type: 'service_reference'`
+- User references require `type: 'user_reference'`
+
+**Status Transitions**:
+- Incidents: triggered -> acknowledged -> resolved (forward only)
+- Services: active, warning, critical, maintenance, disabled
+
+**Rate Limits**:
+- PagerDuty API enforces rate limits per account
+- Implement exponential backoff on 429 responses
+- Bulk operations should be spaced out
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Pagination uses `offset`/`limit`/`more` pattern
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List incidents | PAGERDUTY_FETCH_INCIDENT_LIST | statuses[], service_ids[] |
+| Get incident | PAGERDUTY_RETRIEVE_INCIDENT_BY_INCIDENT_ID | incident_id |
+| Create incident | PAGERDUTY_CREATE_INCIDENT_RECORD | title, service |
+| Update incident | PAGERDUTY_UPDATE_INCIDENT_BY_ID | incident_id, status |
+| Add incident note | PAGERDUTY_POST_INCIDENT_NOTE_USING_ID | incident_id, content |
+| Snooze incident | PAGERDUTY_SNOOZE_INCIDENT_BY_DURATION | incident_id, duration |
+| Get incident alerts | PAGERDUTY_GET_ALERTS_BY_INCIDENT_ID | incident_id |
+| Incident analytics | PAGERDUTY_FETCH_INCIDENT_ANALYTICS_BY_ID | incident_id |
+| List services | PAGERDUTY_RETRIEVE_LIST_OF_SERVICES | (none) |
+| Get service | PAGERDUTY_RETRIEVE_SERVICE_BY_ID | service_id |
+| Create service | PAGERDUTY_CREATE_NEW_SERVICE | name, escalation_policy |
+| Update service | PAGERDUTY_UPDATE_SERVICE_BY_ID | service_id |
+| List schedules | PAGERDUTY_GET_SCHEDULES | (none) |
+| Get schedule | PAGERDUTY_RETRIEVE_SCHEDULE_BY_ID | schedule_id |
+| Get on-call | PAGERDUTY_RETRIEVE_ONCALL_LIST | since, until |
+| Create schedule override | PAGERDUTY_CREATE_SCHEDULE_OVERRIDES_CONFIGURATION | schedule_id |
+| List escalation policies | PAGERDUTY_FETCH_ESCALATION_POLICES_LIST | (none) |
+| Create escalation policy | PAGERDUTY_CREATE_ESCALATION_POLICY | name, escalation_rules |
+| Create team | PAGERDUTY_CREATE_NEW_TEAM_WITH_DETAILS | name, description |
diff --git a/pipedrive-automation/SKILL.md b/pipedrive-automation/SKILL.md
new file mode 100644
index 0000000..fe47078
--- /dev/null
+++ b/pipedrive-automation/SKILL.md
@@ -0,0 +1,221 @@
+---
+name: pipedrive-automation
+description: Automate Pipedrive CRM operations including deals, contacts, organizations, activities, notes, and pipeline management via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Pipedrive Automation via Rube MCP
+
+Automate Pipedrive CRM workflows including deal management, contact and organization operations, activity scheduling, notes, and pipeline/stage queries through Composio's Pipedrive toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Pipedrive connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `pipedrive`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `pipedrive`
+3. If connection is not ACTIVE, follow the returned auth link to complete Pipedrive OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Deals
+
+**When to use**: User wants to create a new deal, update an existing deal, or review deal details in the sales pipeline.
+
+**Tool sequence**:
+1. `PIPEDRIVE_SEARCH_ORGANIZATIONS` - Find existing org to link to the deal [Optional]
+2. `PIPEDRIVE_ADD_AN_ORGANIZATION` - Create organization if none found [Optional]
+3. `PIPEDRIVE_SEARCH_PERSONS` - Find existing contact to link [Optional]
+4. `PIPEDRIVE_ADD_A_PERSON` - Create contact if none found [Optional]
+5. `PIPEDRIVE_GET_ALL_PIPELINES` - Resolve pipeline ID [Prerequisite]
+6. `PIPEDRIVE_GET_ALL_STAGES` - Resolve stage ID within the pipeline [Prerequisite]
+7. `PIPEDRIVE_ADD_A_DEAL` - Create the deal with title, value, org_id, person_id, stage_id [Required]
+8. `PIPEDRIVE_UPDATE_A_DEAL` - Modify deal properties after creation [Optional]
+9. `PIPEDRIVE_ADD_A_PRODUCT_TO_A_DEAL` - Attach line items/products [Optional]
+
+**Key parameters**:
+- `title`: Deal title (required for creation)
+- `value`: Monetary value of the deal
+- `currency`: 3-letter ISO currency code (e.g., "USD")
+- `pipeline_id` / `stage_id`: Numeric IDs for pipeline placement
+- `org_id` / `person_id`: Link to organization and contact
+- `status`: "open", "won", or "lost"
+- `expected_close_date`: Format YYYY-MM-DD
+
+**Pitfalls**:
+- `title` is the only required field for `PIPEDRIVE_ADD_A_DEAL`; all others are optional
+- Custom fields appear as long hash keys in responses; use dealFields endpoint to map them
+- `PIPEDRIVE_UPDATE_A_DEAL` requires the numeric `id` of the deal
+- Setting `status` to "lost" requires also providing `lost_reason`
+
+### 2. Manage Contacts (Persons and Organizations)
+
+**When to use**: User wants to create, update, search, or list contacts and companies in Pipedrive.
+
+**Tool sequence**:
+1. `PIPEDRIVE_SEARCH_PERSONS` - Search for existing person by name, email, or phone [Prerequisite]
+2. `PIPEDRIVE_ADD_A_PERSON` - Create new contact if not found [Required]
+3. `PIPEDRIVE_UPDATE_A_PERSON` - Modify existing contact details [Optional]
+4. `PIPEDRIVE_GET_DETAILS_OF_A_PERSON` - Retrieve full contact record [Optional]
+5. `PIPEDRIVE_SEARCH_ORGANIZATIONS` - Search for existing organization [Prerequisite]
+6. `PIPEDRIVE_ADD_AN_ORGANIZATION` - Create new organization if not found [Required]
+7. `PIPEDRIVE_UPDATE_AN_ORGANIZATION` - Modify organization properties [Optional]
+8. `PIPEDRIVE_GET_DETAILS_OF_AN_ORGANIZATION` - Retrieve full org record [Optional]
+
+**Key parameters**:
+- `name`: Required for both person and organization creation
+- `email`: Array of objects with `value`, `label`, `primary` fields for persons
+- `phone`: Array of objects with `value`, `label`, `primary` fields for persons
+- `org_id`: Link a person to an organization
+- `visible_to`: 1 = owner only, 3 = entire company
+- `term`: Search term for SEARCH_PERSONS / SEARCH_ORGANIZATIONS (minimum 2 characters)
+
+**Pitfalls**:
+- `PIPEDRIVE_ADD_AN_ORGANIZATION` may auto-merge with an existing org; check `response.additional_data.didMerge`
+- Email and phone fields are arrays of objects, not plain strings: `[{"value": "test@example.com", "label": "work", "primary": true}]`
+- `PIPEDRIVE_SEARCH_PERSONS` wildcards like `*` or `@` are NOT supported; use `PIPEDRIVE_GET_ALL_PERSONS` to list all
+- Deletion via `PIPEDRIVE_DELETE_A_PERSON` or `PIPEDRIVE_DELETE_AN_ORGANIZATION` is soft-delete with 30-day retention, then permanent
+
+### 3. Schedule and Track Activities
+
+**When to use**: User wants to create calls, meetings, tasks, or other activities linked to deals, contacts, or organizations.
+
+**Tool sequence**:
+1. `PIPEDRIVE_SEARCH_PERSONS` or `PIPEDRIVE_GET_DETAILS_OF_A_DEAL` - Resolve linked entity IDs [Prerequisite]
+2. `PIPEDRIVE_ADD_AN_ACTIVITY` - Create the activity with subject, type, due date [Required]
+3. `PIPEDRIVE_UPDATE_AN_ACTIVITY` - Modify activity details or mark as done [Optional]
+4. `PIPEDRIVE_GET_DETAILS_OF_AN_ACTIVITY` - Retrieve activity record [Optional]
+5. `PIPEDRIVE_GET_ALL_ACTIVITIES_ASSIGNED_TO_A_PARTICULAR_USER` - List user's activities [Optional]
+
+**Key parameters**:
+- `subject`: Activity title (required)
+- `type`: Activity type key string, e.g., "call", "meeting", "task", "email" (required)
+- `due_date`: Format YYYY-MM-DD
+- `due_time`: Format HH:MM
+- `duration`: Format HH:MM (e.g., "00:30" for 30 minutes)
+- `deal_id` / `person_id` / `org_id`: Link to related entities
+- `done`: 0 = not done, 1 = done
+
+**Pitfalls**:
+- Both `subject` and `type` are required for `PIPEDRIVE_ADD_AN_ACTIVITY`
+- `type` must match an existing ActivityTypes key_string in the account
+- `done` is an integer (0 or 1), not a boolean
+- Response includes `more_activities_scheduled_in_context` in additional_data
+
+### 4. Add and Manage Notes
+
+**When to use**: User wants to attach notes to deals, persons, organizations, leads, or projects.
+
+**Tool sequence**:
+1. `PIPEDRIVE_SEARCH_PERSONS` or `PIPEDRIVE_GET_DETAILS_OF_A_DEAL` - Resolve entity ID [Prerequisite]
+2. `PIPEDRIVE_ADD_A_NOTE` - Create note with HTML content linked to an entity [Required]
+3. `PIPEDRIVE_UPDATE_A_NOTE` - Modify note content [Optional]
+4. `PIPEDRIVE_GET_ALL_NOTES` - List notes filtered by entity [Optional]
+5. `PIPEDRIVE_GET_ALL_COMMENTS_FOR_A_NOTE` - Retrieve comments on a note [Optional]
+
+**Key parameters**:
+- `content`: Note body in HTML format (required)
+- `deal_id` / `person_id` / `org_id` / `lead_id` / `project_id`: At least one entity link required
+- `pinned_to_deal_flag` / `pinned_to_person_flag`: Filter pinned notes when listing
+
+**Pitfalls**:
+- `content` is required and supports HTML; plain text works but is sanitized server-side
+- At least one of `deal_id`, `person_id`, `org_id`, `lead_id`, or `project_id` must be provided
+- `PIPEDRIVE_GET_ALL_NOTES` returns notes across all entities by default; filter with entity ID params
+
+### 5. Query Pipelines and Stages
+
+**When to use**: User wants to view sales pipelines, stages, or deals within a pipeline/stage.
+
+**Tool sequence**:
+1. `PIPEDRIVE_GET_ALL_PIPELINES` - List all pipelines and their IDs [Required]
+2. `PIPEDRIVE_GET_ONE_PIPELINE` - Get details and deal summary for a specific pipeline [Optional]
+3. `PIPEDRIVE_GET_ALL_STAGES` - List all stages, optionally filtered by pipeline [Required]
+4. `PIPEDRIVE_GET_ONE_STAGE` - Get details for a specific stage [Optional]
+5. `PIPEDRIVE_GET_DEALS_IN_A_PIPELINE` - List all deals across stages in a pipeline [Optional]
+6. `PIPEDRIVE_GET_DEALS_IN_A_STAGE` - List deals in a specific stage [Optional]
+
+**Key parameters**:
+- `id`: Pipeline or stage ID (required for single-item endpoints)
+- `pipeline_id`: Filter stages by pipeline
+- `totals_convert_currency`: 3-letter currency code or "default_currency" for converted totals
+- `get_summary`: Set to 1 for deal summary in pipeline responses
+
+**Pitfalls**:
+- `PIPEDRIVE_GET_ALL_PIPELINES` takes no parameters; returns all pipelines
+- `PIPEDRIVE_GET_ALL_STAGES` returns stages for ALL pipelines unless `pipeline_id` is specified
+- Deal counts in pipeline summaries use `per_stages_converted` only when `totals_convert_currency` is set
+
+## Common Patterns
+
+### ID Resolution
+Always resolve display names to numeric IDs before operations:
+- **Organization name -> org_id**: `PIPEDRIVE_SEARCH_ORGANIZATIONS` with `term` param
+- **Person name -> person_id**: `PIPEDRIVE_SEARCH_PERSONS` with `term` param
+- **Pipeline name -> pipeline_id**: `PIPEDRIVE_GET_ALL_PIPELINES` then match by name
+- **Stage name -> stage_id**: `PIPEDRIVE_GET_ALL_STAGES` with `pipeline_id` then match by name
+
+### Pagination
+Most list endpoints use offset-based pagination:
+- Use `start` (offset) and `limit` (page size) parameters
+- Check `additional_data.pagination.more_items_in_collection` to know if more pages exist
+- Use `additional_data.pagination.next_start` as the `start` value for the next page
+- Default limit is ~500 for some endpoints; set explicitly for predictable paging
+
+## Known Pitfalls
+
+### ID Formats
+- All entity IDs (deal, person, org, activity, pipeline, stage) are numeric integers
+- Lead IDs are UUID strings, not integers
+- Custom field keys are long alphanumeric hashes (e.g., "a1b2c3d4e5f6...")
+
+### Rate Limits
+- Pipedrive enforces per-company API rate limits; bulk operations should be paced
+- `PIPEDRIVE_GET_ALL_PERSONS` and `PIPEDRIVE_GET_ALL_ORGANIZATIONS` can return large datasets; always paginate
+
+### Parameter Quirks
+- Email and phone on persons are arrays of objects, not plain strings
+- `visible_to` is numeric: 1 = owner only, 3 = entire company, 5 = specific groups
+- `done` on activities is integer 0/1, not boolean true/false
+- Organization creation may auto-merge duplicates silently; check `didMerge` in response
+- `PIPEDRIVE_SEARCH_PERSONS` requires minimum 2 characters and does not support wildcards
+
+### Response Structure
+- Custom fields appear as hash keys in responses; map them via the respective Fields endpoints
+- Responses often nest data under `response.data.data` in wrapped executions
+- Search results are under `response.data.items`, not top-level
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create deal | `PIPEDRIVE_ADD_A_DEAL` | `title`, `value`, `org_id`, `stage_id` |
+| Update deal | `PIPEDRIVE_UPDATE_A_DEAL` | `id`, `status`, `value`, `stage_id` |
+| Get deal details | `PIPEDRIVE_GET_DETAILS_OF_A_DEAL` | `id` |
+| Search persons | `PIPEDRIVE_SEARCH_PERSONS` | `term`, `fields` |
+| Add person | `PIPEDRIVE_ADD_A_PERSON` | `name`, `email`, `phone`, `org_id` |
+| Update person | `PIPEDRIVE_UPDATE_A_PERSON` | `id`, `name`, `email` |
+| Get person details | `PIPEDRIVE_GET_DETAILS_OF_A_PERSON` | `id` |
+| List all persons | `PIPEDRIVE_GET_ALL_PERSONS` | `start`, `limit`, `filter_id` |
+| Search organizations | `PIPEDRIVE_SEARCH_ORGANIZATIONS` | `term`, `fields` |
+| Add organization | `PIPEDRIVE_ADD_AN_ORGANIZATION` | `name`, `visible_to` |
+| Update organization | `PIPEDRIVE_UPDATE_AN_ORGANIZATION` | `id`, `name`, `address` |
+| Get org details | `PIPEDRIVE_GET_DETAILS_OF_AN_ORGANIZATION` | `id` |
+| Add activity | `PIPEDRIVE_ADD_AN_ACTIVITY` | `subject`, `type`, `due_date`, `deal_id` |
+| Update activity | `PIPEDRIVE_UPDATE_AN_ACTIVITY` | `id`, `done`, `due_date` |
+| Get activity details | `PIPEDRIVE_GET_DETAILS_OF_AN_ACTIVITY` | `id` |
+| List user activities | `PIPEDRIVE_GET_ALL_ACTIVITIES_ASSIGNED_TO_A_PARTICULAR_USER` | `user_id`, `start`, `limit` |
+| Add note | `PIPEDRIVE_ADD_A_NOTE` | `content`, `deal_id` or `person_id` |
+| List notes | `PIPEDRIVE_GET_ALL_NOTES` | `deal_id`, `person_id`, `start`, `limit` |
+| List pipelines | `PIPEDRIVE_GET_ALL_PIPELINES` | (none) |
+| Get pipeline details | `PIPEDRIVE_GET_ONE_PIPELINE` | `id` |
+| List stages | `PIPEDRIVE_GET_ALL_STAGES` | `pipeline_id` |
+| Deals in pipeline | `PIPEDRIVE_GET_DEALS_IN_A_PIPELINE` | `id`, `stage_id` |
+| Deals in stage | `PIPEDRIVE_GET_DEALS_IN_A_STAGE` | `id`, `start`, `limit` |
+| Add product to deal | `PIPEDRIVE_ADD_A_PRODUCT_TO_A_DEAL` | `id`, `product_id`, `item_price` |
diff --git a/posthog-automation/SKILL.md b/posthog-automation/SKILL.md
new file mode 100644
index 0000000..146870f
--- /dev/null
+++ b/posthog-automation/SKILL.md
@@ -0,0 +1,221 @@
+---
+name: posthog-automation
+description: Automate PostHog tasks via Rube MCP (Composio): events, feature flags, projects, user profiles, annotations. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# PostHog Automation via Rube MCP
+
+Automate PostHog product analytics and feature flag management through Composio's PostHog toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active PostHog connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `posthog`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `posthog`
+3. If connection is not ACTIVE, follow the returned auth link to complete PostHog authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Capture Events
+
+**When to use**: User wants to send event data to PostHog for analytics tracking
+
+**Tool sequence**:
+1. `POSTHOG_CAPTURE_EVENT` - Send one or more events to PostHog [Required]
+
+**Key parameters**:
+- `event`: Event name (e.g., '$pageview', 'user_signed_up', 'purchase_completed')
+- `distinct_id`: Unique user identifier (required)
+- `properties`: Object with event-specific properties
+- `timestamp`: ISO 8601 timestamp (optional; defaults to server time)
+
+**Pitfalls**:
+- `distinct_id` is required for every event; identifies the user/device
+- PostHog system events use `$` prefix (e.g., '$pageview', '$identify')
+- Custom events should NOT use the `$` prefix
+- Properties are freeform; maintain consistent schemas across events
+- Events are processed asynchronously; ingestion delay is typically seconds
+
+### 2. List and Filter Events
+
+**When to use**: User wants to browse or search through captured events
+
+**Tool sequence**:
+1. `POSTHOG_LIST_AND_FILTER_PROJECT_EVENTS` - Query events with filters [Required]
+
+**Key parameters**:
+- `project_id`: PostHog project ID (required)
+- `event`: Filter by event name
+- `person_id`: Filter by person ID
+- `after`: Events after this ISO 8601 timestamp
+- `before`: Events before this ISO 8601 timestamp
+- `limit`: Maximum events to return
+- `offset`: Pagination offset
+
+**Pitfalls**:
+- `project_id` is required; resolve via LIST_PROJECTS first
+- Date filters use ISO 8601 format (e.g., '2024-01-15T00:00:00Z')
+- Large event volumes require pagination; use `offset` and `limit`
+- Results are returned in reverse chronological order by default
+- Event properties are nested; parse carefully
+
+### 3. Manage Feature Flags
+
+**When to use**: User wants to create, view, or manage feature flags
+
+**Tool sequence**:
+1. `POSTHOG_LIST_AND_MANAGE_PROJECT_FEATURE_FLAGS` - List existing feature flags [Required]
+2. `POSTHOG_RETRIEVE_FEATURE_FLAG_DETAILS` - Get detailed flag configuration [Optional]
+3. `POSTHOG_CREATE_FEATURE_FLAGS_FOR_PROJECT` - Create a new feature flag [Optional]
+
+**Key parameters**:
+- For listing: `project_id` (required)
+- For details: `project_id`, `id` (feature flag ID)
+- For creation:
+ - `project_id`: Target project
+ - `key`: Flag key (e.g., 'new-dashboard-beta')
+ - `name`: Human-readable name
+ - `filters`: Targeting rules and rollout percentage
+ - `active`: Whether the flag is enabled
+
+**Pitfalls**:
+- Feature flag `key` must be unique within a project
+- Flag keys should use kebab-case (e.g., 'my-feature-flag')
+- `filters` define targeting groups with properties and rollout percentages
+- Creating a flag with `active: true` immediately enables it for matching users
+- Flag changes take effect within seconds due to PostHog's polling mechanism
+
+### 4. Manage Projects
+
+**When to use**: User wants to list or inspect PostHog projects and organizations
+
+**Tool sequence**:
+1. `POSTHOG_LIST_PROJECTS_IN_ORGANIZATION_WITH_PAGINATION` - List all projects [Required]
+
+**Key parameters**:
+- `organization_id`: Organization identifier (may be optional depending on auth)
+- `limit`: Number of results per page
+- `offset`: Pagination offset
+
+**Pitfalls**:
+- Project IDs are numeric; used as parameters in most other endpoints
+- Organization ID may be required; check your PostHog setup
+- Pagination is offset-based; iterate until results are empty
+- Project settings include API keys and configuration details
+
+### 5. User Profile and Authentication
+
+**When to use**: User wants to check current user details or verify API access
+
+**Tool sequence**:
+1. `POSTHOG_WHOAMI` - Get current API user information [Optional]
+2. `POSTHOG_RETRIEVE_CURRENT_USER_PROFILE` - Get detailed user profile [Optional]
+
+**Key parameters**:
+- No required parameters for either call
+- Returns current authenticated user's details, permissions, and organization info
+
+**Pitfalls**:
+- WHOAMI is a lightweight check; use for verifying API connectivity
+- User profile includes organization membership and permissions
+- These endpoints confirm the API key's access level and scope
+
+## Common Patterns
+
+### ID Resolution
+
+**Organization -> Project ID**:
+```
+1. Call POSTHOG_LIST_PROJECTS_IN_ORGANIZATION_WITH_PAGINATION
+2. Find project by name in results
+3. Extract id (numeric) for use in other endpoints
+```
+
+**Feature flag name -> Flag ID**:
+```
+1. Call POSTHOG_LIST_AND_MANAGE_PROJECT_FEATURE_FLAGS with project_id
+2. Find flag by key or name
+3. Extract id for detailed operations
+```
+
+### Feature Flag Targeting
+
+Feature flags support sophisticated targeting:
+```json
+{
+ "filters": {
+ "groups": [
+ {
+ "properties": [
+ {"key": "email", "value": "@company.com", "operator": "icontains"}
+ ],
+ "rollout_percentage": 100
+ },
+ {
+ "properties": [],
+ "rollout_percentage": 10
+ }
+ ]
+ }
+}
+```
+- Groups are evaluated in order; first matching group determines the rollout
+- Properties filter users by their traits
+- Rollout percentage determines what fraction of matching users see the flag
+
+### Pagination
+
+- Events: Use `offset` and `limit` (offset-based)
+- Feature flags: Use `offset` and `limit` (offset-based)
+- Projects: Use `offset` and `limit` (offset-based)
+- Continue until results array is empty or smaller than `limit`
+
+## Known Pitfalls
+
+**Project IDs**:
+- Required for most API endpoints
+- Always resolve project names to numeric IDs first
+- Multiple projects can exist in one organization
+
+**Event Naming**:
+- System events use `$` prefix ($pageview, $identify, $autocapture)
+- Custom events should NOT use `$` prefix
+- Event names are case-sensitive; maintain consistency
+
+**Feature Flags**:
+- Flag keys must be unique within a project
+- Use kebab-case for flag keys
+- Changes propagate within seconds
+- Deleting a flag is permanent; consider disabling instead
+
+**Rate Limits**:
+- Event ingestion has throughput limits
+- Batch events where possible for efficiency
+- API endpoints have per-minute rate limits
+
+**Response Parsing**:
+- Response data may be nested under `data` or `results` key
+- Paginated responses include `count`, `next`, `previous` fields
+- Event properties are nested objects; access carefully
+- Parse defensively with fallbacks for optional fields
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Capture event | POSTHOG_CAPTURE_EVENT | event, distinct_id, properties |
+| List events | POSTHOG_LIST_AND_FILTER_PROJECT_EVENTS | project_id, event, after, before |
+| List feature flags | POSTHOG_LIST_AND_MANAGE_PROJECT_FEATURE_FLAGS | project_id |
+| Get flag details | POSTHOG_RETRIEVE_FEATURE_FLAG_DETAILS | project_id, id |
+| Create flag | POSTHOG_CREATE_FEATURE_FLAGS_FOR_PROJECT | project_id, key, filters |
+| List projects | POSTHOG_LIST_PROJECTS_IN_ORGANIZATION_WITH_PAGINATION | organization_id |
+| Who am I | POSTHOG_WHOAMI | (none) |
+| User profile | POSTHOG_RETRIEVE_CURRENT_USER_PROFILE | (none) |
diff --git a/postmark-automation/SKILL.md b/postmark-automation/SKILL.md
new file mode 100644
index 0000000..6eff402
--- /dev/null
+++ b/postmark-automation/SKILL.md
@@ -0,0 +1,184 @@
+---
+name: postmark-automation
+description: Automate Postmark email delivery tasks via Rube MCP (Composio): send templated emails, manage templates, monitor delivery stats and bounces. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Postmark Automation via Rube MCP
+
+Automate Postmark transactional email operations through Composio's Postmark toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Postmark connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `postmark`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `postmark`
+3. If connection is not ACTIVE, follow the returned auth link to complete Postmark authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send Templated Batch Emails
+
+**When to use**: User wants to send templated emails to multiple recipients in one call
+
+**Tool sequence**:
+1. `POSTMARK_LIST_TEMPLATES` - Find available templates and their IDs [Prerequisite]
+2. `POSTMARK_VALIDATE_TEMPLATE` - Validate template with model data before sending [Optional]
+3. `POSTMARK_SEND_BATCH_WITH_TEMPLATES` - Send batch emails using a template [Required]
+
+**Key parameters**:
+- `TemplateId` or `TemplateAlias`: Identifier for the template to use
+- `Messages`: Array of message objects with `From`, `To`, `TemplateModel`
+- `TemplateModel`: Key-value pairs matching template variables
+
+**Pitfalls**:
+- Maximum 500 messages per batch call
+- Either `TemplateId` or `TemplateAlias` is required, not both
+- `TemplateModel` keys must match template variable names exactly (case-sensitive)
+- Sender address must be a verified Sender Signature or from a verified domain
+
+### 2. Manage Email Templates
+
+**When to use**: User wants to create, edit, or inspect email templates
+
+**Tool sequence**:
+1. `POSTMARK_LIST_TEMPLATES` - List all templates with IDs and names [Required]
+2. `POSTMARK_GET_TEMPLATE` - Get full template details including HTML/text body [Optional]
+3. `POSTMARK_EDIT_TEMPLATE` - Update template content or settings [Optional]
+4. `POSTMARK_VALIDATE_TEMPLATE` - Test template rendering with sample data [Optional]
+
+**Key parameters**:
+- `TemplateId`: Numeric template ID for GET/EDIT operations
+- `Name`: Template display name
+- `Subject`: Email subject line (supports template variables)
+- `HtmlBody`: HTML content of the template
+- `TextBody`: Plain text fallback content
+- `TemplateType`: 'Standard' or 'Layout'
+
+**Pitfalls**:
+- Template IDs are numeric integers, not strings
+- Editing a template replaces the entire content; include all fields you want to keep
+- Layout templates wrap Standard templates; changing a layout affects all linked templates
+- Validate before sending to catch missing variables early
+
+### 3. Monitor Delivery Statistics
+
+**When to use**: User wants to check email delivery health, open/click rates, or outbound overview
+
+**Tool sequence**:
+1. `POSTMARK_GET_DELIVERY_STATS` - Get bounce counts by type [Required]
+2. `POSTMARK_GET_OUTBOUND_OVERVIEW` - Get sent/opened/clicked/bounced summary [Required]
+3. `POSTMARK_GET_TRACKED_EMAIL_COUNTS` - Get tracked email volume over time [Optional]
+
+**Key parameters**:
+- `fromdate`: Start date for filtering stats (YYYY-MM-DD)
+- `todate`: End date for filtering stats (YYYY-MM-DD)
+- `tag`: Filter stats by message tag
+- `messagestreamid`: Filter by message stream (e.g., 'outbound', 'broadcast')
+
+**Pitfalls**:
+- Date parameters use YYYY-MM-DD format without time component
+- Stats are aggregated; individual message tracking requires separate API calls
+- `messagestreamid` defaults to all streams if not specified
+
+### 4. Manage Bounces and Complaints
+
+**When to use**: User wants to review bounced emails or spam complaints
+
+**Tool sequence**:
+1. `POSTMARK_GET_BOUNCES` - List bounced messages with details [Required]
+2. `POSTMARK_GET_SPAM_COMPLAINTS` - List spam complaint records [Optional]
+3. `POSTMARK_GET_DELIVERY_STATS` - Get bounce summary counts [Optional]
+
+**Key parameters**:
+- `count`: Number of records to return per page
+- `offset`: Pagination offset for results
+- `type`: Bounce type filter (e.g., 'HardBounce', 'SoftBounce', 'SpamNotification')
+- `fromdate`/`todate`: Date range filters
+- `emailFilter`: Filter by recipient email address
+
+**Pitfalls**:
+- Bounce types include: HardBounce, SoftBounce, SpamNotification, SpamComplaint, Transient, and others
+- Hard bounces indicate permanent delivery failures; these addresses should be removed
+- Spam complaints affect sender reputation; monitor regularly
+- Pagination uses `count` and `offset`, not page tokens
+
+### 5. Configure Server Settings
+
+**When to use**: User wants to view or modify Postmark server configuration
+
+**Tool sequence**:
+1. `POSTMARK_GET_SERVER` - Retrieve current server settings [Required]
+2. `POSTMARK_EDIT_SERVER` - Update server configuration [Optional]
+
+**Key parameters**:
+- `Name`: Server display name
+- `SmtpApiActivated`: Enable/disable SMTP API access
+- `BounceHookUrl`: Webhook URL for bounce notifications
+- `InboundHookUrl`: Webhook URL for inbound email processing
+- `TrackOpens`: Enable/disable open tracking
+- `TrackLinks`: Link tracking mode ('None', 'HtmlAndText', 'HtmlOnly', 'TextOnly')
+
+**Pitfalls**:
+- Server edits affect all messages sent through that server
+- Webhook URLs must be publicly accessible HTTPS endpoints
+- Changing `SmtpApiActivated` affects SMTP relay access immediately
+- Track settings apply to future messages only, not retroactively
+
+## Common Patterns
+
+### Template Variable Resolution
+
+```
+1. Call POSTMARK_GET_TEMPLATE with TemplateId
+2. Inspect HtmlBody/TextBody for {{variable}} placeholders
+3. Build TemplateModel dict with matching keys
+4. Call POSTMARK_VALIDATE_TEMPLATE to verify rendering
+```
+
+### Pagination
+
+- Set `count` for results per page (varies by endpoint)
+- Use `offset` to skip previously fetched results
+- Increment offset by count each page until results returned < count
+- Total records may be returned in response metadata
+
+## Known Pitfalls
+
+**Authentication**:
+- Postmark uses server-level API tokens, not account-level
+- Each server has its own token; ensure correct server context
+- Sender addresses must be verified Sender Signatures or from verified domains
+
+**Rate Limits**:
+- Batch send limited to 500 messages per call
+- API rate limits vary by endpoint; implement backoff on 429 responses
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Template IDs are always numeric integers
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Send batch templated emails | POSTMARK_SEND_BATCH_WITH_TEMPLATES | Messages, TemplateId/TemplateAlias |
+| List templates | POSTMARK_LIST_TEMPLATES | Count, Offset, TemplateType |
+| Get template details | POSTMARK_GET_TEMPLATE | TemplateId |
+| Edit template | POSTMARK_EDIT_TEMPLATE | TemplateId, Name, Subject, HtmlBody |
+| Validate template | POSTMARK_VALIDATE_TEMPLATE | TemplateId, TemplateModel |
+| Delivery stats | POSTMARK_GET_DELIVERY_STATS | (none or date filters) |
+| Outbound overview | POSTMARK_GET_OUTBOUND_OVERVIEW | fromdate, todate, tag |
+| Get bounces | POSTMARK_GET_BOUNCES | count, offset, type, emailFilter |
+| Get spam complaints | POSTMARK_GET_SPAM_COMPLAINTS | count, offset, fromdate, todate |
+| Tracked email counts | POSTMARK_GET_TRACKED_EMAIL_COUNTS | fromdate, todate, tag |
+| Get server config | POSTMARK_GET_SERVER | (none) |
+| Edit server config | POSTMARK_EDIT_SERVER | Name, TrackOpens, TrackLinks |
diff --git a/reddit-automation/SKILL.md b/reddit-automation/SKILL.md
new file mode 100644
index 0000000..a648517
--- /dev/null
+++ b/reddit-automation/SKILL.md
@@ -0,0 +1,209 @@
+---
+name: reddit-automation
+description: Automate Reddit tasks via Rube MCP (Composio): search subreddits, create posts, manage comments, and browse top content. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Reddit Automation via Rube MCP
+
+Automate Reddit operations through Composio's Reddit toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Reddit connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `reddit`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `reddit`
+3. If connection is not ACTIVE, follow the returned auth link to complete Reddit OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search Reddit
+
+**When to use**: User wants to find posts across subreddits
+
+**Tool sequence**:
+1. `REDDIT_SEARCH_ACROSS_SUBREDDITS` - Search for posts matching a query [Required]
+
+**Key parameters**:
+- `query`: Search terms
+- `subreddit`: Limit search to a specific subreddit (optional)
+- `sort`: Sort results by 'relevance', 'hot', 'top', 'new', 'comments'
+- `time_filter`: Time range ('hour', 'day', 'week', 'month', 'year', 'all')
+- `limit`: Number of results to return
+
+**Pitfalls**:
+- Search results may not include very recent posts due to indexing delay
+- The `time_filter` parameter only works with certain sort options
+- Results are paginated; use after/before tokens for additional pages
+- NSFW content may be filtered based on account settings
+
+### 2. Create Posts
+
+**When to use**: User wants to submit a new post to a subreddit
+
+**Tool sequence**:
+1. `REDDIT_LIST_SUBREDDIT_POST_FLAIRS` - Get available post flairs [Optional]
+2. `REDDIT_CREATE_REDDIT_POST` - Submit the post [Required]
+
+**Key parameters**:
+- `subreddit`: Target subreddit name (without 'r/' prefix)
+- `title`: Post title
+- `text`: Post body text (for text posts)
+- `url`: Link URL (for link posts)
+- `flair_id`: Flair ID from the subreddit's flair list
+
+**Pitfalls**:
+- Some subreddits require flair; use LIST_SUBREDDIT_POST_FLAIRS first
+- Subreddit posting rules vary widely; karma/age restrictions may apply
+- Text and URL are mutually exclusive; a post is either text or link
+- Rate limits apply; avoid rapid successive post creation
+- The subreddit name should not include 'r/' prefix
+
+### 3. Manage Comments
+
+**When to use**: User wants to comment on posts or manage existing comments
+
+**Tool sequence**:
+1. `REDDIT_RETRIEVE_POST_COMMENTS` - Get comments on a post [Optional]
+2. `REDDIT_POST_REDDIT_COMMENT` - Add a comment to a post or reply to a comment [Required]
+3. `REDDIT_EDIT_REDDIT_COMMENT_OR_POST` - Edit an existing comment [Optional]
+4. `REDDIT_DELETE_REDDIT_COMMENT` - Delete a comment [Optional]
+
+**Key parameters**:
+- `post_id`: ID of the post (for retrieving or commenting on)
+- `parent_id`: Full name of the parent (e.g., 't3_abc123' for post, 't1_xyz789' for comment)
+- `body`: Comment text content
+- `thing_id`: Full name of the item to edit or delete
+
+**Pitfalls**:
+- Reddit uses 'fullname' format: 't1_' prefix for comments, 't3_' for posts
+- Editing replaces the entire comment body; include all desired content
+- Deleted comments show as '[deleted]' but the tree structure remains
+- Comment depth limits may apply in some subreddits
+
+### 4. Browse Subreddit Content
+
+**When to use**: User wants to view top or trending content from a subreddit
+
+**Tool sequence**:
+1. `REDDIT_GET_R_TOP` - Get top posts from a subreddit [Required]
+2. `REDDIT_GET` - Get posts from a subreddit endpoint [Alternative]
+3. `REDDIT_RETRIEVE_REDDIT_POST` - Get full details for a specific post [Optional]
+
+**Key parameters**:
+- `subreddit`: Subreddit name
+- `time_filter`: Time range for top posts ('hour', 'day', 'week', 'month', 'year', 'all')
+- `limit`: Number of posts to retrieve
+- `post_id`: Specific post ID for full details
+
+**Pitfalls**:
+- Top posts with time_filter='all' returns all-time top content
+- Post details include the body text but comments require a separate call
+- Some posts may be removed or hidden based on subreddit rules
+- NSFW posts are included unless filtered at the account level
+
+### 5. Manage Posts
+
+**When to use**: User wants to edit or delete their own posts
+
+**Tool sequence**:
+1. `REDDIT_EDIT_REDDIT_COMMENT_OR_POST` - Edit a post's text content [Optional]
+2. `REDDIT_DELETE_REDDIT_POST` - Delete a post [Optional]
+3. `REDDIT_GET_USER_FLAIR` - Get user's flair in a subreddit [Optional]
+
+**Key parameters**:
+- `thing_id`: Full name of the post (e.g., 't3_abc123')
+- `body`: New text content (for editing)
+- `subreddit`: Subreddit name (for flair)
+
+**Pitfalls**:
+- Only text posts can have their body edited; link posts cannot be modified
+- Post titles cannot be edited after submission
+- Deletion is permanent; deleted posts show as '[deleted]'
+- User flair is per-subreddit and may be restricted
+
+## Common Patterns
+
+### Reddit Fullname Format
+
+**Prefixes**:
+```
+t1_ = Comment (e.g., 't1_abc123')
+t2_ = Account (e.g., 't2_xyz789')
+t3_ = Post/Link (e.g., 't3_def456')
+t4_ = Message
+t5_ = Subreddit
+```
+
+**Usage**:
+```
+1. Retrieve a post to get its fullname (t3_XXXXX)
+2. Use fullname as parent_id when commenting
+3. Use fullname as thing_id when editing/deleting
+```
+
+### Pagination
+
+- Reddit uses cursor-based pagination with 'after' and 'before' tokens
+- Set `limit` for items per page (max 100)
+- Check response for `after` token
+- Pass `after` value in subsequent requests to get next page
+
+### Flair Resolution
+
+```
+1. Call REDDIT_LIST_SUBREDDIT_POST_FLAIRS with subreddit name
+2. Find matching flair by text or category
+3. Extract flair_id
+4. Include flair_id when creating the post
+```
+
+## Known Pitfalls
+
+**Rate Limits**:
+- Reddit enforces rate limits per account and per OAuth app
+- Posting is limited to approximately 1 post per 10 minutes for new accounts
+- Commenting has similar but less restrictive limits
+- 429 errors should trigger exponential backoff
+
+**Content Rules**:
+- Each subreddit has its own posting rules and requirements
+- Some subreddits are restricted or private
+- Karma requirements may prevent posting in certain subreddits
+- Auto-moderator rules may remove posts that match certain patterns
+
+**ID Formats**:
+- Always use fullname format (with prefix) for parent_id and thing_id
+- Raw IDs without prefix will cause 'Invalid ID' errors
+- Post IDs from search results may need 't3_' prefix added
+
+**Text Formatting**:
+- Reddit uses Markdown for post and comment formatting
+- Code blocks, tables, and headers are supported
+- Links use `[text](url)` format
+- Mention users with `u/username`, subreddits with `r/subreddit`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Search Reddit | REDDIT_SEARCH_ACROSS_SUBREDDITS | query, subreddit, sort, time_filter |
+| Create post | REDDIT_CREATE_REDDIT_POST | subreddit, title, text/url |
+| Get post comments | REDDIT_RETRIEVE_POST_COMMENTS | post_id |
+| Add comment | REDDIT_POST_REDDIT_COMMENT | parent_id, body |
+| Edit comment/post | REDDIT_EDIT_REDDIT_COMMENT_OR_POST | thing_id, body |
+| Delete comment | REDDIT_DELETE_REDDIT_COMMENT | thing_id |
+| Delete post | REDDIT_DELETE_REDDIT_POST | thing_id |
+| Get top posts | REDDIT_GET_R_TOP | subreddit, time_filter, limit |
+| Browse subreddit | REDDIT_GET | subreddit |
+| Get post details | REDDIT_RETRIEVE_REDDIT_POST | post_id |
+| Get specific comment | REDDIT_RETRIEVE_SPECIFIC_COMMENT | comment_id |
+| List post flairs | REDDIT_LIST_SUBREDDIT_POST_FLAIRS | subreddit |
+| Get user flair | REDDIT_GET_USER_FLAIR | subreddit |
diff --git a/render-automation/SKILL.md b/render-automation/SKILL.md
new file mode 100644
index 0000000..aefe8d2
--- /dev/null
+++ b/render-automation/SKILL.md
@@ -0,0 +1,178 @@
+---
+name: render-automation
+description: Automate Render tasks via Rube MCP (Composio): services, deployments, projects. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Render Automation via Rube MCP
+
+Automate Render cloud platform operations through Composio's Render toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Render connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `render`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `render`
+3. If connection is not ACTIVE, follow the returned auth link to complete Render authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Browse Services
+
+**When to use**: User wants to find or inspect Render services (web services, static sites, workers, cron jobs)
+
+**Tool sequence**:
+1. `RENDER_LIST_SERVICES` - List all services with optional filters [Required]
+
+**Key parameters**:
+- `name`: Filter services by name substring
+- `type`: Filter by service type ('web_service', 'static_site', 'private_service', 'background_worker', 'cron_job')
+- `limit`: Maximum results per page (default 20, max 100)
+- `cursor`: Pagination cursor from previous response
+
+**Pitfalls**:
+- Service types must match exact enum values: 'web_service', 'static_site', 'private_service', 'background_worker', 'cron_job'
+- Pagination uses cursor-based approach; follow `cursor` until absent
+- Name filter is substring-based, not exact match
+- Service IDs follow the format 'srv-xxxxxxxxxxxx'
+- Default limit is 20; set higher for comprehensive listing
+
+### 2. Trigger Deployments
+
+**When to use**: User wants to manually deploy or redeploy a service
+
+**Tool sequence**:
+1. `RENDER_LIST_SERVICES` - Find the service to deploy [Prerequisite]
+2. `RENDER_TRIGGER_DEPLOY` - Trigger a new deployment [Required]
+3. `RENDER_RETRIEVE_DEPLOY` - Monitor deployment progress [Optional]
+
+**Key parameters**:
+- For TRIGGER_DEPLOY:
+ - `serviceId`: Service ID to deploy (required, format: 'srv-xxxxxxxxxxxx')
+ - `clearCache`: Set `true` to clear build cache before deploying
+- For RETRIEVE_DEPLOY:
+ - `serviceId`: Service ID
+ - `deployId`: Deploy ID from trigger response (format: 'dep-xxxxxxxxxxxx')
+
+**Pitfalls**:
+- `serviceId` is required; resolve via LIST_SERVICES first
+- Service IDs start with 'srv-' prefix
+- Deploy IDs start with 'dep-' prefix
+- `clearCache: true` forces a clean build; takes longer but resolves cache-related issues
+- Deployment is asynchronous; use RETRIEVE_DEPLOY to poll status
+- Triggering a deploy while another is in progress may queue the new one
+
+### 3. Monitor Deployment Status
+
+**When to use**: User wants to check the progress or result of a deployment
+
+**Tool sequence**:
+1. `RENDER_RETRIEVE_DEPLOY` - Get deployment details and status [Required]
+
+**Key parameters**:
+- `serviceId`: Service ID (required)
+- `deployId`: Deployment ID (required)
+- Response includes `status`, `createdAt`, `updatedAt`, `finishedAt`, `commit`
+
+**Pitfalls**:
+- Both `serviceId` and `deployId` are required
+- Deploy statuses include: 'created', 'build_in_progress', 'update_in_progress', 'live', 'deactivated', 'build_failed', 'update_failed', 'canceled'
+- 'live' indicates successful deployment
+- 'build_failed' or 'update_failed' indicate deployment errors
+- Poll at reasonable intervals (10-30 seconds) to avoid rate limits
+
+### 4. Manage Projects
+
+**When to use**: User wants to list and organize Render projects
+
+**Tool sequence**:
+1. `RENDER_LIST_PROJECTS` - List all projects [Required]
+
+**Key parameters**:
+- `limit`: Maximum results per page (max 100)
+- `cursor`: Pagination cursor from previous response
+
+**Pitfalls**:
+- Projects group related services together
+- Pagination uses cursor-based approach
+- Project IDs are used for organizational purposes
+- Not all services may be assigned to a project
+
+## Common Patterns
+
+### ID Resolution
+
+**Service name -> Service ID**:
+```
+1. Call RENDER_LIST_SERVICES with name=service_name
+2. Find service by name in results
+3. Extract id (format: 'srv-xxxxxxxxxxxx')
+```
+
+**Deployment lookup**:
+```
+1. Store deployId from RENDER_TRIGGER_DEPLOY response
+2. Call RENDER_RETRIEVE_DEPLOY with serviceId and deployId
+3. Check status for completion
+```
+
+### Deploy and Monitor Pattern
+
+```
+1. RENDER_LIST_SERVICES -> find service by name -> get serviceId
+2. RENDER_TRIGGER_DEPLOY with serviceId -> get deployId
+3. Loop: RENDER_RETRIEVE_DEPLOY with serviceId + deployId
+4. Check status: 'live' = success, 'build_failed'/'update_failed' = error
+5. Continue polling until terminal state reached
+```
+
+### Pagination
+
+- Use `cursor` from response for next page
+- Continue until `cursor` is absent or results are empty
+- Both LIST_SERVICES and LIST_PROJECTS use cursor-based pagination
+- Set `limit` to max (100) for fewer pagination rounds
+
+## Known Pitfalls
+
+**Service IDs**:
+- Always prefixed with 'srv-' (e.g., 'srv-abcd1234efgh')
+- Deploy IDs prefixed with 'dep-' (e.g., 'dep-d2mqkf9r0fns73bham1g')
+- Always resolve service names to IDs via LIST_SERVICES
+
+**Service Types**:
+- Must use exact enum values when filtering
+- Available types: web_service, static_site, private_service, background_worker, cron_job
+- Different service types have different deployment behaviors
+
+**Deployment Behavior**:
+- Deployments are asynchronous; always poll for completion
+- Clear cache deploys take longer but resolve stale cache issues
+- Failed deploys do not roll back automatically; the previous version stays live
+- Concurrent deploy triggers may be queued
+
+**Rate Limits**:
+- Render API has rate limits
+- Avoid rapid polling; use 10-30 second intervals
+- Bulk operations should be throttled
+
+**Response Parsing**:
+- Response data may be nested under `data` key
+- Timestamps use ISO 8601 format
+- Parse defensively with fallbacks for optional fields
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List services | RENDER_LIST_SERVICES | name, type, limit, cursor |
+| Trigger deploy | RENDER_TRIGGER_DEPLOY | serviceId, clearCache |
+| Get deploy status | RENDER_RETRIEVE_DEPLOY | serviceId, deployId |
+| List projects | RENDER_LIST_PROJECTS | limit, cursor |
diff --git a/salesforce-automation/SKILL.md b/salesforce-automation/SKILL.md
new file mode 100644
index 0000000..ee018b2
--- /dev/null
+++ b/salesforce-automation/SKILL.md
@@ -0,0 +1,187 @@
+---
+name: salesforce-automation
+description: Automate Salesforce tasks via Rube MCP (Composio): leads, contacts, accounts, opportunities, SOQL queries. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Salesforce Automation via Rube MCP
+
+Automate Salesforce CRM operations through Composio's Salesforce toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Salesforce connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `salesforce`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `salesforce`
+3. If connection is not ACTIVE, follow the returned auth link to complete Salesforce OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Leads
+
+**When to use**: User wants to create, search, update, or list leads
+
+**Tool sequence**:
+1. `SALESFORCE_SEARCH_LEADS` - Search leads by criteria [Optional]
+2. `SALESFORCE_LIST_LEADS` - List all leads [Optional]
+3. `SALESFORCE_CREATE_LEAD` - Create a new lead [Optional]
+4. `SALESFORCE_UPDATE_LEAD` - Update lead fields [Optional]
+5. `SALESFORCE_ADD_LEAD_TO_CAMPAIGN` - Add lead to campaign [Optional]
+6. `SALESFORCE_APPLY_LEAD_ASSIGNMENT_RULES` - Apply assignment rules [Optional]
+
+**Key parameters**:
+- `LastName`: Required for lead creation
+- `Company`: Required for lead creation
+- `Email`, `Phone`, `Title`: Common lead fields
+- `lead_id`: Lead ID for updates
+- `campaign_id`: Campaign ID for campaign operations
+
+**Pitfalls**:
+- LastName and Company are required fields for lead creation
+- Lead IDs are 15 or 18 character Salesforce IDs
+
+### 2. Manage Contacts and Accounts
+
+**When to use**: User wants to manage contacts and their associated accounts
+
+**Tool sequence**:
+1. `SALESFORCE_SEARCH_CONTACTS` - Search contacts [Optional]
+2. `SALESFORCE_LIST_CONTACTS` - List contacts [Optional]
+3. `SALESFORCE_CREATE_CONTACT` - Create a new contact [Optional]
+4. `SALESFORCE_SEARCH_ACCOUNTS` - Search accounts [Optional]
+5. `SALESFORCE_CREATE_ACCOUNT` - Create a new account [Optional]
+6. `SALESFORCE_ASSOCIATE_CONTACT_TO_ACCOUNT` - Link contact to account [Optional]
+
+**Key parameters**:
+- `LastName`: Required for contact creation
+- `Name`: Account name for creation
+- `AccountId`: Account ID to associate with contact
+- `contact_id`, `account_id`: IDs for association
+
+**Pitfalls**:
+- Contact requires at least LastName
+- Account association requires both valid contact and account IDs
+
+### 3. Manage Opportunities
+
+**When to use**: User wants to track and manage sales opportunities
+
+**Tool sequence**:
+1. `SALESFORCE_SEARCH_OPPORTUNITIES` - Search opportunities [Optional]
+2. `SALESFORCE_LIST_OPPORTUNITIES` - List all opportunities [Optional]
+3. `SALESFORCE_GET_OPPORTUNITY` - Get opportunity details [Optional]
+4. `SALESFORCE_CREATE_OPPORTUNITY` - Create new opportunity [Optional]
+5. `SALESFORCE_RETRIEVE_OPPORTUNITIES_DATA` - Retrieve opportunity data [Optional]
+
+**Key parameters**:
+- `Name`: Opportunity name (required)
+- `StageName`: Sales stage (required)
+- `CloseDate`: Expected close date (required)
+- `Amount`: Deal value
+- `AccountId`: Associated account
+
+**Pitfalls**:
+- Name, StageName, and CloseDate are required for creation
+- Stage names must match exactly what is configured in Salesforce
+
+### 4. Run SOQL Queries
+
+**When to use**: User wants to query Salesforce data with custom SOQL
+
+**Tool sequence**:
+1. `SALESFORCE_RUN_SOQL_QUERY` / `SALESFORCE_QUERY` - Execute SOQL [Required]
+
+**Key parameters**:
+- `query`: SOQL query string
+
+**Pitfalls**:
+- SOQL syntax differs from SQL; uses Salesforce object and field API names
+- Field API names may differ from display labels (e.g., `Account.Name` not `Account Name`)
+- Results are paginated for large datasets
+
+### 5. Manage Tasks
+
+**When to use**: User wants to create, search, update, or complete tasks
+
+**Tool sequence**:
+1. `SALESFORCE_SEARCH_TASKS` - Search tasks [Optional]
+2. `SALESFORCE_UPDATE_TASK` - Update task fields [Optional]
+3. `SALESFORCE_COMPLETE_TASK` - Mark task as complete [Optional]
+
+**Key parameters**:
+- `task_id`: Task ID for updates
+- `Status`: Task status value
+- `Subject`: Task subject
+
+**Pitfalls**:
+- Task status values must match picklist options in Salesforce
+
+## Common Patterns
+
+### SOQL Syntax
+
+**Basic query**:
+```
+SELECT Id, Name, Email FROM Contact WHERE LastName = 'Smith'
+```
+
+**With relationships**:
+```
+SELECT Id, Name, Account.Name FROM Contact WHERE Account.Industry = 'Technology'
+```
+
+**Date filtering**:
+```
+SELECT Id, Name FROM Lead WHERE CreatedDate = TODAY
+SELECT Id, Name FROM Opportunity WHERE CloseDate = NEXT_MONTH
+```
+
+### Pagination
+
+- SOQL queries with large results return pagination tokens
+- Use `SALESFORCE_QUERY` with nextRecordsUrl for pagination
+- Check `done` field in response; if false, continue paging
+
+## Known Pitfalls
+
+**Field API Names**:
+- Always use API names, not display labels
+- Custom fields end with `__c` suffix
+- Use SALESFORCE_GET_ALL_CUSTOM_OBJECTS to discover custom objects
+
+**ID Formats**:
+- Salesforce IDs are 15 (case-sensitive) or 18 (case-insensitive) characters
+- Both formats are accepted in most operations
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create lead | SALESFORCE_CREATE_LEAD | LastName, Company |
+| Search leads | SALESFORCE_SEARCH_LEADS | query |
+| List leads | SALESFORCE_LIST_LEADS | (filters) |
+| Update lead | SALESFORCE_UPDATE_LEAD | lead_id, fields |
+| Create contact | SALESFORCE_CREATE_CONTACT | LastName |
+| Search contacts | SALESFORCE_SEARCH_CONTACTS | query |
+| Create account | SALESFORCE_CREATE_ACCOUNT | Name |
+| Search accounts | SALESFORCE_SEARCH_ACCOUNTS | query |
+| Link contact | SALESFORCE_ASSOCIATE_CONTACT_TO_ACCOUNT | contact_id, account_id |
+| Create opportunity | SALESFORCE_CREATE_OPPORTUNITY | Name, StageName, CloseDate |
+| Get opportunity | SALESFORCE_GET_OPPORTUNITY | opportunity_id |
+| Search opportunities | SALESFORCE_SEARCH_OPPORTUNITIES | query |
+| Run SOQL | SALESFORCE_RUN_SOQL_QUERY | query |
+| Query | SALESFORCE_QUERY | query |
+| Search tasks | SALESFORCE_SEARCH_TASKS | query |
+| Update task | SALESFORCE_UPDATE_TASK | task_id, fields |
+| Complete task | SALESFORCE_COMPLETE_TASK | task_id |
+| Get user info | SALESFORCE_GET_USER_INFO | (none) |
+| Custom objects | SALESFORCE_GET_ALL_CUSTOM_OBJECTS | (none) |
+| Create record | SALESFORCE_CREATE_A_RECORD | object_type, fields |
+| Transfer ownership | SALESFORCE_MASS_TRANSFER_OWNERSHIP | records, new_owner |
diff --git a/segment-automation/SKILL.md b/segment-automation/SKILL.md
new file mode 100644
index 0000000..b1c2cd2
--- /dev/null
+++ b/segment-automation/SKILL.md
@@ -0,0 +1,222 @@
+---
+name: segment-automation
+description: Automate Segment tasks via Rube MCP (Composio): track events, identify users, manage groups, page views, aliases, batch operations. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Segment Automation via Rube MCP
+
+Automate Segment customer data platform operations through Composio's Segment toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Segment connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `segment`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `segment`
+3. If connection is not ACTIVE, follow the returned auth link to complete Segment authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Track Events
+
+**When to use**: User wants to send event data to Segment for downstream destinations
+
+**Tool sequence**:
+1. `SEGMENT_TRACK` - Send a single track event [Required]
+
+**Key parameters**:
+- `userId`: User identifier (required if no `anonymousId`)
+- `anonymousId`: Anonymous identifier (required if no `userId`)
+- `event`: Event name (e.g., 'Order Completed', 'Button Clicked')
+- `properties`: Object with event-specific properties
+- `timestamp`: ISO 8601 timestamp (optional; defaults to server time)
+- `context`: Object with contextual metadata (IP, user agent, etc.)
+
+**Pitfalls**:
+- At least one of `userId` or `anonymousId` is required
+- `event` name is required and should follow consistent naming conventions
+- Properties are freeform objects; ensure consistent schema across events
+- Timestamp must be ISO 8601 format (e.g., '2024-01-15T10:30:00Z')
+- Events are processed asynchronously; successful API response means accepted, not delivered
+
+### 2. Identify Users
+
+**When to use**: User wants to associate traits with a user profile in Segment
+
+**Tool sequence**:
+1. `SEGMENT_IDENTIFY` - Set user traits and identity [Required]
+
+**Key parameters**:
+- `userId`: User identifier (required if no `anonymousId`)
+- `anonymousId`: Anonymous identifier
+- `traits`: Object with user properties (email, name, plan, etc.)
+- `timestamp`: ISO 8601 timestamp
+- `context`: Contextual metadata
+
+**Pitfalls**:
+- At least one of `userId` or `anonymousId` is required
+- Traits are merged with existing traits, not replaced
+- To remove a trait, set it to `null`
+- Identify calls should be made before track calls for new users
+- Avoid sending PII in traits unless destinations are configured for it
+
+### 3. Batch Operations
+
+**When to use**: User wants to send multiple events, identifies, or other calls in a single request
+
+**Tool sequence**:
+1. `SEGMENT_BATCH` - Send multiple Segment calls in one request [Required]
+
+**Key parameters**:
+- `batch`: Array of message objects, each with:
+ - `type`: Message type ('track', 'identify', 'group', 'page', 'alias')
+ - `userId` / `anonymousId`: User identifier
+ - Additional fields based on type (event, properties, traits, etc.)
+
+**Pitfalls**:
+- Each message in the batch must have a valid `type` field
+- Maximum batch size limit applies; check schema for current limit
+- All messages in a batch are processed independently; one failure does not affect others
+- Each message must independently satisfy its type's requirements (e.g., track needs event name)
+- Batch is the most efficient way to send multiple calls; prefer over individual calls
+
+### 4. Group Users
+
+**When to use**: User wants to associate a user with a company, team, or organization
+
+**Tool sequence**:
+1. `SEGMENT_GROUP` - Associate user with a group [Required]
+
+**Key parameters**:
+- `userId`: User identifier (required if no `anonymousId`)
+- `anonymousId`: Anonymous identifier
+- `groupId`: Group/organization identifier (required)
+- `traits`: Object with group properties (name, industry, size, plan)
+- `timestamp`: ISO 8601 timestamp
+
+**Pitfalls**:
+- `groupId` is required; it identifies the company or organization
+- Group traits are merged with existing traits for that group
+- A user can belong to multiple groups
+- Group traits update the group profile, not the user profile
+
+### 5. Track Page Views
+
+**When to use**: User wants to record page view events in Segment
+
+**Tool sequence**:
+1. `SEGMENT_PAGE` - Send a page view event [Required]
+
+**Key parameters**:
+- `userId`: User identifier (required if no `anonymousId`)
+- `anonymousId`: Anonymous identifier
+- `name`: Page name (e.g., 'Home', 'Pricing', 'Dashboard')
+- `category`: Page category (e.g., 'Docs', 'Marketing')
+- `properties`: Object with page-specific properties (url, title, referrer)
+
+**Pitfalls**:
+- At least one of `userId` or `anonymousId` is required
+- `name` and `category` are optional but recommended for proper analytics
+- Standard properties include `url`, `title`, `referrer`, `path`, `search`
+- Page calls are often automated; manual use is for server-side page tracking
+
+### 6. Alias Users and Manage Sources
+
+**When to use**: User wants to merge anonymous and identified users, or manage source configuration
+
+**Tool sequence**:
+1. `SEGMENT_ALIAS` - Link two user identities together [Optional]
+2. `SEGMENT_LIST_SCHEMA_SETTINGS_IN_SOURCE` - View source schema settings [Optional]
+3. `SEGMENT_UPDATE_SOURCE` - Update source configuration [Optional]
+
+**Key parameters**:
+- For ALIAS:
+ - `userId`: New user identifier (the identified ID)
+ - `previousId`: Old user identifier (the anonymous ID)
+- For source operations:
+ - `sourceId`: Source identifier
+
+**Pitfalls**:
+- ALIAS is a one-way operation; cannot be undone
+- `previousId` is the anonymous/old ID, `userId` is the new/identified ID
+- Not all destinations support alias calls; check destination documentation
+- ALIAS should be called once when a user first identifies (e.g., signs up)
+- Source updates may affect data collection; review changes carefully
+
+## Common Patterns
+
+### User Lifecycle
+
+Standard Segment user lifecycle:
+```
+1. Anonymous user visits -> PAGE call with anonymousId
+2. User interacts -> TRACK call with anonymousId
+3. User signs up -> ALIAS (anonymousId -> userId), then IDENTIFY with traits
+4. User takes action -> TRACK call with userId
+5. User joins org -> GROUP call linking userId to groupId
+```
+
+### Batch Optimization
+
+For bulk data ingestion:
+```
+1. Collect events in memory (array of message objects)
+2. Each message includes type, userId/anonymousId, and type-specific fields
+3. Call SEGMENT_BATCH with the collected messages
+4. Check response for any individual message errors
+```
+
+### Naming Conventions
+
+Segment recommends consistent event naming:
+- **Events**: Use "Object Action" format (e.g., 'Order Completed', 'Article Viewed')
+- **Properties**: Use snake_case (e.g., 'order_total', 'product_name')
+- **Traits**: Use snake_case (e.g., 'first_name', 'plan_type')
+
+## Known Pitfalls
+
+**Identity Resolution**:
+- Always include `userId` or `anonymousId` on every call
+- Use ALIAS only once per user identity merge
+- Identify before tracking to ensure proper user association
+
+**Data Quality**:
+- Event names should be consistent across all sources
+- Properties should follow a defined schema for downstream compatibility
+- Avoid sending sensitive PII unless destinations are configured for it
+
+**Rate Limits**:
+- Use BATCH for bulk operations to stay within rate limits
+- Individual calls are rate-limited per source
+- Batch calls are more efficient and less likely to be throttled
+
+**Response Parsing**:
+- Successful responses indicate acceptance, not delivery to destinations
+- Response data may be nested under `data` key
+- Check for error fields in batch responses for individual message failures
+
+**Timestamps**:
+- Must be ISO 8601 format with timezone (e.g., '2024-01-15T10:30:00Z')
+- Omitting timestamp uses server receive time
+- Historical data imports should include explicit timestamps
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Track event | SEGMENT_TRACK | userId, event, properties |
+| Identify user | SEGMENT_IDENTIFY | userId, traits |
+| Batch calls | SEGMENT_BATCH | batch (array of messages) |
+| Group user | SEGMENT_GROUP | userId, groupId, traits |
+| Page view | SEGMENT_PAGE | userId, name, properties |
+| Alias identity | SEGMENT_ALIAS | userId, previousId |
+| Source schema | SEGMENT_LIST_SCHEMA_SETTINGS_IN_SOURCE | sourceId |
+| Update source | SEGMENT_UPDATE_SOURCE | sourceId |
+| Warehouses | SEGMENT_LIST_CONNECTED_WAREHOUSES_FROM_SOURCE | sourceId |
diff --git a/sendgrid-automation/SKILL.md b/sendgrid-automation/SKILL.md
new file mode 100644
index 0000000..549abe6
--- /dev/null
+++ b/sendgrid-automation/SKILL.md
@@ -0,0 +1,225 @@
+---
+name: sendgrid-automation
+description: Automate SendGrid email operations including sending emails, managing contacts/lists, sender identities, templates, and analytics via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# SendGrid Automation via Rube MCP
+
+Automate SendGrid email delivery workflows including marketing campaigns (Single Sends), contact and list management, sender identity setup, and email analytics through Composio's SendGrid toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active SendGrid connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `sendgrid`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `sendgrid`
+3. If connection is not ACTIVE, follow the returned auth link to complete SendGrid API key authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Send Marketing Campaigns (Single Sends)
+
+**When to use**: User wants to create and send a marketing email campaign to a contact list or segment.
+
+**Tool sequence**:
+1. `SENDGRID_RETRIEVE_ALL_LISTS` - List available marketing lists to target [Prerequisite]
+2. `SENDGRID_CREATE_A_LIST` - Create a new list if needed [Optional]
+3. `SENDGRID_ADD_OR_UPDATE_A_CONTACT` - Add contacts to the list [Optional]
+4. `SENDGRID_GET_ALL_SENDER_IDENTITIES` - Get verified sender ID [Prerequisite]
+5. `SENDGRID_CREATE_SINGLE_SEND` - Create the campaign with content, sender, and recipients [Required]
+
+**Key parameters for SENDGRID_CREATE_SINGLE_SEND**:
+- `name`: Campaign name (required)
+- `email__config__subject`: Email subject line
+- `email__config__html__content`: HTML body content
+- `email__config__plain__content`: Plain text version
+- `email__config__sender__id`: Verified sender identity ID
+- `email__config__design__id`: Use instead of html_content for pre-built designs
+- `send__to__list__ids`: Array of list UUIDs to send to
+- `send__to__segment__ids`: Array of segment UUIDs
+- `send__to__all`: true to send to all contacts
+- `email__config__suppression__group__id` or `email__config__custom__unsubscribe__url`: One required for compliance
+
+**Pitfalls**:
+- Setting `send_at` on CREATE does NOT schedule the send; it only prepopulates the UI date; use the Schedule endpoint separately
+- `send_at: "now"` is only valid with the Schedule endpoint, not CREATE
+- Must provide either `suppression_group_id` or `custom_unsubscribe_url` for unsubscribe compliance
+- Sender must be verified before use; check with `SENDGRID_GET_ALL_SENDER_IDENTITIES`
+- Nested params use double-underscore notation (e.g., `email__config__subject`)
+
+### 2. Manage Contacts and Lists
+
+**When to use**: User wants to create contact lists, add/update contacts, search for contacts, or remove contacts from lists.
+
+**Tool sequence**:
+1. `SENDGRID_RETRIEVE_ALL_LISTS` - List all marketing lists [Required]
+2. `SENDGRID_CREATE_A_LIST` - Create a new contact list [Optional]
+3. `SENDGRID_GET_A_LIST_BY_ID` - Get list details and sample contacts [Optional]
+4. `SENDGRID_ADD_OR_UPDATE_A_CONTACT` - Upsert contacts with list association [Required]
+5. `SENDGRID_GET_CONTACTS_BY_EMAILS` - Look up contacts by email [Optional]
+6. `SENDGRID_GET_CONTACTS_BY_IDENTIFIERS` - Look up contacts by email, phone, or external ID [Optional]
+7. `SENDGRID_GET_LIST_CONTACT_COUNT` - Verify contact count after operations [Optional]
+8. `SENDGRID_REMOVE_CONTACTS_FROM_A_LIST` - Remove contacts from a list without deleting [Optional]
+9. `SENDGRID_REMOVE_LIST_AND_OPTIONAL_CONTACTS` - Delete an entire list [Optional]
+10. `SENDGRID_IMPORT_CONTACTS` - Bulk import from CSV [Optional]
+
+**Key parameters for SENDGRID_ADD_OR_UPDATE_A_CONTACT**:
+- `contacts`: Array of contact objects (max 30,000 or 6MB), each with at least one identifier: `email`, `phone_number_id`, `external_id`, or `anonymous_id` (required)
+- `list_ids`: Array of list UUID strings to associate contacts with
+
+**Pitfalls**:
+- `SENDGRID_ADD_OR_UPDATE_A_CONTACT` is asynchronous; returns 202 with `job_id`; contacts may take 10-30 seconds to appear
+- List IDs are UUIDs (e.g., "ca7a3796-e8a8-4029-9ccb-df8937940562"), not integers
+- List names must be unique; duplicate names cause 400 errors
+- `SENDGRID_ADD_A_SINGLE_RECIPIENT_TO_A_LIST` uses the legacy API; prefer `SENDGRID_ADD_OR_UPDATE_A_CONTACT` with `list_ids`
+- `SENDGRID_REMOVE_LIST_AND_OPTIONAL_CONTACTS` is irreversible; require explicit user confirmation
+- Email addresses are automatically lowercased by SendGrid
+
+### 3. Manage Sender Identities
+
+**When to use**: User wants to set up or view sender identities (From addresses) for sending emails.
+
+**Tool sequence**:
+1. `SENDGRID_GET_ALL_SENDER_IDENTITIES` - List all existing sender identities [Required]
+2. `SENDGRID_CREATE_A_SENDER_IDENTITY` - Create a new sender identity [Optional]
+3. `SENDGRID_VIEW_A_SENDER_IDENTITY` - View details for a specific sender [Optional]
+4. `SENDGRID_UPDATE_A_SENDER_IDENTITY` - Update sender details [Optional]
+5. `SENDGRID_CREATE_VERIFIED_SENDER_REQUEST` - Create and verify a new sender [Optional]
+6. `SENDGRID_AUTHENTICATE_A_DOMAIN` - Set up domain authentication for auto-verification [Optional]
+
+**Key parameters for SENDGRID_CREATE_A_SENDER_IDENTITY**:
+- `from__email`: From email address (required)
+- `from__name`: Display name (required)
+- `reply__to__email`: Reply-to address (required)
+- `nickname`: Internal identifier (required)
+- `address`, `city`, `country`: Physical address for CAN-SPAM compliance (required)
+
+**Pitfalls**:
+- New senders must be verified before use; if domain is not authenticated, a verification email is sent
+- Up to 100 unique sender identities per account
+- Avoid using domains with strict DMARC policies (gmail.com, yahoo.com) as from addresses
+- `SENDGRID_CREATE_VERIFIED_SENDER_REQUEST` sends a verification email; sender is unusable until verified
+
+### 4. View Email Statistics and Activity
+
+**When to use**: User wants to review email delivery stats, bounce rates, open/click metrics, or message activity.
+
+**Tool sequence**:
+1. `SENDGRID_RETRIEVE_GLOBAL_EMAIL_STATISTICS` - Get account-wide delivery metrics [Required]
+2. `SENDGRID_GET_ALL_CATEGORIES` - Discover available categories for filtering [Optional]
+3. `SENDGRID_RETRIEVE_EMAIL_STATISTICS_FOR_CATEGORIES` - Get stats broken down by category [Optional]
+4. `SENDGRID_FILTER_ALL_MESSAGES` - Search email activity feed by recipient, status, or date [Optional]
+5. `SENDGRID_FILTER_MESSAGES_BY_MESSAGE_ID` - Get detailed events for a specific message [Optional]
+6. `SENDGRID_REQUEST_CSV` - Export activity data as CSV for large datasets [Optional]
+7. `SENDGRID_DOWNLOAD_CSV` - Download the exported CSV file [Optional]
+
+**Key parameters for SENDGRID_RETRIEVE_GLOBAL_EMAIL_STATISTICS**:
+- `start_date`: Start date YYYY-MM-DD (required)
+- `end_date`: End date YYYY-MM-DD
+- `aggregated_by`: "day", "week", or "month"
+- `limit` / `offset`: Pagination (default 500)
+
+**Key parameters for SENDGRID_FILTER_ALL_MESSAGES**:
+- `query`: SQL-like query string, e.g., `status="delivered"`, `to_email="user@example.com"`, date ranges with `BETWEEN TIMESTAMP`
+- `limit`: 1-1000 (default 10)
+
+**Pitfalls**:
+- `SENDGRID_FILTER_ALL_MESSAGES` requires the "30 Days Additional Email Activity History" paid add-on; returns 403 without it
+- Global statistics are nested under `details[].stats[0].metrics`, not a flat structure
+- Category statistics are only available for the previous 13 months
+- Maximum 10 categories per request in `SENDGRID_RETRIEVE_EMAIL_STATISTICS_FOR_CATEGORIES`
+- CSV export is limited to one request per 12 hours; link expires after 3 days
+
+### 5. Manage Suppressions
+
+**When to use**: User wants to check or manage unsubscribe groups for email compliance.
+
+**Tool sequence**:
+1. `SENDGRID_GET_SUPPRESSION_GROUPS` - List all suppression groups [Required]
+2. `SENDGRID_RETRIEVE_ALL_SUPPRESSION_GROUPS_FOR_AN_EMAIL_ADDRESS` - Check suppression status for a specific email [Optional]
+
+**Pitfalls**:
+- Suppressed addresses remain undeliverable even if present on marketing lists
+- Campaign send counts may be lower than list counts due to suppressions
+
+## Common Patterns
+
+### ID Resolution
+Always resolve names to IDs before operations:
+- **List name -> list_id**: `SENDGRID_RETRIEVE_ALL_LISTS` and match by name
+- **Sender name -> sender_id**: `SENDGRID_GET_ALL_SENDER_IDENTITIES` and match
+- **Contact email -> contact_id**: `SENDGRID_GET_CONTACTS_BY_EMAILS` with email array
+- **Template name -> template_id**: Use the SendGrid UI or template endpoints
+
+### Pagination
+- `SENDGRID_RETRIEVE_ALL_LISTS`: Token-based with `page_token` and `page_size` (max 1000)
+- `SENDGRID_RETRIEVE_GLOBAL_EMAIL_STATISTICS`: Offset-based with `limit` (max 500) and `offset`
+- Always paginate list retrieval to avoid missing existing lists
+
+### Async Operations
+Contact operations (`ADD_OR_UPDATE_A_CONTACT`, `IMPORT_CONTACTS`) are asynchronous:
+- Returns 202 with a `job_id`
+- Wait 10-30 seconds before verifying with `GET_CONTACTS_BY_EMAILS`
+- Use `GET_LIST_CONTACT_COUNT` to confirm list growth
+
+## Known Pitfalls
+
+### ID Formats
+- Marketing list IDs are UUIDs (e.g., "ca7a3796-e8a8-4029-9ccb-df8937940562")
+- Legacy list IDs are integers; do not mix with Marketing API endpoints
+- Sender identity IDs are integers
+- Template IDs: Dynamic templates start with "d-", legacy templates are UUIDs
+- Contact IDs are UUIDs
+
+### Rate Limits
+- SendGrid may return HTTP 429; respect `Retry-After` headers
+- CSV export limited to one request per 12 hours
+- Bulk contact upsert max: 30,000 contacts or 6MB per request
+
+### Parameter Quirks
+- Nested params use double-underscore: `email__config__subject`, `from__email`
+- `send_at` on CREATE_SINGLE_SEND only sets a UI default, does NOT schedule
+- `SENDGRID_ADD_A_SINGLE_RECIPIENT_TO_A_LIST` uses legacy API; `recipient_id` is Base64-encoded lowercase email
+- `SENDGRID_RETRIEVE_ALL_LISTS` and `SENDGRID_GET_ALL_LISTS` both exist; prefer RETRIEVE_ALL_LISTS for Marketing API
+- Contact adds are async (202); always verify after a delay
+
+### Legacy vs Marketing API
+- Some tools use the legacy Contact Database API (`/v3/contactdb/`) which may return 403 on newer accounts
+- Prefer Marketing API tools: `SENDGRID_ADD_OR_UPDATE_A_CONTACT`, `SENDGRID_RETRIEVE_ALL_LISTS`, `SENDGRID_CREATE_SINGLE_SEND`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List marketing lists | `SENDGRID_RETRIEVE_ALL_LISTS` | `page_size`, `page_token` |
+| Create list | `SENDGRID_CREATE_A_LIST` | `name` |
+| Get list by ID | `SENDGRID_GET_A_LIST_BY_ID` | `id` |
+| Get list count | `SENDGRID_GET_LIST_CONTACT_COUNT` | `id` |
+| Add/update contacts | `SENDGRID_ADD_OR_UPDATE_A_CONTACT` | `contacts`, `list_ids` |
+| Search contacts by email | `SENDGRID_GET_CONTACTS_BY_EMAILS` | `emails` |
+| Search by identifiers | `SENDGRID_GET_CONTACTS_BY_IDENTIFIERS` | `identifier_type`, `identifiers` |
+| Remove from list | `SENDGRID_REMOVE_CONTACTS_FROM_A_LIST` | `id`, `contact_ids` |
+| Delete list | `SENDGRID_REMOVE_LIST_AND_OPTIONAL_CONTACTS` | `id`, `delete_contacts` |
+| Import contacts CSV | `SENDGRID_IMPORT_CONTACTS` | field mappings |
+| Create Single Send | `SENDGRID_CREATE_SINGLE_SEND` | `name`, `email__config__*`, `send__to__list__ids` |
+| List sender identities | `SENDGRID_GET_ALL_SENDER_IDENTITIES` | (none) |
+| Create sender | `SENDGRID_CREATE_A_SENDER_IDENTITY` | `from__email`, `from__name`, `address` |
+| Verify sender | `SENDGRID_CREATE_VERIFIED_SENDER_REQUEST` | `from_email`, `nickname`, `address` |
+| Authenticate domain | `SENDGRID_AUTHENTICATE_A_DOMAIN` | `domain` |
+| Global email stats | `SENDGRID_RETRIEVE_GLOBAL_EMAIL_STATISTICS` | `start_date`, `aggregated_by` |
+| Category stats | `SENDGRID_RETRIEVE_EMAIL_STATISTICS_FOR_CATEGORIES` | `start_date`, `categories` |
+| Filter email activity | `SENDGRID_FILTER_ALL_MESSAGES` | `query`, `limit` |
+| Message details | `SENDGRID_FILTER_MESSAGES_BY_MESSAGE_ID` | `msg_id` |
+| Export CSV | `SENDGRID_REQUEST_CSV` | `query` |
+| Download CSV | `SENDGRID_DOWNLOAD_CSV` | `download_uuid` |
+| List categories | `SENDGRID_GET_ALL_CATEGORIES` | (none) |
+| Suppression groups | `SENDGRID_GET_SUPPRESSION_GROUPS` | (none) |
+| Get template | `SENDGRID_RETRIEVE_A_SINGLE_TRANSACTIONAL_TEMPLATE` | `template_id` |
+| Duplicate template | `SENDGRID_DUPLICATE_A_TRANSACTIONAL_TEMPLATE` | `template_id`, `name` |
diff --git a/sentry-automation/SKILL.md b/sentry-automation/SKILL.md
new file mode 100644
index 0000000..aabd886
--- /dev/null
+++ b/sentry-automation/SKILL.md
@@ -0,0 +1,229 @@
+---
+name: sentry-automation
+description: Automate Sentry tasks via Rube MCP (Composio): manage issues/events, configure alerts, track releases, monitor projects and teams. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Sentry Automation via Rube MCP
+
+Automate Sentry error tracking and monitoring operations through Composio's Sentry toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Sentry connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `sentry`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `sentry`
+3. If connection is not ACTIVE, follow the returned auth link to complete Sentry OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Investigate Issues
+
+**When to use**: User wants to find, inspect, or triage error issues
+
+**Tool sequence**:
+1. `SENTRY_LIST_AN_ORGANIZATIONS_ISSUES` - List issues across the organization [Required]
+2. `SENTRY_GET_ORGANIZATION_ISSUE_DETAILS` - Get detailed info on a specific issue [Optional]
+3. `SENTRY_LIST_AN_ISSUES_EVENTS` - View individual error events for an issue [Optional]
+4. `SENTRY_RETRIEVE_AN_ISSUE_EVENT` - Get full event details with stack trace [Optional]
+5. `SENTRY_RETRIEVE_ISSUE_TAG_DETAILS` - Inspect tag distribution for an issue [Optional]
+
+**Key parameters**:
+- `organization_id_or_slug`: Organization identifier
+- `issue_id`: Numeric issue ID
+- `query`: Search query (e.g., `is:unresolved`, `assigned:me`, `browser:Chrome`)
+- `sort`: Sort order (`date`, `new`, `freq`, `priority`)
+- `statsPeriod`: Time window for stats (`24h`, `14d`, etc.)
+
+**Pitfalls**:
+- `organization_id_or_slug` is the org slug (e.g., 'my-org'), not the display name
+- Issue IDs are numeric; do not confuse with event IDs which are UUIDs
+- Query syntax uses Sentry's search format: `is:unresolved`, `assigned:me`, `!has:release`
+- Events within an issue can have different stack traces; inspect individual events for details
+
+### 2. Manage Project Issues
+
+**When to use**: User wants to view issues scoped to a specific project
+
+**Tool sequence**:
+1. `SENTRY_RETRIEVE_ORGANIZATION_PROJECTS` - List projects to find project slug [Prerequisite]
+2. `SENTRY_RETRIEVE_PROJECT_ISSUES_LIST` - List issues for a specific project [Required]
+3. `SENTRY_RETRIEVE_ISSUE_EVENTS_BY_ID` - Get events for a specific issue [Optional]
+
+**Key parameters**:
+- `organization_id_or_slug`: Organization identifier
+- `project_id_or_slug`: Project identifier
+- `query`: Search filter string
+- `statsPeriod`: Stats time window
+
+**Pitfalls**:
+- Project slugs are different from project display names
+- Always resolve project names to slugs via RETRIEVE_ORGANIZATION_PROJECTS first
+- Project-scoped issue lists may have different pagination than org-scoped lists
+
+### 3. Configure Alert Rules
+
+**When to use**: User wants to create or manage alert rules for a project
+
+**Tool sequence**:
+1. `SENTRY_RETRIEVE_ORGANIZATION_PROJECTS` - Find project for the alert [Prerequisite]
+2. `SENTRY_RETRIEVE_PROJECT_RULES_BY_ORG_AND_PROJECT_ID` - List existing rules [Optional]
+3. `SENTRY_CREATE_PROJECT_RULE_FOR_ALERTS` - Create a new alert rule [Required]
+4. `SENTRY_CREATE_ORGANIZATION_ALERT_RULE` - Create org-level metric alert [Alternative]
+5. `SENTRY_UPDATE_ORGANIZATION_ALERT_RULES` - Update existing alert rules [Optional]
+6. `SENTRY_RETRIEVE_ALERT_RULE_DETAILS` - Inspect specific alert rule [Optional]
+7. `SENTRY_GET_PROJECT_RULE_DETAILS` - Get project-level rule details [Optional]
+
+**Key parameters**:
+- `name`: Alert rule name
+- `conditions`: Array of trigger conditions
+- `actions`: Array of actions to perform when triggered
+- `filters`: Array of event filters
+- `frequency`: How often to trigger (in minutes)
+- `actionMatch`: 'all', 'any', or 'none' for condition matching
+
+**Pitfalls**:
+- Project-level rules (CREATE_PROJECT_RULE) and org-level metric alerts (CREATE_ORGANIZATION_ALERT_RULE) are different
+- Conditions, actions, and filters use specific JSON schemas; check Sentry docs for valid types
+- `frequency` is in minutes; setting too low causes alert fatigue
+- `actionMatch` defaults may vary; explicitly set to avoid unexpected behavior
+
+### 4. Manage Releases
+
+**When to use**: User wants to create, track, or manage release versions
+
+**Tool sequence**:
+1. `SENTRY_LIST_ORGANIZATION_RELEASES` - List existing releases [Optional]
+2. `SENTRY_CREATE_RELEASE_FOR_ORGANIZATION` - Create a new release [Required]
+3. `SENTRY_UPDATE_RELEASE_DETAILS_FOR_ORGANIZATION` - Update release metadata [Optional]
+4. `SENTRY_CREATE_RELEASE_DEPLOY_FOR_ORG` - Record a deployment for a release [Optional]
+5. `SENTRY_UPLOAD_RELEASE_FILE_TO_ORGANIZATION` - Upload source maps or files [Optional]
+
+**Key parameters**:
+- `version`: Release version string (e.g., '1.0.0', commit SHA)
+- `projects`: Array of project slugs this release belongs to
+- `dateReleased`: Release timestamp (ISO 8601)
+- `environment`: Deployment environment name (e.g., 'production', 'staging')
+
+**Pitfalls**:
+- Release versions must be unique within an organization
+- Releases can span multiple projects; use the `projects` array
+- Deploying a release is separate from creating it; use CREATE_RELEASE_DEPLOY
+- Source map uploads require the release to exist first
+
+### 5. Monitor Organization and Teams
+
+**When to use**: User wants to view org structure, teams, or member lists
+
+**Tool sequence**:
+1. `SENTRY_GET_ORGANIZATION_DETAILS` or `SENTRY_GET_ORGANIZATION_BY_ID_OR_SLUG` - Get org info [Required]
+2. `SENTRY_LIST_TEAMS_IN_ORGANIZATION` - List all teams [Optional]
+3. `SENTRY_LIST_ORGANIZATION_MEMBERS` - List org members [Optional]
+4. `SENTRY_GET_PROJECT_LIST` - List all accessible projects [Optional]
+
+**Key parameters**:
+- `organization_id_or_slug`: Organization identifier
+- `cursor`: Pagination cursor for large result sets
+
+**Pitfalls**:
+- Organization slugs are URL-safe identifiers, not display names
+- Member lists may be paginated; follow cursor pagination
+- Team and member visibility depends on the authenticated user's permissions
+
+### 6. Manage Monitors (Cron Monitoring)
+
+**When to use**: User wants to update cron job monitoring configuration
+
+**Tool sequence**:
+1. `SENTRY_UPDATE_A_MONITOR` - Update monitor configuration [Required]
+
+**Key parameters**:
+- `organization_id_or_slug`: Organization identifier
+- `monitor_id_or_slug`: Monitor identifier
+- `name`: Monitor display name
+- `schedule`: Cron schedule expression or interval
+- `checkin_margin`: Grace period in minutes for late check-ins
+- `max_runtime`: Maximum expected runtime in minutes
+
+**Pitfalls**:
+- Monitor slugs are auto-generated from the name; use slug for API calls
+- Schedule changes take effect immediately
+- Missing check-ins trigger alerts after the margin period
+
+## Common Patterns
+
+### ID Resolution
+
+**Organization name -> Slug**:
+```
+1. Call SENTRY_GET_ORGANIZATION_DETAILS
+2. Extract slug field from response
+```
+
+**Project name -> Slug**:
+```
+1. Call SENTRY_RETRIEVE_ORGANIZATION_PROJECTS
+2. Find project by name, extract slug
+```
+
+### Pagination
+
+- Sentry uses cursor-based pagination with `Link` headers
+- Check response for cursor values
+- Pass cursor in next request until no more pages
+
+### Search Query Syntax
+
+- `is:unresolved` - Unresolved issues
+- `is:resolved` - Resolved issues
+- `assigned:me` - Assigned to current user
+- `assigned:team-slug` - Assigned to a team
+- `!has:release` - Issues without a release
+- `first-release:1.0.0` - Issues first seen in release
+- `times-seen:>100` - Seen more than 100 times
+- `browser:Chrome` - Filter by browser tag
+
+## Known Pitfalls
+
+**ID Formats**:
+- Organization: use slug (e.g., 'my-org'), not display name
+- Project: use slug (e.g., 'my-project'), not display name
+- Issue IDs: numeric integers
+- Event IDs: UUIDs (32-char hex strings)
+
+**Permissions**:
+- API token scopes must match the operations being performed
+- Organization-level operations require org-level permissions
+- Project-level operations require project access
+
+**Rate Limits**:
+- Sentry enforces per-organization rate limits
+- Implement backoff on 429 responses
+- Bulk operations should be staggered
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List org issues | SENTRY_LIST_AN_ORGANIZATIONS_ISSUES | organization_id_or_slug, query |
+| Get issue details | SENTRY_GET_ORGANIZATION_ISSUE_DETAILS | organization_id_or_slug, issue_id |
+| List issue events | SENTRY_LIST_AN_ISSUES_EVENTS | issue_id |
+| Get event details | SENTRY_RETRIEVE_AN_ISSUE_EVENT | organization_id_or_slug, event_id |
+| List project issues | SENTRY_RETRIEVE_PROJECT_ISSUES_LIST | organization_id_or_slug, project_id_or_slug |
+| List projects | SENTRY_RETRIEVE_ORGANIZATION_PROJECTS | organization_id_or_slug |
+| Get org details | SENTRY_GET_ORGANIZATION_DETAILS | organization_id_or_slug |
+| List teams | SENTRY_LIST_TEAMS_IN_ORGANIZATION | organization_id_or_slug |
+| List members | SENTRY_LIST_ORGANIZATION_MEMBERS | organization_id_or_slug |
+| Create alert rule | SENTRY_CREATE_PROJECT_RULE_FOR_ALERTS | organization_id_or_slug, project_id_or_slug |
+| Create metric alert | SENTRY_CREATE_ORGANIZATION_ALERT_RULE | organization_id_or_slug |
+| Create release | SENTRY_CREATE_RELEASE_FOR_ORGANIZATION | organization_id_or_slug, version |
+| Deploy release | SENTRY_CREATE_RELEASE_DEPLOY_FOR_ORG | organization_id_or_slug, version |
+| List releases | SENTRY_LIST_ORGANIZATION_RELEASES | organization_id_or_slug |
+| Update monitor | SENTRY_UPDATE_A_MONITOR | organization_id_or_slug, monitor_id_or_slug |
diff --git a/shopify-automation/SKILL.md b/shopify-automation/SKILL.md
new file mode 100644
index 0000000..9f2b9ca
--- /dev/null
+++ b/shopify-automation/SKILL.md
@@ -0,0 +1,165 @@
+---
+name: shopify-automation
+description: Automate Shopify tasks via Rube MCP (Composio): products, orders, customers, inventory, collections. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Shopify Automation via Rube MCP
+
+Automate Shopify operations through Composio's Shopify toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Shopify connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `shopify`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `shopify`
+3. If connection is not ACTIVE, follow the returned auth link to complete Shopify OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Products
+
+**When to use**: User wants to list, search, create, or manage products
+
+**Tool sequence**:
+1. `SHOPIFY_GET_PRODUCTS` / `SHOPIFY_GET_PRODUCTS_PAGINATED` - List products [Optional]
+2. `SHOPIFY_GET_PRODUCT` - Get single product details [Optional]
+3. `SHOPIFY_BULK_CREATE_PRODUCTS` - Create products in bulk [Optional]
+4. `SHOPIFY_GET_PRODUCTS_COUNT` - Get product count [Optional]
+
+**Key parameters**:
+- `product_id`: Product ID for single retrieval
+- `title`: Product title
+- `vendor`: Product vendor
+- `status`: 'active', 'draft', or 'archived'
+
+**Pitfalls**:
+- Paginated results require cursor-based pagination for large catalogs
+- Product variants are nested within the product object
+
+### 2. Manage Orders
+
+**When to use**: User wants to list, search, or inspect orders
+
+**Tool sequence**:
+1. `SHOPIFY_GET_ORDERS_WITH_FILTERS` - List orders with filters [Required]
+2. `SHOPIFY_GET_ORDER` - Get single order details [Optional]
+3. `SHOPIFY_GET_FULFILLMENT` - Get fulfillment details [Optional]
+4. `SHOPIFY_GET_FULFILLMENT_EVENTS` - Track fulfillment events [Optional]
+
+**Key parameters**:
+- `status`: Order status filter ('any', 'open', 'closed', 'cancelled')
+- `financial_status`: Payment status filter
+- `fulfillment_status`: Fulfillment status filter
+- `order_id`: Order ID for single retrieval
+- `created_at_min`/`created_at_max`: Date range filters
+
+**Pitfalls**:
+- Order IDs are numeric; use string format for API calls
+- Default order listing may not include all statuses; specify 'any' for all
+
+### 3. Manage Customers
+
+**When to use**: User wants to list or search customers
+
+**Tool sequence**:
+1. `SHOPIFY_GET_ALL_CUSTOMERS` - List all customers [Required]
+
+**Key parameters**:
+- `limit`: Number of customers per page
+- `since_id`: Pagination cursor
+
+**Pitfalls**:
+- Customer data includes order count and total spent
+- Large customer lists require pagination
+
+### 4. Manage Collections
+
+**When to use**: User wants to manage product collections
+
+**Tool sequence**:
+1. `SHOPIFY_GET_SMART_COLLECTIONS` - List smart collections [Optional]
+2. `SHOPIFY_GET_SMART_COLLECTION_BY_ID` - Get collection details [Optional]
+3. `SHOPIFY_CREATE_SMART_COLLECTIONS` - Create a smart collection [Optional]
+4. `SHOPIFY_ADD_PRODUCT_TO_COLLECTION` - Add product to collection [Optional]
+5. `SHOPIFY_GET_PRODUCTS_IN_COLLECTION` - List products in collection [Optional]
+
+**Key parameters**:
+- `collection_id`: Collection ID
+- `product_id`: Product ID for adding to collection
+- `rules`: Smart collection rules for automatic inclusion
+
+**Pitfalls**:
+- Smart collections auto-populate based on rules; manual collections use custom collections API
+- Collection count endpoints provide approximate counts
+
+### 5. Manage Inventory
+
+**When to use**: User wants to check or manage inventory levels
+
+**Tool sequence**:
+1. `SHOPIFY_GET_INVENTORY_LEVELS` / `SHOPIFY_RETRIEVES_A_LIST_OF_INVENTORY_LEVELS` - Check stock [Required]
+2. `SHOPIFY_LIST_LOCATION` - List store locations [Optional]
+
+**Key parameters**:
+- `inventory_item_ids`: Inventory item IDs to check
+- `location_ids`: Location IDs to filter by
+
+**Pitfalls**:
+- Inventory is tracked per variant per location
+- Location IDs are required for multi-location stores
+
+## Common Patterns
+
+### Pagination
+
+- Use `limit` and `page_info` cursor for paginated results
+- Check response for `next` link header
+- Continue until no more pages available
+
+### GraphQL Queries
+
+For advanced operations:
+```
+1. Call SHOPIFY_GRAPH_QL_QUERY with custom query
+2. Parse response from data object
+```
+
+## Known Pitfalls
+
+**API Versioning**:
+- Shopify REST API has versioned endpoints
+- Some features require specific API versions
+
+**Rate Limits**:
+- REST API: 2 requests/second for standard plans
+- GraphQL: 1000 cost points per second
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List products | SHOPIFY_GET_PRODUCTS | (filters) |
+| Get product | SHOPIFY_GET_PRODUCT | product_id |
+| Products paginated | SHOPIFY_GET_PRODUCTS_PAGINATED | limit, page_info |
+| Bulk create | SHOPIFY_BULK_CREATE_PRODUCTS | products |
+| Product count | SHOPIFY_GET_PRODUCTS_COUNT | (none) |
+| List orders | SHOPIFY_GET_ORDERS_WITH_FILTERS | status, financial_status |
+| Get order | SHOPIFY_GET_ORDER | order_id |
+| List customers | SHOPIFY_GET_ALL_CUSTOMERS | limit |
+| Shop details | SHOPIFY_GET_SHOP_DETAILS | (none) |
+| Validate access | SHOPIFY_VALIDATE_ACCESS | (none) |
+| Smart collections | SHOPIFY_GET_SMART_COLLECTIONS | (none) |
+| Products in collection | SHOPIFY_GET_PRODUCTS_IN_COLLECTION | collection_id |
+| Inventory levels | SHOPIFY_GET_INVENTORY_LEVELS | inventory_item_ids |
+| Locations | SHOPIFY_LIST_LOCATION | (none) |
+| Fulfillment | SHOPIFY_GET_FULFILLMENT | order_id, fulfillment_id |
+| GraphQL | SHOPIFY_GRAPH_QL_QUERY | query |
+| Bulk query | SHOPIFY_BULK_QUERY_OPERATION | query |
diff --git a/slack-automation/SKILL.md b/slack-automation/SKILL.md
new file mode 100644
index 0000000..52ac2bc
--- /dev/null
+++ b/slack-automation/SKILL.md
@@ -0,0 +1,186 @@
+---
+name: slack-automation
+description: Automate Slack messaging, channel management, search, reactions, and threads via Rube MCP (Composio). Send messages, search conversations, manage channels/users, and react to messages programmatically.
+requires:
+ mcp: [rube]
+---
+
+# Slack Automation via Rube MCP
+
+Automate Slack workspace operations including messaging, search, channel management, and reaction workflows through Composio's Slack toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Slack connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `slack`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `slack`
+3. If connection is not ACTIVE, follow the returned auth link to complete Slack OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send Messages to Channels
+
+**When to use**: User wants to post a message to a Slack channel or DM
+
+**Tool sequence**:
+1. `SLACK_FIND_CHANNELS` - Resolve channel name to channel ID [Prerequisite]
+2. `SLACK_LIST_ALL_CHANNELS` - Fallback if FIND_CHANNELS returns empty/ambiguous results [Fallback]
+3. `SLACK_FIND_USERS` - Resolve user for DMs or @mentions [Optional]
+4. `SLACK_OPEN_DM` - Open/reuse a DM channel if messaging a user directly [Optional]
+5. `SLACK_SEND_MESSAGE` - Post the message with resolved channel ID [Required]
+6. `SLACK_UPDATES_A_SLACK_MESSAGE` - Edit the posted message if corrections needed [Optional]
+
+**Key parameters**:
+- `channel`: Channel ID or name (without '#' prefix)
+- `markdown_text`: Preferred field for formatted messages (supports headers, bold, italic, code blocks)
+- `text`: Raw text fallback (deprecated in favor of markdown_text)
+- `thread_ts`: Timestamp of parent message to reply in a thread
+- `blocks`: Block Kit layout blocks (deprecated, use markdown_text)
+
+**Pitfalls**:
+- `SLACK_FIND_CHANNELS` requires `query` param; missing it errors with "Invalid request data provided"
+- `SLACK_SEND_MESSAGE` requires valid channel plus one of markdown_text/text/blocks/attachments
+- Invalid block payloads return error=invalid_blocks (max 50 blocks)
+- Replies become top-level posts if `thread_ts` is omitted
+- Persist `response.data.channel` and `response.data.message.ts` from SEND_MESSAGE for edit/thread operations
+
+### 2. Search Messages and Conversations
+
+**When to use**: User wants to find specific messages across the workspace
+
+**Tool sequence**:
+1. `SLACK_FIND_CHANNELS` - Resolve channel for scoped search with `in:#channel` [Optional]
+2. `SLACK_FIND_USERS` - Resolve user for author filter with `from:@user` [Optional]
+3. `SLACK_SEARCH_MESSAGES` - Run keyword search across accessible conversations [Required]
+4. `SLACK_FETCH_MESSAGE_THREAD_FROM_A_CONVERSATION` - Expand threads for relevant hits [Required]
+
+**Key parameters**:
+- `query`: Search string supporting modifiers (`in:#channel`, `from:@user`, `before:YYYY-MM-DD`, `after:YYYY-MM-DD`, `has:link`, `has:file`)
+- `count`: Results per page (max 100), or total with auto_paginate=true
+- `sort`: 'score' (relevance) or 'timestamp' (chronological)
+- `sort_dir`: 'asc' or 'desc'
+
+**Pitfalls**:
+- Validation fails if `query` is missing/empty
+- `ok=true` can still mean no hits (`response.data.messages.total=0`)
+- Matches are under `response.data.messages.matches` (sometimes also `response.data_preview.messages.matches`)
+- `match.text` may be empty/truncated; key info can appear in `matches[].attachments[]`
+- Thread expansion via FETCH_MESSAGE_THREAD can truncate when `response.data.has_more=true`; paginate via `response_metadata.next_cursor`
+
+### 3. Manage Channels and Users
+
+**When to use**: User wants to list channels, users, or workspace info
+
+**Tool sequence**:
+1. `SLACK_FETCH_TEAM_INFO` - Validate connectivity and get workspace identity [Required]
+2. `SLACK_LIST_ALL_CHANNELS` - Enumerate public channels [Required]
+3. `SLACK_LIST_CONVERSATIONS` - Include private channels and DMs [Optional]
+4. `SLACK_LIST_ALL_USERS` - List workspace members [Required]
+5. `SLACK_RETRIEVE_CONVERSATION_INFORMATION` - Get detailed channel metadata [Optional]
+6. `SLACK_LIST_USER_GROUPS_FOR_TEAM_WITH_OPTIONS` - List user groups [Optional]
+
+**Key parameters**:
+- `cursor`: Pagination cursor from `response_metadata.next_cursor`
+- `limit`: Results per page (default varies; set explicitly for large workspaces)
+- `types`: Channel types filter ('public_channel', 'private_channel', 'im', 'mpim')
+
+**Pitfalls**:
+- Workspace metadata is nested under `response.data.team`, not top-level
+- `SLACK_LIST_ALL_CHANNELS` returns public channels only; use `SLACK_LIST_CONVERSATIONS` for private/IM coverage
+- `SLACK_LIST_ALL_USERS` can hit HTTP 429 rate limits; honor Retry-After header
+- Always paginate via `response_metadata.next_cursor` until empty; de-duplicate by `id`
+
+### 4. React to and Thread Messages
+
+**When to use**: User wants to add reactions or manage threaded conversations
+
+**Tool sequence**:
+1. `SLACK_SEARCH_MESSAGES` or `SLACK_FETCH_CONVERSATION_HISTORY` - Find the target message [Prerequisite]
+2. `SLACK_ADD_REACTION_TO_AN_ITEM` - Add an emoji reaction [Required]
+3. `SLACK_FETCH_ITEM_REACTIONS` - List reactions on a message [Optional]
+4. `SLACK_REMOVE_REACTION_FROM_ITEM` - Remove a reaction [Optional]
+5. `SLACK_SEND_MESSAGE` - Reply in thread using `thread_ts` [Optional]
+6. `SLACK_FETCH_MESSAGE_THREAD_FROM_A_CONVERSATION` - Read full thread [Optional]
+
+**Key parameters**:
+- `channel`: Channel ID where the message lives
+- `timestamp` / `ts`: Message timestamp (unique identifier like '1234567890.123456')
+- `name`: Emoji name without colons (e.g., 'thumbsup', 'wave::skin-tone-3')
+- `thread_ts`: Parent message timestamp for threaded replies
+
+**Pitfalls**:
+- Reactions require exact channel ID + message timestamp pair
+- Emoji names use Slack's naming convention without colons
+- `SLACK_FETCH_CONVERSATION_HISTORY` only returns main channel timeline, NOT threaded replies
+- Use `SLACK_FETCH_MESSAGE_THREAD_FROM_A_CONVERSATION` with parent's `thread_ts` to get thread replies
+
+### 5. Schedule Messages
+
+**When to use**: User wants to schedule a message for future delivery
+
+**Tool sequence**:
+1. `SLACK_FIND_CHANNELS` - Resolve channel ID [Prerequisite]
+2. `SLACK_SCHEDULE_MESSAGE` - Schedule the message with `post_at` timestamp [Required]
+
+**Key parameters**:
+- `channel`: Resolved channel ID
+- `post_at`: Unix timestamp for delivery (up to 120 days in advance)
+- `text` / `blocks`: Message content
+
+**Pitfalls**:
+- Scheduling is limited to 120 days in advance
+- `post_at` must be a Unix timestamp, not ISO 8601
+
+## Common Patterns
+
+### ID Resolution
+Always resolve display names to IDs before operations:
+- **Channel name -> Channel ID**: `SLACK_FIND_CHANNELS` with `query` param
+- **User name -> User ID**: `SLACK_FIND_USERS` with `search_query` or `email`
+- **DM channel**: `SLACK_OPEN_DM` with resolved user IDs
+
+### Pagination
+Most list endpoints use cursor-based pagination:
+- Follow `response_metadata.next_cursor` until empty
+- Set explicit `limit` values (e.g., 100-200) for reliable paging
+- De-duplicate results by `id` across pages
+
+### Message Formatting
+- Prefer `markdown_text` over `text` or `blocks` for formatted messages
+- Use `<@USER_ID>` format to mention users (not @username)
+- Use `\n` for line breaks in markdown_text
+
+## Known Pitfalls
+
+- **Channel resolution**: `SLACK_FIND_CHANNELS` can return empty results if channel is private and bot hasn't been invited
+- **Rate limits**: `SLACK_LIST_ALL_USERS` and other list endpoints can hit HTTP 429; honor Retry-After header
+- **Nested responses**: Results may be nested under `response.data.results[0].response.data` in wrapped executions
+- **Thread vs channel**: `SLACK_FETCH_CONVERSATION_HISTORY` returns main timeline only; use `SLACK_FETCH_MESSAGE_THREAD_FROM_A_CONVERSATION` for thread replies
+- **Message editing**: Requires both `channel` and original message `ts`; persist these from SEND_MESSAGE response
+- **Search delays**: Recently posted messages may not appear in search results immediately
+- **Scope limitations**: Missing OAuth scopes can cause 403 errors; check with `SLACK_GET_APP_PERMISSION_SCOPES`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Find channels | `SLACK_FIND_CHANNELS` | `query` |
+| List all channels | `SLACK_LIST_ALL_CHANNELS` | `limit`, `cursor`, `types` |
+| Send message | `SLACK_SEND_MESSAGE` | `channel`, `markdown_text` |
+| Edit message | `SLACK_UPDATES_A_SLACK_MESSAGE` | `channel`, `ts`, `markdown_text` |
+| Search messages | `SLACK_SEARCH_MESSAGES` | `query`, `count`, `sort` |
+| Get thread | `SLACK_FETCH_MESSAGE_THREAD_FROM_A_CONVERSATION` | `channel`, `ts` |
+| Add reaction | `SLACK_ADD_REACTION_TO_AN_ITEM` | `channel`, `name`, `timestamp` |
+| Find users | `SLACK_FIND_USERS` | `search_query` or `email` |
+| List users | `SLACK_LIST_ALL_USERS` | `limit`, `cursor` |
+| Open DM | `SLACK_OPEN_DM` | user IDs |
+| Schedule message | `SLACK_SCHEDULE_MESSAGE` | `channel`, `post_at`, `text` |
+| Get channel info | `SLACK_RETRIEVE_CONVERSATION_INFORMATION` | channel ID |
+| Channel history | `SLACK_FETCH_CONVERSATION_HISTORY` | `channel`, `oldest`, `latest` |
+| Workspace info | `SLACK_FETCH_TEAM_INFO` | (none) |
diff --git a/square-automation/SKILL.md b/square-automation/SKILL.md
new file mode 100644
index 0000000..73c6fe5
--- /dev/null
+++ b/square-automation/SKILL.md
@@ -0,0 +1,173 @@
+---
+name: square-automation
+description: Automate Square tasks via Rube MCP (Composio): payments, orders, invoices, locations. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Square Automation via Rube MCP
+
+Automate Square payment processing, order management, and invoicing through Composio's Square toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Square connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `square`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `square`
+3. If connection is not ACTIVE, follow the returned auth link to complete Square OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Monitor Payments
+
+**When to use**: User wants to view payment history or check payment status
+
+**Tool sequence**:
+1. `SQUARE_LIST_PAYMENTS` - Retrieve payments with optional filters [Required]
+2. `SQUARE_CANCEL_PAYMENT` - Cancel a pending payment if needed [Optional]
+
+**Key parameters**:
+- `begin_time` / `end_time`: RFC 3339 timestamps for date range filtering
+- `sort_order`: 'ASC' or 'DESC' for chronological ordering
+- `cursor`: Pagination cursor from previous response
+- `location_id`: Filter payments by specific location
+
+**Pitfalls**:
+- Timestamps must be RFC 3339 format (e.g., '2024-01-01T00:00:00Z')
+- Pagination required for large result sets; follow `cursor` until absent
+- Only pending payments can be cancelled; completed payments require refunds
+- `SQUARE_CANCEL_PAYMENT` requires exact `payment_id` from list results
+
+### 2. Search and Manage Orders
+
+**When to use**: User wants to find orders by criteria or update order details
+
+**Tool sequence**:
+1. `SQUARE_LIST_LOCATIONS` - Get location IDs for filtering [Prerequisite]
+2. `SQUARE_SEARCH_ORDERS` - Search orders with filters [Required]
+3. `SQUARE_RETRIEVE_ORDER` - Get full details of a specific order [Optional]
+4. `SQUARE_UPDATE_ORDER` - Modify order state or details [Optional]
+
+**Key parameters**:
+- `location_ids`: Array of location IDs to search within (required for search)
+- `query`: Search filter object with date ranges, states, fulfillment types
+- `order_id`: Specific order ID for retrieve/update operations
+- `cursor`: Pagination cursor for search results
+
+**Pitfalls**:
+- `location_ids` is required for SEARCH_ORDERS; get IDs from LIST_LOCATIONS first
+- Order states include: OPEN, COMPLETED, CANCELED, DRAFT
+- UPDATE_ORDER requires the current `version` field to prevent conflicts
+- Search results are paginated; follow `cursor` until absent
+
+### 3. Manage Locations
+
+**When to use**: User wants to view business locations or get location details
+
+**Tool sequence**:
+1. `SQUARE_LIST_LOCATIONS` - List all business locations [Required]
+
+**Key parameters**:
+- No required parameters; returns all accessible locations
+- Response includes `id`, `name`, `address`, `status`, `timezone`
+
+**Pitfalls**:
+- Location IDs are required for most other Square operations (orders, payments)
+- Always cache location IDs after first retrieval to avoid redundant calls
+- Inactive locations may still appear in results; check `status` field
+
+### 4. Invoice Management
+
+**When to use**: User wants to list, view, or cancel invoices
+
+**Tool sequence**:
+1. `SQUARE_LIST_LOCATIONS` - Get location ID for filtering [Prerequisite]
+2. `SQUARE_LIST_INVOICES` - List invoices for a location [Required]
+3. `SQUARE_GET_INVOICE` - Get detailed invoice information [Optional]
+4. `SQUARE_CANCEL_INVOICE` - Cancel a scheduled or unpaid invoice [Optional]
+
+**Key parameters**:
+- `location_id`: Required for listing invoices
+- `invoice_id`: Required for get/cancel operations
+- `cursor`: Pagination cursor for list results
+- `limit`: Number of results per page
+
+**Pitfalls**:
+- `location_id` is required for LIST_INVOICES; resolve via LIST_LOCATIONS first
+- Only SCHEDULED, UNPAID, or PARTIALLY_PAID invoices can be cancelled
+- CANCEL_INVOICE requires the invoice `version` to prevent race conditions
+- Cancelled invoices cannot be uncancelled
+
+## Common Patterns
+
+### ID Resolution
+
+**Location name -> Location ID**:
+```
+1. Call SQUARE_LIST_LOCATIONS
+2. Find location by name in response
+3. Extract id field (e.g., 'L1234ABCD')
+```
+
+**Order lookup**:
+```
+1. Call SQUARE_SEARCH_ORDERS with location_ids and query filters
+2. Extract order_id from results
+3. Use order_id for RETRIEVE_ORDER or UPDATE_ORDER
+```
+
+### Pagination
+
+- Check response for `cursor` field
+- Pass cursor value in next request's `cursor` parameter
+- Continue until `cursor` is absent or empty
+- Use `limit` to control page size
+
+### Date Range Filtering
+
+- Use RFC 3339 format: `2024-01-01T00:00:00Z`
+- For payments: `begin_time` and `end_time` parameters
+- For orders: Use query filter with date_time_filter
+- All timestamps are in UTC
+
+## Known Pitfalls
+
+**ID Formats**:
+- Location IDs are alphanumeric strings (e.g., 'L1234ABCD')
+- Payment IDs and Order IDs are longer alphanumeric strings
+- Always resolve location names to IDs before other operations
+
+**Versioning**:
+- UPDATE_ORDER and CANCEL_INVOICE require current `version` field
+- Fetch the resource first to get its current version
+- Version mismatch returns a 409 Conflict error
+
+**Rate Limits**:
+- Square API has per-endpoint rate limits
+- Implement backoff for bulk operations
+- Pagination should include brief delays for large datasets
+
+**Response Parsing**:
+- Responses may nest data under `data` key
+- Money amounts are in smallest currency unit (cents for USD)
+- Parse defensively with fallbacks for optional fields
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List payments | SQUARE_LIST_PAYMENTS | begin_time, end_time, location_id, cursor |
+| Cancel payment | SQUARE_CANCEL_PAYMENT | payment_id |
+| Search orders | SQUARE_SEARCH_ORDERS | location_ids, query, cursor |
+| Get order | SQUARE_RETRIEVE_ORDER | order_id |
+| Update order | SQUARE_UPDATE_ORDER | order_id, version |
+| List locations | SQUARE_LIST_LOCATIONS | (none) |
+| List invoices | SQUARE_LIST_INVOICES | location_id, cursor |
+| Get invoice | SQUARE_GET_INVOICE | invoice_id |
+| Cancel invoice | SQUARE_CANCEL_INVOICE | invoice_id, version |
diff --git a/stripe-automation/SKILL.md b/stripe-automation/SKILL.md
new file mode 100644
index 0000000..b48639e
--- /dev/null
+++ b/stripe-automation/SKILL.md
@@ -0,0 +1,195 @@
+---
+name: stripe-automation
+description: Automate Stripe tasks via Rube MCP (Composio): customers, charges, subscriptions, invoices, products, refunds. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Stripe Automation via Rube MCP
+
+Automate Stripe payment operations through Composio's Stripe toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Stripe connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `stripe`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `stripe`
+3. If connection is not ACTIVE, follow the returned auth link to complete Stripe connection
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage Customers
+
+**When to use**: User wants to create, update, search, or list Stripe customers
+
+**Tool sequence**:
+1. `STRIPE_SEARCH_CUSTOMERS` - Search customers by email/name [Optional]
+2. `STRIPE_LIST_CUSTOMERS` - List all customers [Optional]
+3. `STRIPE_CREATE_CUSTOMER` - Create a new customer [Optional]
+4. `STRIPE_POST_CUSTOMERS_CUSTOMER` - Update a customer [Optional]
+
+**Key parameters**:
+- `email`: Customer email
+- `name`: Customer name
+- `description`: Customer description
+- `metadata`: Key-value metadata pairs
+- `customer`: Customer ID for updates (e.g., 'cus_xxx')
+
+**Pitfalls**:
+- Stripe allows duplicate customers with the same email; search first to avoid duplicates
+- Customer IDs start with 'cus_'
+
+### 2. Manage Charges and Payments
+
+**When to use**: User wants to create charges, payment intents, or view charge history
+
+**Tool sequence**:
+1. `STRIPE_LIST_CHARGES` - List charges with filters [Optional]
+2. `STRIPE_CREATE_PAYMENT_INTENT` - Create a payment intent [Optional]
+3. `STRIPE_CONFIRM_PAYMENT_INTENT` - Confirm a payment intent [Optional]
+4. `STRIPE_POST_CHARGES` - Create a direct charge [Optional]
+5. `STRIPE_CAPTURE_CHARGE` - Capture an authorized charge [Optional]
+
+**Key parameters**:
+- `amount`: Amount in smallest currency unit (e.g., cents for USD)
+- `currency`: Three-letter ISO currency code (e.g., 'usd')
+- `customer`: Customer ID
+- `payment_method`: Payment method ID
+- `description`: Charge description
+
+**Pitfalls**:
+- Amounts are in smallest currency unit (100 = $1.00 for USD)
+- Currency codes must be lowercase (e.g., 'usd' not 'USD')
+- Payment intents are the recommended flow over direct charges
+
+### 3. Manage Subscriptions
+
+**When to use**: User wants to create, list, update, or cancel subscriptions
+
+**Tool sequence**:
+1. `STRIPE_LIST_SUBSCRIPTIONS` - List subscriptions [Optional]
+2. `STRIPE_POST_CUSTOMERS_CUSTOMER_SUBSCRIPTIONS` - Create subscription [Optional]
+3. `STRIPE_RETRIEVE_SUBSCRIPTION` - Get subscription details [Optional]
+4. `STRIPE_UPDATE_SUBSCRIPTION` - Modify subscription [Optional]
+
+**Key parameters**:
+- `customer`: Customer ID
+- `items`: Array of price items (price_id and quantity)
+- `subscription`: Subscription ID for retrieval/update (e.g., 'sub_xxx')
+
+**Pitfalls**:
+- Subscriptions require a valid customer with a payment method
+- Price IDs (not product IDs) are used for subscription items
+- Cancellation can be immediate or at period end
+
+### 4. Manage Invoices
+
+**When to use**: User wants to create, list, or search invoices
+
+**Tool sequence**:
+1. `STRIPE_LIST_INVOICES` - List invoices [Optional]
+2. `STRIPE_SEARCH_INVOICES` - Search invoices [Optional]
+3. `STRIPE_CREATE_INVOICE` - Create an invoice [Optional]
+
+**Key parameters**:
+- `customer`: Customer ID for invoice
+- `collection_method`: 'charge_automatically' or 'send_invoice'
+- `days_until_due`: Days until invoice is due
+
+**Pitfalls**:
+- Invoices auto-finalize by default; use `auto_advance: false` for draft invoices
+
+### 5. Manage Products and Prices
+
+**When to use**: User wants to list or search products and their pricing
+
+**Tool sequence**:
+1. `STRIPE_LIST_PRODUCTS` - List products [Optional]
+2. `STRIPE_SEARCH_PRODUCTS` - Search products [Optional]
+3. `STRIPE_LIST_PRICES` - List prices [Optional]
+4. `STRIPE_GET_PRICES_SEARCH` - Search prices [Optional]
+
+**Key parameters**:
+- `active`: Filter by active/inactive status
+- `query`: Search query for search endpoints
+
+**Pitfalls**:
+- Products and prices are separate objects; a product can have multiple prices
+- Price IDs (e.g., 'price_xxx') are used for subscriptions and checkout
+
+### 6. Handle Refunds
+
+**When to use**: User wants to issue refunds on charges
+
+**Tool sequence**:
+1. `STRIPE_LIST_REFUNDS` - List refunds [Optional]
+2. `STRIPE_POST_CHARGES_CHARGE_REFUNDS` - Create a refund [Optional]
+3. `STRIPE_CREATE_REFUND` - Create refund via payment intent [Optional]
+
+**Key parameters**:
+- `charge`: Charge ID for refund
+- `amount`: Partial refund amount (omit for full refund)
+- `reason`: Refund reason ('duplicate', 'fraudulent', 'requested_by_customer')
+
+**Pitfalls**:
+- Refunds can take 5-10 business days to appear on customer statements
+- Amount is in smallest currency unit
+
+## Common Patterns
+
+### Amount Formatting
+
+Stripe uses smallest currency unit:
+- USD: $10.50 = 1050 cents
+- EUR: 10.50 = 1050 cents
+- JPY: 1000 = 1000 (no decimals)
+
+### Pagination
+
+- Use `limit` parameter (max 100)
+- Check `has_more` in response
+- Pass `starting_after` with last object ID for next page
+- Continue until `has_more` is false
+
+## Known Pitfalls
+
+**Amount Units**:
+- Always use smallest currency unit (cents for USD/EUR)
+- Zero-decimal currencies (JPY, KRW) use the amount directly
+
+**ID Prefixes**:
+- Customers: `cus_`, Charges: `ch_`, Subscriptions: `sub_`
+- Invoices: `in_`, Products: `prod_`, Prices: `price_`
+- Payment Intents: `pi_`, Refunds: `re_`
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create customer | STRIPE_CREATE_CUSTOMER | email, name |
+| Search customers | STRIPE_SEARCH_CUSTOMERS | query |
+| Update customer | STRIPE_POST_CUSTOMERS_CUSTOMER | customer, fields |
+| List charges | STRIPE_LIST_CHARGES | customer, limit |
+| Create payment intent | STRIPE_CREATE_PAYMENT_INTENT | amount, currency |
+| Confirm payment | STRIPE_CONFIRM_PAYMENT_INTENT | payment_intent |
+| List subscriptions | STRIPE_LIST_SUBSCRIPTIONS | customer |
+| Create subscription | STRIPE_POST_CUSTOMERS_CUSTOMER_SUBSCRIPTIONS | customer, items |
+| Update subscription | STRIPE_UPDATE_SUBSCRIPTION | subscription, fields |
+| List invoices | STRIPE_LIST_INVOICES | customer |
+| Create invoice | STRIPE_CREATE_INVOICE | customer |
+| Search invoices | STRIPE_SEARCH_INVOICES | query |
+| List products | STRIPE_LIST_PRODUCTS | active |
+| Search products | STRIPE_SEARCH_PRODUCTS | query |
+| List prices | STRIPE_LIST_PRICES | product |
+| Search prices | STRIPE_GET_PRICES_SEARCH | query |
+| List refunds | STRIPE_LIST_REFUNDS | charge |
+| Create refund | STRIPE_CREATE_REFUND | charge, amount |
+| Payment methods | STRIPE_LIST_CUSTOMER_PAYMENT_METHODS | customer |
+| Checkout session | STRIPE_CREATE_CHECKOUT_SESSION | line_items |
+| List payment intents | STRIPE_LIST_PAYMENT_INTENTS | customer |
diff --git a/supabase-automation/SKILL.md b/supabase-automation/SKILL.md
new file mode 100644
index 0000000..65d3cb8
--- /dev/null
+++ b/supabase-automation/SKILL.md
@@ -0,0 +1,233 @@
+---
+name: supabase-automation
+description: Automate Supabase database queries, table management, project administration, storage, edge functions, and SQL execution via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Supabase Automation via Rube MCP
+
+Automate Supabase operations including database queries, table schema inspection, SQL execution, project and organization management, storage buckets, edge functions, and service health monitoring through Composio's Supabase toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Supabase connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `supabase`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `supabase`
+3. If connection is not ACTIVE, follow the returned auth link to complete Supabase authentication
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Query and Manage Database Tables
+
+**When to use**: User wants to read data from tables, inspect schemas, or perform CRUD operations
+
+**Tool sequence**:
+1. `SUPABASE_LIST_ALL_PROJECTS` - List projects to find the target project_ref [Prerequisite]
+2. `SUPABASE_LIST_TABLES` - List all tables and views in the database [Prerequisite]
+3. `SUPABASE_GET_TABLE_SCHEMAS` - Get detailed column types, constraints, and relationships [Prerequisite for writes]
+4. `SUPABASE_SELECT_FROM_TABLE` - Query rows with filtering, sorting, and pagination [Required for reads]
+5. `SUPABASE_BETA_RUN_SQL_QUERY` - Execute arbitrary SQL for complex queries, inserts, updates, or deletes [Required for writes]
+
+**Key parameters for SELECT_FROM_TABLE**:
+- `project_ref`: 20-character lowercase project reference
+- `table`: Table or view name to query
+- `select`: Comma-separated column list (supports nested selections and JSON paths like `profile->avatar_url`)
+- `filters`: Array of filter objects with `column`, `operator`, `value`
+- `order`: Sort expression like `created_at.desc`
+- `limit`: Max rows to return (minimum 1)
+- `offset`: Rows to skip for pagination
+
+**PostgREST filter operators**:
+- `eq`, `neq`: Equal / not equal
+- `gt`, `gte`, `lt`, `lte`: Comparison operators
+- `like`, `ilike`: Pattern matching (case-sensitive / insensitive)
+- `is`: IS check (for null, true, false)
+- `in`: In a list of values
+- `cs`, `cd`: Contains / contained by (arrays)
+- `fts`, `plfts`, `phfts`, `wfts`: Full-text search variants
+
+**Key parameters for RUN_SQL_QUERY**:
+- `ref`: Project reference (20 lowercase letters, pattern `^[a-z]{20}$`)
+- `query`: Valid PostgreSQL SQL statement
+- `read_only`: Boolean to force read-only transaction (safer for SELECTs)
+
+**Pitfalls**:
+- `project_ref` must be exactly 20 lowercase letters (a-z only, no numbers or hyphens)
+- `SELECT_FROM_TABLE` is read-only; use `RUN_SQL_QUERY` for INSERT, UPDATE, DELETE operations
+- For PostgreSQL array columns (text[], integer[]), use `ARRAY['item1', 'item2']` or `'{"item1", "item2"}'` syntax, NOT JSON array syntax `'["item1", "item2"]'`
+- SQL identifiers that are case-sensitive must be double-quoted in queries
+- Complex DDL operations may timeout (~60 second limit); break into smaller queries
+- ERROR 42P01 "relation does not exist" usually means unquoted case-sensitive identifiers
+- ERROR 42883 "function does not exist" means you are calling non-standard helpers; prefer information_schema queries
+
+### 2. Manage Projects and Organizations
+
+**When to use**: User wants to list projects, inspect configurations, or manage organizations
+
+**Tool sequence**:
+1. `SUPABASE_LIST_ALL_ORGANIZATIONS` - List all organizations (IDs and names) [Required]
+2. `SUPABASE_GETS_INFORMATION_ABOUT_THE_ORGANIZATION` - Get detailed org info by slug [Optional]
+3. `SUPABASE_LIST_MEMBERS_OF_AN_ORGANIZATION` - List org members with roles and MFA status [Optional]
+4. `SUPABASE_LIST_ALL_PROJECTS` - List all projects with metadata [Required]
+5. `SUPABASE_GETS_PROJECT_S_POSTGRES_CONFIG` - Get database configuration [Optional]
+6. `SUPABASE_GETS_PROJECT_S_AUTH_CONFIG` - Get authentication configuration [Optional]
+7. `SUPABASE_GET_PROJECT_API_KEYS` - Get API keys (sensitive -- handle carefully) [Optional]
+8. `SUPABASE_GETS_PROJECT_S_SERVICE_HEALTH_STATUS` - Check service health [Optional]
+
+**Key parameters**:
+- `ref`: Project reference for project-specific tools
+- `slug`: Organization slug (URL-friendly identifier) for org tools
+- `services`: Array of services for health check: `auth`, `db`, `db_postgres_user`, `pg_bouncer`, `pooler`, `realtime`, `rest`, `storage`
+
+**Pitfalls**:
+- `LIST_ALL_ORGANIZATIONS` returns both `id` and `slug`; `LIST_MEMBERS_OF_AN_ORGANIZATION` expects `slug`, not `id`
+- `GET_PROJECT_API_KEYS` returns live secrets -- NEVER log, display, or persist full key values
+- `GETS_PROJECT_S_SERVICE_HEALTH_STATUS` requires a non-empty `services` array; empty array causes invalid_request error
+- Config tools may return 401/403 if token lacks required scope; handle gracefully rather than failing the whole workflow
+
+### 3. Inspect Database Schema
+
+**When to use**: User wants to understand table structure, columns, constraints, or generate types
+
+**Tool sequence**:
+1. `SUPABASE_LIST_ALL_PROJECTS` - Find the target project [Prerequisite]
+2. `SUPABASE_LIST_TABLES` - Enumerate all tables and views with metadata [Required]
+3. `SUPABASE_GET_TABLE_SCHEMAS` - Get detailed schema for specific tables [Required]
+4. `SUPABASE_GENERATE_TYPE_SCRIPT_TYPES` - Generate TypeScript types from schema [Optional]
+
+**Key parameters for LIST_TABLES**:
+- `project_ref`: Project reference
+- `schemas`: Array of schema names to search (e.g., `["public"]`); omit for all non-system schemas
+- `include_views`: Include views alongside tables (default true)
+- `include_metadata`: Include row count estimates and sizes (default true)
+- `include_system_schemas`: Include pg_catalog, information_schema, etc. (default false)
+
+**Key parameters for GET_TABLE_SCHEMAS**:
+- `project_ref`: Project reference
+- `table_names`: Array of table names (max 20 per request); supports schema prefix like `public.users`, `auth.users`
+- `include_relationships`: Include foreign key info (default true)
+- `include_indexes`: Include index info (default true)
+- `exclude_null_values`: Cleaner output by hiding null fields (default true)
+
+**Key parameters for GENERATE_TYPE_SCRIPT_TYPES**:
+- `ref`: Project reference
+- `included_schemas`: Comma-separated schema names (default `"public"`)
+
+**Pitfalls**:
+- Table names without schema prefix assume `public` schema
+- `row_count` and `size_bytes` from LIST_TABLES may be null for views or recently created tables; treat as unknown, not zero
+- GET_TABLE_SCHEMAS has a max of 20 tables per request; batch if needed
+- TypeScript types include all tables in specified schemas; cannot filter individual tables
+
+### 4. Manage Edge Functions
+
+**When to use**: User wants to list, inspect, or work with Supabase Edge Functions
+
+**Tool sequence**:
+1. `SUPABASE_LIST_ALL_PROJECTS` - Find the project reference [Prerequisite]
+2. `SUPABASE_LIST_ALL_FUNCTIONS` - List all edge functions with metadata [Required]
+3. `SUPABASE_RETRIEVE_A_FUNCTION` - Get detailed info for a specific function [Optional]
+
+**Key parameters**:
+- `ref`: Project reference
+- Function slug for RETRIEVE_A_FUNCTION
+
+**Pitfalls**:
+- `LIST_ALL_FUNCTIONS` returns metadata only, not function code or logs
+- `created_at` and `updated_at` may be epoch milliseconds; convert to human-readable timestamps
+- These tools cannot create or deploy edge functions; they are read-only inspection tools
+- Permission errors may occur without org/project admin rights
+
+### 5. Manage Storage Buckets
+
+**When to use**: User wants to list storage buckets or manage file storage
+
+**Tool sequence**:
+1. `SUPABASE_LIST_ALL_PROJECTS` - Find the project reference [Prerequisite]
+2. `SUPABASE_LISTS_ALL_BUCKETS` - List all storage buckets [Required]
+
+**Key parameters**:
+- `ref`: Project reference
+
+**Pitfalls**:
+- `LISTS_ALL_BUCKETS` returns bucket list only, not bucket contents or access policies
+- For file uploads, `SUPABASE_RESUMABLE_UPLOAD_SIGN_OPTIONS_WITH_ID` handles CORS preflight for TUS resumable uploads only
+- Direct file operations may require using `proxy_execute` with the Supabase storage API
+
+## Common Patterns
+
+### ID Resolution
+- **Project reference**: `SUPABASE_LIST_ALL_PROJECTS` -- extract `ref` field (20 lowercase letters)
+- **Organization slug**: `SUPABASE_LIST_ALL_ORGANIZATIONS` -- use `slug` (not `id`) for downstream org tools
+- **Table names**: `SUPABASE_LIST_TABLES` -- enumerate available tables before querying
+- **Schema discovery**: `SUPABASE_GET_TABLE_SCHEMAS` -- inspect columns and constraints before writes
+
+### Pagination
+- `SUPABASE_SELECT_FROM_TABLE`: Uses `offset` + `limit` pagination. Increment offset by limit until fewer rows than limit are returned.
+- `SUPABASE_LIST_ALL_PROJECTS`: May paginate for large accounts; follow cursors/pages until exhausted.
+- `SUPABASE_LIST_TABLES`: May paginate for large databases.
+
+### SQL Best Practices
+- Always use `SUPABASE_GET_TABLE_SCHEMAS` or `SUPABASE_LIST_TABLES` before writing SQL
+- Use `read_only: true` for SELECT queries to prevent accidental mutations
+- Quote case-sensitive identifiers: `SELECT * FROM "MyTable"` not `SELECT * FROM MyTable`
+- Use PostgreSQL array syntax for array columns: `ARRAY['a', 'b']` not `['a', 'b']`
+- Break complex DDL into smaller statements to avoid timeouts
+
+## Known Pitfalls
+
+### ID Formats
+- Project references are exactly 20 lowercase letters (a-z): pattern `^[a-z]{20}$`
+- Organization identifiers come as both `id` (UUID) and `slug` (URL-friendly string); tools vary in which they accept
+- `LIST_MEMBERS_OF_AN_ORGANIZATION` requires `slug`, not `id`
+
+### SQL Execution
+- `BETA_RUN_SQL_QUERY` has ~60 second timeout for complex operations
+- PostgreSQL array syntax required: `ARRAY['item']` or `'{"item"}'`, NOT JSON syntax `'["item"]'`
+- Case-sensitive identifiers must be double-quoted in SQL
+- ERROR 42P01: relation does not exist (check quoting and schema prefix)
+- ERROR 42883: function does not exist (use information_schema instead of custom helpers)
+
+### Sensitive Data
+- `GET_PROJECT_API_KEYS` returns service-role keys -- NEVER expose full values
+- Auth config tools exclude secrets but may still contain sensitive configuration
+- Always mask or truncate API keys in output
+
+### Schema Metadata
+- `row_count` and `size_bytes` from `LIST_TABLES` can be null; do not treat as zero
+- System schemas are excluded by default; set `include_system_schemas: true` to see them
+- Views appear alongside tables unless `include_views: false`
+
+### Rate Limits and Permissions
+- Enrichment tools (API keys, configs) may return 401/403 without proper scopes; skip gracefully
+- Large table listings may require pagination
+- `GETS_PROJECT_S_SERVICE_HEALTH_STATUS` fails with empty `services` array -- always specify at least one
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List organizations | `SUPABASE_LIST_ALL_ORGANIZATIONS` | (none) |
+| Get org info | `SUPABASE_GETS_INFORMATION_ABOUT_THE_ORGANIZATION` | `slug` |
+| List org members | `SUPABASE_LIST_MEMBERS_OF_AN_ORGANIZATION` | `slug` |
+| List projects | `SUPABASE_LIST_ALL_PROJECTS` | (none) |
+| List tables | `SUPABASE_LIST_TABLES` | `project_ref`, `schemas` |
+| Get table schemas | `SUPABASE_GET_TABLE_SCHEMAS` | `project_ref`, `table_names` |
+| Query table | `SUPABASE_SELECT_FROM_TABLE` | `project_ref`, `table`, `select`, `filters` |
+| Run SQL | `SUPABASE_BETA_RUN_SQL_QUERY` | `ref`, `query`, `read_only` |
+| Generate TS types | `SUPABASE_GENERATE_TYPE_SCRIPT_TYPES` | `ref`, `included_schemas` |
+| Postgres config | `SUPABASE_GETS_PROJECT_S_POSTGRES_CONFIG` | `ref` |
+| Auth config | `SUPABASE_GETS_PROJECT_S_AUTH_CONFIG` | `ref` |
+| Get API keys | `SUPABASE_GET_PROJECT_API_KEYS` | `ref` |
+| Service health | `SUPABASE_GETS_PROJECT_S_SERVICE_HEALTH_STATUS` | `ref`, `services` |
+| List edge functions | `SUPABASE_LIST_ALL_FUNCTIONS` | `ref` |
+| Get edge function | `SUPABASE_RETRIEVE_A_FUNCTION` | `ref`, function slug |
+| List storage buckets | `SUPABASE_LISTS_ALL_BUCKETS` | `ref` |
+| List DB branches | `SUPABASE_LIST_ALL_DATABASE_BRANCHES` | `ref` |
diff --git a/telegram-automation/SKILL.md b/telegram-automation/SKILL.md
new file mode 100644
index 0000000..7854aeb
--- /dev/null
+++ b/telegram-automation/SKILL.md
@@ -0,0 +1,216 @@
+---
+name: telegram-automation
+description: Automate Telegram tasks via Rube MCP (Composio): send messages, manage chats, share photos/documents, and handle bot commands. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Telegram Automation via Rube MCP
+
+Automate Telegram operations through Composio's Telegram toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Telegram connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `telegram`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+- Telegram Bot Token required (created via @BotFather)
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `telegram`
+3. If connection is not ACTIVE, follow the returned auth link to configure the Telegram bot
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send Messages
+
+**When to use**: User wants to send text messages to a Telegram chat
+
+**Tool sequence**:
+1. `TELEGRAM_GET_ME` - Verify bot identity and connection [Prerequisite]
+2. `TELEGRAM_GET_CHAT` - Get chat details and verify access [Optional]
+3. `TELEGRAM_SEND_MESSAGE` - Send a text message [Required]
+
+**Key parameters**:
+- `chat_id`: Numeric chat ID or channel username (e.g., '@channelname')
+- `text`: Message text content
+- `parse_mode`: 'HTML' or 'MarkdownV2' for formatting
+- `disable_notification`: Send silently without notification sound
+- `reply_to_message_id`: Message ID to reply to
+
+**Pitfalls**:
+- Bot must be a member of the chat/group to send messages
+- MarkdownV2 requires escaping special characters: `_*[]()~>#+-=|{}.!`
+- HTML mode supports limited tags: ``, ``, ``, ``, ``
+- Messages have a 4096 character limit; split longer content
+
+### 2. Send Photos and Documents
+
+**When to use**: User wants to share images or files in a Telegram chat
+
+**Tool sequence**:
+1. `TELEGRAM_SEND_PHOTO` - Send an image [Optional]
+2. `TELEGRAM_SEND_DOCUMENT` - Send a file/document [Optional]
+
+**Key parameters**:
+- `chat_id`: Target chat ID
+- `photo`: Photo URL or file_id (for SEND_PHOTO)
+- `document`: Document URL or file_id (for SEND_DOCUMENT)
+- `caption`: Optional caption for the media
+
+**Pitfalls**:
+- Photo captions have a 1024 character limit
+- Document captions also have a 1024 character limit
+- Files up to 50MB can be sent via bot API
+- Photos are compressed by Telegram; use SEND_DOCUMENT for uncompressed images
+
+### 3. Manage Chats
+
+**When to use**: User wants to get chat information or manage chat settings
+
+**Tool sequence**:
+1. `TELEGRAM_GET_CHAT` - Get detailed chat information [Required]
+2. `TELEGRAM_GET_CHAT_ADMINISTRATORS` - List chat admins [Optional]
+3. `TELEGRAM_GET_CHAT_MEMBERS_COUNT` - Get member count [Optional]
+4. `TELEGRAM_EXPORT_CHAT_INVITE_LINK` - Generate invite link [Optional]
+
+**Key parameters**:
+- `chat_id`: Target chat ID or username
+
+**Pitfalls**:
+- Bot must be an administrator to export invite links
+- GET_CHAT returns different fields for private chats vs groups vs channels
+- Member count may be approximate for very large groups
+- Admin list does not include regular members
+
+### 4. Edit and Delete Messages
+
+**When to use**: User wants to modify or remove previously sent messages
+
+**Tool sequence**:
+1. `TELEGRAM_EDIT_MESSAGE` - Edit a sent message [Optional]
+2. `TELEGRAM_DELETE_MESSAGE` - Delete a message [Optional]
+
+**Key parameters**:
+- `chat_id`: Chat where the message is located
+- `message_id`: ID of the message to edit or delete
+- `text`: New text content (for edit)
+
+**Pitfalls**:
+- Bots can only edit their own messages
+- Messages can only be deleted within 48 hours of sending
+- In groups, bots with delete permissions can delete any message
+- Editing a message removes its 'edited' timestamp history
+
+### 5. Forward Messages and Get Updates
+
+**When to use**: User wants to forward messages or retrieve recent updates
+
+**Tool sequence**:
+1. `TELEGRAM_FORWARD_MESSAGE` - Forward a message to another chat [Optional]
+2. `TELEGRAM_GET_UPDATES` - Get recent bot updates/messages [Optional]
+3. `TELEGRAM_GET_CHAT_HISTORY` - Get chat message history [Optional]
+
+**Key parameters**:
+- `from_chat_id`: Source chat for forwarding
+- `chat_id`: Destination chat for forwarding
+- `message_id`: Message to forward
+- `offset`: Update offset for GET_UPDATES
+- `limit`: Number of updates to retrieve
+
+**Pitfalls**:
+- Forwarded messages show the original sender attribution
+- GET_UPDATES returns a limited window of recent updates
+- Chat history access may be limited by bot permissions and chat type
+- Use offset to avoid processing the same update twice
+
+### 6. Manage Bot Commands
+
+**When to use**: User wants to set or update bot command menu
+
+**Tool sequence**:
+1. `TELEGRAM_SET_MY_COMMANDS` - Set the bot's command list [Required]
+2. `TELEGRAM_ANSWER_CALLBACK_QUERY` - Respond to inline button presses [Optional]
+
+**Key parameters**:
+- `commands`: Array of command objects with `command` and `description`
+- `callback_query_id`: ID of the callback query to answer
+
+**Pitfalls**:
+- Commands must start with '/' and be lowercase
+- Command descriptions have a 256 character limit
+- Callback queries must be answered within 10 seconds or they expire
+- Setting commands replaces the entire command list
+
+## Common Patterns
+
+### Chat ID Resolution
+
+**From username**:
+```
+1. Use '@username' format as chat_id (for public channels/groups)
+2. For private chats, numeric chat_id is required
+3. Call GET_CHAT with username to retrieve numeric ID
+```
+
+**From GET_UPDATES**:
+```
+1. Call TELEGRAM_GET_UPDATES
+2. Extract chat.id from message objects
+3. Use numeric chat_id in subsequent calls
+```
+
+### Message Formatting
+
+- Use `parse_mode: 'HTML'` for `bold`, `italic`, `code`
+- Use `parse_mode: 'MarkdownV2'` for `*bold*`, `_italic_`, `` `code` ``
+- Escape special chars in MarkdownV2: `_ * [ ] ( ) ~ > # + - = | { } . !`
+- Omit parse_mode for plain text without formatting
+
+## Known Pitfalls
+
+**Bot Permissions**:
+- Bots must be added to groups/channels to interact
+- Admin permissions needed for: deleting messages, exporting invite links, managing members
+- Bots cannot initiate conversations; users must start them first
+
+**Rate Limits**:
+- 30 messages per second to the same group
+- 20 messages per minute to the same user in groups
+- Bulk operations should implement delays between calls
+- API returns 429 Too Many Requests when limits are hit
+
+**Chat Types**:
+- Private chat: One-on-one with the bot
+- Group: Multi-user chat (bot must be added)
+- Supergroup: Enhanced group with admin features
+- Channel: Broadcast-only (bot must be admin to post)
+
+**Message Limits**:
+- Text messages: 4096 characters max
+- Captions: 1024 characters max
+- File uploads: 50MB max via bot API
+- Inline keyboard buttons: 8 per row
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Verify bot | TELEGRAM_GET_ME | (none) |
+| Send message | TELEGRAM_SEND_MESSAGE | chat_id, text, parse_mode |
+| Send photo | TELEGRAM_SEND_PHOTO | chat_id, photo, caption |
+| Send document | TELEGRAM_SEND_DOCUMENT | chat_id, document, caption |
+| Edit message | TELEGRAM_EDIT_MESSAGE | chat_id, message_id, text |
+| Delete message | TELEGRAM_DELETE_MESSAGE | chat_id, message_id |
+| Forward message | TELEGRAM_FORWARD_MESSAGE | chat_id, from_chat_id, message_id |
+| Get chat info | TELEGRAM_GET_CHAT | chat_id |
+| Get chat admins | TELEGRAM_GET_CHAT_ADMINISTRATORS | chat_id |
+| Get member count | TELEGRAM_GET_CHAT_MEMBERS_COUNT | chat_id |
+| Export invite link | TELEGRAM_EXPORT_CHAT_INVITE_LINK | chat_id |
+| Get updates | TELEGRAM_GET_UPDATES | offset, limit |
+| Get chat history | TELEGRAM_GET_CHAT_HISTORY | chat_id |
+| Set bot commands | TELEGRAM_SET_MY_COMMANDS | commands |
+| Answer callback | TELEGRAM_ANSWER_CALLBACK_QUERY | callback_query_id |
diff --git a/tiktok-automation/SKILL.md b/tiktok-automation/SKILL.md
new file mode 100644
index 0000000..6dc457a
--- /dev/null
+++ b/tiktok-automation/SKILL.md
@@ -0,0 +1,175 @@
+---
+name: tiktok-automation
+description: Automate TikTok tasks via Rube MCP (Composio): upload/publish videos, post photos, manage content, and view user profiles/stats. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# TikTok Automation via Rube MCP
+
+Automate TikTok content creation and profile operations through Composio's TikTok toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active TikTok connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `tiktok`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `tiktok`
+3. If connection is not ACTIVE, follow the returned auth link to complete TikTok OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Upload and Publish a Video
+
+**When to use**: User wants to upload a video and publish it to TikTok
+
+**Tool sequence**:
+1. `TIKTOK_UPLOAD_VIDEO` or `TIKTOK_UPLOAD_VIDEOS` - Upload video file(s) [Required]
+2. `TIKTOK_FETCH_PUBLISH_STATUS` - Check upload/processing status [Required]
+3. `TIKTOK_PUBLISH_VIDEO` - Publish the uploaded video [Required]
+
+**Key parameters for upload**:
+- `video`: Video file object with `s3key`, `mimetype`, `name`
+- `title`: Video title/caption
+
+**Key parameters for publish**:
+- `publish_id`: ID returned from upload step
+- `title`: Video caption text
+- `privacy_level`: 'PUBLIC_TO_EVERYONE', 'MUTUAL_FOLLOW_FRIENDS', 'FOLLOWER_OF_CREATOR', 'SELF_ONLY'
+- `disable_duet`: Disable duet feature
+- `disable_stitch`: Disable stitch feature
+- `disable_comment`: Disable comments
+
+**Pitfalls**:
+- Video upload and publish are TWO separate steps; upload first, then publish
+- After upload, poll FETCH_PUBLISH_STATUS until processing is complete before publishing
+- Video must meet TikTok requirements: MP4/WebM format, max 10 minutes, max 4GB
+- Caption/title has character limits; check current TikTok guidelines
+- Privacy level strings are case-sensitive and must match exactly
+- Processing may take 30-120 seconds depending on video size
+
+### 2. Post a Photo
+
+**When to use**: User wants to post a photo to TikTok
+
+**Tool sequence**:
+1. `TIKTOK_POST_PHOTO` - Upload and post a photo [Required]
+2. `TIKTOK_FETCH_PUBLISH_STATUS` - Check processing status [Optional]
+
+**Key parameters**:
+- `photo`: Photo file object with `s3key`, `mimetype`, `name`
+- `title`: Photo caption text
+- `privacy_level`: Privacy setting for the post
+
+**Pitfalls**:
+- Photo posts are a newer TikTok feature; availability may vary by account type
+- Supported formats: JPEG, PNG, WebP
+- Image size and dimension limits apply; check current TikTok guidelines
+
+### 3. List and Manage Videos
+
+**When to use**: User wants to view their published videos
+
+**Tool sequence**:
+1. `TIKTOK_LIST_VIDEOS` - List user's published videos [Required]
+
+**Key parameters**:
+- `max_count`: Number of videos to return per page
+- `cursor`: Pagination cursor for next page
+
+**Pitfalls**:
+- Only returns the authenticated user's own videos
+- Response includes video metadata: id, title, create_time, share_url, duration, etc.
+- Pagination uses cursor-based approach; check for `has_more` and `cursor` in response
+- Recently published videos may not appear immediately in the list
+
+### 4. View User Profile and Stats
+
+**When to use**: User wants to check their TikTok profile info or account statistics
+
+**Tool sequence**:
+1. `TIKTOK_GET_USER_PROFILE` - Get full profile information [Required]
+2. `TIKTOK_GET_USER_STATS` - Get account statistics [Optional]
+3. `TIKTOK_GET_USER_BASIC_INFO` - Get basic user info [Alternative]
+
+**Key parameters**: (no required parameters; returns data for authenticated user)
+
+**Pitfalls**:
+- Profile data is for the authenticated user only; cannot view other users' profiles
+- Stats include follower count, following count, video count, likes received
+- `GET_USER_PROFILE` returns more details than `GET_USER_BASIC_INFO`
+- Stats may have slight delays; not real-time
+
+### 5. Check Publish Status
+
+**When to use**: User wants to check the status of a content upload or publish operation
+
+**Tool sequence**:
+1. `TIKTOK_FETCH_PUBLISH_STATUS` - Poll for status updates [Required]
+
+**Key parameters**:
+- `publish_id`: The publish ID from a previous upload/publish operation
+
+**Pitfalls**:
+- Status values include processing, success, and failure states
+- Poll at reasonable intervals (5-10 seconds) to avoid rate limits
+- Failed publishes include error details in the response
+- Content moderation may cause delays or rejections after processing
+
+## Common Patterns
+
+### Video Publish Flow
+
+```
+1. Upload video via TIKTOK_UPLOAD_VIDEO -> get publish_id
+2. Poll TIKTOK_FETCH_PUBLISH_STATUS with publish_id until complete
+3. If status is ready, call TIKTOK_PUBLISH_VIDEO with final settings
+4. Optionally poll status again to confirm publication
+```
+
+### Pagination
+
+- Use `cursor` from previous response for next page
+- Check `has_more` boolean to determine if more results exist
+- `max_count` controls page size
+
+## Known Pitfalls
+
+**Content Requirements**:
+- Videos: MP4/WebM, max 4GB, max 10 minutes
+- Photos: JPEG/PNG/WebP
+- Captions: Character limits vary by region
+- Content must comply with TikTok community guidelines
+
+**Authentication**:
+- OAuth tokens have scopes; ensure video.upload and video.publish are authorized
+- Tokens expire; re-authenticate if operations fail with 401
+
+**Rate Limits**:
+- TikTok API has strict rate limits per application
+- Implement exponential backoff on 429 responses
+- Upload operations have daily limits
+
+**Response Parsing**:
+- Response data may be nested under `data` or `data.data`
+- Parse defensively with fallback patterns
+- Publish IDs are strings; use exactly as returned
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Upload video | TIKTOK_UPLOAD_VIDEO | video, title |
+| Upload multiple videos | TIKTOK_UPLOAD_VIDEOS | videos |
+| Publish video | TIKTOK_PUBLISH_VIDEO | publish_id, title, privacy_level |
+| Post photo | TIKTOK_POST_PHOTO | photo, title, privacy_level |
+| List videos | TIKTOK_LIST_VIDEOS | max_count, cursor |
+| Get profile | TIKTOK_GET_USER_PROFILE | (none) |
+| Get user stats | TIKTOK_GET_USER_STATS | (none) |
+| Get basic info | TIKTOK_GET_USER_BASIC_INFO | (none) |
+| Check publish status | TIKTOK_FETCH_PUBLISH_STATUS | publish_id |
diff --git a/todoist-automation/SKILL.md b/todoist-automation/SKILL.md
new file mode 100644
index 0000000..e0260f7
--- /dev/null
+++ b/todoist-automation/SKILL.md
@@ -0,0 +1,228 @@
+---
+name: todoist-automation
+description: Automate Todoist task management, projects, sections, filtering, and bulk operations via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Todoist Automation via Rube MCP
+
+Automate Todoist operations including task creation and management, project organization, section management, filtering, and bulk task workflows through Composio's Todoist toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Todoist connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `todoist`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `todoist`
+3. If connection is not ACTIVE, follow the returned auth link to complete Todoist OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Tasks
+
+**When to use**: User wants to create, update, complete, reopen, or delete tasks
+
+**Tool sequence**:
+1. `TODOIST_GET_ALL_PROJECTS` - List projects to find the target project ID [Prerequisite]
+2. `TODOIST_GET_ALL_SECTIONS` - List sections within a project for task placement [Optional]
+3. `TODOIST_CREATE_TASK` - Create a single task with content, due date, priority, labels [Required]
+4. `TODOIST_BULK_CREATE_TASKS` - Create multiple tasks in one request [Alternative]
+5. `TODOIST_UPDATE_TASK` - Modify task properties (content, due date, priority, labels) [Optional]
+6. `TODOIST_CLOSE_TASK` - Mark a task as completed [Optional]
+7. `TODOIST_REOPEN_TASK` - Restore a previously completed task [Optional]
+8. `TODOIST_DELETE_TASK` - Permanently remove a task [Optional]
+
+**Key parameters for CREATE_TASK**:
+- `content`: Task title (supports markdown and hyperlinks)
+- `description`: Additional notes (do NOT put due dates here)
+- `project_id`: Alphanumeric project ID; omit to add to Inbox
+- `section_id`: Alphanumeric section ID for placement within a project
+- `parent_id`: Task ID for creating subtasks
+- `priority`: 1 (normal) to 4 (urgent) -- note: Todoist UI shows p1=urgent, API p4=urgent
+- `due_string`: Natural language date like `"tomorrow at 3pm"`, `"every Friday at 9am"`
+- `due_date`: Specific date `YYYY-MM-DD` format
+- `due_datetime`: Specific date+time in RFC3339 `YYYY-MM-DDTHH:mm:ssZ`
+- `labels`: Array of label name strings
+- `duration` + `duration_unit`: Task duration (e.g., `30` + `"minute"`)
+
+**Pitfalls**:
+- Only one `due_*` field can be used at a time (except `due_lang` which can accompany any)
+- Do NOT embed due dates in `content` or `description` -- use `due_string` field
+- Do NOT embed duration phrases like "for 30 minutes" in `due_string` -- use `duration` + `duration_unit`
+- `priority` in API: 1=normal, 4=urgent (opposite of Todoist UI display where p1=urgent)
+- Task IDs can be numeric or alphanumeric; use the format returned by the API
+- `CLOSE_TASK` marks complete; `DELETE_TASK` permanently removes -- they are different operations
+
+### 2. Manage Projects
+
+**When to use**: User wants to list, create, update, or inspect projects
+
+**Tool sequence**:
+1. `TODOIST_GET_ALL_PROJECTS` - List all projects with metadata [Required]
+2. `TODOIST_GET_PROJECT` - Get details for a specific project by ID [Optional]
+3. `TODOIST_CREATE_PROJECT` - Create a new project with name, color, view style [Optional]
+4. `TODOIST_UPDATE_PROJECT` - Modify project properties [Optional]
+
+**Key parameters**:
+- `name`: Project name (required for creation)
+- `color`: Todoist palette color (e.g., `"blue"`, `"red"`, `"green"`, `"charcoal"`)
+- `view_style`: `"list"` or `"board"` layout
+- `parent_id`: Parent project ID for creating sub-projects
+- `is_favorite` / `favorite`: Boolean to mark as favorite
+- `project_id`: Required for update and get operations
+
+**Pitfalls**:
+- Projects with similar names can lead to selecting the wrong project_id; always verify
+- `CREATE_PROJECT` uses `favorite` while `UPDATE_PROJECT` uses `is_favorite` -- different field names
+- Use the project `id` returned by API, not the `v2_id`, for downstream operations
+- Alphanumeric/URL-style project IDs may cause HTTP 400 in some tools; use numeric ID if available
+
+### 3. Manage Sections
+
+**When to use**: User wants to organize tasks within projects using sections
+
+**Tool sequence**:
+1. `TODOIST_GET_ALL_PROJECTS` - Find the target project ID [Prerequisite]
+2. `TODOIST_GET_ALL_SECTIONS` - List existing sections to avoid duplicates [Prerequisite]
+3. `TODOIST_CREATE_SECTION` - Create a new section in a project [Required]
+4. `TODOIST_UPDATE_SECTION` - Rename an existing section [Optional]
+5. `TODOIST_DELETE_SECTION` - Permanently remove a section [Optional]
+
+**Key parameters**:
+- `project_id`: Required -- the project to create the section in
+- `name`: Section name (required for creation)
+- `order`: Integer position within the project (lower values appear first)
+- `section_id`: Required for update and delete operations
+
+**Pitfalls**:
+- `CREATE_SECTION` requires `project_id` and `name` -- omitting project_id causes a 400 error
+- HTTP 400 "project_id is invalid" can occur if alphanumeric ID is used; prefer numeric ID
+- Deleting a section may move or regroup its tasks in non-obvious ways
+- Response may include both `id` and `v2_id`; store and reuse the correct identifier consistently
+- Always check existing sections first to avoid creating duplicates
+
+### 4. Search and Filter Tasks
+
+**When to use**: User wants to find tasks by criteria, view today's tasks, or get completed task history
+
+**Tool sequence**:
+1. `TODOIST_GET_ALL_TASKS` - Fetch incomplete tasks with optional filter query [Required]
+2. `TODOIST_GET_TASK` - Get full details of a specific task by ID [Optional]
+3. `TODOIST_GET_COMPLETED_TASKS_BY_COMPLETION_DATE` - Retrieve completed tasks within a date range [Optional]
+4. `TODOIST_LIST_FILTERS` - List user's custom saved filters [Optional]
+
+**Key parameters for GET_ALL_TASKS**:
+- `filter`: Todoist filter syntax string
+ - Keywords: `today`, `tomorrow`, `overdue`, `no date`, `recurring`, `subtask`
+ - Priority: `p1` (urgent), `p2`, `p3`, `p4` (normal)
+ - Projects: `#ProjectName` (must exist in account)
+ - Labels: `@LabelName` (must exist in account)
+ - Date ranges: `7 days`, `-7 days`, `due before: YYYY-MM-DD`, `due after: YYYY-MM-DD`
+ - Search: `search: keyword` for content text search
+ - Operators: `&` (AND), `|` (OR), `!` (NOT)
+- `ids`: List of specific task IDs to retrieve
+
+**Key parameters for GET_COMPLETED_TASKS_BY_COMPLETION_DATE**:
+- `since`: Start date in RFC3339 format (e.g., `2024-01-01T00:00:00Z`)
+- `until`: End date in RFC3339 format
+- `project_id`, `section_id`, `parent_id`: Optional filters
+- `cursor`: Pagination cursor from previous response
+- `limit`: Max results per page (default 50)
+
+**Pitfalls**:
+- `GET_ALL_TASKS` returns ONLY incomplete tasks; use `GET_COMPLETED_TASKS_BY_COMPLETION_DATE` for completed ones
+- Filter terms must reference ACTUAL EXISTING entities; arbitrary text causes HTTP 400 errors
+- Do NOT use `completed`, `!completed`, or `completed after` in GET_ALL_TASKS filter -- causes 400 error
+- `GET_COMPLETED_TASKS_BY_COMPLETION_DATE` limits date range to approximately 3 months between `since` and `until`
+- Search uses `search: keyword` syntax within the filter, not a separate parameter
+
+### 5. Bulk Task Creation
+
+**When to use**: User wants to scaffold a project with multiple tasks at once
+
+**Tool sequence**:
+1. `TODOIST_GET_ALL_PROJECTS` - Find target project ID [Prerequisite]
+2. `TODOIST_GET_ALL_SECTIONS` - Find section IDs for task placement [Optional]
+3. `TODOIST_BULK_CREATE_TASKS` - Create multiple tasks in a single request [Required]
+
+**Key parameters**:
+- `tasks`: Array of task objects, each requiring at minimum `content`
+- Each task object supports: `content`, `description`, `project_id`, `section_id`, `parent_id`, `priority`, `labels`, `due` (object with `string`, `date`, or `datetime`), `duration`, `order`
+
+**Pitfalls**:
+- Each task in the array must have at least the `content` field
+- The `due` field in bulk create is an object with nested fields (`string`, `date`, `datetime`, `lang`) -- different structure from CREATE_TASK's flat fields
+- All tasks can target different projects/sections within the same batch
+
+## Common Patterns
+
+### ID Resolution
+Always resolve human-readable names to IDs before operations:
+- **Project name -> Project ID**: `TODOIST_GET_ALL_PROJECTS`, match by `name` field
+- **Section name -> Section ID**: `TODOIST_GET_ALL_SECTIONS` with `project_id`
+- **Task content -> Task ID**: `TODOIST_GET_ALL_TASKS` with `filter` or `search: keyword`
+
+### Pagination
+- `TODOIST_GET_ALL_TASKS`: Returns all matching incomplete tasks (no pagination needed)
+- `TODOIST_GET_COMPLETED_TASKS_BY_COMPLETION_DATE`: Uses cursor-based pagination; follow `cursor` from response until no more results
+- `TODOIST_GET_ALL_PROJECTS` and `TODOIST_GET_ALL_SECTIONS`: Return all results (no pagination)
+
+### Due Date Handling
+- Natural language: Use `due_string` (e.g., `"tomorrow at 3pm"`, `"every Monday"`)
+- Specific date: Use `due_date` in `YYYY-MM-DD` format
+- Specific datetime: Use `due_datetime` in RFC3339 format (`YYYY-MM-DDTHH:mm:ssZ`)
+- Only use ONE due field at a time (except `due_lang` which can accompany any)
+- Recurring tasks: Use natural language in `due_string` (e.g., `"every Friday at 9am"`)
+
+## Known Pitfalls
+
+### ID Formats
+- Task IDs can be numeric (`"2995104339"`) or alphanumeric (`"6X4Vw2Hfmg73Q2XR"`)
+- Project IDs similarly vary; prefer the format returned by the API
+- Some tools accept only numeric IDs; if 400 error occurs, try fetching the numeric `id` via GET_PROJECT
+- Response objects may contain both `id` and `v2_id`; use `id` for API operations
+
+### Priority Inversion
+- API priority: 1 = normal, 4 = urgent
+- Todoist UI display: p1 = urgent, p4 = normal
+- This is inverted; always clarify with the user which convention they mean
+
+### Filter Syntax
+- Filter terms must reference real entities in the user's account
+- `#NonExistentProject` or `@NonExistentLabel` will cause HTTP 400
+- Use `search: keyword` for text search, not bare keywords
+- Combine with `&` (AND), `|` (OR), `!` (NOT)
+- `completed` filters do NOT work on GET_ALL_TASKS endpoint
+
+### Rate Limits
+- Todoist API has rate limits; batch operations should use `BULK_CREATE_TASKS` where possible
+- Space out rapid sequential requests to avoid throttling
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List all projects | `TODOIST_GET_ALL_PROJECTS` | (none) |
+| Get project | `TODOIST_GET_PROJECT` | `project_id` |
+| Create project | `TODOIST_CREATE_PROJECT` | `name`, `color`, `view_style` |
+| Update project | `TODOIST_UPDATE_PROJECT` | `project_id`, `name`, `color` |
+| List sections | `TODOIST_GET_ALL_SECTIONS` | `project_id` |
+| Create section | `TODOIST_CREATE_SECTION` | `project_id`, `name`, `order` |
+| Update section | `TODOIST_UPDATE_SECTION` | `section_id`, `name` |
+| Delete section | `TODOIST_DELETE_SECTION` | `section_id` |
+| Get all tasks | `TODOIST_GET_ALL_TASKS` | `filter`, `ids` |
+| Get task | `TODOIST_GET_TASK` | `task_id` |
+| Create task | `TODOIST_CREATE_TASK` | `content`, `project_id`, `due_string`, `priority` |
+| Bulk create tasks | `TODOIST_BULK_CREATE_TASKS` | `tasks` (array) |
+| Update task | `TODOIST_UPDATE_TASK` | `task_id`, `content`, `due_string` |
+| Complete task | `TODOIST_CLOSE_TASK` | `task_id` |
+| Reopen task | `TODOIST_REOPEN_TASK` | `task_id` |
+| Delete task | `TODOIST_DELETE_TASK` | `task_id` |
+| Completed tasks | `TODOIST_GET_COMPLETED_TASKS_BY_COMPLETION_DATE` | `since`, `until` |
+| List filters | `TODOIST_LIST_FILTERS` | `sync_token` |
diff --git a/trello-automation/SKILL.md b/trello-automation/SKILL.md
new file mode 100644
index 0000000..2cf2945
--- /dev/null
+++ b/trello-automation/SKILL.md
@@ -0,0 +1,178 @@
+---
+name: trello-automation
+description: Automate Trello boards, cards, and workflows via Rube MCP (Composio). Create cards, manage lists, assign members, and search across boards programmatically.
+requires:
+ mcp: [rube]
+---
+
+# Trello Automation via Rube MCP
+
+Automate Trello board management, card creation, and team workflows through Composio's Rube MCP integration.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Trello connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `trello`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `trello`
+3. If connection is not ACTIVE, follow the returned auth link to complete Trello auth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create a Card on a Board
+
+**When to use**: User wants to add a new card/task to a Trello board
+
+**Tool sequence**:
+1. `TRELLO_GET_MEMBERS_BOARDS_BY_ID_MEMBER` - List boards to find target board ID [Prerequisite]
+2. `TRELLO_GET_BOARDS_LISTS_BY_ID_BOARD` - Get lists on board to find target list ID [Prerequisite]
+3. `TRELLO_ADD_CARDS` - Create the card on the resolved list [Required]
+4. `TRELLO_ADD_CARDS_CHECKLISTS_BY_ID_CARD` - Add a checklist to the card [Optional]
+5. `TRELLO_ADD_CARDS_CHECKLIST_CHECK_ITEM_BY_ID_CARD_BY_ID_CHECKLIST` - Add items to the checklist [Optional]
+
+**Key parameters**:
+- `idList`: 24-char hex ID (NOT list name)
+- `name`: Card title
+- `desc`: Card description (supports Markdown)
+- `pos`: Position ('top'/'bottom')
+- `due`: Due date (ISO 8601 format)
+
+**Pitfalls**:
+- Store returned id (idCard) immediately; downstream checklist operations fail without it
+- Checklist payload may be nested (data.data); extract idChecklist from inner object
+- One API call per checklist item; large checklists can trigger rate limits
+
+### 2. Manage Boards and Lists
+
+**When to use**: User wants to view, browse, or restructure board layout
+
+**Tool sequence**:
+1. `TRELLO_GET_MEMBERS_BOARDS_BY_ID_MEMBER` - List all boards for the user [Required]
+2. `TRELLO_GET_BOARDS_BY_ID_BOARD` - Get detailed board info [Required]
+3. `TRELLO_GET_BOARDS_LISTS_BY_ID_BOARD` - Get lists (columns) on the board [Optional]
+4. `TRELLO_GET_BOARDS_MEMBERS_BY_ID_BOARD` - Get board members [Optional]
+5. `TRELLO_GET_BOARDS_LABELS_BY_ID_BOARD` - Get labels on the board [Optional]
+
+**Key parameters**:
+- `idMember`: Use 'me' for authenticated user
+- `filter`: 'open', 'starred', or 'all'
+- `idBoard`: 24-char hex or 8-char shortLink (NOT board name)
+
+**Pitfalls**:
+- Some runs return boards under response.data.details[]—don't assume flat top-level array
+- Lists may be nested under results[0].response.data.details—parse defensively
+- ISO 8601 timestamps with trailing 'Z' must be parsed as timezone-aware
+
+### 3. Move Cards Between Lists
+
+**When to use**: User wants to change a card's status by moving it to another list
+
+**Tool sequence**:
+1. `TRELLO_GET_SEARCH` - Find the card by name or keyword [Prerequisite]
+2. `TRELLO_GET_BOARDS_LISTS_BY_ID_BOARD` - Get destination list ID [Prerequisite]
+3. `TRELLO_UPDATE_CARDS_BY_ID_CARD` - Update card's idList to move it [Required]
+
+**Key parameters**:
+- `idCard`: Card ID from search
+- `idList`: Destination list ID
+- `pos`: Optional ordering within new list
+
+**Pitfalls**:
+- Search returns partial matches; verify card name before updating
+- Moving doesn't update position within new list; set pos if ordering matters
+
+### 4. Assign Members to Cards
+
+**When to use**: User wants to assign team members to cards
+
+**Tool sequence**:
+1. `TRELLO_GET_BOARDS_MEMBERS_BY_ID_BOARD` - Get member IDs from the board [Prerequisite]
+2. `TRELLO_ADD_CARDS_ID_MEMBERS_BY_ID_CARD` - Add a member to the card [Required]
+
+**Key parameters**:
+- `idCard`: Target card ID
+- `value`: Member ID to assign
+
+**Pitfalls**:
+- UPDATE_CARDS_ID_MEMBERS replaces entire member list; use ADD_CARDS_ID_MEMBERS to append
+- Member must have board permissions
+
+### 5. Search and Filter Cards
+
+**When to use**: User wants to find specific cards across boards
+
+**Tool sequence**:
+1. `TRELLO_GET_SEARCH` - Search by query string [Required]
+
+**Key parameters**:
+- `query`: Search string (supports board:, list:, label:, is:open/archived operators)
+- `modelTypes`: Set to 'cards'
+- `partial`: Set to 'true' for prefix matching
+
+**Pitfalls**:
+- Search indexing has delay; newly created cards may not appear for several minutes
+- For exact name matching, use TRELLO_GET_BOARDS_CARDS_BY_ID_BOARD and filter locally
+- Query uses word tokenization; common words may be ignored as stop words
+
+### 6. Add Comments and Attachments
+
+**When to use**: User wants to add context to an existing card
+
+**Tool sequence**:
+1. `TRELLO_ADD_CARDS_ACTIONS_COMMENTS_BY_ID_CARD` - Post a comment on the card [Required]
+2. `TRELLO_ADD_CARDS_ATTACHMENTS_BY_ID_CARD` - Attach a file or URL [Optional]
+
+**Key parameters**:
+- `text`: Comment text (1-16384 chars, supports Markdown and @mentions)
+- `url` OR `file`: Attachment source (not both)
+- `name`: Attachment display name
+- `mimeType`: File MIME type
+
+**Pitfalls**:
+- Comments don't support file attachments; use the attachment tool separately
+- Attachment deletion is irreversible
+
+## Common Patterns
+
+### ID Resolution
+Always resolve display names to IDs before operations:
+- **Board name → Board ID**: `TRELLO_GET_MEMBERS_BOARDS_BY_ID_MEMBER` with idMember='me'
+- **List name → List ID**: `TRELLO_GET_BOARDS_LISTS_BY_ID_BOARD` with resolved board ID
+- **Card name → Card ID**: `TRELLO_GET_SEARCH` with query string
+- **Member name → Member ID**: `TRELLO_GET_BOARDS_MEMBERS_BY_ID_BOARD`
+
+### Pagination
+Most list endpoints return all items. For boards with 1000+ cards, use `limit` and `before` parameters on card listing endpoints.
+
+### Rate Limits
+300 requests per 10 seconds per token. Use `TRELLO_GET_BATCH` for bulk read operations to stay within limits.
+
+## Known Pitfalls
+
+- **ID Requirements**: Nearly every tool requires IDs, not display names. Always resolve names to IDs first.
+- **Board ID Format**: Board IDs must be 24-char hex or 8-char shortLink. URL slugs like 'my-board' are NOT valid.
+- **Search Delays**: Search indexing has delays; newly created/updated cards may not appear immediately.
+- **Nested Responses**: Response data is often nested (data.data or data.details[]); parse defensively.
+- **Rate Limiting**: 300 req/10s per token. Batch reads with TRELLO_GET_BATCH.
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List user's boards | TRELLO_GET_MEMBERS_BOARDS_BY_ID_MEMBER | idMember='me', filter='open' |
+| Get board details | TRELLO_GET_BOARDS_BY_ID_BOARD | idBoard (24-char hex) |
+| List board lists | TRELLO_GET_BOARDS_LISTS_BY_ID_BOARD | idBoard |
+| Create card | TRELLO_ADD_CARDS | idList, name, desc, pos, due |
+| Update card | TRELLO_UPDATE_CARDS_BY_ID_CARD | idCard, idList (to move) |
+| Search cards | TRELLO_GET_SEARCH | query, modelTypes='cards' |
+| Add checklist | TRELLO_ADD_CARDS_CHECKLISTS_BY_ID_CARD | idCard, name |
+| Add comment | TRELLO_ADD_CARDS_ACTIONS_COMMENTS_BY_ID_CARD | idCard, text |
+| Assign member | TRELLO_ADD_CARDS_ID_MEMBERS_BY_ID_CARD | idCard, value (member ID) |
+| Attach file/URL | TRELLO_ADD_CARDS_ATTACHMENTS_BY_ID_CARD | idCard, url OR file |
+| Get board members | TRELLO_GET_BOARDS_MEMBERS_BY_ID_BOARD | idBoard |
+| Batch read | TRELLO_GET_BATCH | urls (comma-separated paths) |
\ No newline at end of file
diff --git a/twitter-automation/SKILL.md b/twitter-automation/SKILL.md
new file mode 100644
index 0000000..8adc2c3
--- /dev/null
+++ b/twitter-automation/SKILL.md
@@ -0,0 +1,228 @@
+---
+name: twitter-automation
+description: Automate Twitter/X tasks via Rube MCP (Composio): posts, search, users, bookmarks, lists, media. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Twitter/X Automation via Rube MCP
+
+Automate Twitter/X operations through Composio's Twitter toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Twitter connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `twitter`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `twitter`
+3. If connection is not ACTIVE, follow the returned auth link to complete Twitter OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Posts
+
+**When to use**: User wants to create, delete, or look up tweets/posts
+
+**Tool sequence**:
+1. `TWITTER_USER_LOOKUP_ME` - Get authenticated user info [Prerequisite]
+2. `TWITTER_UPLOAD_MEDIA` / `TWITTER_UPLOAD_LARGE_MEDIA` - Upload media [Optional]
+3. `TWITTER_CREATION_OF_A_POST` - Create a new post [Required]
+4. `TWITTER_POST_LOOKUP_BY_POST_ID` - Look up a specific post [Optional]
+5. `TWITTER_POST_DELETE_BY_POST_ID` - Delete a post [Optional]
+
+**Key parameters**:
+- `text`: Post text content (max 280 weighted characters)
+- `media__media_ids`: Array of media ID strings for attachments
+- `reply__in_reply_to_tweet_id`: Tweet ID to reply to
+- `quote_tweet_id`: Tweet ID to quote
+- `id`: Post ID for lookup/delete
+
+**Pitfalls**:
+- Post text is limited to 280 weighted characters; some characters count as more than one
+- Posting is NOT idempotent; retrying on timeout will create duplicate posts
+- Media IDs must be numeric strings, not integers
+- UPLOAD_LARGE_MEDIA is for videos/GIFs; UPLOAD_MEDIA for images
+- Always call USER_LOOKUP_ME first to get the authenticated user's ID
+
+### 2. Search Posts
+
+**When to use**: User wants to find tweets matching specific criteria
+
+**Tool sequence**:
+1. `TWITTER_RECENT_SEARCH` - Search recent tweets (last 7 days) [Required]
+2. `TWITTER_FULL_ARCHIVE_SEARCH` - Search full archive (Academic access) [Optional]
+3. `TWITTER_RECENT_SEARCH_COUNTS` - Get tweet count matching query [Optional]
+
+**Key parameters**:
+- `query`: Search query using Twitter search operators
+- `max_results`: Results per page (10-100)
+- `next_token`: Pagination token
+- `start_time`/`end_time`: ISO 8601 time range
+- `tweet__fields`: Comma-separated fields to include
+- `expansions`: Related objects to expand
+
+**Pitfalls**:
+- RECENT_SEARCH covers only the last 7 days; use FULL_ARCHIVE_SEARCH for older tweets
+- FULL_ARCHIVE_SEARCH requires Academic Research or Enterprise access
+- Query operators: `from:username`, `to:username`, `is:retweet`, `has:media`, `-is:retweet`
+- Empty results return `meta.result_count: 0` with no `data` field
+- Rate limits vary by endpoint and access level; check response headers
+
+### 3. Look Up Users
+
+**When to use**: User wants to find or inspect Twitter user profiles
+
+**Tool sequence**:
+1. `TWITTER_USER_LOOKUP_ME` - Get authenticated user [Optional]
+2. `TWITTER_USER_LOOKUP_BY_USERNAME` - Look up by username [Optional]
+3. `TWITTER_USER_LOOKUP_BY_ID` - Look up by user ID [Optional]
+4. `TWITTER_USER_LOOKUP_BY_IDS` - Batch look up multiple users [Optional]
+
+**Key parameters**:
+- `username`: Twitter handle without @ prefix
+- `id`: Numeric user ID string
+- `ids`: Comma-separated user IDs for batch lookup
+- `user__fields`: Fields to return (description, public_metrics, etc.)
+
+**Pitfalls**:
+- Usernames are case-insensitive but must not include the @ prefix
+- User IDs are numeric strings, not integers
+- Suspended or deleted accounts return errors, not empty results
+- LOOKUP_BY_IDS accepts max 100 IDs per request
+
+### 4. Manage Bookmarks
+
+**When to use**: User wants to save, view, or remove bookmarked tweets
+
+**Tool sequence**:
+1. `TWITTER_USER_LOOKUP_ME` - Get authenticated user ID [Prerequisite]
+2. `TWITTER_BOOKMARKS_BY_USER` - List bookmarked posts [Required]
+3. `TWITTER_ADD_POST_TO_BOOKMARKS` - Bookmark a post [Optional]
+4. `TWITTER_REMOVE_A_BOOKMARKED_POST` - Remove bookmark [Optional]
+
+**Key parameters**:
+- `id`: User ID (from USER_LOOKUP_ME) for listing bookmarks
+- `tweet_id`: Tweet ID to bookmark or unbookmark
+- `max_results`: Results per page
+- `pagination_token`: Token for next page
+
+**Pitfalls**:
+- Bookmarks require the authenticated user's ID, not username
+- Bookmarks are private; only the authenticated user can see their own
+- Pagination uses `pagination_token`, not `next_token`
+
+### 5. Manage Lists
+
+**When to use**: User wants to view or manage Twitter lists
+
+**Tool sequence**:
+1. `TWITTER_USER_LOOKUP_ME` - Get authenticated user ID [Prerequisite]
+2. `TWITTER_GET_A_USER_S_OWNED_LISTS` - List owned lists [Optional]
+3. `TWITTER_GET_A_USER_S_LIST_MEMBERSHIPS` - List memberships [Optional]
+4. `TWITTER_GET_A_USER_S_PINNED_LISTS` - Get pinned lists [Optional]
+5. `TWITTER_GET_USER_S_FOLLOWED_LISTS` - Get followed lists [Optional]
+6. `TWITTER_LIST_LOOKUP_BY_LIST_ID` - Get list details [Optional]
+
+**Key parameters**:
+- `id`: User ID for listing owned/member/followed lists
+- `list_id`: List ID for specific list lookup
+- `max_results`: Results per page (1-100)
+
+**Pitfalls**:
+- List IDs and User IDs are numeric strings
+- Lists endpoints require the user's numeric ID, not username
+
+### 6. Interact with Posts
+
+**When to use**: User wants to like, unlike, or view liked posts
+
+**Tool sequence**:
+1. `TWITTER_USER_LOOKUP_ME` - Get authenticated user ID [Prerequisite]
+2. `TWITTER_RETURNS_POST_OBJECTS_LIKED_BY_THE_PROVIDED_USER_ID` - Get liked posts [Optional]
+3. `TWITTER_UNLIKE_POST` - Unlike a post [Optional]
+
+**Key parameters**:
+- `id`: User ID for listing liked posts
+- `tweet_id`: Tweet ID to unlike
+
+**Pitfalls**:
+- Like/unlike endpoints require user ID from USER_LOOKUP_ME
+- Liked posts pagination may be slow for users with many likes
+
+## Common Patterns
+
+### Search Query Syntax
+
+**Operators**:
+- `from:username` - Posts by user
+- `to:username` - Replies to user
+- `@username` - Mentions user
+- `#hashtag` - Contains hashtag
+- `"exact phrase"` - Exact match
+- `has:media` - Contains media
+- `has:links` - Contains links
+- `is:retweet` / `-is:retweet` - Include/exclude retweets
+- `is:reply` / `-is:reply` - Include/exclude replies
+- `lang:en` - Language filter
+
+**Combinators**:
+- Space for AND
+- `OR` for either condition
+- `-` prefix for NOT
+- Parentheses for grouping
+
+### Media Upload Flow
+
+```
+1. Upload media with TWITTER_UPLOAD_MEDIA (images) or TWITTER_UPLOAD_LARGE_MEDIA (video/GIF)
+2. Get media_id from response
+3. Pass media_id as string in media__media_ids array to TWITTER_CREATION_OF_A_POST
+```
+
+## Known Pitfalls
+
+**Character Limits**:
+- Standard posts: 280 weighted characters
+- Some Unicode characters count as more than 1
+- URLs are shortened and count as fixed length (23 characters)
+
+**Rate Limits**:
+- Vary significantly by access tier (Free, Basic, Pro, Enterprise)
+- Free tier: very limited (e.g., 1,500 posts/month)
+- Check `x-rate-limit-remaining` header in responses
+
+**Idempotency**:
+- Post creation is NOT idempotent; duplicate posts will be created on retry
+- Implement deduplication logic for automated posting
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create post | TWITTER_CREATION_OF_A_POST | text |
+| Delete post | TWITTER_POST_DELETE_BY_POST_ID | id |
+| Look up post | TWITTER_POST_LOOKUP_BY_POST_ID | id |
+| Recent search | TWITTER_RECENT_SEARCH | query |
+| Archive search | TWITTER_FULL_ARCHIVE_SEARCH | query |
+| Search counts | TWITTER_RECENT_SEARCH_COUNTS | query |
+| My profile | TWITTER_USER_LOOKUP_ME | (none) |
+| User by name | TWITTER_USER_LOOKUP_BY_USERNAME | username |
+| User by ID | TWITTER_USER_LOOKUP_BY_ID | id |
+| Users by IDs | TWITTER_USER_LOOKUP_BY_IDS | ids |
+| Upload media | TWITTER_UPLOAD_MEDIA | media |
+| Upload video | TWITTER_UPLOAD_LARGE_MEDIA | media |
+| List bookmarks | TWITTER_BOOKMARKS_BY_USER | id |
+| Add bookmark | TWITTER_ADD_POST_TO_BOOKMARKS | tweet_id |
+| Remove bookmark | TWITTER_REMOVE_A_BOOKMARKED_POST | tweet_id |
+| Unlike post | TWITTER_UNLIKE_POST | tweet_id |
+| Liked posts | TWITTER_RETURNS_POST_OBJECTS_LIKED_BY_THE_PROVIDED_USER_ID | id |
+| Owned lists | TWITTER_GET_A_USER_S_OWNED_LISTS | id |
+| List memberships | TWITTER_GET_A_USER_S_LIST_MEMBERSHIPS | id |
+| Pinned lists | TWITTER_GET_A_USER_S_PINNED_LISTS | id |
+| Followed lists | TWITTER_GET_USER_S_FOLLOWED_LISTS | id |
+| List details | TWITTER_LIST_LOOKUP_BY_LIST_ID | list_id |
diff --git a/vercel-automation/SKILL.md b/vercel-automation/SKILL.md
new file mode 100644
index 0000000..6b06a38
--- /dev/null
+++ b/vercel-automation/SKILL.md
@@ -0,0 +1,223 @@
+---
+name: vercel-automation
+description: Automate Vercel tasks via Rube MCP (Composio): manage deployments, domains, DNS, env vars, projects, and teams. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Vercel Automation via Rube MCP
+
+Automate Vercel platform operations through Composio's Vercel toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Vercel connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `vercel`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `vercel`
+3. If connection is not ACTIVE, follow the returned auth link to complete Vercel OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Monitor and Inspect Deployments
+
+**When to use**: User wants to list, inspect, or debug deployments
+
+**Tool sequence**:
+1. `VERCEL_LIST_ALL_DEPLOYMENTS` or `VERCEL_GET_DEPLOYMENTS` - List deployments with filters [Required]
+2. `VERCEL_GET_DEPLOYMENT` or `VERCEL_GET_DEPLOYMENT_DETAILS` - Get specific deployment info [Optional]
+3. `VERCEL_GET_DEPLOYMENT_LOGS` or `VERCEL_GET_RUNTIME_LOGS` - View build/runtime logs [Optional]
+4. `VERCEL_GET_DEPLOYMENT_EVENTS` - Get deployment event timeline [Optional]
+5. `VERCEL_LIST_DEPLOYMENT_CHECKS` - View deployment check results [Optional]
+
+**Key parameters**:
+- `projectId`: Filter deployments by project
+- `state`: Filter by deployment state (e.g., 'READY', 'ERROR', 'BUILDING')
+- `limit`: Number of deployments to return
+- `target`: Filter by environment ('production', 'preview')
+- `deploymentId` or `idOrUrl`: Specific deployment identifier
+
+**Pitfalls**:
+- Deployment IDs and URLs are both accepted as identifiers in most endpoints
+- Build logs and runtime logs are separate; use the appropriate tool
+- `VERCEL_GET_DEPLOYMENT_LOGS` returns build logs; `VERCEL_GET_RUNTIME_LOGS` returns serverless function logs
+- Deployment events include status transitions and are useful for debugging timing issues
+
+### 2. Create and Manage Deployments
+
+**When to use**: User wants to trigger a new deployment
+
+**Tool sequence**:
+1. `VERCEL_LIST_PROJECTS` - Find the target project [Prerequisite]
+2. `VERCEL_CREATE_NEW_DEPLOYMENT` - Trigger a new deployment [Required]
+3. `VERCEL_GET_DEPLOYMENT` - Monitor deployment progress [Optional]
+
+**Key parameters**:
+- `name`: Project name for the deployment
+- `target`: Deployment target ('production' or 'preview')
+- `gitSource`: Git repository source with ref/branch info
+- `files`: Array of file objects for file-based deployments
+
+**Pitfalls**:
+- Either `gitSource` or `files` must be provided, not both
+- Git-based deployments require proper repository integration
+- Production deployments update the production domain alias automatically
+- Deployment creation is asynchronous; poll with GET_DEPLOYMENT for status
+
+### 3. Manage Environment Variables
+
+**When to use**: User wants to add, list, or remove environment variables for a project
+
+**Tool sequence**:
+1. `VERCEL_LIST_PROJECTS` - Find the project ID [Prerequisite]
+2. `VERCEL_LIST_ENV_VARIABLES` - List existing env vars [Required]
+3. `VERCEL_ADD_ENVIRONMENT_VARIABLE` - Add a new env var [Optional]
+4. `VERCEL_DELETE_ENVIRONMENT_VARIABLE` - Remove an env var [Optional]
+
+**Key parameters**:
+- `projectId`: Target project identifier
+- `key`: Environment variable name
+- `value`: Environment variable value
+- `target`: Array of environments ('production', 'preview', 'development')
+- `type`: Variable type ('plain', 'secret', 'encrypted', 'sensitive')
+
+**Pitfalls**:
+- Environment variable names must be unique per target environment
+- `type: 'secret'` variables cannot be read back after creation; only the ID is returned
+- Deleting an env var requires both `projectId` and the env var `id` (not the key name)
+- Changes require a new deployment to take effect
+
+### 4. Manage Domains and DNS
+
+**When to use**: User wants to configure custom domains or manage DNS records
+
+**Tool sequence**:
+1. `VERCEL_GET_DOMAIN` - Check domain status and configuration [Required]
+2. `VERCEL_GET_DOMAIN_CONFIG` - Get DNS/SSL configuration details [Optional]
+3. `VERCEL_LIST_PROJECT_DOMAINS` - List domains attached to a project [Optional]
+4. `VERCEL_GET_DNS_RECORDS` - List DNS records for a domain [Optional]
+5. `VERCEL_CREATE_DNS_RECORD` - Add a new DNS record [Optional]
+6. `VERCEL_UPDATE_DNS_RECORD` - Modify an existing DNS record [Optional]
+
+**Key parameters**:
+- `domain`: Domain name (e.g., 'example.com')
+- `name`: DNS record name/subdomain
+- `type`: DNS record type ('A', 'AAAA', 'CNAME', 'MX', 'TXT', 'SRV')
+- `value`: DNS record value
+- `ttl`: Time-to-live in seconds
+
+**Pitfalls**:
+- Domain must be added to the Vercel account before DNS management
+- SSL certificates are auto-provisioned but may take time for new domains
+- CNAME records at the apex domain are not supported; use A records instead
+- MX records require priority values
+
+### 5. Manage Projects
+
+**When to use**: User wants to list, inspect, or update project settings
+
+**Tool sequence**:
+1. `VERCEL_LIST_PROJECTS` - List all projects [Required]
+2. `VERCEL_GET_PROJECT` - Get detailed project information [Optional]
+3. `VERCEL_UPDATE_PROJECT` - Modify project settings [Optional]
+
+**Key parameters**:
+- `idOrName`: Project ID or name for lookup
+- `name`: Project name for updates
+- `framework`: Framework preset (e.g., 'nextjs', 'vite', 'remix')
+- `buildCommand`: Custom build command override
+- `rootDirectory`: Root directory if not repo root
+
+**Pitfalls**:
+- Project names are globally unique within a team/account
+- Changing framework settings affects subsequent deployments
+- `rootDirectory` is relative to the repository root
+
+### 6. Team Management
+
+**When to use**: User wants to view team info or list team members
+
+**Tool sequence**:
+1. `VERCEL_LIST_TEAMS` - List all teams the user belongs to [Required]
+2. `VERCEL_GET_TEAM` - Get detailed team information [Optional]
+3. `VERCEL_GET_TEAM_MEMBERS` - List members of a specific team [Optional]
+
+**Key parameters**:
+- `teamId`: Team identifier
+- `limit`: Number of results per page
+- `role`: Filter members by role
+
+**Pitfalls**:
+- Team operations require appropriate team-level permissions
+- Personal accounts have no teams; team endpoints return empty results
+- Member roles include 'OWNER', 'MEMBER', 'DEVELOPER', 'VIEWER'
+
+## Common Patterns
+
+### ID Resolution
+
+**Project name -> Project ID**:
+```
+1. Call VERCEL_LIST_PROJECTS
+2. Find project by name in response
+3. Extract id field for subsequent operations
+```
+
+**Domain -> DNS Records**:
+```
+1. Call VERCEL_GET_DNS_RECORDS with domain name
+2. Extract record IDs for update/delete operations
+```
+
+### Pagination
+
+- Use `limit` parameter to control page size
+- Check response for pagination tokens or `next` fields
+- Continue fetching until no more pages are indicated
+
+## Known Pitfalls
+
+**Deployment States**:
+- States include: INITIALIZING, ANALYZING, BUILDING, DEPLOYING, READY, ERROR, CANCELED, QUEUED
+- Only READY deployments are live and serving traffic
+- ERROR deployments should be inspected via logs for failure details
+
+**Environment Variables**:
+- Secret type vars are write-only; values cannot be retrieved after creation
+- Env vars are scoped to environments (production, preview, development)
+- A redeployment is needed for env var changes to take effect
+
+**Rate Limits**:
+- Vercel API has rate limits per endpoint
+- Implement backoff on 429 responses
+- Batch operations where possible to reduce API calls
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List projects | VERCEL_LIST_PROJECTS | limit |
+| Get project details | VERCEL_GET_PROJECT | idOrName |
+| Update project | VERCEL_UPDATE_PROJECT | idOrName, name, framework |
+| List deployments | VERCEL_LIST_ALL_DEPLOYMENTS | projectId, state, limit |
+| Get deployment | VERCEL_GET_DEPLOYMENT | idOrUrl |
+| Create deployment | VERCEL_CREATE_NEW_DEPLOYMENT | name, target, gitSource |
+| Deployment logs | VERCEL_GET_DEPLOYMENT_LOGS | deploymentId |
+| Runtime logs | VERCEL_GET_RUNTIME_LOGS | deploymentId |
+| List env vars | VERCEL_LIST_ENV_VARIABLES | projectId |
+| Add env var | VERCEL_ADD_ENVIRONMENT_VARIABLE | projectId, key, value, target |
+| Delete env var | VERCEL_DELETE_ENVIRONMENT_VARIABLE | projectId, id |
+| Get domain | VERCEL_GET_DOMAIN | domain |
+| Get domain config | VERCEL_GET_DOMAIN_CONFIG | domain |
+| List DNS records | VERCEL_GET_DNS_RECORDS | domain |
+| Create DNS record | VERCEL_CREATE_DNS_RECORD | domain, name, type, value |
+| Update DNS record | VERCEL_UPDATE_DNS_RECORD | domain, recordId |
+| List project domains | VERCEL_LIST_PROJECT_DOMAINS | projectId |
+| List teams | VERCEL_LIST_TEAMS | (none) |
+| Get team | VERCEL_GET_TEAM | teamId |
+| Get team members | VERCEL_GET_TEAM_MEMBERS | teamId, limit |
diff --git a/webflow-automation/SKILL.md b/webflow-automation/SKILL.md
new file mode 100644
index 0000000..b22c2b9
--- /dev/null
+++ b/webflow-automation/SKILL.md
@@ -0,0 +1,233 @@
+---
+name: webflow-automation
+description: Automate Webflow CMS collections, site publishing, page management, asset uploads, and ecommerce orders via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Webflow Automation via Rube MCP
+
+Automate Webflow operations including CMS collection management, site publishing, page inspection, asset uploads, and ecommerce order retrieval through Composio's Webflow toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Webflow connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `webflow`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `webflow`
+3. If connection is not ACTIVE, follow the returned auth link to complete Webflow OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Manage CMS Collection Items
+
+**When to use**: User wants to create, update, list, or delete items in Webflow CMS collections (blog posts, products, team members, etc.)
+
+**Tool sequence**:
+1. `WEBFLOW_LIST_WEBFLOW_SITES` - List sites to find the target site_id [Prerequisite]
+2. `WEBFLOW_LIST_COLLECTIONS` - List all collections for the site [Prerequisite]
+3. `WEBFLOW_GET_COLLECTION` - Get collection schema to find valid field slugs [Prerequisite for create/update]
+4. `WEBFLOW_LIST_COLLECTION_ITEMS` - List existing items with filtering and pagination [Optional]
+5. `WEBFLOW_GET_COLLECTION_ITEM` - Get a specific item's full details [Optional]
+6. `WEBFLOW_CREATE_COLLECTION_ITEM` - Create a new item with field data [Required for creation]
+7. `WEBFLOW_UPDATE_COLLECTION_ITEM` - Update an existing item's fields [Required for updates]
+8. `WEBFLOW_DELETE_COLLECTION_ITEM` - Permanently remove an item [Optional]
+9. `WEBFLOW_PUBLISH_SITE` - Publish changes to make them live [Optional]
+
+**Key parameters for CREATE_COLLECTION_ITEM**:
+- `collection_id`: 24-character hex string from LIST_COLLECTIONS
+- `field_data`: Object with field slug keys (NOT display names); must include `name` and `slug`
+- `field_data.name`: Display name for the item
+- `field_data.slug`: URL-friendly identifier (lowercase, hyphens, no spaces)
+- `is_draft`: Boolean to create as draft (default false)
+
+**Key parameters for UPDATE_COLLECTION_ITEM**:
+- `collection_id`: Collection identifier
+- `item_id`: 24-character hex MongoDB ObjectId of the existing item
+- `fields`: Object with field slug keys and new values
+- `live`: Boolean to publish changes immediately (default false)
+
+**Field value types**:
+- Text/Email/Link/Date: string
+- Number: integer or float
+- Boolean: true/false
+- Image: `{"url": "...", "alt": "...", "fileId": "..."}`
+- Multi-reference: array of reference ID strings
+- Multi-image: array of image objects
+- Option: option ID string
+
+**Pitfalls**:
+- Field keys must use the exact field `slug` from the collection schema, NOT display names
+- Always call `GET_COLLECTION` first to retrieve the schema and identify correct field slugs
+- `CREATE_COLLECTION_ITEM` requires `name` and `slug` in `field_data`
+- `UPDATE_COLLECTION_ITEM` cannot create new items; it requires a valid existing `item_id`
+- `item_id` must be a 24-character hexadecimal MongoDB ObjectId
+- Slug must be lowercase alphanumeric with hyphens: `^[a-z0-9]+(?:-[a-z0-9]+)*$`
+- CMS items are staged; use `PUBLISH_SITE` or set `live: true` to push to production
+
+### 2. Manage Sites and Publishing
+
+**When to use**: User wants to list sites, inspect site configuration, or publish staged changes
+
+**Tool sequence**:
+1. `WEBFLOW_LIST_WEBFLOW_SITES` - List all accessible sites [Required]
+2. `WEBFLOW_GET_SITE_INFO` - Get detailed site metadata including domains and settings [Optional]
+3. `WEBFLOW_PUBLISH_SITE` - Deploy all staged changes to live site [Required for publishing]
+
+**Key parameters for PUBLISH_SITE**:
+- `site_id`: Site identifier from LIST_WEBFLOW_SITES
+- `custom_domains`: Array of custom domain ID strings (from GET_SITE_INFO)
+- `publish_to_webflow_subdomain`: Boolean to publish to `{shortName}.webflow.io`
+- At least one of `custom_domains` or `publish_to_webflow_subdomain` must be specified
+
+**Pitfalls**:
+- `PUBLISH_SITE` republishes ALL staged changes for selected domains -- verify no unintended drafts are pending
+- Rate limit: 1 successful publish per minute
+- For sites without custom domains, must set `publish_to_webflow_subdomain: true`
+- `custom_domains` expects domain IDs (hex strings), not domain names
+- Publishing is a production action -- always confirm with the user first
+
+### 3. Manage Pages
+
+**When to use**: User wants to list pages, inspect page metadata, or examine page DOM structure
+
+**Tool sequence**:
+1. `WEBFLOW_LIST_WEBFLOW_SITES` - Find the target site_id [Prerequisite]
+2. `WEBFLOW_LIST_PAGES` - List all pages for a site with pagination [Required]
+3. `WEBFLOW_GET_PAGE` - Get detailed metadata for a specific page [Optional]
+4. `WEBFLOW_GET_PAGE_DOM` - Get the DOM/content node structure of a static page [Optional]
+
+**Key parameters**:
+- `site_id`: Site identifier (required for list pages)
+- `page_id`: 24-character hex page identifier
+- `locale_id`: Optional locale filter for multi-language sites
+- `limit`: Max results per page (max 100)
+- `offset`: Pagination offset
+
+**Pitfalls**:
+- `LIST_PAGES` paginates via offset/limit; iterate when sites have many pages
+- Page IDs are 24-character hex strings matching pattern `^[0-9a-fA-F]{24}$`
+- `GET_PAGE_DOM` returns the node structure, not rendered HTML
+- Pages include both static and CMS-driven pages
+
+### 4. Upload Assets
+
+**When to use**: User wants to upload images, files, or other assets to a Webflow site
+
+**Tool sequence**:
+1. `WEBFLOW_LIST_WEBFLOW_SITES` - Find the target site_id [Prerequisite]
+2. `WEBFLOW_UPLOAD_ASSET` - Upload a file with base64-encoded content [Required]
+
+**Key parameters**:
+- `site_id`: Site identifier
+- `file_name`: Name of the file (e.g., `"logo.png"`)
+- `file_content`: Base64-encoded binary content of the file (NOT a placeholder or URL)
+- `content_type`: MIME type (e.g., `"image/png"`, `"image/jpeg"`, `"application/pdf"`)
+- `md5`: MD5 hash of the raw file bytes (32-character hex string)
+- `asset_folder_id`: Optional folder placement
+
+**Pitfalls**:
+- `file_content` must be actual base64-encoded data, NOT a variable reference or placeholder
+- `md5` must be computed from the raw bytes, not from the base64 string
+- This is a two-step process internally: generates an S3 pre-signed URL, then uploads
+- Large files may encounter timeouts; keep uploads reasonable in size
+
+### 5. Manage Ecommerce Orders
+
+**When to use**: User wants to view ecommerce orders from a Webflow site
+
+**Tool sequence**:
+1. `WEBFLOW_LIST_WEBFLOW_SITES` - Find the site with ecommerce enabled [Prerequisite]
+2. `WEBFLOW_LIST_ORDERS` - List all orders with optional status filtering [Required]
+3. `WEBFLOW_GET_ORDER` - Get detailed information for a specific order [Optional]
+
+**Key parameters**:
+- `site_id`: Site identifier (must have ecommerce enabled)
+- `order_id`: Specific order identifier for detailed retrieval
+- `status`: Filter orders by status
+
+**Pitfalls**:
+- Ecommerce must be enabled on the Webflow site for order endpoints to work
+- Order endpoints are read-only; no create/update/delete for orders through these tools
+
+## Common Patterns
+
+### ID Resolution
+Webflow uses 24-character hexadecimal IDs throughout:
+- **Site ID**: `WEBFLOW_LIST_WEBFLOW_SITES` -- find by name, capture `id`
+- **Collection ID**: `WEBFLOW_LIST_COLLECTIONS` with `site_id`
+- **Item ID**: `WEBFLOW_LIST_COLLECTION_ITEMS` with `collection_id`
+- **Page ID**: `WEBFLOW_LIST_PAGES` with `site_id`
+- **Domain IDs**: `WEBFLOW_GET_SITE_INFO` -- found in `customDomains` array
+- **Field slugs**: `WEBFLOW_GET_COLLECTION` -- found in collection `fields` array
+
+### Pagination
+Webflow uses offset-based pagination:
+- `offset`: Starting index (0-based)
+- `limit`: Items per page (max 100)
+- Increment offset by limit until fewer results than limit are returned
+- Available on: LIST_COLLECTION_ITEMS, LIST_PAGES
+
+### CMS Workflow
+Typical CMS content creation flow:
+1. Get site_id from LIST_WEBFLOW_SITES
+2. Get collection_id from LIST_COLLECTIONS
+3. Get field schema from GET_COLLECTION (to learn field slugs)
+4. Create/update items using correct field slugs
+5. Publish site to make changes live
+
+## Known Pitfalls
+
+### ID Formats
+- All Webflow IDs are 24-character hexadecimal strings (MongoDB ObjectIds)
+- Example: `580e63fc8c9a982ac9b8b745`
+- Pattern: `^[0-9a-fA-F]{24}$`
+- Invalid IDs return 404 errors
+
+### Field Slugs vs Display Names
+- CMS operations require field `slug` values, NOT display names
+- A field with displayName "Author Name" might have slug `author-name`
+- Always call `GET_COLLECTION` to discover correct field slugs
+- Using wrong field names silently ignores the data or causes validation errors
+
+### Publishing
+- `PUBLISH_SITE` deploys ALL staged changes, not just specific items
+- Rate limited to 1 publish per minute
+- Must specify at least one domain target (custom or webflow subdomain)
+- This is a production-affecting action; always confirm intent
+
+### Authentication Scopes
+- Different operations require different OAuth scopes: `sites:read`, `cms:read`, `cms:write`, `pages:read`
+- A 403 error typically means missing OAuth scopes
+- Check connection permissions if operations fail with authorization errors
+
+### Destructive Operations
+- `DELETE_COLLECTION_ITEM` permanently removes CMS items
+- `PUBLISH_SITE` makes all staged changes live immediately
+- Always confirm with the user before executing these actions
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List sites | `WEBFLOW_LIST_WEBFLOW_SITES` | (none) |
+| Get site info | `WEBFLOW_GET_SITE_INFO` | `site_id` |
+| Publish site | `WEBFLOW_PUBLISH_SITE` | `site_id`, `custom_domains` or `publish_to_webflow_subdomain` |
+| List collections | `WEBFLOW_LIST_COLLECTIONS` | `site_id` |
+| Get collection schema | `WEBFLOW_GET_COLLECTION` | `collection_id` |
+| List collection items | `WEBFLOW_LIST_COLLECTION_ITEMS` | `collection_id`, `limit`, `offset` |
+| Get collection item | `WEBFLOW_GET_COLLECTION_ITEM` | `collection_id`, `item_id` |
+| Create collection item | `WEBFLOW_CREATE_COLLECTION_ITEM` | `collection_id`, `field_data` |
+| Update collection item | `WEBFLOW_UPDATE_COLLECTION_ITEM` | `collection_id`, `item_id`, `fields` |
+| Delete collection item | `WEBFLOW_DELETE_COLLECTION_ITEM` | `collection_id`, `item_id` |
+| List pages | `WEBFLOW_LIST_PAGES` | `site_id`, `limit`, `offset` |
+| Get page | `WEBFLOW_GET_PAGE` | `page_id` |
+| Get page DOM | `WEBFLOW_GET_PAGE_DOM` | `page_id` |
+| Upload asset | `WEBFLOW_UPLOAD_ASSET` | `site_id`, `file_name`, `file_content`, `content_type`, `md5` |
+| List orders | `WEBFLOW_LIST_ORDERS` | `site_id`, `status` |
+| Get order | `WEBFLOW_GET_ORDER` | `site_id`, `order_id` |
diff --git a/whatsapp-automation/SKILL.md b/whatsapp-automation/SKILL.md
new file mode 100644
index 0000000..3e3201d
--- /dev/null
+++ b/whatsapp-automation/SKILL.md
@@ -0,0 +1,211 @@
+---
+name: whatsapp-automation
+description: Automate WhatsApp Business tasks via Rube MCP (Composio): send messages, manage templates, upload media, and handle contacts. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# WhatsApp Business Automation via Rube MCP
+
+Automate WhatsApp Business operations through Composio's WhatsApp toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active WhatsApp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `whatsapp`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+- WhatsApp Business API account required (not regular WhatsApp)
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `whatsapp`
+3. If connection is not ACTIVE, follow the returned auth link to complete WhatsApp Business setup
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Send a Text Message
+
+**When to use**: User wants to send a text message to a WhatsApp contact
+
+**Tool sequence**:
+1. `WHATSAPP_GET_PHONE_NUMBERS` - List available business phone numbers [Prerequisite]
+2. `WHATSAPP_SEND_MESSAGE` - Send a text message [Required]
+
+**Key parameters**:
+- `to`: Recipient phone number in international format (e.g., '+14155551234')
+- `body`: Message text content
+- `phone_number_id`: Business phone number ID to send from
+
+**Pitfalls**:
+- Phone numbers must be in international E.164 format with country code
+- Messages outside the 24-hour window require approved templates
+- The 24-hour window starts when the customer last messaged you
+- Business-initiated conversations require template messages first
+
+### 2. Send Template Messages
+
+**When to use**: User wants to send pre-approved template messages for outbound communication
+
+**Tool sequence**:
+1. `WHATSAPP_GET_MESSAGE_TEMPLATES` - List available templates [Prerequisite]
+2. `WHATSAPP_GET_TEMPLATE_STATUS` - Check template approval status [Optional]
+3. `WHATSAPP_SEND_TEMPLATE_MESSAGE` - Send the template message [Required]
+
+**Key parameters**:
+- `template_name`: Name of the approved template
+- `language_code`: Template language (e.g., 'en_US')
+- `to`: Recipient phone number
+- `components`: Template variable values and parameters
+
+**Pitfalls**:
+- Templates must be approved by Meta before use
+- Template variables must match the expected count and format
+- Sending unapproved or rejected templates returns errors
+- Language code must match an approved translation of the template
+
+### 3. Send Media Messages
+
+**When to use**: User wants to send images, documents, or other media
+
+**Tool sequence**:
+1. `WHATSAPP_UPLOAD_MEDIA` - Upload media to WhatsApp servers [Required]
+2. `WHATSAPP_SEND_MEDIA_BY_ID` - Send media using the uploaded media ID [Required]
+ OR
+3. `WHATSAPP_SEND_MEDIA` - Send media using a public URL [Alternative]
+
+**Key parameters**:
+- `media_url`: Public URL of the media (for SEND_MEDIA)
+- `media_id`: ID from upload response (for SEND_MEDIA_BY_ID)
+- `type`: Media type ('image', 'document', 'audio', 'video', 'sticker')
+- `caption`: Optional caption for the media
+
+**Pitfalls**:
+- Uploaded media IDs are temporary and expire after a period
+- Media size limits vary by type (images: 5MB, videos: 16MB, documents: 100MB)
+- Supported formats: images (JPEG, PNG), videos (MP4, 3GPP), documents (PDF, etc.)
+- SEND_MEDIA requires a publicly accessible HTTPS URL
+
+### 4. Reply to Messages
+
+**When to use**: User wants to reply to an incoming WhatsApp message
+
+**Tool sequence**:
+1. `WHATSAPP_SEND_REPLY` - Send a reply to a specific message [Required]
+
+**Key parameters**:
+- `message_id`: ID of the message being replied to
+- `to`: Recipient phone number
+- `body`: Reply text content
+
+**Pitfalls**:
+- message_id must be from a message received within the 24-hour window
+- Replies appear as quoted messages in the conversation
+- The original message must still exist (not deleted) for the quote to display
+
+### 5. Manage Business Profile and Templates
+
+**When to use**: User wants to view or manage their WhatsApp Business profile
+
+**Tool sequence**:
+1. `WHATSAPP_GET_BUSINESS_PROFILE` - Get business profile details [Optional]
+2. `WHATSAPP_GET_PHONE_NUMBERS` - List registered phone numbers [Optional]
+3. `WHATSAPP_GET_PHONE_NUMBER` - Get details for a specific number [Optional]
+4. `WHATSAPP_CREATE_MESSAGE_TEMPLATE` - Create a new template [Optional]
+5. `WHATSAPP_GET_MESSAGE_TEMPLATES` - List all templates [Optional]
+
+**Key parameters**:
+- `phone_number_id`: Business phone number ID
+- `template_name`: Name for the new template
+- `category`: Template category (MARKETING, UTILITY, AUTHENTICATION)
+- `language`: Template language code
+
+**Pitfalls**:
+- New templates require Meta review before they can be used
+- Template names must be lowercase with underscores (no spaces)
+- Category affects pricing and approval criteria
+- Templates have specific formatting requirements for headers, body, and buttons
+
+### 6. Share Contacts
+
+**When to use**: User wants to send contact information via WhatsApp
+
+**Tool sequence**:
+1. `WHATSAPP_SEND_CONTACTS` - Send contact cards [Required]
+
+**Key parameters**:
+- `to`: Recipient phone number
+- `contacts`: Array of contact objects with name, phone, email details
+
+**Pitfalls**:
+- Contact objects must follow the WhatsApp Business API contact schema
+- At least a name field is required for each contact
+- Phone numbers in contacts should include country codes
+
+## Common Patterns
+
+### 24-Hour Messaging Window
+
+- Customers must message you first to open a conversation window
+- Within 24 hours of their last message, you can send free-form messages
+- After 24 hours, only approved template messages can be sent
+- Template messages can re-open the conversation window
+
+### Phone Number Resolution
+
+```
+1. Call WHATSAPP_GET_PHONE_NUMBERS
+2. Extract phone_number_id for your business number
+3. Use phone_number_id in all send operations
+```
+
+### Media Upload Flow
+
+```
+1. Call WHATSAPP_UPLOAD_MEDIA with the file
+2. Extract media_id from response
+3. Call WHATSAPP_SEND_MEDIA_BY_ID with media_id
+4. OR use WHATSAPP_SEND_MEDIA with a public URL directly
+```
+
+## Known Pitfalls
+
+**Phone Number Format**:
+- Always use E.164 format: +[country code][number] (e.g., '+14155551234')
+- Do not include dashes, spaces, or parentheses
+- Country code is required; local numbers without it will fail
+
+**Messaging Restrictions**:
+- Business-initiated messages require templates outside the 24-hour window
+- Template messages cost money per conversation
+- Rate limits apply per phone number and per account
+
+**Media Handling**:
+- Uploaded media expires; use promptly after upload
+- Media URLs must be publicly accessible HTTPS
+- Stickers have specific requirements (WebP format, 512x512 pixels)
+
+**Template Management**:
+- Template review can take up to 24 hours
+- Rejected templates need to be fixed and resubmitted
+- Template variables use double curly braces: {{1}}, {{2}}, etc.
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Send message | WHATSAPP_SEND_MESSAGE | to, body |
+| Send template | WHATSAPP_SEND_TEMPLATE_MESSAGE | template_name, to, language_code |
+| Upload media | WHATSAPP_UPLOAD_MEDIA | (file params) |
+| Send media by ID | WHATSAPP_SEND_MEDIA_BY_ID | media_id, to, type |
+| Send media by URL | WHATSAPP_SEND_MEDIA | media_url, to, type |
+| Reply to message | WHATSAPP_SEND_REPLY | message_id, to, body |
+| Send contacts | WHATSAPP_SEND_CONTACTS | to, contacts |
+| Get media | WHATSAPP_GET_MEDIA | media_id |
+| List phone numbers | WHATSAPP_GET_PHONE_NUMBERS | (none) |
+| Get phone number | WHATSAPP_GET_PHONE_NUMBER | phone_number_id |
+| Get business profile | WHATSAPP_GET_BUSINESS_PROFILE | phone_number_id |
+| Create template | WHATSAPP_CREATE_MESSAGE_TEMPLATE | template_name, category, language |
+| List templates | WHATSAPP_GET_MESSAGE_TEMPLATES | (none) |
+| Check template status | WHATSAPP_GET_TEMPLATE_STATUS | template_id |
diff --git a/wrike-automation/SKILL.md b/wrike-automation/SKILL.md
new file mode 100644
index 0000000..8abfb99
--- /dev/null
+++ b/wrike-automation/SKILL.md
@@ -0,0 +1,230 @@
+---
+name: wrike-automation
+description: Automate Wrike project management via Rube MCP (Composio): create tasks/folders, manage projects, assign work, and track progress. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Wrike Automation via Rube MCP
+
+Automate Wrike project management operations through Composio's Wrike toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Wrike connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `wrike`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `wrike`
+3. If connection is not ACTIVE, follow the returned auth link to complete Wrike OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Manage Tasks
+
+**When to use**: User wants to create, assign, or update tasks in Wrike
+
+**Tool sequence**:
+1. `WRIKE_GET_FOLDERS` - Find the target folder/project [Prerequisite]
+2. `WRIKE_GET_ALL_CUSTOM_FIELDS` - Get custom field IDs if needed [Optional]
+3. `WRIKE_CREATE_TASK` - Create a new task [Required]
+4. `WRIKE_MODIFY_TASK` - Update task properties [Optional]
+
+**Key parameters**:
+- `folderId`: Parent folder ID where the task will be created
+- `title`: Task title
+- `description`: Task description (supports HTML)
+- `responsibles`: Array of user IDs to assign
+- `status`: 'Active', 'Completed', 'Deferred', 'Cancelled'
+- `importance`: 'High', 'Normal', 'Low'
+- `customFields`: Array of {id, value} objects
+- `dates`: Object with type, start, due, duration
+
+**Pitfalls**:
+- folderId is required; tasks must belong to a folder
+- responsibles requires Wrike user IDs, not emails or names
+- Custom field IDs must be obtained from GET_ALL_CUSTOM_FIELDS
+- priorityBefore and priorityAfter are mutually exclusive
+- Status field may not be available on Team plan
+- dates.start and dates.due use 'YYYY-MM-DD' format
+
+### 2. Manage Folders and Projects
+
+**When to use**: User wants to create, modify, or organize folders and projects
+
+**Tool sequence**:
+1. `WRIKE_GET_FOLDERS` - List existing folders [Required]
+2. `WRIKE_CREATE_FOLDER` - Create a new folder/project [Optional]
+3. `WRIKE_MODIFY_FOLDER` - Update folder properties [Optional]
+4. `WRIKE_LIST_SUBFOLDERS_BY_FOLDER_ID` - List subfolders [Optional]
+5. `WRIKE_DELETE_FOLDER` - Delete a folder permanently [Optional]
+
+**Key parameters**:
+- `folderId`: Parent folder ID for creation; target folder ID for modification
+- `title`: Folder name
+- `description`: Folder description
+- `customItemTypeId`: Set to create as a project instead of a folder
+- `shareds`: Array of user IDs or emails to share with
+- `project`: Filter for projects (true) or folders (false) in GET_FOLDERS
+
+**Pitfalls**:
+- DELETE_FOLDER is permanent and removes ALL contents (tasks, subfolders, documents)
+- Cannot modify rootFolderId or recycleBinId as parents
+- Folder creation auto-shares with the creator
+- customItemTypeId converts a folder into a project
+- GET_FOLDERS with descendants=true returns folder tree (may be large)
+
+### 3. Retrieve and Track Tasks
+
+**When to use**: User wants to find tasks, check status, or monitor progress
+
+**Tool sequence**:
+1. `WRIKE_FETCH_ALL_TASKS` - List tasks with optional filters [Required]
+2. `WRIKE_GET_TASK_BY_ID` - Get detailed info for a specific task [Optional]
+
+**Key parameters**:
+- `status`: Filter by task status ('Active', 'Completed', etc.)
+- `dueDate`: Filter by due date range (start/end/equal)
+- `fields`: Additional response fields to include
+- `page_size`: Results per page (1-100)
+- `taskId`: Specific task ID for detailed retrieval
+- `resolve_user_names`: Auto-resolve user IDs to names (default true)
+
+**Pitfalls**:
+- FETCH_ALL_TASKS paginates at max 100 items per page
+- dueDate filter supports 'equal', 'start', and 'end' fields
+- Date format: 'yyyy-MM-dd' or 'yyyy-MM-ddTHH:mm:ss'
+- GET_TASK_BY_ID returns read-only detailed information
+- customFields are returned by default for single task queries
+
+### 4. Launch Task Blueprints
+
+**When to use**: User wants to create tasks from predefined templates
+
+**Tool sequence**:
+1. `WRIKE_LIST_TASK_BLUEPRINTS` - List available blueprints [Prerequisite]
+2. `WRIKE_LIST_SPACE_TASK_BLUEPRINTS` - List blueprints in a specific space [Alternative]
+3. `WRIKE_LAUNCH_TASK_BLUEPRINT_ASYNC` - Launch a blueprint [Required]
+
+**Key parameters**:
+- `task_blueprint_id`: ID of the blueprint to launch
+- `title`: Title for the root task
+- `parent_id`: Parent folder/project ID (OR super_task_id)
+- `super_task_id`: Parent task ID (OR parent_id)
+- `reschedule_date`: Target date for task rescheduling
+- `reschedule_mode`: 'RescheduleStartDate' or 'RescheduleFinishDate'
+- `entry_limit`: Max tasks to copy (1-250)
+
+**Pitfalls**:
+- Either parent_id or super_task_id is required, not both
+- Blueprint launch is asynchronous; tasks may take time to appear
+- reschedule_date requires reschedule_mode to be set
+- entry_limit caps at 250 tasks/folders per blueprint launch
+- copy_descriptions defaults to false; set true to include task descriptions
+
+### 5. Manage Workspace and Members
+
+**When to use**: User wants to manage spaces, members, or invitations
+
+**Tool sequence**:
+1. `WRIKE_GET_SPACE` - Get space details [Optional]
+2. `WRIKE_GET_CONTACTS` - List workspace contacts/members [Optional]
+3. `WRIKE_CREATE_INVITATION` - Invite a user to the workspace [Optional]
+4. `WRIKE_DELETE_SPACE` - Delete a space permanently [Optional]
+
+**Key parameters**:
+- `spaceId`: Space identifier
+- `email`: Email for invitation
+- `role`: User role ('Admin', 'Regular User', 'External User')
+- `firstName`/`lastName`: Invitee name
+
+**Pitfalls**:
+- DELETE_SPACE is irreversible and removes all space contents
+- userTypeId and role/external are mutually exclusive in invitations
+- Custom email subjects/messages require a paid Wrike plan
+- GET_CONTACTS returns workspace-level contacts, not task-specific assignments
+
+## Common Patterns
+
+### Folder ID Resolution
+
+```
+1. Call WRIKE_GET_FOLDERS (optionally with project=true for projects only)
+2. Navigate folder tree to find target
+3. Extract folder id (e.g., 'IEAGKVLFK4IHGQOI')
+4. Use as folderId in task/folder creation
+```
+
+### Custom Field Setup
+
+```
+1. Call WRIKE_GET_ALL_CUSTOM_FIELDS to get definitions
+2. Find field by name, extract id and type
+3. Format value according to type (text, dropdown, number, date)
+4. Include as {id: 'FIELD_ID', value: 'VALUE'} in customFields array
+```
+
+### Task Assignment
+
+```
+1. Call WRIKE_GET_CONTACTS to find user IDs
+2. Use user IDs in responsibles array when creating tasks
+3. Or use addResponsibles/removeResponsibles when modifying tasks
+```
+
+### Pagination
+
+- FETCH_ALL_TASKS: Use page_size (max 100) and check for more results
+- GET_FOLDERS: Use nextPageToken when descendants=false and pageSize is set
+- LIST_TASK_BLUEPRINTS: Use next_page_token and page_size (default 100)
+
+## Known Pitfalls
+
+**ID Formats**:
+- Wrike IDs are opaque alphanumeric strings (e.g., 'IEAGTXR7I4IHGABC')
+- Task IDs, folder IDs, space IDs, and user IDs all use this format
+- Custom field IDs follow the same pattern
+- Never guess IDs; always resolve from list/search operations
+
+**Permissions**:
+- Operations depend on user role and sharing settings
+- Shared folders/tasks are visible only to shared users
+- Admin operations require appropriate role
+- Some features (custom statuses, billing types) are plan-dependent
+
+**Deletion Safety**:
+- DELETE_FOLDER removes ALL contents permanently
+- DELETE_SPACE removes the entire space and contents
+- Consider using MODIFY_FOLDER to move to recycle bin instead
+- Restore from recycle bin is possible via MODIFY_FOLDER with restore=true
+
+**Date Handling**:
+- Dates use 'yyyy-MM-dd' format
+- DateTime uses 'yyyy-MM-ddTHH:mm:ssZ' or with timezone offset
+- Task dates include type ('Planned', 'Actual'), start, due, duration
+- Duration is in minutes
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create task | WRIKE_CREATE_TASK | folderId, title, responsibles, status |
+| Modify task | WRIKE_MODIFY_TASK | taskId, title, status, addResponsibles |
+| Get task by ID | WRIKE_GET_TASK_BY_ID | taskId |
+| Fetch all tasks | WRIKE_FETCH_ALL_TASKS | status, dueDate, page_size |
+| Get folders | WRIKE_GET_FOLDERS | project, descendants |
+| Create folder | WRIKE_CREATE_FOLDER | folderId, title |
+| Modify folder | WRIKE_MODIFY_FOLDER | folderId, title, addShareds |
+| Delete folder | WRIKE_DELETE_FOLDER | folderId |
+| List subfolders | WRIKE_LIST_SUBFOLDERS_BY_FOLDER_ID | folderId |
+| Get custom fields | WRIKE_GET_ALL_CUSTOM_FIELDS | (none) |
+| List blueprints | WRIKE_LIST_TASK_BLUEPRINTS | limit, page_size |
+| Launch blueprint | WRIKE_LAUNCH_TASK_BLUEPRINT_ASYNC | task_blueprint_id, title, parent_id |
+| Get space | WRIKE_GET_SPACE | spaceId |
+| Delete space | WRIKE_DELETE_SPACE | spaceId |
+| Get contacts | WRIKE_GET_CONTACTS | (none) |
+| Invite user | WRIKE_CREATE_INVITATION | email, role |
diff --git a/youtube-automation/SKILL.md b/youtube-automation/SKILL.md
new file mode 100644
index 0000000..7ada742
--- /dev/null
+++ b/youtube-automation/SKILL.md
@@ -0,0 +1,215 @@
+---
+name: youtube-automation
+description: Automate YouTube tasks via Rube MCP (Composio): upload videos, manage playlists, search content, get analytics, and handle comments. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# YouTube Automation via Rube MCP
+
+Automate YouTube operations through Composio's YouTube toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active YouTube connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `youtube`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `youtube`
+3. If connection is not ACTIVE, follow the returned auth link to complete Google OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Upload and Manage Videos
+
+**When to use**: User wants to upload a video or update video metadata
+
+**Tool sequence**:
+1. `YOUTUBE_UPLOAD_VIDEO` - Upload a new video [Required]
+2. `YOUTUBE_UPDATE_VIDEO` - Update title, description, tags, privacy [Optional]
+3. `YOUTUBE_UPDATE_THUMBNAIL` - Set a custom thumbnail [Optional]
+
+**Key parameters**:
+- `title`: Video title (max 100 characters)
+- `description`: Video description (max 5000 bytes)
+- `tags`: Array of keyword tags
+- `categoryId`: YouTube category ID (e.g., '22' for People & Blogs)
+- `privacyStatus`: 'public', 'private', or 'unlisted'
+- `videoFilePath`: Object with `{name, mimetype, s3key}` for the video file
+
+**Pitfalls**:
+- UPLOAD_VIDEO consumes high quota; prefer UPDATE_VIDEO for metadata-only changes
+- videoFilePath must be an object with s3key, not a raw file path or URL
+- Tags total must not exceed 500 characters including separators
+- Angle brackets `< >` in tags are automatically stripped
+- Description limit is 5000 bytes, not characters (multibyte chars count more)
+
+### 2. Search YouTube Content
+
+**When to use**: User wants to find videos, channels, or playlists
+
+**Tool sequence**:
+1. `YOUTUBE_SEARCH_YOU_TUBE` - Search for content [Required]
+2. `YOUTUBE_VIDEO_DETAILS` - Get full details for a specific video [Optional]
+3. `YOUTUBE_GET_VIDEO_DETAILS_BATCH` - Get details for multiple videos [Optional]
+
+**Key parameters**:
+- `q`: Search query (supports exact phrases, exclusions, channel handles)
+- `type`: 'video', 'channel', or 'playlist'
+- `maxResults`: Results per page (1-50)
+- `pageToken`: For pagination
+
+**Pitfalls**:
+- Search endpoint only returns 'snippet' part; use VIDEO_DETAILS for statistics
+- Search results are capped at 500 total items
+- Search has higher quota cost (100 units) vs list endpoints (1 unit)
+- BATCH video details practical limit is ~50 IDs per call; chunk larger sets
+
+### 3. Manage Playlists
+
+**When to use**: User wants to create playlists or manage playlist contents
+
+**Tool sequence**:
+1. `YOUTUBE_LIST_USER_PLAYLISTS` - List user's existing playlists [Optional]
+2. `YOUTUBE_CREATE_PLAYLIST` - Create a new playlist [Optional]
+3. `YOUTUBE_ADD_VIDEO_TO_PLAYLIST` - Add a video to a playlist [Optional]
+4. `YOUTUBE_LIST_PLAYLIST_ITEMS` - List videos in a playlist [Optional]
+
+**Key parameters**:
+- `playlistId`: Playlist ID ('PL...' for user-created, 'UU...' for uploads)
+- `part`: Resource parts to include (e.g., 'snippet,contentDetails')
+- `maxResults`: Items per page (1-50)
+- `pageToken`: Pagination token from previous response
+
+**Pitfalls**:
+- Do NOT pass channel IDs ('UC...') as playlist IDs; convert 'UC' to 'UU' for uploads
+- Large playlists require pagination via pageToken; follow nextPageToken until absent
+- items[].id is not the videoId; use items[].snippet.resourceId.videoId
+- Creating duplicate playlist names is allowed; check existing playlists first
+
+### 4. Get Channel and Video Analytics
+
+**When to use**: User wants to analyze channel performance or video metrics
+
+**Tool sequence**:
+1. `YOUTUBE_GET_CHANNEL_ID_BY_HANDLE` - Resolve a handle to channel ID [Prerequisite]
+2. `YOUTUBE_GET_CHANNEL_STATISTICS` - Get channel subscriber/view/video counts [Required]
+3. `YOUTUBE_LIST_CHANNEL_VIDEOS` - List all videos from a channel [Optional]
+4. `YOUTUBE_GET_VIDEO_DETAILS_BATCH` - Get per-video statistics [Optional]
+5. `YOUTUBE_GET_CHANNEL_ACTIVITIES` - Get recent channel activities [Optional]
+
+**Key parameters**:
+- `channelId`: Channel ID ('UC...'), handle ('@handle'), or 'me'
+- `forHandle`: Channel handle (e.g., '@Google')
+- `id`: Comma-separated video IDs for batch details
+- `parts`: Resource parts to include (e.g., 'snippet,statistics')
+
+**Pitfalls**:
+- Channel statistics are lifetime totals, not per-period
+- BATCH video details may return fewer items than requested for private/deleted videos
+- Response data may be nested under `data` or `data_preview`; parse defensively
+- contentDetails.duration uses ISO 8601 format (e.g., 'PT4M13S')
+
+### 5. Manage Subscriptions and Comments
+
+**When to use**: User wants to subscribe to channels or view video comments
+
+**Tool sequence**:
+1. `YOUTUBE_SUBSCRIBE_CHANNEL` - Subscribe to a channel [Optional]
+2. `YOUTUBE_UNSUBSCRIBE_CHANNEL` - Unsubscribe from a channel [Optional]
+3. `YOUTUBE_LIST_USER_SUBSCRIPTIONS` - List subscriptions [Optional]
+4. `YOUTUBE_LIST_COMMENT_THREADS` - List comments on a video [Optional]
+
+**Key parameters**:
+- `channelId`: Channel to subscribe/unsubscribe
+- `videoId`: Video ID for comment threads
+- `maxResults`: Results per page
+- `pageToken`: Pagination token
+
+**Pitfalls**:
+- Subscribing to an already-subscribed channel may return an error
+- Comment threads return top-level comments with up to 5 replies each
+- Comments may be disabled on some videos
+- Unsubscribe requires the subscription ID, not the channel ID
+
+## Common Patterns
+
+### Channel ID Resolution
+
+**Handle to Channel ID**:
+```
+1. Call YOUTUBE_GET_CHANNEL_ID_BY_HANDLE with '@handle'
+2. Extract channelId from response
+3. Use in subsequent channel operations
+```
+
+**Uploads Playlist**:
+```
+1. Get channel ID (starts with 'UC')
+2. Replace 'UC' prefix with 'UU' to get uploads playlist ID
+3. Use with LIST_PLAYLIST_ITEMS to enumerate all videos
+```
+
+### Pagination
+
+- Set `maxResults` (max 50 per page)
+- Check response for `nextPageToken`
+- Pass token as `pageToken` in next request
+- Continue until `nextPageToken` is absent
+
+### Batch Video Details
+
+- Collect video IDs from search or playlist listings
+- Chunk into groups of ~50 IDs
+- Call GET_VIDEO_DETAILS_BATCH per chunk
+- Merge results across chunks
+
+## Known Pitfalls
+
+**Quota Management**:
+- YouTube API has a daily quota limit (default 10,000 units)
+- Upload = 1600 units; search = 100 units; list = 1 unit
+- Prefer list endpoints over search when possible
+- Monitor quota usage to avoid hitting daily limits
+
+**ID Formats**:
+- Video IDs: 11-character alphanumeric strings
+- Channel IDs: Start with 'UC' followed by 22 characters
+- Playlist IDs: Start with 'PL' (user) or 'UU' (uploads)
+- Do not confuse channel IDs with playlist IDs
+
+**Thumbnails**:
+- Custom thumbnails require channel phone verification
+- Must be JPG, PNG, or GIF; under 2MB
+- Recommended: 1280x720 resolution (16:9 aspect ratio)
+
+**Response Parsing**:
+- Statistics values are returned as strings, not integers; cast before math
+- Duration uses ISO 8601 format (PT#H#M#S)
+- Batch responses may wrap data under different keys
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Upload video | YOUTUBE_UPLOAD_VIDEO | title, description, tags, categoryId, privacyStatus, videoFilePath |
+| Update video | YOUTUBE_UPDATE_VIDEO | video_id, title, description, tags |
+| Set thumbnail | YOUTUBE_UPDATE_THUMBNAIL | videoId, thumbnailUrl |
+| Search YouTube | YOUTUBE_SEARCH_YOU_TUBE | q, type, maxResults |
+| Video details | YOUTUBE_VIDEO_DETAILS | id, part |
+| Batch video details | YOUTUBE_GET_VIDEO_DETAILS_BATCH | id, parts |
+| List playlists | YOUTUBE_LIST_USER_PLAYLISTS | maxResults, pageToken |
+| Create playlist | YOUTUBE_CREATE_PLAYLIST | (check schema) |
+| Add to playlist | YOUTUBE_ADD_VIDEO_TO_PLAYLIST | (check schema) |
+| List playlist items | YOUTUBE_LIST_PLAYLIST_ITEMS | playlistId, maxResults |
+| Channel statistics | YOUTUBE_GET_CHANNEL_STATISTICS | id/forHandle/mine |
+| List channel videos | YOUTUBE_LIST_CHANNEL_VIDEOS | channelId, maxResults |
+| Channel ID by handle | YOUTUBE_GET_CHANNEL_ID_BY_HANDLE | channel_handle |
+| Subscribe | YOUTUBE_SUBSCRIBE_CHANNEL | channelId |
+| List subscriptions | YOUTUBE_LIST_USER_SUBSCRIPTIONS | (check schema) |
+| List comments | YOUTUBE_LIST_COMMENT_THREADS | videoId |
+| Channel activities | YOUTUBE_GET_CHANNEL_ACTIVITIES | (check schema) |
diff --git a/zendesk-automation/SKILL.md b/zendesk-automation/SKILL.md
new file mode 100644
index 0000000..bdb416c
--- /dev/null
+++ b/zendesk-automation/SKILL.md
@@ -0,0 +1,212 @@
+---
+name: zendesk-automation
+description: Automate Zendesk tasks via Rube MCP (Composio): tickets, users, organizations, replies. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Zendesk Automation via Rube MCP
+
+Automate Zendesk operations through Composio's Zendesk toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Zendesk connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `zendesk`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `zendesk`
+3. If connection is not ACTIVE, follow the returned auth link to complete Zendesk auth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. List and Search Tickets
+
+**When to use**: User wants to view, filter, or search support tickets
+
+**Tool sequence**:
+1. `ZENDESK_LIST_ZENDESK_TICKETS` - List all tickets with pagination [Required]
+2. `ZENDESK_GET_ZENDESK_TICKET_BY_ID` - Get specific ticket details [Optional]
+
+**Key parameters**:
+- `page`: Page number (1-based)
+- `per_page`: Results per page (max 100)
+- `sort_by`: Sort field ('created_at', 'updated_at', 'priority', 'status')
+- `sort_order`: 'asc' or 'desc'
+- `ticket_id`: Ticket ID for single retrieval
+
+**Pitfalls**:
+- LIST uses `page`/`per_page` pagination, NOT offset-based; check `next_page` in response
+- Maximum 100 results per page; iterate with page numbers until `next_page` is null
+- Deleted tickets are not returned by LIST; use GET_BY_ID which returns status 'deleted'
+- Ticket comments and audits are included in GET_BY_ID but not in LIST responses
+
+### 2. Create and Update Tickets
+
+**When to use**: User wants to create new tickets or modify existing ones
+
+**Tool sequence**:
+1. `ZENDESK_SEARCH_ZENDESK_USERS` - Find requester/assignee [Prerequisite]
+2. `ZENDESK_CREATE_ZENDESK_TICKET` - Create a new ticket [Required]
+3. `ZENDESK_UPDATE_ZENDESK_TICKET` - Update ticket fields [Optional]
+4. `ZENDESK_DELETE_ZENDESK_TICKET` - Delete a ticket [Optional]
+
+**Key parameters**:
+- `subject`: Ticket subject line
+- `description`: Ticket body (for creation; becomes first comment)
+- `priority`: 'urgent', 'high', 'normal', 'low'
+- `status`: 'new', 'open', 'pending', 'hold', 'solved', 'closed'
+- `type`: 'problem', 'incident', 'question', 'task'
+- `assignee_id`: Agent user ID to assign
+- `requester_id`: Requester user ID
+- `tags`: Array of tag strings
+- `ticket_id`: Ticket ID (for update/delete)
+
+**Pitfalls**:
+- Tags on UPDATE REPLACE existing tags entirely; merge with current tags to preserve them
+- Use `safe_update` with `updated_stamp` to prevent concurrent modification conflicts
+- DELETE is permanent and irreversible; tickets cannot be recovered
+- `description` is only used on creation; use REPLY_ZENDESK_TICKET to add comments after creation
+- Closed tickets cannot be updated; create a follow-up ticket instead
+
+### 3. Reply to Tickets
+
+**When to use**: User wants to add comments or replies to tickets
+
+**Tool sequence**:
+1. `ZENDESK_GET_ZENDESK_TICKET_BY_ID` - Get current ticket state [Prerequisite]
+2. `ZENDESK_REPLY_ZENDESK_TICKET` - Add a reply/comment [Required]
+
+**Key parameters**:
+- `ticket_id`: Ticket ID to reply to
+- `body`: Reply text content
+- `public`: Boolean; true for public reply, false for internal note
+- `author_id`: Author user ID (defaults to authenticated user)
+
+**Pitfalls**:
+- Set `public: false` for internal notes visible only to agents
+- Default is public reply which sends email to requester
+- HTML is supported in body text
+- Replying can also update ticket status simultaneously
+
+### 4. Manage Users
+
+**When to use**: User wants to find or create Zendesk users (agents, end-users)
+
+**Tool sequence**:
+1. `ZENDESK_SEARCH_ZENDESK_USERS` - Search for users [Required]
+2. `ZENDESK_CREATE_ZENDESK_USER` - Create a new user [Optional]
+3. `ZENDESK_GET_ABOUT_ME` - Get authenticated user info [Optional]
+
+**Key parameters**:
+- `query`: Search string (matches name, email, phone, etc.)
+- `name`: User's full name (required for creation)
+- `email`: User's email address
+- `role`: 'end-user', 'agent', or 'admin'
+- `verified`: Whether email is verified
+
+**Pitfalls**:
+- User search is fuzzy; may return partial matches
+- Creating a user with an existing email returns the existing user (upsert behavior)
+- Agent and admin roles may require specific plan features
+
+### 5. Manage Organizations
+
+**When to use**: User wants to list, create, or manage organizations
+
+**Tool sequence**:
+1. `ZENDESK_GET_ALL_ZENDESK_ORGANIZATIONS` - List all organizations [Required]
+2. `ZENDESK_GET_ZENDESK_ORGANIZATION` - Get specific organization [Optional]
+3. `ZENDESK_CREATE_ZENDESK_ORGANIZATION` - Create organization [Optional]
+4. `ZENDESK_UPDATE_ZENDESK_ORGANIZATION` - Update organization [Optional]
+5. `ZENDESK_COUNT_ZENDESK_ORGANIZATIONS` - Get total count [Optional]
+
+**Key parameters**:
+- `name`: Organization name (unique, required for creation)
+- `organization_id`: Organization ID for get/update
+- `details`: Organization details text
+- `notes`: Internal notes
+- `domain_names`: Array of associated domains
+- `tags`: Array of tag strings
+
+**Pitfalls**:
+- Organization names must be unique; duplicate names cause creation errors
+- Tags on UPDATE REPLACE existing tags (same behavior as tickets)
+- Domain names can be used for automatic user association
+
+## Common Patterns
+
+### Pagination
+
+**List endpoints**:
+- Use `page` (1-based) and `per_page` (max 100)
+- Check `next_page` URL in response; null means last page
+- `count` field gives total results
+
+### Ticket Lifecycle
+
+```
+new -> open -> pending -> solved -> closed
+ | ^
+ v |
+ hold --------+
+```
+
+- `new`: Unassigned ticket
+- `open`: Assigned, being worked on
+- `pending`: Waiting for customer response
+- `hold`: Waiting for internal action
+- `solved`: Resolved, can be reopened
+- `closed`: Permanently closed, cannot be modified
+
+### User Search for Assignment
+
+```
+1. Call ZENDESK_SEARCH_ZENDESK_USERS with query (name or email)
+2. Extract user ID from results
+3. Use user ID as assignee_id in ticket creation/update
+```
+
+## Known Pitfalls
+
+**Tags Behavior**:
+- Tags on update REPLACE all existing tags
+- Always fetch current tags first and merge before updating
+- Tags are lowercase, no spaces (use underscores)
+
+**Safe Updates**:
+- Use `safe_update: true` with `updated_stamp` (ISO 8601) to prevent conflicts
+- Returns 409 if ticket was modified since the stamp
+
+**Deletion**:
+- Ticket deletion is permanent and irreversible
+- Consider setting status to 'closed' instead of deleting
+- Deleted tickets cannot be recovered via API
+
+**Rate Limits**:
+- Default: 400 requests per minute
+- Varies by plan tier
+- 429 responses include Retry-After header
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List tickets | ZENDESK_LIST_ZENDESK_TICKETS | page, per_page, sort_by |
+| Get ticket | ZENDESK_GET_ZENDESK_TICKET_BY_ID | ticket_id |
+| Create ticket | ZENDESK_CREATE_ZENDESK_TICKET | subject, description, priority |
+| Update ticket | ZENDESK_UPDATE_ZENDESK_TICKET | ticket_id, status, tags |
+| Reply to ticket | ZENDESK_REPLY_ZENDESK_TICKET | ticket_id, body, public |
+| Delete ticket | ZENDESK_DELETE_ZENDESK_TICKET | ticket_id |
+| Search users | ZENDESK_SEARCH_ZENDESK_USERS | query |
+| Create user | ZENDESK_CREATE_ZENDESK_USER | name, email |
+| My profile | ZENDESK_GET_ABOUT_ME | (none) |
+| List orgs | ZENDESK_GET_ALL_ZENDESK_ORGANIZATIONS | page, per_page |
+| Get org | ZENDESK_GET_ZENDESK_ORGANIZATION | organization_id |
+| Create org | ZENDESK_CREATE_ZENDESK_ORGANIZATION | name |
+| Update org | ZENDESK_UPDATE_ZENDESK_ORGANIZATION | organization_id, name |
+| Count orgs | ZENDESK_COUNT_ZENDESK_ORGANIZATIONS | (none) |
diff --git a/zoho-crm-automation/SKILL.md b/zoho-crm-automation/SKILL.md
new file mode 100644
index 0000000..8b2f022
--- /dev/null
+++ b/zoho-crm-automation/SKILL.md
@@ -0,0 +1,203 @@
+---
+name: zoho-crm-automation
+description: Automate Zoho CRM tasks via Rube MCP (Composio): create/update records, search contacts, manage leads, and convert leads. Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Zoho CRM Automation via Rube MCP
+
+Automate Zoho CRM operations through Composio's Zoho toolkit via Rube MCP.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Zoho CRM connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `zoho`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `zoho`
+3. If connection is not ACTIVE, follow the returned auth link to complete Zoho OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Search and Retrieve Records
+
+**When to use**: User wants to find specific CRM records by criteria
+
+**Tool sequence**:
+1. `ZOHO_LIST_MODULES` - List available CRM modules [Prerequisite]
+2. `ZOHO_GET_MODULE_FIELDS` - Get field definitions for a module [Optional]
+3. `ZOHO_SEARCH_ZOHO_RECORDS` - Search records by criteria [Required]
+4. `ZOHO_GET_ZOHO_RECORDS` - Get records from a module [Alternative]
+
+**Key parameters**:
+- `module`: Module name (e.g., 'Leads', 'Contacts', 'Deals', 'Accounts')
+- `criteria`: Search criteria string (e.g., 'Email:equals:john@example.com')
+- `fields`: Comma-separated list of fields to return
+- `per_page`: Number of records per page
+- `page`: Page number for pagination
+
+**Pitfalls**:
+- Module names are case-sensitive (e.g., 'Leads' not 'leads')
+- Search criteria uses specific syntax: 'Field:operator:value'
+- Supported operators: equals, starts_with, contains, not_equal, greater_than, less_than
+- Complex criteria use parentheses and AND/OR: '(Email:equals:john@example.com)AND(Last_Name:equals:Doe)'
+- GET_ZOHO_RECORDS returns all records with optional filtering; SEARCH is for targeted lookups
+
+### 2. Create Records
+
+**When to use**: User wants to add new leads, contacts, deals, or other CRM records
+
+**Tool sequence**:
+1. `ZOHO_GET_MODULE_FIELDS` - Get required fields for the module [Prerequisite]
+2. `ZOHO_CREATE_ZOHO_RECORD` - Create a new record [Required]
+
+**Key parameters**:
+- `module`: Target module name (e.g., 'Leads', 'Contacts')
+- `data`: Record data object with field-value pairs
+- Required fields vary by module (e.g., Last_Name for Contacts)
+
+**Pitfalls**:
+- Each module has mandatory fields; use GET_MODULE_FIELDS to identify them
+- Field names use underscores (e.g., 'Last_Name', 'Email', 'Phone')
+- Lookup fields require the related record ID, not the name
+- Date fields must use 'yyyy-MM-dd' format
+- Creating duplicates is allowed unless duplicate check rules are configured
+
+### 3. Update Records
+
+**When to use**: User wants to modify existing CRM records
+
+**Tool sequence**:
+1. `ZOHO_SEARCH_ZOHO_RECORDS` - Find the record to update [Prerequisite]
+2. `ZOHO_UPDATE_ZOHO_RECORD` - Update the record [Required]
+
+**Key parameters**:
+- `module`: Module name
+- `record_id`: ID of the record to update
+- `data`: Object with fields to update (only changed fields needed)
+
+**Pitfalls**:
+- record_id must be the Zoho record ID (numeric string)
+- Only provide fields that need to change; other fields are preserved
+- Read-only and system fields cannot be updated
+- Lookup field updates require the related record ID
+
+### 4. Convert Leads
+
+**When to use**: User wants to convert a lead into a contact, account, and/or deal
+
+**Tool sequence**:
+1. `ZOHO_SEARCH_ZOHO_RECORDS` - Find the lead to convert [Prerequisite]
+2. `ZOHO_CONVERT_ZOHO_LEAD` - Convert the lead [Required]
+
+**Key parameters**:
+- `lead_id`: ID of the lead to convert
+- `deal`: Deal details if creating a deal during conversion
+- `account`: Account details for the conversion
+- `contact`: Contact details for the conversion
+
+**Pitfalls**:
+- Lead conversion is irreversible; the lead record is removed from the Leads module
+- Conversion can create up to three records: Contact, Account, and Deal
+- Existing account matching may occur based on company name
+- Custom field mappings between Lead and Contact/Account/Deal modules affect the outcome
+
+### 5. Manage Tags and Related Records
+
+**When to use**: User wants to tag records or manage relationships between records
+
+**Tool sequence**:
+1. `ZOHO_CREATE_ZOHO_TAG` - Create a new tag [Optional]
+2. `ZOHO_UPDATE_RELATED_RECORDS` - Update related/linked records [Optional]
+
+**Key parameters**:
+- `module`: Module for the tag
+- `tag_name`: Name of the tag
+- `record_id`: Parent record ID (for related records)
+- `related_module`: Module of the related record
+- `data`: Related record data to update
+
+**Pitfalls**:
+- Tags are module-specific; a tag created for Leads is not available in Contacts
+- Related records require both the parent record ID and the related module
+- Tag names must be unique within a module
+- Bulk tag operations may hit rate limits
+
+## Common Patterns
+
+### Module and Field Discovery
+
+```
+1. Call ZOHO_LIST_MODULES to get all available modules
+2. Call ZOHO_GET_MODULE_FIELDS with module name
+3. Identify required fields, field types, and picklist values
+4. Use field API names (not display labels) in data objects
+```
+
+### Search Criteria Syntax
+
+**Simple search**:
+```
+criteria: '(Email:equals:john@example.com)'
+```
+
+**Combined criteria**:
+```
+criteria: '((Last_Name:equals:Doe)AND(Email:contains:example.com))'
+```
+
+**Supported operators**:
+- `equals`, `not_equal`
+- `starts_with`, `contains`
+- `greater_than`, `less_than`, `greater_equal`, `less_equal`
+- `between` (for dates/numbers)
+
+### Pagination
+
+- Set `per_page` (max 200) and `page` starting at 1
+- Check response `info.more_records` flag
+- Increment page until more_records is false
+- Total count available in response info
+
+## Known Pitfalls
+
+**Field Names**:
+- Use API names, not display labels (e.g., 'Last_Name' not 'Last Name')
+- Custom fields have API names like 'Custom_Field1' or user-defined names
+- Picklist values must match exactly (case-sensitive)
+
+**Rate Limits**:
+- API call limits depend on your Zoho CRM plan
+- Free plan: 5000 API calls/day; Enterprise: 25000+/day
+- Implement delays between bulk operations
+- Monitor 429 responses and respect rate limit headers
+
+**Data Formats**:
+- Dates: 'yyyy-MM-dd' format
+- DateTime: 'yyyy-MM-ddTHH:mm:ss+HH:mm' format
+- Currency: Numeric values without formatting
+- Phone: String values (no specific format enforced)
+
+**Module Access**:
+- Access depends on user role and profile permissions
+- Some modules may be hidden or restricted in your CRM setup
+- Custom modules have custom API names
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| List modules | ZOHO_LIST_MODULES | (none) |
+| Get module fields | ZOHO_GET_MODULE_FIELDS | module |
+| Search records | ZOHO_SEARCH_ZOHO_RECORDS | module, criteria |
+| Get records | ZOHO_GET_ZOHO_RECORDS | module, fields, per_page, page |
+| Create record | ZOHO_CREATE_ZOHO_RECORD | module, data |
+| Update record | ZOHO_UPDATE_ZOHO_RECORD | module, record_id, data |
+| Convert lead | ZOHO_CONVERT_ZOHO_LEAD | lead_id, deal, account, contact |
+| Create tag | ZOHO_CREATE_ZOHO_TAG | module, tag_name |
+| Update related records | ZOHO_UPDATE_RELATED_RECORDS | module, record_id, related_module, data |
diff --git a/zoom-automation/SKILL.md b/zoom-automation/SKILL.md
new file mode 100644
index 0000000..fc8d7de
--- /dev/null
+++ b/zoom-automation/SKILL.md
@@ -0,0 +1,214 @@
+---
+name: zoom-automation
+description: Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current schemas.
+requires:
+ mcp: [rube]
+---
+
+# Zoom Automation via Rube MCP
+
+Automate Zoom operations including meeting scheduling, webinar management, cloud recording retrieval, participant tracking, and usage reporting through Composio's Zoom toolkit.
+
+## Prerequisites
+
+- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
+- Active Zoom connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `zoom`
+- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
+- Most features require a paid Zoom account (Pro plan or higher)
+
+## Setup
+
+1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
+2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `zoom`
+3. If connection is not ACTIVE, follow the returned auth link to complete Zoom OAuth
+4. Confirm connection status shows ACTIVE before running any workflows
+
+## Core Workflows
+
+### 1. Create and Schedule Meetings
+
+**When to use**: User wants to create a new Zoom meeting with specific time, duration, and settings
+
+**Tool sequence**:
+1. `ZOOM_GET_USER` - Verify authenticated user and check license type [Prerequisite]
+2. `ZOOM_CREATE_A_MEETING` - Create the meeting with topic, time, duration, and settings [Required]
+3. `ZOOM_GET_A_MEETING` - Retrieve full meeting details including join_url [Optional]
+4. `ZOOM_UPDATE_A_MEETING` - Modify meeting settings or reschedule [Optional]
+5. `ZOOM_ADD_A_MEETING_REGISTRANT` - Register participants for registration-enabled meetings [Optional]
+
+**Key parameters**:
+- `userId`: Always use `"me"` for user-level apps
+- `topic`: Meeting subject line
+- `type`: `1` (instant), `2` (scheduled), `3` (recurring no fixed time), `8` (recurring fixed time)
+- `start_time`: ISO 8601 format (`yyyy-MM-ddTHH:mm:ssZ` for UTC or `yyyy-MM-ddTHH:mm:ss` with timezone field)
+- `timezone`: Timezone ID (e.g., `"America/New_York"`)
+- `duration`: Duration in minutes
+- `settings__auto_recording`: `"none"`, `"local"`, or `"cloud"`
+- `settings__waiting_room`: Boolean to enable waiting room
+- `settings__join_before_host`: Boolean (disabled when waiting room is enabled)
+- `settings__meeting_invitees`: Array of invitee objects with email addresses
+
+**Pitfalls**:
+- `start_time` must be in the future; Zoom stores and returns times in UTC regardless of input timezone
+- If no `start_time` is set for type `2`, it becomes an instant meeting that expires after 30 days
+- The `join_url` for participants and `start_url` for host come from the create response - persist these
+- `start_url` expires in 2 hours (or 90 days for `custCreate` users)
+- Meeting creation is rate-limited to 100 requests/day
+- Setting names use double underscores for nesting (e.g., `settings__host_video`)
+
+### 2. List and Manage Meetings
+
+**When to use**: User wants to view upcoming, live, or past meetings
+
+**Tool sequence**:
+1. `ZOOM_LIST_MEETINGS` - List meetings by type (scheduled, live, upcoming, previous) [Required]
+2. `ZOOM_GET_A_MEETING` - Get detailed info for a specific meeting [Optional]
+3. `ZOOM_UPDATE_A_MEETING` - Modify meeting details [Optional]
+
+**Key parameters**:
+- `userId`: Use `"me"` for authenticated user
+- `type`: `"scheduled"` (default), `"live"`, `"upcoming"`, `"upcoming_meetings"`, `"previous_meetings"`
+- `page_size`: Records per page (default 30)
+- `next_page_token`: Pagination token from previous response
+- `from` / `to`: Date range filters
+
+**Pitfalls**:
+- `ZOOM_LIST_MEETINGS` excludes instant meetings and only shows unexpired scheduled meetings
+- For past meetings, use `type: "previous_meetings"`
+- Pagination: always follow `next_page_token` until empty to get complete results
+- Token expiration: `next_page_token` expires after 15 minutes
+- Meeting IDs can exceed 10 digits; store as long integers, not standard integers
+
+### 3. Manage Recordings
+
+**When to use**: User wants to list, retrieve, or delete cloud recordings
+
+**Tool sequence**:
+1. `ZOOM_LIST_ALL_RECORDINGS` - List all cloud recordings for a user within a date range [Required]
+2. `ZOOM_GET_MEETING_RECORDINGS` - Get recordings for a specific meeting [Optional]
+3. `ZOOM_DELETE_MEETING_RECORDINGS` - Move recordings to trash or permanently delete [Optional]
+4. `ZOOM_LIST_ARCHIVED_FILES` - List archived meeting/webinar files [Optional]
+
+**Key parameters**:
+- `userId`: Use `"me"` for authenticated user
+- `from` / `to`: Date range in `yyyy-mm-dd` format (max 1 month range)
+- `meetingId`: Meeting ID or UUID for specific recording retrieval
+- `action`: `"trash"` (recoverable) or `"delete"` (permanent) for deletion
+- `include_fields`: Set to `"download_access_token"` to get JWT for downloading recordings
+- `trash`: Set `true` to list recordings from trash
+
+**Pitfalls**:
+- Date range maximum is 1 month; API auto-adjusts `from` if range exceeds this
+- Cloud Recording must be enabled on the account
+- UUIDs starting with `/` or containing `//` must be double URL-encoded
+- `ZOOM_DELETE_MEETING_RECORDINGS` defaults to `"trash"` action (recoverable); `"delete"` is permanent
+- Download URLs require the OAuth token in the Authorization header for passcode-protected recordings
+- Requires Pro plan or higher
+
+### 4. Get Meeting Participants and Reports
+
+**When to use**: User wants to see who attended a past meeting or get usage statistics
+
+**Tool sequence**:
+1. `ZOOM_GET_PAST_MEETING_PARTICIPANTS` - List attendees of a completed meeting [Required]
+2. `ZOOM_GET_A_MEETING` - Get meeting details and registration info for upcoming meetings [Optional]
+3. `ZOOM_GET_DAILY_USAGE_REPORT` - Get daily usage statistics (meetings, participants, minutes) [Optional]
+4. `ZOOM_GET_A_MEETING_SUMMARY` - Get AI-generated meeting summary [Optional]
+
+**Key parameters**:
+- `meetingId`: Meeting ID (latest instance) or UUID (specific occurrence)
+- `page_size`: Records per page (default 30)
+- `next_page_token`: Pagination token for large participant lists
+
+**Pitfalls**:
+- `ZOOM_GET_PAST_MEETING_PARTICIPANTS` only works for completed meetings on paid plans
+- Solo meetings (no other participants) return empty results
+- UUID encoding: UUIDs starting with `/` or containing `//` must be double-encoded
+- Always paginate with `next_page_token` until empty to avoid dropping attendees
+- `ZOOM_GET_A_MEETING_SUMMARY` requires a paid plan with AI Companion enabled; free accounts get 400 errors
+- `ZOOM_GET_DAILY_USAGE_REPORT` has a Heavy rate limit; avoid frequent calls
+
+### 5. Manage Webinars
+
+**When to use**: User wants to list webinars or register participants for webinars
+
+**Tool sequence**:
+1. `ZOOM_LIST_WEBINARS` - List scheduled or upcoming webinars [Required]
+2. `ZOOM_GET_A_WEBINAR` - Get detailed webinar information [Optional]
+3. `ZOOM_ADD_A_WEBINAR_REGISTRANT` - Register a participant for a webinar [Optional]
+
+**Key parameters**:
+- `userId`: Use `"me"` for authenticated user
+- `type`: `"scheduled"` (default) or `"upcoming"`
+- `page_size`: Records per page (default 30)
+- `next_page_token`: Pagination token
+
+**Pitfalls**:
+- Webinar features require Pro plan or higher with Webinar add-on
+- Free/basic accounts cannot use webinar tools
+- Only shows unexpired webinars
+- Registration must be enabled on the webinar for `ZOOM_ADD_A_WEBINAR_REGISTRANT` to work
+
+## Common Patterns
+
+### ID Resolution
+- **User ID**: Always use `"me"` for user-level apps to refer to the authenticated user
+- **Meeting ID**: Numeric ID (store as long integer); use for latest instance
+- **Meeting UUID**: Use for specific occurrence of recurring meetings; double-encode if starts with `/` or contains `//`
+- **Occurrence ID**: Use with recurring meetings to target a specific occurrence
+
+### Pagination
+Most Zoom list endpoints use token-based pagination:
+- Follow `next_page_token` until it is empty or missing
+- Token expires after 15 minutes
+- Set explicit `page_size` (default 30, varies by endpoint)
+- Do not use `page_number` (deprecated on many endpoints)
+
+### Time Handling
+- Zoom stores all times in UTC internally
+- Provide `timezone` field alongside `start_time` for local time input
+- Use ISO 8601 format: `yyyy-MM-ddTHH:mm:ssZ` (UTC) or `yyyy-MM-ddTHH:mm:ss` (with timezone field)
+- Date-only fields use `yyyy-mm-dd` format
+
+## Known Pitfalls
+
+### Plan Requirements
+- Most recording and participant features require Pro plan or higher
+- Webinar features require Webinar add-on
+- AI meeting summaries require AI Companion feature enabled
+- Archived files require "Meeting and Webinar Archiving" enabled by Zoom Support
+
+### Rate Limits
+- Meeting creation: 100 requests/day, 100 updates per meeting in 24 hours
+- `ZOOM_GET_PAST_MEETING_PARTICIPANTS`: Moderate throttle; add delays for batch processing
+- `ZOOM_GET_DAILY_USAGE_REPORT`: Heavy rate limit
+- `ZOOM_GET_A_MEETING`, `ZOOM_GET_MEETING_RECORDINGS`: Light rate limit
+- `ZOOM_LIST_MEETINGS`, `ZOOM_LIST_ALL_RECORDINGS`: Medium rate limit
+
+### Parameter Quirks
+- Nested settings use double underscore notation (e.g., `settings__waiting_room`)
+- `start_url` expires in 2 hours; renew via API if needed
+- `join_before_host` is automatically disabled when `waiting_room` is `true`
+- Recurring meeting fields (`recurrence__*`) only apply to type `3` and `8`
+- `password` field has max 10 characters with alphanumeric and `@`, `-`, `_`, `*` only
+
+## Quick Reference
+
+| Task | Tool Slug | Key Params |
+|------|-----------|------------|
+| Create meeting | `ZOOM_CREATE_A_MEETING` | `userId`, `topic`, `start_time`, `type` |
+| Get meeting details | `ZOOM_GET_A_MEETING` | `meetingId` |
+| Update meeting | `ZOOM_UPDATE_A_MEETING` | `meetingId`, fields to update |
+| List meetings | `ZOOM_LIST_MEETINGS` | `userId`, `type`, `page_size` |
+| Get user info | `ZOOM_GET_USER` | `userId` |
+| List recordings | `ZOOM_LIST_ALL_RECORDINGS` | `userId`, `from`, `to` |
+| Get recording | `ZOOM_GET_MEETING_RECORDINGS` | `meetingId` |
+| Delete recording | `ZOOM_DELETE_MEETING_RECORDINGS` | `meetingId`, `action` |
+| Past participants | `ZOOM_GET_PAST_MEETING_PARTICIPANTS` | `meetingId`, `page_size` |
+| Daily usage report | `ZOOM_GET_DAILY_USAGE_REPORT` | date params |
+| Meeting summary | `ZOOM_GET_A_MEETING_SUMMARY` | `meetingId` |
+| List webinars | `ZOOM_LIST_WEBINARS` | `userId`, `type` |
+| Get webinar | `ZOOM_GET_A_WEBINAR` | webinar ID |
+| Register for meeting | `ZOOM_ADD_A_MEETING_REGISTRANT` | `meetingId`, participant details |
+| Register for webinar | `ZOOM_ADD_A_WEBINAR_REGISTRANT` | webinar ID, participant details |
+| List archived files | `ZOOM_LIST_ARCHIVED_FILES` | `from`, `to` |