Hello from MCP server
/**
* Organization Framework Module
*
* Provides access to organization data and variables for the current user's active org.
*/
import { getApi } from "@/dataAccess/getApi";
import { getDb } from "@/dataAccess/getDb";
/**
* Pricing-related organization variables
*/
export interface OrgPricingVars {
hourlyFee: number;
salesTax: number;
serviceCallFee: number;
saDiscount: number;
}
/**
* Default pricing variables (in base currency XAG)
* Used when org variables are not set
*/
export const DEFAULT_PRICING_VARS: OrgPricingVars = {
hourlyFee: 5.257444573770893, // ~$200/hr at 38.04 XAG/USD
salesTax: 1.08, // 8% tax
serviceCallFee: 2.0, // ~$76 service call fee
saDiscount: 1.0, // No discount (1 = 100%)
};
/**
* Full organization variables (may include additional fields)
*/
export interface OrgVariables extends Partial<OrgPricingVars> {
preApprovedEmails?: string[];
[key: string]: any;
}
/**
* Organization record
*/
export interface OrgRecord {
id: string;
name: string;
owner: string;
currency?: string;
variables: OrgVariables;
}
/**
* Get the current user's active organization ID
*/
export async function getActiveOrgId(): Promise<string | null> {
const { pb } = await getApi();
return pb.authStore.record?.activeOrg || null;
}
/**
* Get organization variables from the local database
* Returns empty object if no org is found
*/
export async function getOrgVariables(): Promise<OrgVariables> {
try {
const { pb } = await getApi();
const activeOrgId = pb.authStore.record?.activeOrg;
if (!activeOrgId) {
return {};
}
const db = await getDb();
const result = await db.dbConn.query(
`SELECT variables FROM organizations WHERE id = ? LIMIT 1`,
[activeOrgId]
);
if (!result.values || result.values.length === 0) {
return {};
}
const org = result.values[0];
return org.variables ? JSON.parse(org.variables) : {};
} catch (e) {
console.warn("[framework/org] Could not load org variables:", e);
return {};
}
}
/**
* Get pricing variables with defaults for any missing values
* This is the primary function for getting pricing-related org vars
*/
export async function getPricingVars(): Promise<OrgPricingVars> {
const orgVars = await getOrgVariables();
return {
hourlyFee: orgVars.hourlyFee ?? DEFAULT_PRICING_VARS.hourlyFee,
salesTax: orgVars.salesTax ?? DEFAULT_PRICING_VARS.salesTax,
serviceCallFee: orgVars.serviceCallFee ?? DEFAULT_PRICING_VARS.serviceCallFee,
saDiscount: orgVars.saDiscount ?? DEFAULT_PRICING_VARS.saDiscount,
};
}
/**
* Get the full organization record from the local database
*/
export async function getOrg(): Promise<OrgRecord | null> {
try {
const { pb } = await getApi();
const activeOrgId = pb.authStore.record?.activeOrg;
if (!activeOrgId) {
return null;
}
const db = await getDb();
const result = await db.dbConn.query(
`SELECT * FROM organizations WHERE id = ? LIMIT 1`,
[activeOrgId]
);
if (!result.values || result.values.length === 0) {
return null;
}
const org = result.values[0];
return {
id: org.id,
name: org.name,
owner: org.owner,
currency: org.currency,
variables: org.variables ? JSON.parse(org.variables) : {},
};
} catch (e) {
console.warn("[framework/org] Could not load org:", e);
return null;
}
}
/**
* Refresh organization data from the API
* Call this after org changes to update local cache
*/
export async function refreshOrg(): Promise<void> {
try {
const db = await getDb();
await db.collections.organizations.refresh();
} catch (e) {
console.warn("[framework/org] Could not refresh org:", e);
}
}