Juicebox MCP

Juicebox MCP

Lets Claude read your Juicebox saved searches and scored candidate results using your own logged-in session, entirely on your machine.

Category
访问服务器

README

Juicebox MCP

A local MCP server that reads your Juicebox sourcing data into Claude — saved searches and their scored results — using your own logged-in Juicebox session.

Runs entirely on your machine. Your session never leaves it, and every call is made as you, on your own seat.

Reads cost no export credits. Everything the read tools return comes from the same free surface the search-results page already renders. One tool writes, and says so: jb_run_search creates a real saved search in your workspace.


Install

Option A — Desktop Extension (easiest)

Download juicebox-mcp.mcpb from Releases, then double-click it, or drag it into Claude Desktop → Settings → Extensions.

There is no API key to paste. After installing, do the one-time browser steps below.

Option B — from source

git clone https://github.com/jnot807/juicebox-mcp.git
cd juicebox-mcp
npm install          # also downloads the Chromium build (see note)
npm run login        # a real browser opens — sign in to Juicebox yourself
npm run check        # proves the session works headless

Then register it with Claude Code:

claude mcp add -s user juicebox -- node "$(pwd)/server.js"

-s user makes it available in every session; without it the registration is scoped to whatever directory you happened to run it from.

The one-time browser download

This drives a real Chromium, and that binary is not part of node_modules — it is a one-time download of roughly 500MB into a shared cache (~/Library/Caches/ms-playwright on macOS).

npm install fetches it automatically via a postinstall step. Desktop Extension users need to run it once by hand, because an extension bundles node_modules but not that cache:

npx patchright install chromium

If it is missing, the server tells you so in plain language rather than throwing a stack trace about a missing executable.

Signing in

Authentication is a real sign-in, not a key. npm run login opens a browser window; sign in to Juicebox as you normally would. The session is then stored in session/ (gitignored, chmod 600) and reused headlessly.

Sign in again whenever npm run check starts failing — sessions expire.


Tools

Tool What it does
jb_list_searches(projectId?) Saved searches on a project (id + name).
jb_get_results(searchId, limit?, minMatchRate?) A search's ranked candidates — name, LinkedIn URL, title, company, location, matchRate, per-criterion verdicts, and dated experience[] + education read off the rendered cards. Up to ~500 per call.
jb_count(queryInput, searchId?) Size a filter set without running a search — the tuning primitive. queryInput is a PATCH over a harvested template; check noEffect in the response.
jb_run_search(prompt, need?) WRITES. Creates and runs a new search from a natural-language prompt, then returns its candidates. Leaves a saved search visible to your whole workspace — confirm before using it.

experience[] is the only way to see past employers: the API payload carries just the current one, so alumni of a target company are invisible without it.


Which project it reads by default

Nothing is hardcoded. At sign-in, a probe loads /projects, which redirects into a project your seat can see, and that id is saved as defaultProjectId in session/session-meta.json.

It is written once and then left alone. The redirect follows whichever project the app most recently had open, so trusting it on every run would make a tool call with no projectId read a different project than it did yesterday.

Resolution order:

  1. JUICEBOX_PROJECT_ID (env — this is what the Desktop Extension's optional "default project" field sets)
  2. JUICEBOX_VALIDATOR_PROJECT (env — also pins the auth check to that project)
  3. defaultProjectId in session/session-meta.json, set by discovery

Every tool also takes an explicit projectId, which always wins.

Juicebox project ids are ~20-character keys like c5PheL2fANnX6uBQVUdo — the /project/<id>/ part of a URL. If you pass a UUID, the server rejects it with an explanation rather than silently navigating to a project that does not exist.


Two rules the tools carry

  • verdictFound: false → unknown, never a negative. "No evidence found" and "evidence says no" are different verdicts. Collapsing them scores a candidate down for a criterion nobody could actually check.
  • Broad skill terms dilute ranking. Skills are OR-weighted; a population-wide term like "Account Management" on a customer-success search inflates the pool by roughly 3.4×. Drop the generic terms and promote the one hard requirement to a skill filter.

Running scripts while the server is up

You can't share the browser profile: session/profile/ is single-writer, and the MCP server holds it whenever it is running. A second process trying to open it fails the auth check — which reports itself as "session expired" and sends you round in circles re-logging-in.

For diagnostics, build a fresh context from the checkpoint instead. No lock, same session:

const { chromium } = require('patchright');
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ storageState: 'session/storage-state.json' });

How it works, and the traps

The results page is server-rendered on first load, so /api/profiles/results only fires on interaction. The client nudges the pager to make the app issue its own request, then captures the response — which carries the whole ranked set, not just the visible page.

Three things that will bite anyone editing client.js:

  1. Never use addInitScript. Patchright silently no-ops it as an anti-detection measure — no error, the script just never runs. Use page.on('response').
  2. The API's linkedin_url is encrypted (hex:hex), as are profiles[].url and profileDetails.id. Real URLs come from the rendered cards and are joined on normalised full_name — measured at 100% on a live search.
  3. The list blanks mid-pagination. A null pager reading means "still moving", not "failed". Gating anything on pager-change detection during a transition is how two earlier bugs happened.

When it breaks

This rides Juicebox's internal API. There is no stability contract, and it can change without notice.

  • npm run check fails → session expired: npm run login.
  • The server says Chromium is missing → npx patchright install chromium.
  • jb_get_results returns source: "dom-fallback" → the API capture broke; you lose matchRate and criteria. Check RESULTS_PATH still matches.
  • jb_get_results reports joinedLinkedInUrls: 0 → the card markup changed; revisit harvestCards / rewindToFirstPage.
  • Empty search list → the project page markup changed; see listSavedSearches.

Requirements

  • Node.js 18 or newer
  • A Juicebox account you can sign into
  • ~500MB free disk for the Chromium download

Licence

MIT. Not affiliated with or endorsed by Juicebox.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选