samarth-gtm-mcp 1.32.0 → 1.32.2
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/dist/tools/tags.d.ts.map +1 -1
- package/dist/tools/tags.js +68 -6
- package/dist/tools/tags.js.map +1 -1
- package/dist/utils/tagParams.d.ts +28 -0
- package/dist/utils/tagParams.d.ts.map +1 -0
- package/dist/utils/tagParams.js +65 -0
- package/dist/utils/tagParams.js.map +1 -0
- package/package.json +2 -2
package/dist/tools/tags.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAyBvD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,GAAG,IAAI,CA8NpF"}
|
package/dist/tools/tags.js
CHANGED
|
@@ -5,6 +5,7 @@ import { z } from 'zod';
|
|
|
5
5
|
import { checkGuardrails, getGuardrailConfig } from '../utils/guardrails.js';
|
|
6
6
|
import { paginate, paginationFields, buildListResult } from '../utils/pagination.js';
|
|
7
7
|
import { jsonResult, textResult, errorResult } from '../utils/toolResponse.js';
|
|
8
|
+
import { addEventParameters, mergeParametersByKey } from '../utils/tagParams.js';
|
|
8
9
|
const wsBase = z.object({
|
|
9
10
|
accountId: z.string().describe('The GTM account ID.'),
|
|
10
11
|
containerId: z.string().describe('The GTM container ID.'),
|
|
@@ -90,8 +91,10 @@ export function registerTagTools(server, getClient) {
|
|
|
90
91
|
});
|
|
91
92
|
// ── tags/update ──────────────────────────────────────────────────────────
|
|
92
93
|
server.registerTool('tags_update', {
|
|
93
|
-
description: '[WRITE] Update an existing GTM tag. Requires GTM_MCP_ENABLE_WRITES=true and confirm=true. ' +
|
|
94
|
-
'
|
|
94
|
+
description: '[WRITE] Update an existing GTM tag (read-modify-write). Requires GTM_MCP_ENABLE_WRITES=true and confirm=true. ' +
|
|
95
|
+
'GTM\'s API replaces the WHOLE tag on update, so this tool first fetches the tag and only overlays the fields you pass — omitted fields are preserved. ' +
|
|
96
|
+
'`parameter` is MERGED with the existing parameters BY KEY (a same-key param replaces, new keys are added, untouched keys are kept), so you will NOT wipe a GA4 tag\'s eventName/measurementId. ' +
|
|
97
|
+
'To add GA4 EVENT parameters to a gaawe tag, prefer tags_add_ga4_event_parameters (event params live in the nested eventSettingsTable, which this generic parameter list cannot express).',
|
|
95
98
|
inputSchema: wsBase.extend({
|
|
96
99
|
tagId: z.string().describe('The GTM tag ID to update.'),
|
|
97
100
|
name: z.string().optional().describe('New tag name.'),
|
|
@@ -101,7 +104,7 @@ export function registerTagTools(server, getClient) {
|
|
|
101
104
|
blockingTriggerId: z.array(z.string()).optional().describe('IDs of blocking triggers.'),
|
|
102
105
|
notes: z.string().optional().describe('Optional notes.'),
|
|
103
106
|
paused: z.boolean().optional().describe('Whether the tag is paused.'),
|
|
104
|
-
fingerprint: z.string().optional().describe('Current tag fingerprint (for optimistic locking).'),
|
|
107
|
+
fingerprint: z.string().optional().describe('Current tag fingerprint (for optimistic locking). Defaults to the fetched one.'),
|
|
105
108
|
confirm: z.boolean().describe('Must be true to confirm this write operation.'),
|
|
106
109
|
}),
|
|
107
110
|
}, async ({ accountId, containerId, workspaceId, tagId, confirm, fingerprint, ...updates }) => {
|
|
@@ -112,10 +115,31 @@ export function registerTagTools(server, getClient) {
|
|
|
112
115
|
return textResult(`[DRY RUN] Would update tag ${tagId} in workspace ${workspaceId}`);
|
|
113
116
|
}
|
|
114
117
|
const client = getClient();
|
|
118
|
+
const path = `accounts/${accountId}/containers/${containerId}/workspaces/${workspaceId}/tags/${tagId}`;
|
|
119
|
+
// Read-modify-write: fetch the full tag, overlay only the provided fields, and
|
|
120
|
+
// merge `parameter` by key — GTM's update is a full replace, so anything we
|
|
121
|
+
// don't send back would otherwise be cleared.
|
|
122
|
+
const existing = (await client.accounts.containers.workspaces.tags.get({ path })).data;
|
|
123
|
+
const merged = { ...existing };
|
|
124
|
+
if (updates.name !== undefined)
|
|
125
|
+
merged.name = updates.name;
|
|
126
|
+
if (updates.type !== undefined)
|
|
127
|
+
merged.type = updates.type;
|
|
128
|
+
if (updates.notes !== undefined)
|
|
129
|
+
merged.notes = updates.notes;
|
|
130
|
+
if (updates.paused !== undefined)
|
|
131
|
+
merged.paused = updates.paused;
|
|
132
|
+
if (updates.firingTriggerId !== undefined)
|
|
133
|
+
merged.firingTriggerId = updates.firingTriggerId;
|
|
134
|
+
if (updates.blockingTriggerId !== undefined)
|
|
135
|
+
merged.blockingTriggerId = updates.blockingTriggerId;
|
|
136
|
+
if (updates.parameter !== undefined) {
|
|
137
|
+
merged.parameter = mergeParametersByKey(existing.parameter ?? [], updates.parameter);
|
|
138
|
+
}
|
|
115
139
|
const res = await client.accounts.containers.workspaces.tags.update({
|
|
116
|
-
path
|
|
117
|
-
|
|
118
|
-
requestBody:
|
|
140
|
+
path,
|
|
141
|
+
fingerprint: fingerprint ?? existing.fingerprint ?? undefined,
|
|
142
|
+
requestBody: merged,
|
|
119
143
|
});
|
|
120
144
|
return jsonResult(res.data);
|
|
121
145
|
}
|
|
@@ -123,6 +147,44 @@ export function registerTagTools(server, getClient) {
|
|
|
123
147
|
return errorResult('tags_update', err);
|
|
124
148
|
}
|
|
125
149
|
});
|
|
150
|
+
// ── tags/add GA4 event parameters ────────────────────────────────────────
|
|
151
|
+
server.registerTool('tags_add_ga4_event_parameters', {
|
|
152
|
+
description: '[WRITE] Add GA4 event parameters to a GA4 Event tag (type "gaawe"). Requires GTM_MCP_ENABLE_WRITES=true and confirm=true. ' +
|
|
153
|
+
'Fetches the tag, APPENDS the parameters to its eventSettingsTable (the correct place for GA4 event parameters — top-level params are ignored by GA4 event tags), and saves the FULL tag so eventName/measurementId stay intact. ' +
|
|
154
|
+
'A parameter whose name already exists has its value updated (not duplicated). Values may be GTM variables, e.g. {{Click Text}}.',
|
|
155
|
+
inputSchema: wsBase.extend({
|
|
156
|
+
tagId: z.string().describe('The GA4 Event (gaawe) tag ID to update.'),
|
|
157
|
+
parameters: z
|
|
158
|
+
.array(z.object({ name: z.string(), value: z.string() }))
|
|
159
|
+
.min(1)
|
|
160
|
+
.describe('Event parameters to add, e.g. [{"name":"click_text","value":"{{Click Text}}"},{"name":"page_path","value":"{{Page Path}}"}].'),
|
|
161
|
+
confirm: z.boolean().describe('Must be true to confirm this write operation.'),
|
|
162
|
+
}),
|
|
163
|
+
}, async ({ accountId, containerId, workspaceId, tagId, parameters, confirm }) => {
|
|
164
|
+
try {
|
|
165
|
+
const config = getGuardrailConfig();
|
|
166
|
+
const { dryRun } = checkGuardrails('write', confirm, config);
|
|
167
|
+
if (dryRun) {
|
|
168
|
+
return textResult(`[DRY RUN] Would add ${parameters.length} event parameter(s) to GA4 tag ${tagId}`);
|
|
169
|
+
}
|
|
170
|
+
const client = getClient();
|
|
171
|
+
const path = `accounts/${accountId}/containers/${containerId}/workspaces/${workspaceId}/tags/${tagId}`;
|
|
172
|
+
const existing = (await client.accounts.containers.workspaces.tags.get({ path })).data;
|
|
173
|
+
if (existing.type !== 'gaawe') {
|
|
174
|
+
return errorResult('tags_add_ga4_event_parameters', new Error(`Tag ${tagId} is type "${existing.type ?? 'unknown'}", not a GA4 Event tag (gaawe). This tool only edits gaawe tags.`));
|
|
175
|
+
}
|
|
176
|
+
const updated = addEventParameters(existing, parameters);
|
|
177
|
+
const res = await client.accounts.containers.workspaces.tags.update({
|
|
178
|
+
path,
|
|
179
|
+
fingerprint: existing.fingerprint ?? undefined,
|
|
180
|
+
requestBody: updated,
|
|
181
|
+
});
|
|
182
|
+
return jsonResult(res.data);
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
return errorResult('tags_add_ga4_event_parameters', err);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
126
188
|
// ── tags/delete ──────────────────────────────────────────────────────────
|
|
127
189
|
server.registerTool('tags_delete', {
|
|
128
190
|
description: '[DELETE] Delete a GTM tag. Requires GTM_MCP_ENABLE_DELETES=true and confirm=true. ' +
|
package/dist/tools/tags.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for SAFELY editing a GTM tag's parameters.
|
|
3
|
+
*
|
|
4
|
+
* GTM's `tags.update` is a FULL replace (PUT) — any field omitted from the request
|
|
5
|
+
* body is cleared. So a naive "send only the new parameter" update WIPES a GA4 event
|
|
6
|
+
* tag's eventName / measurementId / measurementIdOverride / eventSettingsTable. These
|
|
7
|
+
* helpers do the read-modify-write merge that keeps the rest of the tag intact.
|
|
8
|
+
*
|
|
9
|
+
* No runtime googleapis import — types only (erased at build).
|
|
10
|
+
*/
|
|
11
|
+
import type { tagmanager_v2 } from 'googleapis';
|
|
12
|
+
type Param = tagmanager_v2.Schema$Parameter;
|
|
13
|
+
type Tag = tagmanager_v2.Schema$Tag;
|
|
14
|
+
/** Merge `provided` parameters onto `existing` BY KEY: a provided param with the same
|
|
15
|
+
* key replaces the existing one; new keys are added; existing keys not provided are
|
|
16
|
+
* kept. Keyless params (rare for tags) are concatenated. PURE. */
|
|
17
|
+
export declare function mergeParametersByKey(existing: Param[], provided: Param[]): Param[];
|
|
18
|
+
/** Add GA4 event parameters to a GA4 Event tag (type 'gaawe') by appending them to the
|
|
19
|
+
* tag's `eventSettingsTable` (the GTM-correct place — NOT top-level params), creating
|
|
20
|
+
* that table if absent. A param whose name already exists has its VALUE updated rather
|
|
21
|
+
* than duplicated. Every other field of the tag is preserved. PURE — returns a NEW tag
|
|
22
|
+
* resource (the caller PUTs it back). */
|
|
23
|
+
export declare function addEventParameters(tag: Tag, params: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
value: string;
|
|
26
|
+
}>): Tag;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=tagParams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagParams.d.ts","sourceRoot":"","sources":["../../src/utils/tagParams.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,KAAK,KAAK,GAAG,aAAa,CAAC,gBAAgB,CAAC;AAC5C,KAAK,GAAG,GAAG,aAAa,CAAC,UAAU,CAAC;AAEpC;;mEAEmE;AACnE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAMlF;AAgBD;;;;0CAI0C;AAC1C,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,GAAG,CAqBhG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for SAFELY editing a GTM tag's parameters.
|
|
3
|
+
*
|
|
4
|
+
* GTM's `tags.update` is a FULL replace (PUT) — any field omitted from the request
|
|
5
|
+
* body is cleared. So a naive "send only the new parameter" update WIPES a GA4 event
|
|
6
|
+
* tag's eventName / measurementId / measurementIdOverride / eventSettingsTable. These
|
|
7
|
+
* helpers do the read-modify-write merge that keeps the rest of the tag intact.
|
|
8
|
+
*
|
|
9
|
+
* No runtime googleapis import — types only (erased at build).
|
|
10
|
+
*/
|
|
11
|
+
/** Merge `provided` parameters onto `existing` BY KEY: a provided param with the same
|
|
12
|
+
* key replaces the existing one; new keys are added; existing keys not provided are
|
|
13
|
+
* kept. Keyless params (rare for tags) are concatenated. PURE. */
|
|
14
|
+
export function mergeParametersByKey(existing, provided) {
|
|
15
|
+
const byKey = new Map();
|
|
16
|
+
for (const p of existing)
|
|
17
|
+
if (p.key)
|
|
18
|
+
byKey.set(p.key, p);
|
|
19
|
+
for (const p of provided)
|
|
20
|
+
if (p.key)
|
|
21
|
+
byKey.set(p.key, p);
|
|
22
|
+
const keyless = [...existing.filter((p) => !p.key), ...provided.filter((p) => !p.key)];
|
|
23
|
+
return [...byKey.values(), ...keyless];
|
|
24
|
+
}
|
|
25
|
+
/** The {parameter, parameterValue} map entry GA4 event params use inside the
|
|
26
|
+
* eventSettingsTable list (matches what GTM's UI + the create path produce). */
|
|
27
|
+
function eventParamMap(name, value) {
|
|
28
|
+
return {
|
|
29
|
+
type: 'map',
|
|
30
|
+
map: [
|
|
31
|
+
{ type: 'template', key: 'parameter', value: name },
|
|
32
|
+
{ type: 'template', key: 'parameterValue', value: value },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const mapName = (m) => (m.map ?? []).find((x) => x.key === 'parameter')?.value ?? undefined;
|
|
37
|
+
/** Add GA4 event parameters to a GA4 Event tag (type 'gaawe') by appending them to the
|
|
38
|
+
* tag's `eventSettingsTable` (the GTM-correct place — NOT top-level params), creating
|
|
39
|
+
* that table if absent. A param whose name already exists has its VALUE updated rather
|
|
40
|
+
* than duplicated. Every other field of the tag is preserved. PURE — returns a NEW tag
|
|
41
|
+
* resource (the caller PUTs it back). */
|
|
42
|
+
export function addEventParameters(tag, params) {
|
|
43
|
+
const parameter = [...(tag.parameter ?? [])];
|
|
44
|
+
const idx = parameter.findIndex((p) => p.key === 'eventSettingsTable');
|
|
45
|
+
const list = idx >= 0 ? [...(parameter[idx].list ?? [])] : [];
|
|
46
|
+
for (const { name, value } of params) {
|
|
47
|
+
if (!name)
|
|
48
|
+
continue;
|
|
49
|
+
const existing = list.findIndex((m) => mapName(m) === name);
|
|
50
|
+
if (existing >= 0) {
|
|
51
|
+
const map = (list[existing].map ?? []).map((x) => (x.key === 'parameterValue' ? { ...x, value } : x));
|
|
52
|
+
list[existing] = { ...list[existing], map };
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
list.push(eventParamMap(name, value));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const table = { type: 'list', key: 'eventSettingsTable', list };
|
|
59
|
+
if (idx >= 0)
|
|
60
|
+
parameter[idx] = table;
|
|
61
|
+
else
|
|
62
|
+
parameter.push(table);
|
|
63
|
+
return { ...tag, parameter };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=tagParams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagParams.js","sourceRoot":"","sources":["../../src/utils/tagParams.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "samarth-gtm-mcp",
|
|
3
|
-
"version": "1.32.
|
|
3
|
+
"version": "1.32.2",
|
|
4
4
|
"description": "Production-ready MCP server for Google Tag Manager API v2 — Samarth Analytics",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dev:http": "GTM_MCP_TRANSPORT=http tsx src/index.ts",
|
|
24
24
|
"auth:google": "tsx src/scripts/auth-google.ts",
|
|
25
25
|
"oauth:setup": "tsx src/scripts/oauth-setup.ts",
|
|
26
|
-
"test": "node src/__tests__/guardrails.node.test.mjs && node src/__tests__/auth.node.test.mjs && node src/__tests__/pagination.node.test.mjs && node src/__tests__/ga4Admin.node.test.mjs && node src/__tests__/apiRetry.node.test.mjs && node apps/portal/shared/__tests__/cache-keys.node.test.mjs && node apps/portal/shared/__tests__/cache.node.test.mjs && node apps/portal/shared/__tests__/jobs.node.test.mjs && node apps/portal/shared/__tests__/observability.node.test.mjs && node apps/portal/shared/__tests__/metrics.node.test.mjs && npm run test:consent && npm run test:audit && npm run test:snapshot && npm run test:rbac && npm run test:retention && npm run test:storage && npm run test:webaudit && npm run test:tagsuggest && npm run test:webreport",
|
|
26
|
+
"test": "node src/__tests__/guardrails.node.test.mjs && node src/__tests__/auth.node.test.mjs && node src/__tests__/pagination.node.test.mjs && node src/__tests__/ga4Admin.node.test.mjs && node src/__tests__/apiRetry.node.test.mjs && tsx src/__tests__/tag-params.test.ts && node apps/portal/shared/__tests__/cache-keys.node.test.mjs && node apps/portal/shared/__tests__/cache.node.test.mjs && node apps/portal/shared/__tests__/jobs.node.test.mjs && node apps/portal/shared/__tests__/observability.node.test.mjs && node apps/portal/shared/__tests__/metrics.node.test.mjs && npm run test:consent && npm run test:audit && npm run test:snapshot && npm run test:rbac && npm run test:retention && npm run test:storage && npm run test:webaudit && npm run test:tagsuggest && npm run test:webreport",
|
|
27
27
|
"test:consent": "tsx apps/portal/shared/__tests__/consent-audit.node.test.ts",
|
|
28
28
|
"test:audit": "tsx apps/portal/shared/__tests__/audit-accuracy.node.test.ts",
|
|
29
29
|
"test:snapshot": "tsx apps/portal/shared/__tests__/audit-snapshot.node.test.ts",
|