@kya-os/create-mcpi-app 1.10.3 → 1.10.5

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.
@@ -45834,6 +45834,18 @@ var require_oauth_config_service = __commonJS({
45834
45834
  Object.defineProperty(exports, "__esModule", { value: true });
45835
45835
  exports.OAuthConfigService = void 0;
45836
45836
  var oauth_config_cache_js_1 = require_oauth_config_cache();
45837
+ function mapProviderSecretMetadata(raw2) {
45838
+ if (!raw2 || typeof raw2 !== "object")
45839
+ return void 0;
45840
+ const m3 = raw2;
45841
+ const metadata = {
45842
+ clientSecretName: m3.clientSecretName ?? m3.client_secret_name,
45843
+ clientIdSecretName: m3.clientIdSecretName ?? m3.client_id_secret_name,
45844
+ apiKeySecretName: m3.apiKeySecretName ?? m3.api_key_secret_name,
45845
+ clientSecretVersion: m3.clientSecretVersion ?? m3.client_secret_version
45846
+ };
45847
+ return metadata;
45848
+ }
45837
45849
  var OAuthConfigService2 = class {
45838
45850
  config;
45839
45851
  constructor(config4) {
@@ -45907,7 +45919,16 @@ var require_oauth_config_service = __commonJS({
45907
45919
  customParams: p3.customParams ?? p3.custom_params,
45908
45920
  tokenEndpointAuthMethod: p3.tokenEndpointAuthMethod ?? p3.token_endpoint_auth_method,
45909
45921
  responseType: p3.responseType ?? p3.response_type,
45910
- grantType: p3.grantType ?? p3.grant_type
45922
+ grantType: p3.grantType ?? p3.grant_type,
45923
+ // Provider-registry secret metadata (clientSecretName etc.). REQUIRED:
45924
+ // OAuthService.resolveClientSecret resolves a confidential provider's
45925
+ // client secret from secure storage via `metadata.clientSecretName`
45926
+ // (the AgentShield /providers response intentionally omits the plaintext
45927
+ // `clientSecret`). Without mapping this field here, `metadata` is
45928
+ // undefined, resolveClientSecret falls back to the (absent) inline
45929
+ // clientSecret, and the worker sends an empty secret — token exchange
45930
+ // then fails with "client_id and/or client_secret incorrect".
45931
+ metadata: mapProviderSecretMetadata(p3.metadata)
45911
45932
  };
45912
45933
  }
45913
45934
  const configuredProvider = result.data.configuredProvider ?? result.data.configured_provider ?? null;
@@ -141691,7 +141712,7 @@ async function handlePickupInternal(ctx, request, now2) {
141691
141712
  // ../mcp-i-cloudflare/package.json
141692
141713
  var package_default = {
141693
141714
  name: "@kya-os/mcp-i-cloudflare",
141694
- version: "1.12.1",
141715
+ version: "1.12.3",
141695
141716
  description: "Cloudflare Workers adapter for MCP-I framework",
141696
141717
  main: "dist/index.js",
141697
141718
  types: "dist/index.d.ts",
@@ -141720,9 +141741,9 @@ var package_default = {
141720
141741
  },
141721
141742
  dependencies: {
141722
141743
  "@kya-os/consent": "^0.1.41",
141723
- "@kya-os/contracts": "^1.9.0",
141744
+ "@kya-os/contracts": "^1.9.2",
141724
141745
  "@kya-os/mcp": "^1.10.1",
141725
- "@kya-os/mcp-i-core": "^1.8.1",
141746
+ "@kya-os/mcp-i-core": "^1.8.3",
141726
141747
  "@kya-os/mcp-i-runtime": "^1.0.0",
141727
141748
  "@kya-os/provider-registry": "^0.1.7",
141728
141749
  "@modelcontextprotocol/sdk": "^1.25.2",
@@ -147427,6 +147448,215 @@ async function handlePickupGet(c, env2, cfg) {
147427
147448
  init_dist2();
147428
147449
  init_crypto();
147429
147450
  init_storage();
147451
+
147452
+ // ../mcp-i-cloudflare/dist/delegation-http/credential-consent.js
147453
+ function readString(entry, camel, snake) {
147454
+ const value = entry[camel] ?? entry[snake];
147455
+ return typeof value === "string" ? value : void 0;
147456
+ }
147457
+ function readRecord(entry, camel, snake) {
147458
+ const value = entry[camel] ?? entry[snake];
147459
+ return value && typeof value === "object" ? value : void 0;
147460
+ }
147461
+ function isCredentialTyped(entry) {
147462
+ return !!entry && (entry.type === "password" || entry.type === "credential") && entry.configured !== false;
147463
+ }
147464
+ function buildSuccessCheck(raw2) {
147465
+ if (!raw2)
147466
+ return void 0;
147467
+ const path = typeof raw2.path === "string" ? raw2.path : void 0;
147468
+ const expectedValue = raw2.expectedValue ?? raw2.expected_value;
147469
+ if (!path || expectedValue === void 0)
147470
+ return void 0;
147471
+ if (typeof expectedValue !== "string" && typeof expectedValue !== "boolean" && typeof expectedValue !== "number") {
147472
+ return void 0;
147473
+ }
147474
+ return { path, expectedValue };
147475
+ }
147476
+ function buildConsentOverrides(raw2) {
147477
+ if (!raw2)
147478
+ return void 0;
147479
+ const branding = readRecord(raw2, "branding", "branding");
147480
+ const formTitle = readString(raw2, "formTitle", "form_title");
147481
+ const formDescription = readString(raw2, "formDescription", "form_description");
147482
+ const identityFieldLabel = readString(raw2, "identityFieldLabel", "identity_field_label");
147483
+ const identityFieldType = readString(raw2, "identityFieldType", "identity_field_type");
147484
+ const passwordFieldLabel = readString(raw2, "passwordFieldLabel", "password_field_label");
147485
+ const submitButtonText = readString(raw2, "submitButtonText", "submit_button_text");
147486
+ if (!branding && !formTitle && !formDescription && !identityFieldLabel && !identityFieldType && !passwordFieldLabel && !submitButtonText) {
147487
+ return void 0;
147488
+ }
147489
+ return {
147490
+ ...branding ? { branding } : {},
147491
+ ...formTitle ? { formTitle } : {},
147492
+ ...formDescription ? { formDescription } : {},
147493
+ ...identityFieldLabel ? { identityFieldLabel } : {},
147494
+ ...identityFieldType ? { identityFieldType } : {},
147495
+ ...passwordFieldLabel ? { passwordFieldLabel } : {},
147496
+ ...submitButtonText ? { submitButtonText } : {}
147497
+ };
147498
+ }
147499
+ function buildCredentialConfig(entry) {
147500
+ const authEndpoint = readString(entry, "authEndpoint", "auth_endpoint");
147501
+ const requestBodyTemplate = readRecord(entry, "requestBodyTemplate", "request_body_template");
147502
+ const rawResponseFields = readRecord(entry, "responseFields", "response_fields");
147503
+ if (!authEndpoint || !requestBodyTemplate || !rawResponseFields)
147504
+ return null;
147505
+ const sessionToken = readString(rawResponseFields, "sessionToken", "session_token");
147506
+ if (!sessionToken)
147507
+ return null;
147508
+ const responseFields = {
147509
+ sessionToken,
147510
+ userId: readString(rawResponseFields, "userId", "user_id"),
147511
+ userEmail: readString(rawResponseFields, "userEmail", "user_email"),
147512
+ userDisplayName: readString(rawResponseFields, "userDisplayName", "user_display_name"),
147513
+ expiresIn: readString(rawResponseFields, "expiresIn", "expires_in")
147514
+ };
147515
+ const successCheck = buildSuccessCheck(readRecord(entry, "successCheck", "success_check"));
147516
+ const headers = readRecord(entry, "headers", "headers");
147517
+ const tokenUsage = readString(entry, "tokenUsage", "token_usage");
147518
+ const tokenHeader = readString(entry, "tokenHeader", "token_header");
147519
+ const cookieFormat = readString(entry, "cookieFormat", "cookie_format");
147520
+ const consentOverrides = buildConsentOverrides(readRecord(entry, "consentOverrides", "consent_overrides"));
147521
+ return {
147522
+ // The handler ignores `type`, but the contract's discriminant is "credential".
147523
+ type: "credential",
147524
+ displayName: readString(entry, "displayName", "display_name"),
147525
+ authEndpoint,
147526
+ requestBodyTemplate,
147527
+ responseFields,
147528
+ ...successCheck ? { successCheck } : {},
147529
+ ...headers ? { headers } : {},
147530
+ ...tokenUsage ? { tokenUsage } : {},
147531
+ ...tokenHeader ? { tokenHeader } : {},
147532
+ ...cookieFormat ? { cookieFormat } : {},
147533
+ ...consentOverrides ? { consentOverrides } : {}
147534
+ };
147535
+ }
147536
+ async function resolveAnchorCredentialProvider(env2, _scopes) {
147537
+ const apiKey = env2.AGENTSHIELD_API_KEY;
147538
+ const projectId = env2.AGENTSHIELD_PROJECT_ID;
147539
+ if (!apiKey || !projectId)
147540
+ return { status: "none" };
147541
+ const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
147542
+ let providersMap;
147543
+ let configuredProvider;
147544
+ try {
147545
+ const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/projects/${encodeURIComponent(projectId)}/providers`, {
147546
+ method: "GET",
147547
+ headers: {
147548
+ Authorization: `Bearer ${apiKey}`,
147549
+ "Content-Type": "application/json"
147550
+ }
147551
+ });
147552
+ if (!response.ok)
147553
+ return { status: "unavailable" };
147554
+ const body = await response.json();
147555
+ if (body.success !== true || !body.data || typeof body.data.providers !== "object" || body.data.providers === null) {
147556
+ return { status: "unavailable" };
147557
+ }
147558
+ providersMap = body.data.providers;
147559
+ configuredProvider = body.data.configuredProvider ?? body.data.configured_provider ?? null;
147560
+ } catch {
147561
+ return { status: "unavailable" };
147562
+ }
147563
+ const credentialIds = Object.keys(providersMap).filter((id) => isCredentialTyped(providersMap[id]));
147564
+ if (credentialIds.length === 0)
147565
+ return { status: "none" };
147566
+ const chosenId = configuredProvider && isCredentialTyped(providersMap[configuredProvider]) ? configuredProvider : credentialIds.length === 1 ? credentialIds[0] : null;
147567
+ if (!chosenId)
147568
+ return { status: "unavailable" };
147569
+ const config4 = buildCredentialConfig(providersMap[chosenId]);
147570
+ if (!config4)
147571
+ return { status: "unavailable" };
147572
+ return {
147573
+ status: "credential",
147574
+ provider: {
147575
+ providerId: chosenId,
147576
+ displayName: config4.displayName || chosenId,
147577
+ config: config4
147578
+ }
147579
+ };
147580
+ }
147581
+ async function resolveCredentialIdentity(env2, params) {
147582
+ const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
147583
+ const apiKey = env2.AGENTSHIELD_API_KEY;
147584
+ if (!apiKey)
147585
+ return { success: false };
147586
+ try {
147587
+ const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/identity/resolve`, {
147588
+ method: "POST",
147589
+ headers: {
147590
+ "X-API-Key": apiKey,
147591
+ "Content-Type": "application/json"
147592
+ },
147593
+ body: JSON.stringify({
147594
+ project_id: params.projectId,
147595
+ credential_result: {
147596
+ provider: params.provider,
147597
+ user_id: params.userId,
147598
+ email: params.userEmail,
147599
+ name: params.userDisplayName
147600
+ }
147601
+ })
147602
+ });
147603
+ if (!response.ok)
147604
+ return { success: false };
147605
+ const data = await response.json();
147606
+ const userDid = data?.data?.user_did;
147607
+ return userDid ? { success: true, userDid } : { success: false };
147608
+ } catch {
147609
+ return { success: false };
147610
+ }
147611
+ }
147612
+ function sidToDelegationUuid(sid) {
147613
+ const h5 = sha256Hex(sid).slice(0, 32).split("");
147614
+ h5[12] = "4";
147615
+ h5[16] = (parseInt(h5[16], 16) & 3 | 8).toString(16);
147616
+ const s5 = h5.join("");
147617
+ return `${s5.slice(0, 8)}-${s5.slice(8, 12)}-${s5.slice(12, 16)}-${s5.slice(16, 20)}-${s5.slice(20, 32)}`;
147618
+ }
147619
+ async function notifyDelegation(env2, params) {
147620
+ const apiKey = env2.AGENTSHIELD_API_KEY;
147621
+ const projectId = env2.AGENTSHIELD_PROJECT_ID;
147622
+ if (!apiKey || !projectId)
147623
+ return;
147624
+ const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
147625
+ try {
147626
+ const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/delegations/notify`, {
147627
+ method: "POST",
147628
+ headers: {
147629
+ "X-API-Key": apiKey,
147630
+ "Content-Type": "application/json"
147631
+ },
147632
+ body: JSON.stringify({
147633
+ delegation_id: sidToDelegationUuid(params.sid),
147634
+ agent_did: params.agentDid,
147635
+ agent_name: params.agentName || void 0,
147636
+ user_did: params.userDid,
147637
+ user_id: params.userId || void 0,
147638
+ user_identifier: params.userIdentifier || void 0,
147639
+ scopes: params.scopes,
147640
+ provider: params.provider,
147641
+ project_id: projectId,
147642
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
147643
+ expires_at: params.expiresAt || void 0,
147644
+ metadata: {
147645
+ source: "mcp-i-anchor-consent",
147646
+ sid: params.sid,
147647
+ ...params.metadata
147648
+ }
147649
+ })
147650
+ });
147651
+ if (!response.ok) {
147652
+ console.warn(`[kya-http] delegation notify failed (non-blocking): ${response.status} sid=${params.sid}`);
147653
+ }
147654
+ } catch (error87) {
147655
+ console.warn(`[kya-http] delegation notify failed (non-blocking): ${error87 instanceof Error ? error87.message : String(error87)} sid=${params.sid}`);
147656
+ }
147657
+ }
147658
+
147659
+ // ../mcp-i-cloudflare/dist/delegation-http/consent-anchor-bridge.js
147430
147660
  var DO_INTERNAL_ORIGIN2 = "https://do.internal";
147431
147661
  async function callAnchor2(env2, sid, internalPath, body) {
147432
147662
  const stub = getAnchorStub(env2, sid);
@@ -147446,6 +147676,15 @@ function htmlResponse(html, status) {
147446
147676
  }
147447
147677
  });
147448
147678
  }
147679
+ function jsonResponse(body, status) {
147680
+ return new Response(JSON.stringify(body), {
147681
+ status,
147682
+ headers: {
147683
+ "Content-Type": "application/json",
147684
+ "Cache-Control": "no-store"
147685
+ }
147686
+ });
147687
+ }
147449
147688
  function page(title, bodyInner) {
147450
147689
  return `<!DOCTYPE html>
147451
147690
  <html lang="en">
@@ -147477,24 +147716,111 @@ function approvalFailedPage(message3, status = 410) {
147477
147716
  <p>${escapeHtml2(message3)}</p>
147478
147717
  </main>`), status);
147479
147718
  }
147480
- function successPage() {
147481
- return htmlResponse(page("Authorization complete", `<main class="kya-consent-success">
147482
- <h1>Authorization complete</h1>
147483
- <p>You have authorized the request. You can close this window and return to the application.</p>
147484
- </main>`), 200);
147485
- }
147486
- function approveFormPage(sid, info, csrfToken) {
147487
- const scopeItems = info.requiredScopes.length > 0 ? info.requiredScopes.map((s5) => `<li class="kya-scope-item">${escapeHtml2(s5)}</li>`).join("") : `<li class="kya-scope-item">No specific permissions required.</li>`;
147488
- return page("Permission Request", `<main class="kya-consent">
147489
- <h1>Authorize delegation</h1>
147490
- <p class="kya-permissions-header">This request needs the following permissions:</p>
147491
- <ul class="kya-permissions-list">${scopeItems}</ul>
147492
- <form method="POST" action="/consent/approve?sid=${encodeURIComponent(sid)}">
147493
- <input type="hidden" name="sid" value="${escapeHtml2(sid)}">
147494
- <input type="hidden" name="csrf_token" value="${escapeHtml2(csrfToken)}">
147495
- <button type="submit" class="kya-consent-allow">Allow</button>
147496
- </form>
147497
- </main>`);
147719
+ function notFoundJson() {
147720
+ return jsonResponse({
147721
+ error: "We could not find this authorization request. It may have already completed or been cancelled."
147722
+ }, 404);
147723
+ }
147724
+ function approvalFailedJson(message3, status = 410) {
147725
+ return jsonResponse({ error: message3 }, status);
147726
+ }
147727
+ function successJson(delegationId) {
147728
+ return jsonResponse({ success: true, delegation_id: delegationId }, 200);
147729
+ }
147730
+ function resolveAnchorCapabilities(consentConfig, scopes) {
147731
+ if (consentConfig.capabilities && consentConfig.capabilities.length > 0) {
147732
+ return consentConfig.capabilities;
147733
+ }
147734
+ if (scopes.length === 0)
147735
+ return void 0;
147736
+ const derived = resolveCapabilitiesForScopes(scopes);
147737
+ if (derived.length === 0)
147738
+ return void 0;
147739
+ return [{ id: "default", label: "Permissions", capabilities: derived }];
147740
+ }
147741
+ function renderAnchorConsentShell(params) {
147742
+ const { consentConfig, info, sid, csrfToken, serverUrl, projectId, credential } = params;
147743
+ const cpc = credential?.provider.config;
147744
+ const cpcOverrides = cpc?.consentOverrides;
147745
+ const shellConfig = {
147746
+ branding: consentConfig.branding,
147747
+ terms: consentConfig.terms,
147748
+ customFields: consentConfig.customFields,
147749
+ ui: consentConfig.ui,
147750
+ expirationDays: consentConfig.expirationDays,
147751
+ credentials: credential ? {
147752
+ usernameLabel: cpcOverrides?.identityFieldLabel || consentConfig.credentials?.usernameLabel || "Username",
147753
+ usernamePlaceholder: consentConfig.credentials?.usernamePlaceholder || "Enter your username",
147754
+ passwordLabel: cpcOverrides?.passwordFieldLabel || consentConfig.credentials?.passwordLabel || "Password",
147755
+ passwordPlaceholder: consentConfig.credentials?.passwordPlaceholder || "Enter your password",
147756
+ showRememberMe: consentConfig.credentials?.showRememberMe ?? true,
147757
+ showForgotPassword: consentConfig.credentials?.showForgotPassword ?? false,
147758
+ forgotPasswordUrl: consentConfig.credentials?.forgotPasswordUrl
147759
+ } : consentConfig.credentials
147760
+ };
147761
+ const shellOptions = {
147762
+ config: shellConfig,
147763
+ tool: "",
147764
+ scopes: info.requiredScopes,
147765
+ agentDid: info.agentDid || "",
147766
+ sessionId: sid,
147767
+ projectId,
147768
+ serverUrl,
147769
+ // Browser-tab title only (the in-page heading is `shellConfig.ui.title`,
147770
+ // shared across screens) — surface the provider's display name here for the
147771
+ // credential branch instead of dropping it entirely.
147772
+ pageTitle: credential ? `Sign in to ${credential.provider.displayName}` : "Permission Request",
147773
+ csrfToken,
147774
+ capabilities: resolveAnchorCapabilities(consentConfig, info.requiredScopes),
147775
+ agentMetadata: consentConfig.agentMetadata,
147776
+ consentTheme: consentConfig.theme,
147777
+ headlineVerb: consentConfig.headlineVerb,
147778
+ revocationPath: consentConfig.revocationPath,
147779
+ inactivityDays: consentConfig.inactivityDays,
147780
+ ...credential ? {
147781
+ authMode: "credentials",
147782
+ provider: credential.provider.providerId,
147783
+ authorizationType: "password"
147784
+ } : {}
147785
+ };
147786
+ return generateConsentShell(shellOptions);
147787
+ }
147788
+ function resolveServerUrl(env2, c) {
147789
+ const configured = env2.MCP_SERVER_URL;
147790
+ if (configured && configured !== "null" && configured.startsWith("http")) {
147791
+ return configured;
147792
+ }
147793
+ const raw2 = c.req?.raw;
147794
+ if (raw2) {
147795
+ try {
147796
+ return new URL(raw2.url).origin;
147797
+ } catch {
147798
+ }
147799
+ }
147800
+ return "";
147801
+ }
147802
+ async function resolveApproveSid(c) {
147803
+ const query = c.req.query("sid");
147804
+ if (isAnchorSid(query))
147805
+ return query;
147806
+ const raw2 = c.req?.raw;
147807
+ if (!raw2)
147808
+ return void 0;
147809
+ try {
147810
+ const contentType2 = raw2.headers.get("Content-Type") || "";
147811
+ const clone5 = raw2.clone();
147812
+ let candidate;
147813
+ if (contentType2.includes("application/json")) {
147814
+ const body = await clone5.json();
147815
+ candidate = body.sid ?? body.session_id;
147816
+ } else {
147817
+ const form = await clone5.formData();
147818
+ candidate = form.get("sid") ?? form.get("session_id");
147819
+ }
147820
+ return typeof candidate === "string" && isAnchorSid(candidate) ? candidate : void 0;
147821
+ } catch {
147822
+ return void 0;
147823
+ }
147498
147824
  }
147499
147825
  function base64UrlEncodeBytes(bytes) {
147500
147826
  return btoa(String.fromCharCode(...bytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
@@ -147619,7 +147945,10 @@ async function mintDelegationVcJwt(env2, sid, info, expiresInS) {
147619
147945
  const signingInput = withCrossResourceClaims(unsigned, info, sid);
147620
147946
  const signatureBytes = await cryptoProvider.sign(new TextEncoder().encode(signingInput), signingPrivateKey);
147621
147947
  const signature = base64urlEncodeFromBytes2(signatureBytes);
147622
- return completeVCJWT2(signingInput, signature);
147948
+ return {
147949
+ vcJwt: completeVCJWT2(signingInput, signature),
147950
+ subjectDid: agentDid
147951
+ };
147623
147952
  }
147624
147953
  async function handleAnchorConsentGet(c, sid, env2, _cfg) {
147625
147954
  const infoResponse = await callAnchor2(env2, sid, INTERNAL_PICKUP_INFO, {
@@ -147634,34 +147963,93 @@ async function handleAnchorConsentGet(c, sid, env2, _cfg) {
147634
147963
  }
147635
147964
  const info = await infoResponse.json();
147636
147965
  const csrfToken = await mintCsrfToken(env2, sid);
147637
- return htmlResponse(approveFormPage(sid, info, csrfToken), 200);
147966
+ const projectId = env2.AGENTSHIELD_PROJECT_ID || "";
147967
+ const consentConfig = await new ConsentConfigService(env2).getConsentConfig(projectId);
147968
+ const serverUrl = resolveServerUrl(env2, c);
147969
+ const resolution = await resolveAnchorCredentialProvider(env2, info.requiredScopes);
147970
+ if (resolution.status === "credential") {
147971
+ return htmlResponse(renderAnchorConsentShell({
147972
+ consentConfig,
147973
+ info,
147974
+ sid,
147975
+ csrfToken,
147976
+ serverUrl,
147977
+ projectId,
147978
+ credential: { provider: resolution.provider }
147979
+ }), 200);
147980
+ }
147981
+ return htmlResponse(renderAnchorConsentShell({
147982
+ consentConfig,
147983
+ info,
147984
+ sid,
147985
+ csrfToken,
147986
+ serverUrl,
147987
+ projectId
147988
+ }), 200);
147638
147989
  }
147639
147990
  async function handleAnchorConsentApprove(c, sid, env2, cfg) {
147991
+ const bodyFields = await readBodyFields(c);
147640
147992
  if (!isTestConsentMode(env2)) {
147641
- const csrfToken = await readCsrfTokenFromBody(c);
147642
- const valid = await validateCsrfToken(env2, sid, csrfToken);
147993
+ const valid = await validateCsrfToken(env2, sid, bodyFields.csrf_token);
147643
147994
  if (!valid) {
147644
- return htmlResponse(page("Authorization failed", `<main class="kya-consent-failed"><h1>Authorization failed</h1><p>Invalid or missing security token. Please reload and try again.</p></main>`), 403);
147995
+ return jsonResponse({
147996
+ error: "Invalid or missing security token. Please reload and try again."
147997
+ }, 403);
147645
147998
  }
147646
147999
  }
147647
148000
  const infoResponse = await callAnchor2(env2, sid, INTERNAL_PICKUP_INFO, {
147648
148001
  sid
147649
148002
  });
147650
148003
  if (infoResponse.status === 404)
147651
- return notFoundPage();
148004
+ return notFoundJson();
147652
148005
  if (infoResponse.status === 410) {
147653
- return approvalFailedPage("This authorization request has expired. Nothing was authorized.");
148006
+ return approvalFailedJson("This authorization request has expired. Nothing was authorized.");
147654
148007
  }
147655
148008
  if (!infoResponse.ok) {
147656
- return approvalFailedPage("This authorization request could not be loaded. Please start over.", 502);
148009
+ return approvalFailedJson("This authorization request could not be loaded. Please start over.", 502);
147657
148010
  }
147658
148011
  const info = await infoResponse.json();
148012
+ const resolution = await resolveAnchorCredentialProvider(env2, info.requiredScopes);
148013
+ if (resolution.status === "unavailable") {
148014
+ return approvalFailedJson("We could not verify the sign-in requirement for this request. Please try again.", 503);
148015
+ }
148016
+ const provider = resolution.status === "credential" ? resolution.provider : null;
148017
+ let authorizedUser = null;
148018
+ if (provider) {
148019
+ const { sid: _sid, csrf_token: _csrfToken, tool: _tool, scopes: _scopes, agent_did: _agentDid, session_id: _sessionId, project_id: _projectId, provider: _providerField, provider_type: _providerType, auth_mode: _authMode, termsAccepted: _termsAccepted, credential_provider_type: _credentialProviderType, credential_provider: _credentialProvider, oauth_provider_type: _oauthProviderType, user_did: _userDid, credential_user_email: _credentialUserEmail, credential_provider_user_id: _credentialProviderUserId, ...credentials } = bodyFields;
148020
+ const handler = createCredentialAuthHandler({
148021
+ fetch: (...args) => globalThis.fetch(...args),
148022
+ logger: (msg, data) => console.debug(`[kya-http] ${msg}`, data)
148023
+ });
148024
+ const authResult = await handler.authenticate(provider.config, credentials);
148025
+ if (!authResult.success) {
148026
+ return jsonResponse({
148027
+ error: authResult.error || "Those credentials were not accepted. Please try again."
148028
+ }, 401);
148029
+ }
148030
+ const identity = await resolveCredentialIdentity(env2, {
148031
+ projectId: env2.AGENTSHIELD_PROJECT_ID || "",
148032
+ provider: provider.providerId,
148033
+ userId: authResult.userId || "unknown",
148034
+ userEmail: authResult.userEmail,
148035
+ userDisplayName: authResult.userDisplayName
148036
+ });
148037
+ if (!identity.success || !identity.userDid) {
148038
+ return approvalFailedJson("We signed you in but could not resolve your identity. Please start over.", 500);
148039
+ }
148040
+ authorizedUser = {
148041
+ userDid: identity.userDid,
148042
+ userId: authResult.userId,
148043
+ userEmail: authResult.userEmail
148044
+ };
148045
+ }
147659
148046
  let vcJwt;
148047
+ let subjectDid;
147660
148048
  try {
147661
- vcJwt = await mintDelegationVcJwt(env2, sid, info, cfg.delegationExpiresInS);
148049
+ ({ vcJwt, subjectDid } = await mintDelegationVcJwt(env2, sid, info, cfg.delegationExpiresInS));
147662
148050
  } catch (error87) {
147663
148051
  console.warn(`[kya-http] delegation mint failed (sid=${sid}):`, error87 instanceof Error ? error87.message : String(error87));
147664
- return approvalFailedPage("We could not complete the authorization. Please start over.", 500);
148052
+ return approvalFailedJson("We could not complete the authorization. Please start over.", 500);
147665
148053
  }
147666
148054
  const approveResponse = await callAnchor2(env2, sid, INTERNAL_PICKUP_APPROVE, {
147667
148055
  sid,
@@ -147669,31 +148057,53 @@ async function handleAnchorConsentApprove(c, sid, env2, cfg) {
147669
148057
  expiresInS: cfg.delegationExpiresInS
147670
148058
  });
147671
148059
  if (approveResponse.status === 410) {
147672
- return approvalFailedPage("This authorization request expired before it could be completed. Nothing was authorized.");
148060
+ return approvalFailedJson("This authorization request expired before it could be completed. Nothing was authorized.");
147673
148061
  }
147674
148062
  if (approveResponse.status === 404)
147675
- return notFoundPage();
148063
+ return notFoundJson();
147676
148064
  if (!approveResponse.ok) {
147677
- return approvalFailedPage("We could not complete the authorization. Please start over.", 502);
148065
+ return approvalFailedJson("We could not complete the authorization. Please start over.", 502);
147678
148066
  }
147679
- return successPage();
148067
+ if (authorizedUser && provider) {
148068
+ const report = notifyDelegation(env2, {
148069
+ sid,
148070
+ agentDid: subjectDid,
148071
+ userDid: authorizedUser.userDid,
148072
+ userId: authorizedUser.userId,
148073
+ userIdentifier: authorizedUser.userEmail,
148074
+ scopes: info.requiredScopes,
148075
+ provider: provider.providerId,
148076
+ // Record the same expiry the VC was minted with, matching the OAuth path.
148077
+ expiresAt: new Date(Date.now() + cfg.delegationExpiresInS * 1e3).toISOString()
148078
+ });
148079
+ const execCtx = c.executionCtx;
148080
+ execCtx?.waitUntil?.(report);
148081
+ }
148082
+ return successJson(`urn:uuid:${sid}`);
147680
148083
  }
147681
- async function readCsrfTokenFromBody(c) {
148084
+ async function readBodyFields(c) {
148085
+ const out = {};
147682
148086
  const raw2 = c.req?.raw;
147683
148087
  if (!raw2)
147684
- return void 0;
148088
+ return out;
147685
148089
  try {
147686
148090
  const contentType2 = raw2.headers.get("Content-Type") || "";
147687
148091
  if (contentType2.includes("application/json")) {
147688
- const body = await raw2.clone().json();
147689
- const token2 = body?.csrf_token;
147690
- return typeof token2 === "string" ? token2 : void 0;
148092
+ const body = await raw2.json();
148093
+ for (const [key, value] of Object.entries(body)) {
148094
+ if (typeof value === "string")
148095
+ out[key] = value;
148096
+ }
148097
+ return out;
147691
148098
  }
147692
- const form = await raw2.clone().formData();
147693
- const token = form.get("csrf_token");
147694
- return typeof token === "string" ? token : void 0;
148099
+ const form = await raw2.formData();
148100
+ form.forEach((value, key) => {
148101
+ if (typeof value === "string")
148102
+ out[key] = value;
148103
+ });
148104
+ return out;
147695
148105
  } catch {
147696
- return void 0;
148106
+ return out;
147697
148107
  }
147698
148108
  }
147699
148109
 
@@ -147723,8 +148133,10 @@ function registerDelegationHttpRoutes(app, options, deps) {
147723
148133
  });
147724
148134
  app.post(`${CONSENT_ROUTE}/approve`, async (c, next) => {
147725
148135
  const { env: env2, cfg } = resolveRequest(c, options);
147726
- const sid = c.req.query("sid");
147727
- if (!cfg || !isAnchorSid(sid))
148136
+ if (!cfg)
148137
+ return next();
148138
+ const sid = await resolveApproveSid(c);
148139
+ if (!isAnchorSid(sid))
147728
148140
  return next();
147729
148141
  return handleAnchorConsentApprove(c, sid, env2, cfg);
147730
148142
  });
@@ -78,8 +78,8 @@ export async function getPackageVersions() {
78
78
  return {
79
79
  "@kya-os/mcp-i": "^1.7.13",
80
80
  "@kya-os/cli": "^1.5.9",
81
- "@kya-os/mcp-i-cloudflare": "^1.12.1",
82
- "@kya-os/contracts": "^1.9.0",
81
+ "@kya-os/mcp-i-cloudflare": "^1.12.3",
82
+ "@kya-os/contracts": "^1.9.2",
83
83
  };
84
84
  }
85
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/create-mcpi-app",
3
- "version": "1.10.3",
3
+ "version": "1.10.5",
4
4
  "description": "Scaffold a new MCP-I application",
5
5
  "type": "module",
6
6
  "main": "./dist/helpers/index.js",
@@ -55,11 +55,11 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@apidevtools/swagger-parser": "^10.1.1",
58
- "@kya-os/cli": "^1.6.1",
58
+ "@kya-os/cli": "^1.6.3",
59
59
  "@kya-os/cli-effects": "^1.0.19",
60
- "@kya-os/contracts": "^1.9.0",
60
+ "@kya-os/contracts": "^1.9.2",
61
61
  "@kya-os/mcp-i": "^1.7.13",
62
- "@kya-os/mcp-i-cloudflare": "^1.12.1",
62
+ "@kya-os/mcp-i-cloudflare": "^1.12.3",
63
63
  "base-x": "^5.0.0",
64
64
  "chalk": "^4.1.2",
65
65
  "commander": "^12.1.0",