Skip to main content

Vertical SDK

Build domain-specific applications (verticals) that plug into MeetLoyd. A vertical packages MCP tools, tRPC APIs, databases, and UIs for a specific domain like wealth management, claims processing, or HR payroll.

Installation

pnpm add @meetloyd/vertical-sdk

Or scaffold a complete project:

npx create-meetloyd-vertical claims-management
npx create-meetloyd-vertical claims-management --scope cm --description "Insurance claims"

Quick Start

1. Define tools

import { defineTool, createToolRegistry } from "@meetloyd/vertical-sdk";

const registry = createToolRegistry("claims");

registry.register(
defineTool({
name: "claims_file_new",
description: "File a new insurance claim",
parameters: {
type: "object",
properties: {
policyNumber: { type: "string", description: "Policy number" },
description: { type: "string", description: "Claim description" },
amount: { type: "number", description: "Claimed amount" },
},
required: ["policyNumber", "description"],
},
handler: async (args) => {
// Your business logic here
return { claimId: "CLM-001", status: "filed" };
},
category: "claims",
})
);

export const claimsTools = registry.getAll();

2. Create the vertical entry point

import { defineVertical } from "@meetloyd/vertical-sdk";
import { claimsTools } from "./tools/index.js";

export default defineVertical({
name: "claims",
displayName: "Claims Management",
description: "Insurance claims processing and management",
version: "0.1.0",
scope: "@meetloyd/cm",
categories: ["insurance", "claims"],
tools: claimsTools,
});

3. Add a manifest

Create meetloyd.vertical.json at the root of your project:

{
"name": "claims",
"displayName": "Claims Management",
"description": "Insurance claims processing and management",
"version": "0.1.0",
"scope": "@meetloyd/cm",
"meetloyd": {
"minVersion": "0.1.0"
},
"entryPoints": {
"tools": "./packages/meetloyd-tools/dist/index.js",
"mcpServer": "./packages/mcp-server/dist/index.js",
"api": "./packages/api/dist/index.js",
"prismaSchema": "./packages/db/prisma/schema.prisma"
},
"capabilities": ["mcp-tools", "mcp-server", "trpc-api", "prisma-db"],
"categories": ["insurance", "claims"],
"compliance": ["Solvency II"],
"toolCategories": ["claims", "coverage", "assessment"]
}

Project Structure

The scaffolder creates this monorepo layout:

claims-management/
├── meetloyd.vertical.json # Platform manifest
├── package.json # Root workspace config
├── pnpm-workspace.yaml
├── turbo.json
├── tsconfig.json
└── packages/
├── core/ # Business logic
├── db/ # Prisma database layer
├── api/ # tRPC API routes
├── mcp-server/ # Standalone MCP server
├── meetloyd-tools/ # Tool definitions + vertical entry
└── web/ # Web UI components

API Reference

defineVertical(definition)

Creates a vertical that MeetLoyd can mount and discover.

import { defineVertical } from "@meetloyd/vertical-sdk";

export default defineVertical({
name: "claims", // kebab-case identifier
displayName: "Claims Management", // Human-readable name
description: "Insurance claims platform", // Short description
version: "0.1.0", // Semver
scope: "@meetloyd/cm", // npm scope
categories: ["insurance"], // Discovery categories
compliance: ["Solvency II"], // Compliance frameworks
tools: myTools, // MCPTool[]
resources: myResources, // MCPResource[] (optional)
prompts: myPrompts, // MCPPrompt[] (optional)
});

defineTool(options)

Defines a single MCP tool with type safety.

import { defineTool } from "@meetloyd/vertical-sdk";

const tool = defineTool({
name: "claims_check_coverage",
description: "Check if a policy covers a claim type",
parameters: {
type: "object",
properties: {
policyNumber: { type: "string" },
claimType: { type: "string", enum: ["fire", "theft", "flood"] },
},
required: ["policyNumber", "claimType"],
},
handler: async (args, context) => {
// context.userId, context.tenantId available
return { covered: true, deductible: 500 };
},
category: "coverage",
requiresAuth: true,
rateLimit: { maxCalls: 100, windowMs: 60000 },
});

Tool options:

FieldTypeDescription
namestringUnique tool name (prefix with vertical scope)
descriptionstringWhat the tool does
parametersMCPToolParametersJSON Schema input definition
handler(args, context?) => Promise<any>Execution function
categorystring?Tool category for filtering
requiresAuthboolean?Requires authenticated user
requiresApprovalboolean?Triggers HITL approval
requiredRolesstring[]?Required RBAC roles
rateLimit{ maxCalls, windowMs }?Rate limiting
governanceobject?Data classification, audit level, compliance

createToolRegistry(prefix)

Creates a registry to manage tools for a vertical.

import { createToolRegistry } from "@meetloyd/vertical-sdk";

const registry = createToolRegistry("claims");

registry.register(tool1);
registry.register(tool2);
registry.registerAll([tool3, tool4]);

// Query
registry.getAll(); // MCPTool[]
registry.getByCategory("coverage"); // MCPTool[]
registry.getNames(); // string[]
registry.getStats(); // { coverage: 2, claims: 3 }
registry.getSchemas(); // Tool schemas (no handlers)
registry.size; // number

// Execute
await registry.execute("claims_file_new", { policyNumber: "P-123" });

createMCPServer(options)

Creates a pre-configured MCP server for standalone use.

import { createMCPServer } from "@meetloyd/vertical-sdk";

const { server, start } = createMCPServer({
name: "claims-mcp",
version: "0.1.0",
tools: registry.getAll(),
resources: myResources, // optional
});

start(); // Connects via stdio transport

createVerticalTRPC()

Creates a typed tRPC instance with auth middleware.

import { createVerticalTRPC } from "@meetloyd/vertical-sdk";

const t = createVerticalTRPC<{ userId?: string; tenantId?: string }>();

const appRouter = t.router({
getClaim: t.protectedProcedure // Requires userId
.input(z.object({ id: z.string() }))
.query(({ input }) => getClaim(input.id)),

listClaims: t.publicProcedure
.query(() => listAllClaims()),
});

createPrismaSingleton(key, factory)

Creates a global-safe Prisma client instance (avoids multiple clients in dev).

import { createPrismaSingleton } from "@meetloyd/vertical-sdk";
import { PrismaClient } from "@prisma/client";

export const prisma = createPrismaSingleton("claims", () =>
new PrismaClient()
);

Manifest Reference

The meetloyd.vertical.json file declares your vertical's capabilities to the platform.

FieldTypeRequiredDescription
namestringYesLowercase kebab-case identifier
displayNamestringYesHuman-readable name
descriptionstringYesShort description
versionstringYesSemver version
scopestringYesnpm scope (must start with @meetloyd/)
meetloyd.minVersionstringYesMinimum platform version
entryPoints.toolsstringNoPath to tools module
entryPoints.mcpServerstringNoPath to MCP server
entryPoints.apistringNoPath to tRPC router
entryPoints.prismaSchemastringNoPath to Prisma schema
entryPoints.webstringNoPath to web UI
capabilitiesstring[]Yesmcp-tools, mcp-server, trpc-api, web-ui, prisma-db
categoriesstring[]YesDomain categories
compliancestring[]NoCompliance frameworks
toolCategoriesstring[]NoTool category labels

MCPContext

Every tool handler receives an optional MCPContext:

interface MCPContext {
userId?: string;
tenantId?: string;
agentId?: string;
teamId?: string;
runId?: string;
conversationId?: string;
vertical?: Record<string, unknown>; // Domain-specific state
metadata?: Record<string, unknown>;
}

Resources

Define data resources that agents can read:

import type { MCPResource } from "@meetloyd/vertical-sdk";

const policyResource: MCPResource = {
definition: {
uri: "claims://policies/{policyNumber}",
name: "Policy Details",
description: "Insurance policy information",
mimeType: "application/json",
},
handler: async (uri, context) => {
const policyNumber = uri.split("/").pop();
const policy = await getPolicy(policyNumber);
return { text: JSON.stringify(policy), mimeType: "application/json" };
},
};

export default defineVertical({
// ...
resources: [policyResource],
});

Governance

Tools support governance metadata for regulated industries:

defineTool({
name: "claims_approve_payout",
// ...
requiresApproval: true,
requiredRoles: ["claims_manager"],
rateLimit: { maxCalls: 10, windowMs: 3600000 },
governance: {
dataClassification: "confidential",
auditLevel: "full",
complianceFrameworks: ["Solvency II", "GDPR"],
},
});

Next Steps