A community-driven registry for the Claude Code ecosystem. Not affiliated with Anthropic.
Are you the author? Sign in to claim
MCP server that triangulates customer support tickets and feature requests to help PMs decide what to build next
An MCP server that triangulates customer support tickets and feature requests to help PMs decide what to build next.
Real results: Analyzed 2,370 signals (2,136 support tickets + 234 feature requests) across 3 products in 55 seconds. Identified 16 themes, 15 convergent. Top priority: Booking & Scheduling (score: 134.6) — 629 tickets + 77 feature requests pointing at the same problem.
Read the full story: I built an MCP server that changed how I prioritize products — why I built this, how convergent signals work in practice, and what I learned building with Claude Code.
generate_product_plan via kpi_context, and the methodology adjusts priorities accordingly.graph TD
A[Claude Desktop / Code] -->|stdio| B[pm-copilot]
A -->|stdio| C[Metabase MCP]
A -->|stdio| D[Google Analytics MCP]
B -->|Qualitative| E[HelpScout: tickets]
B -->|Qualitative| F[ProductLift: feature requests]
C -->|Quantitative| G[Conversion, Churn, Revenue]
D -->|Acquisition| H[Traffic, Channels, Trends]
B -.->|kpi_context| A
Claude orchestrates multiple MCP servers. PM Copilot handles qualitative customer signals. Other servers provide quantitative business metrics. The kpi_context parameter is the integration point — no point-to-point integrations required.
git clone https://github.com/dkships/pm-copilot.git
cd pm-copilot
npm install
cp .env.example .env # Edit with your credentials
npm run build
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"pm-copilot": {
"command": "node",
"args": ["/absolute/path/to/pm-copilot/dist/index.js"]
}
}
}
claude mcp add pm-copilot -- node /absolute/path/to/pm-copilot/dist/index.js
Or use the .mcp.json already in the project root — Claude Code picks it up automatically.
synthesize_feedbackCross-references HelpScout tickets and ProductLift feature requests, returns theme-matched analysis with priority scores.
| Parameter | Type | Default | Description |
|---|---|---|---|
timeframe_days | number | 30 | Days to look back (1-90) |
top_voted_limit | number | 50 | Max feature requests by vote count |
mailbox_id | string | — | HelpScout mailbox filter (raw ID) |
mailbox_name | string | — | HelpScout mailbox name (case-insensitive); auto-resolved to an ID. Run list_sources to see names |
portal_name | string | — | ProductLift portal filter |
detail_level | string | "summary" | "summary", "standard", or "full". Output size scales with data volume — for one 30-day mailbox, roughly 15KB / 60KB / 360KB |
Returns themes sorted by priority score, each with reactive/proactive counts, convergence flag, evidence summaries, and representative customer quotes.
generate_product_planBuilds a prioritized product plan with evidence and customer quotes. Accepts external business metrics via kpi_context.
| Parameter | Type | Default | Description |
|---|---|---|---|
timeframe_days | number | 30 | Days to look back (1-90) |
top_voted_limit | number | 50 | Max feature requests by vote count |
mailbox_id | string | — | HelpScout mailbox filter (raw ID) |
mailbox_name | string | — | HelpScout mailbox name (case-insensitive); auto-resolved to an ID. Run list_sources to see names |
portal_name | string | — | ProductLift portal filter |
kpi_context | string | — | Business metrics from other MCP servers |
max_priorities | number | 5 | Number of priorities to return (1-10) |
preview_only | boolean | false | Audit mode: show what data would be sent |
detail_level | string | "summary" | "summary", "standard", or "full". Output size scales with data volume — for one 30-day mailbox, roughly 5KB / 21KB / 375KB |
format | string | "json" | "json" (structured, composable) or "markdown" (ready-to-read product brief) |
get_feature_requestsRaw ProductLift data access for browsing feature requests directly. Each request includes its
public url.
| Parameter | Type | Default | Description |
|---|---|---|---|
portal_name | string | — | Filter to a specific portal |
include_comments | boolean | true | Include comments on each request |
status | string | — | Filter to requests with this status (case-insensitive), e.g. open, planned, completed |
list_sourcesLists the data sources the server is connected to — HelpScout mailboxes (id + name) and
ProductLift portals (name + url) — so you can discover the names to pass to mailbox_name /
portal_name. Read-only; never returns API keys or customer data. Takes no parameters.
A trimmed synthesize_feedback response at the default summary detail level. Values are illustrative; note the PII scrubbing applied to the customer quote.
{
"timeframe_days": 30,
"detail_level": "summary",
"portal_name": "all",
"fetched_at": "2026-06-01T16:00:00.000Z",
"pii_scrubbing_applied": true,
"pii_categories_redacted": ["email", "phone"],
"analysis": {
"total_data_points": 612,
"reactive_count": 548,
"proactive_count": 64,
"themes": [
{
"theme_id": "booking-scheduling",
"label": "Booking & Scheduling",
"category": "Core Product",
"priority_score": 87.1,
"convergent": true,
"signal_type": "convergent",
"reactive_count": 211,
"proactive_count": 19,
"evidence_summary": "230 signals (211 tickets, 19 requests). Convergent across both sources.",
"representative_quotes": [
"[Support ticket] \"Double-booked slots again after the timezone change — reach me at [EMAIL REDACTED]\"",
"[Feature request, 47 votes] \"Let me block buffer time between meetings\""
]
},
{
"theme_id": "billing-payment",
"label": "Billing & Payment",
"category": "Monetization",
"priority_score": 64.3,
"convergent": false,
"signal_type": "reactive",
"reactive_count": 188,
"proactive_count": 0,
"evidence_summary": "188 signals (188 tickets, 0 requests). Reactive only.",
"representative_quotes": [
"[Support ticket] \"Charged twice for the annual plan\""
]
}
],
"emerging_themes": [
{ "pattern": "csv export", "frequency": 12 }
],
"unmatched_count": 38
}
}
PM Copilot is designed to work alongside other MCP servers. Here's a worked example showing how a kpi_context override changes the ranking. Numbers are illustrative.
Step 1: The PM asks a single question
Pull our churn and booking completion data, then use pm-copilot to create a product plan using all of that context.
Step 2: pm-copilot analyzes the signals and returns the top priorities
| # | Theme | Score | Tickets | Feature Requests | Signal |
|---|---|---|---|---|---|
| 1 | Billing & Payment | 91.1 | 2,336 | 20 | Convergent |
| 2 | Booking & Scheduling | 87.1 | 682 | 74 | Convergent |
| 3 | Account & Licensing | 69.7 | 1,955 | 8 | Convergent |
| 4 | Team & Collaboration | 64.4 | 1,875 | 19 | Convergent |
| 5 | Whitelabel & Branding | 50.2 | 92 | 30 | Convergent |
Step 3: Business metrics from dashboards arrive as kpi_context
Product A: booking completion rate dropped from 74% to 66% over last
30 days. Monthly churn increased from 3.1% to 4.2%. Organic traffic
up 22% MoM. Product B: document completion rate steady at 81%.
Churn flat at 2.8%.
Step 4: Claude synthesizes both, and overrides the formula
The scores say Billing & Payment is #1. But the methodology says churn data overrides the formula. With Product A's booking completion dropping 8 points and churn spiking 35%, Booking & Scheduling becomes the real #1 — it's the core product breaking.
Product B deprioritized (stable metrics, no fire). Product A's 22% organic traffic growth elevates Whitelabel & Branding as a growth play.
The server provides the signal ranking. KPI context provides the override judgment. Claude synthesizes both.
PM Copilot exposes a pm-copilot://methodology resource — David Kelly's product planning framework, built over 7 years of launching 9 products to 1M+ users.
Key principles:
The methodology is versioned (v2.0) and served as markdown content via the MCP resource protocol. Claude references it automatically when using generate_product_plan.
Customer data flows through PM Copilot on its way to Claude. All text is scrubbed before it enters the analysis pipeline or leaves the server.
| Category | Method | Replacement |
|---|---|---|
| SSNs | Pattern match (XXX-XX-XXXX) | [SSN REDACTED] |
| Credit cards | 13-19 digit sequences + Luhn validation | [CC REDACTED] |
| Email addresses | Standard email pattern | [EMAIL REDACTED] |
| Phone numbers | US formats (+1, parens, dashes, dots) | [PHONE REDACTED] |
| Customer email field | Always redacted | [REDACTED] |
| Data | Why |
|---|---|
| Agent/admin responses | Only customer voice matters; agent replies could leak internal process |
| Internal HelpScout notes | May contain credentials, workarounds, internal discussions |
| Attachments | Could contain screenshots with PII, invoices, medical documents |
| Voter identities | Vote counts are sufficient; individual identity adds no PM value |
preview_only: true on generate_product_plan shows what data would be sent without fetching itpii_scrubbing_applied and pii_categories_redacted metadatanpm install # Install dependencies
npm run build # Compile TypeScript
npm run dev # Watch mode
npm start # Run the server
npm test # Run the test suite
Call a tool in isolation without restarting your MCP client — useful for iterating on changes and for checking response sizes:
npm run build
npm run tool -- --list
npm run tool -- list_sources '{}'
npm run tool -- get_feature_requests '{"portal_name":"<your-portal>","status":"open"}'
The runner prints the byte size of each response. Output may include your configured source names/URLs (and PII-scrubbed customer text) — redact before sharing.
themes.config.json in the project root defines what themes to look for. Edit without rebuilding — loaded at runtime.
Ships with 16 data-driven themes across 9 categories. Add your own by appending to the themes array. Unmatched data points are analyzed for emerging patterns using bigram/trigram frequency detection.
priority = (frequency × 0.35 + severity × 0.35 + vote_momentum × 0.30) × convergence_boost
dist/. After editing
source, run npm run build and restart the client (or the MCP server connection) to pick up
new code.No HelpScout mailbox named "…". Run list_sources to see the exact mailbox names, or
pass the numeric mailbox_id directly.No portal found with name "…" / portal missing. The portal must be configured in
PRODUCTLIFT_PORTALS (or the single-portal env vars). Run list_sources to see configured
portals.git checkout -b feature/your-feature)npm run build succeeds with no errorsregisterTool, API clients get their own module, PII scrubbing happens at the format layerRun Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
English-first Korean equity intelligence MCP — DART filings, foreign-holder 5%-rule flows, activist filings, KRX news. F
Unity MCP acts as a bridge between AI assistants and your Unity Editor. Give your LLM tools to manage assets, control sc
via CLI