Skip to main content
Glama

jina-style-reader-mcp

Clean Markdown URL Extractor, Quantitative/Qualitative Writing Style Recipe Analyzer & DuckDB Style Vault MCP Server (with Full SSRF & Indirect Prompt-Injection Defense)
Webページ・企業IR・官公庁資料からノイズのないクリーンなMarkdown本文を抽出し、「良い記事の構成・文体リズム」を定量・定性解析してローカルDuckDBのお手本辞書(style_templates)にストックできる1ツール特化型 MCP サーバー

License: MIT MCP Protocol Python 3.10+ DuckDB Powered Security: SSRF & Injection Hardened

English | 日本語ドキュメント


🌍 English Documentation

Why jina-style-reader-mcp?

When using Local LLMs (such as Qwen3-8B on LM Studio or Ollama) or cloud AI agents (Claude Desktop, Cursor, Cline) to read external web pages, corporate IR disclosures, or government white papers—and to write high-engagement articles—three major challenges arise:

  1. HTML Noise & Token Waste: Raw HTML pages are bloated with ads, navigation menus, tracking scripts, and sidebar clutter that exhaust LLM context windows.

  2. Difficulty Reproducing Great Writing Styles: Even when you find an article with a compelling opening hook, crisp heading rhythm, and natural prose cadence, translating that implicit "feel" into a reusable, structured writing template is difficult.

  3. SSRF & Indirect Prompt-Injection Risks: Naive URL fetchers expose local services (localhost, 127.0.0.1, cloud metadata 169.254.169.254, private LANs) to Server-Side Request Forgery (SSRF) and pass untrusted web text containing hidden system instructions (<|im_start|>, [INST], System:) directly to the LLM.

jina-style-reader-mcp solves all three in a single, unified MCP tool (read_url_and_capture_style):

  • Dual-Engine Clean Markdown Extraction (url): Queries https://r.jina.ai/<URL> for clean Markdown and automatically falls back to a built-in zero-dependency HTML-to-Markdown parser that strips ads, navbars, scripts, and footers while preserving headings (H1–H6), lists, code blocks, and Markdown tables.

  • Quantitative & Qualitative Style Recipe Capture (save_style_as): Analyzes the extracted article across 3 structural dimensions—(1) Opening Hook Pattern, (2) H2/H3 Heading Granularity & Rhythm, and (3) Sentence Length, Paragraph Structure & Ending Style (です・ます polite vs. だ・である assertive vs. 体言止め noun-endings)—and saves the synthesized template directly into the style_templates table of a local DuckDB database (VAULT_DB_PATH).

  • 100% Shared-Database Compatibility with multi-publisher-mcp: Styles captured via save_style_as (e.g., "人気noteランキング調", "東洋経済アナリスト調") can be immediately invoked by multi-publisher-mcp (style_name="人気noteランキング調") to generate 6-platform manuscripts in <1.0s.


✨ Single Unified Tool: read_url_and_capture_style

Parameter

Type

Required

Default

Description

url

string

Conditional*

""

Public http:// or https:// URL to extract as clean Markdown (*optional when list_saved_styles=True is called alone).

save_style_as

string

No

""

Style recipe name (e.g., "人気noteランキング調", "東洋経済アナリスト調"). When provided, analyzes the article's style & rhythm and saves it to the local DuckDB style_templates table.

list_saved_styles

boolean

No

false

When true, returns all built-in and custom writing style recipes stored in DuckDB style_templates.

analyze_style

boolean

No

true

Whether to compute and return the quantitative/qualitative style analysis report for the extracted article.

use_jina_reader

boolean

No

true

Try https://r.jina.ai/<URL> first and automatically fall back to the local HTML-to-Markdown parser if unavailable.

max_chars

integer

No

30000

Maximum character count of the sanitized Markdown body (500–200000).

export_filename

string

No

""

Optional relative .md filename to save inside the sandboxed READER_EXPORT_DIR (../ traversal is strictly rejected).


🔒 Enterprise-Grade Security Architecture

  1. Complete SSRF Defense (Pre-Request, Post-DNS Resolution & Redirect Hop Re-Validation):

    • Permitted Schemes: Exclusively http:// and https:// (file://, ftp://, gopher://, javascript:, data:, dict:// are blocked).

    • Blocked Targets: localhost, 127.0.0.0/8, 0.0.0.0/8, ::1, cloud metadata endpoints (169.254.169.254, 169.254.0.0/16, metadata.google.internal, 100.100.100.200), private RFC 1918 networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), CGNAT (100.64.0.0/10), and IPv6 unique-local/link-local (fc00::/7, fe80::/10).

    • Obfuscated IP & DNS Rebinding Protection: Decodes integer (2130706433), hex (0x7f000001), octal (0177.0.0.1), short (127.1), and IPv4-mapped IPv6 (::ffff:127.0.0.1) literals, resolves DNS via socket.getaddrinfo(), and verifies that every resolved IP address is globally routable before connecting and across every HTTP redirect hop.

  2. Indirect Prompt-Injection Neutralization & Boundary Tagging:

    • Strips control characters and neutralizes LLM system-spoofing markers (<|im_start|>, <|im_end|>, [INST], [/INST], <<SYS>>, System:, <system>, <instruction>, Ignore all previous instructions, and boundary-escape tags).

    • Wraps all returned external content inside <untrusted_web_content> and <untrusted_data> boundary tags.

  3. Filesystem Sandboxing & Zero File Deletion:

    • Any optional file export uses Path.resolve() and relative_to() to strictly reject ../ path traversal or outside absolute paths. No file deletion APIs (os.remove, unlink, rmtree) exist in the codebase.


🚀 Quick Start

1. Installation

git clone https://github.com/japan-opendata-lab/jina-style-reader-mcp.git
cd jina-style-reader-mcp
pip install -e ".[dev]"
pytest -v

2. Configure in LM Studio (~/.lmstudio/mcp.json), Claude Desktop, or Cursor

{
  "mcpServers": {
    "jina-style-reader-mcp": {
      "command": "python",
      "args": [
        "-X",
        "utf8",
        "./oss_mcp/jina-style-reader-mcp/server.py"
      ],
      "env": {
        "PYTHONIOENCODING": "utf-8",
        "VAULT_DB_PATH": "./data/analyst_vault.duckdb",
        "READER_EXPORT_DIR": "./exports/reader_captures"
      }
    }
  }
}

🔗 Synergy Workflow: jina-style-reader-mcp + japan-data-mcp + multi-publisher-mcp

By sharing the same VAULT_DB_PATH (./data/analyst_vault.duckdb) between jina-style-reader-mcp and multi-publisher-mcp, your local LLM or AI agent becomes a style-aware research and publishing studio:

  1. Step 1 — Read Reference URL & Capture Writing Style (jina-style-reader-mcp):

    {
      "tool": "read_url_and_capture_style",
      "arguments": {
        "url": "https://example.com/popular-data-ranking-article",
        "save_style_as": "人気noteランキング調"
      }
    }

    Extracts clean Markdown and saves the analyzed hook, H2/H3 rhythm, and sentence ending metrics as "人気noteランキング調" in analyst_vault.duckdb (style_templates).

  2. Step 2 — Fetch Official Statistical Evidence (japan-data-mcp / correlation-discovery-mcp): Query normalized municipal and corporate datasets across 162 official data sources by municipality_code or corporate_number.

  3. Step 3 — One-Shot Publish in the Captured Style (multi-publisher-mcp):

    {
      "tool": "vault_and_publish",
      "arguments": {
        "action": "publish_all",
        "title": "全国市区町村の課税所得と住宅地価の乖離ランキング",
        "style_name": "人気noteランキング調",
        "data_records": [
          {"label": "千代田区", "income": 1085, "land_price": 295.0},
          {"label": "つくば市", "income": 542, "land_price": 9.8}
        ]
      }
    }

Related MCP server: agentfetch-mcp

🇯🇵 日本語ドキュメント

なぜ jina-style-reader-mcp が必要なのか?

ローカルLLM(LM Studio 上の Qwen3-8B 等)や Claude Desktop / Cursor に、Web記事・企業IR資料・官公庁の報道発表URLを読ませて調査や記事執筆を行わせる際、以下の3つの課題がありました。

  1. HTMLノイズによるコンテキスト圧迫: 生のHTMLには広告、ナビゲーションメニュー、スクリプト、フッター等のノイズが大量に含まれ、LLMのトークン枠を無駄に消費します。

  2. 「良い記事の構成・文体リズム」の再現性の低さ: 「この記事の導入フックや見出しの立て方、文末のリズムが良いな」と感じても、それを定量・定性的なルール(文体レシピ)として言語化・保存する仕組みがありませんでした。

  3. SSRF(サーバーサイド・リクエスト・フォージェリ)と間接プロンプトインジェクションの脅威: 外部URLを無防備に取得するツールは、localhost や内部ネットワーク(192.168.x.x)、クラウドメタデータ(169.254.169.254)への不正アクセス踏み台にされたり、Webページ内に仕込まれたシステム命令偽装トークン(<|im_start|>, [INST], System:)によってLLMが乗っ取られるリスクがあります。

jina-style-reader-mcp は、これらすべてを たった1つの統合ツール(read_url_and_capture_style) で解決します。


✨ 1ツール統合仕様:read_url_and_capture_style

機能1:高精度Markdown抽出(url)

  • https://r.jina.ai/<URL> によるMarkdown抽出と、内蔵のゼロ依存ローカルHTMLパーサー(CleanHTMLToMarkdownParser)への自動フォールバックを搭載。

  • 広告バナー、グローバルナビ、サイドバー、スクリプト、スタイルシートを自動除去し、見出し(H1〜H6)、段落、箇条書き、Markdownテーブル(表)、引用、コードブロックを綺麗に保った本文を抽出します。

機能2:お手本文体レシピの定量・定性解析&DuckDB保存(save_style_as)

save_style_as(例: "人気noteランキング調", "東洋経済アナリスト調")を指定すると、抽出した記事から以下の3軸を自動解析し、ローカルDuckDB(VAULT_DB_PATH)の style_templates テーブルに保存します。

  1. 冒頭フックの構造パターン(opening_hook_analysis):

    • 「常識逆転×定量エビデンス提示型」「疑問・問いかけフック型」「課題提起・ペインポイント共感型」「結論・検証テーマ明示型」等のパターン判定と、再利用可能なリード文テンプレートの自動合成。

  2. 見出し(H2/H3)の粒度・リズム(heading_rhythm_analysis):

    • H2・H3見出しの個数、H2あたりの平均H3階層比率、見出しの平均文字数、1セクション(H2間)あたりの平均本文文字数、見出し表現の特徴(ナンバリング、【 】 括弧強調、疑問提起型等)を算出。

  3. 平均文長・段落構成・語尾の特徴(sentence_and_ending_analysis):

    • 総文数、平均文長・中央値文長、1段落あたりの平均文数・文字数、文字種比率(漢字・ひらがな・カタカナ・英数字比率)、および語尾の特徴(敬体 です・ます調 比率 vs 常体 だ・である調 比率 vs 体言止め 比率)を定量算出。

list_saved_styles=True を指定することで、保存済みの文体レシピ一覧をいつでも取得できます。


🔒 セキュリティ設計(SSRF完全防御 & プロンプトインジェクション無害化)

  1. SSRF(Server-Side Request Forgery)の完全防御:

    • http:// および https:// スキームのみを許可し、file://, ftp://, gopher://, javascript:, data: 等を完全拒否します。

    • localhost, 127.0.0.1, 0.0.0.0, ::1, クラウドメタデータ(169.254.x.x, metadata.google.internal), プライベートIP帯(10.x.x.x, 172.16-31.x.x, 192.168.x.x)へのアクセスを、10進/8進/16進の難読化IP表記・DNS名前解決後の全IP・HTTPリダイレクト先を含めて完全にブロックします。

  2. 間接プロンプトインジェクション無害化とデータ境界タグ:

    • 外部Webページのテキストに含まれるシステム命令偽装トークン(<|im_start|>, <|im_end|>, [INST], [/INST], <<SYS>>, System:, <system>, Ignore previous instructions, システム命令: 等)や境界脱出タグを [filtered] に無害化します。

    • 返却テキストは必ず <untrusted_web_content> および <untrusted_data> データ境界タグで二重に囲んで返却します。

  3. ファイル出力サンドボックス:

    • export_filename 指定時は Path.resolve() と relative_to() によりパストラバーサル(../)や絶対パス指定を完全拒否し、ファイル削除機能は一切持ちません。


🔗 multi-publisher-mcp / japan-data-mcp との連携ワークフロー

環境変数 VAULT_DB_PATH(デフォルト ./data/analyst_vault.duckdb)を multi-publisher-mcp と共有することで、以下のワンストップ連携が実現します。

  1. お手本記事の文体キャプチャ(jina-style-reader-mcp): read_url_and_capture_style(url="https://...", save_style_as="東洋経済アナリスト調") を呼び出し、記事のクリーンなMarkdownを読み込むと同時に、構成・文体レシピを analyst_vault.duckdb の style_templates テーブルに登録。

  2. 公的オープンデータの抽出・相関発見(japan-data-mcp / correlation-discovery-mcp): japan-data-mcp や correlation-discovery-mcp で市区町村コード・法人番号に紐づく統計データを取得。

  3. キャプチャした文体で6媒体一括パブリッシュ(multi-publisher-mcp): vault_and_publish(action="publish_all", style_name="東洋経済アナリスト調", ...) を実行し、先ほどキャプチャした文体リズムを使って note / Zenn / Qiita / Dev.to / Medium / X の6媒体原稿+グラフPNG+Excel/CSVを1秒以内に一括生成!


📄 License

MIT License — Copyright (c) 2026 Japan Open Data Lab

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables LLMs to retrieve and process web content by fetching URLs and converting HTML to markdown format. Supports chunked reading of large pages and can access both public websites and local networks.
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to fetch web pages with token estimation, caching, and routing to appropriate fetchers (Trafilatura, Jina, FireCrawl, pypdf) for clean Markdown output.
    4
    44 PyPI
    3
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to reliably fetch public web URLs and extract clean, agent-ready text, Markdown, links, and metadata, with automatic browser fallback and optional x402 payment support.
    -