Skip to main content
Glama

Sora (空)

Self-hosted MCP / REST integration server for using the Japanese web from AI agents
All-in-One, Zero-Middleware Web Scraping & Japanese Life Infrastructure Engine for AI Agents

Sora is an all-in-one MCP / REST server that lets LLMs and AI agents (Claude Desktop, Cursor, Cline, OpenCodeInterpreter, Dify, etc.) freely and safely explore and operate the Japanese web space and everyday-life infrastructure.

It requires no external databases (Redis / PostgreSQL) or message queues, and runs instantly from a monthly ¥800 VPS with just a single container / a single binary that bundles headless Chromium and Japanese CJK fonts.

flowchart LR
    subgraph Clients["AI Clients / Agents"]
        Claude["Claude Desktop / Cursor"]
        Agents["LangChain / AutoGen / Dify"]
    end

    subgraph Sora["Sora All-in-One (Distroless / Bun)"]
        direction TB
        MCP["MCP Server (Streamable HTTP / SSE)"]
        REST["Hono REST API (OpenAPI 3.0)"]
        Auth["Timing-Safe Auth & SSRF Guard"]
        LRU["True LRU In-Memory Cache"]
        
        subgraph Engine["Dual Scrape Engine"]
            Fast["Static Fetch + Readability + AI Chunker"]
            Browser["Stealth Chromium + Browser DSL (Tabs/Clicks)"]
        end

        subgraph JP["Japan Life Infrastructure"]
            JMA["気象庁 1,805自治体 天気予報"]
            Transit["Yahoo! 路線乗換・IC運賃"]
            Yahoo["Yahoo! リアルタイム(X)/知恵袋/ニュース/画像/動画"]
        end
    end

    subgraph Web["Public Internet"]
        Sites["Web Sites / PDFs / SPAs"]
        PublicData["気象庁 / Yahoo / X"]
    end

    Clients <-->|MCP / REST| Sora
    Fast --> Sites
    Browser --> Sites
    JP --> PublicData

⚡ Quickstart that connects in 5 seconds (Claude Desktop / Cursor / Cline)

Just add the following to your AI agent's configuration file (e.g., claude_desktop_config.json), and a suite of 16 powerful tools is immediately enabled.

① Remote MCP (HTTP / SSE) connection

Specify the URL while the Sora container is running:

{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/mcp"
    }
  }
}

② One-command startup with Docker / Podman

docker run -d -p 3016:8000 --name sora ghcr.io/ikenokazuki/sora:latest

Related MCP server: Agent Toolbox

🌟 Main features and strengths (Why Sora?)

  1. 🗾 Complete coverage of Japanese daily infrastructure & web exploration:

    • Delivers in a single MCP what overseas tools (Firecrawl / Tavily) cannot handle: "Yahoo! 知恵袋", "X (Twitter) real-time news", "direct connection to 気象庁's official open data (automatic selection of all 1,805 municipalities across Japan)", and "train transfer guidance".

  2. ⚡ Overwhelming millisecond response & ultra-low memory consumption:

    • With Bun native compilation, API response is 1.5 ms and resident memory is JS heap ~32MB / total ~140MB. It minimizes the waiting time of AI agents to the extreme.

  3. 📦 Completely all-in-one & zero middleware:

    • No Redis, PostgreSQL, external worker queues, or anything else required. It is complete immediately with just a single binary / single container.

  4. 🛡️ Distroless (no shell) & strict security:

    • Adopts gcr.io/distroless/cc-debian12 as the base image. Because /bin/sh, bash, curl, etc. do not exist inside the container, RCE (arbitrary code execution) attacks are neutralized.

    • Standard features include SSRF/DNS rebinding blocking, timing-attack prevention via constant-time comparison, browser session ownership separation, and DoS defense with a body limit of 10 MB.

  5. 🕹️ Stateful browser operation DSL:

    • Directly control multi-turn interactive browser sessions — openfillclickscreenshotevaluate — via the API / MCP.


📊 Performance & architecture comparison

API / health check response

Sora (this tool)

Firecrawl (self-hosted)

Typical Node/Python MCP

1.5 ms (0.0015s)

20–50 ms

30–100 ms

Startup time (cold start)

< 10 ms

10–30 s (multiple services)

1–3 s

Resident memory usage (RSS)

~140 MB (JS heap ~140 MB)

2–4 GB+

250–800 MB

Image size (total)

~1.18 GB (includes Chromium + Japanese CJK fonts)

4–6 GB+ (combined multiple images)

800 MB–2.5 GB

Single container structure

Single container (all-in-one)

5–6 (Redis/PG/Workers)

Multiple MCP processes scattered

Security design

Distroless, no shell, non-root

Regular Debian/Alpine

Regular Debian/Ubuntu

Japan-specific local info

Full support (weather, transfers, Chiebukuro, X)

Not supported (web only)

Need individual plugins


⏱️ Measured response speed of each endpoint (Measured Latency: Cold vs Cached)

The following are actual measured latencies for "first fetch (uncached)" and "on cache hit" on a real local server. Compared with the 1–3 seconds an AI agent spends thinking before generating, responses are overwhelmingly fast.

Endpoint

First fetch (uncached)

Cached (2nd and later)

Process / technical characteristics

GET /health

0.2–1.8 ms

API liveness/health check (optimized with Bun)

GET /weather (気象庁)

approx. 38 ms

0.4–0.7 ms

Parse directly from the 気象庁 official CDN (jma.go.jp) and automatically select 1,805 municipalities

POST /scrape (static-fast mode)

approx. 79 ms

0.5–1.0 ms

Fast web page fetch + Markdown body extraction

POST /scrape (SPA auto-upgrade / browser rendering)

approx. 1.2–1.6 s

0.5–1.0 ms

If static fetching yields blank content or a bot screen, automatically promotes to Stealth Chromium and extracts Markdown

POST /transit/route (transfer planning)

approx. 390 ms

0.6–7.0 ms

Scrape Yahoo! 路線情報 (optimal routes & IC fares)

POST /search/realtime (breaking X)

approx. 440 ms

0.6 ms

Yahoo! リアルタイム検索 (X tweet & image extraction)

POST /search/news

approx. 480 ms

0.6 ms

Yahoo! ニュース latest-article search

POST /search/image / video

450–550 ms

0.6 ms

Yahoo! 画像・画像検索

POST /search/chiebukuro (知恵袋)

420–500 ms

0.6 ms

Yahoo! 知恵袋 Q&A search

POST /search/suggest

approx. 820 ms

0.5 ms

Yahoo! オートコンプリート related-word completion

POST /browser/action (first run)

approx. 1.4 s

Start Stealth Chromium, render, click, wait, screenshot, collect Markdown

POST /browser/action (continued session)

approx. 0.5–0.8 s

Execute additional actions on the existing toolbar (sessionId)

⚡ Measured speed of internal enrichment / AI optimization processing (In-Memory)

Without calling external LLM APIs, all processing is completed in less than 1 ms (< 1ms) via Bun-native and optimized algorithms.

Process

per-call time (measured)

Characteristics / algorithm

Reading time / character statistics (calculateContentStats)

0.03 ms (31 ms

Fast counting of CJK/English words & estimated reading time

Citation / citation-only link extraction (extractCitationsFromMarkdown)

0.06 ms (62 ms)

Regex + context-context slicing

RAG semantic chunking (chunkMarkdownContent)

0.13 ms (138 s)

Semantic splits based on headings and code-block boundaries

Search-result dedupe (dedupSearchResults)

0.33 ms (335 s)

N-gram Jaccard similarity comparison for 50 entries

Automatic PII masking (maskPiiInText)

0.55 ms (557 ms)

Email/phone/Luhn-credit-card detection & replacement

Ultracextractive summarization / TL;DR (generateExtractiveSummary)

0.97 ms (970 ms)

TF-IDF-like salient-sentence extraction

Markdown keyword highlight (highlightMatches)

9.1 ms

Syntax-safe insertion of <mark> tags via regex


🏛️ Design philosophy & principles

Sora is built on the following four core design principles:

  1. ✂️ Occam’s razor & zero-middleware

    • “Do not make assumptions when they are not necessary. Make the simplest structure that meets requirements the best.”

    • It eliminates Redis, PostgreSQL, external queues, heavy microservices, and runs with only “single container / single binary.” It keeps running without a fail from an ¥800/month VPS or a Raspberry Pi to cloud setups with tens of thousands of requests.

  2. 🛡️ Stealth and survivability – Pareto optimum

    • Blindly accessing at “0 ms” with a machine will cause the target server’s WAF or Cloudflare to immediately BAN your IP, dropping the success rate to 0%.

    • For consecutive requests to the same domain, it automatically inserts 150 ms + jitter (0–100 ms fluctuation), and also adds 15–40 ms human-like delays between keystrokes. It thus maximizes the “survival rate” of actually returning data, without hurting the AI-facing experience.

  3. 🔒 Robust security by design (Distroless)

    • Because the container contains no /bin/sh, bash, curl, or apt, even an unknown vulnerability gives an attacker no root account (RCE) in principle. It is equipped with non-root execution and strict SSRF blocking.

  4. 🗾 Attach to public open data for sustainability

    • Weather forecasts come straight from 気象庁’s official open-data CDN (jma.go.jp). With zero-millisecond automatic resolution of Japan’s 1,805 municipalities and a 30-minute LRU cache, it runs autonomously forever while keeping the load on the destination server to a minimum.


1. Quick start

1.1 Start the container (Docker / Podman)

You can fire it up in one command from GitHub Container Registry (GHCR):

docker run -d \
  --name sora \
  -p 3016:8000 \
  -e API_KEY="your-secret-api-key" \
  -e ENABLED_MODULES="all" \
  ghcr.io/ikenokazuki/sora:latest

1.2 MCP client configuration (Claude Desktop / Cursor / Cline / Windsurf, etc.)

Add the following to your configuration file (e.g., claude_desktop_config.json or Cursor’s MCP settings):

{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-api-key"
      }
    }
  }
}

SSE connection (for legacy SSE clients)

{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/sse",
      "headers": {
        "Authorization": "Bearer your-secret-api-key"
      }
    }
  }
}

(Markers can be omitted if no API key is set)


2. Provided MCP tools (all 16 tools, 4 modules)

Sora consists of four logical modules depending on the use case. You can freely customize the categories enabled by setting the environment variable ENABLED_MODULES (default all, or web,index,user,life, nullable).

┌──────────────────────────────────────────────────────────────────────────┐
│                         Sora - Modular MCP                               │
├─────────────────┬───────────────────┬──────────────────┬─────────────────┤
│ 🌐 Core Web     │ 🤖 Browser Action │ 🇯🇵 Yahoo Services │ 🗾 Daily Life   │
│ (`web`)         │ (`browser`)       │ (`yahoo`)        │ (`life`)        │
│ ・search_web    │ ・browser_action  │ ・search_image   │ ・search_route  │
│ ・scrape        │   (クリック/入力/ │ ・search_video   │   (乗換案内)    │
│ ・scrape_batch  │    スクショ/JS実行│ ・search_news    │ ・get_weather   │
│ ・search_deep   │    セッション保持)│ ・search_chiebukuro│ (気象庁天気)  │
│ ・map_site      │                   │ ・search_realtime│                 │
│ ・crawl_site    │                   │ ・search_trend   │                 │
│                 │                   │ ・suggest_keywords│                │
└─────────────────┴───────────────────┴──────────────────┴─────────────────┘

🌐 Module 1: Core Web & Crawling (ENABLED_MODULES=web)

Web searching, body scraping, mass parallel fetching, deep discounted search, site-map parsing, and recursive crawls.


| Tool name       | Description                                                                                                                                          | Identification properties                            | Main arguments                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_web`   | Performs a web search and retrieves the top titles, summary snippets, and URLs. Supports domain filtering, exclusion, and time range specification.                                                                                | Each item has `source: "web"`                       | - `query` (string, required): Search keyword<br>- `includeDomains` (string\[], optional): Domains to filter by<br>- `excludeDomains` (string\[], optional): Domains to exclude<br>- `updated` (string, optional): Time range (`"all"`, `"day"`, `"week"`, `"year"`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `scrape`       | Scrapes the web page or PDF at the specified URL and extracts the body as Markdown. Automatically renders SPA sites and bot-protection screens with Chromium. Supports RAG chunking, source extraction, reading time, PII protection, table JSON extraction, and summary generation. | `source: "web"`                              | - `url` (string, required): Target URL / PDF<br>- `maxChars` (number, optional): Maximum number of characters (default: 10000)<br>- `mode` (string, optional): `"auto"` (smart auto-detection, default), `"fast"` (static, fastest), `"browser"` (Stealth Chromium)<br>- `formats` (string\[], optional): `["markdown", "html", "rawHtml", "links", "screenshot", "jsonLd", "images", "tables"]`<br>- `chunkMarkdown` (boolean, optional): Whether to perform semantic chunking for RAG<br>- `chunkSize` (number, optional): Target chunk size in characters (default: 1000)<br>- `extractCitations` (boolean, optional): Whether to extract a list of source/citation links<br>- `validateLinks` (boolean, optional): Whether to validate link reachability and status in parallel<br>- `extractSummary` (boolean, optional): Whether to generate an extractive auto summary (TL;DR)<br>- `maskPii` (boolean, optional): Whether to automatically mask personal information such as emails, phone numbers, and credit card numbers<br>- `formatAsPrompt` (boolean, optional): Whether to generate a standard XML wrapper format for LLMs<br>- `highlightMatches` (boolean, optional): Whether to highlight search match terms<br>- `webhookUrl` (string, optional): Webhook URL for completion notification<br>- `onlyMainContent` (boolean, optional): Whether to extract only the article body (default: true)<br>- `selectors` (object, optional): Associative array of CSS selectors for pinpoint extraction<br>- `clipSelector` (string, optional): CSS selector for clipped element screenshots<br>- `headers` / `cookies` (object/array, optional): Custom headers / Cookie<br>- `removeSelectors` (string\[], optional): Noise selectors to purge<br>- `retries` (number, optional): Number of retries (0–3)<br>- `proxyUrl` (string, optional): Proxy URL to route through |
| `scrape_batch` | Specifies multiple web page URLs and scrapes them concurrently at high speed while maintaining domain throttling, returning all results at once.                                                                               | Each result has `source: "web"`                         | - `urls` (string\[], required): Array of URLs to scrape (max 20)<br>- `concurrency` (number, optional): Number of concurrent workers (default: 3, max: 5)<br>- (Supports all other options equivalent to `scrape`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `search_deep`  | Integrated deep search compatible with Firecrawl / Tavily. Combines web search + automatic scraping of top site content + real-time search in a single fetch.                                                                    | Web results have `source: "web"`<br>X results have `source: "x"` | - `query` (string, required): Search keyword<br>- `limit` (number, optional): Number of content items to fetch (default: 5, max: 20)<br>- `scrapeContent` (boolean, optional): Whether to include content (default: true)<br>- `includeRealtime` (boolean, optional): Whether to also include real-time search (default: true)<br>- `formats` (string\[], optional): `["markdown", "html", "rawHtml", "links", "screenshot"]`<br>- `onlyMainContent` (boolean, optional): Whether to extract only the article body (default: true)<br>- `extractHighlights` (boolean, optional): Whether to extract query-related highlights from each page (default: false)<br>- `includeDomains` / `excludeDomains` (string\[], optional)<br>- `updated` (string, optional): Time range (`"all"`, `"day"`, `"week"`, `"year"`)<br>- `proxyUrl` (string, optional): Proxy URL to route through                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `map_site`     | Explores the sitemap.xml or internal links of the specified website and quickly extracts a full list of all URLs (sitemap) within the site.                                                                         | -                                            | - `url` (string, required): Target base URL<br>- `limit` (number, optional): Number of results (default: 200, max: 1000)<br>- `includeSubdomains` (boolean, optional)<br>- `proxyUrl` (string, optional): Proxy URL to route through                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `crawl_site`   | Recursively crawls pages under the specified URL and collects content from multiple pages at once.                                                                                                 | Each result has `source: "web"`                         | - `url` (string, required): Crawl start URL<br>- `maxPages` (number, optional): Maximum number of pages to fetch (default: 10, max: 50)<br>- `maxDepth` (number, optional): Maximum link depth (default: 2)<br>- `formats` (string\[], optional): `["markdown", "html", "rawHtml", "links", "screenshot"]`<br>- `webhookUrl` (string, optional): Webhook URL to notify when the crawl completes<br>- `proxyUrl` (string, optional): Proxy URL to route through                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

***

### 💡 Best practices for LLM / Agent integration & `limit` adjustment guide

When using web search, scraping, and crawling in agents or RAG applications, the setting of the number of results (`limit`) significantly changes latency and answer quality.

#### 1. Pros and cons of increasing the number of results

| Item | Advantages | Disadvantages/Risks | Recommended Setting |
| :---------------------- | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------- | :------------------------- |
| **Integrated Deep Search (`/search`)** | Can comprehensively gather information from a wider range of sources. | - **Increased latency**: Fetching 10-20 sites in parallel delays response time to 5-15 seconds.<br>- **LLM context bloat**: Passing large volumes of full text increases token consumption and buries important information (the *Lost in the Middle* phenomenon). | Default `5`<br>(max `20`) |
| **Site Crawl (`/crawl`)** | Enables comprehensive knowledge collection across an entire document set. | - **Time and resource consumption**: Processing time increases proportionally with the number of pages. | Default `10`<br>(max `50`) |
| **Sitemap Discovery (`/map`)** | Instantly grasp the structure of the entire site. | - Since it only processes text, the load is extremely small. | Default `200`<br>(max `1000`) |

#### 2. Best Practices for the Highest-Precision LLM Utilization

> \[!TIP]
> **A more effective approach**:
>
> 1. **Using snippets vs. full text**: Returning **10-20 results** from the search snippets (`search_web`) itself gives a broad overview, while limiting full-text scrape targets (`search_deep` `limit`) to the **top 3-5 results** is the fastest and most accurate approach.
> 2. **Combine with highlight extraction**: Enabling `extractHighlights: true` (with `query`) lets the **Structure & Proximity-Aware BM25+ engine** (heading context inheritance, exact phrase matching, proximity scoring, KWIC snippet generation) focus the LLM on **only the most relevant paragraphs and sentences** instead of reading entire long pages, preventing hallucinations while reducing token consumption by 70-90% (no external LLM needed, runs locally in 0.3ms).
> 3. **Common metadata across all endpoints (Firecrawl / Tavily compatible)**: Automatically extracts `publishedTime` (publication/update time), `author` (author name), and `siteName` (site name) from OGP / JSON-LD / HTML meta tags and attaches them to the Frontmatter and JSON response. The LLM can instantly assess information freshness (fact-checking).
> 4. **Preserving GFM syntax highlighting languages**: Accurately identifies the programming language name from `<pre><code class="language-python">` etc. and reproduces it as `` ```python `` in Markdown output.
> 5. **Automatic token compression & noise removal**: Automatically cleans empty links, invalid JavaScript links, and unnecessary duplicate blank lines (`cleanMarkdownTokens`), and completely purges cookie consent banners (OneTrust / Cookiebot, etc.), keeping the LLM context always clean.
> 6. **Automatic robots.txt sitemap discovery**: Automatically detects irregularly placed Sitemap URLs from `/robots.txt` and recursively traverses up to 1,000 Sitemap Index entries.
> 7. **Streaming during crawls**: When crawling many pages, use `POST /crawl/stream` (SSE) to receive and process each page as soon as it is fetched, so you can return intermediate responses to the user or LLM immediately without waiting for the entire crawl to finish.

#### 3. Measured Benchmarks and Scalability Characteristics (Local Measurement Values)

| Process | Count / Pages | Average Latency (ms) | Throughput | Characteristics / Notes |
| :---------------------- | :-------------------------- | :---------------- | :----------------- | :------------------------ |
| **Site crawl** (`/crawl`) | `maxPages: 5` (previous default) | **358 ms** | 13.9 pages/sec | Extremely fast thanks to 3-way parallel fetching |
| | `maxPages: 10` (**new default**) | **341 ms** | **29.3 pages/sec** | Parallel queue improvements keep the time comparable to the previous default |
| | `maxPages: 20` | **2,046 ms** | 9.8 pages/sec | Collects full text from 20 pages in about 2 seconds |
| | `maxPages: 50` (**new upper limit**) | **4,685 ms** | 10.7 pages/sec | Even crawling 50 pages runs stably in under 5 seconds |
| **Sitemap discovery** (`/map`) | `limit: 100` (previous default) | **826 ms** | - | Extremely lightweight since it only parses XML/HTML |
| | `limit: 200` (**new default**) | **882 ms** | - | Response speed almost unchanged from 100 entries (+56 ms) |
| | `limit: 1000` (**new upper limit**) | **808 ms** | - | Almost zero overhead even with 1,000 entries |
| **Integrated deep search** (`/search`) | `limit: 3` (previous default) | **approx. 1.4 sec** | - | Web search + parallel scrape of top 3 results |
| | `limit: 5` (**new default**) | **approx. 2.0-3.4 sec** | - | Web search + parallel scrape of top 5 results |
| | `limit: 20` (**new upper limit**) | **approx. 4-8 sec** | - | For deep research across a wide range of sources |

***

### 🤖 Module 2: Browser Actions & Automation (`ENABLED_MODULES=browser`)

Form input, button clicks, screen scrolling, JavaScript execution, screenshot capture, and multi-turn conversation sessions.

| Tool Name | Description | Identifying Property | Main Arguments |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `browser_action` | Opens a web page, executes a specified sequence of actions (click, text input, key press, scroll, wait, screenshot, JS execution, page navigation), and returns the final screen as Markdown or a Base64 screenshot. Supports clicking buttons by their visible text and maintaining multi-turn conversation sessions via `sessionId`. | `source: "browser"` | - `url` (string, optional): Start/navigation URL<br>- `sessionId` (string, optional): Existing session ID<br>- `createSession` (boolean, optional): Whether to create and maintain a session<br>- `closeSession` (boolean, optional): Whether to end the session<br>- `actions` (array, optional): List of actions to execute (`click`, `fill`, `press`, `select`, `scroll`, `wait`, `evaluate`, `navigate`)<br>- `extract` (object, optional): `{ markdown: true, screenshot: true, html: false }`<br>- `timeout` (number, optional): Timeout ms |

***

### 🇯🇵 Module 3: Yahoo! JAPAN Services (`ENABLED_MODULES=yahoo`)

A search suite fully specialized in Japanese media, Q\&A, trends, and real-time information.

| Tool Name | Description | Identifying Property | Main Arguments |
| ------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `search_image` | Runs Yahoo! JAPAN image search and retrieves image titles, image URLs, thumbnails, image sizes, and source pages. | Each item has `source: "image"` | - `query` (string, required): Search keyword<br>- `limit` (number, optional): Number of results (default: 20, max: 50) |
| `search_video` | Runs Yahoo! JAPAN video search and retrieves video titles, video URLs, playback duration, distributor, and thumbnails. | Each item has `source: "video"` | - `query` (string, required): Search keyword<br>- `limit` (number, optional): Number of results (default: 20, max: 50) |
| `search_news` | Runs Yahoo! News search and retrieves titles, summaries, publishers, publication dates, and article URLs for the latest news articles. | Each item has `source: "news"` | - `query` (string, required): Search keyword<br>- `limit` (number, optional): Number of results (default: 10, max: 50) |
| `search_chiebukuro` | Runs Yahoo! Chiebukuro Q\&A search and retrieves question titles, answer counts, resolution status, and body snippets. | Each item has `source: "chiebukuro"` | - `query` (string, required): Search keyword<br>- `limit` (number, optional): Number of results (default: 10, max: 50) |
| `suggest_keywords` | Retrieves Yahoo! JAPAN autocomplete suggestions and returns related search words and completion candidates. | `source: "suggest"` | - `query` (string, required): Completion keyword<br>- `limit` (number, optional): Number of results (default: 10, max: 30) |
| `search_realtime` | Runs Yahoo! Real-Time Search and retrieves the latest X (formerly Twitter) posts (author, body, posting time, media, and URL). Supports switching between newest-first (`recent`) and trending (`popular`) sorting. | Each item has `source: "x"` | - `query` (string, required): Search keyword<br>- `sort` (string, optional): `"recent"` (newest first, default) or `"popular"` (trending)<br>- `limit` (number, optional): Number of results (default: 20, max: 40)<br>- `page` (number, optional): Page number (default: 1) |
| `search_trend` | Retrieves the latest trends from Yahoo! Real-Time Search (ranking of 20 rapidly rising keywords). | Each item has `source: "x"` | - `limit` (number, optional): Number of results (default: 20) |

***

### 🗾 Module 4: Japan Daily Life & Transit (`ENABLED_MODULES=life`)

Daily life infrastructure functions directly connected to Japanese public transit and official Japan Meteorological Agency open data.

| Tool Name | Description | Identifying Property | Main Arguments |
| -------------- | -------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_route` | Train transfer guidance for Japan. Searches for optimal routes between stations, required travel time, number of transfers, and IC/paper ticket fares. Supports specifying up to 3 intermediate stations, date/time specification, and limited express / Shinkansen usage flags. | `source: "transit"` | - `from` (string, required): Departure station name (e.g., "Tokyo")<br>- `to` (string, required): Arrival station name (e.g., "Shinjuku")<br>- `via` (string[], optional): Intermediate stations (up to 3 stations)<br>- `timeType` (string, optional): `"departure"`, `"arrival"`, `"first_train"`, `"last_train"`<br>- `ticket` (string, optional): `"ic"`, `"cash"`<br>- `sortBy` (string, optional): `"time"`, `"transfer"`, `"fare"` |
| `get_weather` | Retrieves today's, tomorrow's, and the day after tomorrow's weather forecasts, expected temperatures, precipitation probabilities, weather summaries, and wind/wave information for locations across Japan via direct connection to official Japan Meteorological Agency open data. Supports automatic resolution of all 1,805 municipality names nationwide. | `source: "weather"` | - `city` (string, required): Municipality name (e.g., "Tendo City", "Karuizawa", "Hakone", "Urayasu", "Tokyo") or location ID (e.g., "130010")<br>- `days` (number, optional): Number of forecast days (1-3 days, default: 3) |

***

## 3. REST API Specification

Base URL: `http://localhost:3016` (or the domain URL of your deployment)

### 3.1 Health Check & Metrics

#### `GET /health`

GXP8

#### `GET /metrics` (Operational statistics, cache hit rate, resource usage)

GXP9

#### `GET /metrics?format=prometheus` or `Accept: text/plain` (Prometheus monitoring metrics)

Outputs in the standard text format that can be imported directly into a Grafana / Prometheus monitoring stack.

GXP10

***

### 3.2 Single URL / PDF Scrape (`POST /scrape`)

* **Request**:

GXP11

* **Response example**:

GXP12

> \[!TIP]
> **🇯🇵 Automatic Support for Legacy Japanese Sites**: Web sites using `Shift_JIS (CP932)` or `EUC-JP` are auto-detected and decoded as well. No need to worry about garbled text.
>
> **📄 Enhanced PDF Extraction**: Multi-page PDF documents are output as structured Markdown with page-number separators like `<!-- Page 1 -->\n## Page 1`, and metadata such as `totalPages` and author information is also extracted automatically.
>
> **✂️ Syntax-Safe Trimming & Token Estimation**: Even when `maxChars` limits the character count, open code blocks ( ` ``` ` ) and tables are automatically corrected and closed safely. The response also includes an estimated LLM token count, `estimatedTokens`.
>
> **🧩 RAG-Optimized Semantic Chunking (`chunkMarkdown: true`)**: Automatically generates properly split `chunks: [{ index, heading, content, estimatedTokens }]` without breaking the heading hierarchy (H1–H4), paragraphs, or code blocks, ready to be fed directly into vector search or RAG.
>
> **🖼️ Image Metadata & Caption Extraction (`formats: ["images"]`)**: For each image, automatically extracts the URL plus the `<figcaption>` description (`caption`), `width`/`height`, and hero-image detection (`isMainImage`).
>
> **🔗 In-Page Link Health & Reachability Checking (`validateLinks: true`)**: Performs lightweight parallel validation of in-page links and returns the HTTP status and validity as `linksWithStatus: [{ url, status, ok }]`.
>
> **📚 Structured Extraction of Citations & Reference Links (`extractCitations: true`)**: Automatically extracts external links and references in the body text together with their surrounding context as `citations: [{ text, url, context }]`.
>
> **⏱️ Reading Time & Character/Word Count Statistics**: Automatically computes and attaches `characterCount`, `wordCount`, and an estimated reading time `readingTimeMin` (in minutes) based on language characteristics.
>
> **🔔 Asynchronous Webhook Callbacks (`webhookUrl`)**: When long-running batch processing or large-scale crawl jobs complete, the result payload is sent to the specified endpoint asynchronously via HTTP POST.
>
> **🛡️ Automatic PII Masking (`maskPii: true`)**: Sensitive information such as email addresses, Japanese phone numbers, and credit card numbers (Luhn-validated) is automatically redacted to `[EMAIL]`, `[PHONE]`, and `[CREDIT_CARD]` for safe transmission to LLMs.
>
> **📡 Real-Time Progress SSE Streaming (`POST /scrape/stream`)**: Progress events for each stage (`start` → `fetch` → `render` → `enrich` → `done`) can be received in real time via Server-Sent Events.
>
> **🎬 YouTube / Video Media Metadata & Chapter Extraction (`media`)**: Automatically extracts structured playback time, thumbnails, and chapter lists (timestamped tables of contents) from video pages.
>
> **🤖 LLM-Optimized Prompt XML Auto-Generation (`formatAsPrompt: true`)**: Automatically generates a message that Claude / GPT / Gemini can understand most easily (`promptContext`) in the standard `<web_page url="..." title="...">...</web_page>` wrapper format.
>
> **🖍️ Automatic Highlighting of Search Keywords in Body Text (`highlightMatches: true`)**: You can obtain `highlightedContent` with the keywords from the specified `query` highlighted as `<mark>キーワード</mark>` in the body Markdown.
>
> **📊 Structured JSON Table Extraction (`formats: ["tables"]`)**: Directly obtain all tables (`<table>`) in a page as a structured JSON array of `{ caption, headers, rows }`.
>
> **⚡ Extreme-Speed Extractive Auto-Summarization (`extractSummary: true`)**: Without calling an external LLM API, an internal algorithm generates `summary: string[]` (TL;DR important sentences) in milliseconds.
>
> **🎯 Search Result De-Old-location (`dedup: true`)**: In news or real-time searches, automatically removes duplicate copy-paste posts or republished articles through similarity detection, so only unique information remains.
>
> **🔄 Automatic Retry Policy (`retries` & `retryDelayMs`)**: Automatically retries with exponential backoff on connection failures or 429/503 errors to improve fault tolerance.
>
> **📸 Element-Specific Screenshot (`clipSelector`)**: By specifying a target element (e.g. `clipSelector: "#stock-chart"`), you can get a Base64 PNG cropped to just that element.
>
> **🍪 Custom Headers & Cookie Injection (`headers` / `cookies`)**: Transparently send membership-site headers, language preferences (`Accept-Language`), age-verification cookies, etc.
>
> **🧹 User-Specified Noise Selector Removal (`removeSelectors`)**: Specify `removeSelectors: [".ad", ".comments", "#related-articles"]` to thoroughly purge specific blocks before Markdown conversion.
>
> **📖 Interactive API Documentation (`GET /docs`)**: Open `http://localhost:3016/docs` in your browser and test all endpoints directly from the Swagger UI (Try it out).

***

### 3.2.1 Batch Parallel Scraping of Multiple URLs (`POST /scrape/batch`)

Specify multiple web page URLs and have the server fetch them in parallel at high speed while maintaining per-domain throttling.

* **Request (POST)**:

GXP13

* **Response example**:

GXP14

***

### 3.3 Interactive Browser Automation (`POST /browser/action` or `POST /action`)

Opens a web page and sequentially executes a series of actions such as clicking, text input, scrolling, waiting, and taking screenshots to get the final result. It supports both **one-shot execution** and **stateful multi-turn interactive sessions (`sessionId`)** where you proceed while chatting.

#### ① One-shot execution (single completion)

* **Request (POST)**:

GXP15

GXP16

#### ② Stateful multi-turn interaction session (for chat-type UI)

* **Turn 1 (create session & open the screen)**:

GXP17

*(The response returns `"sessionId": "sess_a1b2c3d4"`)*

* **Turn 2 (continue operating on the still-open screen)**:

GXP18

* **Turn 3 (end session & cleanup)**:

GXP19

* **Turn 3** *(If there is no operation for 5 minutes, it also safely frees memory via an automatic timeout.)*

***

### 3.4 Integrated Deep Search (`POST /search`) & Web Search (`POST /search/web`)

* **Deep Search Request (`POST /search`)**:

GXP20

* **When obtaining in HTML format**:

GXP21

* **When extracting only important highlights (token-saving mode)**:

GXP22

* **Web Search Request (`POST /search/web`)**:

GXP23

***

### 3.4.1 Sitemap Discovery (`POST /map`)

Discovers the `sitemap.xml` and internal links for a specified domain, then extracts a list of all URLs on the site.

* **Request**:

GXP24

***

### 3.4.2 Recursive Crawl of Subpages (`POST /crawl` & `POST /crawl/stream`)

Recursively traverses descendant pages from the specified URL and collectively collects Markdown/HTML/images/structured data from multiple pages. Supports Glob/wildcard filtering via `includePatterns` / `excludePatterns`.

* **Request (batch acquisition)**:

GXP25

* **SSE streaming (`POST /crawl/stream`)**: Streams Server-Sent Events in real time as each page is fetched (`start` -> `page` -> `done`).

***

### 3.5 Image / Video / News / Chiebukuro / Suggest Search

* **Image Search (`POST /search/image`)**: `{ "query": "富士山", "limit": 10 }`
* **Video Search (`POST /search/video`)**: `{ "query": "簡単 レシピ", "limit": 10 }`
* **News Search (`POST /search/news`)**: `{ "query": "AI ロボット", "limit": 10 }`
* **Chiebukuro Q\&A (`POST /search/chiebukuro`)**: `{ "query": "プログラミング 初心者", "limit": 10, "status": "solved" }`
* **Keyword Suggest (`POST /search/suggest`)**: `{ "query": "天気", "limit": 10 }`

***

### 3.6 Train Route Search (`POST /transit/route`)

* **Request**:

GXP26

* **Response example**:

GXP27

***

### 3.7 Japan Nationwide Weather Forecasts (`POST /weather` / `GET /weather` / `GET /weather/:city`)

  **This function directly parses the official JMA open-data API format (and the livedoor Weather-compatible format) to fully automatically retrieve detailed weather data for today, tomorrow, and day after tomorrow across Japan.

#### Features & Advantages

* **Fully autonomous, directly connected to the API (zero dependencies)**: Fetches and parses data directly from 気象庁's official CDN (`jma.go.jp`).

* **Smart automatic resolution of 1,805 Japanese municipalities**: Includes the official JMA area definitions (`area.json`) and automatically resolves city/ward/town/village name (e.g. "Tendo City", "Karuizawa", "Hakone", "Urayasu", "Beppu") or famous place name to the assigned meteorological station ID in 0 ms. It also supports input without prefecture name.

* **AI-agent–friendly structured data**: Automatically retrieves, in a clean JSON, 3-day weather descriptions, wind and wave information, highest/lowest temperatures (°C) expectations, precipitation probability by period (0–6h, 6–12h, 12–18h, 18–24h), and the official weather outlook text (headline and no weather figures).

* **Ultra-fast response with LRU cache**: Built-in 30-minute in-memory LRU cache prevents needless duplicate calls to JMA servers.

* **Request (POST)**:

GXP28

* **GET request**: `GET /weather?city=軽井沢&days=2` or `GET /weather/箱根`
* **Response example**:

GXP29

***

### 3.8 Yahoo! Real-Time Search & Trends (`POST /search/realtime` / `POST /search/trend`)

* **Real-time Search (`POST /search/realtime`)**: `{ "query": "イベント名", "sort": "popular", "limit": 20, "page": 1 }`
  * `sort`: `"recent"` (newest-first, default) or `"popular"` (hot / engagement-first)
  * Each post is automatically tagged with `publishedTime` (ISO 8601 string), `author` (username + @account), and `siteName: "X (Twitter)"` in a unified format.
* **Trending Now (`POST /search/trend`)**: `{ "limit": 20 }`

***

### 3.9 Sitemap & Crawl (`POST /map` / `POST /crawl`)

* **Sitemap (`POST /map`)**: `{ "url": "https://example.com", "limit": 200 }`
* **Recursive crawl (`POST /crawl`)**: `{ "url": "https://example.com/docs", "maxPages": 10 }`

***

## 4. Security & Architecture

### 4.1 Distroless Container Design

* **Base image**: `gcr.io/distroless/cc-debian12`
* **No shell, no package manager**: The container has no `/bin/sh`, `apt`, or `curl`, leaving an attacker no shell to take.
* **Least-privilege design**: Designed to run as a non-root user, safely isolated and runnable in standard container environments such as Docker, Podman, Kubernetes.

### 4.2 Security & Performance Features

* **🔒 Multi-Layer SSRF & DNS Rebinding Protection**:
  * Blocks internal access to private IP (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8`, etc.), CGNAT (`100.64.0.0/10`), IPv6 special addresses, and cloud metadata IP (`169.254.169.254`).
  * Does a pre-resolution with `dns.promises.lookup` and blocks public "DNS Rebinding attacks" at connection time instead of domain spoofing.

* **⚡ Single-Flight Cache (In-flight Deduplication)**:
  * When concurrent requests come in for the same URL, share the Promise and aggregate external transmission. It prevents Thundering Herd (cache stampede) and protects the external server and local resources.

* **🚦 Browser Concurrency Limit (Concurrency Control)**:
  * `SimpleSemaphore` safely controls the maximum number of concurrent Chromium processes (`MAX_CONCURRENT_BROWSERS`, default 5). Prevents CPU/RAM exhaustion on the server.

* **🔒 Timing-Safe Auth & Browser Session Ownership**:
  * API-key comparison uses `crypto.timingSafeEqual` + SHA-256 (constant-time comparison) preventing timing attacks against the key.
  * Multi-turn browser sessions are cryptographically bound to the owning token, preventing session-hijacking by other parties.

* **🔨 Safe Switch for Arbitrary JavaScript Execution (`ALLOW_BROWSER_EVALUATE`)**:
  * The `ALLOW_BROWSER_EVALUATE=false` or `SAFE_BROWSER_MODE=true` environment variables can disable/lock down explicit `evaluate` script execution in `/browser/action`.

* **📐 Shared Zod Schema & Full OpenAPI 3.0 Generation**:
  * Input validation with Zod schema is shared between REST and MCP.
  * `/openapi.json` is **100% dynamically generated** from the code's Zod schema to the OpenAPI 3.0 spec, fully avoiding documentation drift.
  * Error responses are shaped for an AI agent to repare or decide autonomously, e.g. JSON is `{ "error": "...", "code": "SSRF_BLOCKED", "status": 403, "retryable": }`.

* **⏱️ Jitter Throttling & True LRU Cache**:
  * Throttles excessive repeated access to the same domain with 150ms + Jitter (0–100ms variation).
  * The 15–30 minute true LRU (refreshed on access) cache and the every-10-minute periodic TTL sweep completely prevent memory leaks.

***

## 5. Acknowledgments

`Sora` is built with the support of the following outstanding soluble open-source projects, public services, public APIs, and library authors. We are truly grateful.

### 🗾 Data Sources & Inspirations

* **JMA (Japan Meteorological Agency) open data**: [jma.go.jp](https://www.jma.go.jp/)
  * We deeply thank you for making high-quality weather forecasts, disaster-prevention data, and daily area definitions (1,800+ locations across Japan) openly available.
* **livedoor Weather API format**: [tsukumijima/weather-api](https://github.com/tsukumijima/weather-api) / [weather.jp](https://weather.tsukumijima.net/)
  * We thank the project for its clear schema design and long-standing community contribution to the Compatible Weather API.
* **Yahoo Japan Search MCP**: [mouseos/Yahoo-Japan-Search-MCP](https://github.com/mouseos/Yahoo-Japan-Search-MCP)
  * Many thanks for the MCP implementation for image / video / news / Chiebukuro / Suggest Search on Yahoo! JAPAN.
* **norikae-guity** (train routing): [tysonwu/norikae-mcp](https://github.com/tysonwu/norikae-mcp)
  * Many thanks for the design and implementation of the transfer-search and route logic via Yahoo Japan route scraping.

### ittesting
 Center Open-Source Tools & Libraries

* **[Hono](https://github.com/honojs/hono)**, created by [@yusukebe](https://github.com/yusukebe) — flexible, modern, cross-environment web framework + MCP integration
* **[Puppeteer](https://pptr.dev/)** (Google Chrome Team) — headless Chromium control & stealth automation
* **[Readability](https://github.com/mozilla/readability)** (Mozilla) — reader-mode article-body extraction engine
* **[Cheerio](https://cheerio.js.org/)** (cheeriojs team) — high-speed DOM parsing & metadata extraction
* **[Turndown](https://github.com/mixmark-io/turndown)** ([Dom Christie](https://github.com/domchristie)) — HTML to Markdown converter
* **[LinkeDOM](https://github.com/WebReflection/linkedom)** ([Andrea Giammarchi](https://github.com/WebReflection)) — very light in-memory DOM engine
* **[unpdf](https://github.com/unjs/unpdf)** (UnJS Team) — fast, small PDF text extraction
* **[Model Context Protocol SDK](https://github.com/modelcontextprotocol)** (Anthropic / MCP Team) — next-generation AI tool integration

***

## 6. Disclaimer

* **Non-official third-party tool**:
  * This software is developed for individual development, research, or own in-house use, and it is a third-party **unofficial** tool.
* **Trademarks**:
  * “Yahoo!” and “Yahoo! JAPAN,” and each service name are trademarks or registered trademarks of **LY Corporation** (formerly Yahoo Japan Corporation). This project is not related to Yahoo Japan Corporation in any way.
* **Compliance with Terms and Laws**:
  * When accessing each external service (Yahoo! JAPAN, JMA, etc.), you must support the user's own terms/ros, robots.txt, and applicable laws, and you are responsible for using it without **excessive load**.
* **Limitation of Liability**:
  * The developers of this project are not liable for any damage or loss from using this software (including blocking from external services, and the integrity, correctness, or freshness of data).

***

## 7. License

This software is licensed under the **[Business Source License 1.1 (BSL 1.1 / BUSL-1.1)](LICENSE)**.

* **Free unlimited use**:
  * Personal / non-commercial / academic use
  * Self-hosted internal use for your company / organization (e.g., a backend that powers your internal product or internal tools)
  * Modify, fork, or share the source code internally
* **Restrictions**:
  * Selling or redistributing the software or its derivatives as a paid cloud, API, scraping/search API, or managed service for third parties.
* **Change Date (open-source change date)**:
  * Automatically converts to the full **MIT License** on **1 August 2020** (or earlier).

Details: [LICENSE](LICENSE)

Copyright (c) 2026 ikeno
A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
3Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides comprehensive search capabilities including web search, content extraction, news search, academic search, and AI-powered multi-source research. Enables natural language access to web content and research through a production-ready MCP server.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Production-ready MCP server for AI agents — web search, content extraction, screenshots, weather, finance, email validation, translation, and IP geolocation.
    10
    6
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    A comprehensive MCP server providing 15 web tools including search, scraping, screenshots, SEO audits, and DNS/SSL checks through a single installation. It delivers clean, LLM-optimized outputs so AI agents can focus on reasoning rather than parsing raw HTML.
    15
    20
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    An APAC-native web scraping API for AI agents that provides tools for scraping, crawling, searching, and extracting structured data from websites, directly usable from MCP-compatible clients like Claude Desktop, Cursor, and Windsurf.
    7
    12
    MIT

View all related MCP servers

Related MCP Connectors

  • Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.

  • MCP server for Japan geodata: cadastral lot numbers (chiban) and reverse geocoding, for AI agents.

  • LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.

View all MCP Connectors

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/ikenokazuki/Sora'

If you have feedback or need assistance with the MCP directory API, please join our Discord server