From 6d4346b543a909738f1a0c5b5165b906af998346 Mon Sep 17 00:00:00 2001 From: Pranay623 Date: Tue, 20 Oct 2026 21:29:20 +0530 Subject: [PATCH 1/2] Fix component slug URLs in MCP tools --- packages/mcp/src/server.test.ts | 50 +++++++++++++++++++++++++++++++++ packages/mcp/src/server.ts | 4 +-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/mcp/src/server.test.ts b/packages/mcp/src/server.test.ts index 39bb6a0effc..8ad20d21a04 100644 --- a/packages/mcp/src/server.test.ts +++ b/packages/mcp/src/server.test.ts @@ -482,6 +482,56 @@ describe('MCP server', () => { }, ) + it.each([ + { + tool: 'get_component_examples', + expectedPath: '/product/components/text-input', + rawIdPath: '/product/components/text_input', + }, + { + tool: 'get_component_accessibility_guidelines', + expectedPath: '/product/components/text-input/accessibility', + rawIdPath: '/product/components/text_input/accessibility', + }, + ] as const)('$tool uses the TextInput slug in its URL', async ({tool, expectedPath, rawIdPath}) => { + const expectedUrl = `https://primer.style${expectedPath}` + const rawIdUrl = `https://primer.style${rawIdPath}` + const responseBody = 'synthetic-text-input-documentation' + const homepageBody = 'homepage-body-not-text-input-documentation' + const fetchMock = vi.mocked(fetch) + fetchMock.mockImplementation(async input => { + const url = input.toString() + + if (url === expectedUrl) { + return responseWithFinalUrl(`

${responseBody}

`, expectedUrl) + } + + if (url === rawIdUrl) { + return responseWithFinalUrl(`

${homepageBody}

`, 'https://primer.style/') + } + + throw new Error(`Unexpected fetch request: ${url}`) + }) + + const result = await client.callTool({name: tool, arguments: {name: 'TextInput'}}) + + expect(result.isError).not.toBe(true) + expect(result.content).toContainEqual( + expect.objectContaining({ + type: 'text', + text: expect.stringContaining(responseBody), + }), + ) + expect(result.content).not.toContainEqual( + expect.objectContaining({ + type: 'text', + text: expect.stringContaining(homepageBody), + }), + ) + expect(fetchMock).toHaveBeenCalledTimes(1) + expect(fetchMock.mock.calls[0]?.[0].toString()).toBe(expectedUrl) + }) + it.each(['ConfirmationDialog', 'confirmationdialog'])( 'retrieves ConfirmationDialog documentation for %s from its published URL', async name => { diff --git a/packages/mcp/src/server.ts b/packages/mcp/src/server.ts index 3440e40889b..9477b1da702 100644 --- a/packages/mcp/src/server.ts +++ b/packages/mcp/src/server.ts @@ -253,7 +253,7 @@ Use \`get_component\` for exactly one component and \`get_component_batch\` for } } - const url = new URL(`/product/components/${match.id}`, 'https://primer.style') + const url = new URL(`/product/components/${match.slug}`, 'https://primer.style') const response = await fetch(url) if (!response.ok) { throw new Error(`Failed to fetch ${url}: ${response.statusText}`) @@ -387,7 +387,7 @@ ${text}`, } } - const url = new URL(`/product/components/${match.id}/accessibility`, 'https://primer.style') + const url = new URL(`/product/components/${match.slug}/accessibility`, 'https://primer.style') const response = await fetch(url) if (!response.ok) { if ((response.status >= 400 && response.status < 500) || (response.status >= 300 && response.status < 400)) { From eaa638b676b7026bc77922963e55d4d6351dec68 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Tue, 20 Oct 2026 13:46:34 -0500 Subject: [PATCH 2/2] Update component slug matching in MCP tools Updated the component MCP tools to ensure HTTP requests match the slug of components for primer.style. --- .changeset/tired-bobcats-tan.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tired-bobcats-tan.md diff --git a/.changeset/tired-bobcats-tan.md b/.changeset/tired-bobcats-tan.md new file mode 100644 index 00000000000..10eb5d0cd24 --- /dev/null +++ b/.changeset/tired-bobcats-tan.md @@ -0,0 +1,5 @@ +--- +"@primer/mcp": patch +--- + +Update component MCP tools to match on the slug of components for HTTP requests to primer.style