@adcp/client 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -0
- package/bin/adcp.js +358 -0
- package/dist/lib/core/ADCPClient.d.ts +58 -2
- package/dist/lib/core/ADCPClient.d.ts.map +1 -1
- package/dist/lib/core/ADCPClient.js +200 -7
- package/dist/lib/core/ADCPClient.js.map +1 -1
- package/dist/lib/discovery/property-crawler.d.ts +44 -0
- package/dist/lib/discovery/property-crawler.d.ts.map +1 -0
- package/dist/lib/discovery/property-crawler.js +140 -0
- package/dist/lib/discovery/property-crawler.js.map +1 -0
- package/dist/lib/discovery/property-index.d.ts +68 -0
- package/dist/lib/discovery/property-index.d.ts.map +1 -0
- package/dist/lib/discovery/property-index.js +151 -0
- package/dist/lib/discovery/property-index.js.map +1 -0
- package/dist/lib/discovery/types.d.ts +35 -0
- package/dist/lib/discovery/types.d.ts.map +1 -0
- package/dist/lib/discovery/types.js +7 -0
- package/dist/lib/discovery/types.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +8 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/protocols/a2a.d.ts.map +1 -1
- package/dist/lib/protocols/a2a.js +53 -20
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +41 -39
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/types/core.generated.d.ts +81 -61
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/schemas.generated.d.ts +61 -270
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +31 -22
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +81 -76
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -347,6 +347,82 @@ All AdCP tools with full type safety:
|
|
|
347
347
|
- `activateSignal()` - Activate audience signals
|
|
348
348
|
- `providePerformanceFeedback()` - Send performance feedback
|
|
349
349
|
|
|
350
|
+
## Property Discovery (AdCP v2.2.0)
|
|
351
|
+
|
|
352
|
+
Build agent registries by discovering properties agents can sell. Works with AdCP v2.2.0's publisher-domain model.
|
|
353
|
+
|
|
354
|
+
### How It Works
|
|
355
|
+
|
|
356
|
+
1. **Agents return publisher domains**: Call `listAuthorizedProperties()` → get `publisher_domains[]`
|
|
357
|
+
2. **Fetch property definitions**: Get `https://{domain}/.well-known/adagents.json` from each domain
|
|
358
|
+
3. **Index properties**: Build fast lookups for "who can sell X?" and "what can agent Y sell?"
|
|
359
|
+
|
|
360
|
+
### Three Key Queries
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
import { PropertyCrawler, getPropertyIndex } from '@adcp/client';
|
|
364
|
+
|
|
365
|
+
// First, crawl agents to discover properties
|
|
366
|
+
const crawler = new PropertyCrawler();
|
|
367
|
+
await crawler.crawlAgents([
|
|
368
|
+
{ agent_url: 'https://agent-x.com', protocol: 'a2a' },
|
|
369
|
+
{ agent_url: 'https://agent-y.com/mcp/', protocol: 'mcp' }
|
|
370
|
+
]);
|
|
371
|
+
|
|
372
|
+
const index = getPropertyIndex();
|
|
373
|
+
|
|
374
|
+
// Query 1: Who can sell this property?
|
|
375
|
+
const matches = index.findAgentsForProperty('domain', 'cnn.com');
|
|
376
|
+
// Returns: [{ property, agent_url, publisher_domain }]
|
|
377
|
+
|
|
378
|
+
// Query 2: What can this agent sell?
|
|
379
|
+
const auth = index.getAgentAuthorizations('https://agent-x.com');
|
|
380
|
+
// Returns: { agent_url, publisher_domains: [...], properties: [...] }
|
|
381
|
+
|
|
382
|
+
// Query 3: Find by tags
|
|
383
|
+
const premiumProperties = index.findAgentsByPropertyTags(['premium', 'ctv']);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Full Example
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { PropertyCrawler, getPropertyIndex } from '@adcp/client';
|
|
390
|
+
|
|
391
|
+
const crawler = new PropertyCrawler();
|
|
392
|
+
|
|
393
|
+
// Crawl agents - gets publisher_domains from each, then fetches adagents.json
|
|
394
|
+
const result = await crawler.crawlAgents([
|
|
395
|
+
{ agent_url: 'https://sales.cnn.com' },
|
|
396
|
+
{ agent_url: 'https://sales.espn.com' }
|
|
397
|
+
]);
|
|
398
|
+
|
|
399
|
+
console.log(`✅ ${result.successfulAgents} agents`);
|
|
400
|
+
console.log(`📡 ${result.totalPublisherDomains} publisher domains`);
|
|
401
|
+
console.log(`📦 ${result.totalProperties} properties indexed`);
|
|
402
|
+
|
|
403
|
+
// Now query
|
|
404
|
+
const index = getPropertyIndex();
|
|
405
|
+
const whoCanSell = index.findAgentsForProperty('ios_bundle', 'com.cnn.app');
|
|
406
|
+
|
|
407
|
+
for (const match of whoCanSell) {
|
|
408
|
+
console.log(`${match.agent_url} can sell ${match.property.name}`);
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Property Types
|
|
413
|
+
|
|
414
|
+
Supports 18 identifier types: `domain`, `subdomain`, `ios_bundle`, `android_package`, `apple_app_store_id`, `google_play_id`, `roku_channel_id`, `podcast_rss_feed`, and more.
|
|
415
|
+
|
|
416
|
+
### Use Case
|
|
417
|
+
|
|
418
|
+
Build a registry service that:
|
|
419
|
+
- Periodically crawls agents with `PropertyCrawler`
|
|
420
|
+
- Persists discovered properties to a database
|
|
421
|
+
- Exposes fast query APIs using the in-memory index patterns
|
|
422
|
+
- Provides web UI for browsing properties and agents
|
|
423
|
+
|
|
424
|
+
Library provides discovery logic - you add persistence layer.
|
|
425
|
+
|
|
350
426
|
## Database Schema
|
|
351
427
|
|
|
352
428
|
Simple unified event log for all operations:
|
|
@@ -379,6 +455,31 @@ WHERE operation_id = 'delivery_report_agent_x_2025-10'
|
|
|
379
455
|
ORDER BY sequence_number;
|
|
380
456
|
```
|
|
381
457
|
|
|
458
|
+
## CLI Tool
|
|
459
|
+
|
|
460
|
+
For development and testing, use the included CLI tool to interact with AdCP agents:
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
# List available tools from an agent
|
|
464
|
+
npx @adcp/client mcp https://test-agent.adcontextprotocol.org
|
|
465
|
+
|
|
466
|
+
# Call a tool with inline JSON payload
|
|
467
|
+
npx @adcp/client a2a https://agent.example.com get_products '{"brief":"Coffee brands"}'
|
|
468
|
+
|
|
469
|
+
# Use a file for payload
|
|
470
|
+
npx @adcp/client mcp https://agent.example.com create_media_buy @payload.json
|
|
471
|
+
|
|
472
|
+
# With authentication
|
|
473
|
+
npx @adcp/client mcp https://agent.example.com get_products '{"brief":"..."}' --auth your-token
|
|
474
|
+
|
|
475
|
+
# JSON output for scripting
|
|
476
|
+
npx @adcp/client mcp https://agent.example.com get_products '{"brief":"..."}' --json
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**MCP Endpoint Discovery**: The client automatically discovers MCP endpoints. Just provide any URL - it tests your path first, and if no MCP server responds, it tries adding `/mcp`. Works with root domains, custom paths, anything.
|
|
480
|
+
|
|
481
|
+
See [docs/CLI.md](docs/CLI.md) for complete CLI documentation including webhook support for async operations.
|
|
482
|
+
|
|
382
483
|
## Testing
|
|
383
484
|
|
|
384
485
|
Try the live testing UI at `http://localhost:8080` when running the server:
|
package/bin/adcp.js
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AdCP CLI Tool
|
|
5
|
+
*
|
|
6
|
+
* Simple command-line utility to call AdCP agents directly
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* adcp <protocol> <agent-url> <tool-name> [payload-json] [--auth token]
|
|
10
|
+
*
|
|
11
|
+
* Examples:
|
|
12
|
+
* adcp mcp https://agent.example.com/mcp get_products '{"brief":"coffee brands"}'
|
|
13
|
+
* adcp a2a https://agent.example.com list_creative_formats '{}' --auth your_token_here
|
|
14
|
+
* adcp mcp https://agent.example.com/mcp create_media_buy @payload.json --auth $AGENT_TOKEN
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { ADCPClient } = require('../dist/lib/index.js');
|
|
18
|
+
const { readFileSync } = require('fs');
|
|
19
|
+
const { AsyncWebhookHandler } = require('./adcp-async-handler.js');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Display agent info - just calls library method
|
|
23
|
+
*/
|
|
24
|
+
async function displayAgentInfo(agentConfig, jsonOutput) {
|
|
25
|
+
const client = new ADCPClient(agentConfig);
|
|
26
|
+
const info = await client.getAgentInfo();
|
|
27
|
+
|
|
28
|
+
if (jsonOutput) {
|
|
29
|
+
console.log(JSON.stringify(info, null, 2));
|
|
30
|
+
} else {
|
|
31
|
+
console.log(`\n📋 Agent Information\n`);
|
|
32
|
+
console.log(`Name: ${info.name}`);
|
|
33
|
+
if (info.description) {
|
|
34
|
+
console.log(`Description: ${info.description}`);
|
|
35
|
+
}
|
|
36
|
+
console.log(`Protocol: ${info.protocol.toUpperCase()}`);
|
|
37
|
+
console.log(`URL: ${info.url}`);
|
|
38
|
+
console.log(`\nAvailable Tools (${info.tools.length}):\n`);
|
|
39
|
+
|
|
40
|
+
if (info.tools.length === 0) {
|
|
41
|
+
console.log('No tools found.');
|
|
42
|
+
} else {
|
|
43
|
+
info.tools.forEach((tool, i) => {
|
|
44
|
+
console.log(`${i + 1}. ${tool.name}`);
|
|
45
|
+
if (tool.description) {
|
|
46
|
+
console.log(` ${tool.description}`);
|
|
47
|
+
}
|
|
48
|
+
if (tool.parameters && tool.parameters.length > 0) {
|
|
49
|
+
console.log(` Parameters: ${tool.parameters.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
console.log('');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function printUsage() {
|
|
58
|
+
console.log(`
|
|
59
|
+
AdCP CLI Tool - Direct Agent Communication
|
|
60
|
+
|
|
61
|
+
USAGE:
|
|
62
|
+
adcp <protocol> <agent-url> [tool-name] [payload] [options]
|
|
63
|
+
|
|
64
|
+
ARGUMENTS:
|
|
65
|
+
protocol Protocol to use: 'mcp' or 'a2a'
|
|
66
|
+
agent-url Full URL to the agent endpoint
|
|
67
|
+
tool-name Name of the tool to call (optional - omit to list available tools)
|
|
68
|
+
payload JSON payload for the tool (default: {})
|
|
69
|
+
- Can be inline JSON: '{"brief":"text"}'
|
|
70
|
+
- Can be file path: @payload.json
|
|
71
|
+
- Can be stdin: -
|
|
72
|
+
|
|
73
|
+
OPTIONS:
|
|
74
|
+
--auth TOKEN Authentication token for the agent
|
|
75
|
+
--wait Wait for async/webhook responses (requires ngrok or --local)
|
|
76
|
+
--local Use local webhook without ngrok (for local agents only)
|
|
77
|
+
--timeout MS Webhook timeout in milliseconds (default: 300000 = 5min)
|
|
78
|
+
--help, -h Show this help message
|
|
79
|
+
--json Output raw JSON response (default: pretty print)
|
|
80
|
+
--debug Show debug information
|
|
81
|
+
|
|
82
|
+
EXAMPLES:
|
|
83
|
+
# List available tools
|
|
84
|
+
adcp mcp https://agent.example.com/mcp
|
|
85
|
+
adcp a2a https://creative.adcontextprotocol.org
|
|
86
|
+
|
|
87
|
+
# Simple product discovery
|
|
88
|
+
adcp mcp https://agent.example.com/mcp get_products '{"brief":"coffee brands"}'
|
|
89
|
+
|
|
90
|
+
# With authentication
|
|
91
|
+
adcp a2a https://agent.example.com list_creative_formats '{}' --auth your_token
|
|
92
|
+
|
|
93
|
+
# Wait for async response (requires ngrok)
|
|
94
|
+
adcp mcp https://agent.example.com/mcp create_media_buy @payload.json --auth $TOKEN --wait
|
|
95
|
+
|
|
96
|
+
# Wait for async response from local agent (no ngrok needed)
|
|
97
|
+
adcp mcp http://localhost:3000/mcp create_media_buy @payload.json --wait --local
|
|
98
|
+
|
|
99
|
+
# From file
|
|
100
|
+
adcp mcp https://agent.example.com/mcp create_media_buy @payload.json --auth $TOKEN
|
|
101
|
+
|
|
102
|
+
# From stdin
|
|
103
|
+
echo '{"brief":"travel"}' | adcp mcp https://agent.example.com/mcp get_products -
|
|
104
|
+
|
|
105
|
+
ENVIRONMENT VARIABLES:
|
|
106
|
+
ADCP_AUTH_TOKEN Default authentication token (overridden by --auth)
|
|
107
|
+
ADCP_DEBUG Enable debug mode (set to 'true')
|
|
108
|
+
|
|
109
|
+
EXIT CODES:
|
|
110
|
+
0 Success
|
|
111
|
+
1 General error
|
|
112
|
+
2 Invalid arguments
|
|
113
|
+
3 Agent error
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function main() {
|
|
118
|
+
const args = process.argv.slice(2);
|
|
119
|
+
|
|
120
|
+
// Handle help
|
|
121
|
+
if (args.includes('--help') || args.includes('-h') || args.length === 0) {
|
|
122
|
+
printUsage();
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Parse arguments
|
|
127
|
+
if (args.length < 2) {
|
|
128
|
+
console.error('ERROR: Missing required arguments\n');
|
|
129
|
+
printUsage();
|
|
130
|
+
process.exit(2);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Parse options first
|
|
134
|
+
const authIndex = args.indexOf('--auth');
|
|
135
|
+
const authToken = authIndex !== -1 ? args[authIndex + 1] : process.env.ADCP_AUTH_TOKEN;
|
|
136
|
+
const jsonOutput = args.includes('--json');
|
|
137
|
+
const debug = args.includes('--debug') || process.env.ADCP_DEBUG === 'true';
|
|
138
|
+
const waitForAsync = args.includes('--wait');
|
|
139
|
+
const useLocalWebhook = args.includes('--local');
|
|
140
|
+
const timeoutIndex = args.indexOf('--timeout');
|
|
141
|
+
const timeout = timeoutIndex !== -1 ? parseInt(args[timeoutIndex + 1]) : 300000;
|
|
142
|
+
|
|
143
|
+
// Filter out flag arguments to find positional arguments
|
|
144
|
+
const positionalArgs = args.filter(arg =>
|
|
145
|
+
!arg.startsWith('--') &&
|
|
146
|
+
arg !== authToken && // Don't include the auth token value
|
|
147
|
+
arg !== (timeoutIndex !== -1 ? args[timeoutIndex + 1] : null) // Don't include timeout value
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const protocol = positionalArgs[0];
|
|
151
|
+
const agentUrl = positionalArgs[1];
|
|
152
|
+
const toolName = positionalArgs[2]; // Optional - if not provided, list tools
|
|
153
|
+
let payloadArg = positionalArgs[3] || '{}';
|
|
154
|
+
|
|
155
|
+
// Validate protocol
|
|
156
|
+
if (protocol !== 'mcp' && protocol !== 'a2a') {
|
|
157
|
+
console.error(`ERROR: Invalid protocol '${protocol}'. Must be 'mcp' or 'a2a'\n`);
|
|
158
|
+
printUsage();
|
|
159
|
+
process.exit(2);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Parse payload
|
|
163
|
+
let payload;
|
|
164
|
+
try {
|
|
165
|
+
if (payloadArg === '-') {
|
|
166
|
+
// Read from stdin
|
|
167
|
+
const stdin = readFileSync(0, 'utf-8');
|
|
168
|
+
payload = JSON.parse(stdin);
|
|
169
|
+
} else if (payloadArg.startsWith('@')) {
|
|
170
|
+
// Read from file
|
|
171
|
+
const filePath = payloadArg.substring(1);
|
|
172
|
+
const fileContent = readFileSync(filePath, 'utf-8');
|
|
173
|
+
payload = JSON.parse(fileContent);
|
|
174
|
+
} else {
|
|
175
|
+
// Parse inline JSON
|
|
176
|
+
payload = JSON.parse(payloadArg);
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error(`ERROR: Invalid JSON payload: ${error.message}\n`);
|
|
180
|
+
process.exit(2);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (debug) {
|
|
184
|
+
console.error('DEBUG: Configuration');
|
|
185
|
+
console.error(` Protocol: ${protocol}`);
|
|
186
|
+
console.error(` Agent URL: ${agentUrl}`);
|
|
187
|
+
console.error(` Tool: ${toolName}`);
|
|
188
|
+
console.error(` Auth: ${authToken ? 'provided' : 'none'}`);
|
|
189
|
+
console.error(` Payload: ${JSON.stringify(payload, null, 2)}`);
|
|
190
|
+
console.error('');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Create agent config
|
|
194
|
+
const agentConfig = {
|
|
195
|
+
id: 'cli-agent',
|
|
196
|
+
name: 'CLI Agent',
|
|
197
|
+
agent_uri: agentUrl,
|
|
198
|
+
protocol: protocol,
|
|
199
|
+
...(authToken && { auth_token_env: authToken })
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
// If no tool name provided, display agent info
|
|
204
|
+
if (!toolName) {
|
|
205
|
+
if (debug) {
|
|
206
|
+
console.error('DEBUG: No tool specified, displaying agent info...\n');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await displayAgentInfo(agentConfig, jsonOutput);
|
|
210
|
+
process.exit(0);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Set up webhook handler if --wait flag is used
|
|
214
|
+
let webhookHandler = null;
|
|
215
|
+
let webhookUrl = null;
|
|
216
|
+
|
|
217
|
+
if (waitForAsync) {
|
|
218
|
+
const useNgrok = !useLocalWebhook;
|
|
219
|
+
|
|
220
|
+
// Check if ngrok is available (unless using --local)
|
|
221
|
+
if (useNgrok) {
|
|
222
|
+
const ngrokAvailable = await AsyncWebhookHandler.isNgrokAvailable();
|
|
223
|
+
if (!ngrokAvailable) {
|
|
224
|
+
console.error('\n❌ ERROR: --wait flag requires ngrok to be installed\n');
|
|
225
|
+
console.error('Install ngrok:');
|
|
226
|
+
console.error(' Mac: brew install ngrok');
|
|
227
|
+
console.error(' Windows: choco install ngrok');
|
|
228
|
+
console.error(' Linux: Download from https://ngrok.com/download');
|
|
229
|
+
console.error('\nOr use --local flag for local agents (e.g., http://localhost:3000)\n');
|
|
230
|
+
process.exit(2);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (debug) {
|
|
235
|
+
console.error(`DEBUG: Setting up ${useNgrok ? 'ngrok' : 'local'} webhook handler...\n`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
webhookHandler = new AsyncWebhookHandler({
|
|
239
|
+
timeout: timeout,
|
|
240
|
+
debug: debug
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
webhookUrl = await webhookHandler.start(useNgrok);
|
|
245
|
+
|
|
246
|
+
if (!jsonOutput) {
|
|
247
|
+
console.log(`\n🌐 ${useNgrok ? 'Public webhook' : 'Local webhook'} endpoint ready`);
|
|
248
|
+
console.log(` URL: ${webhookUrl}`);
|
|
249
|
+
console.log(` Timeout: ${timeout / 1000}s`);
|
|
250
|
+
if (useLocalWebhook) {
|
|
251
|
+
console.log(` ⚠️ Local mode: Agent must be accessible at localhost`);
|
|
252
|
+
}
|
|
253
|
+
console.log('');
|
|
254
|
+
}
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('\n❌ ERROR: Failed to start webhook handler\n');
|
|
257
|
+
console.error(error.message);
|
|
258
|
+
if (debug) {
|
|
259
|
+
console.error('\nStack trace:');
|
|
260
|
+
console.error(error.stack);
|
|
261
|
+
}
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Create ADCP client with optional webhook configuration
|
|
267
|
+
const client = new ADCPClient(agentConfig, {
|
|
268
|
+
debug: debug,
|
|
269
|
+
...(webhookUrl && {
|
|
270
|
+
webhookUrlTemplate: webhookUrl,
|
|
271
|
+
webhookSecret: 'cli-webhook-secret'
|
|
272
|
+
})
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (debug) {
|
|
276
|
+
console.error('DEBUG: Executing task...\n');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Execute the task
|
|
280
|
+
const result = await client.executeTask(toolName, payload);
|
|
281
|
+
|
|
282
|
+
// If waiting for async response, handle webhook
|
|
283
|
+
if (waitForAsync && webhookHandler) {
|
|
284
|
+
if (result.status === 'submitted' || result.status === 'working') {
|
|
285
|
+
if (!jsonOutput) {
|
|
286
|
+
console.log('📤 Task submitted, waiting for async response...');
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const webhookResponse = await webhookHandler.waitForResponse();
|
|
291
|
+
|
|
292
|
+
// Clean up webhook handler
|
|
293
|
+
await webhookHandler.cleanup();
|
|
294
|
+
|
|
295
|
+
// Output webhook response
|
|
296
|
+
if (jsonOutput) {
|
|
297
|
+
console.log(JSON.stringify(webhookResponse.result || webhookResponse, null, 2));
|
|
298
|
+
} else {
|
|
299
|
+
console.log('\n✅ ASYNC RESPONSE RECEIVED\n');
|
|
300
|
+
console.log('Response:');
|
|
301
|
+
console.log(JSON.stringify(webhookResponse.result || webhookResponse, null, 2));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
process.exit(0);
|
|
305
|
+
} catch (error) {
|
|
306
|
+
await webhookHandler.cleanup();
|
|
307
|
+
console.error('\n❌ WEBHOOK TIMEOUT\n');
|
|
308
|
+
console.error(error.message);
|
|
309
|
+
process.exit(3);
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
// Task completed synchronously, clean up webhook
|
|
313
|
+
await webhookHandler.cleanup();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Handle result
|
|
318
|
+
if (result.success) {
|
|
319
|
+
if (jsonOutput) {
|
|
320
|
+
// Raw JSON output
|
|
321
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
322
|
+
} else {
|
|
323
|
+
// Pretty output
|
|
324
|
+
console.log('\n✅ SUCCESS\n');
|
|
325
|
+
console.log('Response:');
|
|
326
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
327
|
+
console.log('');
|
|
328
|
+
console.log(`Response Time: ${result.metadata.responseTimeMs}ms`);
|
|
329
|
+
console.log(`Task ID: ${result.metadata.taskId}`);
|
|
330
|
+
}
|
|
331
|
+
process.exit(0);
|
|
332
|
+
} else {
|
|
333
|
+
console.error('\n❌ TASK FAILED\n');
|
|
334
|
+
console.error(`Error: ${result.error || 'Unknown error'}`);
|
|
335
|
+
if (result.metadata?.clarificationRounds) {
|
|
336
|
+
console.error(`Clarifications: ${result.metadata.clarificationRounds}`);
|
|
337
|
+
}
|
|
338
|
+
if (debug && result.metadata) {
|
|
339
|
+
console.error('\nMetadata:');
|
|
340
|
+
console.error(JSON.stringify(result.metadata, null, 2));
|
|
341
|
+
}
|
|
342
|
+
process.exit(3);
|
|
343
|
+
}
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error('\n❌ ERROR\n');
|
|
346
|
+
console.error(error.message);
|
|
347
|
+
if (debug) {
|
|
348
|
+
console.error('\nStack trace:');
|
|
349
|
+
console.error(error.stack);
|
|
350
|
+
}
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
main().catch(error => {
|
|
356
|
+
console.error('FATAL ERROR:', error.message);
|
|
357
|
+
process.exit(1);
|
|
358
|
+
});
|
|
@@ -52,7 +52,32 @@ export declare class ADCPClient {
|
|
|
52
52
|
private config;
|
|
53
53
|
private executor;
|
|
54
54
|
private asyncHandler?;
|
|
55
|
+
private normalizedAgent;
|
|
56
|
+
private discoveredEndpoint?;
|
|
55
57
|
constructor(agent: AgentConfig, config?: ADCPClientConfig);
|
|
58
|
+
/**
|
|
59
|
+
* Ensure MCP endpoint is discovered (lazy initialization)
|
|
60
|
+
*
|
|
61
|
+
* If the agent needs discovery, perform it now and cache the result.
|
|
62
|
+
* Returns the agent config with the discovered endpoint.
|
|
63
|
+
*/
|
|
64
|
+
private ensureEndpointDiscovered;
|
|
65
|
+
/**
|
|
66
|
+
* Discover MCP endpoint by testing the provided path, then trying /mcp
|
|
67
|
+
*
|
|
68
|
+
* Strategy: Test what the user gave us first. If no MCP server responds,
|
|
69
|
+
* try adding /mcp to the path. That's it.
|
|
70
|
+
*
|
|
71
|
+
* Note: This is async and called lazily on first agent interaction
|
|
72
|
+
*/
|
|
73
|
+
private discoverMCPEndpoint;
|
|
74
|
+
/**
|
|
75
|
+
* Normalize agent config - mark all MCP agents for discovery
|
|
76
|
+
*
|
|
77
|
+
* We always test the endpoint they give us, and if it doesn't work,
|
|
78
|
+
* we try adding /mcp. Simple.
|
|
79
|
+
*/
|
|
80
|
+
private normalizeAgentConfig;
|
|
56
81
|
/**
|
|
57
82
|
* Handle webhook from agent (async task completion)
|
|
58
83
|
*
|
|
@@ -67,8 +92,7 @@ export declare class ADCPClient {
|
|
|
67
92
|
* const signature = req.headers['x-adcp-signature'];
|
|
68
93
|
* const timestamp = req.headers['x-adcp-timestamp'];
|
|
69
94
|
*
|
|
70
|
-
* try
|
|
71
|
-
* const handled = await client.handleWebhook(req.body, signature, timestamp);
|
|
95
|
+
* try * const handled = await client.handleWebhook(req.body, signature, timestamp);
|
|
72
96
|
* res.status(200).json({ received: handled });
|
|
73
97
|
* } catch (error) {
|
|
74
98
|
* res.status(401).json({ error: error.message });
|
|
@@ -402,6 +426,38 @@ export declare class ADCPClient {
|
|
|
402
426
|
* Unregister webhook notifications
|
|
403
427
|
*/
|
|
404
428
|
unregisterWebhook(): Promise<void>;
|
|
429
|
+
/**
|
|
430
|
+
* Get comprehensive agent information including name, description, and available tools/skills
|
|
431
|
+
*
|
|
432
|
+
* Works with both MCP (tools) and A2A (skills) protocols to discover what the agent can do.
|
|
433
|
+
*
|
|
434
|
+
* @returns Promise resolving to agent information including tools
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```typescript
|
|
438
|
+
* const client = new ADCPClient(agentConfig);
|
|
439
|
+
* const info = await client.getAgentInfo();
|
|
440
|
+
*
|
|
441
|
+
* console.log(`${info.name}: ${info.description}`);
|
|
442
|
+
* console.log(`Supports ${info.tools.length} tools`);
|
|
443
|
+
*
|
|
444
|
+
* info.tools.forEach(tool => {
|
|
445
|
+
* console.log(` - ${tool.name}: ${tool.description}`);
|
|
446
|
+
* });
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
getAgentInfo(): Promise<{
|
|
450
|
+
name: string;
|
|
451
|
+
description?: string;
|
|
452
|
+
protocol: 'mcp' | 'a2a';
|
|
453
|
+
url: string;
|
|
454
|
+
tools: Array<{
|
|
455
|
+
name: string;
|
|
456
|
+
description?: string;
|
|
457
|
+
inputSchema?: any;
|
|
458
|
+
parameters?: string[];
|
|
459
|
+
}>;
|
|
460
|
+
}>;
|
|
405
461
|
/**
|
|
406
462
|
* Query a creative agent to discover available creative formats
|
|
407
463
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ADCPClient.d.ts","sourceRoot":"","sources":["../../../src/lib/core/ADCPClient.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,kCAAkC,EAClC,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,MAAM,EACP,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAInF;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,qEAAqE;IACrE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,wFAAwF;IACxF,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;OAYG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,UAAU;
|
|
1
|
+
{"version":3,"file":"ADCPClient.d.ts","sourceRoot":"","sources":["../../../src/lib/core/ADCPClient.ts"],"names":[],"mappings":"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"}
|