@seldonframe/mcp 1.15.0 → 1.16.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 (2) hide show
  1. package/package.json +2 -1
  2. package/src/welcome.js +6 -4
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@seldonframe/mcp",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
+ "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.16.0: WIRE PORTAL TEMPLATE INTO CUSTOMER-FACING ROUTE. v1.15 shipped the templates + renderer + per-customer embeds; the operator could compose templates and verify via preview_portal MCP tool, but customers themselves had no URL to actually SEE the rendered template. v1.16 closes the loop: the existing /portal/[orgSlug] customer-facing route (with magic-link auth already in place pre-v1.16) now renders the operator-defined composite template ABOVE the existing stats grid. WHAT SHIPS: (1) renderPortalForCustomer({ orgId, contactId, workspaceTimezone, workspaceContext }) — server-side helper that loads the template, builds CustomerRenderContext via buildCustomerContext, renders each section, returns html + css. Returns null for empty templates so the page falls through to the existing stats-only view (additive change — workspaces without portal templates see the same UX as pre-v1.16). (2) app/portal/[orgSlug]/(client)/page.tsx wires the helper inline. Existing magic-link session auth provides orgId + contactId; renderPortalForCustomer is awaited in parallel with the existing message + resource queries (cheap). (3) CSS strategy: inject COMPOSITE_CSS + a small token-aliases block scoped to .sf-cmp-portal-host that maps the portal page's --color-primary etc. tokens onto the composite primitive's expected --sf-bg / --sf-text / --sf-border / --sf-primary / --sf-accent variable names. No collisions with the surrounding portal layout. (4) UX FIX from v1.15: get_portal_structure / add_portal_section / etc. used to return preview_url pointing at the MCP-only endpoint (browser-clickable look but required workspace bearer auth — confusing). v1.16 renames the field to customer_portal_url and points at the actual live URL customers visit (https://<slug>.app.seldonframe.com/portal/<slug>). For preview during template-design, operators still use the preview_portal MCP tool. Test count: 2525 (unchanged; v1.16 is a wiring change to existing tested code paths). Typecheck clean. Backward compatible — empty templates fall through cleanly. NO migrations, NO env vars, NO new deps. AUTH MODEL: customers reach the portal via magic-link sent from the operator's admin dashboard (existing pre-v1.16 flow); session is contact-scoped via signPortalSession; renderPortalForCustomer trusts the session's contactId. v1.17+ candidate: stable section IDs for cross-call composition without re-reads.",
4
5
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.15.0: PORTAL COMPOSITE TREES + CUSTOMER.* EMBEDS. The composite primitive vocabulary (12 kinds, v1.12) now extends to the customer-portal surface via 5 new embed.ref values that pull per-customer data: customer.contact_info, customer.next_appointment, customer.recent_appointments, customer.documents, customer.deals. WHY (decisive (α) over (β) on every architectural principle): a portal block IS a landing block with a different render context — same structure, different data binding, different audience. Building a separate portal pipeline (β) would have meant 2× the harness, 2× the agent vocabulary, no compounding of LLM improvements across surfaces. (α) reuses the composite engine; the only new code is per-customer embed render branches + auth-scoped DB resolvers + a workspace-level template store. WHAT SHIPS: (1) Schema extension — 5 new customer.* values added to embed.ref enum; existing 5 workspace embeds still work; unknown refs (customer.password etc) still rejected. (2) CustomerRenderContext extends CompositeRenderContext with customer + 4 per-customer data fields. assembleCustomerContext THROWS on missing customer.id (auth-scope identity, never default to empty). (3) Per-customer DB resolvers (5 functions, each takes orgId+customerId as REQUIRED args, returns auth-scoped data). All five run in parallel via buildCustomerContext. (4) Portal-template storage on organizations.settings.portal_template (CompositeNode[]). One template per workspace; every customer renders against their own data. (5) Five portal MCP tools: get_portal_structure, add_portal_section, update_portal_section, move_portal_section, delete_portal_section. Same atomic-primitive pattern as v1.11/v1.13/v1.14. Empty templates are valid (different from landing's minimum-1 rule — a portal with no template just shows built-in tabs). (6) preview_portal({ workspace_id, contact_id }) renders the template against a real contact for visual verification before customers see it. (7) Renderer extensions: 5 new render branches in renderEmbed (one per customer.* ref). HTML-escaped customer-supplied data (no XSS via document filename or appointment title). (8) Composite SKILL.md addendum: portal patterns (WELCOME / NEXT-VISIT / DOCS+DEALS-SIDE-BY-SIDE), portal voice rules (second-person, customer-addressed), anti-patterns (no cross-customer data, no marketing content). Plus the 'check for near-duplicates before add_composite_section' rule from the v1.14 followup. Test count: 2525 (was 2495; +30: schema/render/assemble + portal-structure pure helpers + XSS + auth-scope contract). NO migrations (template stored on existing settings jsonb), NO env vars, NO new deps. Backward compatible. v1.16 candidate: wire the portal template into a customer-facing rendered route at /portal/<contactId> (currently the rendered HTML is exposed only via the operator-facing preview endpoint).",
5
6
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.14.0: BOOKING FORM STRUCTURAL PRIMITIVES + COMPOSITE CINEMATIC CSS FIX. Five new tools mirror the v1.13 intake-structure pattern but for the booking form, with one critical addition: STANDARD-FIELD CONTRACT — fullName + email at indices 0/1 are server-owned (the renderer + public POST handler require them per the v1.4.2 fix). Destructive ops on indices 0/1 are rejected by design so an operator cannot accidentally break the booking flow. WHAT SHIPS: (1) get_booking_structure — title, description, duration, fields with is_standard flag + 1-line preview. (2) add_booking_field({ field, position? }) — minimum position 2 (slots 0/1 reserved). Allowed types: text, textarea, email, phone, select. ID uniqueness enforced; cannot be 'fullName' or 'email'. (3) move_booking_field({ from_index, to_index }) — both indices must be >= 2. (4) delete_booking_field({ index }) — index must be >= 2; floor is 'just the 2 standards'. (5) update_booking_field({ index, patch }) — index must be >= 2; ID changes blocked from colliding with another field OR with reserved standard ids. Persistence runs through mergeBookingFormFields as defense-in-depth — even if a primitive somehow let a mutation through, the merge re-prepends the standards before persistence. (6) BUNDLED CSS FIX: composite-block renderer adds .sf-frame.sf-cinematic .sf-cmp-* and .sf-frame.sf-light .sf-cmp-* overrides for headline / heading / subhead / text / card / divider / list-x / stat-label / embed-* — fixes the dark-on-dark headline + card-heading bug observed in the v1.12 smoke (composite section text was using var(--sf-text) which resolved to a dark color in workspaces tuned for light backgrounds, then rendered against the cinematic dark backdrop). Mirrors the override pattern in cinematic-overlay.ts for typed sections. Test count: 2495 (was 2475; +20 booking tests). NO migrations, NO env vars, NO new deps. Backward compatible. v1.15: portal blocks (composite tree on customer portal surface, with customer-data embed refs).",
6
7
  "description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.13.0: INTAKE FORM STRUCTURAL PRIMITIVES — five new tools mirror the v1.11 landing-structure pattern but for the intake form surface (linear, no nesting). Operators can now ask 'add a phone field', 'put email at the top', 'rename mobile to cellphone', 'remove the rating question' and the agent calls one atomic tool. WHY: pre-v1.13 the agent had to use persist_block(intake) which REPLACES the whole questions array — a bad fit for incremental edits. v1.13 lets the agent do single-field operations without touching the rest of the form. WHAT SHIPS: (1) get_intake_structure({workspace_id}) — returns title, description, indexed list of fields with type + label + required + 1-line preview. (2) add_intake_field({workspace_id, field, position?}) — append (default) or insert. ID uniqueness enforced. (3) move_intake_field({workspace_id, from_index, to_index}) — splice semantics (atomic). (4) delete_intake_field({workspace_id, index}) — refuses to leave 0 fields (public submit needs ≥1). (5) update_intake_field({workspace_id, index, patch}) — patch any subset of {id, type, label, helper, required, options, ratingScale, validation, showIf}; ID changes blocked from colliding. Persistence touches BOTH Blueprint.intake.questions AND intake_forms.fields (the public POST handler reads the latter); both updated atomically per mutation, formbricks-stack-v1 re-renders. (6) 23 new unit tests covering applyAddField (append / insert / id collision / out-of-range), applyMoveField, applyDeleteField (boundary indices / minimum-1 guard), applyUpdateField (patch / id-collision / type+options together / empty-patch reject), and deriveFieldPreview (label + type + required marker + option count + truncation). Test count: 2475 (was 2452). DESIGN: same thin-harness/fat-skill pattern. Server only validates + persists. Agent's LLM picks WHICH field by reading get_intake_structure previews. Antifragile: as LLMs improve at intent-mapping, output quality rises with zero harness changes. NO migrations, NO env vars, NO new deps. Backward compatible — existing persist_block(intake) still works for full-form replaces.",
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.15.0";
11
+ export const VERSION = "1.16.0";
12
12
 
13
13
  export const WELCOME_MARKDOWN = `# SeldonFrame — create a real Business OS in one conversation
14
14
 
@@ -269,8 +269,10 @@ further natural-language requests ("change the headline to …",
269
269
  as add_composite_section PLUS 5 new customer.* embed refs that
270
270
  pull per-customer data (next appointment, documents, deals,
271
271
  recent appointments, contact info). Template stored once on the
272
- workspace; every customer sees their own data. preview_portal
273
- renders against a real contact for visual verification.
272
+ workspace; every customer sees their own data via magic-link
273
+ login at the customer_portal_url returned in the response (live
274
+ in v1.16+). preview_portal renders the template against a
275
+ specific contact for visual verification.
274
276
  - **\`update_appointment_type\`** — edit the booking page's slot length,
275
277
  title, description.
276
278
  - **\`install_vertical_pack\`** — set up an industry template
@@ -304,4 +306,4 @@ admin dashboard. Pre-fills their email automatically.
304
306
  <https://seldonframe.com> · **Discord:** <https://discord.gg/sbVUu976NW>
305
307
  `;
306
308
 
307
- export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.15.0 is connected. PREFERRED workspace creation: create_workspace_v2 → IN PARALLEL for all 7 recommended_blocks (hero, services, about, faq, cta, booking, intake): get_block_skill + persist_block → complete_workspace_v2 → finalize_workspace({ workspace_id, email }). The v2 flow puts YOUR LLM in charge of every operator-facing surface using one SKILL.md per block. Each block's prop schema is server-validated. Run blocks in PARALLEL (Promise.all) — sequential takes 60+ seconds. v1.10+ TIER 2 CUSTOMIZE TOOLS: regenerate_block (re-do one block with operator instructions; thin-harness — server bundles context, your LLM generates), upload_workspace_image (set logo/hero_background; v1.10.1+ accepts image_url or local_file_path — DON'T base64 unless you have to, the encoded string eats your tool-call token budget). v1.11+ STRUCTURAL PRIMITIVES: get_landing_structure → move_section → delete_section. INDEX-based, handle duplicate section types, atomic. v1.12+ COMPOSITE TREES: add_composite_section / update_composite_section — manifest ANY block (comparison, pricing, "how it works," stats, custom CTAs) from 12 low-level primitives. Server validates + renders; YOUR LLM composes. Read the SKILL.md via get_block_skill('composite') before composing. Every URL is real. NEVER create local files. Skipping finalize_workspace leaves the operator with no admin login.`;
309
+ export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.16.0 is connected. PREFERRED workspace creation: create_workspace_v2 → IN PARALLEL for all 7 recommended_blocks (hero, services, about, faq, cta, booking, intake): get_block_skill + persist_block → complete_workspace_v2 → finalize_workspace({ workspace_id, email }). The v2 flow puts YOUR LLM in charge of every operator-facing surface using one SKILL.md per block. Each block's prop schema is server-validated. Run blocks in PARALLEL (Promise.all) — sequential takes 60+ seconds. v1.10+ TIER 2 CUSTOMIZE TOOLS: regenerate_block (re-do one block with operator instructions; thin-harness — server bundles context, your LLM generates), upload_workspace_image (set logo/hero_background; v1.10.1+ accepts image_url or local_file_path — DON'T base64 unless you have to, the encoded string eats your tool-call token budget). v1.11+ STRUCTURAL PRIMITIVES: get_landing_structure → move_section → delete_section. INDEX-based, handle duplicate section types, atomic. v1.12+ COMPOSITE TREES: add_composite_section / update_composite_section — manifest ANY block (comparison, pricing, "how it works," stats, custom CTAs) from 12 low-level primitives. Server validates + renders; YOUR LLM composes. Read the SKILL.md via get_block_skill('composite') before composing. Every URL is real. NEVER create local files. Skipping finalize_workspace leaves the operator with no admin login.`;