nextbillion-mcp 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +29 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20403,9 +20403,20 @@ function toError(value) {
20403
20403
 
20404
20404
  // src/config.ts
20405
20405
  import { tmpdir } from "node:os";
20406
- import { join } from "node:path";
20406
+ import { isAbsolute, join } from "node:path";
20407
+ function resolveImageDir(env = process.env) {
20408
+ const raw = env.NBAI_IMAGE_DIR?.trim();
20409
+ if (!raw) return {};
20410
+ if (raw.toLowerCase() === "tmp") return { dir: join(tmpdir(), "nextbillion-mcp") };
20411
+ if (!isAbsolute(raw)) {
20412
+ return {
20413
+ warning: `NBAI_IMAGE_DIR must be an absolute path or "tmp", got "${raw}"; map images will not be saved`
20414
+ };
20415
+ }
20416
+ return { dir: raw };
20417
+ }
20407
20418
  function imageOutputDir(env = process.env) {
20408
- return env.NBAI_IMAGE_DIR?.trim() || join(tmpdir(), "nextbillion-mcp");
20419
+ return resolveImageDir(env).dir;
20409
20420
  }
20410
20421
  var DEFAULT_BASE_URL = "https://api.nextbillion.io";
20411
20422
  var DEFAULT_TIMEOUT_MS = 3e4;
@@ -21002,7 +21013,7 @@ var Schema8 = strictObject({
21002
21013
  var distanceMatrix = {
21003
21014
  name: "distance_matrix",
21004
21015
  title: "Distance Matrix",
21005
- description: 'Compute travel distance (meters) and duration (seconds) for every origin-to-destination pair in one call; one row per origin with one element per destination, in input order. Always prefer this over repeated directions calls for multiple pairs. Parameters: origins, destinations (arrays of {latitude, longitude}, required); optional mode, service ("fast" default: up to 1000x1000 points; "flexible": the options below, max 50x50), route_type, departure_time, avoid (soft), exclude (strict), honor_restrictions, route_failed_prompt (unroutable pairs return -1 instead of 0), truck options: truck_size_cm {height, width, length}, truck_weight_kg, truck_axle_load, hazmat_type, emission_class, cross_border. Example: {"origins": [{"latitude": 1.29, "longitude": 103.85}], "destinations": [{"latitude": 1.35, "longitude": 103.99}, {"latitude": 1.3, "longitude": 103.77}], "route_failed_prompt": true}',
21016
+ description: 'Compute travel distance (meters) and duration (seconds) for every origin-to-destination pair in one call; one row per origin with one element per destination, in input order. Use it instead of repeated directions calls when several pairs are needed. Parameters: origins, destinations (arrays of {latitude, longitude}, required); optional mode, service ("fast" default: up to 1000x1000 points; "flexible": the options below, max 50x50), route_type, departure_time, avoid (soft), exclude (strict), honor_restrictions, route_failed_prompt (unroutable pairs return -1 instead of 0), truck options: truck_size_cm {height, width, length}, truck_weight_kg, truck_axle_load, hazmat_type, emission_class, cross_border. Example: {"origins": [{"latitude": 1.29, "longitude": 103.85}], "destinations": [{"latitude": 1.35, "longitude": 103.99}, {"latitude": 1.3, "longitude": 103.77}], "route_failed_prompt": true}',
21006
21017
  inputSchema: Schema8,
21007
21018
  annotations: READ_ONLY,
21008
21019
  async run(args, nb) {
@@ -21329,13 +21340,18 @@ async function fetchImageResult(nb, path, query, caption, args, filePrefix = "ma
21329
21340
  };
21330
21341
  }
21331
21342
  async function saveImage(data, prefix, ext) {
21343
+ const dir = imageOutputDir();
21344
+ if (!dir) return void 0;
21332
21345
  try {
21333
- const dir = imageOutputDir();
21334
21346
  await mkdir(dir, { recursive: true });
21335
21347
  const hash = createHash("sha1").update(data).digest("hex").slice(0, 8);
21336
21348
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\..+/, "");
21337
21349
  const filePath = join2(dir, `${prefix}-${stamp}-${hash}.${ext === "jpg" ? "jpg" : ext}`);
21338
- await writeFile(filePath, data);
21350
+ try {
21351
+ await writeFile(filePath, data, { flag: "wx" });
21352
+ } catch (error2) {
21353
+ if (error2.code !== "EEXIST") throw error2;
21354
+ }
21339
21355
  return filePath;
21340
21356
  } catch (error2) {
21341
21357
  logError("Could not save rendered image to disk", error2);
@@ -21380,7 +21396,7 @@ var Schema11 = strictObject({
21380
21396
  var staticMapImage = {
21381
21397
  name: "static_map_image",
21382
21398
  title: "Static Map Image",
21383
- description: 'Render a static map image centered on a location, with optional markers and line/polygon overlays; returns the image inline and also saves it to a local file (path in the result text) for clients that cannot display images. For a map auto-fitted to a route or to overlays, use static_route_map. Parameters: center {latitude, longitude} and zoom (0-22) (required); optional markers (array of {latitude, longitude, color, icon_url, anchor, scale}), paths (array of {points [{latitude, longitude}] OR geojson_coordinates [[longitude, latitude], ...], stroke_color, stroke_width, fill_color for a filled polygon}), width, height (default 512), style (streets | light | dark | hybrid), format (png | jpg | webp), retina. Example: {"center": {"latitude": 48.8566, "longitude": 2.3522}, "zoom": 14, "markers": [{"latitude": 48.8584, "longitude": 2.2945, "color": "red"}], "paths": [{"points": [{"latitude": 48.85, "longitude": 2.29}, {"latitude": 48.86, "longitude": 2.30}], "stroke_color": "green"}]}',
21399
+ description: 'Render a static map image centered on a location, with optional markers and line/polygon overlays; returns the image inline and, if NBAI_IMAGE_DIR is set, also saves it as a file (path in the result text). For a map auto-fitted to a route or to overlays, use static_route_map. Parameters: center {latitude, longitude} and zoom (0-22) (required); optional markers (array of {latitude, longitude, color, icon_url, anchor, scale}), paths (array of {points [{latitude, longitude}] OR geojson_coordinates [[longitude, latitude], ...], stroke_color, stroke_width, fill_color for a filled polygon}), width, height (default 512), style (streets | light | dark | hybrid), format (png | jpg | webp), retina. Example: {"center": {"latitude": 48.8566, "longitude": 2.3522}, "zoom": 14, "markers": [{"latitude": 48.8584, "longitude": 2.2945, "color": "red"}], "paths": [{"points": [{"latitude": 48.85, "longitude": 2.29}, {"latitude": 48.86, "longitude": 2.30}], "stroke_color": "green"}]}',
21384
21400
  inputSchema: Schema11,
21385
21401
  annotations: READ_ONLY,
21386
21402
  async run(args, nb) {
@@ -21429,7 +21445,7 @@ var ENCODED_CHAR_BUDGETS = [4e3, 3e3, 2e3, 1200, 600, 200];
21429
21445
  var staticRouteMap = {
21430
21446
  name: "static_route_map",
21431
21447
  title: "Static Route Map",
21432
- description: 'Render a static map auto-fitted to a route and/or overlays: a route from directions, and/or lines and filled polygons such as isochrone contours; very long geometry is simplified automatically to fit the map API URL limit (distances unaffected). Returns the image inline and also saves it to a local file (path in the result text). Parameters: at least one of encoded_polyline (the geometry string from directions, preferred), route_points (array of {latitude, longitude}) or paths (array of {points OR geojson_coordinates [[longitude, latitude], ...], stroke_color, stroke_width, fill_color}); optional markers (array of {latitude, longitude, color, icon_url, anchor, scale}), stroke_color, stroke_width (route line), padding, width, height, style, format, retina. Example (isochrone contours) - Example: {"paths": [{"geojson_coordinates": [[-122.42, 37.77], [-122.40, 37.78], [-122.41, 37.79], [-122.42, 37.77]], "fill_color": "rgba(29,78,216,0.35)", "stroke_color": "#1d4ed8"}], "markers": [{"latitude": 37.7749, "longitude": -122.4194, "color": "red"}]}',
21448
+ description: 'Render a static map auto-fitted to a route and/or overlays: a route from directions, and/or lines and filled polygons such as isochrone contours; very long geometry is simplified automatically to fit the map API URL limit (distances unaffected). Returns the image inline and, if NBAI_IMAGE_DIR is set, also saves it as a file (path in the result text). Parameters: at least one of encoded_polyline (the geometry string from directions, preferred), route_points (array of {latitude, longitude}) or paths (array of {points OR geojson_coordinates [[longitude, latitude], ...], stroke_color, stroke_width, fill_color}); optional markers (array of {latitude, longitude, color, icon_url, anchor, scale}), stroke_color, stroke_width (route line), padding, width, height, style, format, retina. Example (isochrone contours) - Example: {"paths": [{"geojson_coordinates": [[-122.42, 37.77], [-122.40, 37.78], [-122.41, 37.79], [-122.42, 37.77]], "fill_color": "rgba(29,78,216,0.35)", "stroke_color": "#1d4ed8"}], "markers": [{"latitude": 37.7749, "longitude": -122.4194, "color": "red"}]}',
21433
21449
  inputSchema: Schema12,
21434
21450
  annotations: READ_ONLY,
21435
21451
  async run(args, nb) {
@@ -21669,7 +21685,7 @@ function extractApiMessage(bodyText) {
21669
21685
  }
21670
21686
 
21671
21687
  // src/index.ts
21672
- var pkg = true ? { version: "0.2.0" } : createRequire(import.meta.url)("../package.json");
21688
+ var pkg = true ? { version: "0.2.2" } : createRequire(import.meta.url)("../package.json");
21673
21689
  function main() {
21674
21690
  const args = process.argv.slice(2);
21675
21691
  if (args.includes("--version") || args.includes("-v")) {
@@ -21686,7 +21702,8 @@ Environment variables:
21686
21702
  NBAI_API_KEY (required) NextBillion.ai API key
21687
21703
  NBAI_BASE_URL (optional) API base URL, default https://api.nextbillion.io
21688
21704
  NBAI_TIMEOUT_MS (optional) per-request timeout, default 30000
21689
- NBAI_IMAGE_DIR (optional) directory for saved map images, default <tmp>/nextbillion-mcp
21705
+ NBAI_IMAGE_DIR (optional) also save rendered maps to this absolute directory, or
21706
+ "tmp" for the OS temp dir; unset = nothing is written to disk
21690
21707
  `
21691
21708
  );
21692
21709
  return;
@@ -21707,6 +21724,9 @@ Environment variables:
21707
21724
  baseUrl: config2.baseUrl,
21708
21725
  timeoutMs: config2.timeoutMs
21709
21726
  });
21727
+ const imageDir = resolveImageDir();
21728
+ if (imageDir.warning) logError(imageDir.warning);
21729
+ else if (imageDir.dir) logInfo(`rendered map images will also be saved to ${imageDir.dir}`);
21710
21730
  const handle = serveStdio(() => buildServer(nb, pkg.version));
21711
21731
  logInfo(`${SERVER_NAME} ${pkg.version} listening on stdio`);
21712
21732
  const shutdown = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextbillion-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "MCP server exposing NextBillion.ai location APIs (geocoding, places, routing, maps) as tools for AI agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",