@kya-os/consent 0.1.13 → 0.1.14
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/dist/bundle/inline.d.ts.map +1 -1
- package/dist/bundle/inline.js +2 -2
- package/dist/bundle/inline.js.map +1 -1
- package/dist/bundle/shell.d.ts +5 -0
- package/dist/bundle/shell.d.ts.map +1 -1
- package/dist/bundle/shell.js +3 -1
- package/dist/bundle/shell.js.map +1 -1
- package/dist/cjs/bundle/index.js +57 -0
- package/dist/cjs/bundle/index.js.map +1 -0
- package/dist/cjs/bundle/inline.js +22 -0
- package/dist/cjs/bundle/inline.js.map +1 -0
- package/dist/cjs/bundle/shell.js +291 -0
- package/dist/cjs/bundle/shell.js.map +1 -0
- package/dist/cjs/components/consent-button.js +180 -0
- package/dist/cjs/components/consent-button.js.map +1 -0
- package/dist/cjs/components/consent-checkbox.js +223 -0
- package/dist/cjs/components/consent-checkbox.js.map +1 -0
- package/dist/cjs/components/consent-input.js +335 -0
- package/dist/cjs/components/consent-input.js.map +1 -0
- package/dist/cjs/components/consent-oauth-button.js +392 -0
- package/dist/cjs/components/consent-oauth-button.js.map +1 -0
- package/dist/cjs/components/consent-otp-input.js +388 -0
- package/dist/cjs/components/consent-otp-input.js.map +1 -0
- package/dist/cjs/components/consent-permissions.js +433 -0
- package/dist/cjs/components/consent-permissions.js.map +1 -0
- package/dist/cjs/components/consent-shell.js +234 -0
- package/dist/cjs/components/consent-shell.js.map +1 -0
- package/dist/cjs/components/consent-terms.js +287 -0
- package/dist/cjs/components/consent-terms.js.map +1 -0
- package/dist/cjs/components/index.js +37 -0
- package/dist/cjs/components/index.js.map +1 -0
- package/dist/cjs/components/mcp-consent.js +1034 -0
- package/dist/cjs/components/mcp-consent.js.map +1 -0
- package/dist/cjs/constants/auth-modes.js +128 -0
- package/dist/cjs/constants/auth-modes.js.map +1 -0
- package/dist/cjs/constants/colors.js +40 -0
- package/dist/cjs/constants/colors.js.map +1 -0
- package/dist/cjs/constants/defaults.js +146 -0
- package/dist/cjs/constants/defaults.js.map +1 -0
- package/dist/cjs/constants/index.js +40 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/cjs/index.js +49 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/react/index.js +190 -0
- package/dist/cjs/react/index.js.map +1 -0
- package/dist/cjs/resolution/index.js +28 -0
- package/dist/cjs/resolution/index.js.map +1 -0
- package/dist/cjs/resolution/resolve-branding.js +159 -0
- package/dist/cjs/resolution/resolve-branding.js.map +1 -0
- package/dist/cjs/resolution/resolve-config.js +270 -0
- package/dist/cjs/resolution/resolve-config.js.map +1 -0
- package/dist/cjs/resolution/resolve-copy.js +136 -0
- package/dist/cjs/resolution/resolve-copy.js.map +1 -0
- package/dist/cjs/schemas/api.schemas.js +156 -0
- package/dist/cjs/schemas/api.schemas.js.map +1 -0
- package/dist/cjs/schemas/branding.schemas.js +57 -0
- package/dist/cjs/schemas/branding.schemas.js.map +1 -0
- package/dist/cjs/schemas/config.schemas.js +147 -0
- package/dist/cjs/schemas/config.schemas.js.map +1 -0
- package/dist/cjs/schemas/index.js +29 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/schemas/modes.schemas.js +107 -0
- package/dist/cjs/schemas/modes.schemas.js.map +1 -0
- package/dist/cjs/security/escape.js +206 -0
- package/dist/cjs/security/escape.js.map +1 -0
- package/dist/cjs/security/index.js +26 -0
- package/dist/cjs/security/index.js.map +1 -0
- package/dist/cjs/security/validators.js +210 -0
- package/dist/cjs/security/validators.js.map +1 -0
- package/dist/cjs/styles/css-variables.js +129 -0
- package/dist/cjs/styles/css-variables.js.map +1 -0
- package/dist/cjs/styles/index.js +28 -0
- package/dist/cjs/styles/index.js.map +1 -0
- package/dist/cjs/styles/stylesheet.js +204 -0
- package/dist/cjs/styles/stylesheet.js.map +1 -0
- package/dist/cjs/styles/tokens.js +183 -0
- package/dist/cjs/styles/tokens.js.map +1 -0
- package/dist/cjs/templates/base/base-template.js +282 -0
- package/dist/cjs/templates/base/base-template.js.map +1 -0
- package/dist/cjs/templates/base/components.js +295 -0
- package/dist/cjs/templates/base/components.js.map +1 -0
- package/dist/cjs/templates/base/index.js +26 -0
- package/dist/cjs/templates/base/index.js.map +1 -0
- package/dist/cjs/templates/index.js +34 -0
- package/dist/cjs/templates/index.js.map +1 -0
- package/dist/cjs/templates/modes/consent-only.template.js +74 -0
- package/dist/cjs/templates/modes/consent-only.template.js.map +1 -0
- package/dist/cjs/templates/modes/credentials.template.js +414 -0
- package/dist/cjs/templates/modes/credentials.template.js.map +1 -0
- package/dist/cjs/templates/modes/index.js +24 -0
- package/dist/cjs/templates/modes/index.js.map +1 -0
- package/dist/cjs/templates/modes/magic-link.template.js +196 -0
- package/dist/cjs/templates/modes/magic-link.template.js.map +1 -0
- package/dist/cjs/templates/modes/oauth.template.js +153 -0
- package/dist/cjs/templates/modes/oauth.template.js.map +1 -0
- package/dist/cjs/templates/modes/otp.template.js +316 -0
- package/dist/cjs/templates/modes/otp.template.js.map +1 -0
- package/dist/cjs/templates/modes/success.template.js +140 -0
- package/dist/cjs/templates/modes/success.template.js.map +1 -0
- package/dist/cjs/templates/registry.js +133 -0
- package/dist/cjs/templates/registry.js.map +1 -0
- package/dist/cjs/types/api.types.js +10 -0
- package/dist/cjs/types/api.types.js.map +1 -0
- package/dist/cjs/types/branding.types.js +10 -0
- package/dist/cjs/types/branding.types.js.map +1 -0
- package/dist/cjs/types/config.types.js +10 -0
- package/dist/cjs/types/config.types.js.map +1 -0
- package/dist/cjs/types/copy.types.js +10 -0
- package/dist/cjs/types/copy.types.js.map +1 -0
- package/dist/cjs/types/index.js +31 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/modes.types.js +140 -0
- package/dist/cjs/types/modes.types.js.map +1 -0
- package/dist/cjs/types/page.types.js +10 -0
- package/dist/cjs/types/page.types.js.map +1 -0
- package/dist/components/mcp-consent.d.ts +6 -0
- package/dist/components/mcp-consent.d.ts.map +1 -1
- package/dist/components/mcp-consent.js +14 -0
- package/dist/components/mcp-consent.js.map +1 -1
- package/dist/consent.js +7 -0
- package/dist/consent.min.js +2 -2
- package/dist/schemas/api.schemas.d.ts +116 -116
- package/dist/schemas/config.schemas.d.ts +116 -116
- package/dist/schemas/modes.schemas.d.ts +28 -28
- package/package.json +29 -15
|
@@ -0,0 +1,1034 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Consent Composite Web Component
|
|
4
|
+
*
|
|
5
|
+
* The main entry point component that orchestrates the full consent flow.
|
|
6
|
+
* Handles all auth modes, form submission, and state management.
|
|
7
|
+
*
|
|
8
|
+
* @module components/mcp-consent
|
|
9
|
+
*/
|
|
10
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
11
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
13
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.McpConsent = void 0;
|
|
18
|
+
const lit_1 = require("lit");
|
|
19
|
+
const decorators_js_1 = require("lit/decorators.js");
|
|
20
|
+
const modes_types_js_1 = require("../types/modes.types.js");
|
|
21
|
+
const resolve_config_js_1 = require("../resolution/resolve-config.js");
|
|
22
|
+
// Import component definitions for side effects
|
|
23
|
+
require("./consent-shell.js");
|
|
24
|
+
require("./consent-button.js");
|
|
25
|
+
require("./consent-checkbox.js");
|
|
26
|
+
require("./consent-input.js");
|
|
27
|
+
require("./consent-permissions.js");
|
|
28
|
+
require("./consent-terms.js");
|
|
29
|
+
require("./consent-oauth-button.js");
|
|
30
|
+
require("./consent-otp-input.js");
|
|
31
|
+
/**
|
|
32
|
+
* McpConsent - Full consent flow component
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```html
|
|
36
|
+
* <mcp-consent
|
|
37
|
+
* config='{"branding": {"primaryColor": "#2563eb"}}'
|
|
38
|
+
* tool="greet"
|
|
39
|
+
* scopes='["read:profile"]'
|
|
40
|
+
* agent-did="did:key:z123"
|
|
41
|
+
* session-id="sess_123"
|
|
42
|
+
* project-id="proj_123"
|
|
43
|
+
* server-url="https://example.com"
|
|
44
|
+
* ></mcp-consent>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @fires mcp-consent:approve - User approved, delegation created
|
|
48
|
+
* @fires mcp-consent:deny - User clicked cancel
|
|
49
|
+
* @fires mcp-consent:error - Submission failed
|
|
50
|
+
*/
|
|
51
|
+
let McpConsent = class McpConsent extends lit_1.LitElement {
|
|
52
|
+
constructor() {
|
|
53
|
+
// === INPUT PROPERTIES (from config) ===
|
|
54
|
+
super(...arguments);
|
|
55
|
+
// === CONSENT DATA (hidden form fields) ===
|
|
56
|
+
/**
|
|
57
|
+
* Tool being authorized
|
|
58
|
+
*/
|
|
59
|
+
this.tool = "";
|
|
60
|
+
/**
|
|
61
|
+
* Permission scopes requested
|
|
62
|
+
*/
|
|
63
|
+
this.scopes = [];
|
|
64
|
+
/**
|
|
65
|
+
* Agent DID
|
|
66
|
+
*/
|
|
67
|
+
this.agentDid = "";
|
|
68
|
+
/**
|
|
69
|
+
* Session ID
|
|
70
|
+
*/
|
|
71
|
+
this.sessionId = "";
|
|
72
|
+
/**
|
|
73
|
+
* Project ID
|
|
74
|
+
*/
|
|
75
|
+
this.projectId = "";
|
|
76
|
+
/**
|
|
77
|
+
* Server URL for form submission
|
|
78
|
+
*/
|
|
79
|
+
this.serverUrl = "";
|
|
80
|
+
/**
|
|
81
|
+
* Agent name for display
|
|
82
|
+
*/
|
|
83
|
+
this.agentName = "";
|
|
84
|
+
/**
|
|
85
|
+
* Auth provider identifier (e.g., 'credentials', 'google', 'github')
|
|
86
|
+
* Required for credential auth and OAuth flows to identify the provider
|
|
87
|
+
*/
|
|
88
|
+
this.provider = "";
|
|
89
|
+
/**
|
|
90
|
+
* CSRF token for form security
|
|
91
|
+
* Required for credential auth flows to prevent CSRF attacks
|
|
92
|
+
*/
|
|
93
|
+
this.csrfToken = "";
|
|
94
|
+
// === POST-CREDENTIAL AUTH PARAMS (for 3-screen flow) ===
|
|
95
|
+
/**
|
|
96
|
+
* Credential provider type from prior auth step
|
|
97
|
+
* Set when redirecting from credential auth → clickwrap page
|
|
98
|
+
* Used to ensure delegation is created with correct authorization type ('password')
|
|
99
|
+
*/
|
|
100
|
+
this.credentialProviderType = "";
|
|
101
|
+
/**
|
|
102
|
+
* Credential provider name from prior auth step
|
|
103
|
+
* Set when redirecting from credential auth → clickwrap page
|
|
104
|
+
*/
|
|
105
|
+
this.credentialProvider = "";
|
|
106
|
+
/**
|
|
107
|
+
* User DID from prior auth step
|
|
108
|
+
* Set when redirecting from credential auth → clickwrap page
|
|
109
|
+
* CRITICAL: Bypasses KV eventual consistency issues by passing userDid directly
|
|
110
|
+
*/
|
|
111
|
+
this.userDid = "";
|
|
112
|
+
this.currentMode = modes_types_js_1.AUTH_MODES.CONSENT_ONLY;
|
|
113
|
+
this.loading = false;
|
|
114
|
+
this.step = "consent";
|
|
115
|
+
this.termsAccepted = false;
|
|
116
|
+
this.formData = {};
|
|
117
|
+
this.resendCooldown = 0;
|
|
118
|
+
this.selectedScopes = [];
|
|
119
|
+
}
|
|
120
|
+
// === LIFECYCLE ===
|
|
121
|
+
connectedCallback() {
|
|
122
|
+
super.connectedCallback();
|
|
123
|
+
this.resolved = (0, resolve_config_js_1.resolveConsentConfig)(this.config, this.agentName);
|
|
124
|
+
this.currentMode =
|
|
125
|
+
this.mode ?? (0, resolve_config_js_1.determineAuthMode)(this.config) ?? modes_types_js_1.AUTH_MODES.CONSENT_ONLY;
|
|
126
|
+
// Initialize selected scopes with all requested scopes
|
|
127
|
+
this.selectedScopes = [...this.scopes];
|
|
128
|
+
}
|
|
129
|
+
disconnectedCallback() {
|
|
130
|
+
super.disconnectedCallback();
|
|
131
|
+
// Clean up interval timer to prevent memory leaks
|
|
132
|
+
if (this.resendCooldownInterval !== undefined) {
|
|
133
|
+
clearInterval(this.resendCooldownInterval);
|
|
134
|
+
this.resendCooldownInterval = undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
updated(changedProperties) {
|
|
138
|
+
if (changedProperties.has("config") || changedProperties.has("agentName")) {
|
|
139
|
+
this.resolved = (0, resolve_config_js_1.resolveConsentConfig)(this.config, this.agentName);
|
|
140
|
+
}
|
|
141
|
+
if (changedProperties.has("mode") && this.mode) {
|
|
142
|
+
this.currentMode = this.mode;
|
|
143
|
+
}
|
|
144
|
+
// Update selected scopes when scopes change
|
|
145
|
+
if (changedProperties.has("scopes")) {
|
|
146
|
+
this.selectedScopes = [...this.scopes];
|
|
147
|
+
}
|
|
148
|
+
// Update CSS variables from resolved config
|
|
149
|
+
if (this.resolved) {
|
|
150
|
+
this.style.setProperty("--consent-primary", this.resolved.branding.primaryColor);
|
|
151
|
+
this.style.setProperty("--consent-secondary", this.resolved.branding.secondaryColor);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// === FORM SUBMISSION ===
|
|
155
|
+
/**
|
|
156
|
+
* Get the provider_type based on the current auth mode.
|
|
157
|
+
*
|
|
158
|
+
* Uses the centralized AUTH_MODE_TO_PROVIDER_TYPE mapping from modes.types.ts
|
|
159
|
+
* to ensure type-safety and DRY principle compliance.
|
|
160
|
+
*
|
|
161
|
+
* For OAuth mode, returns the specific provider from oauthIdentity if available.
|
|
162
|
+
*
|
|
163
|
+
* @see getProviderTypeForAuthMode - The canonical mapping function
|
|
164
|
+
*/
|
|
165
|
+
getProviderType() {
|
|
166
|
+
// For OAuth, prefer the specific provider name if available
|
|
167
|
+
if (this.currentMode === modes_types_js_1.AUTH_MODES.OAUTH && this.oauthIdentity?.provider) {
|
|
168
|
+
return this.oauthIdentity.provider;
|
|
169
|
+
}
|
|
170
|
+
// Use the centralized type-safe mapping
|
|
171
|
+
return (0, modes_types_js_1.getProviderTypeForAuthMode)(this.currentMode);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Handle consent approval - TRIGGERS DELEGATIONCREDENTIAL (VC) CREATION
|
|
175
|
+
*
|
|
176
|
+
* This is the critical method where the user's consent is submitted.
|
|
177
|
+
* When this succeeds, a DelegationCredential (W3C Verifiable Credential)
|
|
178
|
+
* is created on the server, authorizing the agent to act on behalf of the user.
|
|
179
|
+
*
|
|
180
|
+
* ## Flow Context
|
|
181
|
+
*
|
|
182
|
+
* This method is called when the user clicks "Approve" on the Consent Screen:
|
|
183
|
+
* - Consent Only: [Consent Screen] → handleApprove() → [Success Screen]
|
|
184
|
+
* - Auth flows: [Auth Screen] → [Consent Screen] → handleApprove() → [Success Screen]
|
|
185
|
+
*
|
|
186
|
+
* In both cases, the VC is created HERE, not during authentication.
|
|
187
|
+
* Authentication only verifies identity; consent grants the delegation.
|
|
188
|
+
*
|
|
189
|
+
* @fires mcp-consent:approve - Emitted when consent is successfully submitted
|
|
190
|
+
* @fires mcp-consent:error - Emitted if consent submission fails
|
|
191
|
+
*/
|
|
192
|
+
async handleApprove(e) {
|
|
193
|
+
e?.preventDefault();
|
|
194
|
+
// Guard against duplicate submissions
|
|
195
|
+
if (this.loading) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!this.termsAccepted && this.resolved?.terms.required) {
|
|
199
|
+
this.error = "Please accept the terms to continue";
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (this.scopes.length > 0 && this.selectedScopes.length === 0) {
|
|
203
|
+
this.error = "Please select at least one permission";
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.loading = true;
|
|
207
|
+
this.error = undefined;
|
|
208
|
+
try {
|
|
209
|
+
// Build consent approval request
|
|
210
|
+
// The server creates the DelegationCredential (VC) when this request succeeds
|
|
211
|
+
const formData = new FormData();
|
|
212
|
+
formData.append("tool", this.tool);
|
|
213
|
+
formData.append("scopes", JSON.stringify(this.selectedScopes));
|
|
214
|
+
formData.append("agent_did", this.agentDid);
|
|
215
|
+
formData.append("session_id", this.sessionId);
|
|
216
|
+
formData.append("project_id", this.projectId);
|
|
217
|
+
formData.append("auth_mode", this.currentMode);
|
|
218
|
+
// Set provider_type based on auth mode to ensure correct server-side routing
|
|
219
|
+
// This is stored in delegation metadata to track what auth method was used
|
|
220
|
+
formData.append("provider_type", this.getProviderType());
|
|
221
|
+
// Include provider for credential auth and OAuth flows - REQUIRED by consent.service.ts validation
|
|
222
|
+
if (this.provider) {
|
|
223
|
+
formData.append("provider", this.provider);
|
|
224
|
+
}
|
|
225
|
+
// Include CSRF token for security - REQUIRED by consent.service.ts for credential auth
|
|
226
|
+
if (this.csrfToken) {
|
|
227
|
+
formData.append("csrf_token", this.csrfToken);
|
|
228
|
+
}
|
|
229
|
+
formData.append("termsAccepted", String(this.termsAccepted));
|
|
230
|
+
// Include credential auth params if present (3-screen flow: Auth → Clickwrap → Success)
|
|
231
|
+
// These are set when redirecting from credential auth page to clickwrap page
|
|
232
|
+
// They ensure the delegation is created with correct authorization.type ('password')
|
|
233
|
+
if (this.credentialProviderType) {
|
|
234
|
+
formData.append("credential_provider_type", this.credentialProviderType);
|
|
235
|
+
}
|
|
236
|
+
if (this.credentialProvider) {
|
|
237
|
+
formData.append("credential_provider", this.credentialProvider);
|
|
238
|
+
}
|
|
239
|
+
// CRITICAL: Pass userDid directly to bypass KV eventual consistency issues
|
|
240
|
+
// Without this, the delegation might be stored with wrong key due to stale KV read
|
|
241
|
+
if (this.userDid) {
|
|
242
|
+
formData.append("user_did", this.userDid);
|
|
243
|
+
}
|
|
244
|
+
// Add custom form data (e.g., username/password for credential auth)
|
|
245
|
+
Object.entries(this.formData).forEach(([key, value]) => {
|
|
246
|
+
formData.append(key, value);
|
|
247
|
+
});
|
|
248
|
+
// Submit consent - server creates DelegationCredential on success
|
|
249
|
+
const response = await fetch(`${this.serverUrl}/consent/approve`, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
body: formData,
|
|
252
|
+
});
|
|
253
|
+
if (!response.ok) {
|
|
254
|
+
const errorData = await response.json().catch(() => ({}));
|
|
255
|
+
throw new Error(errorData.message || "Approval failed");
|
|
256
|
+
}
|
|
257
|
+
const result = await response.json();
|
|
258
|
+
// Check if server wants us to redirect (e.g., credential auth → clickwrap page)
|
|
259
|
+
// This implements the 3-screen flow: Auth → Clickwrap → Success
|
|
260
|
+
if (result.redirectUrl) {
|
|
261
|
+
// Dispatch event before redirect for any listeners that need to know
|
|
262
|
+
this.dispatchEvent(new CustomEvent("mcp-consent:approve", {
|
|
263
|
+
detail: { success: true, redirectUrl: result.redirectUrl },
|
|
264
|
+
bubbles: true,
|
|
265
|
+
composed: true,
|
|
266
|
+
}));
|
|
267
|
+
// Navigate to the redirect URL (clickwrap page after credential/OAuth auth)
|
|
268
|
+
// The clickwrap page will show user info + scopes, then create the delegation
|
|
269
|
+
window.location.href = result.redirectUrl;
|
|
270
|
+
return; // Don't show success yet - the redirect page will handle it
|
|
271
|
+
}
|
|
272
|
+
// No redirect - VC/delegation created successfully, show success screen
|
|
273
|
+
this.step = "success";
|
|
274
|
+
this.dispatchEvent(new CustomEvent("mcp-consent:approve", {
|
|
275
|
+
detail: { success: true, delegationId: result.delegation_id },
|
|
276
|
+
bubbles: true,
|
|
277
|
+
composed: true,
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
this.error = e instanceof Error ? e.message : "Unknown error";
|
|
282
|
+
this.dispatchEvent(new CustomEvent("mcp-consent:error", {
|
|
283
|
+
detail: { error: this.error },
|
|
284
|
+
bubbles: true,
|
|
285
|
+
composed: true,
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
this.loading = false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
handleDeny() {
|
|
293
|
+
this.dispatchEvent(new CustomEvent("mcp-consent:deny", {
|
|
294
|
+
bubbles: true,
|
|
295
|
+
composed: true,
|
|
296
|
+
}));
|
|
297
|
+
// Try to close the window/tab
|
|
298
|
+
window.close();
|
|
299
|
+
}
|
|
300
|
+
handleTermsChange(e) {
|
|
301
|
+
this.termsAccepted = e.detail.checked;
|
|
302
|
+
}
|
|
303
|
+
handleInputChange(name, value) {
|
|
304
|
+
this.formData = { ...this.formData, [name]: value };
|
|
305
|
+
}
|
|
306
|
+
handleResendOtp() {
|
|
307
|
+
if (this.resendCooldown > 0) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const cooldownSeconds = this.resolved?.otp?.resendCooldown ?? 60;
|
|
311
|
+
this.resendCooldown = cooldownSeconds;
|
|
312
|
+
// Clear any existing interval before starting a new one
|
|
313
|
+
if (this.resendCooldownInterval !== undefined) {
|
|
314
|
+
clearInterval(this.resendCooldownInterval);
|
|
315
|
+
}
|
|
316
|
+
// Start countdown timer (stored in class property for cleanup)
|
|
317
|
+
this.resendCooldownInterval = setInterval(() => {
|
|
318
|
+
this.resendCooldown--;
|
|
319
|
+
if (this.resendCooldown <= 0) {
|
|
320
|
+
clearInterval(this.resendCooldownInterval);
|
|
321
|
+
this.resendCooldownInterval = undefined;
|
|
322
|
+
}
|
|
323
|
+
}, 1000);
|
|
324
|
+
// Dispatch event for parent to handle actual resend
|
|
325
|
+
this.dispatchEvent(new CustomEvent("mcp-consent:resend-otp", {
|
|
326
|
+
bubbles: true,
|
|
327
|
+
composed: true,
|
|
328
|
+
}));
|
|
329
|
+
}
|
|
330
|
+
// === RENDER METHODS ===
|
|
331
|
+
renderAgentInfo() {
|
|
332
|
+
const agentDisplay = this.agentName || "this agent";
|
|
333
|
+
return (0, lit_1.html) `
|
|
334
|
+
<div class="agent-info">
|
|
335
|
+
<div class="agent-icon">
|
|
336
|
+
<svg
|
|
337
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
338
|
+
viewBox="0 0 24 24"
|
|
339
|
+
fill="none"
|
|
340
|
+
stroke="currentColor"
|
|
341
|
+
stroke-width="2"
|
|
342
|
+
>
|
|
343
|
+
<circle cx="12" cy="12" r="10" />
|
|
344
|
+
<path d="M12 16v-4M12 8h.01" />
|
|
345
|
+
</svg>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="agent-text">
|
|
348
|
+
<p>
|
|
349
|
+
<strong>${agentDisplay}</strong> is requesting permission to
|
|
350
|
+
${this.tool
|
|
351
|
+
? (0, lit_1.html) `use the <strong>${this.tool}</strong> tool`
|
|
352
|
+
: "access your data"}
|
|
353
|
+
on your behalf.
|
|
354
|
+
</p>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
handlePermissionsChange(e) {
|
|
360
|
+
this.selectedScopes = e.detail.selected;
|
|
361
|
+
}
|
|
362
|
+
renderPermissions() {
|
|
363
|
+
if (this.scopes.length === 0)
|
|
364
|
+
return lit_1.nothing;
|
|
365
|
+
return (0, lit_1.html) `
|
|
366
|
+
<p class="permissions-header">
|
|
367
|
+
${this.resolved?.ui.permissionsHeader ??
|
|
368
|
+
"The agent is requesting the following permissions:"}
|
|
369
|
+
</p>
|
|
370
|
+
<div class="permissions">
|
|
371
|
+
<consent-permissions
|
|
372
|
+
.scopes=${this.scopes}
|
|
373
|
+
interactive
|
|
374
|
+
select-all
|
|
375
|
+
@change=${this.handlePermissionsChange}
|
|
376
|
+
></consent-permissions>
|
|
377
|
+
</div>
|
|
378
|
+
`;
|
|
379
|
+
}
|
|
380
|
+
renderExpiration() {
|
|
381
|
+
const days = this.resolved?.expirationDays ?? 7;
|
|
382
|
+
return (0, lit_1.html) `
|
|
383
|
+
<p class="expiration">
|
|
384
|
+
${this.resolved?.ui.expirationText ?? "This delegation will expire in"}
|
|
385
|
+
<strong>${days} ${days === 1 ? "day" : "days"}</strong>
|
|
386
|
+
</p>
|
|
387
|
+
`;
|
|
388
|
+
}
|
|
389
|
+
renderTerms() {
|
|
390
|
+
if (!this.resolved?.terms)
|
|
391
|
+
return lit_1.nothing;
|
|
392
|
+
return (0, lit_1.html) `
|
|
393
|
+
<div class="terms">
|
|
394
|
+
<consent-terms
|
|
395
|
+
name="termsAccepted"
|
|
396
|
+
text=${this.resolved.terms.text}
|
|
397
|
+
url=${this.resolved.terms.url ?? ""}
|
|
398
|
+
?required=${this.resolved.terms.required}
|
|
399
|
+
@change=${this.handleTermsChange}
|
|
400
|
+
></consent-terms>
|
|
401
|
+
</div>
|
|
402
|
+
`;
|
|
403
|
+
}
|
|
404
|
+
renderError() {
|
|
405
|
+
if (!this.error)
|
|
406
|
+
return lit_1.nothing;
|
|
407
|
+
return (0, lit_1.html) `<div class="error-message">${this.error}</div>`;
|
|
408
|
+
}
|
|
409
|
+
renderFooter() {
|
|
410
|
+
return (0, lit_1.html) `
|
|
411
|
+
<div slot="footer">
|
|
412
|
+
<consent-button variant="secondary" @click=${this.handleDeny}>
|
|
413
|
+
${this.resolved?.ui.cancelButtonText ?? "Cancel"}
|
|
414
|
+
</consent-button>
|
|
415
|
+
<consent-button
|
|
416
|
+
variant="primary"
|
|
417
|
+
?loading=${this.loading}
|
|
418
|
+
?disabled=${this.resolved?.terms.required && !this.termsAccepted}
|
|
419
|
+
@click=${this.handleApprove}
|
|
420
|
+
>
|
|
421
|
+
${this.resolved?.ui.submitButtonText ?? "Allow access"}
|
|
422
|
+
</consent-button>
|
|
423
|
+
</div>
|
|
424
|
+
`;
|
|
425
|
+
}
|
|
426
|
+
// === MODE-SPECIFIC RENDERS ===
|
|
427
|
+
renderConsentOnly() {
|
|
428
|
+
return (0, lit_1.html) `
|
|
429
|
+
<consent-shell
|
|
430
|
+
page-title=${this.resolved?.ui.title ?? "Permission Request"}
|
|
431
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
432
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
433
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
434
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
435
|
+
>
|
|
436
|
+
<div slot="content">
|
|
437
|
+
${this.renderError()} ${this.renderAgentInfo()}
|
|
438
|
+
${this.renderPermissions()} ${this.renderExpiration()}
|
|
439
|
+
${this.renderTerms()}
|
|
440
|
+
</div>
|
|
441
|
+
${this.renderFooter()}
|
|
442
|
+
</consent-shell>
|
|
443
|
+
`;
|
|
444
|
+
}
|
|
445
|
+
renderCredentials() {
|
|
446
|
+
const creds = this.resolved?.credentials;
|
|
447
|
+
return (0, lit_1.html) `
|
|
448
|
+
<consent-shell
|
|
449
|
+
page-title=${this.resolved?.ui.title ?? "Sign In"}
|
|
450
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
451
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
452
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
453
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
454
|
+
>
|
|
455
|
+
<div slot="content">
|
|
456
|
+
${this.renderError()} ${this.renderAgentInfo()}
|
|
457
|
+
|
|
458
|
+
<div class="form-fields">
|
|
459
|
+
<consent-input
|
|
460
|
+
type="text"
|
|
461
|
+
name="username"
|
|
462
|
+
label=${creds?.usernameLabel ?? "Username"}
|
|
463
|
+
placeholder=${creds?.usernamePlaceholder ?? "Enter your username"}
|
|
464
|
+
autocomplete="username"
|
|
465
|
+
required
|
|
466
|
+
@input=${(e) => {
|
|
467
|
+
// Handle both CustomEvent (from consent-input) and native InputEvent
|
|
468
|
+
const customEvent = e;
|
|
469
|
+
const value = customEvent.detail?.value ??
|
|
470
|
+
e.target?.value ??
|
|
471
|
+
"";
|
|
472
|
+
this.handleInputChange("username", value);
|
|
473
|
+
}}
|
|
474
|
+
></consent-input>
|
|
475
|
+
|
|
476
|
+
<consent-input
|
|
477
|
+
type="password"
|
|
478
|
+
name="password"
|
|
479
|
+
label=${creds?.passwordLabel ?? "Password"}
|
|
480
|
+
placeholder=${creds?.passwordPlaceholder ?? "Enter your password"}
|
|
481
|
+
autocomplete="current-password"
|
|
482
|
+
required
|
|
483
|
+
@input=${(e) => {
|
|
484
|
+
// Handle both CustomEvent (from consent-input) and native InputEvent
|
|
485
|
+
const customEvent = e;
|
|
486
|
+
const value = customEvent.detail?.value ??
|
|
487
|
+
e.target?.value ??
|
|
488
|
+
"";
|
|
489
|
+
this.handleInputChange("password", value);
|
|
490
|
+
}}
|
|
491
|
+
></consent-input>
|
|
492
|
+
</div>
|
|
493
|
+
|
|
494
|
+
${creds?.showForgotPassword && creds.forgotPasswordUrl
|
|
495
|
+
? (0, lit_1.html) `
|
|
496
|
+
<p style="text-align: right; margin-bottom: 1rem;">
|
|
497
|
+
<a
|
|
498
|
+
href=${creds.forgotPasswordUrl}
|
|
499
|
+
style="font-size: 0.75rem; color: var(--_primary);"
|
|
500
|
+
>
|
|
501
|
+
Forgot password?
|
|
502
|
+
</a>
|
|
503
|
+
</p>
|
|
504
|
+
`
|
|
505
|
+
: lit_1.nothing}
|
|
506
|
+
${this.renderPermissions()} ${this.renderExpiration()}
|
|
507
|
+
${this.renderTerms()}
|
|
508
|
+
</div>
|
|
509
|
+
${this.renderFooter()}
|
|
510
|
+
</consent-shell>
|
|
511
|
+
`;
|
|
512
|
+
}
|
|
513
|
+
renderOAuth() {
|
|
514
|
+
const oauth = this.resolved?.oauth;
|
|
515
|
+
const provider = oauth?.providerId ?? "oauth";
|
|
516
|
+
const providerName = oauth?.providerName ?? "OAuth Provider";
|
|
517
|
+
return (0, lit_1.html) `
|
|
518
|
+
<consent-shell
|
|
519
|
+
page-title=${this.resolved?.ui.title ?? "Sign In"}
|
|
520
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
521
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
522
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
523
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
524
|
+
>
|
|
525
|
+
<div slot="content">
|
|
526
|
+
${this.renderError()} ${this.renderAgentInfo()}
|
|
527
|
+
|
|
528
|
+
<consent-oauth-button
|
|
529
|
+
provider=${provider}
|
|
530
|
+
provider-name=${providerName}
|
|
531
|
+
url=${`${this.serverUrl}/oauth/${encodeURIComponent(provider)}?session_id=${encodeURIComponent(this.sessionId)}`}
|
|
532
|
+
button-text=${oauth?.buttonText ?? `Continue with ${providerName}`}
|
|
533
|
+
full-width
|
|
534
|
+
></consent-oauth-button>
|
|
535
|
+
|
|
536
|
+
${this.renderPermissions()}
|
|
537
|
+
|
|
538
|
+
<div class="divider">or</div>
|
|
539
|
+
|
|
540
|
+
${this.renderExpiration()} ${this.renderTerms()}
|
|
541
|
+
</div>
|
|
542
|
+
${this.renderFooter()}
|
|
543
|
+
</consent-shell>
|
|
544
|
+
`;
|
|
545
|
+
}
|
|
546
|
+
renderMagicLink() {
|
|
547
|
+
const ml = this.resolved?.magicLink;
|
|
548
|
+
return (0, lit_1.html) `
|
|
549
|
+
<consent-shell
|
|
550
|
+
page-title=${this.resolved?.ui.title ?? "Sign In"}
|
|
551
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
552
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
553
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
554
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
555
|
+
>
|
|
556
|
+
<div slot="content">
|
|
557
|
+
${this.renderError()} ${this.renderAgentInfo()}
|
|
558
|
+
|
|
559
|
+
<div class="form-fields">
|
|
560
|
+
<consent-input
|
|
561
|
+
type="email"
|
|
562
|
+
name="email"
|
|
563
|
+
label=${ml?.emailLabel ?? "Email"}
|
|
564
|
+
placeholder=${ml?.emailPlaceholder ?? "Enter your email address"}
|
|
565
|
+
autocomplete="email"
|
|
566
|
+
required
|
|
567
|
+
@input=${(e) => {
|
|
568
|
+
// Handle both CustomEvent (from consent-input) and native InputEvent
|
|
569
|
+
const customEvent = e;
|
|
570
|
+
const value = customEvent.detail?.value ??
|
|
571
|
+
e.target?.value ??
|
|
572
|
+
"";
|
|
573
|
+
this.handleInputChange("email", value);
|
|
574
|
+
}}
|
|
575
|
+
></consent-input>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
${this.renderPermissions()} ${this.renderExpiration()}
|
|
579
|
+
${this.renderTerms()}
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
<div slot="footer">
|
|
583
|
+
<consent-button variant="secondary" @click=${this.handleDeny}>
|
|
584
|
+
Cancel
|
|
585
|
+
</consent-button>
|
|
586
|
+
<consent-button
|
|
587
|
+
variant="primary"
|
|
588
|
+
?loading=${this.loading}
|
|
589
|
+
?disabled=${this.resolved?.terms.required && !this.termsAccepted}
|
|
590
|
+
@click=${this.handleApprove}
|
|
591
|
+
>
|
|
592
|
+
${ml?.buttonText ?? "Send magic link"}
|
|
593
|
+
</consent-button>
|
|
594
|
+
</div>
|
|
595
|
+
</consent-shell>
|
|
596
|
+
`;
|
|
597
|
+
}
|
|
598
|
+
renderOTP() {
|
|
599
|
+
const otp = this.resolved?.otp;
|
|
600
|
+
return (0, lit_1.html) `
|
|
601
|
+
<consent-shell
|
|
602
|
+
page-title=${this.resolved?.ui.title ?? "Verify Code"}
|
|
603
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
604
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
605
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
606
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
607
|
+
>
|
|
608
|
+
<div slot="content">
|
|
609
|
+
${this.renderError()} ${this.renderAgentInfo()}
|
|
610
|
+
|
|
611
|
+
<div class="otp-section">
|
|
612
|
+
<p class="otp-instructions">
|
|
613
|
+
${otp?.instructions ??
|
|
614
|
+
"Enter the verification code sent to your device"}
|
|
615
|
+
</p>
|
|
616
|
+
<consent-otp-input
|
|
617
|
+
length=${otp?.digits ?? 6}
|
|
618
|
+
name="otp"
|
|
619
|
+
auto-focus
|
|
620
|
+
@complete=${(e) => {
|
|
621
|
+
const customEvent = e;
|
|
622
|
+
const value = customEvent.detail?.value ?? "";
|
|
623
|
+
this.handleInputChange("otp", value);
|
|
624
|
+
this.handleApprove();
|
|
625
|
+
}}
|
|
626
|
+
@input=${(e) => {
|
|
627
|
+
const customEvent = e;
|
|
628
|
+
const value = customEvent.detail?.value ?? "";
|
|
629
|
+
this.handleInputChange("otp", value);
|
|
630
|
+
}}
|
|
631
|
+
></consent-otp-input>
|
|
632
|
+
<div class="otp-resend">
|
|
633
|
+
Didn't receive the code?
|
|
634
|
+
<button
|
|
635
|
+
type="button"
|
|
636
|
+
?disabled=${this.resendCooldown > 0}
|
|
637
|
+
@click=${this.handleResendOtp}
|
|
638
|
+
>
|
|
639
|
+
${this.resendCooldown > 0
|
|
640
|
+
? `Resend in ${this.resendCooldown}s`
|
|
641
|
+
: "Resend"}
|
|
642
|
+
</button>
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
${this.renderPermissions()} ${this.renderTerms()}
|
|
647
|
+
</div>
|
|
648
|
+
${this.renderFooter()}
|
|
649
|
+
</consent-shell>
|
|
650
|
+
`;
|
|
651
|
+
}
|
|
652
|
+
renderSuccess() {
|
|
653
|
+
const success = this.resolved?.success;
|
|
654
|
+
return (0, lit_1.html) `
|
|
655
|
+
<consent-shell
|
|
656
|
+
page-title=${success?.title ?? "Access Granted"}
|
|
657
|
+
company-name=${this.resolved?.branding.companyName ?? ""}
|
|
658
|
+
logo-url=${this.resolved?.branding.logoUrl ?? ""}
|
|
659
|
+
primary-color=${this.resolved?.branding.primaryColor ?? "#2563eb"}
|
|
660
|
+
secondary-color=${this.resolved?.branding.secondaryColor ?? "#dbeafe"}
|
|
661
|
+
>
|
|
662
|
+
<div slot="content">
|
|
663
|
+
<div class="success-view">
|
|
664
|
+
<div class="success-icon">
|
|
665
|
+
<svg
|
|
666
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
667
|
+
viewBox="0 0 24 24"
|
|
668
|
+
fill="none"
|
|
669
|
+
stroke="currentColor"
|
|
670
|
+
stroke-width="2"
|
|
671
|
+
>
|
|
672
|
+
<polyline points="20 6 9 17 4 12" />
|
|
673
|
+
</svg>
|
|
674
|
+
</div>
|
|
675
|
+
<h2 class="success-title">${success?.title ?? "Access Granted"}</h2>
|
|
676
|
+
<p class="success-description">
|
|
677
|
+
${success?.description ??
|
|
678
|
+
"You have successfully granted access. You can now close this window."}
|
|
679
|
+
</p>
|
|
680
|
+
</div>
|
|
681
|
+
</div>
|
|
682
|
+
|
|
683
|
+
<div slot="footer">
|
|
684
|
+
<consent-button
|
|
685
|
+
variant="primary"
|
|
686
|
+
full-width
|
|
687
|
+
@click=${() => window.close()}
|
|
688
|
+
>
|
|
689
|
+
${success?.continueButtonText ?? "Close"}
|
|
690
|
+
</consent-button>
|
|
691
|
+
</div>
|
|
692
|
+
</consent-shell>
|
|
693
|
+
`;
|
|
694
|
+
}
|
|
695
|
+
// === MAIN RENDER ===
|
|
696
|
+
render() {
|
|
697
|
+
// Use previewStep if provided (for WYSIWYG editor), otherwise fall back to internal step
|
|
698
|
+
const displayStep = this.previewStep ?? this.step;
|
|
699
|
+
if (displayStep === "success") {
|
|
700
|
+
return this.renderSuccess();
|
|
701
|
+
}
|
|
702
|
+
// For "consent" previewStep or normal flow, render based on auth mode
|
|
703
|
+
switch (this.currentMode) {
|
|
704
|
+
case modes_types_js_1.AUTH_MODES.CREDENTIALS:
|
|
705
|
+
return this.renderCredentials();
|
|
706
|
+
case modes_types_js_1.AUTH_MODES.OAUTH:
|
|
707
|
+
return this.renderOAuth();
|
|
708
|
+
case modes_types_js_1.AUTH_MODES.MAGIC_LINK:
|
|
709
|
+
return this.renderMagicLink();
|
|
710
|
+
case modes_types_js_1.AUTH_MODES.OTP:
|
|
711
|
+
return this.renderOTP();
|
|
712
|
+
case modes_types_js_1.AUTH_MODES.CONSENT_ONLY:
|
|
713
|
+
default:
|
|
714
|
+
return this.renderConsentOnly();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
exports.McpConsent = McpConsent;
|
|
719
|
+
McpConsent.styles = (0, lit_1.css) `
|
|
720
|
+
:host {
|
|
721
|
+
display: block;
|
|
722
|
+
/* System font stack with font smoothing for crisp text */
|
|
723
|
+
font-family:
|
|
724
|
+
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
|
725
|
+
Arial, sans-serif;
|
|
726
|
+
-webkit-font-smoothing: antialiased;
|
|
727
|
+
-moz-osx-font-smoothing: grayscale;
|
|
728
|
+
--_primary: var(--consent-primary, #2563eb);
|
|
729
|
+
--_secondary: var(--consent-secondary, #dbeafe);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* Agent info box */
|
|
733
|
+
.agent-info {
|
|
734
|
+
display: flex;
|
|
735
|
+
gap: 1rem;
|
|
736
|
+
padding: 1rem;
|
|
737
|
+
background: #f9fafb;
|
|
738
|
+
border-radius: 0.5rem;
|
|
739
|
+
margin-bottom: 1rem;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.agent-icon {
|
|
743
|
+
width: 40px;
|
|
744
|
+
height: 40px;
|
|
745
|
+
background: var(--_secondary);
|
|
746
|
+
border-radius: 0.5rem;
|
|
747
|
+
display: flex;
|
|
748
|
+
align-items: center;
|
|
749
|
+
justify-content: center;
|
|
750
|
+
flex-shrink: 0;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.agent-icon svg {
|
|
754
|
+
width: 20px;
|
|
755
|
+
height: 20px;
|
|
756
|
+
color: var(--_primary);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
.agent-text {
|
|
760
|
+
flex: 1;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.agent-text p {
|
|
764
|
+
margin: 0;
|
|
765
|
+
font-size: 0.875rem;
|
|
766
|
+
color: #374151;
|
|
767
|
+
line-height: 1.5;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.agent-text strong {
|
|
771
|
+
color: #111827;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/* Permissions section */
|
|
775
|
+
.permissions-header {
|
|
776
|
+
font-size: 0.875rem;
|
|
777
|
+
color: #6b7280;
|
|
778
|
+
margin-bottom: 0.5rem;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
.permissions {
|
|
782
|
+
margin-bottom: 1rem;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/* Expiration */
|
|
786
|
+
.expiration {
|
|
787
|
+
font-size: 0.75rem;
|
|
788
|
+
color: #6b7280;
|
|
789
|
+
margin-top: 1rem;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.expiration strong {
|
|
793
|
+
color: #374151;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/* Terms */
|
|
797
|
+
.terms {
|
|
798
|
+
margin-top: 1.5rem;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/* Error message */
|
|
802
|
+
.error-message {
|
|
803
|
+
background: #fef2f2;
|
|
804
|
+
border: 1px solid #fecaca;
|
|
805
|
+
border-radius: 0.5rem;
|
|
806
|
+
padding: 0.75rem 1rem;
|
|
807
|
+
margin-bottom: 1rem;
|
|
808
|
+
color: #dc2626;
|
|
809
|
+
font-size: 0.875rem;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/* Form fields */
|
|
813
|
+
.form-fields {
|
|
814
|
+
display: flex;
|
|
815
|
+
flex-direction: column;
|
|
816
|
+
gap: 1rem;
|
|
817
|
+
margin-bottom: 1rem;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/* Divider */
|
|
821
|
+
.divider {
|
|
822
|
+
display: flex;
|
|
823
|
+
align-items: center;
|
|
824
|
+
gap: 1rem;
|
|
825
|
+
margin: 1.5rem 0;
|
|
826
|
+
color: #6b7280;
|
|
827
|
+
font-size: 0.75rem;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
.divider::before,
|
|
831
|
+
.divider::after {
|
|
832
|
+
content: "";
|
|
833
|
+
flex: 1;
|
|
834
|
+
height: 1px;
|
|
835
|
+
background: #e5e7eb;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/* Success view */
|
|
839
|
+
.success-view {
|
|
840
|
+
text-align: center;
|
|
841
|
+
padding: 2rem 0;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
.success-icon {
|
|
845
|
+
width: 64px;
|
|
846
|
+
height: 64px;
|
|
847
|
+
background: #d1fae5;
|
|
848
|
+
border-radius: 50%;
|
|
849
|
+
display: flex;
|
|
850
|
+
align-items: center;
|
|
851
|
+
justify-content: center;
|
|
852
|
+
margin: 0 auto 1.5rem;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
.success-icon svg {
|
|
856
|
+
width: 32px;
|
|
857
|
+
height: 32px;
|
|
858
|
+
color: #059669;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.success-title {
|
|
862
|
+
font-size: 1.25rem;
|
|
863
|
+
font-weight: 600;
|
|
864
|
+
color: #111827;
|
|
865
|
+
margin: 0 0 0.5rem;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.success-description {
|
|
869
|
+
font-size: 0.875rem;
|
|
870
|
+
color: #6b7280;
|
|
871
|
+
margin: 0 0 1.5rem;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/* OTP section */
|
|
875
|
+
.otp-section {
|
|
876
|
+
text-align: center;
|
|
877
|
+
margin-bottom: 1.5rem;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.otp-instructions {
|
|
881
|
+
font-size: 0.875rem;
|
|
882
|
+
color: #6b7280;
|
|
883
|
+
margin-bottom: 1rem;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.otp-resend {
|
|
887
|
+
margin-top: 1rem;
|
|
888
|
+
font-size: 0.75rem;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.otp-resend button {
|
|
892
|
+
background: none;
|
|
893
|
+
border: none;
|
|
894
|
+
color: var(--_primary);
|
|
895
|
+
cursor: pointer;
|
|
896
|
+
text-decoration: underline;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.otp-resend button:disabled {
|
|
900
|
+
color: #9ca3af;
|
|
901
|
+
cursor: not-allowed;
|
|
902
|
+
}
|
|
903
|
+
`;
|
|
904
|
+
__decorate([
|
|
905
|
+
(0, decorators_js_1.property)({
|
|
906
|
+
type: Object,
|
|
907
|
+
converter: {
|
|
908
|
+
fromAttribute: (value) => {
|
|
909
|
+
if (!value)
|
|
910
|
+
return undefined;
|
|
911
|
+
try {
|
|
912
|
+
return JSON.parse(value);
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
return undefined;
|
|
916
|
+
}
|
|
917
|
+
},
|
|
918
|
+
toAttribute: (value) => {
|
|
919
|
+
return value ? JSON.stringify(value) : "";
|
|
920
|
+
},
|
|
921
|
+
},
|
|
922
|
+
})
|
|
923
|
+
], McpConsent.prototype, "config", void 0);
|
|
924
|
+
__decorate([
|
|
925
|
+
(0, decorators_js_1.property)({ type: String })
|
|
926
|
+
], McpConsent.prototype, "mode", void 0);
|
|
927
|
+
__decorate([
|
|
928
|
+
(0, decorators_js_1.property)({ type: String })
|
|
929
|
+
], McpConsent.prototype, "tool", void 0);
|
|
930
|
+
__decorate([
|
|
931
|
+
(0, decorators_js_1.property)({
|
|
932
|
+
type: Array,
|
|
933
|
+
converter: {
|
|
934
|
+
fromAttribute: (value) => {
|
|
935
|
+
if (!value)
|
|
936
|
+
return [];
|
|
937
|
+
try {
|
|
938
|
+
return JSON.parse(value);
|
|
939
|
+
}
|
|
940
|
+
catch {
|
|
941
|
+
return [];
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
toAttribute: (value) => {
|
|
945
|
+
return JSON.stringify(value);
|
|
946
|
+
},
|
|
947
|
+
},
|
|
948
|
+
})
|
|
949
|
+
], McpConsent.prototype, "scopes", void 0);
|
|
950
|
+
__decorate([
|
|
951
|
+
(0, decorators_js_1.property)({ type: String, attribute: "agent-did" })
|
|
952
|
+
], McpConsent.prototype, "agentDid", void 0);
|
|
953
|
+
__decorate([
|
|
954
|
+
(0, decorators_js_1.property)({ type: String, attribute: "session-id" })
|
|
955
|
+
], McpConsent.prototype, "sessionId", void 0);
|
|
956
|
+
__decorate([
|
|
957
|
+
(0, decorators_js_1.property)({ type: String, attribute: "project-id" })
|
|
958
|
+
], McpConsent.prototype, "projectId", void 0);
|
|
959
|
+
__decorate([
|
|
960
|
+
(0, decorators_js_1.property)({ type: String, attribute: "server-url" })
|
|
961
|
+
], McpConsent.prototype, "serverUrl", void 0);
|
|
962
|
+
__decorate([
|
|
963
|
+
(0, decorators_js_1.property)({ type: String, attribute: "agent-name" })
|
|
964
|
+
], McpConsent.prototype, "agentName", void 0);
|
|
965
|
+
__decorate([
|
|
966
|
+
(0, decorators_js_1.property)({ type: String, attribute: "provider" })
|
|
967
|
+
], McpConsent.prototype, "provider", void 0);
|
|
968
|
+
__decorate([
|
|
969
|
+
(0, decorators_js_1.property)({ type: String, attribute: "csrf-token" })
|
|
970
|
+
], McpConsent.prototype, "csrfToken", void 0);
|
|
971
|
+
__decorate([
|
|
972
|
+
(0, decorators_js_1.property)({ type: String, attribute: "preview-step" })
|
|
973
|
+
], McpConsent.prototype, "previewStep", void 0);
|
|
974
|
+
__decorate([
|
|
975
|
+
(0, decorators_js_1.property)({ type: String, attribute: "credential-provider-type" })
|
|
976
|
+
], McpConsent.prototype, "credentialProviderType", void 0);
|
|
977
|
+
__decorate([
|
|
978
|
+
(0, decorators_js_1.property)({ type: String, attribute: "credential-provider" })
|
|
979
|
+
], McpConsent.prototype, "credentialProvider", void 0);
|
|
980
|
+
__decorate([
|
|
981
|
+
(0, decorators_js_1.property)({ type: String, attribute: "user-did" })
|
|
982
|
+
], McpConsent.prototype, "userDid", void 0);
|
|
983
|
+
__decorate([
|
|
984
|
+
(0, decorators_js_1.property)({
|
|
985
|
+
type: Object,
|
|
986
|
+
attribute: "oauth-identity",
|
|
987
|
+
converter: {
|
|
988
|
+
fromAttribute: (value) => {
|
|
989
|
+
if (!value)
|
|
990
|
+
return undefined;
|
|
991
|
+
try {
|
|
992
|
+
return JSON.parse(value);
|
|
993
|
+
}
|
|
994
|
+
catch {
|
|
995
|
+
return undefined;
|
|
996
|
+
}
|
|
997
|
+
},
|
|
998
|
+
toAttribute: (value) => {
|
|
999
|
+
return value ? JSON.stringify(value) : "";
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
})
|
|
1003
|
+
], McpConsent.prototype, "oauthIdentity", void 0);
|
|
1004
|
+
__decorate([
|
|
1005
|
+
(0, decorators_js_1.state)()
|
|
1006
|
+
], McpConsent.prototype, "resolved", void 0);
|
|
1007
|
+
__decorate([
|
|
1008
|
+
(0, decorators_js_1.state)()
|
|
1009
|
+
], McpConsent.prototype, "currentMode", void 0);
|
|
1010
|
+
__decorate([
|
|
1011
|
+
(0, decorators_js_1.state)()
|
|
1012
|
+
], McpConsent.prototype, "loading", void 0);
|
|
1013
|
+
__decorate([
|
|
1014
|
+
(0, decorators_js_1.state)()
|
|
1015
|
+
], McpConsent.prototype, "error", void 0);
|
|
1016
|
+
__decorate([
|
|
1017
|
+
(0, decorators_js_1.state)()
|
|
1018
|
+
], McpConsent.prototype, "step", void 0);
|
|
1019
|
+
__decorate([
|
|
1020
|
+
(0, decorators_js_1.state)()
|
|
1021
|
+
], McpConsent.prototype, "termsAccepted", void 0);
|
|
1022
|
+
__decorate([
|
|
1023
|
+
(0, decorators_js_1.state)()
|
|
1024
|
+
], McpConsent.prototype, "formData", void 0);
|
|
1025
|
+
__decorate([
|
|
1026
|
+
(0, decorators_js_1.state)()
|
|
1027
|
+
], McpConsent.prototype, "resendCooldown", void 0);
|
|
1028
|
+
__decorate([
|
|
1029
|
+
(0, decorators_js_1.state)()
|
|
1030
|
+
], McpConsent.prototype, "selectedScopes", void 0);
|
|
1031
|
+
exports.McpConsent = McpConsent = __decorate([
|
|
1032
|
+
(0, decorators_js_1.customElement)("mcp-consent")
|
|
1033
|
+
], McpConsent);
|
|
1034
|
+
//# sourceMappingURL=mcp-consent.js.map
|