Skip to content

Commit 4fb3b04

Browse files
committed
fix: improve Windows compatibility for OAuth and file handling
- Replace platform-specific shell commands with cross-platform 'open' package for browser launching - Fix file:// URL path conversion on Windows using fileURLToPath instead of URL.pathname - Bind OAuth callback server to localhost explicitly for better security - Add documentation comment for file permission behavior on Windows - Remove unused imports (exec, promisify, throttle)
1 parent 0f66b44 commit 4fb3b04

File tree

2 files changed

+6
-29
lines changed

2 files changed

+6
-29
lines changed

src/client/oauth-provider.ts

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1-
import { exec } from 'node:child_process';
21
import fs from 'node:fs/promises';
32
import { createServer } from 'node:http';
43
import os from 'node:os';
54
import path from 'node:path';
65
import { URL } from 'node:url';
7-
import { promisify } from 'node:util';
86
import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
97
import type {
108
OAuthClientInformation,
119
OAuthClientInformationFull,
1210
OAuthClientMetadata,
1311
OAuthTokens,
1412
} from '@modelcontextprotocol/sdk/shared/auth.js';
15-
import { throttle } from 'lodash';
16-
17-
const execAsync = promisify(exec);
13+
import open from 'open';
1814

1915
interface StoredTokens {
2016
tokens?: OAuthTokens;
@@ -31,7 +27,6 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
3127
private _clientInfo?: OAuthClientInformationFull;
3228
private _codeVerifier?: string;
3329
private tokenFilePath: string;
34-
private throttledOpenBrowser: (url: string) => Promise<void>;
3530

3631
/**
3732
* Check for existing client information in storage
@@ -60,8 +55,6 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
6055
this.tokenFilePath =
6156
tokenStoragePath ||
6257
path.join(os.homedir(), '.pageindex-mcp', 'oauth-tokens.json');
63-
64-
this.throttledOpenBrowser = throttle(this.openBrowser.bind(this), 1000);
6558
}
6659

6760
get redirectUrl(): string | URL {
@@ -107,7 +100,7 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
107100

108101
async redirectToAuthorization(authorizationUrl: URL): Promise<void> {
109102
try {
110-
await this.throttledOpenBrowser(authorizationUrl.toString());
103+
await open(authorizationUrl.toString());
111104
} catch (error) {
112105
console.error(
113106
error instanceof Error
@@ -221,7 +214,7 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
221214
res.end('Not found');
222215
});
223216

224-
server.listen(port, () => {
217+
server.listen(port, 'localhost', () => {
225218
console.error(`Listening for OAuth callback on port ${port}...\n`);
226219
});
227220

@@ -239,24 +232,6 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
239232
});
240233
}
241234

242-
private async openBrowser(url: string): Promise<void> {
243-
const platform = process.platform;
244-
let command: string;
245-
246-
switch (platform) {
247-
case 'darwin':
248-
command = `open "${url}"`;
249-
break;
250-
case 'win32':
251-
command = `start "${url}"`;
252-
break;
253-
default:
254-
command = `xdg-open "${url}"`;
255-
break;
256-
}
257-
await execAsync(command);
258-
}
259-
260235
public async loadFromStorage(): Promise<void> {
261236
try {
262237
const data = await fs.readFile(this.tokenFilePath, 'utf-8');
@@ -281,6 +256,7 @@ export class PageIndexOAuthProvider implements OAuthClientProvider {
281256

282257
try {
283258
await fs.mkdir(path.dirname(this.tokenFilePath), { recursive: true });
259+
// Set restrictive file permissions (Unix-like systems only; ignored on Windows)
284260
await fs.writeFile(this.tokenFilePath, JSON.stringify(stored, null, 2), {
285261
mode: 0o600,
286262
});

src/tools/process-document.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'node:fs/promises';
22
import path from 'node:path';
3+
import { fileURLToPath } from 'node:url';
34
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
45
import open from 'open';
56
import pRetry, { AbortError } from 'p-retry';
@@ -149,7 +150,7 @@ async function processDocument(
149150
async function readLocalPdf(filePath: string): Promise<FileInfo> {
150151
let resolvedPath = filePath;
151152
if (filePath.startsWith('file://')) {
152-
resolvedPath = new URL(filePath).pathname;
153+
resolvedPath = fileURLToPath(filePath);
153154
}
154155
if (!path.isAbsolute(resolvedPath)) {
155156
resolvedPath = path.resolve(process.cwd(), resolvedPath);

0 commit comments

Comments
 (0)