Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strong-lions-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/mcp': minor
---

Adds review_alt_text tool to the Primer MCP
57 changes: 57 additions & 0 deletions packages/mcp/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,4 +629,61 @@ The following list of coding guidelines must be followed:
},
)

// -----------------------------------------------------------------------------
// Accessibility
// -----------------------------------------------------------------------------

/**
* The `review_alt_text` tool is experimental and may be removed in future versions.
*
* The intent of this tool is to assist products like Copilot Code Review and Copilot Coding Agent
* in reviewing both user- and AI-generated alt text for images, ensuring compliance with accessibility guidelines.
* This tool is not intended to replace human-generated alt text; rather, it supports the review process
* by providing suggestions for improvement. It should be used alongside human review, not as a substitute.
*
*
**/
server.tool(
'review_alt_text',
'Evaluates image alt text against accessibility best practices and context relevance.',
{
surroundingText: z.string().describe('Text surrounding the image, relevant to the image.'),
alt: z.string().describe('The alt text of the image being evaluated'),
image: z
.union([
z.instanceof(File).describe('The image src file being evaluated'),
z.string().url().describe('The URL of the image src being evaluated'),
z.string().describe('The file path of the image src being evaluated'),
])
.describe('The image file, file path, or URL being evaluated'),
},
async ({surroundingText, alt, image}) => {
// Call the LLM through MCP sampling
const response = await server.server.createMessage({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Does this alt text: '${alt}' meet accessibility guidelines and describe the image: ${image} accurately in context of this surrounding text: '${surroundingText}'?\n\n`,
},
},
],
sampling: {temperature: 0.4},
Copy link
Copy Markdown
Contributor Author

@kendallgassner kendallgassner Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

temperature -> Controls how “random” or “creative” the model’s output is. Low temperature is more predictable/conservative while a high temp is more creative/varied. I chose .4 (almost mid range) to allow some flexibility in how the LLM reviews alt text.

maxTokens: 500,
})

return {
content: [
{
type: 'text',
text: response.content.type === 'text' ? response.content.text : 'Unable to generate summary',
},
],
altTextEvaluation: response.content.type === 'text' ? response.content.text : 'Unable to generate summary',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joshblack I updated the nextSteps field after your approval to include: DO NOT run this tool repeatedly on the same image - evaluations may vary slightly with each run.

nextSteps: `If the evaluation indicates issues with the alt text, provide more meaningful alt text based on the feedback. DO NOT run this tool repeatedly on the same image - evaluations may vary slightly with each run.`,
}
},
)

export {server}
Loading