DEV Community

atu ino
atu ino

Posted on Edited on

Japan Intel MCP: 8 Tools for Japanese Public Data

Most "global intelligence" MCP servers are built on Western data sources. If you want your agent to know what is happening in Japan right now, the options were thin — so I built one, and released it on the official MCP registry.

What it does

japan-intel-mcp exposes eight read-only tools over free, keyless Japanese public data:

Tool What you get Source
japan_earthquakes Epicenter, magnitude, max intensity, depth Japan Meteorological Agency
japan_weather_warnings Active advisories by prefecture JMA
japan_weather_overview Narrative forecast text JMA
japan_weekly_forecast Temperatures + precipitation probability JMA
japan_typhoons Monitored typhoons JMA
japan_edinet_filings Corporate regulatory disclosures EDINET
japan_postal_lookup Postal code to address (kanji + kana) zipcloud
japan_watch_summary One-call cross-source snapshot JMA

No API key. No account. No paid tier. Every source is public.

Install

pip install japan-intel-mcp
japan-intel-mcp   # stdio MCP
Enter fullscreen mode Exit fullscreen mode

Or grab the .mcpb bundle from the v0.2.0 release.

It is registered on the official registry as io.github.atushi1841/japan-intel-mcp, so it is discoverable from any MCP client.

The design decision that matters: never silently lose a source

Every response is wrapped in an envelope:

{
  "retrieved_at": "2026-10-12T01:30:00+00:00",
  "sources": ["https://www.jma.go.jp/bosai/quake/data/list.json"],
  "data_gaps": [],
  "data": [ ... ]
}
Enter fullscreen mode Exit fullscreen mode

That data_gaps array is the whole point. When an upstream API is down, the field says so explicitly instead of returning an empty list that an agent would confidently interpret as "nothing happened."

An agent that gets [] will tell you there were no earthquakes. An agent that gets data_gaps: ["jma-quake: HTTP 503"] will tell you it could not check. Only one of those is honest.

Three bugs the data will hand you

Building this surfaced some traps worth documenting.

1. The weekly forecast splits data across series with different region names. The JMA feed returns multiple timeSeries — weather/wind/wave in one, precipitation probability in another, temperatures in a third. Worse, the area names differ between them: series[0] says "Tokyo Area" while series[1] says "Tokyo." Joining by area name silently breaks. Structuring by series instead.

2. The earthquake list includes quakes far from Japan. A magnitude 7.6 off Central America appears alongside domestic events. The tell is an empty maxIntensity field — nothing was felt in Japan. Filter on that, or you will report foreign earthquakes as Japanese.

3. Advisories are sometimes a list, sometimes a dict. The warning feed's warnings field changes shape. Calling .items() on the list variant raises AttributeError: 'list' object has no attribute 'keys'. Handle both.

Why keyless matters

The moment an MCP server needs an API key, your install funnel collapses: the user has to sign up, find the key, configure it, and hope it is still valid. Every source here is keyless, which means pip install genuinely is the whole setup.

Links

If you are building agents that need to reason about Japan — logistics, travel, supply chain, risk — the data is now one tool call away.


Data used in this post

The datasets behind this analysis are available on Apify (pay-per-result, free tier to start):


The datasets behind this analysis are available on Apify (pay-per-result, free tier to start):

A trap that only shows up after you publish

Building this surfaced a class of bug that is invisible until someone actually installs it. Four of them, all caught by installing the built wheel into a fresh virtualenv and starting it as a real MCP server.

1. show_banner=False is not optional for stdio. FastMCP prints a banner to stdout by default. On the stdio transport, stdout is the JSON-RPC stream — so the banner corrupts it and the client parses nothing. The server looks like it installs fine and then simply never responds. One line fixes it:

server.run(transport="stdio", show_banner=False)
Enter fullscreen mode Exit fullscreen mode

2. An entry point that points outside the package. Declaring mypkg-cli = "stdio_main:main" works in the repo and fails for every user, because stdio_main is not part of the distribution. Point entry points only at modules inside the package.

3. A missing __init__.py. The directory is not a package without it, and the build silently produces a wheel that imports nothing.

4. Two dependency universes. The bundle build wanted one MCP library and the container build wanted another. Unifying them on a single dependency is the only way both artifacts can work.

The lesson generalizes: build the wheel, install it into an empty environment, and start it. A green test suite in the development tree proves nothing about the artifact you actually ship.


Install via Smithery

Get this server installed in your AI client (Claude Desktop, Cursor, VS Code, etc.) via Smithery:

Enter fullscreen mode Exit fullscreen mode

This is an MCP server that provides structured Japanese market data to AI agents.

Top comments (0)