Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ============================================
# Markdownify MCP Server — Environment Variables
# ============================================
# Copy this file to .env and adjust as needed.
# All variables are optional with sensible defaults.

# --- Executable Paths ---
# Override the path to the `markitdown` Python CLI.
# Default: .venv/bin/markitdown (project venv) → "markitdown" on PATH
# MARKITDOWN_PATH=/opt/markitdown/bin/markitdown

# Override the path to the `repomix` Node.js CLI.
# Default: node_modules/.bin/repomix → "repomix" on PATH
# REPOMIX_PATH=/opt/repomix/bin/repomix

# --- Security: File Access Control ---
# Semicolon-separated list (Windows) or colon-separated list (macOS/Linux)
# of directories that the server is allowed to read files from.
#
# When set, filePath arguments outside these directories are rejected.
# When UNset, file access is UNRESTRICTED — USE WITH CAUTION.
#
# Examples:
# macOS/Linux: MD_ALLOWED_PATHS=/home/user/docs:/tmp/shared
# Windows: MD_ALLOWED_PATHS=C:\Users\user\docs;D:\shared
# MD_ALLOWED_PATHS=

# Deprecated: Single-directory alias for MD_ALLOWED_PATHS.
# Prefer MD_ALLOWED_PATHS for multi-directory support.
# MD_SHARE_DIR=
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: CI

on:
pull_request:
branches: [main]

jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v2

- run: bun install

- run: bun run lint

- run: bun run build

- run: bun test
59 changes: 59 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Changelog

## [Unreleased]

### Fixed
- `Markdownify.get()` now correctly resolves relative paths and home directory (`~`) paths. Previously the resolved path was computed but never used, causing `existsSync` and `readFile` to operate on the raw input.
- `isWithinDirectory()` no longer produces false positives for prefix matches (e.g. `/home/user/docs-other` matching `/home/user/docs`).
- `validateUrl()` now blocks IPv6 loopback addresses (`::1`) and rejects URLs with embedded credentials (`user:pass@host`).
- `inferExtensionFromUrl()` now correctly handles URLs with query strings and fragments before checking file extension.
- `isMarkdownFile()` now matches extensions case-insensitively (`.MD`, `.MARKDOWN`).

### Changed
- Increased test timeouts for PDF conversion (15s, onnxruntime warmup) and invalid repo detection (120s, GitHub API latency).

### Added
- `server.test.ts`: 17 MCP protocol integration tests covering tool listing, routing dispatch, argument validation, error formatting, and response structure.
- `tools.test.ts`: 15 tool schema validation tests for naming conventions, required fields, and annotation consistency.
- `Markdownify.extended.test.ts`: 16 edge case tests for redirect handling, command injection defense, path allowlist enforcement, and error message quality.
- Extended `utils.test.ts` with 12 additional tests for IPv6 security, credential injection, path boundary edge cases, and URL query/fragment handling.
- `.env.example` with documentation for all supported environment variables.

## [1.1.0] — 2025-05

### Added
- Docker path resolution: `MARKITDOWN_PATH`, `REPOMIX_PATH`, and `MD_ALLOWED_PATHS` environment variables are now overridable inside containers.
- Docker E2E smoke test via `scripts/docker-smoke-test.sh`.

### Fixed
- Dockerfile: use `markitdown[pdf]` instead of `[all]` to avoid ONNX runtime ARM compatibility issues.

## [1.0.4] — 2025-04

### Added
- GitHub Actions CI workflow with `lint → build → test` pipeline (on `ci/add-biome-and-github-actions` branch).
- Biome configuration for linting and formatting.

## [1.0.3] — 2025-04

### Fixed
- Dockerfile and `pyproject.toml` updated to use `markitdown[all]` for complete format support.
- CI: added Python setup step for markitdown tests.
- CI: ignore harmless stderr warnings from markitdown subprocess.

## [1.0.2] — 2025-04

### Fixed
- Missing `test.pdf` sample data file added.
- `CLAUDE.md` project documentation added.

## [1.0.1] — 2025-04

### Added
- Initial public release.
- 11 MCP tools for file-to-markdown conversion.
- SSRF protection with `private-ip` library and redirect validation.
- Path allowlist security (`MD_ALLOWED_PATHS` / `MD_SHARE_DIR`).
- `git-repo-to-markdown` tool wrapping Repomix.
- Docker multi-stage build support.
- 30+ unit tests and 14 integration tests.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,29 @@ Notes for the Docker MCP catalog (`mcp/markdownify`):
- `docx-to-markdown`: Convert DOCX files to Markdown
- `xlsx-to-markdown`: Convert XLSX files to Markdown
- `pptx-to-markdown`: Convert PPTX files to Markdown
- `git-repo-to-markdown`: Convert a GitHub repository into a single Markdown document (wraps Repomix). Supports `owner/repo` shorthand and full URLs.
- `get-markdown-file`: Retrieve an existing Markdown file. File extension must end with: *.md, *.markdown.

OPTIONAL: set `MD_ALLOWED_PATHS` to restrict every file-input tool to a list of directories, e.g. `MD_ALLOWED_PATHS=/data/in:/data/out bun start`.

### Docker feature matrix

| Tool | Local | Docker |
|------|-------|--------|
| `pdf-to-markdown` | ✅ | ✅ |
| `docx-to-markdown` | ✅ | ✅ |
| `xlsx-to-markdown` | ✅ | ✅ |
| `pptx-to-markdown` | ✅ | ✅ |
| `webpage-to-markdown` | ✅ | ✅ |
| `youtube-to-markdown` | ✅ | ✅ |
| `bing-search-to-markdown` | ✅ | ✅ |
| `git-repo-to-markdown` | ✅ | ✅ |
| `get-markdown-file` | ✅ | ✅ |
| `image-to-markdown` | ✅ | ❌ ¹ |
| `audio-to-markdown` | ✅ | ❌ ¹ |

¹ Docker image installs `markitdown[pdf]` only — image/audio extras are excluded to keep the image slim and avoid ONNX runtime ARM compatibility issues.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
Expand Down
58 changes: 58 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"includes": ["**", "!!**/dist", "!!**/sample-data", "!!**/markdownify"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noStaticOnlyClass": "off"
},
"style": {
"noNonNullAssertion": "off"
},
"suspicious": {
"noExplicitAny": "off"
}
}
},
"overrides": [
{
"includes": ["*.test.ts"],
"linter": {
"rules": {
"style": {
"noNonNullAssertion": "off"
},
"suspicious": {
"noExplicitAny": "off"
}
}
}
}
],
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
19 changes: 19 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"preinstall": "node preinstall.js",
"prepublishOnly": "bun run build",
"start": "bun dist/index.js",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"test": "bun test",
"test:watch": "bun test --watch"
},
Expand All @@ -32,6 +34,7 @@
"zod": "^4.3.6"
},
"devDependencies": {
"@biomejs/biome": "^2.4.10",
"@types/node": "^25.3.5",
"typescript": "^6.0.2"
}
Expand Down
Loading