From 41fb6ade25a1f398e9e86b16e7ad7bc0a1eb5c7a Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 10:54:16 +0000 Subject: [PATCH 1/8] Add CLAUDE.md to orient Claude Code in this repository Provides architecture overview, skill documentation, key conventions (security-first defaults, progressive disclosure, read-only access), and development workflow for this declarative plugin. Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..639ca15 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,54 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Is + +Intercom plugin for Claude Code — a skill-based integration (not compiled code). Skills are pure Markdown files that Claude reads at runtime to interact with Intercom workspaces via a remote MCP server. + +## Architecture + +``` +User → Claude Code CLI → Skill (SKILL.md) → MCP Server (https://mcp.intercom.com/mcp) → Intercom API +``` + +- **No build step, no dependencies, no tests.** The plugin is entirely declarative. +- `.mcp.json` routes the `intercom` namespace to the remote HTTP-based MCP server. +- `.claude-plugin/plugin.json` is the plugin manifest for Claude Code's plugin registry. +- `.claude/settings.local.json` manages local permissions (currently allows WebFetch from raw.githubusercontent.com). + +## Skills + +Three skills live under `skills/`, each in its own directory: + +| Skill | Trigger | Key Files | +| ------------------- | ---------------------------------------------------- | -------------------------------------------- | +| `install-messenger` | Explicit: `/intercom:install-messenger [framework]` | `SKILL.md`, `references/framework-guides.md` | +| `intercom-insights` | Auto-triggered by keywords | `SKILL.md`, `references/mcp-tools.md` | +| `intercom-search` | Explicit: `/intercom:intercom-search [type] [query]` | `SKILL.md` | + +### Skill File Structure + +Each skill directory contains: + +- `SKILL.md` — Main skill file with YAML frontmatter (`name`, `description`, optional `disable-model-invocation`, `argument-hint`) followed by Markdown instructions Claude reads at runtime. +- `references/` — Supplementary docs loaded on demand for progressive disclosure (keeps SKILL.md concise). + +### Invocation Modes + +- **Auto-triggered:** No `disable-model-invocation` in frontmatter. Claude activates the skill when the user's intent matches the `description` field. +- **Explicit:** `disable-model-invocation: true` in frontmatter. Only invoked via `/intercom:`. + +## Key Conventions + +- **Security-first:** `install-messenger` defaults to JWT-based identity verification (HS256). Insecure mode requires explicit user opt-in. Never default to insecure installation. +- **Progressive disclosure:** Keep SKILL.md focused on workflow logic. Move API references, framework-specific code, and tool documentation into `references/` subdirectories. +- **Read-only access:** The MCP server only supports search and retrieval operations — no create, update, or delete. +- **Regional awareness:** Intercom supports US, EU (Ireland), and Australia data residency. Currently US-only; EU/AU planned. + +## Development Workflow + +1. Edit SKILL.md files or reference documents +2. Test by running skills in Claude Code CLI (e.g., `/intercom:install-messenger react`) +3. For auto-triggered skills, test by typing natural language that matches the skill's `description` field +4. Push to GitHub — the plugin registry picks up changes from the repository From 2042dbf7ab17a672a76fe7c6f29d596001349e9b Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 11:17:29 +0000 Subject: [PATCH 2/8] Fix missing api_base in React SDK Messenger examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The React @intercom/messenger-js-sdk examples omitted api_base from both the authenticated and anonymous Intercom() calls. Next.js and Vue.js examples already included it. Without api_base, EU and AU customers silently hit the wrong data center — requests succeed but return no data. Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/install-messenger/references/framework-guides.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/skills/install-messenger/references/framework-guides.md b/skills/install-messenger/references/framework-guides.md index f1d4172..343a48d 100644 --- a/skills/install-messenger/references/framework-guides.md +++ b/skills/install-messenger/references/framework-guides.md @@ -42,6 +42,7 @@ export function IntercomProvider({ appId, isAuthenticated, children }: IntercomP .then(res => res.json()) .then(({ token }) => { Intercom({ + api_base: 'https://api-iam.intercom.io', app_id: appId, intercom_user_jwt: token, }); @@ -49,6 +50,7 @@ export function IntercomProvider({ appId, isAuthenticated, children }: IntercomP } else { // Anonymous visitor — no JWT needed Intercom({ + api_base: 'https://api-iam.intercom.io', app_id: appId, }); } From 68e5f891ac48f777a6ad9fd3b22010b346805f9d Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 11:17:38 +0000 Subject: [PATCH 3/8] Remove intercom-search skill This skill was a thin wrapper around MCP tool calls that Claude can already perform natively. Its trigger phrases overlapped with intercom-insights, causing ambiguous skill activation. Useful UX patterns (table formatting, follow-up suggestions, empty-result recovery) have been folded into the intercom-analysis skill. Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/intercom-search/SKILL.md | 73 --------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 skills/intercom-search/SKILL.md diff --git a/skills/intercom-search/SKILL.md b/skills/intercom-search/SKILL.md deleted file mode 100644 index 7ca6060..0000000 --- a/skills/intercom-search/SKILL.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -name: intercom-search -description: > - This skill should be used when the user asks to "search Intercom", - "find conversations about", "look up contacts", "search for a customer", - or wants to quickly query Intercom conversations or contacts by keyword, - email, or topic. -argument-hint: "[conversations|contacts] [query]" ---- - -# Intercom Search - -Perform a quick search against the user's Intercom workspace. Parse the user's intent, call the appropriate MCP tool, and return formatted results. - -## Parse Arguments - -Extract two pieces of information from the user's input: - -1. **Object type** — What to search for: - - `conversations` — If the user mentions conversations, tickets, messages, chats, or support threads - - `contacts` — If the user mentions contacts, customers, users, leads, people, or emails - - If ambiguous, default to `conversations` and mention that the user can also search contacts - -2. **Query** — The search term: - - Keywords or phrases (e.g., "billing issue", "timeout error") - - Email addresses (e.g., "jane@example.com") — implies a contacts search - - A name (e.g., "Jane Doe") — implies a contacts search - - A topic (e.g., "pricing", "onboarding") — implies a conversations search - -## Execute Search - -### For Conversations - -Use the `search_conversations` MCP tool. If the user provided keywords, search conversation content. If they specified a state (open, closed, snoozed), apply that as a filter. Default to searching across all states. - -### For Contacts - -Use the `search_contacts` MCP tool. If the user provided an email address, filter by the `email` field. If they provided a name, filter by the `name` field. For domain searches (e.g., "@acme.com"), use the contains operator on the `email` field. - -## Format Results - -Present results as a clean, scannable table: - -### Conversation Results - -| ID | Subject | State | Last Updated | -|----|---------|-------|-------------| -| #12345 | Cannot access billing portal | open | 2 hours ago | -| #12340 | Billing charge question | closed | 1 day ago | -| #12332 | Update payment method | closed | 3 days ago | - -### Contact Results - -| ID | Name | Email | Last Seen | -|----|------|-------|-----------| -| contact_abc | Jane Doe | jane@example.com | 2 hours ago | -| contact_def | John Smith | john@example.com | 5 days ago | - -Use relative timestamps (e.g., "2 hours ago", "3 days ago") for readability. - -## Follow-Up - -After displaying results, offer to fetch full details for any item: - -- "Want me to pull up the full thread for conversation #12345?" -- "I can get the complete profile for Jane Doe — want to see it?" - -If the search returned no results, suggest: -- Broadening the query (fewer or different keywords) -- Searching the other object type (contacts instead of conversations, or vice versa) -- Checking for typos in email addresses or names - -If results are paginated (more results available), let the user know and offer to fetch the next page. From 239733fd41ec14bd4738b0de99f8be616f40ca6f Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 11:17:48 +0000 Subject: [PATCH 4/8] Rename intercom-insights to intercom-analysis and restructure Restructure the skill to lead with workflows rather than API docs: - Rename directory from intercom-insights/ to intercom-analysis/ - Rewrite SKILL.md: remove tool documentation (~40 lines), keep workflow steps verbatim, add defined output artifacts for both pattern analysis and issue investigation, add troubleshooting section - Incorporate salvaged UX patterns from intercom-search (table formatting, follow-up suggestions, empty-result recovery) into Best Practices - Add Tool Selection Guide, Conversation Search Strategies, and Contact Lookup Strategies to references/mcp-tools.md where the content belongs This follows the progressive disclosure pattern: SKILL.md focuses on what to do (workflows), mcp-tools.md covers how (API details), loaded only when needed. Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/intercom-analysis/SKILL.md | 101 +++++++++++++++ .../references/mcp-tools.md | 47 +++++++ skills/intercom-insights/SKILL.md | 122 ------------------ 3 files changed, 148 insertions(+), 122 deletions(-) create mode 100644 skills/intercom-analysis/SKILL.md rename skills/{intercom-insights => intercom-analysis}/references/mcp-tools.md (67%) delete mode 100644 skills/intercom-insights/SKILL.md diff --git a/skills/intercom-analysis/SKILL.md b/skills/intercom-analysis/SKILL.md new file mode 100644 index 0000000..f29e07a --- /dev/null +++ b/skills/intercom-analysis/SKILL.md @@ -0,0 +1,101 @@ +--- +name: intercom-analysis +license: MIT +description: > + Analyze Intercom conversations to identify support patterns, investigate + customer issues, and look up contacts and companies. Use when the user asks + to "analyze conversations", "find support patterns", "search Intercom", + "look up a customer", "investigate a customer issue", "check contact info", + or asks questions about their Intercom data. +--- + +# Intercom Analysis + +Use the Intercom MCP server to analyze customer conversations, look up contacts and companies, identify support patterns, and investigate customer issues. + +Refer to `references/mcp-tools.md` for detailed tool reference, query DSL syntax, search strategies, and field-level documentation for each MCP tool. + +## Pattern Analysis Workflow + +When the user asks to analyze patterns or trends in their support data, follow this workflow: + +1. **Define scope.** Clarify what the user wants to analyze — a time period, topic, customer segment, or conversation state. Ask if unclear. + +2. **Fetch a representative sample.** Search for conversations matching the scope. Retrieve at least 10–20 conversations to establish meaningful patterns. Paginate if the first page is insufficient. + +3. **Read conversation details.** For each relevant conversation, fetch the full conversation to read the actual messages. Summaries from search results alone are often insufficient for pattern analysis. + +4. **Identify recurring themes.** Group conversations by: + - Common topics or keywords + - Product areas or features mentioned + - Error messages or symptoms reported + - Resolution approaches used + - Time to resolution + +5. **Quantify and summarize.** Present findings with counts and proportions (e.g., "8 of 15 conversations mention timeout errors"). Highlight the most common patterns first. + +6. **Recommend actions.** Based on patterns, suggest concrete next steps — knowledge base articles to create, bugs to investigate, or process improvements. + +**Output artifact:** Produce a markdown report with the following structure: + +- **Theme Summary** — Table of identified themes with conversation counts and percentage of total +- **Top Issues** — The 3–5 most common issues with representative conversation excerpts +- **Recommended Actions** — Prioritized list of concrete next steps based on the patterns found + +## Issue Investigation Steps + +When a user asks you to investigate a specific customer issue or incident: + +1. **Identify the customer.** Look up the contact by email, name, or ID. Get their full profile to understand their account context (plan, company, location, custom attributes). + +2. **Trace the timeline.** Search for all conversations from this contact, ordered by date. Fetch each conversation to build a chronological narrative of their interactions. + +3. **Check for multi-customer impact.** Search for conversations from other contacts mentioning the same symptoms, error messages, or affected feature. This determines if the issue is isolated or widespread. + +4. **Examine conversation details.** For the most relevant conversations, read through the full thread including internal notes. Notes from teammates often contain diagnostic information and root cause analysis. + +5. **Summarize findings.** Present: + - A timeline of the customer's interactions + - The core issue and any error messages + - What was tried and what resolved it (if anything) + - Whether other customers are affected + - Links to the relevant conversations + +**Output artifact:** Produce a timeline summary with: + +- **Customer Context** — Contact details, company, plan, and account attributes +- **Interaction Timeline** — Chronological list of conversations with dates, channels, and outcomes +- **Impact Assessment** — Whether the issue affects other customers, with links to related conversations + +## Best Practices + +- **Start broad, then narrow.** Begin with a general search to understand the landscape, then apply filters to focus on what matters. + +- **Always cite conversation links.** When referencing specific conversations, include their IDs so the user can find them in the Intercom inbox. Format as: `Conversation #12345`. + +- **State data limitations.** If search results are paginated and you've only seen the first page, say so. If the data doesn't support a conclusion, be explicit about what would be needed to confirm it. + +- **Respect data freshness.** The MCP server returns live data from the Intercom workspace. Results reflect the current state — if the user asks about historical trends, note that conversation states may have changed since the events occurred. + +- **Combine tools effectively.** A typical workflow involves `search` or `search_conversations` to find relevant items, then `get_conversation` or `get_contact` to get full details. Don't try to answer complex questions from search results alone. + +- **Handle empty results gracefully.** If a search returns no results, suggest alternatives: broaden the query with fewer or different keywords, try a different object type (contacts instead of conversations, or vice versa), check for typos in email addresses or names, or run an unfiltered search first to confirm data exists. + +- **Format search results for scannability.** Present results as clean tables. For conversations: ID | Subject | State | Last Updated (with relative timestamps). For contacts: ID | Name | Email | Last Seen. After displaying results, offer to fetch full details (e.g., "Want me to pull up the full thread for conversation #12345?" or "I can get the complete profile — want to see it?"). + +## Troubleshooting + +### MCP Server Disconnected +Error: Tool calls fail with connection/timeout errors +Cause: MCP server unreachable or authentication expired +Solution: Re-authenticate, check network, try again later + +### Search Returns 0 Results +Error: Empty result set when matches expected +Cause: Query too narrow, wrong field names, or no matching data +Solution: Broaden filters, try different object type, run unfiltered search first + +### Workspace Has No Conversations +Error: All conversation searches return empty +Cause: New/unused workspace or access scope limitation +Solution: Confirm workspace has data, try contact/company searches instead diff --git a/skills/intercom-insights/references/mcp-tools.md b/skills/intercom-analysis/references/mcp-tools.md similarity index 67% rename from skills/intercom-insights/references/mcp-tools.md rename to skills/intercom-analysis/references/mcp-tools.md index 3383295..1eb91b7 100644 --- a/skills/intercom-insights/references/mcp-tools.md +++ b/skills/intercom-analysis/references/mcp-tools.md @@ -2,6 +2,23 @@ This document provides detailed parameter and query DSL reference for each MCP tool available through the Intercom MCP server. +## Tool Selection Guide + +Use this table to pick the right tool for the task: + +| Goal | Tool | When to Use | +|------|------|-------------| +| Find conversations by criteria | `search` or `search_conversations` | Use `search_conversations` when you need conversation-specific filters (state, source type, assignee). Use `search` for simpler keyword queries or when searching across object types. | +| Find contacts by criteria | `search` or `search_contacts` | Use `search_contacts` when filtering by contact-specific fields (email, name, location, custom attributes). Use `search` for simpler queries. | +| Find companies | `search` | The only search tool that supports company queries. Set `object_type` to `company`. | +| Get full conversation thread | `get_conversation` | After finding a conversation via search, use this to read the complete message history including notes and state changes. | +| Get full contact profile | `get_contact` | After finding a contact via search, use this to see all attributes, tags, segments, and associated companies. | +| Get any object by ID | `fetch` | When you already have an ID (conversation, contact, or company) and need the full object. Works across all object types. | + +**Typical workflow:** Start with a search tool to find relevant items, then use a get/fetch tool for full details. Don't try to answer complex questions from search results alone. + +--- + ## `search` — General-Purpose Search The `search` tool queries across multiple Intercom object types using a structured query DSL. @@ -122,6 +139,24 @@ Search specifically for conversations with conversation-oriented filters. | `tags.tag.id` | string | Filter by tag ID | | `custom_attributes.` | varies | Custom conversation attributes | +### Search Strategies for Conversations + +When searching for conversations, consider these approaches: + +**Filter by State** — Search by state to understand workload or find unresolved issues: +- `open` — Currently active conversations requiring attention +- `closed` — Resolved conversations, useful for pattern analysis +- `snoozed` — Temporarily deferred conversations + +**Filter by Content** — Search conversation content by keywords to find discussions about specific topics, features, or error messages. Combine keyword searches with state filters to narrow results (e.g., find open conversations mentioning "billing error"). + +**Filter by Source Type** — Conversations originate from different channels: +- `email` — Email-based conversations +- `chat` — Live chat / Messenger conversations +- `api` — Programmatically created conversations + +**Pagination** — Search results return a page at a time. Use the `starting_after` cursor from the response to fetch subsequent pages. Always check if there are more results before summarizing — a single page may not tell the full story. + --- ## `get_conversation` — Fetch Single Conversation @@ -180,6 +215,18 @@ Search specifically for contacts with contact-oriented filters. | `segment.id` | string | Filter by segment ID | | `custom_attributes.` | varies | Custom contact attributes | +### Contact Lookup Strategies + +When looking up contacts, use the most specific identifier available: + +**By Email** — The most reliable lookup method. Search for contacts using their exact email address when investigating a specific person's conversations or account status. + +**By Domain** — Search contacts by their email domain (using the `~` contains operator on the `email` field) to find all people from a specific company. Useful for investigating company-wide issues or understanding an organization's support history. + +**By Custom Attributes** — Contacts may have custom attributes set by the customer's Intercom workspace (e.g., plan type, account ID, role). Use these when the user references workspace-specific identifiers. + +**By Location** — Search contacts by city, country, or region when investigating geographically scoped issues (e.g., "are customers in Europe seeing more latency?"). + --- ## `get_contact` — Fetch Single Contact diff --git a/skills/intercom-insights/SKILL.md b/skills/intercom-insights/SKILL.md deleted file mode 100644 index 07e2584..0000000 --- a/skills/intercom-insights/SKILL.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -name: intercom-insights -description: > - This skill should be used when the user asks to "analyze conversations", - "find support patterns", "search Intercom", "look up a customer", - "investigate a customer issue", "check contact info", or asks questions - about their Intercom data such as conversations, contacts, or companies. ---- - -# Intercom Insights - -Use the Intercom MCP server to analyze customer conversations, look up contacts and companies, identify support patterns, and investigate customer issues. You have access to six MCP tools — choose the right one based on the user's question. - -## Available MCP Tools - -Use these tools from the `intercom` MCP server: - -1. **`search`** — General-purpose search across conversations, contacts, and companies. Use this when the user wants to find items matching specific criteria (keywords, filters, states). Supports a query DSL with operators and pagination. - -2. **`fetch`** — Retrieve a single object by its ID. Use this when you already have an ID (e.g., `conversation_12345` or `contact_abc123`) and need full details including all metadata and conversation parts. - -3. **`search_conversations`** — Search specifically for conversations with conversation-specific filters (state, source type, teammate assignment). Prefer this over `search` when the user is explicitly asking about conversations and needs conversation-specific filtering. - -4. **`get_conversation`** — Fetch a single conversation by ID with its full thread of conversation parts (messages, notes, state changes). Use this after finding a conversation via search to get the complete history. - -5. **`search_contacts`** — Search specifically for contacts with contact-specific filters (email, name, custom attributes, location). Prefer this over `search` when looking up specific people or filtering by contact attributes. - -6. **`get_contact`** — Fetch a single contact by ID with all their attributes, tags, segments, and associated companies. Use this to get the full profile of a known contact. - -## Conversation Search Strategies - -When searching for conversations, consider these approaches: - -### Filter by State -Search for conversations in a specific state to understand workload or find unresolved issues: -- `open` — Currently active conversations requiring attention -- `closed` — Resolved conversations, useful for pattern analysis -- `snoozed` — Temporarily deferred conversations - -### Filter by Content -Search conversation content by keywords to find discussions about specific topics, features, or error messages. Combine keyword searches with state filters to narrow results (e.g., find open conversations mentioning "billing error"). - -### Filter by Source Type -Conversations originate from different channels: -- `email` — Email-based conversations -- `chat` — Live chat / Messenger conversations -- `api` — Programmatically created conversations - -### Pagination -Search results return a page at a time. Use the `starting_after` cursor from the response to fetch subsequent pages. Always check if there are more results before summarizing — a single page may not tell the full story. - -## Contact Lookup Techniques - -When looking up contacts, use the most specific identifier available: - -### By Email -The most reliable lookup method. Search for contacts using their exact email address when investigating a specific person's conversations or account status. - -### By Domain -Search contacts by their email domain to find all people from a specific company. This is useful for investigating company-wide issues or understanding an organization's support history. - -### By Custom Attributes -Contacts may have custom attributes set by the customer's Intercom workspace (e.g., plan type, account ID, role). Use these when the user references workspace-specific identifiers. - -### By Location -Search contacts by city, country, or region when investigating geographically scoped issues (e.g., "are customers in Europe seeing more latency?"). - -## Pattern Analysis Workflow - -When the user asks to analyze patterns or trends in their support data, follow this workflow: - -1. **Define scope.** Clarify what the user wants to analyze — a time period, topic, customer segment, or conversation state. Ask if unclear. - -2. **Fetch a representative sample.** Search for conversations matching the scope. Retrieve at least 10–20 conversations to establish meaningful patterns. Paginate if the first page is insufficient. - -3. **Read conversation details.** For each relevant conversation, fetch the full conversation to read the actual messages. Summaries from search results alone are often insufficient for pattern analysis. - -4. **Identify recurring themes.** Group conversations by: - - Common topics or keywords - - Product areas or features mentioned - - Error messages or symptoms reported - - Resolution approaches used - - Time to resolution - -5. **Quantify and summarize.** Present findings with counts and proportions (e.g., "8 of 15 conversations mention timeout errors"). Highlight the most common patterns first. - -6. **Recommend actions.** Based on patterns, suggest concrete next steps — knowledge base articles to create, bugs to investigate, or process improvements. - -## Issue Investigation Steps - -When a user asks you to investigate a specific customer issue or incident: - -1. **Identify the customer.** Look up the contact by email, name, or ID. Get their full profile to understand their account context (plan, company, location, custom attributes). - -2. **Trace the timeline.** Search for all conversations from this contact, ordered by date. Fetch each conversation to build a chronological narrative of their interactions. - -3. **Check for multi-customer impact.** Search for conversations from other contacts mentioning the same symptoms, error messages, or affected feature. This determines if the issue is isolated or widespread. - -4. **Examine conversation details.** For the most relevant conversations, read through the full thread including internal notes. Notes from teammates often contain diagnostic information and root cause analysis. - -5. **Summarize findings.** Present: - - A timeline of the customer's interactions - - The core issue and any error messages - - What was tried and what resolved it (if anything) - - Whether other customers are affected - - Links to the relevant conversations - -## Best Practices - -- **Start broad, then narrow.** Begin with a general search to understand the landscape, then apply filters to focus on what matters. - -- **Always cite conversation links.** When referencing specific conversations, include their IDs so the user can find them in the Intercom inbox. Format as: `Conversation #12345`. - -- **State data limitations.** If search results are paginated and you've only seen the first page, say so. If the data doesn't support a conclusion, be explicit about what would be needed to confirm it. - -- **Respect data freshness.** The MCP server returns live data from the Intercom workspace. Results reflect the current state — if the user asks about historical trends, note that conversation states may have changed since the events occurred. - -- **Combine tools effectively.** A typical workflow involves `search` or `search_conversations` to find relevant items, then `get_conversation` or `get_contact` to get full details. Don't try to answer complex questions from search results alone. - -- **Handle empty results gracefully.** If a search returns no results, suggest alternative queries — different keywords, broader filters, or a different object type. The absence of results is itself informative. - -Refer to `references/mcp-tools.md` for detailed query DSL syntax, operator reference, and field-level documentation for each MCP tool. From 12e5463efcc92e995f1bb4bbf01c32feb8963a9a Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 11:17:59 +0000 Subject: [PATCH 5/8] Add troubleshooting and improve install-messenger skill Three changes to the install-messenger skill: - Update frontmatter: add license field, rewrite description to lead with outcomes rather than trigger phrases - Add placeholder substitution instruction after Requirements section so generated code uses real values, not YOUR_WORKSPACE_ID placeholders - Add Troubleshooting section covering the five most common setup failures: missing JWT library, wrong secret, plan limitations, clock skew on exp, and CORS errors on the JWT endpoint Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/install-messenger/SKILL.md | 40 +++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/skills/install-messenger/SKILL.md b/skills/install-messenger/SKILL.md index fea9a99..a5e7fbe 100644 --- a/skills/install-messenger/SKILL.md +++ b/skills/install-messenger/SKILL.md @@ -1,10 +1,12 @@ --- name: install-messenger +license: MIT description: > - This skill should be used when the user asks to "install Intercom", - "add the Intercom Messenger", "set up Intercom chat widget", - "add customer chat to my website", or "integrate Intercom" into - their website or application. + Install the Intercom Messenger on a website or web application with + secure JWT-based identity verification. Generates backend and frontend + code for React, Next.js, Vue.js, and plain JavaScript. Use when the user + asks to "install Intercom", "add the Intercom Messenger", "set up Intercom + chat widget", "add customer chat to my website", or "integrate Intercom". disable-model-invocation: true argument-hint: "[framework]" --- @@ -27,6 +29,8 @@ Gather these from the user before proceeding: Ask the user for both values. Do not proceed without the Workspace ID. If they don't have the Identity Verification Secret yet, direct them to **Settings > Channels > Messenger > Security** in Intercom to enable it. +In all generated code, replace `YOUR_WORKSPACE_ID` with the user's actual Workspace ID. Do not leave placeholders — substitute the real values they provided. + ## Installation Overview The secure installation has two parts: @@ -209,7 +213,7 @@ Always include the shutdown call. Skipping it leaks conversation data between us ### Protect Identifying Attributes -In Intercom (**Settings > Messenger > Security**), mark identifying attributes (email, phone, account IDs) as **protected**. This prevents client-side code from spoofing these values — only the server-signed JWT can set them. +In Intercom (**Settings > Channels > Messenger > Security**), mark identifying attributes (email, phone, account IDs) as **protected**. This prevents client-side code from spoofing these values — only the server-signed JWT can set them. ### Token Expiration @@ -231,6 +235,32 @@ function refreshIntercomToken() { } ``` +## Troubleshooting + +### JWT Library Not Installed +Error: `Cannot find module 'jsonwebtoken'` (Node.js), `ModuleNotFoundError: No module named 'jwt'` (Python), or `LoadError: cannot load such file -- jwt` (Ruby) +Solution: Install the JWT library for the user's language — `npm install jsonwebtoken`, `pip install PyJWT`, or `gem install jwt`. + +### Wrong Identity Verification Secret +Symptom: Messenger loads but shows "Identity verification failed" or user attributes don't appear. +Cause: The secret used to sign JWTs doesn't match the workspace's Identity Verification Secret. +Solution: Verify the secret in Intercom at **Settings > Channels > Messenger > Security**. Ensure the environment variable holds the correct value for this workspace. + +### Plan Doesn't Support Identity Verification +Symptom: Identity Verification Secret not available in Intercom settings. +Cause: Identity verification is a paid feature not available on all Intercom plans. +Solution: Check the workspace's Intercom plan. If identity verification is unavailable, the user may need to upgrade or use the insecure installation (with explicit acknowledgment of the security trade-off). + +### JWT `exp` in the Past +Symptom: Messenger rejects the token immediately after creation. +Cause: Server clock is wrong or `exp` calculation is incorrect. +Solution: Check the server's system time (`date` command). Ensure NTP is configured. Verify the `exp` value is a future Unix timestamp in seconds (not milliseconds). + +### CORS Errors on JWT Endpoint +Symptom: Browser console shows `Access-Control-Allow-Origin` errors when fetching the JWT. +Cause: The backend JWT endpoint doesn't allow requests from the frontend's origin. +Solution: Configure CORS on the JWT endpoint to allow the frontend origin. For Express: `cors({ origin: 'https://your-app.com', credentials: true })`. For other frameworks, add the appropriate CORS headers. + ## Single-Page App (SPA) Route Changes In SPAs where the page does not fully reload on navigation, notify the Messenger of route changes: From 895ff12d183d85e30c62ec48129676104776bf50 Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 11:18:09 +0000 Subject: [PATCH 6/8] Add customer-360 skill and update project documentation Add a new customer-360 skill that produces comprehensive customer profiles by aggregating contact data, conversation history, and interaction timelines from Intercom. This replaces the removed intercom-search as the third skill, providing a genuine workflow rather than a thin search wrapper. Update README.md and CLAUDE.md to reflect the new skill composition: - Replace intercom-search with customer-360 in skills tables - Rename intercom-insights to intercom-analysis - Update usage examples - Reframe Limitations as Access & Limitations, leading with read-only safety as a feature Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 10 ++--- README.md | 19 ++++----- skills/customer-360/SKILL.md | 77 ++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 skills/customer-360/SKILL.md diff --git a/CLAUDE.md b/CLAUDE.md index 639ca15..89f3b2c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,11 +21,11 @@ User → Claude Code CLI → Skill (SKILL.md) → MCP Server (https://mcp.interc Three skills live under `skills/`, each in its own directory: -| Skill | Trigger | Key Files | -| ------------------- | ---------------------------------------------------- | -------------------------------------------- | -| `install-messenger` | Explicit: `/intercom:install-messenger [framework]` | `SKILL.md`, `references/framework-guides.md` | -| `intercom-insights` | Auto-triggered by keywords | `SKILL.md`, `references/mcp-tools.md` | -| `intercom-search` | Explicit: `/intercom:intercom-search [type] [query]` | `SKILL.md` | +| Skill | Trigger | Key Files | +| ------------------- | ---------------------------------------------------------- | -------------------------------------------- | +| `install-messenger` | Explicit: `/intercom:install-messenger [framework]` | `SKILL.md`, `references/framework-guides.md` | +| `intercom-analysis` | Auto-triggered by keywords | `SKILL.md`, `references/mcp-tools.md` | +| `customer-360` | Explicit: `/intercom:customer-360 [email or company name]` | `SKILL.md` | ### Skill File Structure diff --git a/README.md b/README.md index 5d8be02..6160f8e 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Connect your Intercom workspace to Claude Code. Search conversations, analyze cu | Skill | Invocation | Description | |-------|-----------|-------------| -| **Intercom Insights** | Auto-triggered | Analyze conversations, find support patterns, investigate customer issues, and look up contacts. Triggers automatically when you ask about your Intercom data. | -| **Install Messenger** | `/intercom:install-messenger [framework]` | Step-by-step guide to install the Intercom Messenger on your website. Supports React, Next.js, Vue.js, and plain JavaScript. | -| **Intercom Search** | `/intercom:intercom-search [type] [query]` | Quick search for conversations or contacts by keyword, email, or topic. Returns formatted results with follow-up options. | +| **Intercom Analysis** | Auto-triggered | Analyze conversations, find support patterns, investigate customer issues, and look up contacts. Triggers automatically when you ask about your Intercom data. | +| **Install Messenger** | `/intercom:install-messenger [framework]` | Install the Intercom Messenger with secure JWT-based identity verification. Supports React, Next.js, Vue.js, and plain JavaScript. | +| **Customer 360** | `/intercom:customer-360 [email or company]` | Build a comprehensive customer profile with conversation history, account context, and interaction timeline. | ## Usage Examples @@ -28,14 +28,9 @@ Show me the most common topics in open conversations this week Look up all conversations from jane@example.com and summarize her issues ``` -**Search for specific conversations:** +**Build a customer profile:** ``` -/intercom:intercom-search conversations billing error -``` - -**Find contacts at a company:** -``` -/intercom:intercom-search contacts @acme.com +/intercom:customer-360 jane@example.com ``` **Install the Messenger:** @@ -48,9 +43,9 @@ Look up all conversations from jane@example.com and summarize her issues Pull up conversation #12345 and show me the full thread ``` -## Limitations +## Access & Limitations -- **Read-only access** — The plugin can search and retrieve data but cannot create, update, or delete conversations, contacts, or other Intercom objects. +- **Safe, read-only access** — The plugin can search and retrieve data but cannot create, update, or delete conversations, contacts, or other Intercom objects. Your workspace data is never modified. - **US region only** — Currently supports US-hosted Intercom workspaces. EU and Australia region support is planned. - **Rate limits** — Search operations are subject to Intercom API rate limits. The MCP server handles throttling automatically. diff --git a/skills/customer-360/SKILL.md b/skills/customer-360/SKILL.md new file mode 100644 index 0000000..1530de1 --- /dev/null +++ b/skills/customer-360/SKILL.md @@ -0,0 +1,77 @@ +--- +name: customer-360 +license: MIT +description: > + Build a comprehensive customer profile from Intercom data, including + conversation history, account context, and interaction timeline. Use when + the user asks to "look up a customer", "customer profile", "customer 360", + "tell me about this customer", "summarize a customer's history", or provides + a customer email or company name and wants a full picture. +disable-model-invocation: true +argument-hint: "[email or company name]" +--- + +# Customer 360 + +Produce a comprehensive customer profile by aggregating data from across the Intercom workspace. + +## Workflow + +### Step 1: Identify the Customer +- Parse the user's input for an email, name, or company +- Use `search_contacts` to find the contact (by email is most reliable) +- If company name given, search contacts by email domain +- Use `get_contact` to fetch the full profile (attributes, tags, segments, companies) + +### Step 2: Gather Conversation History +- Use `search_conversations` filtered to this contact's conversations +- Paginate to get all conversations (not just the first page) +- For the most recent/relevant conversations, use `get_conversation` for full threads + +### Step 3: Build the Profile +Produce a markdown profile with these sections: + +#### Contact Summary +- Name, email, role (user/lead), company +- Location, timezone, last seen +- Plan/tier (if available via custom attributes) +- Tags and segments + +#### Conversation History +- Total conversation count +- Table: ID | Subject | State | Channel | Date +- Highlight any currently open/snoozed conversations + +#### Key Themes +- Common topics across conversations +- Recurring issues or feature requests +- Sentiment signals (escalations, positive feedback) + +#### Timeline +- Chronological list of significant interactions +- First contact → most recent activity + +#### Open Items +- Unresolved conversations +- Pending questions or follow-ups + +### Step 4: Present and Offer Next Steps +- Present the profile +- Offer to dive deeper into any conversation +- Offer to search for similar customers (same company, same issues) + +## Best Practices +- Always cite conversation IDs so the user can find them in the Intercom inbox +- Note data freshness — states may have changed since events occurred +- If the contact has many conversations, summarize the most recent 10-15 and note the total count +- Handle cases where the contact exists but has no conversations + +## Troubleshooting + +### Contact Not Found +Symptom: No results for the provided email or name. +Solution: Check for typos. Try searching by email domain to find related contacts. Ask the user to confirm the identifier. + +### Too Many Conversations +Symptom: Contact has 50+ conversations, making full analysis impractical. +Solution: Focus on the most recent 10-15 conversations. Summarize older ones by theme rather than individually. Note the total count. From 191e34d5290615bdda823e1bd4f3ea50913181a3 Mon Sep 17 00:00:00 2001 From: Levin Dixon Date: Wed, 25 Feb 2026 20:04:26 +0000 Subject: [PATCH 7/8] Remove api_base from code examples; only require for EU/AU regions The official Intercom install page omits api_base since it defaults to US. Updated all boot examples to match, and reframed the Regional Data Centers section to clarify api_base is only needed for EU or Australia. Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/install-messenger/SKILL.md | 21 +++++++------------ .../references/framework-guides.md | 9 -------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/skills/install-messenger/SKILL.md b/skills/install-messenger/SKILL.md index a5e7fbe..96eb44c 100644 --- a/skills/install-messenger/SKILL.md +++ b/skills/install-messenger/SKILL.md @@ -147,7 +147,6 @@ Add before the closing `` tag: .then(res => res.json()) .then(({ token }) => { window.Intercom('boot', { - api_base: 'https://api-iam.intercom.io', app_id: 'YOUR_WORKSPACE_ID', intercom_user_jwt: token, }); @@ -164,7 +163,6 @@ For pages where the visitor is not logged in (marketing pages, docs), boot witho ```javascript window.Intercom('boot', { - api_base: 'https://api-iam.intercom.io', app_id: 'YOUR_WORKSPACE_ID', }); ``` @@ -179,15 +177,15 @@ After reading the framework guide, adapt the code to the user's specific project ## Regional Data Centers -Intercom operates in multiple regions. The `api_base` URL must match the user's data residency region: +Most Intercom workspaces are in the US region, which is the default — no `api_base` is needed. Only add `api_base` if the user's workspace is hosted in EU or Australia: -| Region | `api_base` URL | -|--------|----------------| -| US (default) | `https://api-iam.intercom.io` | -| EU (Ireland) | `https://api-iam.eu.intercom.io` | -| Australia | `https://api-iam.au.intercom.io` | +| Region | `api_base` | Required? | +|--------|------------|-----------| +| US (default) | *(not needed)* | No | +| EU (Ireland) | `https://api-iam.eu.intercom.io` | Yes | +| Australia | `https://api-iam.au.intercom.io` | Yes | -Ask the user which region their workspace is hosted in if they mention EU or Australian hosting, GDPR compliance, or data residency requirements. Default to US if unspecified. +If the user mentions EU or Australian hosting, GDPR compliance, or data residency requirements, add the appropriate `api_base` to every `Intercom('boot', ...)` call. Otherwise, omit it. ## Security Best Practices @@ -204,7 +202,6 @@ After shutdown, re-initialize for the next user or as anonymous: ```javascript Intercom('boot', { - api_base: 'https://api-iam.intercom.io', app_id: 'YOUR_WORKSPACE_ID', }); ``` @@ -227,7 +224,6 @@ function refreshIntercomToken() { .then(res => res.json()) .then(({ token }) => { window.Intercom('boot', { - api_base: 'https://api-iam.intercom.io', app_id: 'YOUR_WORKSPACE_ID', intercom_user_jwt: token, }); @@ -286,7 +282,7 @@ After generating the installation code, verify with the user: 2. The Identity Verification Secret is stored as an environment variable (not hardcoded) 3. JWTs include `user_id` and have a short expiration (`exp`) 4. The frontend passes `intercom_user_jwt` when booting the Messenger -5. The Workspace ID and `api_base` are correct for their region +5. The Workspace ID is correct (and `api_base` is set if the workspace is in EU or Australia) 6. The logout flow calls `Intercom('shutdown')` 7. SPA route changes trigger `Intercom('update')` 8. Identifying attributes are marked as protected in Intercom settings @@ -298,7 +294,6 @@ If the user explicitly asks for an "insecure installation" (no JWT, no identity ```html