@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/README.md CHANGED
@@ -1,21 +1,115 @@
1
1
  # @advertising-chat/mcp
2
2
 
3
- MCP server for [Advertising.chat](https://advertising.chat) — give any
4
- agent the ability to serve (clearly labeled) sponsored messages and earn
5
- revenue from its conversations.
3
+ The MCP server for [Advertising.chat](https://advertising.chat). It runs in
4
+ one of two modes:
5
+
6
+ - **manage**: run Offer Manager from Claude Code, Claude Desktop, or any MCP
7
+ host, with your own login. Agents, moments, rules, and offers; why a
8
+ customer did or did not see an offer; the docs.
9
+ - **serve**: give an agent the in-chat ad tools (`fetch_ad`,
10
+ `record_event`, `record_reply`) with an API key.
11
+
12
+ ## Manage Offer Manager
13
+
14
+ Sign in once. The login is the same as the `ads` command line tool's
15
+ (`~/.ads-cli`), so signing in with either signs in both:
6
16
 
7
17
  ```bash
8
- ADCHAT_API_KEY=... npx @advertising-chat/mcp
18
+ npx @advertising-chat/mcp login
9
19
  ```
10
20
 
11
- Agent host config:
21
+ Then add the server to your host:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "advertising-chat": {
27
+ "command": "npx",
28
+ "args": ["-y", "@advertising-chat/mcp", "manage"]
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ Every call runs as you, with your role in the org: a viewer can read, and an
35
+ editor can also create, change, and delete. Changes are recorded as made
36
+ through the MCP server (`_audit.updatedBy.agent` is `mcp`).
37
+
38
+ | Variable | Meaning |
39
+ |---|---|
40
+ | `ADCHAT_ORG` | The org to work in. Default: your own. |
41
+ | `ADCHAT_TOKEN` | An access token to use instead of the cached login. |
42
+ | `ADS_API_ROOT` | Another gateway, e.g. `http://localhost:8380/system`. |
43
+ | `ADCHAT_SYSTEM_REQUEST` | `true` for sysops working in another org (with `ADCHAT_ORG`). |
44
+
45
+ `manage --read-only` registers only the tools that read.
46
+
47
+ ### Tools
48
+
49
+ | Tool | Kind | Role |
50
+ |---|---|---|
51
+ | `whoami`, `list_applications` | read | viewer |
52
+ | `list_moments`, `get_moment` | read | viewer |
53
+ | `create_moment`, `update_moment` | write | editor |
54
+ | `list_attributes`, `get_attribute` | read | viewer |
55
+ | `add_attribute`, `document_attribute`, `update_attribute` | write | editor |
56
+ | `translate_rule_text`, `describe_rule`, `preview_rule_impact` | read | viewer |
57
+ | `list_rules`, `get_rule` | read | viewer |
58
+ | `create_rule`, `update_rule` | write | editor |
59
+ | `list_offers`, `get_offer` | read | viewer |
60
+ | `create_offer`, `update_offer`, `publish_offer`, `pause_offer` | write | editor |
61
+ | `get_offer_limit` | read | viewer |
62
+ | `set_offer_limit` | write | editor |
63
+ | `delete_moment`, `delete_attribute`, `delete_rule`, `delete_offer` | destructive | editor |
64
+ | `get_results`, `get_network_status` | read | viewer |
65
+ | `set_network_ads` | write | editor |
66
+ | `list_campaigns`, `get_campaign` | read | viewer |
67
+ | `request_campaign`, `pause_campaign`, `resume_campaign`, `resubmit_campaign` | write | editor |
68
+ | `find_requests`, `explain_decision`, `get_stats` | read | viewer |
69
+ | `search_docs`, `read_doc` | read | viewer |
70
+
71
+ Offers, rules, customer details (attributes), and translation need Offer
72
+ Manager in the workspace, and campaigns need campaigns (`advertise`); the
73
+ tool says so (`capability` in the table). Results, moments, and ads from the
74
+ network work in any workspace. Every
75
+ change carries a plain sentence for the person approving it
76
+ (`approvalSentence(tool, input, before)`).
77
+
78
+ Moments and rules belong to one agent: their tools take the agent as
79
+ `application`. Rule inputs are the schemas of
80
+ [`@advertising-chat/offer-rules`](https://docs.advertising.chat/reference/rules/),
81
+ the package the platform validates rules with, and a rule is checked before
82
+ it is sent. Rules are created disabled unless you ask to launch. How often
83
+ an offer appears is its rule's `frequency`; the workspace's offer limit
84
+ (`get_offer_limit`, `set_offer_limit`) caps how many of the brand's offers
85
+ one customer sees in a period.
86
+
87
+ ### In your own code
88
+
89
+ The tool table is importable. The Advertising.chat console's Assistant runs
90
+ the same definitions in process:
91
+
92
+ ```ts
93
+ import { DocsIndex, ManageClient, toolsByName } from '@advertising-chat/mcp';
94
+
95
+ const client = new ManageClient({ authorization: `Bearer ${token}`, org });
96
+ const rules = await toolsByName
97
+ .get('list_rules')!
98
+ .run({ client, docs: new DocsIndex() }, { application });
99
+ ```
100
+
101
+ Each tool has a `kind` (`read`, `write`, `destructive`), a `roleFloor`, a
102
+ zod `input` shape, and, for a change to one record, the `reader` tool that
103
+ returns it.
104
+
105
+ ## Serve in-chat ads
12
106
 
13
107
  ```json
14
108
  {
15
109
  "mcpServers": {
16
110
  "adchat": {
17
111
  "command": "npx",
18
- "args": ["-y", "@advertising-chat/mcp"],
112
+ "args": ["-y", "@advertising-chat/mcp", "serve"],
19
113
  "env": {
20
114
  "ADCHAT_API_KEY": "<your key from console.advertising.chat>",
21
115
  "ADCHAT_AD_UNIT": "<optional default ad unit>"
@@ -25,19 +119,30 @@ Agent host config:
25
119
  }
26
120
  ```
27
121
 
28
- ## Tools
122
+ Without a mode argument the server serves when `ADCHAT_API_KEY` is set, and
123
+ manages otherwise.
124
+
125
+ Use a fetch key: it is bound to one application (agent), so nothing else is
126
+ needed. With any other key, also set `ADCHAT_APPLICATION` to the
127
+ application's id, or fetches are rejected with a 422.
29
128
 
30
- - **`fetch_ad`** — fetch one sponsored message for the current
31
- conversation. Takes `conversation_context` (a short topic/intent
32
- summary used only to select the ad), optional `subscriber` (anonymous
33
- id for frequency capping), `ad_unit`, `format`. Returns the ad with a
34
- mandatory sponsored-disclosure reminder and click-tracked URLs, or
35
- `no_ad`.
36
- - **`record_event`** — report engagement (`click`, `conversion` with
37
- optional value/currency, or message lifecycle events) for a fetched ad.
129
+ - **`fetch_ad`**: fetch one sponsored message for the current
130
+ conversation. Takes `conversation_context` (a short topic and intent
131
+ summary used only to select the ad), an optional `subscriber` (an
132
+ anonymous id for frequency capping), `ad_unit`, and `format`. Returns the
133
+ ad with a mandatory sponsored-disclosure reminder and click-tracked URLs,
134
+ or `no_ad`.
135
+ - **`record_event`**: report engagement (`click`, `conversion` with an
136
+ optional value and currency, or message lifecycle events) for a fetched
137
+ ad.
138
+ - **`record_reply`**: report that the user chose one of the ad's replies,
139
+ with the reply's `postback_data` from `fetch_ad`. A reply that accepts or
140
+ declines the offer is recorded as the customer's response, which rules
141
+ can use.
38
142
 
39
143
  Pair it with the [Ad Skill](https://github.com/advertising-chat/adkit/blob/main/skill/SKILL.md)
40
- so your assistant knows *when* to fetch and how to present ads.
144
+ so your assistant knows when to fetch and how to present ads.
41
145
 
42
- Env: `ADCHAT_API_KEY` (required), `ADCHAT_AD_UNIT`, `ADCHAT_BASE_URL`.
43
- Quickstart: [docs.advertising.chat](https://docs.advertising.chat).
146
+ Variables: `ADCHAT_API_KEY` (required), `ADCHAT_APPLICATION`,
147
+ `ADCHAT_AD_UNIT`, `ADCHAT_BASE_URL`. Quickstart:
148
+ [docs.advertising.chat](https://docs.advertising.chat).
package/bin/auth.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ export declare const AUTH0_DOMAIN = "advertising-chat.us.auth0.com";
2
+ /** The "Advertising.chat CLI" Auth0 native client (device-code flow). */
3
+ export declare const AUTH0_CLIENT_ID = "rZ67p5ctrl5dwcl38ZyjYNGVf7PFb11B";
4
+ export declare const AUTH0_AUDIENCE = "https://api.advertising.chat/";
5
+ export declare const TOKEN_CACHE_PATH: string;
6
+ export interface CachedToken {
7
+ access_token: string;
8
+ token_type?: string;
9
+ expires_in?: number;
10
+ /** Epoch ms when the token was obtained. */
11
+ obtained_at?: number;
12
+ refresh_token?: string;
13
+ }
14
+ export interface TokenProviderOptions {
15
+ /** Explicit access token (ADCHAT_TOKEN). Wins over the cache. */
16
+ token?: string;
17
+ /** Cache path override (tests). */
18
+ cachePath?: string;
19
+ fetchFn?: typeof fetch;
20
+ }
21
+ export declare function loadCachedToken(path?: string): CachedToken | null;
22
+ export declare function saveCachedToken(token: CachedToken, path?: string): void;
23
+ export declare function clearCachedToken(path?: string): void;
24
+ /** An async provider of a current access token. */
25
+ export declare function createTokenProvider(options?: TokenProviderOptions): () => Promise<string>;
26
+ export interface DeviceCode {
27
+ device_code: string;
28
+ user_code: string;
29
+ verification_uri: string;
30
+ verification_uri_complete: string;
31
+ expires_in: number;
32
+ interval: number;
33
+ }
34
+ export interface DeviceLoginOptions {
35
+ cachePath?: string;
36
+ fetchFn?: typeof fetch;
37
+ /** Called once with the code the user confirms in the browser. */
38
+ prompt: (device: DeviceCode) => void;
39
+ /** Sleep between polls (tests). */
40
+ sleep?: (ms: number) => Promise<void>;
41
+ }
42
+ /**
43
+ * The device-code flow: request a code, let the user confirm it in a
44
+ * browser, poll until Auth0 issues tokens, and cache them.
45
+ */
46
+ export declare function deviceLogin(options: DeviceLoginOptions): Promise<CachedToken>;
package/bin/auth.js ADDED
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TOKEN_CACHE_PATH = exports.AUTH0_AUDIENCE = exports.AUTH0_CLIENT_ID = exports.AUTH0_DOMAIN = void 0;
37
+ exports.loadCachedToken = loadCachedToken;
38
+ exports.saveCachedToken = saveCachedToken;
39
+ exports.clearCachedToken = clearCachedToken;
40
+ exports.createTokenProvider = createTokenProvider;
41
+ exports.deviceLogin = deviceLogin;
42
+ /**
43
+ * Sign-in for the management tools: the user's own Auth0 login.
44
+ *
45
+ * `adchat-mcp login` runs the Auth0 device-code flow with the
46
+ * "Advertising.chat CLI" native client, the same client and token cache
47
+ * (`~/.ads-cli`) as `ads login` in ads-cli, so signing in with either signs
48
+ * in both. The server then reads the cache and refreshes the access token
49
+ * with the cached refresh token when it nears expiry, writing the new token
50
+ * back. `ADCHAT_TOKEN` overrides the cache with an explicit access token.
51
+ *
52
+ * Tokens are never logged.
53
+ */
54
+ const fs = __importStar(require("fs"));
55
+ const os = __importStar(require("os"));
56
+ exports.AUTH0_DOMAIN = 'advertising-chat.us.auth0.com';
57
+ /** The "Advertising.chat CLI" Auth0 native client (device-code flow). */
58
+ exports.AUTH0_CLIENT_ID = 'rZ67p5ctrl5dwcl38ZyjYNGVf7PFb11B';
59
+ exports.AUTH0_AUDIENCE = 'https://api.advertising.chat/';
60
+ exports.TOKEN_CACHE_PATH = `${os.homedir()}/.ads-cli`;
61
+ /** Refresh five minutes before expiry. */
62
+ const EXPIRY_BUFFER_MS = 5 * 60 * 1000;
63
+ function loadCachedToken(path = exports.TOKEN_CACHE_PATH) {
64
+ try {
65
+ if (!fs.existsSync(path))
66
+ return null;
67
+ return JSON.parse(fs.readFileSync(path, 'utf-8'));
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ function saveCachedToken(token, path = exports.TOKEN_CACHE_PATH) {
74
+ fs.writeFileSync(path, JSON.stringify(token, null, 2), { mode: 0o600 });
75
+ }
76
+ function clearCachedToken(path = exports.TOKEN_CACHE_PATH) {
77
+ if (fs.existsSync(path))
78
+ fs.unlinkSync(path);
79
+ }
80
+ function isExpired(token) {
81
+ // Without timing information there is no way to tell: assume valid.
82
+ if (!token.obtained_at || !token.expires_in)
83
+ return false;
84
+ return (Date.now() >= token.obtained_at + token.expires_in * 1000 - EXPIRY_BUFFER_MS);
85
+ }
86
+ async function postJson(fetchFn, path, body) {
87
+ const res = await fetchFn(`https://${exports.AUTH0_DOMAIN}${path}`, {
88
+ method: 'POST',
89
+ headers: { 'Content-Type': 'application/json' },
90
+ body: JSON.stringify(body),
91
+ });
92
+ const data = (await res.json().catch(() => ({})));
93
+ return { ok: res.ok, status: res.status, data };
94
+ }
95
+ async function refresh(token, cachePath, fetchFn) {
96
+ if (!token.refresh_token) {
97
+ throw new Error('Your Advertising.chat session expired. Run `npx @advertising-chat/mcp login` to sign in again.');
98
+ }
99
+ const res = await postJson(fetchFn, '/oauth/token', {
100
+ grant_type: 'refresh_token',
101
+ client_id: exports.AUTH0_CLIENT_ID,
102
+ refresh_token: token.refresh_token,
103
+ });
104
+ if (!res.ok) {
105
+ throw new Error(`Token refresh failed (${res.status}). Run \`npx @advertising-chat/mcp login\` to sign in again.`);
106
+ }
107
+ const updated = {
108
+ access_token: res.data.access_token,
109
+ token_type: res.data.token_type,
110
+ expires_in: res.data.expires_in,
111
+ obtained_at: Date.now(),
112
+ refresh_token: res.data.refresh_token || token.refresh_token,
113
+ };
114
+ saveCachedToken(updated, cachePath);
115
+ return updated;
116
+ }
117
+ /** An async provider of a current access token. */
118
+ function createTokenProvider(options = {}) {
119
+ const cachePath = options.cachePath || exports.TOKEN_CACHE_PATH;
120
+ const fetchFn = options.fetchFn || fetch.bind(globalThis);
121
+ return async () => {
122
+ if (options.token)
123
+ return options.token;
124
+ const cached = loadCachedToken(cachePath);
125
+ if (!cached) {
126
+ throw new Error('Not signed in. Run `npx @advertising-chat/mcp login` (or `ads login`), or set ADCHAT_TOKEN.');
127
+ }
128
+ if (isExpired(cached)) {
129
+ return (await refresh(cached, cachePath, fetchFn)).access_token;
130
+ }
131
+ return cached.access_token;
132
+ };
133
+ }
134
+ /**
135
+ * The device-code flow: request a code, let the user confirm it in a
136
+ * browser, poll until Auth0 issues tokens, and cache them.
137
+ */
138
+ async function deviceLogin(options) {
139
+ const fetchFn = options.fetchFn || fetch.bind(globalThis);
140
+ const sleep = options.sleep || ((ms) => new Promise(r => setTimeout(r, ms)));
141
+ const code = await postJson(fetchFn, '/oauth/device/code', {
142
+ client_id: exports.AUTH0_CLIENT_ID,
143
+ audience: exports.AUTH0_AUDIENCE,
144
+ scope: 'openid profile email offline_access',
145
+ });
146
+ if (!code.ok)
147
+ throw new Error(`Could not start sign-in (${code.status}).`);
148
+ const device = code.data;
149
+ options.prompt(device);
150
+ const deadline = Date.now() + device.expires_in * 1000;
151
+ let interval = device.interval * 1000;
152
+ while (Date.now() < deadline) {
153
+ await sleep(interval);
154
+ const res = await postJson(fetchFn, '/oauth/token', {
155
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
156
+ client_id: exports.AUTH0_CLIENT_ID,
157
+ device_code: device.device_code,
158
+ });
159
+ if (res.ok) {
160
+ const token = {
161
+ access_token: res.data.access_token,
162
+ token_type: res.data.token_type,
163
+ expires_in: res.data.expires_in,
164
+ obtained_at: Date.now(),
165
+ refresh_token: res.data.refresh_token,
166
+ };
167
+ saveCachedToken(token, options.cachePath);
168
+ return token;
169
+ }
170
+ switch (res.data.error) {
171
+ case 'authorization_pending':
172
+ continue;
173
+ case 'slow_down':
174
+ interval += 5000;
175
+ continue;
176
+ case 'access_denied':
177
+ throw new Error('Sign-in was denied.');
178
+ case 'expired_token':
179
+ throw new Error('The sign-in code expired. Run login again.');
180
+ default:
181
+ throw new Error(`Sign-in failed: ${res.data.error ?? res.status}`);
182
+ }
183
+ }
184
+ throw new Error('The sign-in code expired. Run login again.');
185
+ }
186
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/bin/cli.js CHANGED
@@ -2,31 +2,99 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  /**
5
- * AdKit MCP server (stdio).
5
+ * adchat-mcp: the Advertising.chat MCP server (stdio).
6
6
  *
7
- * Usage: set ADCHAT_API_KEY (and optionally ADCHAT_AD_UNIT), then run
8
- * `npx @advertising-chat/mcp` from any MCP-capable agent host.
7
+ * adchat-mcp login sign in (device code; shares ~/.ads-cli with `ads login`)
8
+ * adchat-mcp logout forget the cached login
9
+ * adchat-mcp manage Offer Manager tools, as the signed-in user
10
+ * adchat-mcp serve in-chat ad tools (fetch_ad, record_event), with ADCHAT_API_KEY
11
+ * adchat-mcp `serve` when ADCHAT_API_KEY is set, otherwise `manage`
12
+ *
13
+ * manage: ADCHAT_ORG picks the org (default: the user's own), ADCHAT_TOKEN
14
+ * overrides the cached login, `--read-only` registers only read tools,
15
+ * ADS_API_ROOT points at another gateway (`http://localhost:8380/system`),
16
+ * and ADCHAT_SYSTEM_REQUEST=true (sysops, with ADCHAT_ORG) works in another
17
+ * org. serve: ADCHAT_APPLICATION, ADCHAT_AD_UNIT, ADCHAT_BASE_URL.
18
+ *
19
+ * stdout carries the MCP protocol, so everything for people goes to stderr.
9
20
  */
21
+ const child_process_1 = require("child_process");
10
22
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
23
+ const auth_1 = require("./auth");
24
+ const client_1 = require("./client");
25
+ const serve_1 = require("./serve");
11
26
  const server_1 = require("./server");
12
- async function main() {
27
+ const say = (line = '') => process.stderr.write(`${line}\n`);
28
+ function openBrowser(url) {
29
+ const cmd = process.platform === 'darwin'
30
+ ? `open "${url}"`
31
+ : process.platform === 'win32'
32
+ ? `start "" "${url}"`
33
+ : `xdg-open "${url}"`;
34
+ (0, child_process_1.exec)(cmd, () => undefined);
35
+ }
36
+ function manageClient() {
37
+ const getToken = (0, auth_1.createTokenProvider)({ token: process.env.ADCHAT_TOKEN });
38
+ return new client_1.ManageClient({
39
+ authorization: async () => `Bearer ${await getToken()}`,
40
+ org: process.env.ADCHAT_ORG,
41
+ systemRequest: process.env.ADCHAT_SYSTEM_REQUEST === 'true',
42
+ baseUrl: process.env.ADS_API_ROOT,
43
+ agent: 'mcp',
44
+ });
45
+ }
46
+ async function login() {
47
+ await (0, auth_1.deviceLogin)({
48
+ prompt: device => {
49
+ say(`Your code: ${device.user_code}`);
50
+ say(`Confirm it at ${device.verification_uri_complete}`);
51
+ say('Waiting for you to sign in in the browser...');
52
+ openBrowser(device.verification_uri_complete);
53
+ },
54
+ });
55
+ const me = await manageClient().get('/user/me');
56
+ say(`Signed in as ${me?.email ?? 'unknown'}${me?.org?.name ? ` (${me.org.name})` : ''}. The login is cached at ${auth_1.TOKEN_CACHE_PATH}.`);
57
+ }
58
+ async function manage(readOnly) {
59
+ const server = (0, server_1.createManageServer)({ client: manageClient(), readOnly });
60
+ await server.connect(new stdio_js_1.StdioServerTransport());
61
+ say('Advertising.chat MCP server running (manage, stdio)');
62
+ }
63
+ async function serve() {
13
64
  const apiKey = process.env.ADCHAT_API_KEY;
14
65
  if (!apiKey) {
15
- console.error('ADCHAT_API_KEY is required. Get an API key from the ' +
16
- 'Advertising.chat console (https://console.advertising.chat) and ' +
17
- 'set it in the MCP server environment.');
66
+ say('ADCHAT_API_KEY is required for serve. Create an API key in the console (https://console.advertising.chat) and set it in the MCP server environment.');
18
67
  process.exit(1);
19
68
  }
20
- const server = (0, server_1.createAdKitServer)({
69
+ const server = (0, serve_1.createAdKitServer)({
21
70
  apiKey,
71
+ application: process.env.ADCHAT_APPLICATION,
22
72
  adUnit: process.env.ADCHAT_AD_UNIT,
23
73
  baseUrl: process.env.ADCHAT_BASE_URL,
24
74
  });
25
75
  await server.connect(new stdio_js_1.StdioServerTransport());
26
- console.error('AdKit MCP server running (stdio)');
76
+ say('Advertising.chat MCP server running (serve, stdio)');
77
+ }
78
+ async function main(argv) {
79
+ const command = argv.find(a => !a.startsWith('-')) ??
80
+ (process.env.ADCHAT_API_KEY ? 'serve' : 'manage');
81
+ switch (command) {
82
+ case 'login':
83
+ return login();
84
+ case 'logout':
85
+ (0, auth_1.clearCachedToken)();
86
+ return say('Signed out.');
87
+ case 'manage':
88
+ return manage(argv.includes('--read-only'));
89
+ case 'serve':
90
+ return serve();
91
+ default:
92
+ say(`Unknown command "${command}". Use login, logout, manage, or serve.`);
93
+ process.exit(2);
94
+ }
27
95
  }
28
- main().catch(err => {
29
- console.error('AdKit MCP server failed to start:', err);
96
+ main(process.argv.slice(2)).catch(err => {
97
+ say(`adchat-mcp: ${err instanceof Error ? err.message : String(err)}`);
30
98
  process.exit(1);
31
99
  });
32
100
  //# sourceMappingURL=cli.js.map
package/bin/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA;;;;;GAKG;AACH,wEAAiF;AACjF,qCAA6C;AAE7C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CACX,sDAAsD;YACpD,kEAAkE;YAClE,uCAAuC,CAC1C,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,0BAAiB,EAAC;QAC/B,MAAM;QACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;QAClC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;KACrC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,+BAAoB,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;AACpD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * HTTP client for the Advertising.chat management API, the api gateway's
3
+ * `/system/*` surface.
4
+ *
5
+ * Every request carries the user's own Auth0 bearer token, the org it acts
6
+ * in (`X-Adchat-Target-Org`), and the surface that made it
7
+ * (`X-Adchat-Agent`, stamped into `_audit` on every write). The client holds
8
+ * no platform credential, so a tool can do exactly what the user could do
9
+ * in the console and nothing more. Tokens are never logged.
10
+ */
11
+ export declare const DEFAULT_API_URL = "https://api.advertising.chat/system";
12
+ /** Surfaces that call the management API, as carried in `X-Adchat-Agent`. */
13
+ export type Surface = 'mcp' | 'copilot' | 'cli' | 'console';
14
+ export interface ManageClientOptions {
15
+ /**
16
+ * The `Authorization` header value (`Bearer <token>`), or an async
17
+ * provider of it (the MCP server refreshes the cached login).
18
+ */
19
+ authorization: string | (() => Promise<string>);
20
+ /**
21
+ * Target org id. When omitted, the client resolves the user's own org
22
+ * once with `GET /user/me`.
23
+ */
24
+ org?: string;
25
+ /**
26
+ * Sysop cross-org mode: also send `X-Adchat-System-Request: true`.
27
+ * Only meaningful for members of the sysop org; requires `org`.
28
+ */
29
+ systemRequest?: boolean;
30
+ /** The `/system` root. Defaults to production. */
31
+ baseUrl?: string;
32
+ /** Attribution for `_audit`. Defaults to `mcp`. */
33
+ agent?: Surface;
34
+ /** Per-request timeout. Default 30 seconds. */
35
+ timeoutMs?: number;
36
+ /** Override fetch (tests). */
37
+ fetchFn?: typeof fetch;
38
+ }
39
+ /** A non-2xx answer from the management API. */
40
+ export declare class ApiError extends Error {
41
+ readonly status: number;
42
+ readonly method: string;
43
+ readonly path: string;
44
+ /** Parsed response body (JSON when the server sent JSON). */
45
+ readonly body?: unknown | undefined;
46
+ constructor(status: number, method: string, path: string,
47
+ /** Parsed response body (JSON when the server sent JSON). */
48
+ body?: unknown | undefined);
49
+ }
50
+ export type QueryParams = Record<string, string | number | boolean | undefined>;
51
+ export declare class ManageClient {
52
+ private readonly opts;
53
+ private org;
54
+ private readonly baseUrl;
55
+ private readonly agent;
56
+ constructor(opts: ManageClientOptions);
57
+ get<T = unknown>(path: string, query?: QueryParams): Promise<T>;
58
+ post<T = unknown>(path: string, body?: unknown): Promise<T>;
59
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
60
+ patch<T = unknown>(path: string, body?: unknown): Promise<T>;
61
+ delete<T = unknown>(path: string): Promise<T>;
62
+ /** The org requests act in, resolving the user's own org if needed. */
63
+ resolveOrg(): Promise<string>;
64
+ /** `path` is relative to `/system`, e.g. `/offer-manager/adunit`. */
65
+ request<T>(method: string, path: string, { query, body, withOrg, }: {
66
+ query?: QueryParams;
67
+ body?: unknown;
68
+ withOrg?: boolean;
69
+ }): Promise<T>;
70
+ }