Skip to content

Commit 5e6d03b

Browse files
committed
debug(pdf-server): add hex char diagnostics for path mismatch
1 parent 3d6ba15 commit 5e6d03b

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

examples/pdf-server/server.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ export function isAncestorDir(dir: string, filePath: string): boolean {
106106
* Handles Unix paths (/...), home-relative (~), and Windows drive letters (C:\...).
107107
*/
108108
function isLocalPath(url: string): boolean {
109-
return url.startsWith("/") || url.startsWith("~") || /^[A-Za-z]:[/\\]/.test(url);
109+
return (
110+
url.startsWith("/") || url.startsWith("~") || /^[A-Za-z]:[/\\]/.test(url)
111+
);
110112
}
111113

112114
export function validateUrl(url: string): { valid: boolean; error?: string } {
@@ -125,11 +127,20 @@ export function validateUrl(url: string): { valid: boolean; error?: string } {
125127

126128
if (!exactMatch && !dirMatch) {
127129
const diagnostics = [...allowedLocalDirs].map((d) => {
128-
const rel = path.relative(d, resolved);
129-
return `dir=${d} rel=${rel} match=${isAncestorDir(d, resolved)}`;
130+
// Find first char that differs to diagnose encoding issues
131+
const prefix = resolved.substring(0, d.length);
132+
let firstDiff = "";
133+
for (let i = 0; i < Math.min(d.length, prefix.length); i++) {
134+
if (d[i] !== prefix[i]) {
135+
firstDiff = `firstDiff@${i}: dir=0x${d.charCodeAt(i).toString(16)} file=0x${prefix.charCodeAt(i).toString(16)}`;
136+
break;
137+
}
138+
}
139+
if (!firstDiff && d.length === prefix.length) firstDiff = "IDENTICAL_PREFIX";
140+
return `match=${isAncestorDir(d, resolved)} ${firstDiff} resolvedLen=${resolved.length} dirLen=${d.length}`;
130141
});
131142
console.error(
132-
`[pdf-server] validateUrl REJECTED:\n url=${url}\n resolved=${resolved}\n diagnostics:\n ${diagnostics.join("\n ")}`,
143+
`[pdf-server] REJECTED url=${JSON.stringify(url)}\n resolved=${JSON.stringify(resolved)}\n dirs=${JSON.stringify([...allowedLocalDirs])}\n ${diagnostics.join("\n ")}`,
133144
);
134145
return {
135146
valid: false,
@@ -556,7 +567,10 @@ Accepts:
556567
- Local files under directories provided by the client as MCP roots
557568
- Any remote PDF accessible via HTTPS`,
558569
inputSchema: {
559-
url: z.string().default(DEFAULT_PDF).describe("PDF URL or local file path"),
570+
url: z
571+
.string()
572+
.default(DEFAULT_PDF)
573+
.describe("PDF URL or local file path"),
560574
page: z.number().min(1).default(1).describe("Initial page"),
561575
},
562576
outputSchema: z.object({

0 commit comments

Comments
 (0)