tak-server-mcp-skyfi
Version:
Model Context Protocol (MCP) server for TAK Server integration with geospatial support
251 lines • 10.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateDistanceTool = void 0;
const turf = __importStar(require("@turf/turf"));
exports.calculateDistanceTool = {
name: 'tak_calculate_distance',
description: 'Calculate distances between entities, points, or coordinates',
category: 'geospatial',
requiresAuth: true,
requiresWrite: false,
inputSchema: {
type: 'object',
properties: {
from: {
type: 'object',
properties: {
entityId: {
type: 'string',
description: 'Entity ID to calculate distance from'
},
coordinates: {
type: 'array',
items: { type: 'number' },
minItems: 2,
maxItems: 2,
description: 'Coordinates [lat, lon] to calculate distance from'
}
},
description: 'Starting point (provide either entityId or coordinates)'
},
to: {
type: 'object',
properties: {
entityId: {
type: 'string',
description: 'Entity ID to calculate distance to'
},
coordinates: {
type: 'array',
items: { type: 'number' },
minItems: 2,
maxItems: 2,
description: 'Coordinates [lat, lon] to calculate distance to'
}
},
description: 'Destination point (provide either entityId or coordinates)'
},
units: {
type: 'string',
enum: ['meters', 'kilometers', 'miles', 'nauticalmiles'],
default: 'meters',
description: 'Units for distance measurement'
},
method: {
type: 'string',
enum: ['greatcircle', 'euclidean'],
default: 'greatcircle',
description: 'Calculation method'
},
batch: {
type: 'array',
items: {
type: 'object',
properties: {
entityId: { type: 'string' },
coordinates: {
type: 'array',
items: { type: 'number' },
minItems: 2,
maxItems: 2
}
}
},
description: 'Calculate distances from "from" point to multiple destinations'
}
},
oneOf: [
{
required: ['from', 'to']
},
{
required: ['from', 'batch']
}
]
},
handler: async (context) => {
const { takClient, params, logger } = context;
try {
// Helper function to get coordinates
const getCoordinates = async (point) => {
if (point.coordinates) {
return point.coordinates;
}
if (point.entityId) {
const entities = await takClient.getEntities();
const entity = entities.find(e => e.uid === point.entityId);
if (!entity) {
throw new Error(`Entity ${point.entityId} not found`);
}
return [entity.location.lat, entity.location.lon];
}
throw new Error('Either entityId or coordinates must be provided');
};
// Get from coordinates
const fromCoords = await getCoordinates(params.from);
const fromPoint = turf.point([fromCoords[1], fromCoords[0]]); // turf uses [lon, lat]
// Handle single distance calculation
if (params.to) {
const toCoords = await getCoordinates(params.to);
const toPoint = turf.point([toCoords[1], toCoords[0]]);
const distance = turf.distance(fromPoint, toPoint, { units: params.units || 'meters' });
const bearing = turf.bearing(fromPoint, toPoint);
// Calculate additional info
const midpoint = turf.midpoint(fromPoint, toPoint);
const travelTime = calculateTravelTime(distance, params.units || 'meters');
return {
success: true,
data: {
from: {
entityId: params.from.entityId,
coordinates: fromCoords
},
to: {
entityId: params.to.entityId,
coordinates: toCoords
},
distance: distance,
units: params.units || 'meters',
bearing: bearing,
backBearing: (bearing + 180) % 360,
midpoint: [midpoint.geometry.coordinates[1], midpoint.geometry.coordinates[0]],
estimatedTravelTime: travelTime
},
metadata: {
timestamp: new Date().toISOString(),
calculationMethod: params.method || 'greatcircle'
}
};
}
// Handle batch distance calculations
if (params.batch) {
const results = await Promise.all(params.batch.map(async (destination) => {
try {
const toCoords = await getCoordinates(destination);
const toPoint = turf.point([toCoords[1], toCoords[0]]);
const distance = turf.distance(fromPoint, toPoint, { units: params.units || 'meters' });
const bearing = turf.bearing(fromPoint, toPoint);
return {
to: {
entityId: destination.entityId,
coordinates: toCoords
},
distance: distance,
bearing: bearing
};
}
catch (error) {
return {
to: destination,
error: error instanceof Error ? error.message : 'Failed to calculate distance'
};
}
}));
// Sort by distance
const validResults = results.filter(r => !r.error);
validResults.sort((a, b) => a.distance - b.distance);
return {
success: true,
data: {
from: {
entityId: params.from.entityId,
coordinates: fromCoords
},
distances: results,
nearest: validResults[0],
farthest: validResults[validResults.length - 1],
units: params.units || 'meters'
},
metadata: {
timestamp: new Date().toISOString(),
calculationMethod: params.method || 'greatcircle',
totalCalculations: params.batch.length,
successfulCalculations: validResults.length
}
};
}
}
catch (error) {
logger.error('Failed to calculate distance:', error);
return {
success: false,
error: {
code: 'TAK_CALCULATION_ERROR',
message: 'Failed to calculate distance',
details: error instanceof Error ? error.message : 'Unknown error'
}
};
}
}
};
// Helper function to estimate travel time based on distance
function calculateTravelTime(distance, units) {
// Convert to meters if needed
let distanceInMeters = distance;
if (units === 'kilometers')
distanceInMeters = distance * 1000;
if (units === 'miles')
distanceInMeters = distance * 1609.34;
if (units === 'nauticalmiles')
distanceInMeters = distance * 1852;
return {
walking: Math.round(distanceInMeters / 1.4 / 60), // 5 km/h
vehicle: Math.round(distanceInMeters / 16.67 / 60), // 60 km/h
helicopter: Math.round(distanceInMeters / 55.56 / 60), // 200 km/h
units: 'minutes'
};
}
//# sourceMappingURL=calculate-distance.js.map