Skip to content
54 changes: 54 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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-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

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:<skill-name>`.

## 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
19 changes: 7 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:**
Expand All @@ -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.

Expand Down
77 changes: 77 additions & 0 deletions skills/customer-360/SKILL.md
Original file line number Diff line number Diff line change
@@ -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.
40 changes: 35 additions & 5 deletions skills/install-messenger/SKILL.md
Original file line number Diff line number Diff line change
@@ -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]"
---
Expand All @@ -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:
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions skills/install-messenger/references/framework-guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export function IntercomProvider({ appId, isAuthenticated, children }: IntercomP
.then(res => res.json())
.then(({ token }) => {
Intercom({
api_base: 'https://api-iam.intercom.io',
Comment thread
levindixon marked this conversation as resolved.
Outdated
app_id: appId,
intercom_user_jwt: token,
});
});
} else {
// Anonymous visitor — no JWT needed
Intercom({
api_base: 'https://api-iam.intercom.io',
app_id: appId,
});
}
Expand Down
101 changes: 101 additions & 0 deletions skills/intercom-analysis/SKILL.md
Original file line number Diff line number Diff line change
@@ -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
Loading