MCP Research Friend Server

chính thức

Công cụ nghiên cứu, bao gồm kho tài liệu hỗ trợ bởi Sqlite

Tài liệu

Research Friend

Một trợ lý thân thiện dành cho các công cụ AI cần tra cứu thông tin trên web và quản lý kho lưu trữ nghiên cứu cục bộ.

Research Friend là một máy chủ MCP cung cấp cho các công cụ AI của bạn khả năng tải trang web và tìm kiếm trên internet. Nó sử dụng một trình duyệt web thực sự ở phía sau, vì vậy nó hoạt động ngay cả với các trang web hiện đại phụ thuộc nhiều vào JavaScript. Nó cũng bao gồm một "kho lưu trữ" cục bộ để lưu trữ tài liệu, trích xuất văn bản và tìm kiếm trong thư viện của bạn.

Để tận dụng tất cả các tính năng của nó, bạn sẽ cần một máy khách MCP hỗ trợ prompt (phổ biến) và sampling (ít phổ biến hơn). Chúng tôi đang xây dựng Research Friend cùng với Chabeau, hỗ trợ cả hai.

Nó có thể làm gì?

  • Tải trang web bằng trình duyệt thực (bao gồm các trang web nặng về JS)
  • Tải PDF và trích xuất nội dung văn bản của chúng
  • Tìm kiếm trên web qua DuckDuckGo hoặc Google
  • Duy trì kho lưu trữ cục bộ tài liệu để tìm kiếm, liệt kê và trích xuất

Bắt đầu

Bạn sẽ cần Node.js phiên bản 20 trở lên được cài đặt trên máy tính của bạn.

1. Cài đặt các phụ thuộc

Mở một terminal trong thư mục này và chạy:

npm install

2. Cài đặt hỗ trợ trình duyệt

Research Friend sử dụng Playwright để điều khiển một trình duyệt web. Sau khi cài đặt các phụ thuộc, bạn sẽ cần cài đặt trình duyệt:

npx playwright install chromium

Thao tác này tải xuống một bản sao của Chromium mà Playwright sẽ sử dụng. Nó tách biệt với bất kỳ trình duyệt nào bạn đã cài đặt.

3. Khởi động máy chủ

node src/index.js

Máy chủ giao tiếp qua stdio (đầu vào/đầu ra tiêu chuẩn), đó là cách các máy khách MCP kết nối với nó.

Thêm vào máy khách MCP của bạn

Cách bạn thêm Research Friend phụ thuộc vào máy khách MCP bạn đang sử dụng. Dưới đây là một ví dụ chung về cấu hình có thể trông như thế nào:

[[mcp_servers]]
id = "research-friend"
command = "node"
args = ["/path/to/mcp-research-friend/src"]
transport = "stdio"

Thay thế /path/to/mcp-research-friend bằng đường dẫn thực tế đến thư mục này trên máy tính của bạn.

Công cụ

Công cụ web

friendly_web_fetch

Tải một trang web và trả về nội dung của nó. Theo mặc định, trả về markdown với các liên kết được bảo toàn — lý tưởng cho các LLM. Sử dụng Readability để trích xuất nội dung chính (loại bỏ điều hướng, quảng cáo, v.v.). Đối với PDF, phân trang hoặc tìm kiếm trong nội dung, hãy sử dụng friendly_web_extract thay thế.

Tham số:

  • url (bắt buộc) - Địa chỉ web cần tải
  • outputFormat - Định dạng đầu ra: markdown (mặc định), text, hoặc html
  • waitMs - Thời gian chờ thêm sau khi trang tải, trong trường hợp nội dung xuất hiện chậm
  • timeoutMs - Thời gian chờ trước khi bỏ cuộc (mặc định: 15 giây)
  • maxChars - Lượng nội dung tối đa cần trả về (mặc định: 40.000 ký tự)
  • includeHtml - Đặt thành true để cũng trả về HTML thô cùng với nội dung
  • headless - Đặt thành false để xem cửa sổ trình duyệt (hữu ích cho việc gỡ lỗi)

Trả về:

  • url - URL đã được yêu cầu
  • finalUrl - URL sau bất kỳ chuyển hướng nào
  • title - Tiêu đề trang
  • content - Nội dung đã trích xuất (theo định dạng được yêu cầu)
  • html - HTML thô (chỉ khi includeHtml là true)
  • meta - Siêu dữ liệu trang (mô tả, tác giả, thời gian xuất bản, v.v.)
  • fetchedAt - Dấu thời gian ISO khi trang được tải
  • truncated - Liệu nội dung có bị cắt bớt để phù hợp với maxChars hay không

friendly_search

Tìm kiếm trên web và trả về danh sách kết quả.

Tham số:

  • query (bắt buộc) - Nội dung cần tìm kiếm
  • engine - Sử dụng công cụ tìm kiếm nào (duckduckgo hoặc google)
  • maxResults - Số lượng kết quả cần trả về (mặc định: 10, tối đa: 50)
  • timeoutMs - Thời gian chờ trước khi bỏ cuộc (mặc định: 15 giây)
  • headless - Đặt thành false để xem cửa sổ trình duyệt

Trả về:

  • query - Truy vấn tìm kiếm đã được sử dụng
  • engine - Công cụ tìm kiếm nào đã được sử dụng
  • results - Mảng kết quả, mỗi kết quả có title, url, và snippet
  • searchedAt - Dấu thời gian ISO khi tìm kiếm được thực hiện
  • fallback_result_html - HTML thô của trang (chỉ được bao gồm nếu không tìm thấy kết quả)
  • debug_info - Thông tin chẩn đoán về nỗ lực tìm kiếm

Xử lý CAPTCHA: Nếu CAPTCHA được phát hiện khi đang chạy ở chế độ headless, công cụ sẽ tự động thử lại với cửa sổ trình duyệt hiển thị. Điều này cho bạn cơ hội giải CAPTCHA thủ công. Trường debug_info.retried cho biết liệu phương án dự phòng này có được sử dụng hay không.

friendly_web_extract

Trích xuất nội dung từ một URL. Tự động phát hiện xem URL trỏ đến PDF hay trang web và xử lý từng loại một cách phù hợp.

Tham số:

  • url (bắt buộc) - URL cần tải (PDF hoặc trang web)
  • maxChars - Lượng văn bản tối đa cần trả về (mặc định: 40.000 ký tự)
  • offset - Vị trí ký tự bắt đầu (mặc định: 0). Sử dụng để phân trang qua nội dung lớn.
  • search - Tìm kiếm một cụm từ và trả về các kết quả khớp với ngữ cảnh xung quanh thay vì toàn bộ nội dung
  • contextChars - Số ký tự ngữ cảnh xung quanh mỗi kết quả khớp tìm kiếm (mặc định: 200)
  • waitMs - Thời gian chờ thêm sau khi tải trang cho nội dung động (chỉ trang web)
  • timeoutMs - Thời gian chờ trước khi bỏ cuộc (mặc định: 15 giây, chỉ trang web)
  • headless - Đặt thành false để xem cửa sổ trình duyệt (chỉ trang web)

Trả về (chế độ bình thường):

  • url - URL đã được yêu cầu
  • contentType - Hoặc pdf hoặc html
  • title - Tiêu đề trang/tài liệu
  • author - Tác giả PDF (chỉ PDF, nếu có)
  • creationDate - Thời điểm PDF được tạo (chỉ PDF, nếu có)
  • pageCount - Số trang (chỉ PDF)
  • totalChars - Tổng số ký tự (sử dụng với offset để phân trang)
  • offset - Độ lệch đã được sử dụng
  • content - Nội dung văn bản đã trích xuất
  • fetchedAt - Dấu thời gian ISO
  • truncated - Liệu còn nội dung nào sau đoạn này không

Trả về (chế độ tìm kiếm):

  • url, contentType, title, totalChars, fetchedAt - Giống như trên
  • search - Cụm từ tìm kiếm đã được sử dụng
  • matchCount - Số lượng kết quả khớp được tìm thấy
  • matches - Mảng các kết quả khớp, mỗi kết quả có position, context, prefix, và suffix

friendly_web_ask

Tải một URL (PDF hoặc trang web) và yêu cầu LLM trả lời các câu hỏi về nó. Tự động phát hiện loại nội dung. Tài liệu được xử lý trong một ngữ cảnh riêng biệt, giữ cho cuộc trò chuyện chính của bạn gọn gàng.

Tham số:

  • url (bắt buộc) - URL cần tải (PDF hoặc trang web)
  • ask (bắt buộc) - Câu hỏi hoặc hướng dẫn cho LLM (tóm tắt, trích xuất thông tin, trả lời câu hỏi, v.v.)
  • askMaxInputTokens - Token đầu vào tối đa cho mỗi lần gọi LLM (mặc định: 150.000)
  • askMaxOutputTokens - Token đầu ra tối đa cho mỗi lần gọi LLM (mặc định: 4.096)
  • askTimeout - Thời gian chờ tính bằng mili giây (mặc định: 300.000 = 5 phút)
  • askSplitAndSynthesize - Đối với tài liệu lớn: chia thành các đoạn, xử lý từng đoạn, sau đó tổng hợp kết quả (mặc định: false). Cảnh báo: tiêu tốn nhiều token.
  • waitMs - Thời gian chờ thêm sau khi tải trang cho nội dung động (chỉ trang web)
  • timeoutMs - Thời gian chờ trước khi bỏ cuộc (mặc định: 15 giây, chỉ trang web)
  • headless - Đặt thành false để xem cửa sổ trình duyệt (chỉ trang web)

Trả về:

  • url - URL đã được yêu cầu
  • contentType - Hoặc pdf hoặc html
  • title - Tiêu đề trang/tài liệu
  • totalChars - Tổng số ký tự trong tài liệu
  • ask - Hướng dẫn đã được đưa ra
  • answer - Phản hồi của LLM
  • model - Mô hình đã tạo ra phản hồi
  • chunksProcessed - Số đoạn đã xử lý (1 đối với tài liệu nhỏ, nhiều hơn khi sử dụng askSplitAndSynthesize)
  • fetchedAt - Dấu thời gian ISO

Chế độ hỏi sử dụng MCP sampling để LLM xử lý tài liệu với bất kỳ hướng dẫn nào. Điều này hữu ích cho:

  • Các tài liệu lớn có thể làm quá tải ngữ cảnh
  • Giảm chi phí token cho cuộc trò chuyện chính

Khi askSplitAndSynthesize được bật, các tài liệu vượt quá askMaxInputTokens sẽ tự động được chia thành các đoạn chồng lấp. Mỗi đoạn được xử lý riêng biệt và kết quả được tổng hợp thành một câu trả lời mạch lạc duy nhất. Phản hồi cuối cùng được cung cấp bằng cùng ngôn ngữ với yêu cầu của bạn, bất kể ngôn ngữ của tài liệu.

Kho lưu trữ tài liệu

Kho lưu trữ là một thư viện tài liệu cục bộ, có thể tìm kiếm. Nó hỗ trợ PDF, tệp HTML và văn bản thuần túy (Markdown/TXT). Khi bạn thêm một tài liệu, Research Friend lưu trữ tệp gốc, trích xuất văn bản (đối với PDF/HTML) và lưu siêu dữ liệu trong cơ sở dữ liệu cục bộ. Tìm kiếm sử dụng ripgrep bên dưới để khớp cụm từ nhanh chóng, nhận biết ngữ cảnh.

Vị trí kho lưu trữ

Kho lưu trữ nằm trong ~/.research-friend/:

  • inbox/ - Thả tệp vào đây để được xử lý
  • store/ - Lưu trữ tài liệu có tổ chức và văn bản đã trích xuất
  • stash.db - Cơ sở dữ liệu siêu dữ liệu

Loại tệp được hỗ trợ

  • PDF: .pdf (văn bản được trích xuất)
  • HTML: .html, .htm (văn bản được trích xuất)
  • Markdown: .md, .markdown (lưu trữ dưới dạng văn bản thuần túy)
  • Văn bản: .txt (lưu trữ dưới dạng văn bản thuần túy)

Công cụ kho lưu trữ

stash_open_inbox

Mở thư mục hộp thư đến của kho lưu trữ trong trình quản lý tệp của bạn để dễ dàng kéo thả.

Trả về:

  • opened - Liệu yêu cầu mở thư mục đã được gửi hay chưa
  • inboxPath - Đường dẫn tuyệt đối đến hộp thư đến
  • command - Lệnh hệ điều hành được sử dụng
  • args - Các đối số lệnh được sử dụng

stash_process_inbox

Xử lý các tệp trong inbox/, phân loại chúng thành các chủ đề, trích xuất văn bản và lưu trữ kết quả. Đối với các tài liệu dài, việc phân loại sử dụng các phần được lấy mẫu (đầu/giữa/cuối cộng với một vài đoạn ngẫu nhiên) để cải thiện độ chính xác của chủ đề.

Trả về:

  • processed - Mảng tên tệp đã được xử lý thành công
  • errors - Bất kỳ lỗi nào gặp phải
  • documents - Mảng các bản ghi tài liệu đã tạo

reindex_stash

Tạo lại tóm tắt, phân bổ lại chủ đề và cập nhật siêu dữ liệu lưu trữ cho các tài liệu trong kho. Nếu ids bị bỏ qua hoặc để trống, tất cả tài liệu sẽ được lập chỉ mục lại.

Tham số:

  • ids - ID tài liệu cần lập chỉ mục lại (tùy chọn)

Trả về:

  • reindexed - ID tài liệu đã được lập chỉ mục lại
  • errors - Bất kỳ lỗi nào gặp phải
  • documents - Mảng các bản ghi tài liệu đã cập nhật

stash_list

Liệt kê các tài liệu trong kho lưu trữ.

Tham số:

  • topic - Lọc theo chủ đề (tùy chọn)
  • limit - Kết quả tối đa (mặc định: 50)
  • offset - Độ lệch phân trang (mặc định: 0)

Trả về:

  • type - all hoặc topic
  • totalDocuments - Tổng số tài liệu (chỉ khi typeall)
  • count - Kết quả trả về sau khi phân trang
  • offset - Độ lệch phân trang đã sử dụng
  • limit - Giới hạn phân trang đã sử dụng
  • topics - Tóm tắt các chủ đề đã biết và số lượng tài liệu
  • documents - Danh sách tài liệu với siêu dữ liệu (bao gồm isPrimary khi liệt kê một chủ đề)

stash_search

Tìm kiếm tên tệp và nội dung trong toàn bộ kho lưu trữ. Tất cả các thuật ngữ tìm kiếm phải có mặt (logic AND). Các kết quả khớp tên tệp được liệt kê trước. Sử dụng dấu ngoặc kép cho các cụm từ chính xác.

Tham số:

  • query (bắt buộc) - Thuật ngữ tìm kiếm. Sử dụng dấu ngoặc kép cho các cụm từ: "sparkling wine"
  • topic - Lọc theo chủ đề (tùy chọn)
  • ids - Lọc theo ID tài liệu cụ thể (tùy chọn)
  • limit - Số lượng tài liệu tối đa cần trả về (mặc định: 20)
  • offset - Độ lệch phân trang (mặc định: 0)
  • maxMatchesPerDoc - Số lượng kết quả khớp tối đa trên mỗi tài liệu (mặc định: 50)
  • context - Số dòng ngữ cảnh xung quanh mỗi kết quả khớp (mặc định: 1, tối đa: 5). Kiểm soát cả mức độ gần nhau của các thuật ngữ để khớp VÀ lượng văn bản xung quanh được trả về. Trả về:
  • totalMatches - Tổng số tài liệu khớp trước khi phân trang
  • count - Kết quả trả về sau khi phân trang
  • results - Mảng các tài liệu, mỗi tài liệu có:
    • id, filename, fileType, summary, charCount, createdAt
    • matchType - filename, content, hoặc filename+content
    • matches - Mảng { line, context } cho mỗi vị trí khớp

Sử dụng các giá trị line với stash_extract để nhảy trực tiếp đến các vị trí khớp.

stash_extract

Trích xuất nội dung từ một tài liệu đã lưu trữ để đọc. Sử dụng số dòng từ kết quả stash_search để nhảy trực tiếp đến các vị trí khớp.

Tham số:

  • id (bắt buộc) - ID tài liệu từ stash_list/stash_search
  • maxChars - Lượng văn bản tối đa trả về (mặc định: 40.000 ký tự)
  • offset - Vị trí ký tự bắt đầu (loại trừ lẫn nhau với line)
  • line - Số dòng bắt đầu (loại trừ lẫn nhau với offset)

Trả về:

  • id, filename, fileType, summary - Siêu dữ liệu tài liệu
  • totalChars - Tổng số ký tự trong tài liệu
  • offset - Độ lệch ký tự (được bao gồm khi sử dụng line để tham chiếu)
  • line - Số dòng (chỉ khi tham số line được sử dụng)
  • content - Nội dung văn bản được trích xuất
  • truncated - Liệu còn nội dung nào sau đoạn này không

stash_ask

Yêu cầu LLM trả lời câu hỏi về một tài liệu đã lưu trữ. Tài liệu được xử lý trong một ngữ cảnh riêng biệt, giữ cho cuộc trò chuyện chính của bạn gọn gàng.

Tham số:

  • id (bắt buộc) - ID tài liệu từ stash_list/stash_search
  • ask (bắt buộc) - Câu hỏi hoặc hướng dẫn cho LLM
  • askMaxInputTokens - Token đầu vào tối đa cho mỗi lần gọi LLM (mặc định: 150.000)
  • askMaxOutputTokens - Token đầu ra tối đa cho mỗi lần gọi LLM (mặc định: 4.096)
  • askTimeout - Thời gian chờ tính bằng mili giây (mặc định: 300.000 = 5 phút)
  • askSplitAndSynthesize - Đối với tài liệu lớn: chia thành các đoạn, xử lý từng đoạn, sau đó tổng hợp kết quả (mặc định: false)

Trả về:

  • id, filename, fileType, summary - Siêu dữ liệu tài liệu
  • totalChars - Tổng số ký tự trong tài liệu
  • ask - Hướng dẫn đã được đưa ra
  • answer - Phản hồi của LLM
  • model - Mô hình đã tạo ra phản hồi
  • chunksProcessed - Số đoạn đã xử lý

Quy trình điển hình

  1. Thả tệp vào ~/.research-friend/inbox/
  2. Chạy stash_process_inbox
  3. Sử dụng stash_list để duyệt các chủ đề
  4. Sử dụng stash_search để tìm tài liệu liên quan
  5. Sử dụng stash_extract để đọc một tài liệu cụ thể, hoặc stash_ask để đặt câu hỏi về tài liệu đó

Khắc phục sự cố

"Trình duyệt đóng bất ngờ" hoặc các lỗi tương tự

Thử cài đặt lại trình duyệt:

npx playwright install chromium --force

Trên Linux, bạn cũng có thể cần các phụ thuộc hệ thống:

npx playwright install-deps chromium

Máy chủ không khởi động

Đảm bảo bạn đang sử dụng Node.js 20 trở lên:

node --version

Nếu phiên bản của bạn cũ hơn, hãy truy cập nodejs.org để tải xuống phiên bản mới hơn.

Giấy phép

MIT