Skip to main content
Glama
yangsheng6810

Department Web-Search MCP Gateway

부서 웹 검색 MCP 게이트웨이

전체 부서가 공유할 수 있는 자체 호스팅 웹 검색 서비스입니다. 단일 로그인 브라우저 세션(공유 서비스 계정)을 재사용하므로 인트라넷 / SSO / 동의 화면 로그인은 한 번만 처리하면 됩니다. 모든 클라이언트는 web_search 도구만 호출하면 되며, 사용자별 로그인이나 API 키가 필요하지 않습니다.

모든 MCP 클라이언트는 하나의 URL에 연결합니다:

  • Chatbox (≥1.14)

  • OpenCode — 로컬, 공유 서버, 또는 vscode-remote를 통해

  • Claude Code (및 MCP를 사용하는 기타 코딩 에이전트)

이는 연구 노트의 T1 "중앙 집중식 검색 게이트웨이" 입니다: 내부 머신 한 대 + 공유 Chrome 프로필 하나 + HTTP MCP 엔드포인트 하나.


작동 방식

Chatbox / OpenCode(local|server|vscode-remote) / Claude Code
        │  remote MCP (Streamable HTTP, /mcp) — same URL for everyone
        ▼
┌──────────────────────────────────────────────┐
│  Gateway (this service, Node + Express)       │
│   • Bearer token (optional) + Host validation │
│   • MCP tools: web_search / read_webpage      │
└──────────────────────────────────────────────┘
        │  connectOverCDP / launchPersistentContext
        ▼
┌──────────────────────────────────────────────┐
│  Chrome (persistent profile, shared account)  │  ← logged in ONCE via `npm run login`
│   • per-request new tab (isolation)           │
│   • concurrency cap + timeouts                │
└──────────────────────────────────────────────┘
        │  optional fallback
        ▼
   SearXNG (if SEARXNG_URL set) — public-search fallback when browser returns nothing

createMcpHandler는 2025년형과 2026년형 MCP 클라이언트 모두 동일한 /mcp 엔드포인트에서 제공하므로 클라이언트 전송 호환성은 문제가 되지 않습니다.


Related MCP server: local-web-search-service

헤드리스 Linux 서버 + 로그인용 Windows PC

서버에는 GUI가 없지만 Windows PC에서 사람이 로그인할 수 있습니다. .env에서 모드를 선택하세요(BROWSER_MODE). 코드는 동일하며 설정만 다릅니다.

⚠️ Windows Chrome 프로필 디렉토리를 Linux에 복사하지 마십시오. Chromium은 쿠키를 OS에 종속된 키(Windows의 DPAPI, Linux의 keyring/"peanuts")로 암호화하므로 복사된 프로필은 자동으로 로그인 정보를 잃게 됩니다. 아래의 OS 간 안전한 모드 중 하나를 사용하세요.

모드 C — BROWSER_MODE=cdp (권장): Linux 게이트웨이가 Windows 브라우저에 연결

  • Windows PC (계속 켜짐): 공유 계정으로 한 번 로그인한 후, 로컬 전용 디버그 포트로 Chrome을 계속 실행합니다:

    chrome --remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 ^
           --user-data-dir=C:\dept-search-profile
  • SSH 역방향 터널을 사용하여 해당 포트를 Linux 서버로 안전하게 전달합니다(Windows PC에서 실행, Win10/11에는 OpenSSH 탑재):

    ssh -R 9222:127.0.0.1:9222 linuxuser@gateway.server
  • Linux 서버: .env → BROWSER_MODE=cdp, CDP_ENDPOINT=http://127.0.0.1:9222 (서버 로컬, Windows 브라우저로 터널링됨). 그런 다음 npm start.

  • 로그인은 실시간으로 유지됩니다(브라우저를 사용하면서 쿠키가 갱신됨). 프로필 복사 불필요. 인증되지 않은 CDP 포트는 네트워크에 노출되지 않습니다. 단점: Windows PC가 꺼지면 검색이 실패합니다(그것이 용납되지 않으면 모드 B를 사용하세요).

모드 B — BROWSER_MODE=storagestate: 스냅샷, Linux 자체 운영

  • Windows PC: npm run login (헤드 모드), 로그인, Enter 키 입력 → auth.json 생성(OS에 구애받지 않는 쿠키 + localStorage의 JSON).

  • auth.json을 Linux 서버에 복사하고, BROWSER_MODE=storagestate, STORAGE_STATE_FILE=./auth.json으로 설정한 후 npm start를 실행합니다. Linux는 스냅샷을 로드하는 자체 헤드리스 브라우저를 실행합니다. 터널이 필요 없으며 Windows PC가 꺼져도 작동합니다.

  • 절충점: 고정된 스냅샷 — SSO 쿠키가 만료되면 다시 내보내야 합니다. 쿠키 + localStorage만 포함(IndexedDB/클라이언트 인증서는 제외) — 대부분의 SSO에 충분합니다.

모드 A — BROWSER_MODE=persistent: Windows PC가 모든 것을 실행

  • 항상 켜져 있는 Windows PC를 서비스 호스트로 사용할 수 있는 경우: 거기서 npm run login을 실행하여(프로필 시드) BROWSER_MODE=persistent로 npm start를 실행합니다.

  • Linux 서버는 http://<windows-pc>:8787/mcp를 가리키는 순수 클라이언트입니다.

  • 가장 간단합니다 — 터널도, 스냅샷 절차도 없습니다.

클라이언트 온보딩은 모든 모드에서 동일합니다: 클라이언트는 게이트웨이의 MCP URL을 가리키고, 게이트웨이는 설정된 브라우저 모드와 통신합니다.


구축 실행 설명서 — 모드 C (Linux 게이트웨이 + Windows 브라우저)

확인된 설정: Linux 서버가 게이트웨이를 실행하고, 항상 켜져 있는 Windows PC가 실제 Chrome(한 번 로그인)과 SSH 역방향 터널을 실행합니다. Linux 서버에는 브라우저가 다운로드되지 않습니다(playwright-core만 사용).

Windows PC (한 번 설정 후 계속 실행) — windows/README.md 참조

  1. windows\start-browser.ps1 → 127.0.0.1:9222에서 전용 Chrome 실행, 프로필 C:\dept-search-profile. 공유 계정(SSO/2FA)으로 로그인합니다. 계속 열어 둡니다.

  2. $env:GATEWAY_SSH = "linuxuser@gateway.server"; windows\start-tunnel.ps1 → ssh -R 9222:127.0.0.1:9222 gateway 유지, 자동 재연결.

  3. 둘 다 예약된 작업으로 만듭니다(시작 시 / 로그온 시, 로그온 여부와 관계없이 실행). PC가 자가 치유 브라우저 어플라이언스가 됩니다.

Linux 게이트웨이 서버 (이 머신)

cd dept-web-search-gateway
cp .env.example .env
# edit .env:
#   BROWSER_MODE=cdp                       (default)
#   CDP_ENDPOINT=http://127.0.0.1:9222     (the tunneled port, local on this server)
#   HOST=0.0.0.0
#   ALLOWED_HOSTS=search.internal,localhost   # hostnames clients will use
#   GATEWAY_TOKEN=...                      (optional; else rely on network ACL)
npm install                 # lean — playwright-core, no Chromium download
npm run build               # typecheck
npm start                   # dev (tsx); or `npm run build && npm run start:prod`
curl http://127.0.0.1:8787/health         # {"ok":true,...}

클라이언트를 http://<this-server>:8787/mcp로 지정합니다(클라이언트 온보딩 참조).

터널 상태 확인

Linux 서버에서:

curl -s http://127.0.0.1:9222/json/version   # Chrome's JSON → tunnel + Chrome are up

비어 있음 / 연결 거부 → Windows Chrome 또는 역방향 터널이 아직 실행 중이지 않음을 의미합니다. 실행될 때까지 web_search가 실패합니다.


설정 (일회성)

cd dept-web-search-gateway
npm install                 # also runs `playwright install chromium`
cp .env.example .env       # then edit .env (see knobs below)

1) 공유 로그인 시드 (핵심)

디스플레이가 있는 머신에서(또는 xvfb-run -a 하에서) 한 번 실행:

npm run login
# or, for an internal portal:
LOGIN_START_URL=https://wiki.internal npm run login

실제 Chrome 창이 열립니다. 공유 서비스 계정(SSO / 2FA)으로 로그인하고, 검색 엔진/포털에 로그인되었는지 확인한 후 창을 닫습니다. 세션은 BROWSER_PROFILE_DIR(기본값 ./.profile)에 저장되며, 이후부터 헤드리스 게이트웨이에서 재사용됩니다.

서버가 헤드리스인가요? Windows PC에서 npm run login 단계를 수행한 다음, 위의 "헤드리스 Linux 서버 + 로그인용 Windows PC" 에 설명된 대로 모드 B(auth.json을 Linux에 복사) 또는 모드 C(CDP를 Linux에 SSH 터널링)를 선택하세요. SSO 세션이 만료되면 갱신: 모드 A/B → npm run login을 다시 실행(모드 B의 경우 auth.json도 다시 복사); 모드 C → Windows Chrome에서 다시 로그인하기만 하면 됩니다.

2) 게이트웨이 실행

npm start                   # dev (tsx)
# or production:
npm run build && npm run start:prod

다음과 같은 출력이 표시되어야 합니다:

[server] MCP gateway on http://0.0.0.0:8787/mcp  (engine=bing)
[server] profile=./.profile

클라이언트 온보딩 (동료에게 제공)

search.internal / 8787을 게이트웨이 호스트/포트로 바꾸세요. 모든 사람이 동일한 URL을 사용합니다.

Chatbox (≥1.14)

설정 → MCP → 서버 추가 → 원격 / URL 선택:

  • URL: http://search.internal:8787/mcp

  • (GATEWAY_TOKEN이 설정된 경우) 클라이언트가 지원하는 경우 헤더 Authorization: Bearer <TOKEN>을 추가합니다. 그렇지 않으면 네트워크 ACL로 보호합니다.

원클릭 딥 링크 (인트라넷 페이지에 추가):

chatbox://mcp/install?server=<base64 of {"name":"websearch","url":"http://search.internal:8787/mcp"}>

OpenCode — 세 가지 방식 모두

opencode.json(프로젝트) 또는 ~/.config/opencode/opencode.json(전역)에 추가:

{
  "mcp": {
    "websearch": {
      "type": "remote",
      "url": "http://search.internal:8787/mcp",
      "enabled": true
    }
  }
}
  • 로컬 opencode: 동일한 코드 조각, 호스트 = 127.0.0.1 또는 게이트웨이 호스트.

  • 서버 opencode: 프로세스가 서버에서 실행됨 → 게이트웨이의 내부 URL을 직접 가리킵니다(서버가 내부 네트워크를 통해 연결할 수 있어야 함).

  • vscode-remote opencode: 프로세스가 원격 호스트에서 실행됨 → 게이트웨이의 내부 URL을 가리킵니다(해당 호스트에서 연결 가능). 게이트웨이가 내부 네트워크에 있으므로 터널링이 필요하지 않습니다.

  • 확인: opencode mcp list.

Claude Code

claude mcp add --transport http websearch http://search.internal:8787/mcp
# with a token:
claude mcp add --transport http --header "Authorization: Bearer <TOKEN>" \
  websearch http://search.internal:8787/mcp

Cline / Cursor / 기타

원격 MCP를 지원하는 경우 동일한 URL을 가리키세요. stdio만 지원하는 경우 HTTP 게이트웨이를 호출하는 작은 로컬 심(20줄 래퍼)을 실행하세요. 여기에 포함되지는 않았지만 추가하는 것은 간단합니다.


노출된 도구

도구

인수

반환값

web_search

query (str, 필수), engine (bing|google|duck|custom, 선택 사항)

{title, url, snippet} 목록을 텍스트 + JSON으로 반환

read_webpage

url (str, 필수)

# title + 주요 텍스트 (≤20k 자), 로그인/SSO 처리됨

Chatbox/OpenCode/Claude Code의 에이전트는 최신 정보가 필요할 때 web_search를 호출하고, 특정 페이지를 읽기 위해 read_webpage를 호출합니다. 추가 연결이 필요하지 않습니다.


구성 설정 (.env)

변수

기본값

의미

HOST

0.0.0.0

바인드 주소. 127.0.0.1 = localhost 전용(+자동 DNS-리바인딩 보호)

ALLOWED_HOSTS

—

클라이언트가 사용하는 호스트 이름의 쉼표 목록(Host-헤더 검증 활성화). 0.0.0.0 바인딩 시 설정

PORT

8787

수신 포트

GATEWAY_TOKEN

—

설정된 경우 Authorization: Bearer <token> 필요. 비어 있음 = 인증 없음(네트워크 ACL만)

BROWSER_MODE

cdp

persistent / storagestate / cdp — 토폴로지 섹션 참조

CDP_ENDPOINT

http://127.0.0.1:9222

cdp 모드: 연결된 브라우저의 CDP URL (일반적으로 터널링된 포트)

STORAGE_STATE_FILE

./auth.json

storagestate 모드: Windows에서 내보낸 로그인 스냅샷, 여기에 복사됨

BROWSER_PROFILE_DIR

./.profile

persistent 모드: 공유 로그인을 보유한 Chrome 프로필

HEADLESS

true

false는 디버깅 전용

MAX_CONCURRENT_PAGES

4

동시성 제한 (Chrome 하나, 격리된 탭)

PAGE_TIMEOUT_MS

20000

페이지당 하드 타임아웃

SEARCH_ENGINE

bing

bing (튜닝된 추출기) / google / duck / custom

SEARCH_URL_TEMPLATE

—

{q} 플레이스홀더가 있는 사용자 정의 URL, 예: https://wiki.internal/search?q={q} (엔진 URL 재정의)

RESULT_COUNT

10

쿼리당 결과 수

SEARXNG_URL

—

선택적 공개 검색 대체(아웃바운드 인터넷 필요), 예: http://127.0.0.1:8080


사용자 정의 내부 포털 추출기 추가

src/tools.ts의 extractBing은 Bing의 DOM에 맞게 튜닝되었습니다. 내부 포털의 경우 extractPortal(page, count)를 추가하고 searchWithBrowser의 엔진 이름으로 선택하세요. 일반 extractGeneric은 알 수 없는 DOM에 대한 대체 수단으로 앵커 링크 + 주변 텍스트를 이미 반환합니다.


보안 및 운영 참고 사항

  • 바인드 및 노출: 게이트웨이를 내부 네트워크에 유지하는 것이 좋습니다. 0.0.0.0에 바인딩하는 경우 ALLOWED_HOSTS를 설정하고 방화벽/네트워크 ACL을 사용하거나 GATEWAY_TOKEN을 설정하거나 SSO 역방향 프록시 뒤에 두십시오.

  • 공유 프로필 = 공유 ID: 모든 검색은 공유 계정에 귀속됩니다. 부서 서비스 계정에는 적합합니다. 대상이 사용자별 감사 또는 할당량을 수행하는 경우 검토하십시오.

  • 세션 갱신: SSO가 만료되면 npm run login을 다시 실행하십시오. 알림 이메일을 보내는 주간 cron이나 로그인 장벽을 감지하는 상태 프로브(read_webpage가 알려진 로그인 필요 URL에서 로그인 페이지 텍스트를 반환)를 고려하십시오.

  • 동시성/확장: 격리된 탭이 있는 Chrome 하나는 소규모 부서를 처리합니다. 포화 상태가 되면 브라우저 풀(N개의 영구 컨텍스트)로 확장하십시오. withPage 결합 부분만 변경하면 됩니다.

  • Linux에서의 헤드리스 Chrome: --no-sandbox --disable-dev-shm-usage가 이미 설정되어 있습니다(컨테이너 친화적).


개발 및 테스트

  • 프로브는 scripts/에 있으며 ../dist/에서 가져오므로 먼저 빌드하십시오: npm run build.

    • scripts/probe-search.mjs "<query>" — 공유 브라우저를 직접 구동합니다(MCP 우회). CDP 연결 및 Bing 추출기를 검증합니다.

    • scripts/probe-mcp.mjs <url> "<query>" — 실행 중인 게이트웨이에 Streamable HTTP를 통해 연결합니다(실제 클라이언트 경로). 도구를 나열하고 web_search를 호출합니다. 먼저 게이트웨이를 시작하십시오: node --env-file=.env dist/server.js.

  • 개발 모드 (npm start → tsx): npm 11에서 tsx의 전이적 esbuild postinstall은 기본적으로 allow-scripts에 의해 차단됩니다. 한 번 승인(npm approve-scripts)하거나 모든 곳에서 컴파일된 경로를 사용하십시오: npm run build && node --env-file=.env dist/server.js.


상태

이는 검토 가능한 PoC / 스켈레톤입니다 — v2 MCP SDK API (@modelcontextprotocol/server 2.x, createMcpHandler / createMcpExpressApp / requireBearerAuth / toNodeHandler) 및 Playwright의 영구 컨텍스트 API에 대해 검증되었습니다. 프로덕션 배포 전에: 정확한 종속성 버전을 고정하고, 테스트를 추가하며, 신뢰할 수 있는 내부 네트워크를 넘어 노출할 경우 인증 계층(정적 토큰 대신 JWT / 인트로스펙션)을 강화하세요.

설계 컨텍스트(A/B/C 모드 토폴로지, OS 간 쿠키 암호화 문제, SearXNG 경계)는 위의 "Headless Linux 서버 + 로그인용 Windows PC" 섹션에 있습니다.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers