Skip to content

Commit c10af03

Browse files
committed
feat: improve chapter ID matching with normalization and refined error handling.
1 parent 40c2256 commit c10af03

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

packages/mcp-server/src/tools/read-chapter.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,66 @@ import type { ChapterIndexService } from "../services/chapter-index.js";
77
import type { SpecLoader } from "../services/spec-loader.js";
88
import type { ToolResult } from "../types.js";
99

10+
/**
11+
* Normalize chapter ID for flexible matching:
12+
* - lowercase
13+
* - trim whitespace
14+
* - replace spaces/underscores with hyphens
15+
* - remove special characters
16+
*/
17+
function normalizeChapterId(id: string): string {
18+
return id
19+
.toLowerCase()
20+
.trim()
21+
.replace(/[\s_]+/g, "-") // spaces/underscores to hyphens
22+
.replace(/[^a-z0-9-]/g, "") // remove special chars
23+
.replace(/-+/g, "-") // collapse multiple hyphens
24+
.replace(/^-|-$/g, ""); // trim leading/trailing hyphens
25+
}
26+
1027
export async function handleReadChapter(
1128
params: ReadChapterInput,
1229
specLoader: SpecLoader,
1330
indexService: ChapterIndexService,
1431
): Promise<ToolResult> {
32+
const validChapters = await indexService.listChapterIds();
33+
const normalizedInput = normalizeChapterId(params.chapter);
34+
35+
// Find matching chapter (exact or normalized match)
36+
const matchedChapter = validChapters.find(
37+
(chapterId) =>
38+
chapterId === params.chapter || normalizeChapterId(chapterId) === normalizedInput,
39+
);
40+
41+
if (!matchedChapter) {
42+
return {
43+
isError: true,
44+
content: [
45+
{
46+
type: "text",
47+
text: `Chapter '${
48+
params.chapter
49+
}' not found. Valid chapters: ${validChapters.join(", ")}`,
50+
},
51+
],
52+
};
53+
}
54+
1555
try {
16-
const content = await specLoader.loadChapter(params.chapter);
56+
const content = await specLoader.loadChapter(matchedChapter);
1757

1858
return {
1959
content: [{ type: "text", text: content }],
2060
};
2161
} catch (error) {
22-
// If chapter not found, provide helpful error with valid chapters
23-
const validChapters = await indexService.listChapterIds();
24-
2562
return {
2663
isError: true,
2764
content: [
2865
{
2966
type: "text",
30-
text: `Chapter '${
31-
params.chapter
32-
}' not found. Valid chapters: ${validChapters.join(", ")}`,
67+
text: `Error loading chapter '${matchedChapter}': ${
68+
error instanceof Error ? error.message : "Unknown error"
69+
}`,
3370
},
3471
],
3572
};

0 commit comments

Comments
 (0)