Skip to main content
Glama
Juicebox MCP

Juicebox MCP

by jnot807

Juicebox MCP

Juicebox 소싱 데이터를 Claude로 읽어들이는 로컬 MCP 서버 — 저장된 검색과 점수화된 결과를, 로그인한 Juicebox 세션을 사용하여 처리합니다.

전적으로 사용자 머신에서 실행됩니다. 세션이 머신을 떠나지 않으며, 모든 호출은 사용자 본인으로, 사용자 자신의 시트에서 이루어집니다.

읽기 작업은 내보내기 크레딧을 소모하지 않습니다. 읽기 도구가 반환하는 모든 것은 검색 결과 페이지가 이미 렌더링하는 동일한 무료 표면에서 나옵니다. 하나의 도구만 쓰기 작업을 하며, 그렇게 명시합니다: jb_run_search는 워크스페이스에 실제 저장된 검색을 생성합니다.


설치

옵션 A — 데스크톱 확장 (가장 쉬움)

Releases에서 juicebox-mcp.mcpb를 다운로드한 후, 더블클릭하거나 Claude Desktop → 설정 → 확장으로 드래그하세요.

붙여넣을 API 키는 없습니다. 설치 후 아래의 일회성 브라우저 단계를 수행하세요.

옵션 B — 소스에서

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

그런 다음 Claude Code에 등록하세요:

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

-s user는 모든 세션에서 사용할 수 있게 합니다. 없으면 등록은 실행한 디렉토리로 범위가 제한됩니다.

일회성 브라우저 다운로드

이것은 실제 Chromium을 구동하며, 해당 바이너리는 node_modules의 일부가 아닙니다 — 공유 캐시(macOS의 ~/Library/Caches/ms-playwright)에 약 500MB를 일회성으로 다운로드합니다.

npm install은 postinstall 단계를 통해 자동으로 가져옵니다. 데스크톱 확장 사용자는 한 번 수동으로 실행해야 합니다. 확장은 node_modules를 번들하지만 해당 캐시는 번들하지 않기 때문입니다:

npx patchright install chromium

없으면 서버는 누락된 실행 파일에 대한 스택 트레이스를 던지는 대신 평이한 언어로 알려줍니다.

로그인

인증은 키가 아닌 실제 로그인입니다. npm run login은 브라우저 창을 엽니다. 평소처럼 Juicebox에 로그인하세요. 세션은 session/(gitignore, chmod 600)에 저장되며 헤드리스로 재사용됩니다.

npm run check가 실패하기 시작할 때마다 다시 로그인하세요 — 세션은 만료됩니다.


Related MCP server: JobSpy MCP Server

도구

도구

기능

jb_list_searches(projectId?)

프로젝트의 저장된 검색 (id + 이름).

jb_get_results(searchId, limit?, minMatchRate?)

검색의 순위가 매겨진 후보 — 이름, LinkedIn URL, 직함, 회사, 위치, matchRate, 기준별 판정, 그리고 렌더링된 카드에서 읽은 날짜가 있는 experience[] + education. 호출당 최대 ~500개.

jb_count(queryInput, searchId?)

검색을 실행하지 않고 필터 세트의 크기를 측정 — 튜닝의 기본 요소. queryInput은 수집된 템플릿에 대한 PATCH입니다. 응답에서 noEffect를 확인하세요.

jb_run_search(prompt, need?)

쓰기 작업. 자연어 프롬프트에서 새 검색을 생성하고 실행한 후 후보를 반환합니다. 전체 워크스페이스에 보이는 저장된 검색을 남깁니다 — 사용 전에 확인하세요.

experience[]는 과거 고용주를 볼 수 있는 유일한 방법입니다. API 페이로드는 현재 고용주만 전달하므로, 대상 회사의 동문은 이것 없이는 보이지 않습니다.


기본으로 읽는 프로젝트

하드코딩된 것은 없습니다. 로그인 시 프로브가 /projects를 로드하며, 이는 사용자 시트가 볼 수 있는 프로젝트로 리디렉션되고, 해당 id는 session/session-meta.json의 defaultProjectId로 저장됩니다.

한 번 기록된 후 그대로 둡니다. 리디렉션은 앱이 가장 최근에 열었던 프로젝트를 따르므로, 매 실행마다 신뢰하면 projectId 없이 호출된 도구가 어제와 다른 프로젝트를 읽게 됩니다.

해결 순서:

  1. JUICEBOX_PROJECT_ID (환경 변수 — 데스크톱 확장의 선택적 "기본 프로젝트" 필드가 설정하는 것)

  2. JUICEBOX_VALIDATOR_PROJECT (환경 변수 — 인증 확인도 해당 프로젝트로 고정)

  3. session/session-meta.json의 defaultProjectId (탐색으로 설정)

모든 도구는 명시적 projectId도 받으며, 항상 우선합니다.

Juicebox 프로젝트 id는 c5PheL2fANnX6uBQVUdo와 같은 ~20자 키입니다 — URL의 /project/<id>/ 부분입니다. UUID를 전달하면 서버는 존재하지 않는 프로젝트로 조용히 이동하는 대신 설명과 함께 거부합니다.


도구가 지니는 두 가지 규칙

  • verdictFound: false → unknown, 결코 부정이 아님. "증거 없음"과 "증거가 아니라고 말함"은 다른 판정입니다. 이 둘을 합치면 아무도 실제로 확인할 수 없는 기준에 대해 후보를 낮게 평가하게 됩니다.

  • 광범위한 기술 용어는 순위를 희석시킵니다. 기술은 OR 가중치가 적용됩니다. 고객 성공 검색에서 "Account Management"와 같은 인구 전체 용어는 풀을 약 3.4배 부풀립니다. 일반 용어를 제거하고 하나의 핵심 요구 사항을 기술 필터로 승격하세요.


서버가 실행되는 동안 스크립트 실행

브라우저 프로필을 공유할 수 없습니다. session/profile/은 단일 작성자이며, MCP 서버는 실행 중일 때 항상 이를 보유합니다. 이를 열려고 하는 두 번째 프로세스는 인증 확인에 실패합니다 — 이는 "세션 만료"로 보고되며, 재로그인을 반복하게 만듭니다.

진단을 위해 체크포인트에서 새 컨텍스트를 빌드하세요. 잠금 없음, 동일한 세션:

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

작동 방식 및 함정

결과 페이지는 첫 로드 시 서버 렌더링되므로 /api/profiles/results는 상호작용 시에만 발생합니다. 클라이언트는 페이저를 움직여 앱이 자체 요청을 발행하게 한 다음 응답을 캡처합니다 — 응답은 보이는 페이지만이 아니라 전체 순위 세트를 전달합니다.

client.js를 편집하는 사람을 물릴 세 가지:

  1. addInitScript를 절대 사용하지 마세요. Patchright는 탐지 방지 조치로 이를 조용히 무시합니다 — 오류 없이 스크립트가 실행되지 않습니다. page.on('response')를 사용하세요.

  2. API의 linkedin_url은 암호화되어 있습니다 (hex:hex), profiles[].url 및 profileDetails.id도 마찬가지입니다. 실제 URL은 렌더링된 카드에서 오며 정규화된 full_name으로 조인됩니다 — 라이브 검색에서 100%로 측정되었습니다.

  3. 목록은 페이지 매김 중간에 비워집니다. null 페이저 읽기는 "아직 이동 중"을 의미하며 "실패"가 아닙니다. 전환 중 페이저 변경 감지에 무엇이든 게이트하는 것이 이전 두 버그가 발생한 방법입니다.


문제 발생 시

이것은 Juicebox의 내부 API를 사용합니다. 안정성 계약이 없으며, 통지 없이 변경될 수 있습니다.

  • npm run check 실패 → 세션 만료: npm run login.

  • 서버가 Chromium이 없다고 말함 → npx patchright install chromium.

  • jb_get_results가 source: "dom-fallback" 반환 → API 캡처가 깨졌습니다. matchRate와 기준을 잃게 됩니다. RESULTS_PATH가 여전히 일치하는지 확인하세요.

  • jb_get_results가 joinedLinkedInUrls: 0 보고 → 카드 마크업이 변경되었습니다. harvestCards / rewindToFirstPage를 다시 검토하세요.

  • 빈 검색 목록 → 프로젝트 페이지 마크업이 변경되었습니다. listSavedSearches를 참조하세요.


요구 사항

  • Node.js 18 이상

  • 로그인할 수 있는 Juicebox 계정

  • Chromium 다운로드를 위한 약 500MB 여유 디스크

라이선스

MIT. Juicebox와 제휴하거나 보증하지 않습니다.

Available Tools

4 tools
jb_countA

Size a filter set WITHOUT running a search — the tuning primitive. Free and side-effect free, so permute filters and compare before committing to a run. The endpoint is VERIFIED DETERMINISTIC (same body, same count on repeat), which is what makes the comparisons below trustworthy.

queryInput is a PATCH, not a whole body. It is merged over a ~164-key template harvested live from a saved search, because a PARTIAL body does not error — it returns result:0, which reads exactly like "nobody matches your filters". Pass only the keys you want to change. Use searchId to choose which saved search supplies the template; the response echoes baseline (the unpatched count).

ALWAYS CHECK noEffect IN THE RESPONSE. Unrecognised keys and wrong value shapes are dropped SILENTLY, so an unchanged count means the key name is probably wrong, NOT that the filter does not matter. Measured example: coSizes (company headcount) is ignored in all eight shapes tried, including [{name:"51-200"}], ["51-200"], [{title,tag}] and [{min,max}]. Its real shape is still unknown — set the filter in the Juicebox UI and capture the request before trusting it.

SOME FILTERS EXPAND RATHER THAN RESTRICT, which is the opposite of the intuition and was measured on one search (baseline 1413): dropping industries gives 1387 and dropping coTags gives 1247 — REMOVING them SHRINKS the pool, so they act as OR-expanders and cannot be used to narrow onto a category. An unrecognised industry ("mining & metals") returns the same 1387 as an empty list. What actually restricts: skills (removing all four widened 1413 to 4526), yearsOfExp (20 gives 881), selectedLocs, and criteria. Note this REVISES the older claim that broad skill terms widen the pool — specific skills restrict hard, broad ones merely fail to restrict. The practical rule is unchanged: drop skill terms that describe the whole population, and promote the ONE hard requirement to a skill (e.g. "AI Agents", not prose about being AI-first).

NameRequiredDescriptionDefault
searchIdNoSaved search to harvest the template from (from jb_list_searches). Defaults to the first saved search on the project. Pick the one whose titles/locations you want as your starting point.
projectIdNoJuicebox project id — a ~20-character key like c5PheL2fANnX6uBQVUdo, taken from the /project/<id>/ part of a Juicebox URL. Optional: omit it to use the default project discovered at sign-in.
queryInputYesPATCH over the harvested template — only the keys you are changing. Verified keys: jobTitles[{title,tag}], pastJobTitles, skills[{title,tag}], industries[{name}], coTags[{title,name,tag}], selectedLocs[{name,country,continent,type,...}], selectedCos, timezones, revenueRanges, fundingStages, yearsOfExp (number), criteria[{text,id}], excludeDncCountries (bool), coSizes (present but IGNORED in every shape tried).

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the entire behavioral burden, and it excels. It reveals that the endpoint is deterministic, that partial bodies are silently merged over a template, that unrecognized keys are dropped silently, and that filter behavior can be counterintuitive (some expand rather than restrict). It even provides measured examples showing how to detect silent failures via the noEffect flag. This is exemplary transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but every sentence carries critical, non-redundant information. It front-loads the core purpose and safety properties, then layers in warnings and measured data. No filler or repetition exists; each paragraph adds actionable knowledge an agent needs to use the tool correctly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (nested objects, no output schema) and the absence of annotations, this description is remarkably complete. It covers expected behavior, failure modes (silent drops, noEffect), practical examples, and even guidance on filter semantics that only become apparent through experimentation. An agent has everything it needs to call this tool correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the schema already describes each parameter, the description adds value by clarifying that queryInput is a PATCH over a template, enumerating the verified key shapes (e.g., 'skills[{title,tag}]'), and explicitly flagging coSizes as ignored in every tested shape. It also explains how searchId selects the template and the meaning of the echoed 'baseline.' This goes well beyond the schema definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb and object: 'Size a filter set WITHOUT running a search — the tuning primitive.' This immediately distinguishes it from running a search and states its role as a sizing/measurement tool. It also explicitly contrasts with the sibling jb_run_search by saying 'before committing to a run,' leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance ('permute filters and compare before committing to a run') and explains the side-effect-free nature that makes this safe for experimentation. It also instructs on selecting the saved search template via searchId and warns about the partial-body PATCH semantics. This is far more than typical usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jb_get_resultsA

Pull a saved search's ranked candidates — up to ~500 in one call. Returns name, LinkedIn URL, title, company, location, a numeric matchRate (0-100, banded) and per-criterion verdicts. Costs NO export credits: this is the same free surface the results page renders.

READING THE RESULTS: at the top of a ranked list every candidate meets every criterion, so criteria-met count does NOT discriminate up there — use matchRate and depth. A criterion with verdictFound=false is reported as result "unknown": that means no evidence was found, NOT that the candidate fails it. Never treat an unknown as a negative.

If the search has never been executed, this errors — open it in the app and press "Run search" once.

NameRequiredDescriptionDefault
limitNoMax candidates to return (default 50, max 500).
searchIdYesSaved search id from jb_list_searches.
projectIdNoJuicebox project id — a ~20-character key like c5PheL2fANnX6uBQVUdo, taken from the /project/<id>/ part of a Juicebox URL. Optional: omit it to use the default project discovered at sign-in.
minMatchRateNoOnly return candidates at or above this matchRate.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the free/costless nature, the exact return data, the significance of verdictFound=false ('not a negative'), and the error condition for unexecuted searches. It also notes that matchRate is 'banded' and that criteria-met count doesn't discriminate at the top of a ranked list. This is rich behavioral detail well beyond structured fields, giving the agent a clear understanding of what happens when calling the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence earns its place: the first line states the action and output, the cost note is critical, the 'READING THE RESULTS' section is indispensable for correct interpretation, and the final error note is essential. It's well-structured with clear sections (purpose, cost, interpretation, error condition). No fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description enumerates the return fields and explains the semantic meaning of matchRate and verdicts (including the crucial 'unknown ≠ negative' nuance). It covers error behavior, limits, and the relationship to search execution. With four parameters fully documented in the schema and the description adding inter-tool references, an agent has everything necessary to correctly invoke and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers all parameters with descriptions at 100% coverage, so the baseline is 3. The description adds meaningful context: it tells the agent that searchId comes from jb_list_searches, that projectId is a specific format and can be omitted to use a default project, and that limit has a default of 50 and max of 500. These references connect the tool to its ecosystem and clarify usage, exceeding the schema's raw field meanings.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb ('Pull') and a specific resource ('a saved search's ranked candidates'), and details the exact fields returned (name, LinkedIn URL, title, company, location, matchRate, per-criterion verdicts). This clearly distinguishes it from siblings like jb_list_searches (which lists searches) and jb_count (counts). The scope is precise and non-tautological.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states that this costs no export credits and is the same surface as the results page, giving context on when it's appropriate. It also provides a prerequisite: 'If the search has never been executed, this errors — open it in the app and press Run search once.' It doesn't explicitly name sibling alternatives, but the distinct purposes of siblings (list, count, run) make the usage boundary clear. The 'READING THE RESULTS' section adds interpretive guidance, though it's more about reading the output than choosing when to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jb_list_searchesA

List the saved searches on a Juicebox project (searchId + name). Saved searches are stable and re-runnable, so this is the entry point for pulling existing sourcing work. Defaults to the configured project.

NameRequiredDescriptionDefault
projectIdNoJuicebox project id, or a /project/{id} URL. Optional.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that saved searches are stable and re-runnable (reassuring the agent that reuse is safe), and that it defaults to the configured project. This adds useful behavioral context beyond the raw schema. It doesn't mention pagination or error behavior, but for a simple list operation this is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences: the first states the purpose and output, the second adds context and default behavior. No wasted words, and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter list tool with no output schema, the description is nearly complete: it explains what is returned, the stability, and the default. It could mention whether an empty list is returned when none exist, but that is minor. It doesn't need to explain return values since it already says 'searchId + name'. Missing details are negligible.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already describes projectId as optional and as a URL or ID (100% coverage). The description adds value by stating it defaults to the configured project, which is not in the schema. That's meaningful extra guidance for when an agent can omit the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (list), the resource (saved searches on a Juicebox project), and the output (searchId + name). It also situates the tool as an entry point for pulling existing sourcing work, distinguishing it from siblings like jb_run_search or jb_get_results without needing to inspect them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says this is the entry point for pulling existing sourcing work, implying you should use this before running or fetching results. It also notes the default-project behavior, which helps an agent decide when explicitly passing projectId is unnecessary. It doesn't explicitly say 'don't use this if you want results' or name alternatives, but the use case is implied clearly enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv1.0.0
    • First observedjb_count
    • First observedjb_get_results
    • First observedjb_list_searches
    • First observedjb_run_search

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: list saved searches, fetch ranked results, tune filter counts, and create/run a new search. No two tools overlap in function, making misselection unlikely.

Naming Consistency5/5

All tools follow the consistent pattern of 'jb_' prefix + verb_noun (list_searches, get_results, run_search) with count as a concise verb. This is predictable and uniform.

Tool Count5/5

Four tools is well-scoped for a talent sourcing server. Each tool earns its place and covers the core workflow without redundancy or bloat.

Completeness4/5

The surface covers the essential lifecycle: listing existing searches, retrieving results, tuning filters without execution, and creating new searches. Minor gaps like deleting or updating saved searches exist but are not critical for the primary use case.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables Claude to perform actions on X, LinkedIn, and Reddit via a Chrome extension, such as connecting with recruiters, finding threads, and replying to posts.
    36
    22 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables job search and scraping across multiple job boards (LinkedIn, Indeed, Glassdoor, etc.) with advanced filtering, directly from Claude Desktop or other MCP clients.
    6
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables searching and evaluating job postings from LinkedIn and freehire.me directly through Claude Desktop. Provides tools to search jobs, fetch full posting details, and assess candidate fit using eligibility scans and a scoring rubric.
    MIT