get_similar_apps
Find apps similar to a specified app by providing its ID and platform, with options to customize results by region, language, and quantity.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| appId | Yes | The unique identifier for the app (Android package name, iOS numeric ID or bundle ID). | |
| platform | Yes | The platform of the app ('ios' or 'android'). | |
| country | No | Two-letter country code for the App Store/Play Store region. Default 'us'. | us |
| lang | No | Language code for the results. Default 'en'. | en |
| num | No | Number of similar apps to return (default 20). |
Implementation Reference
- server.js:1521-1613 (handler)The handler function that implements the core logic of the 'get_similar_apps' tool. It fetches similar apps from either Google Play Store (using google-play-scraper.similar) or Apple App Store (using app-store-scraper.similar), normalizes the results, limits to the requested number, and returns structured JSON.async ({ appId, platform, country, lang, num }) => { try { let similarApps = []; if (platform === "android") { // Get similar apps from Google Play Store const apps = await memoizedGplay.similar({ appId, country, lang }); // Limit results to num similarApps = apps.slice(0, num).map(app => ({ id: app.appId, appId: app.appId, title: app.title, summary: app.summary || "", developer: app.developer, developerId: app.developerId, icon: app.icon, score: app.score, scoreText: app.scoreText, price: app.price, free: app.free, currency: app.currency || "USD", platform: "android", url: app.url })); } else { // For iOS, we need to check if appId is a numeric ID or bundle ID const isNumericId = /^\d+$/.test(appId); // Get similar apps from Apple App Store let iosParams = {}; if (isNumericId) { iosParams = { id: appId, country }; } else { iosParams = { appId, country }; } const apps = await memoizedAppStore.similar(iosParams); // Limit results to num similarApps = apps.slice(0, num).map(app => ({ id: app.id.toString(), appId: app.appId, title: app.title, summary: app.description || "", developer: app.developer, developerId: app.developerId, icon: app.icon, score: app.score, price: app.price, free: app.free === true, currency: app.currency, platform: "ios", url: app.url })); } return { content: [{ type: "text", text: JSON.stringify({ appId, platform, count: similarApps.length, similarApps }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error.message, appId, platform }, null, 2) }], isError: true }; } }
- server.js:1514-1520 (schema)Zod input schema validation for the 'get_similar_apps' tool, defining parameters like appId (required), platform (ios/android), optional country, lang, and num results.{ appId: z.string().describe("The unique identifier for the app (Android package name, iOS numeric ID or bundle ID)."), platform: z.enum(["ios", "android"]).describe("The platform of the app ('ios' or 'android')."), country: z.string().length(2).optional().default("us").describe("Two-letter country code for the App Store/Play Store region. Default 'us'."), lang: z.string().optional().default("en").describe("Language code for the results. Default 'en'."), num: z.number().optional().default(20).describe("Number of similar apps to return (default 20).") },
- server.js:1512-1614 (registration)The registration of the 'get_similar_apps' tool on the MCP server using server.tool(name, inputSchema, handlerFn). This binds the tool name to its schema and implementation.server.tool( "get_similar_apps", { appId: z.string().describe("The unique identifier for the app (Android package name, iOS numeric ID or bundle ID)."), platform: z.enum(["ios", "android"]).describe("The platform of the app ('ios' or 'android')."), country: z.string().length(2).optional().default("us").describe("Two-letter country code for the App Store/Play Store region. Default 'us'."), lang: z.string().optional().default("en").describe("Language code for the results. Default 'en'."), num: z.number().optional().default(20).describe("Number of similar apps to return (default 20).") }, async ({ appId, platform, country, lang, num }) => { try { let similarApps = []; if (platform === "android") { // Get similar apps from Google Play Store const apps = await memoizedGplay.similar({ appId, country, lang }); // Limit results to num similarApps = apps.slice(0, num).map(app => ({ id: app.appId, appId: app.appId, title: app.title, summary: app.summary || "", developer: app.developer, developerId: app.developerId, icon: app.icon, score: app.score, scoreText: app.scoreText, price: app.price, free: app.free, currency: app.currency || "USD", platform: "android", url: app.url })); } else { // For iOS, we need to check if appId is a numeric ID or bundle ID const isNumericId = /^\d+$/.test(appId); // Get similar apps from Apple App Store let iosParams = {}; if (isNumericId) { iosParams = { id: appId, country }; } else { iosParams = { appId, country }; } const apps = await memoizedAppStore.similar(iosParams); // Limit results to num similarApps = apps.slice(0, num).map(app => ({ id: app.id.toString(), appId: app.appId, title: app.title, summary: app.description || "", developer: app.developer, developerId: app.developerId, icon: app.icon, score: app.score, price: app.price, free: app.free === true, currency: app.currency, platform: "ios", url: app.url })); } return { content: [{ type: "text", text: JSON.stringify({ appId, platform, count: similarApps.length, similarApps }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error.message, appId, platform }, null, 2) }], isError: true }; } } );