markdown-for-agents-mcp
markdown-for-agents-mcp
전체 JavaScript 렌더링을 통해 URL을 가져와 AI 에이전트를 위한 깔끔하고 토큰 효율적인 마크다운으로 변환하는 MCP(Model Context Protocol) 서버입니다.
대부분의 MCP 가져오기 도구는 일반 HTTP를 사용하므로 JavaScript를 실행하지 않고 서버가 보내는 내용만 확인합니다. 정적 사이트에는 효과적이지만, React, Vue, Angular, SPA 및 데이터를 동적으로 로드하는 모든 페이지에서는 내용이 비어 있거나 깨진 상태로 반환됩니다. 이 서버는 Playwright를 통해 실제 Chromium 브라우저를 실행하므로, 추출 전에 전체 페이지를 렌더링하여 사람이 보는 것과 동일한 콘텐츠를 가져옵니다.
Playwright와 markdown-for-agents 라이브러리로 구동됩니다. 광고, 탐색 메뉴, 상용구(boilerplate)를 제거하여 원시 HTML 대비 최대 80% 적은 토큰을 제공합니다.
왜 Playwright인가?
기능 | 일반 HTTP 가져오기 도구 | markdown-for-agents-mcp |
정적 HTML 페이지 | ✅ | ✅ |
React / Vue / Angular 앱 | ❌ | ✅ |
JavaScript 렌더링 콘텐츠 | ❌ | ✅ |
단일 페이지 앱 경로 | ❌ | ✅ |
지연 로딩 / 무한 스크롤 | ❌ | ✅ |
원시 HTML 대비 토큰 효율성 | 보통 | 최대 80% 감소 |
봇 탐지 회피 | 없음 | UA 회전, 웹드라이버 스푸핑 |
토큰 감소 예시: 일반적인 뉴스 기사 페이지는 약 150KB의 원시 HTML(약 40,000 토큰)입니다. Playwright 렌더링, DOM 정리 및 마크다운 변환 후 동일한 기사는 약 2,000 토큰이 되어 95% 감소합니다.
목차
기능
JavaScript 렌더링 — Playwright 기반 Chromium이 React, Vue, Angular 및 JS가 많이 사용되는 모든 페이지를 추출 전에 렌더링합니다.
구조화된 출력 — 도구는 텍스트 응답과 함께 MCP SDK 1.11+와 호환되는 타입이 지정된
structuredContent(url, title, markdown, fetchedAt, contentSize)를 반환합니다.스마트 콘텐츠 추출 — 메인 콘텐츠 블록(
main>article>#content>body)을 점수화하여 선택하고, 사이드바, 탐색 메뉴, 광고를 자동으로 제거합니다.토큰 효율성 — LLM에 적합한 압축된 마크다운을 생성하며, 벤치마크 결과 원시 HTML 대비 최대 80% 적은 토큰을 보여줍니다.
웹 검색 — DuckDuckGo 검색 및 상위 결과에 대한 선택적 가져오기 및 변환 기능을 제공합니다.
LRU 캐시 — 15분 TTL이 적용된 50MB 메모리 내 캐시로 중복 가져오기를 방지합니다.
도메인 필터링 — 추적기/소셜 도메인에 대한 내장 차단 목록; 요청별 허용/차단 목록 및 서버 수준 허용 목록 모드를 지원합니다.
일괄 가져오기 — 구성 가능한 병렬 처리 기능을 갖춘 동시 다중 URL 가져오기.
HTTP 서버 모드 — HTTP 서버로 실행(
--http [port]또는HTTP_PORT환경 변수)하며 선택적으로 Bearer 토큰 인증을 지원합니다.프록시 지원 —
PLAYWRIGHT_PROXY를 전달하여 Playwright 트래픽을 프록시를 통해 라우팅합니다.상태 모니터링 —
health_check도구가 캐시 및 가져오기 지표를 노출합니다.제로 구성 — 첫 실행 시 Chromium이 자동으로 설치됩니다.
설치
npm install -g markdown-for-agents-mcpChromium은 postinstall 스크립트를 통해 자동으로 다운로드됩니다. 실패할 경우 문제 해결을 참조하세요.
전역 설치 없이 npx를 사용하여 실행할 수도 있습니다:
npx markdown-for-agents-mcpMCP 클라이언트 설정
MCP 클라이언트 구성에 서버를 추가하세요.
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) 또는 %APPDATA%\Claude\claude_desktop_config.json(Windows)을 편집하세요:
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}VS Code (Copilot / Continue)
관련 MCP 확장 키 아래의 작업 공간 또는 사용자 settings.json에 추가하세요. 예:
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp"
}
}
}Cursor / Windsurf / Zed
MCP 사양을 구현하는 모든 클라이언트는 이 서버를 사용할 수 있습니다. 명령 진입점은 markdown-mcp(전역 설치 후 PATH에서 사용 가능) 또는 로컬 빌드의 경우 dist/index.js의 전체 경로입니다.
환경 변수 재정의 사용
{
"mcpServers": {
"markdown": {
"command": "markdown-mcp",
"env": {
"FETCH_TIMEOUT_MS": "60000",
"LOG_LEVEL": "DEBUG"
}
}
}
}HTTP 서버 모드
stdio 대신 서버를 표준 HTTP 엔드포인트로 실행할 수 있습니다. 이는 공유 배포, Docker 또는 Streamable HTTP 전송을 선호하는 클라이언트에 유용합니다:
# Start on port 3456
markdown-mcp --http 3456
# Or use the env var
HTTP_PORT=3456 markdown-mcp모든 MCP 트래픽은 POST|GET|DELETE /mcp에서 처리됩니다. Bearer 토큰을 요구하려면 MCP_AUTH_TOKEN을 설정하세요:
MCP_AUTH_TOKEN=mysecrettoken HTTP_PORT=3456 markdown-mcp클라이언트는 모든 요청에 Authorization: Bearer mysecrettoken을 전달해야 합니다.
사용 가능한 도구
fetch_url
전체 JavaScript 렌더링을 통해 단일 URL을 가져와 깔끔한 마크다운을 반환합니다.
인수:
이름 | 타입 | 필수 | 설명 |
| string | 예 | 가져오고 변환할 URL |
| number | 아니오 | 요청 시간 제한(ms) ( |
예시:
fetch_url(url="https://example.com/blog/post")텍스트 출력 (항상 존재, 하위 호환성 유지):
# Blog Post Title
Source: https://example.com/blog/post
This is the main content of the article, stripped of navigation, ads, and boilerplate.
## Related Section
More content here...
---
*Converted by markdown-for-agents-mcp*구조화된 출력 (MCP SDK 1.11+ 클라이언트에서 structuredContent를 통해 사용 가능):
{
"url": "https://example.com/blog/post",
"title": "Blog Post Title",
"markdown": "# Blog Post Title\n\nSource: ...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2048
}fetch_urls
여러 URL을 동시에 가져와 URL당 하나의 섹션으로 결합된 마크다운을 반환합니다.
인수:
이름 | 타입 | 필수 | 설명 |
| string[] | 예 | 가져올 URL들 |
| number | 아니오 | 요청당 시간 제한(ms) |
예시:
fetch_urls(urls=[
"https://example.com/post1",
"https://example.com/post2"
])텍스트 출력:
# Post 1 Title
Source: https://example.com/post1
...
---
# Post 2 Title
Source: https://example.com/post2
...
---구조화된 출력 (structuredContent를 통해):
{
"results": [
{
"url": "https://example.com/post1",
"title": "Post 1 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 1820,
"success": true
},
{
"url": "https://example.com/post2",
"title": "Post 2 Title",
"markdown": "...",
"fetchedAt": "2026-04-06T17:00:00.000Z",
"contentSize": 2104,
"success": true
}
],
"summary": { "total": 2, "succeeded": 2, "failed": 0 }
}병렬 처리는 MAX_CONCURRENT_FETCHES(기본값: 5)에 의해 제어됩니다.
web_search
DuckDuckGo를 검색하고 선택적으로 상위 결과를 마크다운으로 가져옵니다. 봇 탐지를 피하기 위해 일반 HTTP 엔드포인트를 사용하며, 검색 자체에는 Playwright를 사용하지 않습니다.
인수:
이름 | 타입 | 필수 | 설명 |
| string | 예 | 검색 쿼리 |
| number | 아니오 | 반환할 최대 결과 수 (기본값: 10) |
| string[] | 아니오 | 이 도메인의 결과만 포함 |
| string[] | 아니오 | 이 도메인의 결과 제외 |
| boolean | 아니오 | 상위 결과 페이지를 가져와 마크다운으로 변환 |
| number | 아니오 | 요청 시간 제한(ms) |
예시 — 검색만:
web_search(
query="typescript tutorials",
maxResults=5,
allowedDomains=["typescriptlang.org", "github.com"]
)예시 — 검색 및 가져오기:
web_search(
query="react hooks guide",
fetchResults=true,
maxResults=3
)텍스트 출력:
# Web Search Results
## Query: typescript tutorials
**Found 5 results in 1234ms**
### Results:
1. [TypeScript Handbook](https://www.typescriptlang.org/docs/)
The TypeScript Handbook provides comprehensive documentation...
2. [Best TypeScript Tutorials](https://github.com/danistefanovic/build-your-own-typescript)
Learn TypeScript by building your own compiler...구조화된 출력 (structuredContent를 통해):
{
"query": "typescript tutorials",
"results": [
{ "title": "TypeScript Handbook", "url": "https://www.typescriptlang.org/docs/", "snippet": "...", "domain": "typescriptlang.org" }
],
"fetchedContent": [
{ "url": "https://www.typescriptlang.org/docs/", "markdown": "..." }
],
"durationMs": 1234
}참고:
allowedDomains및blockedDomains인수는 검색 결과 필터링에만 적용됩니다. 결과가 이후에 가져와질 때는 서버 수준의BLOCKLIST_DOMAINS/USE_ALLOWLIST_MODE설정이 여전히 적용됩니다.
download_file
URL에서 바이너리 파일(PDF, 이미지, ZIP 등)을 다운로드하여 로컬 경로에 저장합니다. 일반 HTTP 클라이언트를 사용하며 Playwright는 필요하지 않습니다. SSRF 보호 및 도메인 차단 목록이 적용됩니다.
인수:
이름 | 타입 | 필수 | 설명 |
| string | 예 | 다운로드할 파일의 URL |
| string | 예 | 파일을 저장할 절대 로컬 경로 (상위 디렉토리가 존재해야 함) |
예시:
download_file(
url="https://example.com/report.pdf",
outputPath="/tmp/report.pdf"
)출력:
{
"savedPath": "/tmp/report.pdf",
"sizeBytes": 204800,
"mimeType": "application/pdf",
"filename": "report.pdf"
}참고:
/download/...와 같은 경로를 가진 URL은fetch_url에서 차단되더라도 이 도구에서는 허용됩니다(바이너리 다운로드 체인 방지). HTML 페이지에는fetch_url을 사용하세요.download_file은text/html응답을 거부합니다.
health_check
현재 서버 상태, 캐시 지표 및 가져오기 통계를 반환합니다. 모니터링 및 디버깅에 유용합니다.
인수: 없음
출력 예시:
{
"status": "healthy",
"cache": {
"hits": 47,
"misses": 15,
"currentSize": 12,
"totalBytes": 4194304,
"maxBytes": 52428800
},
"metrics": {
"totalFetches": 62,
"successCount": 59,
"errorCount": 3,
"avgDuration": 1840,
"cacheUtilization": 76
}
}CLI 사용법
MCP 프로토콜 외부에서 사용할 수 있는 독립형 CLI(markdown-cli)가 포함되어 있습니다.
단일 URL
markdown-cli https://example.com다중 URL (일괄 모드)
markdown-cli -b https://example.com https://example.org https://example.net파일로 저장
markdown-cli https://example.com/article > article.md바이너리 파일 다운로드
markdown-cli -d -o /tmp/report.pdf https://example.com/report.pdf명령 참조
명령 | 설명 |
| 단일 URL을 가져와 마크다운 출력 |
| 일괄 모드에서 여러 URL 가져오기 |
| 바이너리 파일을 로컬 경로로 다운로드 |
| 도움말 표시 |
구성
모든 설정은 시작 시 환경 변수에서 읽어오며 Zod로 검증됩니다. 잘못된 값은 설명적인 오류와 함께 0이 아닌 종료 코드를 발생시킵니다.
.env.example을 .env로 복사하여 시작하세요:
cp .env.example .env참조
변수 | 기본값 | 설명 |
|
| 가져오기 요청당 시간 제한(ms) |
|
| 일괄 작업 시 최대 병렬 가져오기 수 |
|
| 오류 발생 전 최대 리디렉션 홉 |
|
| 잘리기 전 최대 콘텐츠 크기(문자) |
|
|
|
|
|
|
|
| 최대 LRU 캐시 크기 (50MB) |
|
| 캐시 항목 TTL (15분) |
|
|
|
| (비어 있음) | 차단할(또는 허용 목록 모드에서 허용할) 쉼표로 구분된 도메인 |
| (비어 있음) | URL 경로별로 차단할 쉼표로 구분된 정규식 패턴 |
|
| 검색 요청의 기본 시간 제한(ms) |
|
| 바이너리 파일 다운로드 시간 제한(ms) |
| (설정 안 됨) | 설정 시 stdio 대신 이 포트에서 HTTP 서버 시작 |
| (설정 안 됨) | 모든 HTTP 요청에 필요한 Bearer 토큰 (HTTP 모드 전용) |
| (설정 안 됨) | Playwright용 프록시 서버 URL (예: |
| (설정 안 됨) | 프록시를 우회할 쉼표로 구분된 도메인 |
모든 로그는 MCP 프로토콜을 위해 `stdout
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/JohnnyFoulds/markdown-for-agents-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server