@adcp/client 3.8.1 ā 3.9.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/bin/adcp.js +527 -11
- package/dist/lib/agents/index.generated.d.ts +9 -1
- package/dist/lib/agents/index.generated.d.ts.map +1 -1
- package/dist/lib/agents/index.generated.js +12 -0
- package/dist/lib/agents/index.generated.js.map +1 -1
- package/dist/lib/auth/index.d.ts +1 -0
- package/dist/lib/auth/index.d.ts.map +1 -1
- package/dist/lib/auth/index.js +16 -0
- package/dist/lib/auth/index.js.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.d.ts +61 -0
- package/dist/lib/auth/oauth/CLIFlowHandler.d.ts.map +1 -0
- package/dist/lib/auth/oauth/CLIFlowHandler.js +287 -0
- package/dist/lib/auth/oauth/CLIFlowHandler.js.map +1 -0
- package/dist/lib/auth/oauth/MCPOAuthProvider.d.ts +126 -0
- package/dist/lib/auth/oauth/MCPOAuthProvider.d.ts.map +1 -0
- package/dist/lib/auth/oauth/MCPOAuthProvider.js +236 -0
- package/dist/lib/auth/oauth/MCPOAuthProvider.js.map +1 -0
- package/dist/lib/auth/oauth/index.d.ts +104 -0
- package/dist/lib/auth/oauth/index.d.ts.map +1 -0
- package/dist/lib/auth/oauth/index.js +168 -0
- package/dist/lib/auth/oauth/index.js.map +1 -0
- package/dist/lib/auth/oauth/types.d.ts +114 -0
- package/dist/lib/auth/oauth/types.d.ts.map +1 -0
- package/dist/lib/auth/oauth/types.js +104 -0
- package/dist/lib/auth/oauth/types.js.map +1 -0
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +21 -9
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +11 -3
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/protocols/index.d.ts +2 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +4 -1
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/mcp.d.ts +80 -0
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +158 -0
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/testing/agent-tester.d.ts +1 -1
- package/dist/lib/testing/agent-tester.d.ts.map +1 -1
- package/dist/lib/testing/agent-tester.js +39 -1
- package/dist/lib/testing/agent-tester.js.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js +11 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.d.ts +27 -0
- package/dist/lib/testing/scenarios/capabilities.d.ts.map +1 -0
- package/dist/lib/testing/scenarios/capabilities.js +250 -0
- package/dist/lib/testing/scenarios/capabilities.js.map +1 -0
- package/dist/lib/testing/scenarios/governance.d.ts +35 -0
- package/dist/lib/testing/scenarios/governance.d.ts.map +1 -0
- package/dist/lib/testing/scenarios/governance.js +428 -0
- package/dist/lib/testing/scenarios/governance.js.map +1 -0
- package/dist/lib/testing/scenarios/index.d.ts +3 -0
- package/dist/lib/testing/scenarios/index.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/index.js +15 -1
- package/dist/lib/testing/scenarios/index.js.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.d.ts +34 -0
- package/dist/lib/testing/scenarios/sponsored-intelligence.d.ts.map +1 -0
- package/dist/lib/testing/scenarios/sponsored-intelligence.js +318 -0
- package/dist/lib/testing/scenarios/sponsored-intelligence.js.map +1 -0
- package/dist/lib/testing/types.d.ts +9 -1
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/types/adcp.d.ts +47 -1
- package/dist/lib/types/adcp.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +393 -164
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +2 -2
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.d.ts +1275 -845
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +300 -198
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +461 -167
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/version.d.ts +5 -5
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +5 -5
- package/dist/lib/version.js.map +1 -1
- package/package.json +2 -2
package/bin/adcp.js
CHANGED
|
@@ -17,7 +17,21 @@
|
|
|
17
17
|
const { AdCPClient, detectProtocol, usesDeprecatedAssetsField } = require('../dist/lib/index.js');
|
|
18
18
|
const { readFileSync } = require('fs');
|
|
19
19
|
const { AsyncWebhookHandler } = require('./adcp-async-handler.js');
|
|
20
|
-
const {
|
|
20
|
+
const {
|
|
21
|
+
getAgent,
|
|
22
|
+
listAgents,
|
|
23
|
+
isAlias,
|
|
24
|
+
interactiveSetup,
|
|
25
|
+
removeAgent,
|
|
26
|
+
getConfigPath,
|
|
27
|
+
saveAgent,
|
|
28
|
+
} = require('./adcp-config.js');
|
|
29
|
+
const {
|
|
30
|
+
createCLIOAuthProvider,
|
|
31
|
+
hasValidOAuthTokens,
|
|
32
|
+
clearOAuthTokens,
|
|
33
|
+
getEffectiveAuthToken,
|
|
34
|
+
} = require('../dist/lib/auth/oauth/index.js');
|
|
21
35
|
|
|
22
36
|
// Test scenarios available
|
|
23
37
|
const TEST_SCENARIOS = [
|
|
@@ -35,6 +49,12 @@ const TEST_SCENARIOS = [
|
|
|
35
49
|
'temporal_validation',
|
|
36
50
|
'behavior_analysis',
|
|
37
51
|
'response_consistency',
|
|
52
|
+
// v3 protocol scenarios
|
|
53
|
+
'capability_discovery',
|
|
54
|
+
'governance_property_lists',
|
|
55
|
+
'governance_content_standards',
|
|
56
|
+
'si_session_lifecycle',
|
|
57
|
+
'si_availability',
|
|
38
58
|
];
|
|
39
59
|
|
|
40
60
|
// Built-in test agent aliases (shared between main CLI and test command)
|
|
@@ -221,6 +241,12 @@ async function handleTestCommand(args) {
|
|
|
221
241
|
temporal_validation: 'Test date/time ordering and format validation',
|
|
222
242
|
behavior_analysis: 'Analyze agent behavior: auth, brief relevance, filtering',
|
|
223
243
|
response_consistency: 'Check for schema errors, pagination bugs, data mismatches',
|
|
244
|
+
// v3 protocol scenarios
|
|
245
|
+
capability_discovery: 'Test get_adcp_capabilities and verify v3 protocol support',
|
|
246
|
+
governance_property_lists: 'Test property list CRUD (create, get, update, delete)',
|
|
247
|
+
governance_content_standards: 'Test content standards listing and calibration',
|
|
248
|
+
si_session_lifecycle: 'Test full SI session: initiate ā messages ā terminate',
|
|
249
|
+
si_availability: 'Quick check for SI offering availability',
|
|
224
250
|
};
|
|
225
251
|
|
|
226
252
|
for (const scenario of TEST_SCENARIOS) {
|
|
@@ -412,6 +438,8 @@ ARGUMENTS:
|
|
|
412
438
|
OPTIONS:
|
|
413
439
|
--protocol PROTO Force protocol: 'mcp' or 'a2a' (default: auto-detect)
|
|
414
440
|
--auth TOKEN Authentication token for the agent
|
|
441
|
+
--oauth Use OAuth for authentication (MCP only, opens browser)
|
|
442
|
+
--clear-oauth Clear saved OAuth tokens for an agent
|
|
415
443
|
--wait Wait for async/webhook responses (requires ngrok or --local)
|
|
416
444
|
--local Use local webhook without ngrok (for local agents only)
|
|
417
445
|
--timeout MS Webhook timeout in milliseconds (default: 300000 = 5min)
|
|
@@ -427,9 +455,11 @@ BUILT-IN TEST AGENTS:
|
|
|
427
455
|
creative Official AdCP creative agent (MCP only)
|
|
428
456
|
|
|
429
457
|
AGENT MANAGEMENT:
|
|
430
|
-
--save-auth <alias> [url] [protocol] [--auth token | --no-auth]
|
|
458
|
+
--save-auth <alias> [url] [protocol] [--auth token | --no-auth | --oauth]
|
|
431
459
|
Save agent configuration with an alias name
|
|
432
|
-
|
|
460
|
+
--auth TOKEN: Save with static auth token
|
|
461
|
+
--no-auth: Save without authentication
|
|
462
|
+
--oauth: Authenticate via OAuth and save tokens (MCP only)
|
|
433
463
|
--list-agents List all saved agents
|
|
434
464
|
--remove-agent <alias> Remove saved agent configuration
|
|
435
465
|
--show-config Show config file location
|
|
@@ -459,6 +489,9 @@ EXAMPLES:
|
|
|
459
489
|
# Non-interactive: save without auth
|
|
460
490
|
adcp --save-auth myagent https://test-agent.adcontextprotocol.org --no-auth
|
|
461
491
|
|
|
492
|
+
# Save with OAuth (opens browser, saves tokens)
|
|
493
|
+
adcp --save-auth myagent https://oauth-server.com/mcp --oauth
|
|
494
|
+
|
|
462
495
|
# Interactive setup (prompts for URL, protocol, and auth)
|
|
463
496
|
adcp --save-auth myagent
|
|
464
497
|
|
|
@@ -479,6 +512,17 @@ EXAMPLES:
|
|
|
479
512
|
# Override saved auth token
|
|
480
513
|
adcp myagent get_products '{"brief":"..."}' --auth different-token
|
|
481
514
|
|
|
515
|
+
# OAuth authentication (opens browser for login)
|
|
516
|
+
adcp https://oauth-agent.example.com/mcp --oauth
|
|
517
|
+
adcp myagent get_products '{"brief":"..."}' --oauth # Saves tokens to alias
|
|
518
|
+
|
|
519
|
+
# Auto-detect OAuth (automatically starts OAuth if server requires it)
|
|
520
|
+
adcp https://oauth-server.com/mcp get_products '{"brief":"..."}' # Auto-detects!
|
|
521
|
+
|
|
522
|
+
# Clear OAuth tokens and re-authenticate
|
|
523
|
+
adcp myagent --clear-oauth
|
|
524
|
+
adcp myagent --oauth
|
|
525
|
+
|
|
482
526
|
# Wait for async response (requires ngrok)
|
|
483
527
|
adcp myagent create_media_buy @payload.json --wait
|
|
484
528
|
|
|
@@ -526,12 +570,13 @@ async function main() {
|
|
|
526
570
|
// Parse flags first
|
|
527
571
|
const authFlagIndex = args.indexOf('--auth');
|
|
528
572
|
const noAuthFlag = args.includes('--no-auth');
|
|
573
|
+
const oauthFlag = args.includes('--oauth');
|
|
529
574
|
const providedAuthToken = authFlagIndex !== -1 ? args[authFlagIndex + 1] : null;
|
|
530
575
|
|
|
531
576
|
// Filter out flags to get positional args
|
|
532
577
|
const saveAuthPositional = args
|
|
533
578
|
.slice(1)
|
|
534
|
-
.filter(arg => arg !== '--auth' && arg !== '--no-auth' && arg !== providedAuthToken);
|
|
579
|
+
.filter(arg => arg !== '--auth' && arg !== '--no-auth' && arg !== '--oauth' && arg !== providedAuthToken);
|
|
535
580
|
|
|
536
581
|
let alias = saveAuthPositional[0];
|
|
537
582
|
let url = saveAuthPositional[1] || null;
|
|
@@ -539,8 +584,9 @@ async function main() {
|
|
|
539
584
|
|
|
540
585
|
if (!alias) {
|
|
541
586
|
console.error('ERROR: --save-auth requires an alias\n');
|
|
542
|
-
console.error('Usage: adcp --save-auth <alias> [url] [protocol] [--auth token | --no-auth]\n');
|
|
587
|
+
console.error('Usage: adcp --save-auth <alias> [url] [protocol] [--auth token | --no-auth | --oauth]\n');
|
|
543
588
|
console.error('Example: adcp --save-auth myagent https://agent.example.com --auth your_token\n');
|
|
589
|
+
console.error(' adcp --save-auth myagent https://oauth-server.com/mcp --oauth\n');
|
|
544
590
|
process.exit(2);
|
|
545
591
|
}
|
|
546
592
|
|
|
@@ -554,12 +600,98 @@ async function main() {
|
|
|
554
600
|
process.exit(2);
|
|
555
601
|
}
|
|
556
602
|
|
|
557
|
-
// Validate flags
|
|
558
|
-
|
|
559
|
-
|
|
603
|
+
// Validate flags - only one auth method allowed
|
|
604
|
+
const authMethods = [providedAuthToken !== null, noAuthFlag, oauthFlag].filter(Boolean).length;
|
|
605
|
+
if (authMethods > 1) {
|
|
606
|
+
console.error('ERROR: Cannot use multiple auth methods (--auth, --no-auth, --oauth)\n');
|
|
560
607
|
process.exit(2);
|
|
561
608
|
}
|
|
562
609
|
|
|
610
|
+
// Handle OAuth save flow
|
|
611
|
+
if (oauthFlag) {
|
|
612
|
+
if (!url) {
|
|
613
|
+
console.error('ERROR: --oauth requires a URL\n');
|
|
614
|
+
console.error('Usage: adcp --save-auth <alias> <url> --oauth\n');
|
|
615
|
+
process.exit(2);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// OAuth is only for MCP
|
|
619
|
+
const detectedProtocol = protocol || (url.includes('/mcp') ? 'mcp' : null);
|
|
620
|
+
if (detectedProtocol && detectedProtocol !== 'mcp') {
|
|
621
|
+
console.error('ERROR: OAuth is only supported for MCP protocol\n');
|
|
622
|
+
process.exit(2);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
console.log(`\nš Setting up OAuth for '${alias}'...`);
|
|
626
|
+
console.log(`URL: ${url}\n`);
|
|
627
|
+
|
|
628
|
+
// Create a temporary agent config for OAuth
|
|
629
|
+
const tempAgent = {
|
|
630
|
+
id: alias,
|
|
631
|
+
name: alias,
|
|
632
|
+
agent_uri: url,
|
|
633
|
+
protocol: 'mcp',
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
const { Client: MCPClient } = require('@modelcontextprotocol/sdk/client/index.js');
|
|
637
|
+
const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
638
|
+
const { UnauthorizedError } = require('@modelcontextprotocol/sdk/client/auth.js');
|
|
639
|
+
|
|
640
|
+
const oauthProvider = createCLIOAuthProvider(tempAgent);
|
|
641
|
+
const mcpClient = new MCPClient({ name: 'adcp-cli', version: '1.0.0' });
|
|
642
|
+
const createTransport = () => new StreamableHTTPClientTransport(new URL(url), { authProvider: oauthProvider });
|
|
643
|
+
|
|
644
|
+
let transport = createTransport();
|
|
645
|
+
|
|
646
|
+
try {
|
|
647
|
+
console.log('Connecting to verify OAuth support...');
|
|
648
|
+
await mcpClient.connect(transport);
|
|
649
|
+
// If we connected without OAuth, the server doesn't require it
|
|
650
|
+
console.log('\nā ļø Server connected without requiring OAuth.');
|
|
651
|
+
console.log('Saving agent without OAuth tokens.\n');
|
|
652
|
+
await oauthProvider.cleanup();
|
|
653
|
+
await mcpClient.close();
|
|
654
|
+
saveAgent(alias, { url, protocol: 'mcp' });
|
|
655
|
+
console.log(`ā
Agent '${alias}' saved.`);
|
|
656
|
+
console.log(`Use: adcp ${alias} <tool> <payload>\n`);
|
|
657
|
+
} catch (error) {
|
|
658
|
+
if (error instanceof UnauthorizedError || error.name === 'UnauthorizedError') {
|
|
659
|
+
console.log('OAuth authorization required.');
|
|
660
|
+
console.log('Opening browser for authentication...\n');
|
|
661
|
+
|
|
662
|
+
try {
|
|
663
|
+
const code = await oauthProvider.waitForCallback();
|
|
664
|
+
console.log('Authorization received!');
|
|
665
|
+
await transport.finishAuth(code);
|
|
666
|
+
|
|
667
|
+
// Save agent with OAuth tokens
|
|
668
|
+
const agentConfig = {
|
|
669
|
+
url,
|
|
670
|
+
protocol: 'mcp',
|
|
671
|
+
oauth_tokens: tempAgent.oauth_tokens,
|
|
672
|
+
oauth_client: tempAgent.oauth_client,
|
|
673
|
+
};
|
|
674
|
+
saveAgent(alias, agentConfig);
|
|
675
|
+
|
|
676
|
+
console.log(`\nā
Agent '${alias}' saved with OAuth tokens.`);
|
|
677
|
+
console.log(`Use: adcp ${alias} <tool> <payload>\n`);
|
|
678
|
+
|
|
679
|
+
await oauthProvider.cleanup();
|
|
680
|
+
await mcpClient.close();
|
|
681
|
+
} catch (authError) {
|
|
682
|
+
await oauthProvider.cleanup();
|
|
683
|
+
console.error('\nā OAuth failed:', authError.message);
|
|
684
|
+
process.exit(1);
|
|
685
|
+
}
|
|
686
|
+
} else {
|
|
687
|
+
await oauthProvider.cleanup();
|
|
688
|
+
console.error('\nā Connection failed:', error.message);
|
|
689
|
+
process.exit(1);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
process.exit(0);
|
|
693
|
+
}
|
|
694
|
+
|
|
563
695
|
// Determine mode:
|
|
564
696
|
// - If URL provided AND (--auth or --no-auth): fully non-interactive
|
|
565
697
|
// - Otherwise: interactive (prompts for missing values)
|
|
@@ -589,7 +721,11 @@ async function main() {
|
|
|
589
721
|
console.log(` Protocol: ${agent.protocol}`);
|
|
590
722
|
}
|
|
591
723
|
if (agent.auth_token) {
|
|
592
|
-
console.log(` Auth: configured`);
|
|
724
|
+
console.log(` Auth: token configured`);
|
|
725
|
+
}
|
|
726
|
+
if (agent.oauth_tokens) {
|
|
727
|
+
const hasValid = hasValidOAuthTokens(agent);
|
|
728
|
+
console.log(` OAuth: ${hasValid ? 'valid tokens' : 'expired (use --oauth to refresh)'}`);
|
|
593
729
|
}
|
|
594
730
|
console.log('');
|
|
595
731
|
});
|
|
@@ -619,6 +755,39 @@ async function main() {
|
|
|
619
755
|
process.exit(0);
|
|
620
756
|
}
|
|
621
757
|
|
|
758
|
+
// Handle --clear-oauth command
|
|
759
|
+
if (args.includes('--clear-oauth')) {
|
|
760
|
+
const positionalArgs = args.filter(arg => !arg.startsWith('--'));
|
|
761
|
+
const alias = positionalArgs[0];
|
|
762
|
+
|
|
763
|
+
if (!alias) {
|
|
764
|
+
console.error('ERROR: --clear-oauth requires an agent alias\n');
|
|
765
|
+
console.error('Usage: adcp <alias> --clear-oauth\n');
|
|
766
|
+
process.exit(2);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (!isAlias(alias)) {
|
|
770
|
+
console.error(`ERROR: '${alias}' is not a saved agent alias\n`);
|
|
771
|
+
process.exit(2);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
const agentConfig = getAgent(alias);
|
|
775
|
+
if (!agentConfig.oauth_tokens) {
|
|
776
|
+
console.log(`\nAgent '${alias}' has no OAuth tokens to clear.\n`);
|
|
777
|
+
process.exit(0);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Clear OAuth tokens from agent config
|
|
781
|
+
delete agentConfig.oauth_tokens;
|
|
782
|
+
delete agentConfig.oauth_client;
|
|
783
|
+
delete agentConfig.oauth_code_verifier;
|
|
784
|
+
saveAgent(alias, agentConfig);
|
|
785
|
+
|
|
786
|
+
console.log(`\nā
Cleared OAuth tokens for '${alias}'`);
|
|
787
|
+
console.log('Use --oauth to re-authenticate.\n');
|
|
788
|
+
process.exit(0);
|
|
789
|
+
}
|
|
790
|
+
|
|
622
791
|
// Handle test command (handleTestCommand calls process.exit internally)
|
|
623
792
|
if (args[0] === 'test') {
|
|
624
793
|
await handleTestCommand(args.slice(1));
|
|
@@ -643,6 +812,8 @@ async function main() {
|
|
|
643
812
|
const useLocalWebhook = args.includes('--local');
|
|
644
813
|
const timeoutIndex = args.indexOf('--timeout');
|
|
645
814
|
const timeout = timeoutIndex !== -1 ? parseInt(args[timeoutIndex + 1]) : 300000;
|
|
815
|
+
const useOAuth = args.includes('--oauth');
|
|
816
|
+
const clearOAuth = args.includes('--clear-oauth');
|
|
646
817
|
|
|
647
818
|
// Validate protocol flag if provided
|
|
648
819
|
if (protocolFlag && protocolFlag !== 'mcp' && protocolFlag !== 'a2a') {
|
|
@@ -778,18 +949,46 @@ async function main() {
|
|
|
778
949
|
console.error(` Protocol: ${protocol}`);
|
|
779
950
|
console.error(` Agent URL: ${agentUrl}`);
|
|
780
951
|
console.error(` Tool: ${toolName || '(list tools)'}`);
|
|
781
|
-
console.error(` Auth: ${authToken ? 'provided' : 'none'}`);
|
|
952
|
+
console.error(` Auth: ${authToken ? 'provided' : useOAuth ? 'oauth' : 'none'}`);
|
|
782
953
|
console.error(` Payload: ${JSON.stringify(payload, null, 2)}`);
|
|
783
954
|
console.error('');
|
|
784
955
|
}
|
|
785
956
|
|
|
957
|
+
// Check OAuth requirements
|
|
958
|
+
if (useOAuth && protocol !== 'mcp') {
|
|
959
|
+
console.error('\nā ERROR: OAuth is only supported for MCP protocol\n');
|
|
960
|
+
console.error('Use --auth TOKEN for A2A protocol authentication.\n');
|
|
961
|
+
process.exit(2);
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Build agent config
|
|
965
|
+
// If using OAuth with a saved alias, we need to load existing OAuth tokens
|
|
966
|
+
let agentOAuthTokens = null;
|
|
967
|
+
let agentOAuthClient = null;
|
|
968
|
+
let agentAlias = null;
|
|
969
|
+
|
|
970
|
+
if (useOAuth && savedAgent && isAlias(firstArg)) {
|
|
971
|
+
agentAlias = firstArg;
|
|
972
|
+
// Reload the full saved config to get OAuth tokens
|
|
973
|
+
const fullSavedConfig = getAgent(firstArg);
|
|
974
|
+
if (fullSavedConfig.oauth_tokens) {
|
|
975
|
+
agentOAuthTokens = fullSavedConfig.oauth_tokens;
|
|
976
|
+
agentOAuthClient = fullSavedConfig.oauth_client;
|
|
977
|
+
if (!jsonOutput && hasValidOAuthTokens({ oauth_tokens: agentOAuthTokens })) {
|
|
978
|
+
console.log('Using saved OAuth tokens...\n');
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
786
983
|
// Create agent config
|
|
787
984
|
const agentConfig = {
|
|
788
985
|
id: 'cli-agent',
|
|
789
986
|
name: 'CLI Agent',
|
|
790
987
|
agent_uri: agentUrl,
|
|
791
988
|
protocol: protocol,
|
|
792
|
-
...(authToken && { auth_token: authToken, requiresAuth: true }),
|
|
989
|
+
...(authToken && !useOAuth && { auth_token: authToken, requiresAuth: true }),
|
|
990
|
+
...(agentOAuthTokens && { oauth_tokens: agentOAuthTokens }),
|
|
991
|
+
...(agentOAuthClient && { oauth_client: agentOAuthClient }),
|
|
793
992
|
};
|
|
794
993
|
|
|
795
994
|
try {
|
|
@@ -799,6 +998,76 @@ async function main() {
|
|
|
799
998
|
console.error('DEBUG: No tool specified, displaying agent info...\n');
|
|
800
999
|
}
|
|
801
1000
|
|
|
1001
|
+
// For OAuth without a tool, just authenticate and list tools
|
|
1002
|
+
if (useOAuth && protocol === 'mcp') {
|
|
1003
|
+
const { Client: MCPClient } = require('@modelcontextprotocol/sdk/client/index.js');
|
|
1004
|
+
const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
1005
|
+
const { UnauthorizedError } = require('@modelcontextprotocol/sdk/client/auth.js');
|
|
1006
|
+
|
|
1007
|
+
const oauthProvider = createCLIOAuthProvider(agentConfig, { quiet: jsonOutput });
|
|
1008
|
+
const mcpClient = new MCPClient({ name: 'adcp-cli', version: '1.0.0' });
|
|
1009
|
+
const createTransport = () =>
|
|
1010
|
+
new StreamableHTTPClientTransport(new URL(agentUrl), { authProvider: oauthProvider });
|
|
1011
|
+
|
|
1012
|
+
let transport = createTransport();
|
|
1013
|
+
|
|
1014
|
+
try {
|
|
1015
|
+
if (!jsonOutput) {
|
|
1016
|
+
console.log('Connecting to MCP agent...');
|
|
1017
|
+
}
|
|
1018
|
+
await mcpClient.connect(transport);
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
if (error instanceof UnauthorizedError || error.name === 'UnauthorizedError') {
|
|
1021
|
+
if (!jsonOutput) {
|
|
1022
|
+
console.log('\nOAuth authorization required.');
|
|
1023
|
+
console.log('Opening browser for authentication...\n');
|
|
1024
|
+
}
|
|
1025
|
+
const code = await oauthProvider.waitForCallback();
|
|
1026
|
+
await transport.finishAuth(code);
|
|
1027
|
+
if (agentAlias && agentConfig.oauth_tokens) {
|
|
1028
|
+
const savedConfig = getAgent(agentAlias);
|
|
1029
|
+
savedConfig.oauth_tokens = agentConfig.oauth_tokens;
|
|
1030
|
+
savedConfig.oauth_client = agentConfig.oauth_client;
|
|
1031
|
+
saveAgent(agentAlias, savedConfig);
|
|
1032
|
+
if (!jsonOutput) {
|
|
1033
|
+
console.log(`OAuth tokens saved to '${agentAlias}'.\n`);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
transport = createTransport();
|
|
1037
|
+
await mcpClient.connect(transport);
|
|
1038
|
+
} else {
|
|
1039
|
+
await oauthProvider.cleanup();
|
|
1040
|
+
throw error;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (!jsonOutput) {
|
|
1045
|
+
console.log('Connected!\n');
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// List tools
|
|
1049
|
+
const toolsResult = await mcpClient.listTools();
|
|
1050
|
+
await oauthProvider.cleanup();
|
|
1051
|
+
await mcpClient.close();
|
|
1052
|
+
|
|
1053
|
+
if (jsonOutput) {
|
|
1054
|
+
console.log(JSON.stringify({ tools: toolsResult.tools, protocol: 'mcp', oauth: true }, null, 2));
|
|
1055
|
+
} else {
|
|
1056
|
+
console.log(`\nš Agent Information (OAuth)\n`);
|
|
1057
|
+
console.log(`Protocol: MCP`);
|
|
1058
|
+
console.log(`URL: ${agentUrl}`);
|
|
1059
|
+
console.log(`\nAvailable Tools (${toolsResult.tools.length}):\n`);
|
|
1060
|
+
toolsResult.tools.forEach((tool, i) => {
|
|
1061
|
+
console.log(`${i + 1}. ${tool.name}`);
|
|
1062
|
+
if (tool.description) {
|
|
1063
|
+
console.log(` ${tool.description}`);
|
|
1064
|
+
}
|
|
1065
|
+
console.log('');
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
process.exit(0);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
802
1071
|
await displayAgentInfo(agentConfig, jsonOutput);
|
|
803
1072
|
process.exit(0);
|
|
804
1073
|
}
|
|
@@ -856,6 +1125,138 @@ async function main() {
|
|
|
856
1125
|
}
|
|
857
1126
|
}
|
|
858
1127
|
|
|
1128
|
+
// Handle OAuth flow for MCP if --oauth is specified
|
|
1129
|
+
if (useOAuth && protocol === 'mcp') {
|
|
1130
|
+
const { Client: MCPClient } = require('@modelcontextprotocol/sdk/client/index.js');
|
|
1131
|
+
const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
1132
|
+
const { UnauthorizedError } = require('@modelcontextprotocol/sdk/client/auth.js');
|
|
1133
|
+
|
|
1134
|
+
// Create OAuth provider
|
|
1135
|
+
const oauthProvider = createCLIOAuthProvider(agentConfig, {
|
|
1136
|
+
quiet: jsonOutput,
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
// Create MCP client
|
|
1140
|
+
const mcpClient = new MCPClient({
|
|
1141
|
+
name: 'adcp-cli',
|
|
1142
|
+
version: '1.0.0',
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
const createTransport = () =>
|
|
1146
|
+
new StreamableHTTPClientTransport(new URL(agentUrl), {
|
|
1147
|
+
authProvider: oauthProvider,
|
|
1148
|
+
});
|
|
1149
|
+
|
|
1150
|
+
let transport = createTransport();
|
|
1151
|
+
let needsOAuth = !hasValidOAuthTokens(agentConfig);
|
|
1152
|
+
|
|
1153
|
+
try {
|
|
1154
|
+
if (!jsonOutput) {
|
|
1155
|
+
console.log('Connecting to MCP agent...');
|
|
1156
|
+
}
|
|
1157
|
+
await mcpClient.connect(transport);
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
if (error instanceof UnauthorizedError || error.name === 'UnauthorizedError') {
|
|
1160
|
+
needsOAuth = true;
|
|
1161
|
+
if (!jsonOutput) {
|
|
1162
|
+
console.log('\nOAuth authorization required.');
|
|
1163
|
+
console.log('Opening browser for authentication...\n');
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
try {
|
|
1167
|
+
// Wait for user to complete OAuth in browser
|
|
1168
|
+
const code = await oauthProvider.waitForCallback();
|
|
1169
|
+
if (!jsonOutput) {
|
|
1170
|
+
console.log('Authorization received!');
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// Finish OAuth flow
|
|
1174
|
+
await transport.finishAuth(code);
|
|
1175
|
+
|
|
1176
|
+
// Save tokens to alias if using a saved agent
|
|
1177
|
+
if (agentAlias && agentConfig.oauth_tokens) {
|
|
1178
|
+
const savedConfig = getAgent(agentAlias);
|
|
1179
|
+
savedConfig.oauth_tokens = agentConfig.oauth_tokens;
|
|
1180
|
+
savedConfig.oauth_client = agentConfig.oauth_client;
|
|
1181
|
+
saveAgent(agentAlias, savedConfig);
|
|
1182
|
+
if (!jsonOutput) {
|
|
1183
|
+
console.log(`OAuth tokens saved to '${agentAlias}'.\n`);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// Reconnect with new tokens
|
|
1188
|
+
if (!jsonOutput) {
|
|
1189
|
+
console.log('Reconnecting with OAuth tokens...');
|
|
1190
|
+
}
|
|
1191
|
+
transport = createTransport();
|
|
1192
|
+
await mcpClient.connect(transport);
|
|
1193
|
+
} catch (authError) {
|
|
1194
|
+
await oauthProvider.cleanup();
|
|
1195
|
+
throw authError;
|
|
1196
|
+
}
|
|
1197
|
+
} else {
|
|
1198
|
+
await oauthProvider.cleanup();
|
|
1199
|
+
throw error;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (!jsonOutput) {
|
|
1204
|
+
console.log('Connected!\n');
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
// Execute tool call directly via MCP
|
|
1208
|
+
try {
|
|
1209
|
+
const startTime = Date.now();
|
|
1210
|
+
const toolResult = await mcpClient.callTool({ name: toolName, arguments: payload });
|
|
1211
|
+
const responseTime = Date.now() - startTime;
|
|
1212
|
+
|
|
1213
|
+
await oauthProvider.cleanup();
|
|
1214
|
+
await mcpClient.close();
|
|
1215
|
+
|
|
1216
|
+
// Format result similar to AdCPClient response
|
|
1217
|
+
let resultData = toolResult;
|
|
1218
|
+
if (toolResult.content && Array.isArray(toolResult.content)) {
|
|
1219
|
+
const textContent = toolResult.content.find(c => c.type === 'text');
|
|
1220
|
+
if (textContent && textContent.text) {
|
|
1221
|
+
try {
|
|
1222
|
+
resultData = JSON.parse(textContent.text);
|
|
1223
|
+
} catch {
|
|
1224
|
+
resultData = textContent.text;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
if (jsonOutput) {
|
|
1230
|
+
console.log(
|
|
1231
|
+
JSON.stringify(
|
|
1232
|
+
{
|
|
1233
|
+
data: resultData,
|
|
1234
|
+
metadata: {
|
|
1235
|
+
protocol: 'mcp',
|
|
1236
|
+
responseTimeMs: responseTime,
|
|
1237
|
+
oauth: true,
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1240
|
+
null,
|
|
1241
|
+
2
|
|
1242
|
+
)
|
|
1243
|
+
);
|
|
1244
|
+
} else {
|
|
1245
|
+
console.log('\nā
SUCCESS\n');
|
|
1246
|
+
console.log('Response:');
|
|
1247
|
+
console.log(JSON.stringify(resultData, null, 2));
|
|
1248
|
+
console.log('');
|
|
1249
|
+
console.log(`Protocol: MCP (OAuth)`);
|
|
1250
|
+
console.log(`Response Time: ${responseTime}ms`);
|
|
1251
|
+
}
|
|
1252
|
+
process.exit(0);
|
|
1253
|
+
} catch (toolError) {
|
|
1254
|
+
await oauthProvider.cleanup();
|
|
1255
|
+
await mcpClient.close();
|
|
1256
|
+
throw toolError;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
859
1260
|
// Create ADCP client with optional webhook configuration
|
|
860
1261
|
// Note: AdCPClient (multi-agent) expects an array of configs
|
|
861
1262
|
const client = new AdCPClient([agentConfig], {
|
|
@@ -1008,6 +1409,121 @@ async function main() {
|
|
|
1008
1409
|
process.exit(3);
|
|
1009
1410
|
}
|
|
1010
1411
|
} catch (error) {
|
|
1412
|
+
// Check if this is an OAuth-required error for MCP and offer auto-authentication
|
|
1413
|
+
const isUnauthorized =
|
|
1414
|
+
error.name === 'UnauthorizedError' ||
|
|
1415
|
+
error.message?.toLowerCase().includes('unauthorized') ||
|
|
1416
|
+
error.message?.includes('401');
|
|
1417
|
+
|
|
1418
|
+
if (isUnauthorized && protocol === 'mcp' && !useOAuth && !authToken) {
|
|
1419
|
+
console.log('\nš Server requires authentication.');
|
|
1420
|
+
console.log('Starting OAuth authentication...\n');
|
|
1421
|
+
|
|
1422
|
+
// Run OAuth flow automatically
|
|
1423
|
+
const { Client: MCPClient } = require('@modelcontextprotocol/sdk/client/index.js');
|
|
1424
|
+
const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
1425
|
+
const { UnauthorizedError } = require('@modelcontextprotocol/sdk/client/auth.js');
|
|
1426
|
+
|
|
1427
|
+
const oauthProvider = createCLIOAuthProvider(agentConfig, { quiet: jsonOutput });
|
|
1428
|
+
const mcpClient = new MCPClient({ name: 'adcp-cli', version: '1.0.0' });
|
|
1429
|
+
const createTransport = () =>
|
|
1430
|
+
new StreamableHTTPClientTransport(new URL(agentUrl), { authProvider: oauthProvider });
|
|
1431
|
+
|
|
1432
|
+
let transport = createTransport();
|
|
1433
|
+
|
|
1434
|
+
try {
|
|
1435
|
+
await mcpClient.connect(transport);
|
|
1436
|
+
} catch (connectError) {
|
|
1437
|
+
if (connectError instanceof UnauthorizedError || connectError.name === 'UnauthorizedError') {
|
|
1438
|
+
console.log('Opening browser for authentication...\n');
|
|
1439
|
+
const code = await oauthProvider.waitForCallback();
|
|
1440
|
+
console.log('Authorization received!');
|
|
1441
|
+
await transport.finishAuth(code);
|
|
1442
|
+
|
|
1443
|
+
// Save tokens if using a saved alias
|
|
1444
|
+
if (agentAlias && agentConfig.oauth_tokens) {
|
|
1445
|
+
const savedConfig = getAgent(agentAlias);
|
|
1446
|
+
savedConfig.oauth_tokens = agentConfig.oauth_tokens;
|
|
1447
|
+
savedConfig.oauth_client = agentConfig.oauth_client;
|
|
1448
|
+
saveAgent(agentAlias, savedConfig);
|
|
1449
|
+
console.log(`OAuth tokens saved to '${agentAlias}'.\n`);
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
// Reconnect and execute
|
|
1453
|
+
console.log('Reconnecting with OAuth tokens...');
|
|
1454
|
+
transport = createTransport();
|
|
1455
|
+
await mcpClient.connect(transport);
|
|
1456
|
+
console.log('Connected!\n');
|
|
1457
|
+
|
|
1458
|
+
// Execute the tool if specified
|
|
1459
|
+
if (toolName) {
|
|
1460
|
+
const startTime = Date.now();
|
|
1461
|
+
const toolResult = await mcpClient.callTool({ name: toolName, arguments: payload });
|
|
1462
|
+
const responseTime = Date.now() - startTime;
|
|
1463
|
+
|
|
1464
|
+
await oauthProvider.cleanup();
|
|
1465
|
+
await mcpClient.close();
|
|
1466
|
+
|
|
1467
|
+
let resultData = toolResult;
|
|
1468
|
+
if (toolResult.content && Array.isArray(toolResult.content)) {
|
|
1469
|
+
const textContent = toolResult.content.find(c => c.type === 'text');
|
|
1470
|
+
if (textContent && textContent.text) {
|
|
1471
|
+
try {
|
|
1472
|
+
resultData = JSON.parse(textContent.text);
|
|
1473
|
+
} catch {
|
|
1474
|
+
resultData = textContent.text;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
if (jsonOutput) {
|
|
1480
|
+
console.log(
|
|
1481
|
+
JSON.stringify(
|
|
1482
|
+
{
|
|
1483
|
+
data: resultData,
|
|
1484
|
+
metadata: { protocol: 'mcp', responseTimeMs: responseTime, oauth: true },
|
|
1485
|
+
},
|
|
1486
|
+
null,
|
|
1487
|
+
2
|
|
1488
|
+
)
|
|
1489
|
+
);
|
|
1490
|
+
} else {
|
|
1491
|
+
console.log('\nā
SUCCESS\n');
|
|
1492
|
+
console.log('Response:');
|
|
1493
|
+
console.log(JSON.stringify(resultData, null, 2));
|
|
1494
|
+
console.log('');
|
|
1495
|
+
console.log(`Protocol: MCP (OAuth)`);
|
|
1496
|
+
console.log(`Response Time: ${responseTime}ms`);
|
|
1497
|
+
}
|
|
1498
|
+
process.exit(0);
|
|
1499
|
+
} else {
|
|
1500
|
+
// List tools
|
|
1501
|
+
const toolsResult = await mcpClient.listTools();
|
|
1502
|
+
await oauthProvider.cleanup();
|
|
1503
|
+
await mcpClient.close();
|
|
1504
|
+
|
|
1505
|
+
if (jsonOutput) {
|
|
1506
|
+
console.log(JSON.stringify({ tools: toolsResult.tools, protocol: 'mcp', oauth: true }, null, 2));
|
|
1507
|
+
} else {
|
|
1508
|
+
console.log(`\nš Agent Information (OAuth)\n`);
|
|
1509
|
+
console.log(`Protocol: MCP`);
|
|
1510
|
+
console.log(`URL: ${agentUrl}`);
|
|
1511
|
+
console.log(`\nAvailable Tools (${toolsResult.tools.length}):\n`);
|
|
1512
|
+
toolsResult.tools.forEach((tool, i) => {
|
|
1513
|
+
console.log(`${i + 1}. ${tool.name}`);
|
|
1514
|
+
if (tool.description) console.log(` ${tool.description}`);
|
|
1515
|
+
console.log('');
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
process.exit(0);
|
|
1519
|
+
}
|
|
1520
|
+
} else {
|
|
1521
|
+
await oauthProvider.cleanup();
|
|
1522
|
+
throw connectError;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1011
1527
|
console.error('\nā ERROR\n');
|
|
1012
1528
|
console.error(error.message);
|
|
1013
1529
|
if (debug) {
|