@revclamp/google-ads-transparency-mcp-actor 0.0.0-stage → 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/glama.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://glama.ai/mcp/schemas/server.json",
3
+ "maintainers": [
4
+ "lhphong09t2"
5
+ ]
6
+ }
package/index.mjs ADDED
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Entrypoint & Barrel Export for RevClamp AdPulse - Google Ads Transparency MCP & Apify Actor (`index.mjs`)
5
+ */
6
+
7
+ import fs from 'node:fs';
8
+ import readline from 'node:readline';
9
+ import { fileURLToPath } from 'node:url';
10
+ import {
11
+ ALLOWED_GOOGLE_ADS_RPC_HOSTS,
12
+ verifyEgressUrlSsrfSafe,
13
+ assertAllowedGoogleAdsEgress,
14
+ } from './src/egress_guard.mjs';
15
+
16
+ import {
17
+ GOOGLE_ADS_RPC_ENDPOINTS,
18
+ ADVERTISER_ID_RE,
19
+ CREATIVE_ID_RE,
20
+ ISO_COUNTRY_RE,
21
+ ISO_COUNTRY_TO_GOOGLE_GEO_ID,
22
+ GOOGLE_GEO_ID_TO_ISO_COUNTRY,
23
+ MAX_RPC_RESPONSE_BYTES,
24
+ DEFAULT_RUN_DEADLINE_MS,
25
+ COMPOSITE_CURSOR_PREFIX,
26
+ MAX_CURSOR_LENGTH,
27
+ MAX_QUERY_LENGTH,
28
+ CORPORATE_LEGAL_SUFFIX_TOKENS,
29
+ collapseDottedAcronyms,
30
+ foldBrandText,
31
+ parseBrandQueryTokens,
32
+ validateBoundedIntegerParam,
33
+ computePaginationScopeHash,
34
+ encodeCompositeCursor,
35
+ decodePaginationCursor,
36
+ computeRewoundCursorForDeliveredPrefix,
37
+ verifyRpcResponseSchemaCanary,
38
+ scoreAdvertiserCandidate,
39
+ executeGoogleAdsRpcPost,
40
+ resolveAdvertiserEntities,
41
+ extractCreativeAssetUrls,
42
+ sanitizeUntrustedAdText,
43
+ createEmptyUntrustedAdContent,
44
+ extractStaticAdCopyFromContentJs,
45
+ fetchAndExtractStaticAdCopy,
46
+ normalizeCreativeRecord,
47
+ fetchAdvertiserCreatives,
48
+ getCreativeDetailsById,
49
+ } from './src/rpc_client.mjs';
50
+
51
+ import {
52
+ ACTOR_PRICING_CONTRACT,
53
+ computeChunkIdempotencyKey,
54
+ computeRunEconomicsTelemetry,
55
+ createApifyPlatformHooks,
56
+ loadApifyActorInput,
57
+ runGoogleAdsTransparencyActor,
58
+ } from './src/apify_actor.mjs';
59
+
60
+ import {
61
+ MCP_MAX_ENVELOPE_BYTES,
62
+ MCP_MAX_ITEMS_LIMIT,
63
+ MCP_MAX_REQ_ID_BYTES,
64
+ SUPPORTED_MCP_PROTOCOL_VERSIONS,
65
+ ENCODED_BRAND_ICON_DATA_URI,
66
+ MCP_SERVER_INFO,
67
+ MCP_TOOLS_MANIFEST,
68
+ sliceUtf8Safe,
69
+ truncateMcpResponseEnvelope,
70
+ validateMcpToolArguments,
71
+ handleMcpJsonRpcRequest,
72
+ } from './src/mcp_server.mjs';
73
+
74
+ import {
75
+ PLAYGROUND_CSP_HEADER,
76
+ MAX_PLAYGROUND_BODY_BYTES,
77
+ PLAYGROUND_REQUEST_TIMEOUT_MS,
78
+ createAdPulsePreviewServer,
79
+ } from './src/web_preview_server.mjs';
80
+
81
+ export {
82
+ ALLOWED_GOOGLE_ADS_RPC_HOSTS,
83
+ verifyEgressUrlSsrfSafe,
84
+ assertAllowedGoogleAdsEgress,
85
+ GOOGLE_ADS_RPC_ENDPOINTS,
86
+ ADVERTISER_ID_RE,
87
+ CREATIVE_ID_RE,
88
+ ISO_COUNTRY_RE,
89
+ ISO_COUNTRY_TO_GOOGLE_GEO_ID,
90
+ GOOGLE_GEO_ID_TO_ISO_COUNTRY,
91
+ MAX_RPC_RESPONSE_BYTES,
92
+ DEFAULT_RUN_DEADLINE_MS,
93
+ COMPOSITE_CURSOR_PREFIX,
94
+ MAX_CURSOR_LENGTH,
95
+ MAX_QUERY_LENGTH,
96
+ CORPORATE_LEGAL_SUFFIX_TOKENS,
97
+ collapseDottedAcronyms,
98
+ foldBrandText,
99
+ parseBrandQueryTokens,
100
+ validateBoundedIntegerParam,
101
+ computePaginationScopeHash,
102
+ encodeCompositeCursor,
103
+ decodePaginationCursor,
104
+ computeRewoundCursorForDeliveredPrefix,
105
+ verifyRpcResponseSchemaCanary,
106
+ scoreAdvertiserCandidate,
107
+ executeGoogleAdsRpcPost,
108
+ resolveAdvertiserEntities,
109
+ extractCreativeAssetUrls,
110
+ sanitizeUntrustedAdText,
111
+ createEmptyUntrustedAdContent,
112
+ extractStaticAdCopyFromContentJs,
113
+ fetchAndExtractStaticAdCopy,
114
+ normalizeCreativeRecord,
115
+ fetchAdvertiserCreatives,
116
+ getCreativeDetailsById,
117
+ ACTOR_PRICING_CONTRACT,
118
+ computeChunkIdempotencyKey,
119
+ computeRunEconomicsTelemetry,
120
+ createApifyPlatformHooks,
121
+ loadApifyActorInput,
122
+ runGoogleAdsTransparencyActor,
123
+ MCP_MAX_ENVELOPE_BYTES,
124
+ MCP_MAX_ITEMS_LIMIT,
125
+ MCP_MAX_REQ_ID_BYTES,
126
+ SUPPORTED_MCP_PROTOCOL_VERSIONS,
127
+ ENCODED_BRAND_ICON_DATA_URI,
128
+ MCP_SERVER_INFO,
129
+ MCP_TOOLS_MANIFEST,
130
+ sliceUtf8Safe,
131
+ truncateMcpResponseEnvelope,
132
+ validateMcpToolArguments,
133
+ handleMcpJsonRpcRequest,
134
+ PLAYGROUND_CSP_HEADER,
135
+ MAX_PLAYGROUND_BODY_BYTES,
136
+ PLAYGROUND_REQUEST_TIMEOUT_MS,
137
+ createAdPulsePreviewServer,
138
+ };
139
+
140
+ export async function runCli(argv = process.argv.slice(2)) {
141
+ const args = Array.isArray(argv) ? argv : [];
142
+ if (args.includes('--playground')) {
143
+ const portArg = Number(process.env.PORT || 4410);
144
+ const srv = await createAdPulsePreviewServer({ port: portArg });
145
+ process.stdout.write(`RevClamp AdPulse Web Playground listening on ${srv.url}\n`);
146
+ return srv;
147
+ }
148
+
149
+ if (args.includes('--mcp-stdio')) {
150
+ const rl = readline.createInterface({
151
+ input: process.stdin,
152
+ terminal: false,
153
+ });
154
+ for await (const line of rl) {
155
+ const trimmed = line.trim();
156
+ if (!trimmed) {
157
+ continue;
158
+ }
159
+ let parsedReq;
160
+ try {
161
+ parsedReq = JSON.parse(trimmed);
162
+ } catch {
163
+ process.stdout.write(
164
+ `${JSON.stringify({
165
+ jsonrpc: '2.0',
166
+ id: null,
167
+ error: { code: -32700, message: 'Parse error' },
168
+ })}\n`
169
+ );
170
+ continue;
171
+ }
172
+
173
+ try {
174
+ const res = await handleMcpJsonRpcRequest(parsedReq);
175
+ if (res !== null && res !== undefined) {
176
+ process.stdout.write(`${JSON.stringify(res)}\n`);
177
+ }
178
+ } catch (err) {
179
+ const hasId =
180
+ parsedReq &&
181
+ typeof parsedReq === 'object' &&
182
+ !Array.isArray(parsedReq) &&
183
+ Object.prototype.hasOwnProperty.call(parsedReq, 'id') &&
184
+ parsedReq.id !== undefined;
185
+ if (hasId) {
186
+ process.stdout.write(
187
+ `${JSON.stringify({
188
+ jsonrpc: '2.0',
189
+ id: typeof parsedReq.id === 'string' || typeof parsedReq.id === 'number' ? parsedReq.id : null,
190
+ error: { code: -32603, message: `Internal error: ${err?.message || String(err)}` },
191
+ })}\n`
192
+ );
193
+ }
194
+ }
195
+ }
196
+ return null;
197
+ }
198
+
199
+ const inputObj = await loadApifyActorInput(args, process.env);
200
+ const platformHooks = createApifyPlatformHooks(process.env);
201
+ const res = await runGoogleAdsTransparencyActor(inputObj, platformHooks);
202
+ process.stdout.write(`${JSON.stringify(res, null, 2)}\n`);
203
+ process.exit(res.ok ? 0 : 1);
204
+ }
205
+
206
+ function isExecutedAsMainModule(metaUrl) {
207
+ if (!process.argv[1]) return false;
208
+ try {
209
+ const entryPath = fs.realpathSync(process.argv[1]);
210
+ const selfPath = fs.realpathSync(fileURLToPath(metaUrl));
211
+ return entryPath === selfPath;
212
+ } catch {
213
+ return false;
214
+ }
215
+ }
216
+
217
+ if (isExecutedAsMainModule(import.meta.url)) {
218
+ runCli().catch((err) => {
219
+ process.stderr.write(`Fatal error in RevClamp AdPulse CLI: ${err?.message || String(err)}\n`);
220
+ process.exit(1);
221
+ });
222
+ }
package/package.json CHANGED
@@ -1,6 +1,40 @@
1
1
  {
2
2
  "name": "@revclamp/google-ads-transparency-mcp-actor",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "mcpName": "com.revclamp/google-ads-transparency-mcp-actor",
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "description": "RevClamp AdPulse - For Google Ads Transparency Center (MCP & Apify Actor). Independent intelligence tool by RevClamp; not affiliated with or endorsed by Google LLC.",
7
+ "homepage": "https://revclamp.com",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/lhphong09t2/revclamp-mcp.git",
11
+ "directory": "products/google-ads-transparency-mcp-actor"
12
+ },
13
+ "license": "MIT",
14
+ "main": "./index.mjs",
15
+ "bin": {
16
+ "google-ads-transparency-mcp-actor": "./index.mjs",
17
+ "google-ads-transparency-mcp": "./index.mjs"
18
+ },
19
+ "files": [
20
+ "index.mjs",
21
+ "src/",
22
+ "assets/",
23
+ "actor_config.json",
24
+ "server.json",
25
+ "glama.json",
26
+ ".well-known/",
27
+ ".actor/",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "scripts": {
32
+ "start": "node ./index.mjs",
33
+ "mcp": "node ./index.mjs --mcp-stdio",
34
+ "playground": "node ./src/web_preview_server.mjs",
35
+ "test": "node --test ./test/google_ads_transparency.test.mjs ./test/metamorphic_and_mutation.test.mjs ./test/cdp_zero_false_green_e2e.test.mjs"
36
+ },
37
+ "engines": {
38
+ "node": ">=20.0.0"
39
+ }
40
+ }
package/server.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3
+ "name": "com.revclamp/google-ads-transparency-mcp-actor",
4
+ "title": "RevClamp AdPulse (Google Ads Transparency MCP)",
5
+ "description": "Find verified Google Ads advertiser entities and extract active or historical ad creatives (Text, Image, Video), preview links, and run dates. Independent intelligence tool by RevClamp; not affiliated with or endorsed by Google LLC.",
6
+ "version": "1.0.0",
7
+ "websiteUrl": "https://revclamp.com",
8
+ "repository": {
9
+ "url": "https://github.com/lhphong09t2/revclamp-mcp",
10
+ "source": "github",
11
+ "subfolder": "products/google-ads-transparency-mcp-actor"
12
+ },
13
+ "icons": [
14
+ {
15
+ "src": "https://revclamp.com/apple-touch-icon.png",
16
+ "mimeType": "image/png",
17
+ "sizes": ["180x180"]
18
+ },
19
+ {
20
+ "src": "https://revclamp.com/favicon.png",
21
+ "mimeType": "image/png",
22
+ "sizes": ["32x32"]
23
+ }
24
+ ],
25
+ "packages": [
26
+ {
27
+ "registryType": "npm",
28
+ "registryBaseUrl": "https://registry.npmjs.org",
29
+ "identifier": "@revclamp/google-ads-transparency-mcp-actor",
30
+ "version": "1.0.0",
31
+ "transport": {
32
+ "type": "stdio"
33
+ }
34
+ }
35
+ ]
36
+ }