MCP Server
Produktly provides a Model Context Protocol (MCP) server that lets you connect AI assistants like Claude, Cursor, Windsurf, and others directly to your Produktly data.
With the MCP server you can query your changelogs, feedback widgets, roadmaps, NPS widgets, and cross-feature usage stats through natural language — and have your AI assistant create and update changelog posts on your behalf.
Endpoint
https://api.produktly.com/api/mcp
The server uses the Streamable HTTP transport (stateless mode).
Authentication
The MCP server authenticates using your Produktly Private Key as a Bearer token.
- Go to Settings > Private Keys in your Produktly dashboard
- Generate a new private key (give it a name like "MCP")
- Use the key as a Bearer token in your MCP client configuration
Setup
Claude Code (CLI)
Run this command in your terminal:
claude mcp add produktly --transport http --url https://api.produktly.com/api/mcp --header "Authorization: Bearer YOUR_PRIVATE_KEY"
Or add it manually to your Claude Code MCP settings:
{
"mcpServers": {
"produktly": {
"type": "streamable-http",
"url": "https://api.produktly.com/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_PRIVATE_KEY"
}
}
}
}
Cursor / Windsurf
Add to your MCP configuration file:
{
"mcpServers": {
"produktly": {
"url": "https://api.produktly.com/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_PRIVATE_KEY"
}
}
}
}
GitHub Copilot / VS Code
In VS Code, open the Command Palette and run MCP: Add Server. Select HTTP as the transport type, then enter the URL https://api.produktly.com/api/mcp.
Or add it manually to your .vscode/mcp.json:
{
"servers": {
"produktly": {
"type": "http",
"url": "https://api.produktly.com/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_PRIVATE_KEY"
}
}
}
}
The Produktly tools will be available in Copilot's Agent mode.
Other MCP clients
Any MCP client that supports the Streamable HTTP transport can connect. Set the URL to https://api.produktly.com/api/mcp and include the Authorization: Bearer YOUR_PRIVATE_KEY header.
ChatGPT / Gemini
ChatGPT and Gemini require OAuth-based authentication for MCP servers, which is not yet supported. We're working on adding OAuth support — stay tuned.
Available tools
list_changelogs
List all your changelogs (id, name, active status, creation date).
get_changelog_posts
Get posts for a specific changelog.
| Parameter | Type | Required | Description |
|---|---|---|---|
changelogId | number | Yes | The ID of the changelog |
startDate | string | No | Filter posts from this date (ISO 8601) |
endDate | string | No | Filter posts until this date (ISO 8601) |
latestCount | number | No | Return only the latest X posts (max 100) |
list_feedback_widgets
List all your feedback widgets (id, name, active status, creation date).
get_feedback_responses
Get responses for a specific feedback widget.
| Parameter | Type | Required | Description |
|---|---|---|---|
feedbackWidgetId | number | Yes | The ID of the feedback widget |
startDate | string | No | Filter responses from this date (ISO 8601) |
endDate | string | No | Filter responses until this date (ISO 8601) |
latestCount | number | No | Return only the latest X responses (max 100) |
list_roadmaps
List all your roadmaps with their sections (id, name, public name, active status, sections).
get_roadmap
Get a full roadmap with all sections and items. Supports search and tag filtering within the roadmap.
| Parameter | Type | Required | Description |
|---|---|---|---|
roadmapId | number | Yes | The ID of the roadmap |
startDate | string | No | Filter items updated from this date (ISO 8601) |
endDate | string | No | Filter items updated until this date (ISO 8601) |
latestCount | number | No | Return latest X items per section (max 100) |
query | string | No | Case-insensitive substring match on item name or description |
tagNames | string[] | No | Filter items whose tag name matches any of these (case-insensitive exact match) |
list_nps_widgets
List all your NPS widgets (id, name, active status, creation date).
get_nps_score
Get the NPS score and response breakdown for an NPS widget. NPS = % promoters (rating 9-10) − % detractors (rating 0-6); passives are 7-8.
| Parameter | Type | Required | Description |
|---|---|---|---|
npsWidgetId | number | Yes | The ID of the NPS widget |
startDate | string | No | Filter responses from this date (ISO 8601) |
endDate | string | No | Filter responses until this date (ISO 8601) |
Returns npsScore, totalResponses, and counts/percentages for promoters, passives, and detractors.
get_nps_responses
Get individual responses for an NPS widget.
| Parameter | Type | Required | Description |
|---|---|---|---|
npsWidgetId | number | Yes | The ID of the NPS widget |
startDate | string | No | Filter responses from this date (ISO 8601) |
endDate | string | No | Filter responses until this date (ISO 8601) |
latestCount | number | No | Return only the latest X responses (max 100) |
get_widget_stats
Get event counts and unique users per widget for a given widget type. Returns one entry per widget with a breakdown by event type. Useful for comparing widgets of the same type (e.g. "which tours have the best completion rate?") or inspecting a single widget when entityId is provided.
| Parameter | Type | Required | Description |
|---|---|---|---|
entityType | enum | Yes | One of tour, checklist, smartTip, announcement, changelog, npsWidget, roadmap |
entityId | number | No | Filter to a single widget |
startDate | string | No | Start date (ISO 8601). Defaults to 30 days ago |
endDate | string | No | End date (ISO 8601). Defaults to today |
Max range 90 days. uniqueUsers is a per-day sum approximation — it may double-count users active across multiple days.
get_stats_summary
Get a company-wide stats summary across all widget types. Returns primary and secondary metrics (completion rate, open rate, action rate), event counts, period-over-period comparison, and a trend series for each widget type.
| Parameter | Type | Required | Description |
|---|---|---|---|
startDate | string | No | Start date (ISO 8601). Defaults to 7 days ago |
endDate | string | No | End date (ISO 8601). Defaults to today |
The trend series is daily when the range is 21 days or less, weekly otherwise. Max range 90 days.
list_tags
List all tags in the company (id, name, colors). Useful for looking up tag names to pass to create_changelog_post and update_changelog_post.
create_changelog_post
Create a new changelog post. Posts default to draft (active: false) unless active: true is explicitly passed.
| Parameter | Type | Required | Description |
|---|---|---|---|
changelogId | number | Yes | The ID of the changelog to add the post to |
title | string | Yes | Post title |
description | string | No | Post description as HTML (e.g. <p>, <ul>, <strong>) |
date | string | No | Post date (ISO 8601). Defaults to now |
active | boolean | No | Whether the post is live. Defaults to false |
tagNames | string[] | No | Tag names to attach. Must match existing tags (case-insensitive) |
Unknown tagNames return an error listing the unresolved names — use list_tags first.
update_changelog_post
Update an existing changelog post. Only the fields you provide are changed.
| Parameter | Type | Required | Description |
|---|---|---|---|
changelogItemId | number | Yes | The ID of the post to update |
title | string | No | New title |
description | string | No | New HTML description |
date | string | No | New post date (ISO 8601) |
active | boolean | No | Whether the post is live |
tagNames | string[] | No | Replacement tag names. Omit to leave tags unchanged; pass [] to clear |
Example usage
Once connected, you can ask your AI assistant things like:
- "What are our latest changelog posts?"
- "Show me feedback from the last week"
- "What items are on our product roadmap?"
- "Search the roadmap for items about 'integration' tagged as 'New Feature'"
- "What's our NPS score this quarter, and what are the detractors saying?"
- "Which product tour has the best completion rate over the last month?"
- "How did our overall engagement change this week vs last week?"
- "Summarize the feedback we got this month"
- "Draft a changelog post about the webhook improvements we shipped this week, tag it as Improvement, leave it as a draft"