@kya-os/mcp-i-core 1.3.14 → 1.3.16

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.
@@ -33,6 +33,13 @@ export interface TokenUsageMetadata {
33
33
  cookieFormat?: string;
34
34
  /** Additional headers to include in API calls */
35
35
  apiHeaders?: Record<string, string>;
36
+ /**
37
+ * User ID extracted from credential provider response
38
+ *
39
+ * For credential providers, this is the userId extracted via responseFields.userId.
40
+ * This is passed to tool handlers via ToolExecutionContext.userId.
41
+ */
42
+ userId?: string;
36
43
  }
37
44
  /**
38
45
  * Extended IdpTokens with usage metadata (CRED-003)
@@ -122,9 +122,10 @@ export declare class MCPIRuntimeBase {
122
122
  * @param session - Current session context
123
123
  * @param resumeToken - Token to resume after delegation
124
124
  * @param projectId - Project ID for AgentShield API
125
+ * @param provider - Provider name (e.g., "github", "credentials") to select specific auth method
125
126
  * @returns Full consent URL with snake_case parameters
126
127
  */
127
- protected buildConsentUrl(toolName: string, scopes: string[], session?: any, resumeToken?: string, projectId?: string): string;
128
+ protected buildConsentUrl(toolName: string, scopes: string[], session?: any, resumeToken?: string, projectId?: string, provider?: string): string;
128
129
  /**
129
130
  * Issue a new nonce and register it in the cache
130
131
  * Use this to get a nonce for the session context before calling processToolCall
@@ -271,7 +271,10 @@ class MCPIRuntimeBase {
271
271
  const resumeToken = this.generateResumeToken(interceptedCall);
272
272
  // Build consent URL with resume token
273
273
  // Note: projectId is not available in base class - subclasses should override buildConsentUrl
274
- const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken);
274
+ // Pass oauthProvider to ensure correct auth method is selected (e.g., "credentials" vs "github")
275
+ const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken, undefined, // projectId - handled by subclass override
276
+ protection.oauthProvider // Provider from tool config
277
+ );
275
278
  // Create error with intercepted call context and pre-generated resume token
276
279
  const error = new tool_protection_js_1.DelegationRequiredError(toolName, protection.requiredScopes, consentUrl, interceptedCall, resumeToken);
277
280
  // Store intercepted call for resumption
@@ -379,7 +382,9 @@ class MCPIRuntimeBase {
379
382
  expiresAt: this.clock.calculateExpiry(1800), // 30 minutes
380
383
  };
381
384
  const resumeToken = this.generateResumeToken(interceptedCall);
382
- const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken);
385
+ const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken, undefined, // projectId - handled by subclass override
386
+ protection.oauthProvider // Provider from tool config
387
+ );
383
388
  this.interceptedCalls.set(resumeToken, interceptedCall);
384
389
  this.cleanupExpiredInterceptedCalls();
385
390
  throw new tool_protection_js_1.DelegationRequiredError(toolName, protection.requiredScopes, consentUrl, interceptedCall, resumeToken);
@@ -413,7 +418,9 @@ class MCPIRuntimeBase {
413
418
  expiresAt: this.clock.calculateExpiry(1800), // 30 minutes
414
419
  };
415
420
  const resumeToken = this.generateResumeToken(interceptedCall);
416
- const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken);
421
+ const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken, undefined, // projectId - handled by subclass override
422
+ protection.oauthProvider // Provider from tool config
423
+ );
417
424
  this.interceptedCalls.set(resumeToken, interceptedCall);
418
425
  this.cleanupExpiredInterceptedCalls();
419
426
  throw new tool_protection_js_1.DelegationRequiredError(toolName, protection.requiredScopes, consentUrl, interceptedCall, resumeToken);
@@ -477,7 +484,9 @@ class MCPIRuntimeBase {
477
484
  expiresAt: this.clock.calculateExpiry(1800),
478
485
  };
479
486
  const resumeToken = this.generateResumeToken(interceptedCall);
480
- const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken);
487
+ const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken, undefined, // projectId - handled by subclass override
488
+ protection.oauthProvider // Provider from tool config
489
+ );
481
490
  this.interceptedCalls.set(resumeToken, interceptedCall);
482
491
  this.cleanupExpiredInterceptedCalls();
483
492
  throw new tool_protection_js_1.DelegationRequiredError(toolName, protection.requiredScopes, consentUrl, interceptedCall, resumeToken);
@@ -500,7 +509,9 @@ class MCPIRuntimeBase {
500
509
  expiresAt: this.clock.calculateExpiry(1800),
501
510
  };
502
511
  const resumeToken = this.generateResumeToken(interceptedCall);
503
- const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken);
512
+ const consentUrl = this.buildConsentUrl(toolName, protection.requiredScopes, session, resumeToken, undefined, // projectId - handled by subclass override
513
+ protection.oauthProvider // Provider from tool config
514
+ );
504
515
  this.interceptedCalls.set(resumeToken, interceptedCall);
505
516
  this.cleanupExpiredInterceptedCalls();
506
517
  throw new tool_protection_js_1.DelegationRequiredError(toolName, protection.requiredScopes, consentUrl, interceptedCall, resumeToken);
@@ -616,9 +627,10 @@ class MCPIRuntimeBase {
616
627
  * @param session - Current session context
617
628
  * @param resumeToken - Token to resume after delegation
618
629
  * @param projectId - Project ID for AgentShield API
630
+ * @param provider - Provider name (e.g., "github", "credentials") to select specific auth method
619
631
  * @returns Full consent URL with snake_case parameters
620
632
  */
621
- buildConsentUrl(toolName, scopes, session, resumeToken, projectId) {
633
+ buildConsentUrl(toolName, scopes, session, resumeToken, projectId, provider) {
622
634
  // Default implementation - override in subclasses
623
635
  // This URL should point to AgentShield's consent page
624
636
  // Parameter names use snake_case for AgentShield API compatibility
@@ -636,6 +648,11 @@ class MCPIRuntimeBase {
636
648
  if (resumeToken) {
637
649
  params.set("resume_token", resumeToken);
638
650
  }
651
+ // Add provider if specified (allows selecting specific auth method like "credentials" or "github")
652
+ // This is critical when multiple providers are configured for a project
653
+ if (provider) {
654
+ params.set("provider", provider);
655
+ }
639
656
  // Use AgentShield consent endpoint
640
657
  return `https://kya.vouched.id/bouncer/consent?${params.toString()}`;
641
658
  }
@@ -86,6 +86,7 @@ class ToolContextBuilder {
86
86
  // CRED-003: Build headers based on tokenUsage
87
87
  const idpHeaders = this.buildAuthHeaders(tokenData);
88
88
  // Build context with token and headers
89
+ // Include userId from token metadata (extracted from credential provider response)
89
90
  const context = {
90
91
  idpToken: tokenData.access_token,
91
92
  idpHeaders,
@@ -94,12 +95,15 @@ class ToolContextBuilder {
94
95
  userDid,
95
96
  sessionId,
96
97
  delegationToken,
98
+ // CRED-003: Include userId from credential provider's extracted user ID
99
+ userId: tokenData.userId,
97
100
  };
98
101
  this.config.logger("[ToolContextBuilder] Context built successfully", {
99
102
  toolName,
100
103
  userDid: userDid.substring(0, 20) + "...",
101
104
  provider,
102
105
  hasToken: !!tokenData.access_token,
106
+ hasUserId: !!tokenData.userId,
103
107
  tokenUsage: tokenData.tokenUsage,
104
108
  headerKeys: Object.keys(idpHeaders),
105
109
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/mcp-i-core",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "Core runtime and types for MCP-I framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "prepublishOnly": "npm run build && node ../create-mcpi-app/scripts/validate-no-workspace.js"
29
29
  },
30
30
  "dependencies": {
31
- "@kya-os/contracts": "^1.6.7",
31
+ "@kya-os/contracts": "^1.6.9",
32
32
  "jose": "^5.6.3",
33
33
  "json-canonicalize": "^2.0.0",
34
34
  "zod": "^3.25.76"