JAXA Earth API for JavaScript also lets you develop an MCP (Model Context Protocol) for integration with generative AI. In this tutorial, we will build an MCP using the Streamable HTTP method. This means you can also run the MCP server (the source code below) and the MCP client (such as Claude Desktop) on separate machines and have them work across a network.
Note that the source code below omits security measures such as HTTPS support and user authentication, so it is intended for use within a trusted local network. To publish it on the internet so that an unspecified number of users can access it, separate security measures are required.
This explanation assumes that you understand the STDIO method, so for anything unclear please refer to the STDIO method tutorial.
The content of this explanation has been verified to operate in the following environment (as of 2026.5).
Download the complete source code from the link below, extract the ZIP file, and save it to any folder (hereinafter referred to as the "project root").
Complete MCP sample code (Japanese Version Only)
The sample code includes the following files.
- package.json //A Node.js file describing information about this package
- tsconfig.json //TypeScript configuration file
- src/
- index.ts //File required to run the MCP
- createMcpServer.ts //File for the function that creates the McpServer
- test.ts //File for module unit testing
- getElevationValue.ts //Function that returns elevation data values via the JAXA Earth API
- getElevationImage.ts //Function that returns an elevation data image via the JAXA Earth API
- getCatalogList.ts //Function that returns the catalog files available via the JAXA Earth API
- jaxa.earth.esm.js //Module file of the JAXA Earth API
- jaxa.earth.esm.d.ts //Type definition file of the JAXA Earth API module
The index.ts file contains the code for running as an MCP server.
As a difference from the STDIO method, the part that creates the McpServer is separated out as createMcpServer.ts.
The part that defines the tool descriptions and the details of the accepted arguments is the same.
The server startup part of the index.ts file looks like the following for the Streamable HTTP method.
For the const host = part, specify the IP address of the machine that runs this source code.
//Load the modules for Streamable HTTP
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import cors from "cors";
import type { Request, Response } from "express";
//(omitted in between)
const port = "3001";
// const host = "localhost"; //For when a client such as Claude Desktop runs on the same machine.
const host = "192.168.xxx.xxx"; //For when a client such as Claude Desktop runs on a separate machine, specify the IP address of this machine.
const app = createMcpExpressApp({ host });
app.use(cors());
app.all("/mcp", async (req: Request, res: Response) => {
//Display the content of the request from the generative AI in the console.
console.log(req.body);
//Since this sample has only stateless functionality, it does not hold a session and starts a new one each time.
//When building stateful functionality such as user authentication, a separate implementation for managing sessions is required.
const server = createMcpServer();
const transport = new StreamableHTTPServerTransport();
res.on("close", () => {
transport.close().catch(() => { });
server.close().catch(() => { });
});
try {
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
} catch (error) {
console.error("MCP error:", error);
if (!res.headersSent) {
res.status(500).json({
jsonrpc: "2.0",
error: { code: -32603, message: "Internal server error" },
id: null,
});
}
}
});
const httpServer = app.listen(port, (err) => {
if (err) {
console.error("Failed to start server:", err);
process.exit(1);
}
console.log(`MCP server listening on http://${host}:${port}/mcp`);
});
//(rest omitted)
Open a terminal (command prompt) in the project root and run the following to install the required modules.
npm i
Continue by running the following in the terminal. The TypeScript files are compiled and the MCP server is started. As for npm usage, start can also be written in the shortened form npm start.
npm run start
If the following message appears, the MCP server has started successfully.
> jaxa-earth-api@1.0.0 start
> npm run build && node ./build/index.js
> jaxa-earth-api@1.0.0 build
> tsc
MCP server listening on http://192.168.xxx.xxx:3001/mcp
In the terminal, the MCP server stays running, so to stop it press [Ctrl] + C.
As with the STDIO method, open the claude_desktop_config.json file and write the following.
{
"mcpServers": {
"jaxa-earth-api": {
"command": "npx",
"args": [
"mcp-remote",
"http://192.168.xxx.xxx:3001/mcp",
"--allow-http"
]
}
}
}
As for the URL part, if you set const host = "localhost"; in index.ts, write "http://localhost:3001/mcp".
Claude Desktop does not support adding a remote MCP running on localhost or within a LAN via a custom connector (as of 2026.5), so we use npx and mcp-remote. Since mcp-remote is installed automatically when npx runs, no special installation work is required.
As with the STDIO method, restart Claude Desktop, and if jaxa-earth-api appears in the connectors, the MCP server connection is complete.
Try asking a question in the chat box. As with the STDIO method, the generative AI answers by making full use of JAXA Earth API data!
With the STDIO method and the Streamable HTTP method, you could return text and image responses to the generative AI. By using MCP Apps, you can also return a web application as the UI.