admanagekit-mcp-server 1.0.0
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/content/README.md +851 -0
- package/content/docs/AD_FREQUENCY_CONTROL.md +450 -0
- package/content/docs/AD_LOADING_STRATEGIES.md +369 -0
- package/content/docs/API_REFERENCE.md +734 -0
- package/content/docs/APP_PURCHASE_GUIDE.md +704 -0
- package/content/docs/BANNER_AD_IMPROVEMENTS.md +325 -0
- package/content/docs/COMPOSE_INTEGRATION.md +477 -0
- package/content/docs/CONFIGURATION_USAGE.md +168 -0
- package/content/docs/INTERSTITIAL_BUILDER_GUIDE.md +518 -0
- package/content/docs/JAVA_USAGE_GUIDE.md +785 -0
- package/content/docs/LOADING_STRATEGY_EXAMPLES.md +463 -0
- package/content/docs/NATIVE_AD_MANAGER_ENHANCEMENTS.md +347 -0
- package/content/docs/NATIVE_AD_PRELOADING.md +467 -0
- package/content/docs/NATIVE_TEMPLATE_VIEW.md +413 -0
- package/content/docs/app-open-ads.md +412 -0
- package/content/docs/interstitial-ads.md +269 -0
- package/content/docs/native-ads-caching.md +182 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.1.0.md +156 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.2.0.md +248 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.3.0.md +280 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.5.0.md +73 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.6.0.md +265 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.7.0.md +168 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.8.0.md +153 -0
- package/content/docs/release-notes/RELEASE_NOTES_v2.9.0.md +479 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.0.0.md +343 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.1.0.md +131 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.0.md +252 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.2.md +215 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.3.md +116 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.4.md +142 -0
- package/content/docs/release-notes/RELEASE_NOTES_v3.3.5.md +94 -0
- package/content/docs/rewarded-ads.md +623 -0
- package/content/wiki/Ad-Loading-Strategies.md +209 -0
- package/content/wiki/App-Open-Ads.md +189 -0
- package/content/wiki/Banner-Ads.md +133 -0
- package/content/wiki/Billing-Integration.md +69 -0
- package/content/wiki/Configuration.md +252 -0
- package/content/wiki/Consumable-Products.md +166 -0
- package/content/wiki/Home.md +144 -0
- package/content/wiki/Interstitial-Ads.md +313 -0
- package/content/wiki/Jetpack-Compose.md +270 -0
- package/content/wiki/NativeAdManager.md +220 -0
- package/content/wiki/Purchase-Categories.md +94 -0
- package/content/wiki/Rewarded-Ads.md +420 -0
- package/content/wiki/Subscription-Upgrades.md +278 -0
- package/content/wiki/Subscriptions.md +368 -0
- package/content/wiki/_Footer.md +3 -0
- package/content/wiki/_Sidebar.md +18 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +18 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/code-generation.d.ts +2 -0
- package/dist/tools/code-generation.js +264 -0
- package/dist/tools/code-generation.js.map +1 -0
- package/dist/tools/documentation.d.ts +2 -0
- package/dist/tools/documentation.js +202 -0
- package/dist/tools/documentation.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +83 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/doc-loader.d.ts +17 -0
- package/dist/utils/doc-loader.js +245 -0
- package/dist/utils/doc-loader.js.map +1 -0
- package/dist/utils/search.d.ts +2 -0
- package/dist/utils/search.js +62 -0
- package/dist/utils/search.js.map +1 -0
- package/dist/utils/templates.d.ts +60 -0
- package/dist/utils/templates.js +793 -0
- package/dist/utils/templates.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Subscriptions
|
|
2
|
+
|
|
3
|
+
AdManageKit provides comprehensive subscription management including state tracking, upgrade/downgrade support, and lifecycle management.
|
|
4
|
+
|
|
5
|
+
## Setting Up Subscriptions
|
|
6
|
+
|
|
7
|
+
### Define Subscription Products
|
|
8
|
+
|
|
9
|
+
```kotlin
|
|
10
|
+
val products = listOf(
|
|
11
|
+
// Subscription with free trial offer
|
|
12
|
+
PurchaseItem("premium_monthly", "free_trial_7d", TYPE_IAP.SUBSCRIPTION),
|
|
13
|
+
|
|
14
|
+
// Subscription without trial
|
|
15
|
+
PurchaseItem("premium_yearly", null, TYPE_IAP.SUBSCRIPTION),
|
|
16
|
+
|
|
17
|
+
// Multiple tiers
|
|
18
|
+
PurchaseItem("basic_monthly", null, TYPE_IAP.SUBSCRIPTION),
|
|
19
|
+
PurchaseItem("pro_monthly", "intro_offer", TYPE_IAP.SUBSCRIPTION)
|
|
20
|
+
)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Initialize
|
|
24
|
+
|
|
25
|
+
```kotlin
|
|
26
|
+
AppPurchase.getInstance().initBilling(application, products)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Subscribing
|
|
30
|
+
|
|
31
|
+
```kotlin
|
|
32
|
+
// Start subscription flow
|
|
33
|
+
AppPurchase.getInstance().subscribe(activity, "premium_monthly")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Subscription States
|
|
37
|
+
|
|
38
|
+
### State Enum
|
|
39
|
+
|
|
40
|
+
```kotlin
|
|
41
|
+
enum class SubscriptionState {
|
|
42
|
+
ACTIVE, // Subscribed and will renew
|
|
43
|
+
CANCELLED, // Cancelled but still has access
|
|
44
|
+
GRACE_PERIOD, // Payment issue, still has access (server-side only)
|
|
45
|
+
ON_HOLD, // Payment issue, no access (server-side only)
|
|
46
|
+
PAUSED, // User paused (server-side only)
|
|
47
|
+
EXPIRED, // Subscription ended
|
|
48
|
+
NOT_SUBSCRIPTION // Product is not a subscription
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Client-Side Detection
|
|
53
|
+
|
|
54
|
+
| State | Detectable Client-Side | How |
|
|
55
|
+
|-------|----------------------|-----|
|
|
56
|
+
| ACTIVE | Yes | `isAutoRenewing = true` |
|
|
57
|
+
| CANCELLED | Yes | `isAutoRenewing = false`, still in purchase list |
|
|
58
|
+
| GRACE_PERIOD | No | Requires server API |
|
|
59
|
+
| ON_HOLD | No | Requires server API |
|
|
60
|
+
| PAUSED | No | Requires server API |
|
|
61
|
+
| EXPIRED | Yes | Not returned by `queryPurchasesAsync` |
|
|
62
|
+
|
|
63
|
+
## Checking Subscription Status
|
|
64
|
+
|
|
65
|
+
### Basic Checks
|
|
66
|
+
|
|
67
|
+
```kotlin
|
|
68
|
+
// Any subscription active?
|
|
69
|
+
if (AppPurchase.getInstance().isSubscribed()) {
|
|
70
|
+
showPremiumContent()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Specific subscription active?
|
|
74
|
+
if (AppPurchase.getInstance().isSubscribed("premium_yearly")) {
|
|
75
|
+
showYearlyBenefits()
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Get Subscription State
|
|
80
|
+
|
|
81
|
+
```kotlin
|
|
82
|
+
val state = AppPurchase.getInstance().getSubscriptionState("premium_monthly")
|
|
83
|
+
|
|
84
|
+
when (state) {
|
|
85
|
+
SubscriptionState.ACTIVE -> {
|
|
86
|
+
// User is subscribed and will renew
|
|
87
|
+
showPremiumUI()
|
|
88
|
+
}
|
|
89
|
+
SubscriptionState.CANCELLED -> {
|
|
90
|
+
// User cancelled but still has access until expiration
|
|
91
|
+
showRenewalPrompt()
|
|
92
|
+
}
|
|
93
|
+
SubscriptionState.EXPIRED -> {
|
|
94
|
+
// Subscription ended
|
|
95
|
+
showSubscribeButton()
|
|
96
|
+
}
|
|
97
|
+
else -> {
|
|
98
|
+
// Not subscribed or other state
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Additional Checks
|
|
104
|
+
|
|
105
|
+
```kotlin
|
|
106
|
+
// Check if any subscription is cancelled (but still active)
|
|
107
|
+
if (AppPurchase.getInstance().hasSubscriptionCancelled()) {
|
|
108
|
+
showResubscribePrompt()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check if all subscriptions will renew
|
|
112
|
+
if (AppPurchase.getInstance().willSubscriptionsRenew()) {
|
|
113
|
+
// User is committed subscriber
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Get all active subscriptions
|
|
117
|
+
val subscriptions = AppPurchase.getInstance().getActiveSubscriptions()
|
|
118
|
+
for (sub in subscriptions) {
|
|
119
|
+
println("${sub.getFirstProductId()}: ${sub.getSubscriptionStateString()}")
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Subscription Details
|
|
124
|
+
|
|
125
|
+
### Get Subscription PurchaseResult
|
|
126
|
+
|
|
127
|
+
```kotlin
|
|
128
|
+
val subscription = AppPurchase.getInstance().getSubscription("premium_monthly")
|
|
129
|
+
if (subscription != null) {
|
|
130
|
+
// Basic info
|
|
131
|
+
val orderId = subscription.orderId
|
|
132
|
+
val purchaseTime = subscription.getPurchaseTimeFormatted()
|
|
133
|
+
|
|
134
|
+
// State info
|
|
135
|
+
val isActive = subscription.isSubscriptionActive()
|
|
136
|
+
val willRenew = subscription.willSubscriptionRenew()
|
|
137
|
+
val isCancelled = subscription.isSubscriptionCancelled()
|
|
138
|
+
val stateString = subscription.getSubscriptionStateString()
|
|
139
|
+
|
|
140
|
+
// Display
|
|
141
|
+
showSubscriptionInfo(
|
|
142
|
+
status = stateString, // "Active", "Cancelled (access until expiration)"
|
|
143
|
+
since = purchaseTime, // "2024-01-15 14:30:00"
|
|
144
|
+
willRenew = willRenew // true/false
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Subscription Pricing
|
|
150
|
+
|
|
151
|
+
```kotlin
|
|
152
|
+
// Get formatted price
|
|
153
|
+
val monthlyPrice = AppPurchase.getInstance().getPriceSub("premium_monthly")
|
|
154
|
+
// "$9.99"
|
|
155
|
+
|
|
156
|
+
val yearlyPrice = AppPurchase.getInstance().getPriceSub("premium_yearly")
|
|
157
|
+
// "$99.99"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Trial Offers
|
|
161
|
+
|
|
162
|
+
Specify trial offer ID when creating PurchaseItem:
|
|
163
|
+
|
|
164
|
+
```kotlin
|
|
165
|
+
// The second parameter is the offer ID from Google Play Console
|
|
166
|
+
PurchaseItem("premium_monthly", "free_trial_7d", TYPE_IAP.SUBSCRIPTION)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The library automatically selects the matching offer when subscribing.
|
|
170
|
+
|
|
171
|
+
## Handling Subscription Changes
|
|
172
|
+
|
|
173
|
+
See [[Subscription Upgrades]] for upgrade/downgrade handling.
|
|
174
|
+
|
|
175
|
+
## Best Practices
|
|
176
|
+
|
|
177
|
+
### 1. Always Show Subscription State
|
|
178
|
+
|
|
179
|
+
```kotlin
|
|
180
|
+
fun updateSubscriptionUI() {
|
|
181
|
+
val state = AppPurchase.getInstance().getSubscriptionState("premium_monthly")
|
|
182
|
+
|
|
183
|
+
subscriptionBadge.text = when (state) {
|
|
184
|
+
SubscriptionState.ACTIVE -> "Premium Member"
|
|
185
|
+
SubscriptionState.CANCELLED -> "Premium (Expires Soon)"
|
|
186
|
+
else -> "Free User"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 2. Prompt Cancelled Users to Resubscribe
|
|
192
|
+
|
|
193
|
+
```kotlin
|
|
194
|
+
if (AppPurchase.getInstance().hasSubscriptionCancelled()) {
|
|
195
|
+
showDialog(
|
|
196
|
+
title = "Your subscription is ending",
|
|
197
|
+
message = "Renew now to keep premium features",
|
|
198
|
+
action = "Renew" to { reopenSubscription() }
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fun reopenSubscription() {
|
|
203
|
+
// This will show the resubscribe flow in Google Play
|
|
204
|
+
AppPurchase.getInstance().subscribe(activity, "premium_monthly")
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 3. Restore Purchases on App Start
|
|
209
|
+
|
|
210
|
+
```kotlin
|
|
211
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
212
|
+
super.onCreate(savedInstanceState)
|
|
213
|
+
|
|
214
|
+
// Verify purchases to restore subscription state
|
|
215
|
+
AppPurchase.getInstance().verifyPurchased(true)
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 4. Handle Grace Period (Server-Side)
|
|
220
|
+
|
|
221
|
+
For grace period detection, implement server-side verification using Google Play Developer API and Real-time Developer Notifications (RTDN).
|
|
222
|
+
|
|
223
|
+
## Subscription Expiry Verification
|
|
224
|
+
|
|
225
|
+
The Google Play Billing Library does NOT provide subscription expiry dates client-side. To get accurate expiry dates, you need server-side verification.
|
|
226
|
+
|
|
227
|
+
### Setting Up Verification Callback
|
|
228
|
+
|
|
229
|
+
```kotlin
|
|
230
|
+
// In Application.onCreate() or early initialization
|
|
231
|
+
AppPurchase.getInstance().setSubscriptionVerificationCallback { packageName, subscriptionId, purchaseToken, listener ->
|
|
232
|
+
// Call your backend API
|
|
233
|
+
yourBackendApi.verifySubscription(packageName, subscriptionId, purchaseToken,
|
|
234
|
+
onSuccess = { expiryTimeMillis, isAutoRenewing ->
|
|
235
|
+
val details = SubscriptionVerificationCallback.SubscriptionDetails.Builder()
|
|
236
|
+
.setExpiryTimeMillis(expiryTimeMillis)
|
|
237
|
+
.setAutoRenewing(isAutoRenewing)
|
|
238
|
+
.build()
|
|
239
|
+
listener.onVerified(details)
|
|
240
|
+
},
|
|
241
|
+
onError = { error ->
|
|
242
|
+
listener.onVerificationFailed(error)
|
|
243
|
+
}
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Verifying a Subscription
|
|
249
|
+
|
|
250
|
+
```kotlin
|
|
251
|
+
AppPurchase.getInstance().verifySubscription("premium_monthly",
|
|
252
|
+
object : AppPurchase.SubscriptionVerificationListener {
|
|
253
|
+
override fun onVerified(subscription: PurchaseResult) {
|
|
254
|
+
// Expiry info now available
|
|
255
|
+
val expiryDate = subscription.getExpiryTimeFormatted("dd MMM yyyy")
|
|
256
|
+
val remainingDays = subscription.getRemainingDays()
|
|
257
|
+
val isExpired = subscription.isExpired()
|
|
258
|
+
|
|
259
|
+
updateUI(expiryDate, remainingDays)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
override fun onVerificationFailed(errorMessage: String?) {
|
|
263
|
+
Log.e("Subscription", "Verification failed: $errorMessage")
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
// Verify all active subscriptions at once
|
|
269
|
+
AppPurchase.getInstance().verifyAllSubscriptions(listener)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Getting Expiry Information
|
|
273
|
+
|
|
274
|
+
After verification, expiry data is stored and accessible:
|
|
275
|
+
|
|
276
|
+
```kotlin
|
|
277
|
+
// Get expiry time in milliseconds
|
|
278
|
+
val expiryMillis = AppPurchase.getInstance().getSubscriptionExpiryTime("premium_monthly")
|
|
279
|
+
|
|
280
|
+
// Get formatted expiry date
|
|
281
|
+
val expiryDate = AppPurchase.getInstance().getSubscriptionExpiryTimeFormatted("premium_monthly")
|
|
282
|
+
// "2024-03-15 14:30:00"
|
|
283
|
+
|
|
284
|
+
// Custom format
|
|
285
|
+
val customFormat = AppPurchase.getInstance().getSubscriptionExpiryTimeFormatted("premium_monthly", "dd MMM yyyy")
|
|
286
|
+
// "15 Mar 2024"
|
|
287
|
+
|
|
288
|
+
// Get remaining days
|
|
289
|
+
val daysLeft = AppPurchase.getInstance().getSubscriptionRemainingDays("premium_monthly")
|
|
290
|
+
// 30
|
|
291
|
+
|
|
292
|
+
// Check if expired
|
|
293
|
+
val isExpired = AppPurchase.getInstance().isSubscriptionExpired("premium_monthly")
|
|
294
|
+
// false
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Using PurchaseResult Directly
|
|
298
|
+
|
|
299
|
+
```kotlin
|
|
300
|
+
val subscription = AppPurchase.getInstance().getSubscription("premium_monthly")
|
|
301
|
+
if (subscription != null && subscription.isExpiryVerified()) {
|
|
302
|
+
// Expiry data available
|
|
303
|
+
val expiryDate = subscription.getExpiryDate() // Date object
|
|
304
|
+
val expiryFormatted = subscription.getExpiryTimeFormatted() // String
|
|
305
|
+
val remainingDays = subscription.getRemainingDays() // Int (-1 if not verified)
|
|
306
|
+
val remainingMillis = subscription.getRemainingTime() // Long (-1 if not verified)
|
|
307
|
+
val isExpired = subscription.isExpired() // Boolean
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Backend API Implementation
|
|
312
|
+
|
|
313
|
+
Your backend should call Google Play Developer API:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptionsv2/tokens/{purchaseToken}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Response includes:
|
|
320
|
+
- `expiryTime` - RFC 3339 timestamp
|
|
321
|
+
- `subscriptionState` - ACTIVE, CANCELED, IN_GRACE_PERIOD, ON_HOLD, PAUSED, EXPIRED
|
|
322
|
+
- `linkedPurchaseToken` - For upgrade/downgrade tracking
|
|
323
|
+
|
|
324
|
+
### Example: Show Subscription Status UI
|
|
325
|
+
|
|
326
|
+
```kotlin
|
|
327
|
+
fun updateSubscriptionUI() {
|
|
328
|
+
val subscription = AppPurchase.getInstance().getSubscription("premium_monthly")
|
|
329
|
+
|
|
330
|
+
if (subscription == null) {
|
|
331
|
+
showNotSubscribedUI()
|
|
332
|
+
return
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!subscription.isExpiryVerified()) {
|
|
336
|
+
// Verify first
|
|
337
|
+
AppPurchase.getInstance().verifySubscription("premium_monthly",
|
|
338
|
+
object : AppPurchase.SubscriptionVerificationListener {
|
|
339
|
+
override fun onVerified(sub: PurchaseResult) {
|
|
340
|
+
showSubscriptionDetails(sub)
|
|
341
|
+
}
|
|
342
|
+
override fun onVerificationFailed(error: String?) {
|
|
343
|
+
showBasicSubscriptionUI(subscription)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
)
|
|
347
|
+
} else {
|
|
348
|
+
showSubscriptionDetails(subscription)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
fun showSubscriptionDetails(subscription: PurchaseResult) {
|
|
353
|
+
val daysLeft = subscription.getRemainingDays()
|
|
354
|
+
|
|
355
|
+
when {
|
|
356
|
+
subscription.isExpired() -> {
|
|
357
|
+
statusText.text = "Subscription Expired"
|
|
358
|
+
renewButton.visibility = View.VISIBLE
|
|
359
|
+
}
|
|
360
|
+
daysLeft <= 7 && !subscription.isAutoRenewing -> {
|
|
361
|
+
statusText.text = "Expires in $daysLeft days"
|
|
362
|
+
renewPrompt.visibility = View.VISIBLE
|
|
363
|
+
}
|
|
364
|
+
else -> {
|
|
365
|
+
statusText.text = "Premium until ${subscription.getExpiryTimeFormatted("dd MMM yyyy")}"
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
### Ad Types
|
|
2
|
+
- [[Interstitial Ads]]
|
|
3
|
+
- [[Rewarded Ads]]
|
|
4
|
+
- [[App Open Ads]]
|
|
5
|
+
- [[Native Ads|NativeAdManager]]
|
|
6
|
+
- [[Banner Ads]]
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
- [[Ad Loading Strategies]]
|
|
10
|
+
- [[Configuration]]
|
|
11
|
+
- [[Jetpack Compose]]
|
|
12
|
+
|
|
13
|
+
### Billing
|
|
14
|
+
- [[Billing Integration]]
|
|
15
|
+
- [[Purchase Categories]]
|
|
16
|
+
- [[Consumable Products]]
|
|
17
|
+
- [[Subscriptions]]
|
|
18
|
+
- [[Subscription Upgrades]]
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,2CAA0C;AAE1C,IAAA,uBAAW,GAAE,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startServer(): Promise<void>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startServer = startServer;
|
|
4
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const documentation_js_1 = require("./tools/documentation.js");
|
|
7
|
+
const code_generation_js_1 = require("./tools/code-generation.js");
|
|
8
|
+
async function startServer() {
|
|
9
|
+
const server = new mcp_js_1.McpServer({
|
|
10
|
+
name: "admanagekit-docs",
|
|
11
|
+
version: "1.0.0",
|
|
12
|
+
});
|
|
13
|
+
(0, documentation_js_1.registerDocumentationTools)(server);
|
|
14
|
+
(0, code_generation_js_1.registerCodeGenerationTools)(server);
|
|
15
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
16
|
+
await server.connect(transport);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;AAKA,kCAWC;AAhBD,oEAAoE;AACpE,wEAAiF;AACjF,+DAAsE;AACtE,mEAAyE;AAElE,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC;QAC3B,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,IAAA,6CAA0B,EAAC,MAAM,CAAC,CAAC;IACnC,IAAA,gDAA2B,EAAC,MAAM,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerCodeGenerationTools = registerCodeGenerationTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const templates_js_1 = require("../utils/templates.js");
|
|
6
|
+
function registerCodeGenerationTools(server) {
|
|
7
|
+
// Tool 7: generate_config
|
|
8
|
+
server.tool("generate_config", "Generate AdManageKitConfig setup code for your Application class. Produces complete configuration including ad initialization, billing setup, and loading strategies.", {
|
|
9
|
+
language: zod_1.z
|
|
10
|
+
.enum(["kotlin", "java"])
|
|
11
|
+
.optional()
|
|
12
|
+
.default("kotlin")
|
|
13
|
+
.describe("Output language (default: kotlin)"),
|
|
14
|
+
features: zod_1.z
|
|
15
|
+
.object({
|
|
16
|
+
debug_mode: zod_1.z.boolean().optional().describe("Enable debug mode"),
|
|
17
|
+
smart_preloading: zod_1.z
|
|
18
|
+
.boolean()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Enable smart ad preloading"),
|
|
21
|
+
auto_retry: zod_1.z
|
|
22
|
+
.boolean()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Enable automatic retry on failed ad loads"),
|
|
25
|
+
max_retry_attempts: zod_1.z
|
|
26
|
+
.number()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Max retry attempts (default: 3)"),
|
|
29
|
+
performance_metrics: zod_1.z
|
|
30
|
+
.boolean()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Enable performance tracking"),
|
|
33
|
+
interstitial_strategy: zod_1.z
|
|
34
|
+
.enum(["ON_DEMAND", "ONLY_CACHE", "HYBRID"])
|
|
35
|
+
.optional(),
|
|
36
|
+
app_open_strategy: zod_1.z
|
|
37
|
+
.enum(["ON_DEMAND", "ONLY_CACHE", "HYBRID"])
|
|
38
|
+
.optional(),
|
|
39
|
+
native_strategy: zod_1.z.enum(["ON_DEMAND", "HYBRID"]).optional(),
|
|
40
|
+
interstitial_auto_reload: zod_1.z.boolean().optional(),
|
|
41
|
+
app_open_auto_reload: zod_1.z.boolean().optional(),
|
|
42
|
+
rewarded_auto_reload: zod_1.z.boolean().optional(),
|
|
43
|
+
billing: zod_1.z
|
|
44
|
+
.boolean()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Include billing setup"),
|
|
47
|
+
app_open_ad_unit: zod_1.z
|
|
48
|
+
.string()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("App open ad unit ID"),
|
|
51
|
+
test_mode: zod_1.z.boolean().optional().describe("Enable test mode"),
|
|
52
|
+
})
|
|
53
|
+
.optional()
|
|
54
|
+
.default({}),
|
|
55
|
+
}, async ({ language, features }) => {
|
|
56
|
+
const code = (0, templates_js_1.generateConfig)({
|
|
57
|
+
language,
|
|
58
|
+
...features,
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: `\`\`\`${language}\n${code}\n\`\`\``,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
// Tool 8: generate_ad_integration
|
|
70
|
+
server.tool("generate_ad_integration", "Generate complete ad integration code for a specific ad type. Includes XML layout, loading code, display code, and callback handling.", {
|
|
71
|
+
ad_type: zod_1.z
|
|
72
|
+
.enum([
|
|
73
|
+
"interstitial",
|
|
74
|
+
"banner",
|
|
75
|
+
"native_small",
|
|
76
|
+
"native_medium",
|
|
77
|
+
"native_large",
|
|
78
|
+
"native_template",
|
|
79
|
+
"app_open",
|
|
80
|
+
"rewarded",
|
|
81
|
+
])
|
|
82
|
+
.describe("The type of ad to generate code for"),
|
|
83
|
+
language: zod_1.z
|
|
84
|
+
.enum(["kotlin", "java"])
|
|
85
|
+
.optional()
|
|
86
|
+
.default("kotlin")
|
|
87
|
+
.describe("Output language (default: kotlin)"),
|
|
88
|
+
ad_unit_id: zod_1.z
|
|
89
|
+
.string()
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("AdMob ad unit ID (default: test ad unit)"),
|
|
92
|
+
options: zod_1.z
|
|
93
|
+
.object({
|
|
94
|
+
display_mode: zod_1.z
|
|
95
|
+
.enum([
|
|
96
|
+
"force",
|
|
97
|
+
"time_based",
|
|
98
|
+
"count_based",
|
|
99
|
+
"builder",
|
|
100
|
+
"splash_wait",
|
|
101
|
+
])
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("For interstitial: how to show the ad"),
|
|
104
|
+
loading_strategy: zod_1.z
|
|
105
|
+
.enum(["ON_DEMAND", "ONLY_CACHE", "HYBRID"])
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("Loading strategy to use"),
|
|
108
|
+
use_caching: zod_1.z
|
|
109
|
+
.boolean()
|
|
110
|
+
.optional()
|
|
111
|
+
.describe("For native ads: use cached ads"),
|
|
112
|
+
template: zod_1.z
|
|
113
|
+
.string()
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("For native_template: template name (e.g., MATERIAL3, CARD_MODERN)"),
|
|
116
|
+
collapsible: zod_1.z
|
|
117
|
+
.boolean()
|
|
118
|
+
.optional()
|
|
119
|
+
.describe("For banner: use collapsible banner"),
|
|
120
|
+
with_callbacks: zod_1.z
|
|
121
|
+
.boolean()
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Include full callback handling (default: true)"),
|
|
124
|
+
with_fallbacks: zod_1.z
|
|
125
|
+
.boolean()
|
|
126
|
+
.optional()
|
|
127
|
+
.describe("For interstitial builder: include fallback ad units"),
|
|
128
|
+
frequency_control: zod_1.z
|
|
129
|
+
.object({
|
|
130
|
+
every_nth_time: zod_1.z.number().optional(),
|
|
131
|
+
max_shows: zod_1.z.number().optional(),
|
|
132
|
+
min_interval_seconds: zod_1.z.number().optional(),
|
|
133
|
+
})
|
|
134
|
+
.optional(),
|
|
135
|
+
exclude_activities: zod_1.z
|
|
136
|
+
.array(zod_1.z.string())
|
|
137
|
+
.optional()
|
|
138
|
+
.describe("For app_open: activity classes to exclude"),
|
|
139
|
+
auto_reload: zod_1.z
|
|
140
|
+
.boolean()
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("Auto-reload after dismissal"),
|
|
143
|
+
})
|
|
144
|
+
.optional()
|
|
145
|
+
.default({}),
|
|
146
|
+
}, async ({ ad_type, language, ad_unit_id, options }) => {
|
|
147
|
+
const code = (0, templates_js_1.generateAdIntegration)({
|
|
148
|
+
ad_type,
|
|
149
|
+
language,
|
|
150
|
+
ad_unit_id,
|
|
151
|
+
...options,
|
|
152
|
+
});
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: "text",
|
|
157
|
+
text: `\`\`\`${language}\n${code}\n\`\`\``,
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
// Tool 9: generate_billing_code
|
|
163
|
+
server.tool("generate_billing_code", "Generate billing/purchase integration code for AdManageKit. Supports in-app purchases, subscriptions, consumable products, and subscription management.", {
|
|
164
|
+
language: zod_1.z
|
|
165
|
+
.enum(["kotlin", "java"])
|
|
166
|
+
.optional()
|
|
167
|
+
.default("kotlin")
|
|
168
|
+
.describe("Output language (default: kotlin)"),
|
|
169
|
+
scenario: zod_1.z
|
|
170
|
+
.enum([
|
|
171
|
+
"setup",
|
|
172
|
+
"purchase",
|
|
173
|
+
"subscribe",
|
|
174
|
+
"consumable",
|
|
175
|
+
"subscription_management",
|
|
176
|
+
"expiry_verification",
|
|
177
|
+
"complete",
|
|
178
|
+
])
|
|
179
|
+
.describe("Which billing scenario to generate code for"),
|
|
180
|
+
products: zod_1.z
|
|
181
|
+
.array(zod_1.z.object({
|
|
182
|
+
product_id: zod_1.z.string(),
|
|
183
|
+
type: zod_1.z.enum(["PURCHASE", "SUBSCRIPTION"]),
|
|
184
|
+
category: zod_1.z
|
|
185
|
+
.enum([
|
|
186
|
+
"CONSUMABLE",
|
|
187
|
+
"FEATURE_UNLOCK",
|
|
188
|
+
"LIFETIME_PREMIUM",
|
|
189
|
+
"REMOVE_ADS",
|
|
190
|
+
])
|
|
191
|
+
.optional(),
|
|
192
|
+
offer_token: zod_1.z.string().optional(),
|
|
193
|
+
}))
|
|
194
|
+
.optional()
|
|
195
|
+
.describe("Product definitions to include"),
|
|
196
|
+
}, async ({ language, scenario, products }) => {
|
|
197
|
+
const code = (0, templates_js_1.generateBillingCode)({
|
|
198
|
+
language,
|
|
199
|
+
scenario,
|
|
200
|
+
products,
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
content: [
|
|
204
|
+
{
|
|
205
|
+
type: "text",
|
|
206
|
+
text: `\`\`\`${language}\n${code}\n\`\`\``,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
// Tool 10: generate_compose_code
|
|
212
|
+
server.tool("generate_compose_code", "Generate Jetpack Compose ad integration code. Supports all Compose ad components: BannerAdCompose, NativeTemplateCompose, rememberInterstitialAd, ConditionalAd, CacheWarmingEffect.", {
|
|
213
|
+
component: zod_1.z
|
|
214
|
+
.enum([
|
|
215
|
+
"banner",
|
|
216
|
+
"native_template",
|
|
217
|
+
"native_small",
|
|
218
|
+
"native_medium",
|
|
219
|
+
"native_large",
|
|
220
|
+
"interstitial",
|
|
221
|
+
"interstitial_state",
|
|
222
|
+
"conditional_ad",
|
|
223
|
+
"cache_warming",
|
|
224
|
+
"complete_screen",
|
|
225
|
+
])
|
|
226
|
+
.describe("Which Compose component to generate"),
|
|
227
|
+
ad_unit_id: zod_1.z
|
|
228
|
+
.string()
|
|
229
|
+
.optional()
|
|
230
|
+
.describe("AdMob ad unit ID (default: test unit)"),
|
|
231
|
+
options: zod_1.z
|
|
232
|
+
.object({
|
|
233
|
+
template: zod_1.z
|
|
234
|
+
.string()
|
|
235
|
+
.optional()
|
|
236
|
+
.describe("For native_template: NativeAdTemplate value (e.g., MATERIAL3)"),
|
|
237
|
+
loading_strategy: zod_1.z
|
|
238
|
+
.enum(["ON_DEMAND", "ONLY_CACHE", "HYBRID"])
|
|
239
|
+
.optional(),
|
|
240
|
+
with_callbacks: zod_1.z.boolean().optional(),
|
|
241
|
+
show_mode: zod_1.z
|
|
242
|
+
.enum(["TIME", "COUNT", "FORCE", "FORCE_WITH_DIALOG"])
|
|
243
|
+
.optional()
|
|
244
|
+
.describe("For interstitial_state: how to show the ad"),
|
|
245
|
+
})
|
|
246
|
+
.optional()
|
|
247
|
+
.default({}),
|
|
248
|
+
}, async ({ component, ad_unit_id, options }) => {
|
|
249
|
+
const code = (0, templates_js_1.generateComposeCode)({
|
|
250
|
+
component,
|
|
251
|
+
ad_unit_id,
|
|
252
|
+
...options,
|
|
253
|
+
});
|
|
254
|
+
return {
|
|
255
|
+
content: [
|
|
256
|
+
{
|
|
257
|
+
type: "text",
|
|
258
|
+
text: `\`\`\`kotlin\n${code}\n\`\`\``,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=code-generation.js.map
|