Repository navigation
You've got a few bugs #6
Description
Product
VS Code extension (perplexity-vscode)
Version
1
MCP Client (if applicable)
None
Perplexity tier
None
OS
Mac
Browser used by the MCP server
No response
What happened?
The upstream/general bugs we found, separate from the repo-trimming work, are:
-
CLI silently exits when launched through a symlink
The direct-run guard used:import.meta.url === pathToFileURL(process.argv[1]).href
That fails when
process.argv[1]is a symlink, becauseimport.meta.urlresolves to the real built file. Result:routeCommand()never runs and commands exit0with no output.Upstream fix: compare
realpathSync(fileURLToPath(import.meta.url))torealpathSync(process.argv[1]). -
Built
dist/cli.mjsneeds a real executable shebang
The npmbinpoints at./dist/cli.mjs. Without:#!/usr/bin/env nodeand executable mode, global installs or raw symlinked bins can fail or behave weirdly on macOS/Homebrew setups.
Upstream fix: keep shebang in source or add it as part of build, and chmod the built CLI.
-
Repeated macOS Keychain prompts
The doctor/status/login paths can touch vault/keychain repeatedly, causing the user to be prompted many times. That is a real UX bug, not trim-specific.Upstream fix: cache keychain probe results per process, avoid repeated
keytar.getPassword()calls in diagnostics, and add a supported escape hatch likePERPLEXITY_DISABLE_KEYCHAIN=1for tests/headless diagnostics. -
Manual login browser session was not persistent enough
The login flow opened Chrome but did not preserve Google SSO state reliably between attempts. If the Perplexity login depends on Google, users can get confused because the launched Chrome is not their normal Chrome profile.Upstream fix: use a dedicated persistent browser profile for MCP login, document where it lives, and clear stale Chrome singleton lock files before launch.
-
Image payload rejection recovery in Hermes, adjacent but not this repo
This one is not a Perplexity MCP bug directly, but it affected debugging: Hermes sentimage_urlblocks to a text-only DeepSeek endpoint and did not recognize the provider’s error wording.
Activity
ARHAEEM commentedon May 11, 2026
Thanks for the careful writeup — confirmed all four upstream bugs against
main. Bundling these into the 0.8.43 release that's already in flight for #5 since they touch overlapping CLI/login code paths and one VSIX smoke pass covers everything.Confirmed and planned
1. CLI symlink exit — confirmed
Two call sites bite, not one:
packages/mcp-server/src/cli.js:1306ANDpackages/mcp-server/src/index.ts:194. Theindex.tsone is the daemon entrypoint, so the same regression silently no-ops the daemon when the bin is symlinked too — worth fixing both.Fix shape:
Keep the original comparison as the catch fallback so we don't regress on platforms where realpath rejects (rare, but defense in depth). Drop the
/* v8 ignore start */block too — with realpath we can write a proper fixture.2. Built
dist/cli.mjsshebang + exec mode — confirmedtsup.config.ts:82-87explicitly does NOT emit a shebang and the comment claims "npm'sbinlinker wraps the entry with its own node invocation on install." That's wrong on POSIX — npm just creates a symlink atnode_modules/.bin/perplexity-user-mcp → ../perplexity-user-mcp/dist/cli.mjsand chmods it 755. Kernel can't exec a file without a shebang or magic bytes; you get the silent-no-output failure mode you described.Fix shape:
banner: { js: "#!/usr/bin/env node" }scoped to the cli entry only (not the lib bundles — they'd break ESM import). Tsup supports per-entry options via theentrymap but needs a small refactor to splitclifrom the lib entries; alternative is a post-buildprepend-shebangscript that targets onlydist/cli.mjs. Going with the post-build script to avoid touching the lib build.chmodSync(dist/cli.mjs, 0o755)so even direct execution from the cloned repo works withoutnode ./dist/cli.mjs.cli.jsshebang-free so vitest/esbuild test imports still parse cleanly (the original constraint that motivated stripping the shebang is real).3. Repeated macOS Keychain prompts — partially confirmed, fixing both halves
There are four independent keytar probe paths today:
cli.js:probeVaultState(called fromsetup-vault,status, login preflight)checks/vault.js:tryKeychain(called fromdoctor)vault.js:keyFromKeychain— cached via_unsealMaterialCachefor the runtime path, butgetAllUnsealMaterials()calls it un-cached every readextension/src/auth/vault-passphrase.ts:probeKeytarAvailable(extension host probe via fork()'d child)Within one process the runtime path is fine after first hit; the prompt-spam comes from (a) separate CLI invocations each re-probing and (b)
getAllUnsealMaterialsnot caching after the first negative probe in headless-Linux scenarios.Fix shape:
vault.jssogetAllUnsealMaterialsandgetUnsealMaterialshare state — one probe per process, regardless of how many vault reads happen.PERPLEXITY_DISABLE_KEYCHAIN=1as a documented escape hatch, honored intryKeytar()(and mirrored inchecks/vault.js:tryKeychainso the doctor agrees with the runtime path). When set, the keychain probe short-circuits to "unavailable" without ever callingkeytar.getPassword().PERPLEXITY_VAULT_PASSPHRASE— if env passphrase is set, the keychain probe is decoration and we can skip it on that branch inprobeVaultState. Keeps the doctor honest while removing the gratuitous prompt.4. Manual login Chrome profile not persistent — confirmed; need a quick design call
manual-login-runner.js:45-50launches non-persistent. Daemon'sheadedBootstrapalready useslaunchPersistentContext(getActivePaths().browserData, ...). Two options for where the login runner's persistent profile lives — want your input here because either reads as "dedicated persistent browser profile" depending on what you meant:Option A — Share the daemon's
~/.perplexity-mcp/profiles/<name>/browser-data/. Single source of truth: Google SSO state from login carries directly into the daemon's headed bootstrap (the daemon's auth check might even succeed on first init without needing the vault round-trip). Risk: Chrome singleton-lock collision if the daemon is mid-headed-bootstrap when the user kicks off login — the existingclearStaleSingletonLocks()helper handles stale locks but not LIVE concurrent access. Mitigation: login runner waits up to N seconds for the lock to clear, falls back to option B if it can't.Option B — Dedicated
~/.perplexity-mcp/profiles/<name>/login-browser-data/. Clean lock separation, never conflicts with daemon. Trade-off: Google SSO state stays scoped to the login runner; the daemon picks up the resulting cookies through the vault path (which is already how it works today, just now with persisted Google session for next login).Which way do you want to go? Your wording "dedicated persistent browser profile" reads as Option B but A has bigger ergonomic upside if the lock case can be handled cleanly.
Secondary note: this fix interacts with #5's Fix 2 (Phase 2 of the daemon currently uses non-persistent context too, so it discards the headed phase's fresh
cf_clearance). If we go Option A here AND Fix 2 there, the daemon's Phase 2 reads the same browser-data dir as both the headed bootstrap AND the login runner — cookies and cf_clearance flow naturally through one disk profile.5. Hermes image_url rejection — acknowledged, not this repo
Filed mentally. If you have the Hermes-side write-up somewhere, link it here so future readers can find it; otherwise no action.
Process
0.8.43 is the target release. Smoke matrix per
docs/release-process.mdcovers Win11, macOS 14+, and Ubuntu 22+ — your bug 1+2 specifically need the macOS row to actually pass since Homebrew bin layout is the canonical reproducer.If you've already got patches in your fork for any of bugs 1–4, please send them as PRs and we'll review there — saves rebuilding the diff blind. Otherwise we'll cut the patches against
mainand push a draft PR within the next pass once #5's diagnostic data lands.Thanks again — the symlink + shebang pair was a clean catch and would have stayed hidden until the next macOS user filed.
juangrukat commentedon May 11, 2026
I trimmed your repo pretty severely so can’t PR.
I kept only the useful parts.
The main problem was having to log in constantly, which should be addressed by previously noted.
ARHAEEM commentedon May 11, 2026
Understood, no worries on the PR — the four diagnoses were enough to fix all of them. Locking in Option B (dedicated
~/.perplexity-mcp/profiles/<name>/login-browser-data/for the login runner) per your "dedicated persistent browser profile" wording. The Option A upside disappeared once I looked closer at Chromium's user-data-dir locking — it's a per-process LIVE lock, not just a stale-file check, so even withclearStaleSingletonLocks()the login-while-daemon-is-mid-bootstrap window is a real failure mode. Option B sidesteps that entirely.Starting the patches now. Will ping when the 0.8.43 VSIX is ready for smoke; if you want to take it for a spin on your trimmed setup before the public release, I'll attach the artifact here.
Thanks again for the focused reports — "having to log in constantly" was a real UX paper cut and fixing #6/4 alongside #5 means the daemon's headed bootstrap can stop being a CF-only step too.
juangrukat commentedon May 11, 2026
No. need, I'll get pinged once you release, and my setup is working.
Thanks for the work on this. I was going back and forth between browsers (perplexity, search). You've saved me time with this idea. thanks
ARHAEEM commentedon May 11, 2026
Pinging as promised — all four bugs are patched and in PR #7 targeting 0.8.43.
Quick summary of what landed:
isMainModule()now usesrealpathSyncon both sides, with fallback to the old comparison if realpath rejects. Bothcli.jsandindex.tsupdated.dist/cli.mjsgets#!/usr/bin/env nodeprepended andchmod 755via a post-build script. No more silent-no-output on direct invocation.probeKeychainState()shared acrosscli.jsandchecks/vault.js(removes three duplicate inline probes);PERPLEXITY_DISABLE_KEYCHAIN=1escape hatch for headless/CI.login-runner.jsandmanual-login-runner.jsnow uselaunchPersistentContext(paths.loginBrowserData, ...)— dedicatedlogin-browser-data/dir, separate from the daemon'sbrowser-data/to avoid Chromium singleton-lock collisions (Option B as agreed). Soft-logout clears it so the next login starts fresh.130/130 tests pass, full typecheck clean. PR: #7
Will attach the VSIX to the release notes once smoke passes — appreciate the patience.
Merge pull request #7 from Automations-Project/fix/0.8.43-auth-cli-ha…
fix(macos): scope daemon vault-cache reset to passphrase reinits