@seldonframe/mcp 1.8.0 → 1.9.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.
- package/package.json +3 -1
- package/src/welcome.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seldonframe/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
|
+
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.9.0: BEHAVIORAL CONTRACT TESTS — kills the handler-execution-state-drift bug class structurally. Three bugs in 7 days hit the same shape: a server-side function `throw new Error()`s for an edge user/workspace state (no users row, no Stripe customer, free tier, empty form_fields), and the throw cascades through the SSR boundary as 'This page couldn't load.' WHAT SHIPS: (1) static analysis test (tests/unit/contract-no-uncaught-throws.spec.ts) that scans designated directories — lib/billing/**, lib/auth/**, lib/page-blocks/persist.ts, app/(dashboard)/** — for `throw new Error()` patterns. Every throw must EITHER be wrapped in try/catch OR carry a `// contract:throw-ok: <reason>` annotation. CI fails if any throw is unannotated. (2) 34 existing throws audited and annotated with semantic reasons (Stripe API errors, programmer-error sentinels, deployment config, form-submit error UX, etc.). Going forward, every NEW throw added to scoped directories must be annotated explicitly. (3) Behavioral runtime test (tests/unit/contract-booking-form-fields.spec.ts) for the v1.4.2 bug: 5 tests asserting mergeBookingFormFields always prepends standard fullName + email regardless of LLM input — preserves order, dedupes redundant LLM-supplied standards, sets required=true. mergeBookingFormFields exported from lib/page-blocks/persist.ts for testability. (4) docs/CONTRACTS.md documenting the rule, annotation pattern, scoped directories, when NOT to throw, how to add a new contract test. The MCP package itself didn't change in v1.9.0 — version bumps coupled with backend so they redeploy together. Test count: 2344 (was 2338; +1 static check + 5 booking contract tests). v1.10 candidate: integration test harness so we can write contract tests for the v1.7.3 + v1.8.1 fixes (currently documented in CONTRACTS.md but not yet runtime-asserted).",
|
|
5
|
+
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.8.1: HOTFIX for /settings/billing crashing when free-tier users click 'Manage subscription'. createBillingPortalSessionAction threw 'No Stripe customer is associated with this account' when the user had never completed a Stripe checkout — the throw cascaded through the SSR boundary and produced 'This page couldn't load — A server error occurred'. Two-layer fix: (1) UI conditionally hides 'Manage subscription' button for free tier, shows 'Upgrade' link instead. Free-tier operators see the right CTA. (2) The action gracefully redirects to /settings/billing?upgrade=needed instead of throwing — defense in depth in case a stale page state, direct form POST, or admin-token edge case still hits the action with no customer. New banner on /settings/billing surfaces the redirect reason ('No active subscription to manage yet — upgrade to manage'). No code changes to the MCP package itself; version bump is coupled with the backend redeploy.",
|
|
4
6
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.8.0: CUSTOM DOMAINS for paying tiers (Growth $29 / Scale $99). Operators on a paid plan can route their own hostname (joescuts.com, ironandoak.ca, bookings.coastlinemusic.ca, etc.) to their workspace; Vercel auto-provisions SSL via Let's Encrypt; subdomain path stays the default for free tier. WHAT SHIPS: (1) workspace_domains table (migration 0039, applied to prod) — workspace_id, hostname (unique among non-removed rows), status walk pending→verified→failed→removed, verification_record jsonb, vercel_domain_id, is_primary, with three indexes including a hot-path lookup for proxy.ts host→workspace resolution. (2) lib/integrations/vercel-domains.ts: thin Vercel Domains API wrapper (vercelAddDomain, vercelGetDomainConfig, vercelRemoveDomain, isValidHostname, isVercelConfigured). Requires VERCEL_TOKEN + VERCEL_PROJECT_ID env vars; returns 'vercel_not_configured' cleanly when missing. (3) lib/domains/store.ts: addCustomDomain (validate + Vercel register + persist + DNS instructions), verifyCustomDomain (Vercel /config check + state transition), listCustomDomainsForWorkspace, removeCustomDomain (mark removed in DB first, then best-effort Vercel cleanup), resolveWorkspaceForCustomDomain (the proxy.ts hot path). (4) Single REST endpoint POST /api/v1/domains dispatching on `op` field (add/verify/list/remove) with workspace bearer auth + tier gate (free returns 402 upgrade_required) + Vercel-configured gate (503 vercel_not_configured) + try/catch wrapping for JSON 500 shape. (5) Four new MCP tools: add_custom_domain, verify_domain, list_workspace_domains, remove_workspace_domain. Free-tier MCP calls surface the 402 with upgrade CTA. (6) /api/v1/public/domain (the proxy hostname-to-workspace resolver) now checks workspace_domains FIRST, then falls back to legacy organizations.settings.customDomain, then to subdomain extraction. (7) Welcome email v2: tier-conditional block between Next-Steps and Discord CTA — free tier sees 'Want your own domain?' upgrade pitch; paid tier sees 'Custom domain ready — ask Claude to add_custom_domain'. WelcomeEmailRequest now accepts optional `tier` param, validateWelcomeRequest passes it through. MCP loads 98 tools (was 94; +4 domain tools). ⚠️ BACKEND REDEPLOY REQUIRED. Migration 0039 already applied. SET VERCEL_TOKEN + VERCEL_PROJECT_ID (+ optional VERCEL_TEAM_ID) on Vercel project env vars to enable the feature; without these, MCP tools return vercel_not_configured.",
|
|
5
7
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.7.3: HOTFIX for /dashboard crashing with 'This page couldn't load' when a NextAuth session exists but the users table has no matching row. Symptom: operator signs into app.seldonframe.com (NextAuth + Resend or Google OAuth), navigates to /dashboard, server returns 500 with `Error: Unauthorized`. Logs show `userId: <real uuid>, userOrgId: <real uuid>, membershipIdsRaw: []`. Root cause: lib/billing/orgs.ts::getBillingUserById threw 'Unauthorized' when the session user.id had no row in the users table (NextAuth Drizzle-adapter race? imported user from another deployment? failed insert?). The throw cascaded through dashboard layout → page → SSR boundary → frontend error. Fix: getBillingUserById now returns a synthesized empty record (id=session-user-id, orgId=null, no plan/sub) instead of throwing. listManagedOrganizations + getOwnedWorkspaceCount + dashboard data-loaders return []/0 for these synthesized users so the dashboard renders an empty 'no workspaces yet' state instead of crashing. Two callers were updated to handle the new nullable user.orgId — listManagedOrganizations builds OR conditions defensively, and the orgId-membership lookup falls back to ownerId/parentUserId paths when user.orgId is null. The MCP package itself didn't change in v1.7.3 — version bumps are coupled across backend + npm by convention so they redeploy together. ⚠️ BACKEND REDEPLOY REQUIRED. v1.8 candidate: auto-create users row on first session OR auto-claim anonymous workspaces by matching operator email when a user signs in (so users see workspaces they created via MCP).",
|
|
6
8
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.7.2: HOTFIX for the device-flow approve handler crashing on production environments without ENCRYPTION_KEY set. Symptom (Iron & Oak test): operator clicks Yes on the browser approval page, server logs `Missing ENCRYPTION_KEY`, returns empty 500, browser shows `Failed to execute 'json' on 'Response': Unexpected end of JSON input`, MCP polling loop keeps returning pending until the 5-min budget exhausts. Three fixes: (1) approveDeviceAuth now wraps encryptValue in try/catch; on failure (missing ENCRYPTION_KEY), stores the bearer raw + logs a warning telling operators to set the env var. The bearer is still single-shot (atomic claim in checkDeviceAuth) + still scoped via atok+status+claimedAt semantics — encryption-at-rest was defense-in-depth, not the primary security. checkDeviceAuth's existing decrypt-or-passthrough logic handles both cases. (2) All four /api/v1/auth/* endpoints (initiate, approve, reject, check) wrapped in try/catch returning JSON 500 on unexpected errors instead of empty bodies — keeps the browser approval page + MCP polling loop showing readable error messages. (3) checkDeviceAuth's decrypt fallback now logs the failure reason. No schema changes. ⚠️ BACKEND REDEPLOY REQUIRED. Existing pending atoks from v1.7.0/v1.7.1 attempts will still expire in 5min — run connect_workspace again to get a fresh atok.",
|
package/src/welcome.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// stripped. `create_full_workspace` is the only workspace-creation
|
|
9
9
|
// path mentioned anywhere in this briefing.
|
|
10
10
|
|
|
11
|
-
export const VERSION = "1.
|
|
11
|
+
export const VERSION = "1.9.0";
|
|
12
12
|
|
|
13
13
|
export const WELCOME_MARKDOWN = `# SeldonFrame — create a real Business OS in one conversation
|
|
14
14
|
|