diff --git a/skills/activecampaign-automation/SKILL.md b/skills/activecampaign-automation/SKILL.md new file mode 100644 index 00000000..f618bc0e --- /dev/null +++ b/skills/activecampaign-automation/SKILL.md @@ -0,0 +1,209 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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/skills/airtable-automation/SKILL.md b/skills/airtable-automation/SKILL.md new file mode 100644 index 00000000..1a39963c --- /dev/null +++ b/skills/airtable-automation/SKILL.md @@ -0,0 +1,170 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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/skills/amplitude-automation/SKILL.md b/skills/amplitude-automation/SKILL.md new file mode 100644 index 00000000..c9b23c0f --- /dev/null +++ b/skills/amplitude-automation/SKILL.md @@ -0,0 +1,216 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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/skills/asana-automation/SKILL.md b/skills/asana-automation/SKILL.md new file mode 100644 index 00000000..63e7b83a --- /dev/null +++ b/skills/asana-automation/SKILL.md @@ -0,0 +1,171 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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/skills/bamboohr-automation/SKILL.md b/skills/bamboohr-automation/SKILL.md new file mode 100644 index 00000000..7c075a85 --- /dev/null +++ b/skills/bamboohr-automation/SKILL.md @@ -0,0 +1,220 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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/skills/basecamp-automation/SKILL.md b/skills/basecamp-automation/SKILL.md new file mode 100644 index 00000000..6f27369e --- /dev/null +++ b/skills/basecamp-automation/SKILL.md @@ -0,0 +1,234 @@ +--- +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 + +**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works. + + +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 `
` tags; use ``, ``, `