Skip to content

Commit 79477cd

Browse files
committed
fixing documentation links (file ids versus reflection ids)
1 parent 3a8bcbd commit 79477cd

File tree

5 files changed

+62
-23
lines changed

5 files changed

+62
-23
lines changed

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mcp-typescribe",
3-
"version": "0.8.0",
3+
"version": "0.8.1",
44
"description": "An MCP server that answers questions about TypeScript APIs using TypeDoc JSON documentation",
55
"main": "dist/mcp-server/index.js",
66
"type": "module",
@@ -72,7 +72,7 @@
7272
"kuzu": "^0.10.0",
7373
"langchain": "0.3.26",
7474
"object-hash": "^3.0.0",
75-
"typedoc": "^0.28.4",
75+
"typedoc": "0.28.5",
7676
"yaml": "^2.8.0",
7777
"zod": "^3.24.4",
7878
"zod-to-json-schema": "^3.24.5"

src/mcp-server/core/typescript-api-handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ export class TypeScriptApiHandlers {
990990
offset: number = 0,
991991
section?: string,
992992
): Promise<string> {
993-
const result = this.project.getReflectionById(id);
993+
const result = this.project.files.resolve(id, this.project);
994994
if (result instanceof ProjectReflection && result.readme) {
995995
return await extractDocument(
996996
offset,

src/mcp-server/utils/format-utils.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
DeclarationReflection,
2020
DocumentReflection,
2121
ParameterReflection,
22+
ProjectReflection,
2223
ReferenceReflection,
2324
Reflection,
2425
ReflectionKind,
@@ -381,6 +382,20 @@ export function extractSection(content: string, section: string) {
381382
return { filteredContent, breadcrumbs };
382383
}
383384

385+
function convertReflectionToDocumentId(
386+
walker: ProjectReflection | undefined,
387+
child: DocumentReflection,
388+
) {
389+
let id = 1;
390+
let resolved = walker?.project.files.resolve(id, walker?.project);
391+
while (typeof resolved !== "undefined" && resolved !== child) {
392+
id++;
393+
resolved = walker?.project.files.resolve(id, walker?.project);
394+
}
395+
if (resolved === child) return id;
396+
return undefined;
397+
}
398+
384399
export async function extractDocument(
385400
offset: number,
386401
id: number,
@@ -395,13 +410,18 @@ export async function extractDocument(
395410

396411
//breadcrumbs
397412
let walker = parent;
413+
const breadCrumbs: string[] = [];
398414
while (walker instanceof DocumentReflection) {
399-
finalResult += `[${walker.name}](${createDocLink(walker.id)}) > `;
415+
const id = convertReflectionToDocumentId(walker.project, walker);
416+
if (id) {
417+
breadCrumbs.push(`[${walker.name}](${createDocLink(id)}) `);
418+
} else {
419+
breadCrumbs.push(walker.name);
420+
}
400421
walker = walker.parent;
401422
}
402-
403-
if (finalResult.length > 0) {
404-
finalResult += "\n\n";
423+
if (breadCrumbs.length > 0) {
424+
finalResult += "Breadcrumbs: >> " + breadCrumbs.join(" >> ") + "\n\n";
405425
}
406426

407427
if (offset == 0) {
@@ -423,10 +443,20 @@ export async function extractDocument(
423443
finalResult += `**Tags:** ${frontmatter.tags.join(", ")}\n\n`;
424444
}
425445
}
446+
/*
447+
We cannot link to child ids because we need a file id and we only get a reflection id.
448+
*/
426449
if (Array.isArray(children) && children.length > 0) {
427450
finalResult += "## Child Pages\n\n";
428451
finalResult += children
429-
.map((child) => `- [${child.name}](${createDocLink(child.id)})`)
452+
.map((child) => {
453+
const id = convertReflectionToDocumentId(walker?.project, child);
454+
if (id) {
455+
return `- [${child.name}](${createDocLink(id)})`;
456+
} else {
457+
return `- ${child.name}`;
458+
}
459+
})
430460
.join("\n");
431461
}
432462
}

tests/handlers.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,27 +148,36 @@ Some text 7
148148
describe("getDocumentation", () => {
149149
it("should return the documentation page", async () => {
150150
const result = await handlers.handleGetDocumentation(
151-
19,
151+
1,
152152
0,
153153
"introduction",
154154
);
155155
expect(result).toBeDefined();
156156
expect(result).toContain("## Introduction");
157-
expect(result).toContain("Complete File [here](api://doc/19)");
157+
expect(result).toContain("Complete File [here](api://doc/1)");
158158
expect(result).toContain("Breadcrumbs: >> [Welcome to Our Project]");
159159
expect(result).not.toContain("# Welcome to Our Project");
160160
expect(result).not.toContain("Getting Started");
161161
expect(result).not.toContain("Thank you");
162162
});
163163
it("should return a documentation page section", async () => {
164-
const result = await handlers.handleGetDocumentation(19);
164+
const result = await handlers.handleGetDocumentation(1);
165165
expect(result).toBeDefined();
166166
expect(result).toContain("# External Markdown");
167167
});
168-
it("should return the README page", async () => {
169-
const result = await handlers.handleGetDocumentation(0);
168+
it("should properly link between api docs", async () => {
169+
const result = await handlers.handleGetDocumentation(1);
170170
expect(result).toBeDefined();
171-
expect(result).toContain("README");
171+
expect(result).toContain("api://doc/");
172+
expect(result).toMatch(/api:\/\/doc\/(\d+)/);
173+
const id = Number.parseInt(
174+
result.match(/\[links]\(api:\/\/doc\/(\d+)/)![1],
175+
);
176+
const linkedDocument = await handlers.handleGetDocumentation(id);
177+
expect(linkedDocument).toBeDefined();
178+
179+
expect(linkedDocument).toContain("External");
180+
expect(linkedDocument).toContain("[External Markdown](api://doc/1)");
172181
});
173182
it("should include api-doc links in descriptions", async () => {
174183
const result = handlers.handleGetSymbolDetails({ name: "Kerle" });

0 commit comments

Comments
 (0)