@seldonframe/mcp 1.18.1 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1) hide show
  1. package/package.json +2 -1
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@seldonframe/mcp",
3
- "version": "1.18.1",
3
+ "version": "1.19.0",
4
+ "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.19.0: STABILITY BUNDLE — five focused root-cause fixes after the v1.18 white-label CRM smoke. (1) PORTAL ACCESS-CODE CASE-INSENSITIVE LOOKUP + SILENT-NO-OP OBSERVABILITY. requestPortalAccessCodeAction + verifyPortalAccessCodeAction now normalize email at action entry (trim + lowercase) AND use lower(stored_email) at the SQL compare, so a customer typing dresslikeAG@Gmail.com still matches a stored dresslikeag@gmail.com. Pre-1.19 the silent-success branches dropped requests with zero log signal — now each branch (org_not_found / plan_gate_denied / contact_not_found / portal_access_disabled) emits a structured warn so production monitoring can attribute every silent-no-op to a specific cause. (2) POLYMORPHIC AGENCY OWNERSHIP. Migration 0041 adds owner_workspace_id to partner_agencies + at-least-one-owner CHECK + lookup index. registerPartnerAgency / attachWorkspaceToAgency / detachWorkspaceFromAgency / registerAgencySenderDomain / verifyAgencySenderDomain now accept EITHER ownerUserId OR ownerWorkspaceId; the API route /api/v1/partner-agencies resolves both identities from the bearer's workspace and falls back to ownerWorkspaceId = guard.orgId when organizations.owner_id is null. Anonymous workspaces (create_workspace_v2 + the v1.7.3 NextAuth-bug claimed-but-unlinked path) can now register agencies natively without a manual users-row INSERT unblock. 12 new contract tests covering the predicate (user-only, workspace-only, dual-pointer, empty caller, null-vs-undefined ambiguity, anonymous-workspace-as-actor). (3) DUPLICATE-CONTACT UNIQUENESS. Migration 0042 adds a partial unique index on contacts (org_id, lower(email)) WHERE email IS NOT NULL — combined with v1.19's case-insensitive lookup, this structurally prevents the dup-row class that produced the v1.18 'no email arrived' bug (two contact rows with the same lowercased email, lookup .limit(1) returned the wrong one with portal_access_enabled=false). Defensive backfill repoints FKs from loser → winner across all 14 contact-referencing tables (activities/bookings/conversations/deals/emails/intake_forms/invoices/payments/portal_access_codes/portal_documents/portal_messages/portal_resources/sms_messages/subscriptions/workspace_records) before deleting losers; idempotent — safe to re-run. Prod confirmed 0 dups before queuing the migration. (4) NEXTAUTH USERS-ROW ROOT-CAUSE FIX — SELF-HEALING JWT RECOVERY. The session strategy is JWT, so token.sub can drift from the actual users.id row in three ways (createUser failed mid-flow, JWT minted from a deleted-then-recreated user, cross-deployment carry-over). Pre-1.19 the v1.7.3 synthesizer prevented the uncaught-throw crash but left the user permanently in a 'signed in but locked in synthesized empty record' dead-state. v1.19 the JWT callback now: on byId miss, falls back to lookup by lower(email); on email match, re-anchors token.sub to that user's id silently; on neither match, logs a structured orphan_token_no_email_match warn for production monitoring to count. 8 new tests covering normalization shape + the 3-state classifier (resolved / self_healed / orphan). (5) PORTAL EXPERIENCE POLISH. The /portal/<orgSlug> client layout + overview page were using legacy crm-card / crm-button-secondary / crm-button-ghost utility classes that didn't pick up workspace branding (every workspace's portal looked SeldonFrame-blue regardless of theme). v1.19 wraps the inner client area in PortalLayout (PublicThemeProvider + branded header) and re-themes nav links, welcome card, stat cards, and message rows with --sf-* CSS variables (--sf-card-bg / --sf-text / --sf-muted / --sf-border / --sf-radius / --sf-primary / --sf-bg). Auth + data plumbing UNCHANGED — same requirePortalSessionForOrg / listPortalMessages / clearPortalSessionAction calls; only the chrome is re-themed. Portal now visually descends from the branded login experience end-to-end. NO new MCP tools; this is a backend stability ship. The MCP package itself is unchanged; version bump is coupled with the backend so they redeploy together. ⚠️ BACKEND REDEPLOY REQUIRED. Migrations 0041 + 0042 already applied to prod via Neon MCP. v1.20 — agency self-serve management tools + nightly plan-gate sweep (deferred, fresh session). v1.21 — agency custom domain + per-client wildcard subdomains via Vercel (deferred, fresh session).",
4
5
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.18.1: HOTFIX — register_partner_agency_sender_domain is now idempotent. Smoke surfaced 2026-05-06: agency tried to register a domain that was already registered in our Resend account (from a prior smoke), got Resend 403 'The <name> domain has been registered already'. Pre-1.18.1 the operator dead-ended with no recovery. v1.18.1: when create returns 403/already-registered, we list all domains in our Resend account, find the existing record by name, fetch its DNS records, and use that domain_id + records as if create had succeeded. If the existing record happens to be already verified by Resend (DNS resolved at some prior point), we mirror that into our agency row's verified_sender_at and skip the DNS-add prompt entirely. Edge case: if Resend says the domain is already registered but it's NOT in our account list, we surface a structured error pointing the operator at a different domain or support — that's the 'registered under a different Resend account' case which is unrecoverable without contacting Resend. NO migrations, NO env vars, NO new deps. The MCP package itself is unchanged in v1.18.1 — version bump coupled with backend so they redeploy together.",
5
6
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.18.0: WHITE-LABEL CRM PHASE 2 — Resend per-agency sender + agency-branded transactional emails. v1.17 shipped the partner-agency hierarchy. v1.18 closes the loop on email branding: agencies' clients now receive transactional emails (portal-access-code in v1.18.0; welcome + admin-link queued for v1.18.1) FROM the agency's verified domain WITH the agency's brand name in the template, instead of welcome@seldonframe.com / 'on SeldonFrame'. WHAT SHIPS: (1) Resend Domains API integration (lib/integrations/resend-domains.ts) — createResendSenderDomain (POST /domains), getResendSenderDomain (GET /domains/:id), triggerResendDomainVerification (POST /domains/:id/verify), removeResendSenderDomain. Uses the existing RESEND_API_KEY (no new env var). Each agency's sender domain registered UNDER our Resend account (no separate Resend account per agency). (2) Sender-domain orchestration (lib/partner-agencies/sender-domain.ts) — registerAgencySenderDomain creates the Resend domain + persists resend_domain_id + sender_email_address on the agency row (verified_sender_at left NULL until verification confirms); verifyAgencySenderDomain triggers Resend's verify endpoint, persists verified_sender_at on first success. (3) Two new MCP tools: register_partner_agency_sender_domain (returns DNS records the agency must add at their registrar), verify_partner_agency_sender_domain (idempotent — safe to call while DNS propagates). (4) Portal-access-code email wired to agency branding: when workspace has active agency with verified_sender_at, the email goes FROM the agency's domain + 'on <Agency Name>' in the footer + (optionally) the agency's logo in template. Falls back to SF defaults when no agency / not verified — defense-in-depth via deriveEffectiveBranding (only exposes sender_email_address when verified_sender_at is populated). (5) Email template extended: PortalAccessCodeEmailRequest gains brandName / logoUrl / supportUrl optional fields; HTML + text bodies branch on brandName for footer text. SECURITY: agencies only operate on their OWN agency rows (caller_owns_agency check at every mutation). Resend's standard SPF/DKIM/DMARC enforcement covers email-spoofing risk. Test count: 2539 (unchanged from v1.17 — v1.18 is wiring + integration; the security-critical pure helpers were already covered by v1.17's tests). Typecheck clean. Backward compatible. NO migrations (v1.17's 0040 is sufficient). v1.18.1 candidate (this session if time permits, else fresh): wire welcome + device-auth + admin-link emails to also use agency branding + admin dashboard chrome substitution. v1.19 — agency self-serve management tools + nightly plan-gate sweep. v1.20 — agency custom domain + per-client wildcard subdomains via Vercel.",
6
7
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.17.0: WHITE-LABEL CRM PHASE 1 — partner-agency hierarchy + foundational primitives. SeldonFrame's Scale-tier customers (agencies / solopreneurs reselling AI-native Business OS to SMBs like HVAC contractors / dentists / lawyers / realtors) can now register as a partner agency, attach client workspaces to that agency, and have those workspaces' chrome (logo, colors, sender, support pointers, 'Powered by' badge) substitute the agency's branding for SeldonFrame's. WHAT SHIPS: (1) Migration 0040 — new partner_agencies table (id, name, slug, logo_url, colors, support pointers, sender_email_address + verified_sender_at for v1.18, agency_domain + agency_domain_verified_at for v1.20, owner_user_id, status: pending|active|suspended|archived, hide_powered_by_badge). organizations.parent_agency_id FK column. Applied to prod via Neon MCP. (2) Drizzle schema modules: partner-agencies.ts + organizations.ts extended with parentAgencyId. (3) Pure helper deriveEffectiveBranding(agency, workspaceName) — decides chrome (SF default vs agency-substituted). Defense-in-depth: doesn't expose sender_email_address until verified_sender_at is populated; doesn't expose agency_domain until agency_domain_verified_at is populated. Plan-gate semantics: only 'active' agencies substitute chrome; pending/suspended/archived fall back to SF defaults (data preserved). (4) DB-loading wrapper getEffectiveBrandingForWorkspace(workspaceId) for chrome consumers. (5) State management: registerPartnerAgency (Scale-tier check + slug uniqueness), attachWorkspaceToAgency (caller-owns-both check), detachWorkspaceFromAgency (caller is workspace owner OR agency owner). (6) Three new MCP tools: register_partner_agency, attach_workspace_to_agency, detach_workspace_from_agency. (7) shouldShowPoweredByBadgeForOrg now respects agency.hide_powered_by_badge for active agencies — first chrome surface wired up. (8) 14 new unit tests covering branding-derivation in all status states, color/sender/domain echo, defense-in-depth on unverified sender + domain. Test count: 2539 (was 2525). NO new env vars (Resend + Vercel come into play in v1.18 + v1.20). Plan gate: agency creation requires Scale-tier ownership; non-Scale callers get the agency in 'pending' status (chrome substitution only activates on active). v1.18 (next ship) — wire the dashboard chrome substitution + welcome/admin/portal-access-code emails to use the agency's verified Resend sender. v1.19 — agency self-serve management tools (list_my_agencies, update_partner_agency, list_my_workspaces). v1.20 — agency custom domain (crm.acmeai.com) with per-client wildcard subdomains via Vercel.",