Compare commits

...

1 Commits

Author SHA1 Message Date
Nolann B. e6b8502036 Resolve .md page URLs in the MCP getPage tool (RND-13634) (#4735) 2026-11-02 12:59:34 +01:00
4 changed files with 40 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the MCP `getPage` tool returning "Page not found" for the Markdown URL of a page (`<page>.md`).
+10
View File
@@ -50,6 +50,16 @@ describe('extractPagePath', () => {
it('returns empty string when URL equals root base URL', () => {
expect(extractPagePath('https://docs.example.com/', 'https://docs.example.com/')).toBe('');
});
it('extracts path from the markdown URL of a page', () => {
expect(
extractPagePath('https://docs.example.com/api/guides/installation.md', baseURL)
).toBe('guides/installation');
expect(extractPagePath('https://docs.example.com/api/.md', baseURL)).toBe('');
expect(extractPagePath('https://docs.example.com/api/notes.md.html', baseURL)).toBe(
'notes.md.html'
);
});
});
describe('resolveFirstDocument', () => {
+2 -1
View File
@@ -412,7 +412,8 @@ function flattenPages(
* Returns the path segment after the base, or undefined if the URL doesn't match.
*/
export function extractPagePath(url: string, baseURL: string): string | undefined {
const urlPath = getURLPathname(url);
// Pages are also served as Markdown at `<page>.md`, the form llms.txt links to.
const urlPath = getURLPathname(url)?.replace(/\.md$/, '');
const basePath = getURLPathname(baseURL);
if (urlPath === undefined || basePath === undefined) {
+23
View File
@@ -55,6 +55,29 @@ it(
{ timeout: 15_000 }
);
it(
'should get a page through MCP from its markdown URL',
async () => {
const client = await connectMCPClient(
getContentTestURL(
'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/~gitbook/mcp/auth'
)
);
const response = await client.callTool({
name: 'getPage',
arguments: {
url: 'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/3.0/other-page.md',
},
});
expect(response.isError).toBeFalsy();
// @ts-expect-error - response.content is of type unknown
expect(response.content[0]?.text).toContain('# Other Page');
},
{ timeout: 15_000 }
);
describe('MCP on a site behind visitor authentication', () => {
const VA_SITE_URL = 'https://gitbook-open-e2e-sites.gitbook.io/va-site-redirects-fallback';