@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.
- package/README.md +123 -18
- package/bin/auth.d.ts +46 -0
- package/bin/auth.js +186 -0
- package/bin/auth.js.map +1 -0
- package/bin/cli.js +79 -11
- package/bin/cli.js.map +1 -1
- package/bin/client.d.ts +70 -0
- package/bin/client.js +121 -0
- package/bin/client.js.map +1 -0
- package/bin/docs.d.ts +66 -0
- package/bin/docs.js +247 -0
- package/bin/docs.js.map +1 -0
- package/bin/flow/flowSchema.d.ts +298 -0
- package/bin/flow/flowSchema.js +234 -0
- package/bin/flow/flowSchema.js.map +1 -0
- package/bin/flow/flowValidator.d.ts +15 -0
- package/bin/flow/flowValidator.js +179 -0
- package/bin/flow/flowValidator.js.map +1 -0
- package/bin/flow/flowZod.d.ts +117 -0
- package/bin/flow/flowZod.js +130 -0
- package/bin/flow/flowZod.js.map +1 -0
- package/bin/format.d.ts +14 -0
- package/bin/format.js +50 -0
- package/bin/format.js.map +1 -0
- package/bin/index.d.ts +23 -1
- package/bin/index.js +65 -4
- package/bin/index.js.map +1 -1
- package/bin/routeInventory.d.ts +69 -0
- package/bin/routeInventory.js +201 -0
- package/bin/routeInventory.js.map +1 -0
- package/bin/serve.d.ts +24 -0
- package/bin/serve.js +196 -0
- package/bin/serve.js.map +1 -0
- package/bin/server.d.ts +24 -36
- package/bin/server.js +54 -182
- package/bin/server.js.map +1 -1
- package/bin/tool.d.ts +84 -0
- package/bin/tool.js +39 -0
- package/bin/tool.js.map +1 -0
- package/bin/tools/account.d.ts +2 -0
- package/bin/tools/account.js +47 -0
- package/bin/tools/account.js.map +1 -0
- package/bin/tools/attributes.d.ts +10 -0
- package/bin/tools/attributes.js +200 -0
- package/bin/tools/attributes.js.map +1 -0
- package/bin/tools/campaigns.d.ts +12 -0
- package/bin/tools/campaigns.js +230 -0
- package/bin/tools/campaigns.js.map +1 -0
- package/bin/tools/decisions.d.ts +14 -0
- package/bin/tools/decisions.js +309 -0
- package/bin/tools/decisions.js.map +1 -0
- package/bin/tools/docs.d.ts +3 -0
- package/bin/tools/docs.js +55 -0
- package/bin/tools/docs.js.map +1 -0
- package/bin/tools/index.d.ts +21 -0
- package/bin/tools/index.js +60 -0
- package/bin/tools/index.js.map +1 -0
- package/bin/tools/moments.d.ts +9 -0
- package/bin/tools/moments.js +143 -0
- package/bin/tools/moments.js.map +1 -0
- package/bin/tools/network.d.ts +5 -0
- package/bin/tools/network.js +99 -0
- package/bin/tools/network.js.map +1 -0
- package/bin/tools/offers.d.ts +11 -0
- package/bin/tools/offers.js +239 -0
- package/bin/tools/offers.js.map +1 -0
- package/bin/tools/results.d.ts +18 -0
- package/bin/tools/results.js +116 -0
- package/bin/tools/results.js.map +1 -0
- package/bin/tools/rules.d.ts +9 -0
- package/bin/tools/rules.js +318 -0
- package/bin/tools/rules.js.map +1 -0
- package/bin/tools/settings.d.ts +3 -0
- package/bin/tools/settings.js +54 -0
- package/bin/tools/settings.js.map +1 -0
- package/bin/tools/shared.d.ts +50 -0
- package/bin/tools/shared.js +171 -0
- package/bin/tools/shared.js.map +1 -0
- package/bin/tools/translation.d.ts +6 -0
- package/bin/tools/translation.js +139 -0
- package/bin/tools/translation.js.map +1 -0
- package/bin/version.d.ts +2 -0
- package/bin/version.js +6 -0
- package/bin/version.js.map +1 -0
- 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)
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
18
|
+
npx @advertising-chat/mcp login
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
|
|
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
|
-
|
|
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
|
|
31
|
-
conversation. Takes `conversation_context` (a short topic
|
|
32
|
-
summary used only to select the ad), optional `subscriber` (
|
|
33
|
-
id for frequency capping), `ad_unit`, `format`. Returns the
|
|
34
|
-
mandatory sponsored-disclosure reminder and click-tracked URLs,
|
|
35
|
-
`no_ad`.
|
|
36
|
-
- **`record_event
|
|
37
|
-
optional value
|
|
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
|
|
144
|
+
so your assistant knows when to fetch and how to present ads.
|
|
41
145
|
|
|
42
|
-
|
|
43
|
-
Quickstart:
|
|
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
|
package/bin/auth.js.map
ADDED
|
@@ -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
|
-
*
|
|
5
|
+
* adchat-mcp: the Advertising.chat MCP server (stdio).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/bin/client.d.ts
ADDED
|
@@ -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
|
+
}
|