Skip to main content

PMS Sync is currently in a pilot programme; capabilities described here are live in pilot deployments.

Architecture & Dependencies

Architecture & Dependencies

Last updated Owner: AlterspectiveFor: Technical & security reviewers

A deeper technical companion to the Architecture flow page. It answers three questions precisely: what the moving parts are and what they depend on, whether any AI runs when a user imports a matter, and whether the system exposes a Model Context Protocol (MCP) service that an AI agent can use. Short version: a live user import is pure deterministic code — no AI, no MCP in the loop — while AI and MCP exist as separate, well-bounded capabilities described below.

1. The four building blocks

Think of it as a relay team — each part has exactly one job.

Portal

AderantImportPortal

Next.js 15 · React 19 · the UI

The face. The screens staff use to search matters, preview the transform, click Import, and review history. Loads per-org config server-side and brokers it through the Proxy; tenant secrets are stripped before any config reaches the browser. Has no MCP service by design.

Proxy

ShareDoAderantAPIProxy

Express · the brain + the writer

Holds per-tenant secrets, transforms Aderant data into the Clio Operate shape, and is the only component that writes into Clio Operate. Exposes the main MCP service (7 tools, including the gated write tools).

SQL API

AderantSQLAPITypeScript

Express · the on-prem reader

The only component allowed to touch the on-premises Aderant SQL Server. Read-only, column-whitelisted, parameterised. Exposes a read-only MCP service (5 tools). Tunnelled out because the database sits behind a firewall.

Widget

pms-sync-embed

Foundry SDK · runs inside Sharedo

The doorway into Sharedo. A widget that iframes the Portal, uses signed single-sign-on handoff so the Sharedo user is logged in automatically, and brokers API calls back through Sharedo.

Mental model. The Widget is the door into Sharedo · the Portal is the screens · the Proxy is the brain that decides and writes · the SQL API is the hand that reaches into the on-premises database.

2. How one import flows

The money path: a user picks a matter and it becomes a Clio Operate work item. Reads go to Aderant (left); writes go to Clio Operate (right). The Proxy is the only writer.

User + Widget
   │  1 search / select a matter
   ▼
Portal ───2 preview / import (with org config)──▶ Proxy
                                                   │  3 read matter + parties
                                                   ▼
                                                 SQL API ──▶ Aderant SQL (on-prem)
                                                   │  4 transform (deterministic, sandboxed)
                                                   ▼
                                                 Clio Operate API
                                                   │  5 create ODS parties + work item + key dates
                                                   ▼
                                           Portal / Proxy audit
                                      (6 history row or audit event)
Why this shape. The Portal never touches the database, and tenant secrets stay server-side — never exposed to the browser. The SQL API is read-only (it cannot damage Aderant) and the Proxy is the single write choke-point — one place to audit, rate-limit, and gate. That separation is the core safety design.

3. What runs during a user import — and what doesn't

This is the question most people actually want answered. When a user clicks Preview or Import, the runtime path is 100% deterministic. No language model is called, and the MCP service is not involved. The per-tenant field transform runs inside a QuickJS WebAssembly sandbox — sandboxed JavaScript with no network, no I/O, and no timers. Provided a transform does not call non-deterministic globals such as Date.now() or Math.random(), the same input produces the same output.

Runs during a user import

  • Keystone — authenticates the session
  • Supabase — loads the org's config & saved mapping
  • SQL API → Aderant SQL — reads the matter and parties
  • QuickJS sandbox — runs the saved transform (deterministic)
  • Clio Operate API — writes the work item

Does NOT run during a user import

  • No LLM / Synapse call
  • No MCP tool invocation
  • No Anthropic / OpenAI / OpenRouter call
  • No non-deterministic step in platform code (a custom transform using Date.now()/Math.random() is the exception)
The one-line model. AI is design-time (authoring mappings), MCP is an agent-facing front door, and the live user import in the middle is pure deterministic code that touches neither. Imports are therefore auditable and reproducible — no model in the loop.

4. Where the AI actually lives (design-time only)

AI assistance exists, but it is used before any import — when a consultant or administrator authors a work-type mapping transform. The portal offers two admin-only helpers that call the Alterspective Synapse LLM service:

  • Suggest — generate a draft JavaScript transform for a field mapping.
  • Repair — fix a transform that is failing validation.

The administrator reviews the suggestion and saves it as mapping configuration. From then on, every import just executes that saved deterministic snippet. If Synapse were offline, imports would be completely unaffected — only the authoring assistant would be unavailable.

5. The MCP service (for AI agents)

Yes — the system exposes two Model Context Protocol services that an AI agent can use. They are a completely separate surface from the user import path: a different route (/mcp), different authentication (Keystone OAuth 2.1 bearer tokens), and different callers (agents, not the browser). The Portal deliberately has no MCP service — it is the human UI, and its capabilities are already exposed by the two backends.

Proxy MCP — 7 tools (read + gated write)

ToolAccessWhat it does
get_statuspublicHealth of the proxy
list_work_typesreadSharedo work types in the caller's tenant
search_mattersreadSearch Aderant matters by name / code / client
list_client_mattersreadAll matters for a given client code
preview_matterreadDry-run of what an import would produce
import_matterwriteIrreversible — creates the work item + ODS parties
reconcile_closuresread / writeCompare Aderant status vs Sharedo phase; optionally close drifted matters

SQL API MCP — 5 tools (read-only)

ToolAccessWhat it does
get_statuspublicHealth of the SQL agent
list_tablesreadDiscovered Aderant tables / views and their columns
query_tablereadRead rows — columns whitelisted, values parameterised, paginated
search_clientsreadSearch clients by name or code
search_mattersreadSearch matters by name, code, or client
Write tools pass three gates. An MCP write (e.g. import_matter) only proceeds when the caller has the write scope and the org's import_write_enabled flag is on and the call includes confirm: true. The tenant is resolved strictly from the token, never a free parameter, and secrets never leave the proxy.

The elegant part: an agent calling import_matter ends up running the exact same deterministic import code a human triggers — the MCP tool simply calls the proxy's own HTTP API in-process. So AI can initiate an import, but no AI runs inside it. There is no arbitrary-SQL tool by design; every database read is whitelisted and parameterised.

6. Dependency map (key libraries)

JobPortalProxySQL API
Frameworknext 15 · react 19express 4express 5
MCP@modelcontextprotocol/sdk@modelcontextprotocol/sdk
Auth / JWTjose · iron-sessionjosejose
Databasemssql · axios-ntlmmssql
Tunnelhyco-https (Azure Relay)
Config store@supabase/supabase-js@supabase/supabase-js
Transform sandboxquickjs-emscripten
Loggingpinopino · morganstructured JSONL
Security middlewareNext headers / CSPhelmet · cors · rate-limithelmet · cors
AI / observabilitylangfuse · @sentry/nextjs@sentry/node

The Sharedo widget (pms-sync-embed) is built on the Alterspective Foundry SDK and pulls its packages from GitHub Packages.

7. External systems we depend on

SystemUsed byForIf it's down…
Keystone (identity)Portal, MCPStandalone login (OIDC) + MCP token validation (OAuth 2.1)Standalone/OIDC login and MCP calls fail; embedded Sharedo SSO (proxy-signed JWT) is unaffected
SupabasePortal, ProxyPer-org config, mappings, standalone portal historyImports can't resolve the tenant
Clio Operate / Sharedo APIProxy, WidgetThe write target: parties, work items, key datesImports fail at the write step
Aderant SQL Server (on-prem)SQL APIThe source of truth: clients, matters, partiesNothing to read — previews are empty
ngrok / Azure RelaySQL APIOutbound tunnel so the cloud can reach on-premCloud loses its link to on-prem data
Synapse LLMPortalAI-assisted mapping authoring (design-time only)Authoring assistant unavailable; imports still work
GitHub PackagesWidget (build)Foundry SDK packagesWidget can't build / deploy
Most fragile link. The on-premises SQL Server plus its tunnel is the dependency to watch (firewall, local host, tunnel session). Keystone is the hard dependency for all authentication. Everything else degrades gracefully — including, notably, the AI authoring assistant.