MCP Research Friend
About
Research tools, including a Sqlite-backed document stash
Details
- Author
- permacommons
- Categories
- Search, Knowledge Base, Other
Jump to
Setup
Install MCP Research Friend in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/permacommons/mcp-research-friend
Follow the installation instructions in the repository README, then restart your MCP client.
What can you do with Research Friend MCP?
- Fetch and extract web pages— Ask your assistant to retrieve a page’s main content as clean markdown usingfriendly_web_fetch.
- Search the web— Have your assistant run a web search via DuckDuckGo or Google withfriendly_searchand return titles, URLs, and snippets.
- Extract PDFs or paginate large pages— Usefriendly_web_extractto pull text from a PDF, paginate with offsets, or search for phrases within a document.
- Answer questions about a URL— Ask your assistant to fetch a page or PDF and have an LLM answer a specific question about it viafriendly_web_ask.
- Build and search a local document stash— Drop files into the inbox, process them withstash_process_inbox, then search across filenames and content usingstash_search.
- Query a stashed document with an LLM— Usestash_askto ask questions about a stored document without loading it into the main conversation.
A friendly helper for AI assistants that need to look things up on the web and manage a local research stash.
Research Friend is an MCP server that gives your AI tools the ability to fetch web pages and search the internet. It uses a real web browser behind the scenes, so it works even with modern websites that rely heavily on JavaScript. It also includes a local “stash” for storing documents, extracting text, and searching across your library.
To make use of all its features, you'll want an MCP client that supports prompts (common) and sampling (less common). We're building Research Friend alongsideChabeau, which supports both.
- Fetch web pageswith a real browser (including JS-heavy sites)
- Fetch PDFsand extract their text content
- Search the webvia DuckDuckGo or Google
- Maintain a local stashof documents for search, listing, and extraction
You'll needNode.jsversion 20 or newer installed on your computer.
Research Friend uses Playwright to control a web browser. After installing dependencies, you'll need to install the browser:
This downloads a copy of Chromium that Playwright will use. It's separate from any browsers you already have installed.
The server communicates over stdio (standard input/output), which is how MCP clients connect to it.
How you add Research Friend depends on which MCP client you're using. Here's a general example of what the configuration might look like:
[[mcp_servers]] id = "research-friend" command = "node" args = ["/path/to/mcp-research-friend/src"] transport = "stdio"
Replace/path/to/mcp-research-friendwith the actual path to this folder on your computer.
Fetches a web page and returns its content. By default, returns markdown with links preserved — ideal for LLMs. UsesReadabilityto extract the main content (stripping navigation, ads, etc.). For PDFs, pagination, or searching within content, usefriendly_web_extractinstead.
- url(required) - The web address to fetch
- outputFormat- Output format:markdown(default),text, orhtml
- waitMs- Extra time to wait after the page loads, in case content appears slowly
- timeoutMs- How long to wait before giving up (default: 15 seconds)
- maxChars- Maximum amount of content to return (default: 40,000 characters)
- includeHtml- Set totrueto also return the raw HTML alongside the content
- headless- Set tofalseto see the browser window (useful for debugging)
- url- The URL that was requested
- finalUrl- The URL after any redirects
- title- The page title
- content- The extracted content (in the requested format)
- html- Raw HTML (only ifincludeHtmlis true)
- meta- Page metadata (description, author, published time, etc.)
- fetchedAt- ISO timestamp of when the page was fetched
- truncated- Whether the content was truncated to fitmaxChars
Searches the web and returns a list of results.
- query(required) - What to search for
- engine- Which search engine to use (duckduckgoorgoogle)
- maxResults- How many results to return (default: 10, maximum: 50)
- timeoutMs- How long to wait before giving up (default: 15 seconds)
- headless- Set tofalseto see the browser window
- query- The search query that was used
- engine- Which search engine was used
- results- Array of results, each withtitle,url, andsnippet
- searchedAt- ISO timestamp of when the search was performed
- fallback_result_html- Raw HTML of the page (only included if no results were found)
- debug_info- Diagnostic information about the search attempt
CAPTCHA handling:If a CAPTCHA is detected while running in headless mode, the tool automatically retries with a visible browser window. This gives you a chance to solve the CAPTCHA manually. Thedebug_info.retriedfield indicates whether this fallback was used.
Extracts content from a URL. Auto-detects whether the URL points to a PDF or a web page and handles each appropriately.
- url(required) - The URL to fetch (PDF or web page)
- maxChars- Maximum amount of text to return (default: 40,000 characters)
- offset- Character position to start from (default: 0). Use this to paginate through large content.
- search- Search for a phrase and return matches with surrounding context instead of full content
- contextChars- Characters of context around each search match (default: 200)
- waitMs- Extra time to wait after page load for dynamic content (web pages only)
- timeoutMs- How long to wait before giving up (default: 15 seconds, web pages only)
- headless- Set tofalseto see the browser window (web pages only)
- url- The URL that was requested
- contentType- Eitherpdforhtml
- title- The page/document title
- author- The PDF author (PDFs only, if available)
- creationDate- When the PDF was created (PDFs only, if available)
- pageCount- Number of pages (PDFs only)
- totalChars- Total characters (use withoffsetto paginate)
- offset- The offset that was used
- content- The extracted text content
- fetchedAt- ISO timestamp
- truncated- Whether more content remains after this chunk
- url,contentType,title,totalChars,fetchedAt- Same as above
- search- The search phrase that was used
- matchCount- Number of matches found
- matches- Array of matches, each withposition,context,prefix, andsuffix
Fetches a URL (PDF or web page) and has an LLM answer questions about it. Auto-detects content type. The document is processed in a separate context, keeping your main conversation compact.
- url(required) - The URL to fetch (PDF or web page)
- ask(required) - Question or instruction for the LLM (summarize, extract info, answer questions, etc.)
- askMaxInputTokens- Maximum input tokens per LLM call (default: 150,000)
- askMaxOutputTokens- Maximum output tokens per LLM call (default: 4,096)
- askTimeout- Timeout in milliseconds (default: 300,000 = 5 minutes)
- askSplitAndSynthesize- For large documents: split into chunks, process each, then synthesize results (default: false). Warning: consumes many tokens.
- waitMs- Extra time to wait after page load for dynamic content (web pages only)
- timeoutMs- How long to wait before giving up (default: 15 seconds, web pages only)
- headless- Set tofalseto see the browser window (web pages only)
- url- The URL that was requested
- contentType- Eitherpdforhtml
- title- The page/document title
- totalChars- Total characters in the document
- ask- The instruction that was given
- answer- The LLM's response
- model- The model that generated the response
- chunksProcessed- Number of chunks processed (1 for small documents, more when usingaskSplitAndSynthesize)
- fetchedAt- ISO timestamp
Ask modeuses MCP sampling to have an LLM process the document with any instruction. This is useful for:
- Large documents that would overwhelm context
- Keeping token costs down on the main conversation
WhenaskSplitAndSynthesizeis enabled, documents exceedingaskMaxInputTokensare automatically split into overlapping chunks. Each chunk is processed separately, and the results are synthesized into a single coherent answer. The final response is provided in the same language as your request, regardless of the document's language.
The stash is a local, searchable library of documents. It supports PDFs, HTML files, and plaintext (Markdown/TXT). When you add a document, Research Friend stores the original file, extracts text (for PDFs/HTML), and saves metadata in a local database. Searches use ripgrep under the hood for fast, phrase-aware matching.
The stash lives under~/.research-friend/:
- inbox/- Drop files here to be processed
- store/- Organized document storage and extracted text
- stash.db- Metadata database
- PDF:.pdf(text extracted)
- HTML:.html,.htm(text extracted)
- Markdown:.md,.markdown(stored as plaintext)
- Text:.txt(stored as plaintext)
Open the stash inbox folder in your file manager for easier drag-and-drop.
- opened- Whether the folder open request was sent
- inboxPath- Absolute path to the inbox
- command- OS command used
- args- Command arguments used
Process files ininbox/, classify them into topics, extract text, and store results. For long documents, classification uses sampled sections (start/middle/end plus a few random chunks) to improve topic accuracy.
- processed- Array of filenames successfully processed
- errors- Any errors encountered
- documents- Array of created document records
Regenerate summaries, re-allocate topics, and update store metadata for stashed documents. Ifidsis omitted or empty, all documents are reindexed.
- ids- Document IDs to reindex (optional)
- reindexed- Document IDs reindexed
- errors- Any errors encountered
- documents- Array of updated document records
- topic- Filter to a topic (optional)
- limit- Max results (default: 50)
- offset- Pagination offset (default: 0)
- type-allortopic
- totalDocuments- Total documents (only whentypeisall)
- count- Results returned after pagination
- offset- Pagination offset used
- limit- Pagination limit used
- topics- Summary of known topics and doc counts
- documents- Document list with metadata (includesisPrimarywhen listing a topic)
Search filenames and content across the stash. All search terms must be present (AND logic). Filename matches are listed first. Use quotes for exact phrases.
- query(required) - Search terms. Use quotes for phrases:"sparkling wine"
- topic- Filter to a topic (optional)
- ids- Filter to specific document IDs (optional)
- limit- Max documents to return (default: 20)
- offset- Pagination offset (default: 0)
- maxMatchesPerDoc- Max matches per document (default: 50)
- context- Lines of context around each match (default: 1, max: 5). Controls both how close terms must appear to match AND how much surrounding text is returned.
- totalMatches- Total documents matched before pagination
- count- Results returned after pagination
- results- Array of documents, each with:
- id,filename,fileType,summary,charCount,createdAt
- matchType-filename,content, orfilename+content
- matches- Array of{ line, context }for each match location
Use thelinevalues withstash_extractto jump directly to match locations.
Extract content from a stashed document for reading. Use line numbers fromstash_searchresults to jump directly to matches.
- id(required) - Document ID fromstash_list/stash_search
- maxChars- Maximum amount of text to return (default: 40,000 characters)
- offset- Character position to start from (mutually exclusive withline)
- line- Line number to start from (mutually exclusive withoffset)
- id,filename,fileType,summary- Document metadata
- totalChars- Total characters in the document
- offset- Character offset (included when usinglinefor reference)
- line- Line number (only whenlineparameter was used)
- content- The extracted text content
- truncated- Whether more content remains after this chunk
Have an LLM answer questions about a stashed document. The document is processed in a separate context, keeping your main conversation compact.
- id(required) - Document ID fromstash_list/stash_search
- ask(required) - Question or instruction for the LLM
- askMaxInputTokens- Maximum input tokens per LLM call (default: 150,000)
- askMaxOutputTokens- Maximum output tokens per LLM call (default: 4,096)
- askTimeout- Timeout in milliseconds (default: 300,000 = 5 minutes)
- askSplitAndSynthesize- For large documents: split into chunks, process each, then synthesize results (default: false)
- id,filename,fileType,summary- Document metadata
- totalChars- Total characters in the document
- ask- The instruction that was given
- answer- The LLM's response
- model- The model that generated the response
- chunksProcessed- Number of chunks processed
- Drop files into~/.research-friend/inbox/
- Runstash_process_inbox
- Usestash_listto browse topics
- Usestash_searchto find relevant docs
- Usestash_extractto read a specific doc, orstash_askto ask questions about it
"Browser closed unexpectedly" or similar errors
On Linux, you might also need system dependencies:
Make sure you're using Node.js 20 or newer:
If your version is older, visitnodejs.orgto download a newer one.
Search global news using natural language. Webz.io News Search API returns the most relevant articles and content, with filters for source, country, language, date, sentiment, and category.
Fetch, convert, and search AWS documentation pages, with recommendations for related content.
Search campgrounds around the world on campertunity, check availability, and provide booking links.
The Ferryhopper MCP Server exposes ferry routes, schedules and booking redirects so an AI assistant can discover connections across Europe and the Mediterranean and send users to Ferryhopper to complete bookings.
All-in-One SEO & Web Intelligence Toolkit API from FetchSERP.
MCP server that provides read-only access to HyperKitty, the web-based email archive component of Mailman 3.
At Sunrise Apps, we believe AI agents should be limitless, especially when it comes to visual data. We created ImageSorcery to bridge the critical gap in AI's ability to interact with and manipulate images directly, all while upholding the highest standards of privacy and security.
Just Domain is the domain registrar for businesses built with AI. Its remote MCP server checks availability and returns first-year and renewal pricing, plus a link to register on justdomain.ai, with DNS and WHOIS privacy in the same place. No account, no API key, read only. Endpoint: https://mcp.justdomain.ai/
Semantic search over 9 free-license stock photo sources. Hosted remote server with OAuth — no API key to paste.
SerpApi MCP Server for Google and other search engine results
Access to your site's SEO data — crawl results, Search Console and Analytics, so your assistant can tell you what's broken, what's ranking, and what to fix next.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




