cli.js•28.6 kB
#!/usr/bin/env node
import{a as n}from"./chunk-W2DM2HDK.js";import{config as W}from"dotenv";import{resolve as z}from"path";import qe from"yargs";import{hideBin as Ve}from"yargs/helpers";import{z as f}from"zod";import{Client as Z,Language as Y}from"@googlemaps/google-maps-services-js";import U from"dotenv";U.config();function h(o){let e=o?.response?.data?.error_message,r=o?.response?.status;return e?`${e} (HTTP ${r})`:o instanceof Error?o.message:String(o)}var R=class{constructor(e){this.defaultLanguage=Y.en;if(this.client=new Z({}),this.apiKey=e||process.env.GOOGLE_MAPS_API_KEY||"",!this.apiKey)throw new Error("Google Maps API Key is required")}async searchNearbyPlaces(e){let r={location:e.location,radius:e.radius||1e3,keyword:e.keyword,opennow:e.openNow,language:this.defaultLanguage,key:this.apiKey};try{let s=(await this.client.placesNearby({params:r})).data.results;return e.minRating&&(s=s.filter(i=>(i.rating||0)>=(e.minRating||0))),s}catch(t){throw n.error("Error in searchNearbyPlaces:",t),new Error(`Failed to search nearby places: ${h(t)}`)}}async getPlaceDetails(e){try{return(await this.client.placeDetails({params:{place_id:e,fields:["name","rating","formatted_address","opening_hours","reviews","geometry","formatted_phone_number","website","price_level","photos"],language:this.defaultLanguage,key:this.apiKey}})).data.result}catch(r){throw n.error("Error in getPlaceDetails:",r),new Error(`Failed to get place details for ${e}: ${h(r)}`)}}async geocodeAddress(e){try{let r=await this.client.geocode({params:{address:e,key:this.apiKey,language:this.defaultLanguage}});if(r.data.results.length===0)throw new Error(`No location found for address: "${e}"`);let t=r.data.results[0],s=t.geometry.location;return{lat:s.lat,lng:s.lng,formatted_address:t.formatted_address,place_id:t.place_id}}catch(r){throw n.error("Error in geocodeAddress:",r),new Error(`Failed to geocode address "${e}": ${h(r)}`)}}parseCoordinates(e){let r=e.split(",").map(t=>parseFloat(t.trim()));if(r.length!==2||isNaN(r[0])||isNaN(r[1]))throw new Error(`Invalid coordinate format: "${e}". Please use "latitude,longitude" format (e.g., "25.033,121.564"`);return{lat:r[0],lng:r[1]}}async getLocation(e){return e.isCoordinates?this.parseCoordinates(e.value):this.geocodeAddress(e.value)}async geocode(e){try{let r=await this.geocodeAddress(e);return{location:{lat:r.lat,lng:r.lng},formatted_address:r.formatted_address||"",place_id:r.place_id||""}}catch(r){throw n.error("Error in geocode:",r),new Error(`Failed to geocode address "${e}": ${h(r)}`)}}async reverseGeocode(e,r){try{let t=await this.client.reverseGeocode({params:{latlng:{lat:e,lng:r},language:this.defaultLanguage,key:this.apiKey}});if(t.data.results.length===0)throw new Error(`No address found for coordinates: (${e}, ${r})`);let s=t.data.results[0];return{formatted_address:s.formatted_address,place_id:s.place_id,address_components:s.address_components}}catch(t){throw n.error("Error in reverseGeocode:",t),new Error(`Failed to reverse geocode coordinates (${e}, ${r}): ${h(t)}`)}}async calculateDistanceMatrix(e,r,t="driving"){try{let i=(await this.client.distancematrix({params:{origins:e,destinations:r,mode:t,language:this.defaultLanguage,key:this.apiKey}})).data;if(i.status!=="OK")throw new Error(`Distance matrix calculation failed with status: ${i.status}`);let c=[],a=[];return i.rows.forEach(g=>{let p=[],y=[];g.elements.forEach(m=>{m.status==="OK"?(p.push({value:m.distance.value,text:m.distance.text}),y.push({value:m.duration.value,text:m.duration.text})):(p.push(null),y.push(null))}),c.push(p),a.push(y)}),{distances:c,durations:a,origin_addresses:i.origin_addresses,destination_addresses:i.destination_addresses}}catch(s){throw n.error("Error in calculateDistanceMatrix:",s),new Error(`Failed to calculate distance matrix: ${h(s)}`)}}async getDirections(e,r,t="driving",s,i){try{let c;i&&(c=Math.floor(i.getTime()/1e3));let a;c||(s instanceof Date?a=Math.floor(s.getTime()/1e3):s?a=s:a="now");let p=(await this.client.directions({params:{origin:e,destination:r,mode:t,language:this.defaultLanguage,key:this.apiKey,arrival_time:c,departure_time:a}})).data;if(p.status!=="OK")throw new Error(`Failed to get directions with status: ${p.status} (arrival_time: ${c}, departure_time: ${a}`);if(p.routes.length===0)throw new Error(`No route found from "${e}" to "${r}" with mode: ${t}`);let y=p.routes[0],m=y.legs[0],H=v=>{if(!v||typeof v.value!="number")return"";let V=new Date(v.value*1e3),L={year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1};return v.time_zone&&typeof v.time_zone=="string"&&(L.timeZone=v.time_zone),V.toLocaleString(this.defaultLanguage.toString(),L)};return{routes:p.routes,summary:y.summary,total_distance:{value:m.distance.value,text:m.distance.text},total_duration:{value:m.duration.value,text:m.duration.text},arrival_time:H(m.arrival_time),departure_time:H(m.departure_time)}}catch(c){throw n.error("Error in getDirections:",c),new Error(`Failed to get directions from "${e}" to "${r}": ${h(c)}`)}}async getElevation(e){try{let r=e.map(i=>({lat:i.latitude,lng:i.longitude})),s=(await this.client.elevation({params:{locations:r,key:this.apiKey}})).data;if(s.status!=="OK")throw new Error(`Failed to get elevation data with status: ${s.status}`);return s.results.map((i,c)=>({elevation:i.elevation,location:r[c]}))}catch(r){throw n.error("Error in getElevation:",r),new Error(`Failed to get elevation data for ${e.length} location(s): ${h(r)}`)}}async getWeather(e,r="metric"){try{let t="https://weather.googleapis.com/v1/currentConditions:lookup",s=r==="imperial"?"IMPERIAL":"METRIC",i=`${t}?key=${this.apiKey}&location.latitude=${e.latitude}&location.longitude=${e.longitude}&unitsSystem=${s}`;n.info(`Fetching weather for coordinates: (${e.latitude}, ${e.longitude})`);let c=await fetch(i),a=await c.json();if(!c.ok)throw new Error(`Weather API error: ${a.error?.message||c.statusText}`);let g={temperature:a.temperature?.value||null,conditions:a.condition?.description||"Unknown",humidity:a.relativeHumidity?.value||null,wind_speed:a.wind?.speed?.value||null,wind_direction:a.wind?.direction?.degrees||null,precipitation:a.precipitationProbability?.value||null,uv_index:a.uvIndex?.value||null,visibility:a.visibility?.value||null,pressure:a.pressure?.value||null,cloud_cover:a.cloudCover?.value||null,dew_point:a.dewPoint?.value||null,raw_data:a};return n.info(`Weather fetched successfully: ${g.temperature}\xB0, ${g.conditions}`),g}catch(t){throw n.error("Error in getWeather:",t),new Error(`Failed to get weather data: ${h(t)}`)}}async getStaticMap(e){try{let r="https://maps.googleapis.com/maps/api/staticmap",t=`${e.center.latitude},${e.center.longitude}`,s=`${e.size.width}x${e.size.height}`,i=e.mapType||"roadmap",c=`${r}?center=${t}&zoom=${e.zoom}&size=${s}&maptype=${i}&key=${this.apiKey}`;if(e.markers&&e.markers.length>0&&e.markers.forEach(a=>{let g=`color:${a.color||"red"}|label:${a.label||""}|${a.latitude},${a.longitude}`;c+=`&markers=${encodeURIComponent(g)}`}),e.path&&e.path.length>0){let a=e.path.map(g=>`${g.latitude},${g.longitude}`).join("|");c+=`&path=color:0x0000ff|weight:5|${a}`}return{url:c}}catch(r){throw n.error("Error in getStaticMap:",r),new Error(`Failed to generate static map: ${h(r)}`)}}async snapToRoads(e,r=!1){try{let s=`https://roads.googleapis.com/v1/snapToRoads?path=${e.map(a=>`${a.latitude},${a.longitude}`).join("|")}&interpolate=${r}&key=${this.apiKey}`,i=await fetch(s),c=await i.json();if(!i.ok)throw new Error(`Roads API error: ${c.error?.message||i.statusText}`);return c.snappedPoints.map(a=>({latitude:a.location.latitude,longitude:a.location.longitude,placeId:a.placeId,originalIndex:a.originalIndex}))}catch(t){throw n.error("Error in snapToRoads:",t),new Error(`Failed to snap to roads: ${h(t)}`)}}};var l=class{constructor(e){this.mapsTools=new R(e)}async searchNearby(e){try{let r=await this.mapsTools.getLocation(e.center),t=await this.mapsTools.searchNearbyPlaces({location:r,keyword:e.keyword,radius:e.radius,openNow:e.openNow,minRating:e.minRating});return{location:r,success:!0,data:t.map(s=>({name:s.name,place_id:s.place_id,address:s.formatted_address,location:s.geometry.location,rating:s.rating,total_ratings:s.user_ratings_total,open_now:s.opening_hours?.open_now}))}}catch(r){return{success:!1,error:r instanceof Error?r.message:"An error occurred during search"}}}async getPlaceDetails(e){try{let r=await this.mapsTools.getPlaceDetails(e);return{success:!0,data:{name:r.name,address:r.formatted_address,location:r.geometry?.location,rating:r.rating,total_ratings:r.user_ratings_total,open_now:r.opening_hours?.open_now,phone:r.formatted_phone_number,website:r.website,price_level:r.price_level,reviews:r.reviews?.map(t=>({rating:t.rating,text:t.text,time:t.time,author_name:t.author_name}))}}}catch(r){return{success:!1,error:r instanceof Error?r.message:"An error occurred while getting place details"}}}async geocode(e){try{return{success:!0,data:await this.mapsTools.geocode(e)}}catch(r){return{success:!1,error:r instanceof Error?r.message:"An error occurred while geocoding address"}}}async reverseGeocode(e,r){try{return{success:!0,data:await this.mapsTools.reverseGeocode(e,r)}}catch(t){return{success:!1,error:t instanceof Error?t.message:"An error occurred during reverse geocoding"}}}async calculateDistanceMatrix(e,r,t="driving"){try{return{success:!0,data:await this.mapsTools.calculateDistanceMatrix(e,r,t)}}catch(s){return{success:!1,error:s instanceof Error?s.message:"An error occurred while calculating distance matrix"}}}async getDirections(e,r,t="driving",s,i){try{let c=s?new Date(s):new Date,a=i?new Date(i):void 0;return{success:!0,data:await this.mapsTools.getDirections(e,r,t,c,a)}}catch(c){return{success:!1,error:c instanceof Error?c.message:"An error occurred while getting directions"}}}async getElevation(e){try{return{success:!0,data:await this.mapsTools.getElevation(e)}}catch(r){return{success:!1,error:r instanceof Error?r.message:"An error occurred while getting elevation data"}}}async getWeather(e,r="metric"){try{return{success:!0,data:await this.mapsTools.getWeather(e,r)}}catch(t){return{success:!1,error:t instanceof Error?t.message:"An error occurred while getting weather data"}}}async getStaticMap(e){try{return{success:!0,data:await this.mapsTools.getStaticMap(e)}}catch(r){return{success:!1,error:r instanceof Error?r.message:"An error occurred while generating static map"}}}async snapToRoads(e,r=!1){try{return{success:!0,data:await this.mapsTools.snapToRoads(e,r)}}catch(t){return{success:!1,error:t instanceof Error?t.message:"An error occurred while snapping to roads"}}}};import{AsyncLocalStorage as B}from"async_hooks";var F=new B;function d(){return F.getStore()?.apiKey||process.env.GOOGLE_MAPS_API_KEY}function G(o,e){return F.run(o,e)}var Q="search_nearby",X="Search for nearby places based on location, with optional filtering by keywords, distance, rating, and operating hours",ee={center:f.object({value:f.string().describe("Address, landmark name, or coordinates (coordinate format: lat,lng)"),isCoordinates:f.boolean().default(!1).describe("Whether the value is coordinates")}).describe("Search center point"),keyword:f.string().optional().describe("Search keyword (e.g., restaurant, cafe, hotel)"),radius:f.number().default(1e3).describe("Search radius in meters"),openNow:f.boolean().default(!1).describe("Only show places that are currently open"),minRating:f.number().min(0).max(5).optional().describe("Minimum rating requirement (0-5)")};async function re(o){try{let e=d(),t=await new l(e).searchNearby(o);return t.success?{content:[{type:"text",text:`location: ${JSON.stringify(t.location,null,2)}
`+JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Search failed"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error searching nearby places: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var b={NAME:Q,DESCRIPTION:X,SCHEMA:ee,ACTION:re};import{z as te}from"zod";var oe="get_place_details",se="Get detailed information about a specific place including contact details, reviews, ratings, and operating hours",ae={placeId:te.string().describe("Google Maps place ID")};async function ne(o){try{let e=d(),t=await new l(e).getPlaceDetails(o.placeId);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to get place details"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error getting place details: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var E={NAME:oe,DESCRIPTION:se,SCHEMA:ae,ACTION:ne};import{z as ie}from"zod";var ce="maps_geocode",le="Convert addresses or place names to geographic coordinates (latitude and longitude)",de={address:ie.string().describe("Address or place name to convert to coordinates")};async function ue(o){try{let e=d(),t=await new l(e).geocode(o.address);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to geocode address"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error geocoding address: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var S={NAME:ce,DESCRIPTION:le,SCHEMA:de,ACTION:ue};import{z as j}from"zod";var pe="maps_reverse_geocode",me="Convert geographic coordinates (latitude and longitude) to a human-readable address",ge={latitude:j.number().describe("Latitude coordinate"),longitude:j.number().describe("Longitude coordinate")};async function ye(o){try{let e=d(),t=await new l(e).reverseGeocode(o.latitude,o.longitude);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to reverse geocode coordinates"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error reverse geocoding: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var w={NAME:pe,DESCRIPTION:me,SCHEMA:ge,ACTION:ye};import{z as P}from"zod";var he="maps_distance_matrix",fe="Calculate travel distances and durations between multiple origins and destinations for different travel modes",ve={origins:P.array(P.string()).describe("List of origin addresses or coordinates"),destinations:P.array(P.string()).describe("List of destination addresses or coordinates"),mode:P.enum(["driving","walking","bicycling","transit"]).default("driving").describe("Travel mode for calculation")};async function be(o){try{let e=d(),t=await new l(e).calculateDistanceMatrix(o.origins,o.destinations,o.mode);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to calculate distance matrix"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error calculating distance matrix: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var x={NAME:he,DESCRIPTION:fe,SCHEMA:ve,ACTION:be};import{z as _}from"zod";var Ee="maps_directions",Se="Get detailed turn-by-turn navigation directions between two locations with route information",we={origin:_.string().describe("Starting point address or coordinates"),destination:_.string().describe("Destination address or coordinates"),mode:_.enum(["driving","walking","bicycling","transit"]).default("driving").describe("Travel mode for directions"),departure_time:_.string().optional().describe("Departure time (ISO string format)"),arrival_time:_.string().optional().describe("Arrival time (ISO string format)")};async function Pe(o){try{let e=d(),t=await new l(e).getDirections(o.origin,o.destination,o.mode,o.departure_time,o.arrival_time);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to get directions"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error getting directions: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var A={NAME:Ee,DESCRIPTION:Se,SCHEMA:we,ACTION:Pe};import{z as D}from"zod";var xe="maps_elevation",_e="Get elevation data (height above sea level) for specific geographic locations",Ae={locations:D.array(D.object({latitude:D.number().describe("Latitude coordinate"),longitude:D.number().describe("Longitude coordinate")})).describe("List of locations to get elevation data for")};async function Me(o){try{let e=d(),t=await new l(e).getElevation(o.locations);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to get elevation data"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error getting elevation data: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var M={NAME:xe,DESCRIPTION:_e,SCHEMA:Ae,ACTION:Me};import{z as K}from"zod";var Ce="maps_weather",Te="Get current weather conditions and forecast for a specific location using Google Weather API",Ne={location:K.object({latitude:K.number().describe("Latitude coordinate"),longitude:K.number().describe("Longitude coordinate")}).describe("Location to get weather data for"),units:K.enum(["metric","imperial"]).optional().describe("Temperature units (metric=Celsius, imperial=Fahrenheit). Default: metric")};async function Ie(o){try{let e=d(),t=await new l(e).getWeather(o.location,o.units||"metric");return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to get weather data"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error getting weather data: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var C={NAME:Ce,DESCRIPTION:Te,SCHEMA:Ne,ACTION:Ie};import{z as u}from"zod";var $e="maps_static_map",Oe="Generate a static map image URL for a specific location and area. Useful for textures in 3D visualization.",Re={center:u.object({latitude:u.number().describe("Center latitude coordinate"),longitude:u.number().describe("Center longitude coordinate")}).describe("Center point of the map"),zoom:u.number().min(0).max(21).describe("Zoom level (0-21, where 21 is maximum detail)"),size:u.object({width:u.number().min(1).max(2048).describe("Image width in pixels"),height:u.number().min(1).max(2048).describe("Image height in pixels")}).describe("Size of the map image"),mapType:u.enum(["roadmap","satellite","terrain","hybrid"]).optional().describe("Map type. Default: roadmap"),markers:u.array(u.object({latitude:u.number(),longitude:u.number(),label:u.string().optional(),color:u.string().optional()})).optional().describe("Optional markers to show on the map"),path:u.array(u.object({latitude:u.number(),longitude:u.number()})).optional().describe("Optional path/route to draw on the map")};async function De(o){try{let e=d(),t=await new l(e).getStaticMap(o);return t.success?{content:[{type:"text",text:JSON.stringify({url:t.data.url,parameters:{center:o.center,zoom:o.zoom,size:o.size,mapType:o.mapType||"roadmap"}},null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to generate static map"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error generating static map: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var T={NAME:$e,DESCRIPTION:Oe,SCHEMA:Re,ACTION:De};import{z as N}from"zod";var Ke="maps_snap_to_roads",Ge="Snap GPS coordinates to the most likely roads travelled. Essential for real-time vehicle tracking and accurate route visualization.",ke={path:N.array(N.object({latitude:N.number().describe("Latitude coordinate"),longitude:N.number().describe("Longitude coordinate")})).describe("Array of GPS coordinates to snap to roads"),interpolate:N.boolean().optional().describe("Whether to interpolate a path with additional points. Default: false")};async function ze(o){try{let e=d(),t=await new l(e).snapToRoads(o.path,o.interpolate||!1);return t.success?{content:[{type:"text",text:JSON.stringify(t.data,null,2)}],isError:!1}:{content:[{type:"text",text:t.error||"Failed to snap to roads"}],isError:!0}}catch(e){return{isError:!0,content:[{type:"text",text:`Error snapping to roads: ${e instanceof Error?e.message:JSON.stringify(e)}`}]}}}var I={NAME:Ke,DESCRIPTION:Ge,SCHEMA:ke,ACTION:ze};var He=[{name:"MCP-Server",portEnvVar:"MCP_SERVER_PORT",tools:[{name:b.NAME,description:b.DESCRIPTION,schema:b.SCHEMA,action:o=>b.ACTION(o)},{name:E.NAME,description:E.DESCRIPTION,schema:E.SCHEMA,action:o=>E.ACTION(o)},{name:S.NAME,description:S.DESCRIPTION,schema:S.SCHEMA,action:o=>S.ACTION(o)},{name:w.NAME,description:w.DESCRIPTION,schema:w.SCHEMA,action:o=>w.ACTION(o)},{name:x.NAME,description:x.DESCRIPTION,schema:x.SCHEMA,action:o=>x.ACTION(o)},{name:A.NAME,description:A.DESCRIPTION,schema:A.SCHEMA,action:o=>A.ACTION(o)},{name:M.NAME,description:M.DESCRIPTION,schema:M.SCHEMA,action:o=>M.ACTION(o)},{name:C.NAME,description:C.DESCRIPTION,schema:C.SCHEMA,action:o=>C.ACTION(o)},{name:T.NAME,description:T.DESCRIPTION,schema:T.SCHEMA,action:o=>T.ACTION(o)},{name:I.NAME,description:I.DESCRIPTION,schema:I.SCHEMA,action:o=>I.ACTION(o)}]}],k=He;import{McpServer as Le}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Fe}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as je}from"@modelcontextprotocol/sdk/types.js";import J from"express";import{randomUUID as Je}from"crypto";var $=class o{constructor(){this.defaultApiKey=process.env.GOOGLE_MAPS_API_KEY}static getInstance(){return o.instance||(o.instance=new o),o.instance}setDefaultApiKey(e){this.defaultApiKey=e,process.env.GOOGLE_MAPS_API_KEY=e}getApiKey(e,r){if(e){let t=e.headers["x-google-maps-api-key"];if(t)return t;let s=e.headers.authorization;if(s&&s.startsWith("Bearer "))return s.substring(7)}return r||this.defaultApiKey}hasApiKey(e,r){return!!this.getApiKey(e,r)}isValidApiKeyFormat(e){return/^[A-Za-z0-9_-]{20,50}$/.test(e)}};var We="0.0.1",O=class{constructor(e,r){this.sessions={};this.httpServer=null;this.isStdioMode=!1;this.serverName=e,this.server=new Le({name:this.serverName,version:We},{capabilities:{logging:{},tools:{}}}),this.registerTools(r)}registerTools(e){e.forEach(r=>{this.server.tool(r.name,r.description,r.schema,async t=>r.action(t))})}async connect(e){await this.server.connect(e),this.isStdioMode||n.log(`${this.serverName} connected and ready to process requests`)}async startHttpServer(e){this.isStdioMode=!1;let r=J();r.use(J.json()),r.post("/mcp",async(s,i)=>{let c=s.headers["mcp-session-id"],a,p=$.getInstance().getApiKey(s);if(n.log(`${this.serverName} Get API KEY: ${p}`),c&&this.sessions[c])a=this.sessions[c],p&&(a.apiKey=p);else if(!c&&je(s.body)){let y=new Fe({sessionIdGenerator:()=>Je(),onsessioninitialized:m=>{this.sessions[m]=a,n.log(`[${this.serverName}] New session initialized: ${m}`)}});a={transport:y,apiKey:p},y.onclose=()=>{y.sessionId&&(delete this.sessions[y.sessionId],n.log(`[${this.serverName}] Session closed: ${y.sessionId}`))},await this.server.connect(y)}else{i.status(400).json({jsonrpc:"2.0",error:{code:-32e3,message:"Bad Request: No valid session ID provided"},id:null});return}await G({apiKey:a.apiKey,sessionId:c},async()=>{await a.transport.handleRequest(s,i,s.body)})});let t=async(s,i)=>{let c=s.headers["mcp-session-id"];if(!c||!this.sessions[c]){i.status(400).send("Invalid or missing session ID");return}let a=this.sessions[c],p=$.getInstance().getApiKey(s);p&&(a.apiKey=p),await G({apiKey:a.apiKey,sessionId:c},async()=>{await a.transport.handleRequest(s,i)})};r.get("/mcp",t),r.delete("/mcp",t),this.httpServer=r.listen(e,()=>{n.log(`[${this.serverName}] HTTP server listening on port ${e}`),n.log(`[${this.serverName}] MCP endpoint available at http://localhost:${e}/mcp`)})}async stopHttpServer(){if(!this.httpServer){n.error(`[${this.serverName}] HTTP server is not running or already stopped.`);return}return new Promise((e,r)=>{this.httpServer.close(t=>{if(t){n.error(`[${this.serverName}] Error stopping HTTP server:`,t),r(t);return}n.log(`[${this.serverName}] HTTP server stopped.`),this.httpServer=null;let s=Object.values(this.sessions).map(i=>(i.transport.sessionId&&delete this.sessions[i.transport.sessionId],Promise.resolve()));Promise.all(s).then(()=>{n.log(`[${this.serverName}] All transports closed.`),e()}).catch(i=>{n.error(`[${this.serverName}] Error during bulk transport closing:`,i),r(i)})})})}async startStdioServer(){this.isStdioMode=!0;let{StdioServerTransport:e}=await import("@modelcontextprotocol/sdk/server/stdio.js");console.error(`[${this.serverName}] Starting STDIO MCP Server...`);let r=new e;await this.connect(r),console.error(`[${this.serverName}] STDIO MCP Server ready and waiting for requests`)}async stopStdioServer(){console.error(`[${this.serverName}] Stopping STDIO MCP Server...`),process.exit(0)}};import{fileURLToPath as Ze}from"url";import{dirname as Ye}from"path";import{readFileSync as Ue}from"fs";var Be=Ze(import.meta.url),q=Ye(Be);W({path:z(process.cwd(),".env")});W({path:z(q,"../.env")});async function Qe(o,e){o&&(process.env.MCP_SERVER_PORT=o.toString()),e&&(process.env.GOOGLE_MAPS_API_KEY=e),n.log("\u{1F680} Starting Google Maps MCP Server..."),n.log("\u{1F4CD} Available tools: search_nearby, get_place_details, maps_geocode, maps_reverse_geocode, maps_distance_matrix, maps_directions, maps_elevation, maps_weather, maps_static_map, maps_snap_to_roads"),n.log("");let r=k.map(async t=>{let s=process.env[t.portEnvVar];if(!s){n.error(`\u26A0\uFE0F [${t.name}] Port environment variable ${t.portEnvVar} not set.`),n.log(`\u{1F4A1} Please set ${t.portEnvVar} in your .env file or use --port parameter.`),n.log(` Example: ${t.portEnvVar}=3000 or --port 3000`);return}let i=Number(s);if(isNaN(i)||i<=0){n.error(`\u274C [${t.name}] Invalid port number "${s}" defined in ${t.portEnvVar}.`);return}try{let c=new O(t.name,t.tools);n.log(`\u{1F527} [${t.name}] Initializing MCP Server in HTTP mode on port ${i}...`),await c.startHttpServer(i),n.log(`\u2705 [${t.name}] MCP Server started successfully!`),n.log(` \u{1F310} Endpoint: http://localhost:${i}/mcp`),n.log(` \u{1F4DA} Tools: ${t.tools.length} available`)}catch(c){n.error(`\u274C [${t.name}] Failed to start MCP Server on port ${i}:`,c)}});await Promise.allSettled(r),n.log(""),n.log("\u{1F389} Server initialization completed!"),n.log("\u{1F4A1} Need help? Check the README.md for configuration details.")}async function Xe(){let o=(...e)=>console.error(...e);o("\u{1F50C} Starting Google Maps MCP Server in STDIO mode..."),process.env.GOOGLE_MAPS_API_KEY||(o("\u274C Error: GOOGLE_MAPS_API_KEY not found in environment"),o(" Please set it in your .env file or environment variables"),process.exit(1));try{await new O("google-maps",k[0].tools).startStdioServer(),o("\u2705 MCP Server running in STDIO mode"),o(" Ready to receive requests from Claude Desktop"),process.stdin.resume()}catch(e){o("\u274C Failed to start STDIO server:",e),process.exit(1)}}var er=process.argv[1]&&(process.argv[1].endsWith("cli.ts")||process.argv[1].endsWith("cli.js")||process.argv[1].endsWith("mcp-google-map-stdio")||process.argv[1].includes("mcp-google-map-stdio")),rr=import.meta.url===`file://${process.argv[1]}`;if(er||rr)if(process.argv.includes("--stdio"))Xe().catch(o=>{console.error("\u274C Fatal error:",o),process.exit(1)});else{let o="0.0.0";try{let r=z(q,"../package.json");o=JSON.parse(Ue(r,"utf-8")).version}catch{o="0.0.0"}let e=qe(Ve(process.argv)).option("port",{alias:"p",type:"number",description:"Port to run the MCP server on",default:process.env.MCP_SERVER_PORT?parseInt(process.env.MCP_SERVER_PORT):3e3}).option("apikey",{alias:"k",type:"string",description:"Google Maps API key",default:process.env.GOOGLE_MAPS_API_KEY}).option("stdio",{type:"boolean",description:"Run in STDIO mode (for Claude Desktop)",default:!1}).option("help",{alias:"h",type:"boolean",description:"Show help"}).version(o).alias("version","v").example([["$0","Start server in HTTP mode with default settings"],['$0 --port 3000 --apikey "your_api_key"',"Start HTTP server with custom port and API key"],["$0 --stdio","Start server in STDIO mode for Claude Desktop"]]).help().parseSync();n.log("\u{1F5FA}\uFE0F Google Maps MCP Server"),n.log(" A Model Context Protocol server for Google Maps services"),n.log(""),e.apikey||(n.log("\u26A0\uFE0F Google Maps API Key not found!"),n.log(" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file"),n.log(" Example: mcp-google-map-stdio --apikey your_api_key_here"),n.log("")),Qe(e.port,e.apikey).catch(r=>{n.error("\u274C Failed to start server:",r),process.exit(1)})}export{Qe as startServer};