@advertising-chat/mcp 0.2.1 → 0.17.3

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.
Files changed (85) hide show
  1. package/README.md +123 -18
  2. package/bin/auth.d.ts +46 -0
  3. package/bin/auth.js +186 -0
  4. package/bin/auth.js.map +1 -0
  5. package/bin/cli.js +79 -11
  6. package/bin/cli.js.map +1 -1
  7. package/bin/client.d.ts +70 -0
  8. package/bin/client.js +121 -0
  9. package/bin/client.js.map +1 -0
  10. package/bin/docs.d.ts +66 -0
  11. package/bin/docs.js +247 -0
  12. package/bin/docs.js.map +1 -0
  13. package/bin/flow/flowSchema.d.ts +298 -0
  14. package/bin/flow/flowSchema.js +234 -0
  15. package/bin/flow/flowSchema.js.map +1 -0
  16. package/bin/flow/flowValidator.d.ts +15 -0
  17. package/bin/flow/flowValidator.js +179 -0
  18. package/bin/flow/flowValidator.js.map +1 -0
  19. package/bin/flow/flowZod.d.ts +117 -0
  20. package/bin/flow/flowZod.js +130 -0
  21. package/bin/flow/flowZod.js.map +1 -0
  22. package/bin/format.d.ts +14 -0
  23. package/bin/format.js +50 -0
  24. package/bin/format.js.map +1 -0
  25. package/bin/index.d.ts +23 -1
  26. package/bin/index.js +65 -4
  27. package/bin/index.js.map +1 -1
  28. package/bin/routeInventory.d.ts +69 -0
  29. package/bin/routeInventory.js +201 -0
  30. package/bin/routeInventory.js.map +1 -0
  31. package/bin/serve.d.ts +24 -0
  32. package/bin/serve.js +196 -0
  33. package/bin/serve.js.map +1 -0
  34. package/bin/server.d.ts +24 -36
  35. package/bin/server.js +54 -182
  36. package/bin/server.js.map +1 -1
  37. package/bin/tool.d.ts +84 -0
  38. package/bin/tool.js +39 -0
  39. package/bin/tool.js.map +1 -0
  40. package/bin/tools/account.d.ts +2 -0
  41. package/bin/tools/account.js +47 -0
  42. package/bin/tools/account.js.map +1 -0
  43. package/bin/tools/attributes.d.ts +10 -0
  44. package/bin/tools/attributes.js +200 -0
  45. package/bin/tools/attributes.js.map +1 -0
  46. package/bin/tools/campaigns.d.ts +12 -0
  47. package/bin/tools/campaigns.js +230 -0
  48. package/bin/tools/campaigns.js.map +1 -0
  49. package/bin/tools/decisions.d.ts +14 -0
  50. package/bin/tools/decisions.js +309 -0
  51. package/bin/tools/decisions.js.map +1 -0
  52. package/bin/tools/docs.d.ts +3 -0
  53. package/bin/tools/docs.js +55 -0
  54. package/bin/tools/docs.js.map +1 -0
  55. package/bin/tools/index.d.ts +21 -0
  56. package/bin/tools/index.js +60 -0
  57. package/bin/tools/index.js.map +1 -0
  58. package/bin/tools/moments.d.ts +9 -0
  59. package/bin/tools/moments.js +143 -0
  60. package/bin/tools/moments.js.map +1 -0
  61. package/bin/tools/network.d.ts +5 -0
  62. package/bin/tools/network.js +99 -0
  63. package/bin/tools/network.js.map +1 -0
  64. package/bin/tools/offers.d.ts +11 -0
  65. package/bin/tools/offers.js +239 -0
  66. package/bin/tools/offers.js.map +1 -0
  67. package/bin/tools/results.d.ts +18 -0
  68. package/bin/tools/results.js +116 -0
  69. package/bin/tools/results.js.map +1 -0
  70. package/bin/tools/rules.d.ts +9 -0
  71. package/bin/tools/rules.js +318 -0
  72. package/bin/tools/rules.js.map +1 -0
  73. package/bin/tools/settings.d.ts +3 -0
  74. package/bin/tools/settings.js +54 -0
  75. package/bin/tools/settings.js.map +1 -0
  76. package/bin/tools/shared.d.ts +50 -0
  77. package/bin/tools/shared.js +171 -0
  78. package/bin/tools/shared.js.map +1 -0
  79. package/bin/tools/translation.d.ts +6 -0
  80. package/bin/tools/translation.js +139 -0
  81. package/bin/tools/translation.js.map +1 -0
  82. package/bin/version.d.ts +2 -0
  83. package/bin/version.js +6 -0
  84. package/bin/version.js.map +1 -0
  85. package/package.json +10 -7
package/bin/client.js ADDED
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /**
3
+ * HTTP client for the Advertising.chat management API, the api gateway's
4
+ * `/system/*` surface.
5
+ *
6
+ * Every request carries the user's own Auth0 bearer token, the org it acts
7
+ * in (`X-Adchat-Target-Org`), and the surface that made it
8
+ * (`X-Adchat-Agent`, stamped into `_audit` on every write). The client holds
9
+ * no platform credential, so a tool can do exactly what the user could do
10
+ * in the console and nothing more. Tokens are never logged.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ManageClient = exports.ApiError = exports.DEFAULT_API_URL = void 0;
14
+ exports.DEFAULT_API_URL = 'https://api.advertising.chat/system';
15
+ /** A non-2xx answer from the management API. */
16
+ class ApiError extends Error {
17
+ status;
18
+ method;
19
+ path;
20
+ body;
21
+ constructor(status, method, path,
22
+ /** Parsed response body (JSON when the server sent JSON). */
23
+ body) {
24
+ super(`${method} ${path} failed (${status})${serverMessage(body)}`);
25
+ this.status = status;
26
+ this.method = method;
27
+ this.path = path;
28
+ this.body = body;
29
+ this.name = 'ApiError';
30
+ }
31
+ }
32
+ exports.ApiError = ApiError;
33
+ function serverMessage(body) {
34
+ if (body && typeof body === 'object' && 'message' in body) {
35
+ return `: ${String(body.message)}`;
36
+ }
37
+ return typeof body === 'string' && body ? `: ${body.slice(0, 300)}` : '';
38
+ }
39
+ class ManageClient {
40
+ opts;
41
+ org;
42
+ baseUrl;
43
+ agent;
44
+ constructor(opts) {
45
+ this.opts = opts;
46
+ if (opts.systemRequest && !opts.org) {
47
+ throw new Error('A system request needs a target org.');
48
+ }
49
+ this.org = opts.org;
50
+ this.baseUrl = (opts.baseUrl || exports.DEFAULT_API_URL).replace(/\/+$/, '');
51
+ this.agent = opts.agent ?? 'mcp';
52
+ }
53
+ get(path, query) {
54
+ return this.request('GET', path, { query });
55
+ }
56
+ post(path, body) {
57
+ return this.request('POST', path, { body });
58
+ }
59
+ put(path, body) {
60
+ return this.request('PUT', path, { body });
61
+ }
62
+ patch(path, body) {
63
+ return this.request('PATCH', path, { body });
64
+ }
65
+ delete(path) {
66
+ return this.request('DELETE', path, {});
67
+ }
68
+ /** The org requests act in, resolving the user's own org if needed. */
69
+ async resolveOrg() {
70
+ if (this.org)
71
+ return this.org;
72
+ const me = await this.request('GET', '/user/me', { withOrg: false });
73
+ const resolved = me?.org?._id ?? me?.org?.id;
74
+ if (!resolved) {
75
+ throw new Error('Could not determine your org. Set ADCHAT_ORG to the org id to work in.');
76
+ }
77
+ this.org = resolved;
78
+ return resolved;
79
+ }
80
+ /** `path` is relative to `/system`, e.g. `/offer-manager/adunit`. */
81
+ async request(method, path, { query, body, withOrg = true, }) {
82
+ const auth = this.opts.authorization;
83
+ const headers = {
84
+ Authorization: typeof auth === 'string' ? auth : await auth(),
85
+ Accept: 'application/json',
86
+ 'X-Adchat-Agent': this.agent,
87
+ };
88
+ if (withOrg) {
89
+ headers['X-Adchat-Target-Org'] = await this.resolveOrg();
90
+ if (this.opts.systemRequest)
91
+ headers['X-Adchat-System-Request'] = 'true';
92
+ }
93
+ if (body !== undefined)
94
+ headers['Content-Type'] = 'application/json';
95
+ const url = new URL(this.baseUrl + path);
96
+ for (const [k, v] of Object.entries(query ?? {})) {
97
+ if (v !== undefined)
98
+ url.searchParams.set(k, String(v));
99
+ }
100
+ const doFetch = this.opts.fetchFn ?? fetch;
101
+ const res = await doFetch(url.toString(), {
102
+ method,
103
+ headers,
104
+ body: body === undefined ? undefined : JSON.stringify(body),
105
+ signal: AbortSignal.timeout(this.opts.timeoutMs ?? 30_000),
106
+ });
107
+ const text = await res.text();
108
+ let parsed = text;
109
+ try {
110
+ parsed = text ? JSON.parse(text) : undefined;
111
+ }
112
+ catch {
113
+ /* keep the text */
114
+ }
115
+ if (!res.ok)
116
+ throw new ApiError(res.status, method, path, parsed);
117
+ return parsed;
118
+ }
119
+ }
120
+ exports.ManageClient = ManageClient;
121
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/bin/docs.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The public docs (docs.advertising.chat) as data for `search_docs` and
3
+ * `read_doc`. Ported from AnyChat's `@anychat-ai/mcp` `docs.ts`.
4
+ *
5
+ * Reads the two machine-readable exports the docs build writes
6
+ * (docs repo, `hooks/llms_txt.py`):
7
+ * - `/llms.txt` index: `- [Title](url): one-line summary` per page
8
+ * - `/llms-full.txt` every page's markdown, each preceded by
9
+ * `<!-- page: <url> -->` and `# Title`
10
+ *
11
+ * Both are cached in process for {@link CACHE_TTL_MS}. When a refresh fails
12
+ * and a cached copy exists, the stale copy is served rather than failing the
13
+ * tool call. Search is a plain keyword scorer over title, summary, and body:
14
+ * the corpus is about 30 pages, and the model reads the page it picks with
15
+ * `read_doc` anyway.
16
+ */
17
+ export declare const DEFAULT_DOCS_URL = "https://docs.advertising.chat";
18
+ export declare const CACHE_TTL_MS: number;
19
+ export interface DocPage {
20
+ title: string;
21
+ url: string;
22
+ summary: string;
23
+ /** Full markdown, from llms-full.txt. */
24
+ body?: string;
25
+ }
26
+ export interface DocSearchHit {
27
+ title: string;
28
+ url: string;
29
+ summary: string;
30
+ score: number;
31
+ snippet?: string;
32
+ }
33
+ export declare class DocsIndex {
34
+ private readonly baseUrl;
35
+ private readonly fetchImpl;
36
+ private readonly now;
37
+ private index?;
38
+ private full?;
39
+ constructor(opts?: {
40
+ baseUrl?: string;
41
+ fetchImpl?: typeof fetch;
42
+ now?: () => number;
43
+ });
44
+ /** The page index (llms.txt), in nav order. */
45
+ pages(): Promise<DocPage[]>;
46
+ /** Normalized page url to markdown body, from llms-full.txt. */
47
+ private bodies;
48
+ private cached;
49
+ search(query: string, limit?: number): Promise<DocSearchHit[]>;
50
+ /**
51
+ * One page with its markdown, by exact url, by url on any docs host, by
52
+ * title, or by a fragment of either.
53
+ */
54
+ read(ref: string): Promise<DocPage | undefined>;
55
+ private fetchText;
56
+ }
57
+ /** Parse `- [Title](url): summary` lines. Tolerates `*` bullets and missing summaries. */
58
+ export declare function parseLlmsTxt(text: string): DocPage[];
59
+ /** Split llms-full.txt on `<!-- page: url -->` markers into url to body. */
60
+ export declare function parseLlmsFull(text: string): Map<string, string>;
61
+ /**
62
+ * `https://d/x/index.md`, `https://d/x/`, `https://d/x/index.html` and
63
+ * `https://d/x` all identify the same page: llms.txt links the markdown file
64
+ * while llms-full.txt markers carry the canonical HTML url.
65
+ */
66
+ export declare function normalizeUrl(url: string): string;
package/bin/docs.js ADDED
@@ -0,0 +1,247 @@
1
+ "use strict";
2
+ /**
3
+ * The public docs (docs.advertising.chat) as data for `search_docs` and
4
+ * `read_doc`. Ported from AnyChat's `@anychat-ai/mcp` `docs.ts`.
5
+ *
6
+ * Reads the two machine-readable exports the docs build writes
7
+ * (docs repo, `hooks/llms_txt.py`):
8
+ * - `/llms.txt` index: `- [Title](url): one-line summary` per page
9
+ * - `/llms-full.txt` every page's markdown, each preceded by
10
+ * `<!-- page: <url> -->` and `# Title`
11
+ *
12
+ * Both are cached in process for {@link CACHE_TTL_MS}. When a refresh fails
13
+ * and a cached copy exists, the stale copy is served rather than failing the
14
+ * tool call. Search is a plain keyword scorer over title, summary, and body:
15
+ * the corpus is about 30 pages, and the model reads the page it picks with
16
+ * `read_doc` anyway.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.DocsIndex = exports.CACHE_TTL_MS = exports.DEFAULT_DOCS_URL = void 0;
20
+ exports.parseLlmsTxt = parseLlmsTxt;
21
+ exports.parseLlmsFull = parseLlmsFull;
22
+ exports.normalizeUrl = normalizeUrl;
23
+ exports.DEFAULT_DOCS_URL = 'https://docs.advertising.chat';
24
+ exports.CACHE_TTL_MS = 10 * 60 * 1000;
25
+ class DocsIndex {
26
+ baseUrl;
27
+ fetchImpl;
28
+ now;
29
+ index;
30
+ full;
31
+ constructor(opts = {}) {
32
+ this.baseUrl = (opts.baseUrl || exports.DEFAULT_DOCS_URL).replace(/\/+$/, '');
33
+ this.fetchImpl = opts.fetchImpl || fetch;
34
+ this.now = opts.now || Date.now;
35
+ }
36
+ /** The page index (llms.txt), in nav order. */
37
+ async pages() {
38
+ this.index = await this.cached(this.index, async () => parseLlmsTxt(await this.fetchText('/llms.txt')));
39
+ return this.index.value;
40
+ }
41
+ /** Normalized page url to markdown body, from llms-full.txt. */
42
+ async bodies() {
43
+ this.full = await this.cached(this.full, async () => parseLlmsFull(await this.fetchText('/llms-full.txt')));
44
+ return this.full.value;
45
+ }
46
+ async cached(entry, load) {
47
+ if (entry && this.now() - entry.at < exports.CACHE_TTL_MS)
48
+ return entry;
49
+ try {
50
+ return { value: await load(), at: this.now() };
51
+ }
52
+ catch (err) {
53
+ if (entry)
54
+ return entry;
55
+ throw err;
56
+ }
57
+ }
58
+ async search(query, limit = 5) {
59
+ const terms = tokenize(query);
60
+ if (terms.length === 0)
61
+ return [];
62
+ const pages = await this.pages();
63
+ let bodies;
64
+ try {
65
+ bodies = await this.bodies();
66
+ }
67
+ catch {
68
+ bodies = undefined; // index-only search still works
69
+ }
70
+ const hits = [];
71
+ for (const p of pages) {
72
+ const title = p.title.toLowerCase();
73
+ const summary = p.summary.toLowerCase();
74
+ const rawBody = bodies?.get(normalizeUrl(p.url));
75
+ const body = (rawBody || '').toLowerCase();
76
+ let score = 0;
77
+ let matched = 0;
78
+ for (const t of terms) {
79
+ let hit = false;
80
+ if (title.includes(t)) {
81
+ score += 5;
82
+ hit = true;
83
+ }
84
+ if (summary.includes(t)) {
85
+ score += 2;
86
+ hit = true;
87
+ }
88
+ if (body) {
89
+ const n = count(body, t);
90
+ if (n) {
91
+ score += Math.min(n, 10) * 0.5;
92
+ hit = true;
93
+ }
94
+ }
95
+ if (hit)
96
+ matched++;
97
+ }
98
+ // Pages that mention every term beat pages that mention one term loudly.
99
+ if (matched === terms.length && terms.length > 1)
100
+ score += 3;
101
+ if (score > 0) {
102
+ hits.push({
103
+ title: p.title,
104
+ url: p.url,
105
+ summary: p.summary,
106
+ score,
107
+ snippet: rawBody ? snippet(rawBody, terms) : undefined,
108
+ });
109
+ }
110
+ }
111
+ hits.sort((a, b) => b.score - a.score);
112
+ return hits.slice(0, limit);
113
+ }
114
+ /**
115
+ * One page with its markdown, by exact url, by url on any docs host, by
116
+ * title, or by a fragment of either.
117
+ */
118
+ async read(ref) {
119
+ const pages = await this.pages();
120
+ const needle = ref.trim().toLowerCase();
121
+ const page = pages.find(p => p.url.toLowerCase() === needle) ||
122
+ pages.find(p => normalizeUrl(p.url).toLowerCase() === normalizeUrl(needle)) ||
123
+ pages.find(p => samePath(p.url, needle)) ||
124
+ pages.find(p => p.title.toLowerCase() === needle) ||
125
+ pages.find(p => p.url.toLowerCase().includes(needle)) ||
126
+ pages.find(p => p.title.toLowerCase().includes(needle));
127
+ if (!page)
128
+ return undefined;
129
+ const bodies = await this.bodies();
130
+ return { ...page, body: bodies.get(normalizeUrl(page.url)) };
131
+ }
132
+ async fetchText(path) {
133
+ const url = `${this.baseUrl}${path}`;
134
+ const res = await this.fetchImpl(url, {
135
+ headers: { Accept: 'text/plain, text/markdown' },
136
+ signal: AbortSignal.timeout(10_000),
137
+ });
138
+ if (!res.ok)
139
+ throw new Error(`docs fetch failed: ${res.status} ${url}`);
140
+ return res.text();
141
+ }
142
+ }
143
+ exports.DocsIndex = DocsIndex;
144
+ /** Parse `- [Title](url): summary` lines. Tolerates `*` bullets and missing summaries. */
145
+ function parseLlmsTxt(text) {
146
+ const out = [];
147
+ const re = /^\s*[-*]\s+\[([^\]]+)\]\(([^)\s]+)\)\s*:?\s*(.*)$/;
148
+ for (const line of text.split(/\r?\n/)) {
149
+ const m = re.exec(line);
150
+ if (!m)
151
+ continue;
152
+ out.push({ title: m[1].trim(), url: m[2].trim(), summary: m[3].trim() });
153
+ }
154
+ return out;
155
+ }
156
+ /** Split llms-full.txt on `<!-- page: url -->` markers into url to body. */
157
+ function parseLlmsFull(text) {
158
+ const map = new Map();
159
+ const re = /<!--\s*page:\s*(\S+?)\s*-->/g;
160
+ const marks = [];
161
+ let m;
162
+ while ((m = re.exec(text))) {
163
+ marks.push({ url: m[1], start: m.index, end: m.index + m[0].length });
164
+ }
165
+ for (let i = 0; i < marks.length; i++) {
166
+ const bodyStart = marks[i].end;
167
+ const bodyEnd = i + 1 < marks.length ? marks[i + 1].start : text.length;
168
+ map.set(normalizeUrl(marks[i].url), text.slice(bodyStart, bodyEnd).trim());
169
+ }
170
+ return map;
171
+ }
172
+ const STOP = new Set([
173
+ 'the',
174
+ 'and',
175
+ 'for',
176
+ 'with',
177
+ 'how',
178
+ 'can',
179
+ 'what',
180
+ 'does',
181
+ 'this',
182
+ 'that',
183
+ 'are',
184
+ 'you',
185
+ 'your',
186
+ 'from',
187
+ 'into',
188
+ 'about',
189
+ 'use',
190
+ 'using',
191
+ 'set',
192
+ 'get',
193
+ ]);
194
+ function tokenize(q) {
195
+ return q
196
+ .toLowerCase()
197
+ .split(/[^a-z0-9]+/)
198
+ .filter(t => t.length > 2 && !STOP.has(t));
199
+ }
200
+ function count(hay, needle) {
201
+ let n = 0;
202
+ let i = 0;
203
+ while ((i = hay.indexOf(needle, i)) !== -1) {
204
+ n++;
205
+ i += needle.length;
206
+ }
207
+ return n;
208
+ }
209
+ function snippet(body, terms, width = 240) {
210
+ const lower = body.toLowerCase();
211
+ let best = -1;
212
+ for (const t of terms) {
213
+ const i = lower.indexOf(t);
214
+ if (i !== -1 && (best === -1 || i < best))
215
+ best = i;
216
+ }
217
+ if (best === -1)
218
+ return undefined;
219
+ const start = Math.max(0, best - width / 3);
220
+ const s = body
221
+ .slice(start, start + width)
222
+ .replace(/\s+/g, ' ')
223
+ .trim();
224
+ return (start > 0 ? '…' : '') + s + (start + width < body.length ? '…' : '');
225
+ }
226
+ /** Whether two absolute urls name the same page on any host. */
227
+ function samePath(a, b) {
228
+ if (!/^https?:\/\//i.test(b))
229
+ return false;
230
+ try {
231
+ const pa = normalizeUrl(new URL(a).pathname).toLowerCase();
232
+ const pb = normalizeUrl(new URL(b).pathname).toLowerCase();
233
+ return pa === pb;
234
+ }
235
+ catch {
236
+ return false;
237
+ }
238
+ }
239
+ /**
240
+ * `https://d/x/index.md`, `https://d/x/`, `https://d/x/index.html` and
241
+ * `https://d/x` all identify the same page: llms.txt links the markdown file
242
+ * while llms-full.txt markers carry the canonical HTML url.
243
+ */
244
+ function normalizeUrl(url) {
245
+ return url.trim().replace(/\/?(index\.md|index\.html)?\/?$/i, '');
246
+ }
247
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}