Get LaunchNotes Feedback Item
launchnotes_get_feedbackRetrieve detailed feedback information including customer data, reporter details, sentiment analysis, and associated items to understand user input context.
Instructions
Retrieve complete details for a specific feedback item including customer info, reporter, and associations.
Args:
feedback_id (string): The ID of the feedback item (required)
response_format ('json' | 'markdown'): Output format (default: 'markdown')
Returns: Complete feedback details including:
Content and internal notes
Sentiment (reaction) and importance
Affected customer information
Reporter information
Associated announcement/idea/work item
Timestamps
Use Cases:
"Show me details for feedback #abc123"
"Get the full context of this feedback item"
"What announcement is this feedback associated with?"
Error Handling:
Returns "Feedback not found" if ID doesn't exist
Returns "Authentication failed" if API token is invalid
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| feedback_id | Yes | The ID of the feedback item to retrieve | |
| response_format | No | Output format: 'json' for structured data, 'markdown' for human-readable | markdown |
Implementation Reference
- src/feedback/tools.ts:121-193 (registration)Registration of the launchnotes_get_feedback tool with the MCP server, including tool metadata, input schema reference, annotations, and the complete handler function that fetches and formats the feedback item.
server.registerTool( "launchnotes_get_feedback", { title: "Get LaunchNotes Feedback Item", description: `Retrieve complete details for a specific feedback item including customer info, reporter, and associations. Args: - feedback_id (string): The ID of the feedback item (required) - response_format ('json' | 'markdown'): Output format (default: 'markdown') Returns: Complete feedback details including: - Content and internal notes - Sentiment (reaction) and importance - Affected customer information - Reporter information - Associated announcement/idea/work item - Timestamps Use Cases: - "Show me details for feedback #abc123" - "Get the full context of this feedback item" - "What announcement is this feedback associated with?" Error Handling: - Returns "Feedback not found" if ID doesn't exist - Returns "Authentication failed" if API token is invalid`, inputSchema: GetFeedbackSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async (params: GetFeedbackInput) => { try { const result = await getFeedback(client, params.feedback_id); const feedback = result.feedback; if (params.response_format === RESPONSE_FORMAT.JSON) { return { content: [ { type: "text", text: JSON.stringify(feedback, null, 2), }, ], }; } // Markdown format return { content: [ { type: "text", text: formatFeedbackMarkdown(feedback), }, ], }; } catch (error) { return { isError: true, content: [ { type: "text", text: `Error retrieving feedback: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } } ); - src/feedback/schemas.ts:75-83 (schema)Zod input schema (GetFeedbackSchema) for validating parameters of launchnotes_get_feedback tool: required feedback_id and optional response_format.
export const GetFeedbackSchema = z .object({ feedback_id: z .string() .min(1, "Feedback ID is required") .describe("The ID of the feedback item to retrieve"), response_format: responseFormatSchema, }) .strict(); - src/feedback/queries.ts:128-135 (helper)Helper function that executes the GraphQL query to fetch a specific feedback item by ID, called by the tool handler.
export async function getFeedback( client: GraphQLClient, feedbackId: string ): Promise<{ feedback: LaunchNotesFeedback; }> { return client.execute(GET_FEEDBACK_QUERY, { id: feedbackId }); } - src/feedback/formatters.ts:10-81 (helper)Helper function to format the retrieved feedback data into human-readable Markdown, used when response_format is 'markdown'.
export function formatFeedbackMarkdown(feedback: LaunchNotesFeedback): string { const sections: string[] = []; // Header sections.push(`# Feedback Details`); sections.push(`**ID:** ${feedback.id}`); // Sentiment indicators const reactionEmoji = { happy: "😊 Happy", meh: "😐 Neutral", sad: "😞 Unhappy", }; if (feedback.reaction) { sections.push(`**Reaction:** ${reactionEmoji[feedback.reaction]}`); } if (feedback.importance) { const importanceLabel = feedback.importance.charAt(0).toUpperCase() + feedback.importance.slice(1); sections.push(`**Importance:** ${importanceLabel}`); } sections.push(`**Starred:** ${feedback.starred ? "⭐ Yes" : "No"}`); sections.push(`**Archived:** ${feedback.archived ? "📦 Yes" : "No"}`); // Customer info sections.push(`\n## Affected Customer`); sections.push(`**ID:** ${feedback.affectedCustomer.id}`); sections.push(`**Email:** ${feedback.affectedCustomer.email}`); if (feedback.affectedCustomer.initials) { sections.push(`**Initials:** ${feedback.affectedCustomer.initials}`); } if (feedback.affectedCustomer.confirmedAt) { sections.push(`**Confirmed:** ${new Date(feedback.affectedCustomer.confirmedAt).toLocaleString()}`); } // Reporter info if (feedback.reporter) { sections.push(`\n## Reporter`); sections.push(`**ID:** ${feedback.reporter.id}`); sections.push(`**Email:** ${feedback.reporter.email}`); } // Associated item if (feedback.feedbackable) { sections.push(`\n## Associated With`); sections.push(`**Type:** ${feedback.feedbackable.__typename}`); sections.push(`**ID:** ${feedback.feedbackable.id}`); if (feedback.feedbackable.name) { sections.push(`**Name:** ${feedback.feedbackable.name}`); } } // Content sections.push(`\n## Content`); sections.push(feedback.content); // Notes if (feedback.notes) { sections.push(`\n## Internal Notes`); sections.push(feedback.notes); } // Timestamps sections.push( `\n*Created: ${new Date(feedback.createdAt).toLocaleString()}*` ); sections.push(`*Updated: ${new Date(feedback.updatedAt).toLocaleString()}*`); return sections.join("\n"); }