@iflow-mcp/jiantaofu-appinsightmcp 1.0.8
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.
- package/LICENSE +21 -0
- package/README.md +168 -0
- package/package.json +1 -0
- package/src/server.js +828 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 JiantaoFu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
[](https://mseep.ai/app/jiantaofu-appinsightmcp)
|
|
2
|
+
|
|
3
|
+
<a href="https://glama.ai/mcp/servers/@JiantaoFu/AppInsightMCP">
|
|
4
|
+
<img width="380" height="200" src="https://glama.ai/mcp/servers/@JiantaoFu/AppInsightMCP/badge" alt="App Market Intelligence MCP server" />
|
|
5
|
+
</a>
|
|
6
|
+
|
|
7
|
+
# App Market Intelligence MCP
|
|
8
|
+
|
|
9
|
+
An MCP server that provides comprehensive market intelligence by analyzing data from both the Apple App Store and Google Play Store. Get insights about apps, market trends, competitors, and user feedback across the major mobile app marketplaces.
|
|
10
|
+
|
|
11
|
+
## API Coverage
|
|
12
|
+
|
|
13
|
+
### App Store API Coverage
|
|
14
|
+
|
|
15
|
+
| API Function | Implemented | MCP Tool Name | Description |
|
|
16
|
+
|-------------|-------------|---------------|-------------|
|
|
17
|
+
| app | ✅ | app-store-details | Get detailed information about an App Store app |
|
|
18
|
+
| list | ✅ | app-store-list | Retrieve apps from iTunes collections |
|
|
19
|
+
| search | ✅ | app-store-search | Search for apps on the App Store |
|
|
20
|
+
| developer | ✅ | app-store-developer | Get apps by a developer |
|
|
21
|
+
| privacy | ✅ | app-store-privacy | Get privacy details for an app |
|
|
22
|
+
| suggest | ✅ | app-store-suggest | Get search suggestions |
|
|
23
|
+
| similar | ✅ | app-store-similar | Get similar apps |
|
|
24
|
+
| reviews | ✅ | app-store-reviews | Get app reviews |
|
|
25
|
+
| ratings | ✅ | app-store-ratings | Get app ratings |
|
|
26
|
+
| versionHistory | ✅ | app-store-version-history | Get app version history |
|
|
27
|
+
|
|
28
|
+
### Google Play API Coverage
|
|
29
|
+
|
|
30
|
+
| API Function | Implemented | MCP Tool Name | Description |
|
|
31
|
+
|-------------|-------------|---------------|-------------|
|
|
32
|
+
| app | ✅ | google-play-details | Get detailed app information |
|
|
33
|
+
| list | ✅ | google-play-list | Retrieve apps from collections |
|
|
34
|
+
| search | ✅ | google-play-search | Search for apps |
|
|
35
|
+
| developer | ✅ | google-play-developer | Get apps by developer |
|
|
36
|
+
| suggest | ✅ | google-play-suggest | Get search suggestions |
|
|
37
|
+
| reviews | ✅ | google-play-reviews | Get app reviews |
|
|
38
|
+
| similar | ✅ | google-play-similar | Get similar apps |
|
|
39
|
+
| permissions | ✅ | google-play-permissions | Get app permissions |
|
|
40
|
+
| datasafety | ✅ | google-play-datasafety | Get data safety information |
|
|
41
|
+
| categories | ✅ | google-play-categories | Get list of categories |
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
Start the MCP server:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
node src/server.js
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The server exposes tools that can be used through any MCP client. For example, using Claude for Desktop, you can:
|
|
52
|
+
|
|
53
|
+
- Search for apps across both stores
|
|
54
|
+
- Get detailed app information
|
|
55
|
+
- Read reviews and ratings
|
|
56
|
+
- Find similar apps
|
|
57
|
+
- Check app privacy and permissions
|
|
58
|
+
- And more
|
|
59
|
+
|
|
60
|
+
## Usage Examples
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
// Get top free iOS apps
|
|
64
|
+
{
|
|
65
|
+
"name": "app-store-list",
|
|
66
|
+
"params": {
|
|
67
|
+
"collection": "topfreeapplications",
|
|
68
|
+
"num": 10
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Get top paid Android games
|
|
73
|
+
{
|
|
74
|
+
"name": "google-play-list",
|
|
75
|
+
"params": {
|
|
76
|
+
"collection": "TOP_PAID",
|
|
77
|
+
"category": "GAME",
|
|
78
|
+
"num": 10
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Test with MCP Inspector
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
npm run test:inspector
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
## Test with mcp-cli
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
npx @wong2/mcp-cli npx -y "app-insight-mcp"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Usage with Claude Desktop
|
|
98
|
+
Add this to your `claude_desktop_config.json`:
|
|
99
|
+
|
|
100
|
+
### Installing via Smithery
|
|
101
|
+
|
|
102
|
+
To install App Market Intelligence for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@JiantaoFu/appinsightmcp):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx -y @smithery/cli install @JiantaoFu/appinsightmcp --client claude
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Docker
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"mcpServers": {
|
|
113
|
+
"app-insight-mcp": {
|
|
114
|
+
"command": "docker",
|
|
115
|
+
"args": [
|
|
116
|
+
"run",
|
|
117
|
+
"-i",
|
|
118
|
+
"--rm",
|
|
119
|
+
"app-insight-mcp"
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### NPX
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"app-insight-mcp": {
|
|
132
|
+
"command": "npx",
|
|
133
|
+
"args": [
|
|
134
|
+
"-y",
|
|
135
|
+
"@jeromyfu/app-insight-mcp"
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Build
|
|
143
|
+
|
|
144
|
+
Docker build:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
docker build -t app-insight-mcp -f Dockerfile .
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Error Handling
|
|
151
|
+
|
|
152
|
+
All tools include error handling and will return appropriate error messages if:
|
|
153
|
+
- Required parameters are missing
|
|
154
|
+
- API calls fail
|
|
155
|
+
- Rate limits are hit
|
|
156
|
+
- Invalid IDs or parameters are provided
|
|
157
|
+
|
|
158
|
+
## Contributing
|
|
159
|
+
|
|
160
|
+
Feel free to contribute by:
|
|
161
|
+
1. Implementing missing features
|
|
162
|
+
2. Improving error handling
|
|
163
|
+
3. Adding more API capabilities
|
|
164
|
+
4. Enhancing documentation
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name": "@iflow-mcp/jiantaofu-appinsightmcp", "version": "1.0.8", "description": "MCP server for gathering market intelligence from mobile app stores (Apple App Store & Google Play)", "type": "module", "main": "src/server.js", "bin": {"iflow-mcp-jiantaofu-appinsightmcp": "src/server.js"}, "files": ["src"], "scripts": {"start": "node src/server.js", "dev": "node --watch src/server.js", "test:inspector": "npx @modelcontextprotocol/inspector node src/server.js", "test:claude": "node src/server.js", "build": "chmod +x src/server.js", "prepare": "npm run build"}, "keywords": ["mcp", "app-store", "google-play", "scraper", "ai"], "author": "Jeromy Fu", "license": "MIT", "dependencies": {"@modelcontextprotocol/sdk": "^1.6.1", "@jeromyfu/app-store-scraper": "^0.18.0", "@jeromyfu/google-play-scraper": "^10.0.1", "punycode": "^2.3.1"}, "devDependencies": {"chai": "^5.2.0", "mocha": "^11.1.0"}, "engines": {"node": ">=18.0.0"}}
|
package/src/server.js
ADDED
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MIT License
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2024 Insightly
|
|
7
|
+
*
|
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
* furnished to do so, subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
* copies or substantial portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
* SOFTWARE.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
28
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
29
|
+
import store from '@jeromyfu/app-store-scraper';
|
|
30
|
+
import gplay from '@jeromyfu/google-play-scraper';
|
|
31
|
+
import { z } from 'zod';
|
|
32
|
+
|
|
33
|
+
const server = new McpServer({
|
|
34
|
+
name: "app-info-scraper",
|
|
35
|
+
version: "1.0.0"
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// App Store Tools
|
|
39
|
+
server.tool("app-store-search",
|
|
40
|
+
"Search for apps on the App Store. Returns a list of apps with the following fields:\n" +
|
|
41
|
+
"- id: App Store ID number\n" +
|
|
42
|
+
"- appId: Bundle ID (e.g. 'com.company.app')\n" +
|
|
43
|
+
"- title: App name\n" +
|
|
44
|
+
"- icon: Icon image URL\n" +
|
|
45
|
+
"- url: App Store URL\n" +
|
|
46
|
+
"- price: Price in USD\n" +
|
|
47
|
+
"- currency: Price currency code\n" +
|
|
48
|
+
"- free: Boolean indicating if app is free\n" +
|
|
49
|
+
"- description: App description\n" +
|
|
50
|
+
"- developer: Developer name\n" +
|
|
51
|
+
"- developerUrl: Developer's App Store URL\n" +
|
|
52
|
+
"- developerId: Developer's ID\n" +
|
|
53
|
+
"- genre: App category name\n" +
|
|
54
|
+
"- genreId: Category ID\n" +
|
|
55
|
+
"- released: Release date (ISO string)",
|
|
56
|
+
{
|
|
57
|
+
term: z.string().describe("Search term (required)"),
|
|
58
|
+
num: z.number().default(50).describe("Number of results to retrieve (default: 50)"),
|
|
59
|
+
page: z.number().default(1).describe("Page of results to retrieve (default: 1)"),
|
|
60
|
+
country: z.string().default("us").describe("Two letter country code (default: us)"),
|
|
61
|
+
lang: z.string().default("en-us").describe("Language code for result text (default: en-us)"),
|
|
62
|
+
idsOnly: z.boolean().default(false).describe("Skip extra lookup request. Returns array of application IDs only (default: false)")
|
|
63
|
+
},
|
|
64
|
+
async ({ term, num, page, country, lang, idsOnly }) => {
|
|
65
|
+
const results = await store.search({ term, num, page, country, lang, idsOnly });
|
|
66
|
+
return { content: [{ type: "text", text: JSON.stringify(results) }] };
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
server.tool("app-store-details",
|
|
71
|
+
"Get detailed information about an App Store app. Returns an object with:\n" +
|
|
72
|
+
"- id: App Store ID number\n" +
|
|
73
|
+
"- appId: Bundle ID (e.g. 'com.company.app')\n" +
|
|
74
|
+
"- title: App name\n" +
|
|
75
|
+
"- url: App Store URL\n" +
|
|
76
|
+
"- description: Full app description\n" +
|
|
77
|
+
"- icon: Icon URL\n" +
|
|
78
|
+
"- genres: Array of category names\n" +
|
|
79
|
+
"- genreIds: Array of category IDs\n" +
|
|
80
|
+
"- primaryGenre: Main category name\n" +
|
|
81
|
+
"- primaryGenreId: Main category ID\n" +
|
|
82
|
+
"- contentRating: Content rating (e.g. '4+')\n" +
|
|
83
|
+
"- languages: Array of language codes\n" +
|
|
84
|
+
"- size: App size in bytes\n" +
|
|
85
|
+
"- requiredOsVersion: Minimum iOS version required\n" +
|
|
86
|
+
"- released: Initial release date (ISO string)\n" +
|
|
87
|
+
"- updated: Last update date (ISO string)\n" +
|
|
88
|
+
"- releaseNotes: Latest version changes\n" +
|
|
89
|
+
"- version: Current version string\n" +
|
|
90
|
+
"- price: Price in USD\n" +
|
|
91
|
+
"- currency: Price currency code\n" +
|
|
92
|
+
"- free: Boolean indicating if app is free\n" +
|
|
93
|
+
"- developerId: Developer's ID\n" +
|
|
94
|
+
"- developer: Developer name\n" +
|
|
95
|
+
"- developerUrl: Developer's App Store URL\n" +
|
|
96
|
+
"- developerWebsite: Developer's website URL if available\n" +
|
|
97
|
+
"- score: Current rating (0-5)\n" +
|
|
98
|
+
"- reviews: Total number of ratings\n" +
|
|
99
|
+
"- currentVersionScore: Current version rating (0-5)\n" +
|
|
100
|
+
"- currentVersionReviews: Current version review count\n" +
|
|
101
|
+
"- screenshots: Array of screenshot URLs\n" +
|
|
102
|
+
"- ipadScreenshots: Array of iPad screenshot URLs\n" +
|
|
103
|
+
"- appletvScreenshots: Array of Apple TV screenshot URLs\n" +
|
|
104
|
+
"- supportedDevices: Array of supported device IDs\n" +
|
|
105
|
+
"- ratings: Total number of ratings (when ratings option enabled)\n" +
|
|
106
|
+
"- histogram: Rating distribution by star level (when ratings option enabled)",
|
|
107
|
+
{
|
|
108
|
+
id: z.number().optional().describe("Numeric App ID (e.g., 553834731). Either this or appId must be provided."),
|
|
109
|
+
appId: z.string().optional().describe("Bundle ID (e.g., 'com.midasplayer.apps.candycrushsaga'). Either this or id must be provided."),
|
|
110
|
+
country: z.string().default("us").describe("Country code to get app details from (default: us). Also affects data language."),
|
|
111
|
+
lang: z.string().optional().describe("Language code for result text. If not provided, uses country-specific language."),
|
|
112
|
+
ratings: z.boolean().optional().default(false).describe("Load additional ratings information like ratings count and histogram")
|
|
113
|
+
},
|
|
114
|
+
async ({ id, appId, country, lang, ratings }) => {
|
|
115
|
+
const details = await store.app({ id, appId, country, lang, ratings });
|
|
116
|
+
return { content: [{ type: "text", text: JSON.stringify(details) }] };
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
server.tool("app-store-reviews",
|
|
121
|
+
"Get reviews for an App Store app. Returns an array of reviews with:\n" +
|
|
122
|
+
"- id: Review ID\n" +
|
|
123
|
+
"- userName: Reviewer's name\n" +
|
|
124
|
+
"- userUrl: Reviewer's profile URL\n" +
|
|
125
|
+
"- version: App version reviewed\n" +
|
|
126
|
+
"- score: Rating (1-5)\n" +
|
|
127
|
+
"- title: Review title\n" +
|
|
128
|
+
"- text: Review content\n" +
|
|
129
|
+
"- url: Review URL\n" +
|
|
130
|
+
"- updated: Review date (ISO string)",
|
|
131
|
+
{
|
|
132
|
+
id: z.number().optional().describe("Numeric App ID (e.g., 553834731). Either this or appId must be provided."),
|
|
133
|
+
appId: z.string().optional().describe("Bundle ID (e.g., 'com.midasplayer.apps.candycrushsaga'). Either this or id must be provided."),
|
|
134
|
+
country: z.string().default("us").describe("Country code to get reviews from (default: us)"),
|
|
135
|
+
page: z.number().min(1).max(10).default(1).describe("Page number to retrieve (default: 1, max: 10)"),
|
|
136
|
+
sort: z.enum(["recent", "helpful"]).default("recent").describe("Sort order (recent or helpful)")
|
|
137
|
+
},
|
|
138
|
+
async ({ id, appId, country, page, sort }) => {
|
|
139
|
+
const reviews = await store.reviews({
|
|
140
|
+
id,
|
|
141
|
+
appId,
|
|
142
|
+
country,
|
|
143
|
+
page,
|
|
144
|
+
sort: sort === "helpful" ? store.sort.HELPFUL : store.sort.RECENT
|
|
145
|
+
});
|
|
146
|
+
return { content: [{ type: "text", text: JSON.stringify(reviews) }] };
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
server.tool("app-store-similar",
|
|
151
|
+
"Get similar apps ('customers also bought') from the App Store. Returns a list of apps with:\n" +
|
|
152
|
+
"- id: App Store ID number\n" +
|
|
153
|
+
"- appId: Bundle ID (e.g. 'com.company.app')\n" +
|
|
154
|
+
"- title: App name\n" +
|
|
155
|
+
"- icon: Icon image URL\n" +
|
|
156
|
+
"- url: App Store URL\n" +
|
|
157
|
+
"- price: Price in USD\n" +
|
|
158
|
+
"- currency: Price currency code\n" +
|
|
159
|
+
"- free: Boolean indicating if app is free\n" +
|
|
160
|
+
"- description: App description\n" +
|
|
161
|
+
"- developer: Developer name\n" +
|
|
162
|
+
"- developerUrl: Developer's App Store URL\n" +
|
|
163
|
+
"- developerId: Developer's ID\n" +
|
|
164
|
+
"- genre: App category name\n" +
|
|
165
|
+
"- genreId: Category ID\n" +
|
|
166
|
+
"- released: Release date (ISO string)",
|
|
167
|
+
{
|
|
168
|
+
id: z.number().optional().describe("Numeric App ID (e.g., 553834731). Either this or appId must be provided."),
|
|
169
|
+
appId: z.string().optional().describe("Bundle ID (e.g., 'com.midasplayer.apps.candycrushsaga'). Either this or id must be provided.")
|
|
170
|
+
},
|
|
171
|
+
async ({ id, appId }) => {
|
|
172
|
+
const similar = await store.similar({ id, appId });
|
|
173
|
+
return { content: [{ type: "text", text: JSON.stringify(similar) }] };
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Additional App Store Tools
|
|
178
|
+
server.tool("app-store-developer",
|
|
179
|
+
"Get apps by a developer on the App Store. Returns a list of apps with:\n" +
|
|
180
|
+
"- id: App Store ID number\n" +
|
|
181
|
+
"- appId: Bundle ID (e.g. 'com.company.app')\n" +
|
|
182
|
+
"- title: App name\n" +
|
|
183
|
+
"- icon: Icon image URL\n" +
|
|
184
|
+
"- url: App Store URL\n" +
|
|
185
|
+
"- price: Price in USD\n" +
|
|
186
|
+
"- currency: Price currency code\n" +
|
|
187
|
+
"- free: Boolean indicating if app is free\n" +
|
|
188
|
+
"- description: App description\n" +
|
|
189
|
+
"- developer: Developer name\n" +
|
|
190
|
+
"- developerUrl: Developer's App Store URL\n" +
|
|
191
|
+
"- developerId: Developer's ID\n" +
|
|
192
|
+
"- genre: App category name\n" +
|
|
193
|
+
"- genreId: Category ID\n" +
|
|
194
|
+
"- released: Release date (ISO string)",
|
|
195
|
+
{
|
|
196
|
+
devId: z.string().describe("iTunes artist ID of the developer (e.g., 284882218 for Facebook)"),
|
|
197
|
+
country: z.string().default("us").describe("Country code to get app details from (default: us). Also affects data language."),
|
|
198
|
+
lang: z.string().optional().describe("Language code for result text. If not provided, uses country-specific language.")
|
|
199
|
+
},
|
|
200
|
+
async ({ devId, country, lang }) => {
|
|
201
|
+
const apps = await store.developer({ devId, country, lang });
|
|
202
|
+
return { content: [{ type: "text", text: JSON.stringify(apps) }] };
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
server.tool("app-store-suggest",
|
|
207
|
+
"Get search suggestions from the App Store. Returns an array of objects with:\n" +
|
|
208
|
+
"- term: Suggested search term\n" +
|
|
209
|
+
"Each suggestion has a priority from 0 (low traffic) to 10000 (most searched)",
|
|
210
|
+
{
|
|
211
|
+
term: z.string().describe("Search term to get suggestions for")
|
|
212
|
+
},
|
|
213
|
+
async ({ term, country }) => {
|
|
214
|
+
const suggestions = await store.suggest({ term });
|
|
215
|
+
return { content: [{ type: "text", text: JSON.stringify(suggestions) }] };
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
server.tool("app-store-ratings",
|
|
220
|
+
"Get ratings for an App Store app. Returns an object with:\n" +
|
|
221
|
+
"- ratings: Total number of ratings\n" +
|
|
222
|
+
"- histogram: Distribution of ratings by star level (1-5)",
|
|
223
|
+
{
|
|
224
|
+
id: z.number().optional().describe("Numeric App ID (e.g., 553834731). Either this or appId must be provided."),
|
|
225
|
+
appId: z.string().optional().describe("Bundle ID (e.g., 'com.midasplayer.apps.candycrushsaga'). Either this or id must be provided."),
|
|
226
|
+
country: z.string().default("us").describe("Country code to get ratings from (default: us)")
|
|
227
|
+
},
|
|
228
|
+
async ({ id, appId, country }) => {
|
|
229
|
+
const ratings = await store.ratings({ id, appId, country });
|
|
230
|
+
return { content: [{ type: "text", text: JSON.stringify(ratings) }] };
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
server.tool("app-store-version-history",
|
|
235
|
+
"Get version history for an App Store app. Returns an array of versions with:\n" +
|
|
236
|
+
"- versionDisplay: Version number string\n" +
|
|
237
|
+
"- releaseNotes: Update description\n" +
|
|
238
|
+
"- releaseDate: Release date (YYYY-MM-DD)\n" +
|
|
239
|
+
"- releaseTimestamp: Release date and time (ISO string)",
|
|
240
|
+
{
|
|
241
|
+
id: z.number().describe("Numeric App ID (e.g., 444934666)")
|
|
242
|
+
},
|
|
243
|
+
async ({ id }) => {
|
|
244
|
+
const history = await store.versionHistory({ id });
|
|
245
|
+
return { content: [{ type: "text", text: JSON.stringify(history) }] };
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
server.tool("app-store-privacy",
|
|
250
|
+
"Get privacy details for an App Store app. Returns an object with:\n" +
|
|
251
|
+
"- managePrivacyChoicesUrl: URL to manage privacy choices (if available)\n" +
|
|
252
|
+
"- privacyTypes: Array of privacy data types, each containing:\n" +
|
|
253
|
+
" - privacyType: Name of the privacy category\n" +
|
|
254
|
+
" - identifier: Unique identifier for the privacy type\n" +
|
|
255
|
+
" - description: Detailed description of how data is used\n" +
|
|
256
|
+
" - dataCategories: Array of data categories, each containing:\n" +
|
|
257
|
+
" - dataCategory: Category name\n" +
|
|
258
|
+
" - identifier: Category identifier\n" +
|
|
259
|
+
" - dataTypes: Array of specific data types collected\n" +
|
|
260
|
+
" - purposes: Array of purposes for data collection\n" +
|
|
261
|
+
"Note: Currently only available for US App Store.",
|
|
262
|
+
{
|
|
263
|
+
id: z.number().describe("Numeric App ID (e.g., 553834731)")
|
|
264
|
+
},
|
|
265
|
+
async ({ id }) => {
|
|
266
|
+
const privacy = await store.privacy({ id });
|
|
267
|
+
return { content: [{ type: "text", text: JSON.stringify(privacy) }] };
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
server.tool("app-store-list",
|
|
272
|
+
"Get apps from iTunes collections. Returns a list of apps with:\n" +
|
|
273
|
+
"- id: App Store ID number\n" +
|
|
274
|
+
"- appId: Bundle ID (e.g. 'com.company.app')\n" +
|
|
275
|
+
"- title: App name\n" +
|
|
276
|
+
"- icon: Icon image URL\n" +
|
|
277
|
+
"- url: App Store URL\n" +
|
|
278
|
+
"- price: Price in USD\n" +
|
|
279
|
+
"- currency: Price currency code\n" +
|
|
280
|
+
"- free: Boolean indicating if app is free\n" +
|
|
281
|
+
"- description: App description\n" +
|
|
282
|
+
"- developer: Developer name\n" +
|
|
283
|
+
"- developerUrl: Developer's App Store URL\n" +
|
|
284
|
+
"- developerId: Developer's ID\n" +
|
|
285
|
+
"- genre: App category name\n" +
|
|
286
|
+
"- genreId: Category ID\n" +
|
|
287
|
+
"- released: Release date (ISO string)",
|
|
288
|
+
{
|
|
289
|
+
collection: z.enum([
|
|
290
|
+
'newapplications',
|
|
291
|
+
'newfreeapplications',
|
|
292
|
+
'newpaidapplications',
|
|
293
|
+
'topfreeapplications',
|
|
294
|
+
'topfreeipadapplications',
|
|
295
|
+
'topgrossingapplications',
|
|
296
|
+
'topgrossingipadapplications',
|
|
297
|
+
'toppaidapplications',
|
|
298
|
+
'toppaidipadapplications'
|
|
299
|
+
]).describe(
|
|
300
|
+
"Collection to fetch from. Available collections:\n" +
|
|
301
|
+
"- newapplications: New iOS applications\n" +
|
|
302
|
+
"- newfreeapplications: New free iOS applications\n" +
|
|
303
|
+
"- newpaidapplications: New paid iOS applications\n" +
|
|
304
|
+
"- topfreeapplications: Top free iOS applications\n" +
|
|
305
|
+
"- topfreeipadapplications: Top free iPad applications\n" +
|
|
306
|
+
"- topgrossingapplications: Top grossing iOS applications\n" +
|
|
307
|
+
"- topgrossingipadapplications: Top grossing iPad applications\n" +
|
|
308
|
+
"- toppaidapplications: Top paid iOS applications\n" +
|
|
309
|
+
"- toppaidipadapplications: Top paid iPad applications"
|
|
310
|
+
),
|
|
311
|
+
category: z.number().optional().describe(
|
|
312
|
+
"Category ID to filter by. Available categories:\n" +
|
|
313
|
+
"Main Categories:\n" +
|
|
314
|
+
"- 6000: BUSINESS\n" +
|
|
315
|
+
"- 6001: WEATHER\n" +
|
|
316
|
+
"- 6002: UTILITIES\n" +
|
|
317
|
+
"- 6003: TRAVEL\n" +
|
|
318
|
+
"- 6004: SPORTS\n" +
|
|
319
|
+
"- 6005: SOCIAL_NETWORKING\n" +
|
|
320
|
+
"- 6006: REFERENCE\n" +
|
|
321
|
+
"- 6007: PRODUCTIVITY\n" +
|
|
322
|
+
"- 6008: PHOTO_AND_VIDEO\n" +
|
|
323
|
+
"- 6009: NEWS\n" +
|
|
324
|
+
"- 6010: NAVIGATION\n" +
|
|
325
|
+
"- 6011: MUSIC\n" +
|
|
326
|
+
"- 6012: LIFESTYLE\n" +
|
|
327
|
+
"- 6013: HEALTH_AND_FITNESS\n" +
|
|
328
|
+
"- 6014: GAMES\n" +
|
|
329
|
+
"- 6015: FINANCE\n" +
|
|
330
|
+
"- 6016: ENTERTAINMENT\n" +
|
|
331
|
+
"- 6017: EDUCATION\n" +
|
|
332
|
+
"- 6018: BOOKS\n" +
|
|
333
|
+
"- 6020: MEDICAL\n" +
|
|
334
|
+
"- 6021: MAGAZINES_AND_NEWSPAPERS\n" +
|
|
335
|
+
"- 6022: CATALOGS\n" +
|
|
336
|
+
"- 6023: FOOD_AND_DRINK\n" +
|
|
337
|
+
"- 6024: SHOPPING\n\n" +
|
|
338
|
+
"Games Subcategories:\n" +
|
|
339
|
+
"- 7001: ACTION\n" +
|
|
340
|
+
"- 7002: ADVENTURE\n" +
|
|
341
|
+
"- 7003: ARCADE\n" +
|
|
342
|
+
"- 7004: BOARD\n" +
|
|
343
|
+
"- 7005: CARD\n" +
|
|
344
|
+
"- 7006: CASINO\n" +
|
|
345
|
+
"- 7007: DICE\n" +
|
|
346
|
+
"- 7008: EDUCATIONAL\n" +
|
|
347
|
+
"- 7009: FAMILY\n" +
|
|
348
|
+
"- 7011: MUSIC\n" +
|
|
349
|
+
"- 7012: PUZZLE\n" +
|
|
350
|
+
"- 7013: RACING\n" +
|
|
351
|
+
"- 7014: ROLE_PLAYING\n" +
|
|
352
|
+
"- 7015: SIMULATION\n" +
|
|
353
|
+
"- 7016: SPORTS\n" +
|
|
354
|
+
"- 7017: STRATEGY\n" +
|
|
355
|
+
"- 7018: TRIVIA\n" +
|
|
356
|
+
"- 7019: WORD\n\n" +
|
|
357
|
+
"Magazine Subcategories:\n" +
|
|
358
|
+
"- 13001: POLITICS\n" +
|
|
359
|
+
"- 13002: FASHION\n" +
|
|
360
|
+
"- 13003: HOME\n" +
|
|
361
|
+
"- 13004: OUTDOORS\n" +
|
|
362
|
+
"- 13005: SPORTS\n" +
|
|
363
|
+
"- 13006: AUTOMOTIVE\n" +
|
|
364
|
+
"- 13007: ARTS\n" +
|
|
365
|
+
"- 13008: WEDDINGS\n" +
|
|
366
|
+
"- 13009: BUSINESS\n" +
|
|
367
|
+
"- 13010: CHILDREN\n" +
|
|
368
|
+
"- 13011: COMPUTER\n" +
|
|
369
|
+
"- 13012: FOOD\n" +
|
|
370
|
+
"- 13013: CRAFTS\n" +
|
|
371
|
+
"- 13014: ELECTRONICS\n" +
|
|
372
|
+
"- 13015: ENTERTAINMENT\n" +
|
|
373
|
+
"- 13017: HEALTH\n" +
|
|
374
|
+
"- 13018: HISTORY\n" +
|
|
375
|
+
"- 13019: LITERARY\n" +
|
|
376
|
+
"- 13020: MEN\n" +
|
|
377
|
+
"- 13021: MOVIES_AND_MUSIC\n" +
|
|
378
|
+
"- 13023: FAMILY\n" +
|
|
379
|
+
"- 13024: PETS\n" +
|
|
380
|
+
"- 13025: PROFESSIONAL\n" +
|
|
381
|
+
"- 13026: REGIONAL\n" +
|
|
382
|
+
"- 13027: SCIENCE\n" +
|
|
383
|
+
"- 13028: TEENS\n" +
|
|
384
|
+
"- 13029: TRAVEL\n" +
|
|
385
|
+
"- 13030: WOMEN"
|
|
386
|
+
),
|
|
387
|
+
lang: z.string().optional().describe("Language code for result text. If not provided, uses country-specific language."),
|
|
388
|
+
fullDetail: z.boolean().default(false).describe("Get full app details including ratings, reviews etc (default: false)"),
|
|
389
|
+
country: z.string().default("us").describe("Country code (default: us)"),
|
|
390
|
+
num: z.number().max(200).default(50).describe("Number of results (default: 50, max: 200)")
|
|
391
|
+
},
|
|
392
|
+
async ({ collection, category, country, num, lang, fullDetail }) => {
|
|
393
|
+
const results = await store.list({ collection, category, country, num, lang, fullDetail });
|
|
394
|
+
return { content: [{ type: "text", text: JSON.stringify(results) }] };
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Google Play Tools
|
|
399
|
+
server.tool("google-play-search",
|
|
400
|
+
"Search for apps on Google Play. Returns a list of apps with:\n" +
|
|
401
|
+
"- title: App name\n" +
|
|
402
|
+
"- appId: Package name (e.g. 'com.company.app')\n" +
|
|
403
|
+
"- url: Play Store URL\n" +
|
|
404
|
+
"- icon: Icon image URL\n" +
|
|
405
|
+
"- developer: Developer name\n" +
|
|
406
|
+
"- developerId: Developer ID\n" +
|
|
407
|
+
"- priceText: Price display text\n" +
|
|
408
|
+
"- free: Boolean indicating if app is free\n" +
|
|
409
|
+
"- summary: Short description\n" +
|
|
410
|
+
"- scoreText: Rating display text\n" +
|
|
411
|
+
"- score: Rating (0-5)",
|
|
412
|
+
{
|
|
413
|
+
term: z.string().describe("Search term to query apps"),
|
|
414
|
+
price: z.enum(["all", "free", "paid"]).default("all").describe("Filter by price: all, free, or paid (default: all)"),
|
|
415
|
+
num: z.number().default(20).describe("Number of results to retrieve (default: 20, max: 250)"),
|
|
416
|
+
lang: z.string().default("en").describe("Language code for result text (default: en)"),
|
|
417
|
+
country: z.string().default("us").describe("Country code to get results from (default: us)"),
|
|
418
|
+
fullDetail: z.boolean().default(false).describe("Include full app details in results (default: false)")
|
|
419
|
+
},
|
|
420
|
+
async ({ term, price, num, lang, country, fullDetail }) => {
|
|
421
|
+
const results = await gplay.search({ term, price, num, lang, country, fullDetail });
|
|
422
|
+
return { content: [{ type: "text", text: JSON.stringify(results) }] };
|
|
423
|
+
}
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
server.tool("google-play-details",
|
|
427
|
+
"Get detailed information about a Google Play app. Returns an object with:\n" +
|
|
428
|
+
"- title: App name\n" +
|
|
429
|
+
"- description: Full app description\n" +
|
|
430
|
+
"- descriptionHTML: Description with HTML formatting\n" +
|
|
431
|
+
"- summary: Short description\n" +
|
|
432
|
+
"- installs: Install count range\n" +
|
|
433
|
+
"- minInstalls: Minimum install count\n" +
|
|
434
|
+
"- maxInstalls: Maximum install count\n" +
|
|
435
|
+
"- score: Average rating (0-5)\n" +
|
|
436
|
+
"- scoreText: Rating display text\n" +
|
|
437
|
+
"- ratings: Total number of ratings\n" +
|
|
438
|
+
"- reviews: Total number of reviews\n" +
|
|
439
|
+
"- histogram: Rating distribution by star level\n" +
|
|
440
|
+
"- price: Price in local currency\n" +
|
|
441
|
+
"- free: Boolean indicating if app is free\n" +
|
|
442
|
+
"- currency: Price currency code\n" +
|
|
443
|
+
"- priceText: Formatted price string\n" +
|
|
444
|
+
"- offersIAP: Boolean indicating in-app purchases\n" +
|
|
445
|
+
"- IAPRange: Price range for in-app purchases\n" +
|
|
446
|
+
"- androidVersion: Minimum Android version required\n" +
|
|
447
|
+
"- androidVersionText: Formatted Android version text\n" +
|
|
448
|
+
"- developer: Developer name\n" +
|
|
449
|
+
"- developerId: Developer ID\n" +
|
|
450
|
+
"- developerEmail: Developer contact email\n" +
|
|
451
|
+
"- developerWebsite: Developer website URL\n" +
|
|
452
|
+
"- developerAddress: Developer physical address\n" +
|
|
453
|
+
"- genre: App category\n" +
|
|
454
|
+
"- genreId: Category ID\n" +
|
|
455
|
+
"- icon: Icon URL\n" +
|
|
456
|
+
"- headerImage: Feature graphic URL\n" +
|
|
457
|
+
"- screenshots: Array of screenshot URLs\n" +
|
|
458
|
+
"- contentRating: Content rating (e.g. 'Everyone')\n" +
|
|
459
|
+
"- contentRatingDescription: Content rating details\n" +
|
|
460
|
+
"- adSupported: Boolean indicating if app shows ads\n" +
|
|
461
|
+
"- released: Release date\n" +
|
|
462
|
+
"- updated: Last update date\n" +
|
|
463
|
+
"- version: Current version string\n" +
|
|
464
|
+
"- recentChanges: Latest version changes\n" +
|
|
465
|
+
"- preregister: Boolean indicating if app is in pre-registration\n" +
|
|
466
|
+
"- editorsChoice: Boolean indicating Editor's Choice status\n" +
|
|
467
|
+
"- features: Array of special features",
|
|
468
|
+
{
|
|
469
|
+
appId: z.string().describe("Google Play package name (e.g., 'com.google.android.apps.translate')"),
|
|
470
|
+
lang: z.string().default("en").describe("Language code for result text (default: en)"),
|
|
471
|
+
country: z.string().default("us").describe("Country code to check app availability (default: us)")
|
|
472
|
+
},
|
|
473
|
+
async ({ appId, lang, country }) => {
|
|
474
|
+
const details = await gplay.app({ appId, lang, country });
|
|
475
|
+
return { content: [{ type: "text", text: JSON.stringify(details) }] };
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
server.tool("google-play-reviews",
|
|
480
|
+
"Get reviews for a Google Play app. Returns an array of reviews with:\n" +
|
|
481
|
+
"- id: Review ID string\n" +
|
|
482
|
+
"- userName: Reviewer's name\n" +
|
|
483
|
+
"- userImage: Reviewer's profile image URL\n" +
|
|
484
|
+
"- date: Review date (ISO string)\n" +
|
|
485
|
+
"- score: Rating (1-5)\n" +
|
|
486
|
+
"- scoreText: Rating display text\n" +
|
|
487
|
+
"- title: Review title\n" +
|
|
488
|
+
"- text: Review content\n" +
|
|
489
|
+
"- url: Review URL\n" +
|
|
490
|
+
"- version: App version reviewed\n" +
|
|
491
|
+
"- thumbsUp: Number of thumbs up votes\n" +
|
|
492
|
+
"- replyDate: Developer reply date (if any)\n" +
|
|
493
|
+
"- replyText: Developer reply content (if any)\n" +
|
|
494
|
+
"- criterias: Array of rating criteria (if any)\n" +
|
|
495
|
+
"\nNote: Reviews are returned in the specified language. The total review count\n" +
|
|
496
|
+
"shown in Google Play refers to ratings, not written reviews.",
|
|
497
|
+
{
|
|
498
|
+
appId: z.string().describe("Package name of the app (e.g., 'com.mojang.minecraftpe')"),
|
|
499
|
+
lang: z.string().default("en").describe("Language code for reviews (default: en)"),
|
|
500
|
+
country: z.string().default("us").describe("Country code (default: us)"),
|
|
501
|
+
sort: z.enum(["newest", "rating", "helpfulness"]).default("newest")
|
|
502
|
+
.describe("Sort order: newest, rating, or helpfulness (default: newest)"),
|
|
503
|
+
num: z.number().default(100).describe("Number of reviews to retrieve (default: 100). Ignored if paginate is true."),
|
|
504
|
+
paginate: z.boolean().default(false).describe("Enable pagination with 150 reviews per page"),
|
|
505
|
+
nextPaginationToken: z.string().optional().describe("Token for fetching next page of reviews")
|
|
506
|
+
},
|
|
507
|
+
async ({ appId, lang, country, sort, num, paginate, nextPaginationToken }) => {
|
|
508
|
+
const sortMap = {
|
|
509
|
+
newest: gplay.sort.NEWEST,
|
|
510
|
+
rating: gplay.sort.RATING,
|
|
511
|
+
helpfulness: gplay.sort.HELPFULNESS
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const reviews = await gplay.reviews({
|
|
515
|
+
appId,
|
|
516
|
+
lang,
|
|
517
|
+
country,
|
|
518
|
+
sort: sortMap[sort],
|
|
519
|
+
num,
|
|
520
|
+
paginate,
|
|
521
|
+
nextPaginationToken
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
return {
|
|
525
|
+
content: [{
|
|
526
|
+
type: "text",
|
|
527
|
+
text: JSON.stringify({
|
|
528
|
+
reviews: reviews.data,
|
|
529
|
+
nextPage: reviews.nextPaginationToken
|
|
530
|
+
})
|
|
531
|
+
}]
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
server.tool("google-play-similar",
|
|
537
|
+
"Get similar apps from Google Play. Returns a list of apps with:\n" +
|
|
538
|
+
"- url: Play Store URL\n" +
|
|
539
|
+
"- appId: Package name (e.g. 'com.company.app')\n" +
|
|
540
|
+
"- summary: Short description\n" +
|
|
541
|
+
"- developer: Developer name\n" +
|
|
542
|
+
"- developerId: Developer ID\n" +
|
|
543
|
+
"- icon: Icon image URL\n" +
|
|
544
|
+
"- score: Rating (0-5)\n" +
|
|
545
|
+
"- scoreText: Rating display text\n" +
|
|
546
|
+
"- priceText: Price display text\n" +
|
|
547
|
+
"- free: Boolean indicating if app is free\n",
|
|
548
|
+
{
|
|
549
|
+
appId: z.string().describe("Google Play package name (e.g., 'com.dxco.pandavszombies')"),
|
|
550
|
+
lang: z.string().default("en").describe("Language code for result text (default: en)"),
|
|
551
|
+
country: z.string().default("us").describe("Country code to get results from (default: us)"),
|
|
552
|
+
fullDetail: z.boolean().default(false).describe("Include full app details in results (default: false), If fullDetail is true, includes all fields from app details endpoint.")
|
|
553
|
+
},
|
|
554
|
+
async ({ appId, lang, country, fullDetail }) => {
|
|
555
|
+
const similar = await gplay.similar({ appId, lang, country, fullDetail });
|
|
556
|
+
return { content: [{ type: "text", text: JSON.stringify(similar) }] };
|
|
557
|
+
}
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
// Additional Google Play Tools
|
|
561
|
+
server.tool("google-play-developer",
|
|
562
|
+
"Get apps by a developer on Google Play. Returns a list of apps with:\n" +
|
|
563
|
+
"- url: Play Store URL\n" +
|
|
564
|
+
"- appId: Package name (e.g. 'com.company.app')\n" +
|
|
565
|
+
"- title: App name\n" +
|
|
566
|
+
"- summary: Short app description\n" +
|
|
567
|
+
"- developer: Developer name\n" +
|
|
568
|
+
"- developerId: Developer ID\n" +
|
|
569
|
+
"- icon: Icon image URL\n" +
|
|
570
|
+
"- score: Rating (0-5)\n" +
|
|
571
|
+
"- scoreText: Rating display text\n" +
|
|
572
|
+
"- priceText: Price display text\n" +
|
|
573
|
+
"- free: Boolean indicating if app is free\n",
|
|
574
|
+
{
|
|
575
|
+
devId: z.string().describe("Developer name (e.g., 'DxCo Games')"),
|
|
576
|
+
lang: z.string().default("en").describe("Language code for result text (default: en)"),
|
|
577
|
+
country: z.string().default("us").describe("Country code to get results from (default: us)"),
|
|
578
|
+
num: z.number().default(60).describe("Number of results to retrieve (default: 60)"),
|
|
579
|
+
fullDetail: z.boolean().default(false).describe("Include full app details in results (default: false), If fullDetail is true, includes all fields from app details endpoint.")
|
|
580
|
+
},
|
|
581
|
+
async ({ devId, lang, country, num, fullDetail }) => {
|
|
582
|
+
const apps = await gplay.developer({ devId, lang, country, num, fullDetail });
|
|
583
|
+
return { content: [{ type: "text", text: JSON.stringify(apps) }] };
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
server.tool("google-play-suggest",
|
|
588
|
+
"Get search suggestions from Google Play. Returns an array of suggested search terms (up to 5).\n" +
|
|
589
|
+
"Sample response: ['panda pop', 'panda', 'panda games', 'panda run', 'panda pop for free']",
|
|
590
|
+
{
|
|
591
|
+
term: z.string().describe("Search term to get suggestions for (e.g., 'panda')"),
|
|
592
|
+
lang: z.string().default("en").describe("Language code for suggestions (default: en)"),
|
|
593
|
+
country: z.string().default("us").describe("Country code to get suggestions from (default: us)")
|
|
594
|
+
},
|
|
595
|
+
async ({ term, lang, country }) => {
|
|
596
|
+
const suggestions = await gplay.suggest({ term, lang, country });
|
|
597
|
+
// API returns array of strings directly
|
|
598
|
+
return { content: [{ type: "text", text: JSON.stringify(suggestions) }] };
|
|
599
|
+
}
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
server.tool("google-play-permissions",
|
|
603
|
+
"Get permissions required by a Google Play app. Returns a list of permissions with:\n" +
|
|
604
|
+
"- permission: Description of the permission (e.g., 'modify storage contents')\n" +
|
|
605
|
+
"- type: Permission category (e.g., 'Storage', 'Network')\n\n" +
|
|
606
|
+
"When short=true, returns just an array of permission strings.\n" +
|
|
607
|
+
"Note: Permissions are returned in the specified language.",
|
|
608
|
+
{
|
|
609
|
+
appId: z.string().describe("Google Play package name (e.g., 'com.dxco.pandavszombies')"),
|
|
610
|
+
lang: z.string().default("en").describe("Language code for permission text (default: en)"),
|
|
611
|
+
country: z.string().default("us").describe("Country code to check app (default: us)"),
|
|
612
|
+
short: z.boolean().default(false).describe("Return only permission names without categories (default: false)")
|
|
613
|
+
},
|
|
614
|
+
async ({ appId, lang, country, short }) => {
|
|
615
|
+
const permissions = await gplay.permissions({ appId, lang, country, short });
|
|
616
|
+
return { content: [{ type: "text", text: JSON.stringify(permissions) }] };
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
server.tool("google-play-datasafety",
|
|
621
|
+
"Get data safety information for a Google Play app. Returns an object with:\n" +
|
|
622
|
+
"- dataShared: Array of shared data items, each containing:\n" +
|
|
623
|
+
" - data: Name of the data being shared (e.g., 'User IDs')\n" +
|
|
624
|
+
" - optional: Boolean indicating if sharing is optional\n" +
|
|
625
|
+
" - purpose: Comma-separated list of purposes (e.g., 'Analytics, Marketing')\n" +
|
|
626
|
+
" - type: Category of data (e.g., 'Personal info')\n" +
|
|
627
|
+
"- dataCollected: Array of collected data items with same structure as dataShared\n" +
|
|
628
|
+
"- securityPractices: Array of security practices, each containing:\n" +
|
|
629
|
+
" - practice: Name of the security practice\n" +
|
|
630
|
+
" - description: Detailed description of the practice\n" +
|
|
631
|
+
"- privacyPolicyUrl: URL to the app's privacy policy\n\n" +
|
|
632
|
+
"Data types can include: Personal info, Financial info, Messages, Contacts,\n" +
|
|
633
|
+
"App activity, App info and performance, Device or other IDs",
|
|
634
|
+
{
|
|
635
|
+
appId: z.string().describe("Google Play package name (e.g., 'com.dxco.pandavszombies')"),
|
|
636
|
+
lang: z.string().default("en").describe("Language code for data safety info (default: en)")
|
|
637
|
+
},
|
|
638
|
+
async ({ appId, lang }) => {
|
|
639
|
+
const datasafety = await gplay.datasafety({ appId, lang });
|
|
640
|
+
return { content: [{ type: "text", text: JSON.stringify(datasafety) }] };
|
|
641
|
+
}
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
server.tool("google-play-categories",
|
|
645
|
+
"Get list of all Google Play categories. Returns an array of category identifiers like:\n" +
|
|
646
|
+
"- 'APPLICATION': All applications\n" +
|
|
647
|
+
"- 'GAME': All games\n" +
|
|
648
|
+
"- 'ANDROID_WEAR': Wear OS apps\n" +
|
|
649
|
+
"- 'SOCIAL': Social apps\n" +
|
|
650
|
+
"- 'PRODUCTIVITY': Productivity apps\n" +
|
|
651
|
+
"etc.\n\n" +
|
|
652
|
+
"These category IDs can be used with the google-play-list tool to filter apps by category.\n" +
|
|
653
|
+
"Sample response: ['AUTO_AND_VEHICLES', 'LIBRARIES_AND_DEMO', 'LIFESTYLE', ...]",
|
|
654
|
+
{}, // No parameters needed
|
|
655
|
+
async () => {
|
|
656
|
+
const categories = await gplay.categories();
|
|
657
|
+
return { content: [{ type: "text", text: JSON.stringify(categories) }] };
|
|
658
|
+
}
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
server.tool("google-play-list",
|
|
662
|
+
"Get apps from Google Play collections. Returns a list of apps with:\n" +
|
|
663
|
+
"- url: Play Store URL\n" +
|
|
664
|
+
"- appId: Package name (e.g., 'com.company.app')\n" +
|
|
665
|
+
"- title: App name\n" +
|
|
666
|
+
"- summary: Short description\n" +
|
|
667
|
+
"- developer: Developer name\n" +
|
|
668
|
+
"- developerId: Developer ID\n" +
|
|
669
|
+
"- icon: Icon URL\n" +
|
|
670
|
+
"- score: Rating (0-5)\n" +
|
|
671
|
+
"- scoreText: Rating display text\n" +
|
|
672
|
+
"- priceText: Price display text\n" +
|
|
673
|
+
"- free: Boolean indicating if app is free\n\n" +
|
|
674
|
+
"When fullDetail is true, includes all fields from app details endpoint.",
|
|
675
|
+
{
|
|
676
|
+
collection: z.enum(['TOP_FREE', 'TOP_PAID', 'GROSSING', 'TOP_FREE_GAMES', 'TOP_PAID_GAMES', 'TOP_GROSSING_GAMES'])
|
|
677
|
+
.default('TOP_FREE')
|
|
678
|
+
.describe(
|
|
679
|
+
"Collection to fetch apps from (default: TOP_FREE). Available collections:\n" +
|
|
680
|
+
"- TOP_FREE: Top free applications\n" +
|
|
681
|
+
"- TOP_PAID: Top paid applications\n" +
|
|
682
|
+
"- GROSSING: Top grossing applications"
|
|
683
|
+
),
|
|
684
|
+
category: z.enum([
|
|
685
|
+
'APPLICATION',
|
|
686
|
+
'ANDROID_WEAR',
|
|
687
|
+
'ART_AND_DESIGN',
|
|
688
|
+
'AUTO_AND_VEHICLES',
|
|
689
|
+
'BEAUTY',
|
|
690
|
+
'BOOKS_AND_REFERENCE',
|
|
691
|
+
'BUSINESS',
|
|
692
|
+
'COMICS',
|
|
693
|
+
'COMMUNICATION',
|
|
694
|
+
'DATING',
|
|
695
|
+
'EDUCATION',
|
|
696
|
+
'ENTERTAINMENT',
|
|
697
|
+
'EVENTS',
|
|
698
|
+
'FINANCE',
|
|
699
|
+
'FOOD_AND_DRINK',
|
|
700
|
+
'HEALTH_AND_FITNESS',
|
|
701
|
+
'HOUSE_AND_HOME',
|
|
702
|
+
'LIBRARIES_AND_DEMO',
|
|
703
|
+
'LIFESTYLE',
|
|
704
|
+
'MAPS_AND_NAVIGATION',
|
|
705
|
+
'MEDICAL',
|
|
706
|
+
'MUSIC_AND_AUDIO',
|
|
707
|
+
'NEWS_AND_MAGAZINES',
|
|
708
|
+
'PARENTING',
|
|
709
|
+
'PERSONALIZATION',
|
|
710
|
+
'PHOTOGRAPHY',
|
|
711
|
+
'PRODUCTIVITY',
|
|
712
|
+
'SHOPPING',
|
|
713
|
+
'SOCIAL',
|
|
714
|
+
'SPORTS',
|
|
715
|
+
'TOOLS',
|
|
716
|
+
'TRAVEL_AND_LOCAL',
|
|
717
|
+
'VIDEO_PLAYERS',
|
|
718
|
+
'WATCH_FACE',
|
|
719
|
+
'WEATHER',
|
|
720
|
+
'GAME',
|
|
721
|
+
'GAME_ACTION',
|
|
722
|
+
'GAME_ADVENTURE',
|
|
723
|
+
'GAME_ARCADE',
|
|
724
|
+
'GAME_BOARD',
|
|
725
|
+
'GAME_CARD',
|
|
726
|
+
'GAME_CASINO',
|
|
727
|
+
'GAME_CASUAL',
|
|
728
|
+
'GAME_EDUCATIONAL',
|
|
729
|
+
'GAME_MUSIC',
|
|
730
|
+
'GAME_PUZZLE',
|
|
731
|
+
'GAME_RACING',
|
|
732
|
+
'GAME_ROLE_PLAYING',
|
|
733
|
+
'GAME_SIMULATION',
|
|
734
|
+
'GAME_SPORTS',
|
|
735
|
+
'GAME_STRATEGY',
|
|
736
|
+
'GAME_TRIVIA',
|
|
737
|
+
'GAME_WORD',
|
|
738
|
+
'FAMILY'
|
|
739
|
+
]).optional().describe(
|
|
740
|
+
"Category to filter by. Available categories:\n" +
|
|
741
|
+
"Main Categories:\n" +
|
|
742
|
+
"- APPLICATION: All applications\n" +
|
|
743
|
+
"- ANDROID_WEAR: Wear OS apps\n" +
|
|
744
|
+
"- ART_AND_DESIGN: Art & Design\n" +
|
|
745
|
+
"- AUTO_AND_VEHICLES: Auto & Vehicles\n" +
|
|
746
|
+
"- BEAUTY: Beauty\n" +
|
|
747
|
+
"- BOOKS_AND_REFERENCE: Books & Reference\n" +
|
|
748
|
+
"- BUSINESS: Business\n" +
|
|
749
|
+
"- COMICS: Comics\n" +
|
|
750
|
+
"- COMMUNICATION: Communication\n" +
|
|
751
|
+
"- DATING: Dating\n" +
|
|
752
|
+
"- EDUCATION: Education\n" +
|
|
753
|
+
"- ENTERTAINMENT: Entertainment\n" +
|
|
754
|
+
"- EVENTS: Events\n" +
|
|
755
|
+
"- FINANCE: Finance\n" +
|
|
756
|
+
"- FOOD_AND_DRINK: Food & Drink\n" +
|
|
757
|
+
"- HEALTH_AND_FITNESS: Health & Fitness\n" +
|
|
758
|
+
"- HOUSE_AND_HOME: House & Home\n" +
|
|
759
|
+
"- LIFESTYLE: Lifestyle\n" +
|
|
760
|
+
"- MAPS_AND_NAVIGATION: Maps & Navigation\n" +
|
|
761
|
+
"- MEDICAL: Medical\n" +
|
|
762
|
+
"- MUSIC_AND_AUDIO: Music & Audio\n" +
|
|
763
|
+
"- NEWS_AND_MAGAZINES: News & Magazines\n" +
|
|
764
|
+
"- PARENTING: Parenting\n" +
|
|
765
|
+
"- PERSONALIZATION: Personalization\n" +
|
|
766
|
+
"- PHOTOGRAPHY: Photography\n" +
|
|
767
|
+
"- PRODUCTIVITY: Productivity\n" +
|
|
768
|
+
"- SHOPPING: Shopping\n" +
|
|
769
|
+
"- SOCIAL: Social\n" +
|
|
770
|
+
"- SPORTS: Sports\n" +
|
|
771
|
+
"- TOOLS: Tools\n" +
|
|
772
|
+
"- TRAVEL_AND_LOCAL: Travel & Local\n" +
|
|
773
|
+
"- VIDEO_PLAYERS: Video Players\n" +
|
|
774
|
+
"- WATCH_FACE: Watch Faces\n" +
|
|
775
|
+
"- WEATHER: Weather\n\n" +
|
|
776
|
+
"Game Categories:\n" +
|
|
777
|
+
"- GAME: All Games\n" +
|
|
778
|
+
"- GAME_ACTION: Action Games\n" +
|
|
779
|
+
"- GAME_ADVENTURE: Adventure Games\n" +
|
|
780
|
+
"- GAME_ARCADE: Arcade Games\n" +
|
|
781
|
+
"- GAME_BOARD: Board Games\n" +
|
|
782
|
+
"- GAME_CARD: Card Games\n" +
|
|
783
|
+
"- GAME_CASINO: Casino Games\n" +
|
|
784
|
+
"- GAME_CASUAL: Casual Games\n" +
|
|
785
|
+
"- GAME_EDUCATIONAL: Educational Games\n" +
|
|
786
|
+
"- GAME_MUSIC: Music Games\n" +
|
|
787
|
+
"- GAME_PUZZLE: Puzzle Games\n" +
|
|
788
|
+
"- GAME_RACING: Racing Games\n" +
|
|
789
|
+
"- GAME_ROLE_PLAYING: Role Playing Games\n" +
|
|
790
|
+
"- GAME_SIMULATION: Simulation Games\n" +
|
|
791
|
+
"- GAME_SPORTS: Sports Games\n" +
|
|
792
|
+
"- GAME_STRATEGY: Strategy Games\n" +
|
|
793
|
+
"- GAME_TRIVIA: Trivia Games\n" +
|
|
794
|
+
"- GAME_WORD: Word Games\n" +
|
|
795
|
+
"- FAMILY: Family Games"
|
|
796
|
+
),
|
|
797
|
+
age: z.enum(['FIVE_UNDER', 'SIX_EIGHT', 'NINE_UP'])
|
|
798
|
+
.optional()
|
|
799
|
+
.describe("Age range filter (only for FAMILY category). Options: FIVE_UNDER, SIX_EIGHT, NINE_UP"),
|
|
800
|
+
num: z.number()
|
|
801
|
+
.default(500)
|
|
802
|
+
.describe("Number of apps to retrieve (default: 500)"),
|
|
803
|
+
lang: z.string()
|
|
804
|
+
.default("en")
|
|
805
|
+
.describe("Language code for result text (default: en)"),
|
|
806
|
+
country: z.string()
|
|
807
|
+
.default("us")
|
|
808
|
+
.describe("Country code to get results from (default: us)"),
|
|
809
|
+
fullDetail: z.boolean()
|
|
810
|
+
.default(false)
|
|
811
|
+
.describe("Include full app details in results (default: false)")
|
|
812
|
+
},
|
|
813
|
+
async ({ collection, category, age, num, lang, country, fullDetail }) => {
|
|
814
|
+
const results = await gplay.list({
|
|
815
|
+
collection,
|
|
816
|
+
category,
|
|
817
|
+
age,
|
|
818
|
+
num,
|
|
819
|
+
lang,
|
|
820
|
+
country,
|
|
821
|
+
fullDetail
|
|
822
|
+
});
|
|
823
|
+
return { content: [{ type: "text", text: JSON.stringify(results) }] };
|
|
824
|
+
}
|
|
825
|
+
);
|
|
826
|
+
|
|
827
|
+
const transport = new StdioServerTransport();
|
|
828
|
+
await server.connect(transport);
|