@kya-os/mcp-i-core 1.3.9 → 1.3.10

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.
@@ -87,55 +87,56 @@ import type {
87
87
  import type { ToolProtectionCache } from "../cache/tool-protection-cache.js";
88
88
  import { InMemoryToolProtectionCache } from "../cache/tool-protection-cache.js";
89
89
 
90
+ /**
91
+ * Tool protection data structure in API responses
92
+ */
93
+ interface ToolProtectionData {
94
+ requiresDelegation?: boolean;
95
+ requires_delegation?: boolean;
96
+ requiredScopes?: string[];
97
+ required_scopes?: string[];
98
+ scopes?: string[];
99
+ riskLevel?: string;
100
+ risk_level?: string;
101
+ oauthProvider?: string;
102
+ oauth_provider?: string;
103
+ authorization?: {
104
+ type: string;
105
+ provider?: string;
106
+ issuer?: string;
107
+ credentialType?: string;
108
+ };
109
+ }
110
+
90
111
  /**
91
112
  * Response from AgentShield API bouncer endpoints
92
113
  *
93
114
  * Supports multiple endpoint formats:
94
- * 1. Merged config endpoint (/projects/{projectId}/config): { data: { config: { toolProtection: { tools: {...} } } } }
95
- * 2. Old endpoint (/config?agent_did=...): { data: { tools: [{ name: string, ... }] } }
96
- * 3. Legacy format: { data: { tools: { [toolName]: {...} } } }
97
- * 4. Legacy toolProtections format: { data: { toolProtections: {...} } } (deprecated)
115
+ * 1. Merged config (/projects/{projectId}/config): { data: { config: { toolProtection: { tools: {...} } } } }
116
+ * 2. Legacy tool-protections endpoint: { data: { toolProtections: { [toolName]: {...} } } }
117
+ * 3. Old config endpoint (/config?agent_did=...): { data: { tools: [{ name: string, ... }] } }
118
+ * 4. Legacy format: { data: { tools: { [toolName]: {...} } } }
98
119
  */
99
120
  interface BouncerConfigApiResponse {
100
121
  success: boolean;
101
122
  data: {
102
123
  agent_did?: string;
103
- // Merged config format: config object with embedded toolProtection.tools
124
+
125
+ // NEW: Merged config format (v1.6.0+) - preferred format
126
+ // The entire config is returned with tools embedded at config.toolProtection.tools
104
127
  config?: {
105
128
  toolProtection?: {
106
129
  source?: string;
107
- tools?: Record<
108
- string,
109
- {
110
- requiresDelegation?: boolean;
111
- requires_delegation?: boolean;
112
- requiredScopes?: string[];
113
- required_scopes?: string[];
114
- scopes?: string[];
115
- riskLevel?: string;
116
- risk_level?: string;
117
- oauthProvider?: string;
118
- oauth_provider?: string;
119
- }
120
- >;
130
+ tools?: Record<string, ToolProtectionData>;
121
131
  };
132
+ // Other config fields we don't need to parse
133
+ [key: string]: unknown;
122
134
  };
123
- // Legacy toolProtections format (deprecated, kept for backward compatibility)
124
- toolProtections?: Record<
125
- string,
126
- {
127
- requiresDelegation?: boolean;
128
- requires_delegation?: boolean;
129
- requiredScopes?: string[];
130
- required_scopes?: string[];
131
- scopes?: string[];
132
- riskLevel?: string;
133
- risk_level?: string;
134
- oauthProvider?: string; // Phase 2: Tool-specific OAuth provider
135
- oauth_provider?: string; // Phase 2: snake_case variant
136
- }
137
- >;
138
- // Old endpoint format: tools array or object
135
+
136
+ // DEPRECATED: Top-level toolProtections (backward compatibility during transition)
137
+ toolProtections?: Record<string, ToolProtectionData>;
138
+
139
+ // Legacy endpoint formats
139
140
  tools?:
140
141
  | Array<{
141
142
  name: string;
@@ -143,20 +144,10 @@ interface BouncerConfigApiResponse {
143
144
  requires_delegation?: boolean;
144
145
  scopes?: string[];
145
146
  required_scopes?: string[];
146
- oauthProvider?: string; // Phase 2: Tool-specific OAuth provider
147
- oauth_provider?: string; // Phase 2: snake_case variant
147
+ oauthProvider?: string;
148
+ oauth_provider?: string;
148
149
  }>
149
- | Record<
150
- string,
151
- {
152
- requiresDelegation?: boolean;
153
- requires_delegation?: boolean;
154
- scopes?: string[];
155
- required_scopes?: string[];
156
- oauthProvider?: string; // Phase 2: Tool-specific OAuth provider
157
- oauth_provider?: string; // Phase 2: snake_case variant
158
- }
159
- >;
150
+ | Record<string, ToolProtectionData>;
160
151
  reputation_threshold?: number;
161
152
  denied_agents?: string[];
162
153
  };
@@ -727,7 +718,10 @@ export class ToolProtectionService {
727
718
 
728
719
  /**
729
720
  * Fetch tool protection config from AgentShield API
730
- * Uses projectId endpoint if available (preferred, project-scoped), otherwise falls back to agent_did query param
721
+ *
722
+ * Uses the merged /config endpoint which returns tool protections embedded
723
+ * at config.toolProtection.tools. Falls back to legacy formats for backward
724
+ * compatibility.
731
725
  *
732
726
  * @param agentDid DID of the agent to fetch config for
733
727
  * @param options Optional fetch options
@@ -737,17 +731,17 @@ export class ToolProtectionService {
737
731
  agentDid: string,
738
732
  options?: { bypassCDNCache?: boolean }
739
733
  ): Promise<BouncerConfigApiResponse> {
740
- // Prefer project-scoped merged config endpoint: /api/v1/bouncer/projects/{projectId}/config
741
- // Falls back to old endpoint: /api/v1/bouncer/config?agent_did={did} for backward compatibility
734
+ // Use the merged /config endpoint which includes embedded tool protections
735
+ // This endpoint returns config.toolProtection.tools with all tool rules
742
736
  let url: string;
743
- let useMergedConfigEndpoint = false;
737
+ let useMergedEndpoint = false;
744
738
 
745
739
  if (this.config.projectId) {
746
- // ✅ MERGED CONFIG ENDPOINT: Project-scoped, returns config with embedded toolProtection.tools
740
+ // ✅ MERGED CONFIG ENDPOINT: Returns config with embedded toolProtection.tools
747
741
  url = `${this.config.apiUrl}/api/v1/bouncer/projects/${encodeURIComponent(this.config.projectId)}/config`;
748
- useMergedConfigEndpoint = true;
742
+ useMergedEndpoint = true;
749
743
  } else {
750
- // ⚠️ OLD ENDPOINT: Agent-scoped, returns tools array (backward compatibility)
744
+ // ⚠️ LEGACY ENDPOINT: Agent-scoped, returns tools array (backward compatibility)
751
745
  url = `${this.config.apiUrl}/api/v1/bouncer/config?agent_did=${encodeURIComponent(agentDid)}`;
752
746
  }
753
747
 
@@ -774,9 +768,9 @@ export class ToolProtectionService {
774
768
 
775
769
  if (this.config.debug) {
776
770
  console.log("[ToolProtectionService] Fetching from API:", url, {
777
- method: useMergedConfigEndpoint
771
+ method: useMergedEndpoint
778
772
  ? "projects/{projectId}/config (merged)"
779
- : "config?agent_did (old)",
773
+ : "config?agent_did (legacy)",
780
774
  projectId: this.config.projectId || "none",
781
775
  apiKeyPresent: !!this.config.apiKey,
782
776
  apiKeyLength,
@@ -798,19 +792,19 @@ export class ToolProtectionService {
798
792
  );
799
793
  }
800
794
 
801
- // Build headers - merged config endpoint uses X-API-Key (preferred), old endpoint uses Authorization Bearer
795
+ // Build headers - merged endpoint uses X-API-Key, legacy uses Authorization Bearer
802
796
  const headers: Record<string, string> = {
803
797
  "Content-Type": "application/json",
804
798
  };
805
799
 
806
- if (useMergedConfigEndpoint) {
807
- // ✅ Merged config endpoint headers (X-API-Key preferred by AgentShield V1 API)
800
+ if (useMergedEndpoint) {
801
+ // ✅ Merged config endpoint headers
808
802
  headers["X-API-Key"] = this.config.apiKey;
809
803
  if (this.config.projectId) {
810
804
  headers["X-Project-Id"] = this.config.projectId;
811
805
  }
812
806
  } else {
813
- // ⚠️ Old endpoint headers (backward compatibility)
807
+ // ⚠️ Legacy endpoint headers (backward compatibility)
814
808
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
815
809
  }
816
810
 
@@ -848,6 +842,19 @@ export class ToolProtectionService {
848
842
  throw new Error("API returned success: false");
849
843
  }
850
844
 
845
+ // Transform merged config format to normalized format
846
+ // If response contains config.toolProtection.tools, extract them to data.toolProtections
847
+ if (useMergedEndpoint && data.data.config?.toolProtection?.tools) {
848
+ // Extract embedded tools to the standard toolProtections field
849
+ data.data.toolProtections = data.data.config.toolProtection.tools;
850
+ if (this.config.debug) {
851
+ console.log("[ToolProtectionService] Extracted tools from merged config", {
852
+ toolCount: Object.keys(data.data.toolProtections).length,
853
+ tools: Object.keys(data.data.toolProtections),
854
+ });
855
+ }
856
+ }
857
+
851
858
  return data;
852
859
  }
853
860