@sodiumhq/mcp-pm 0.1.0-beta.4441 → 0.1.0-beta.4445

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/README.md CHANGED
@@ -62,6 +62,8 @@ Only enable write mode with an AI client you trust — it hands the client the a
62
62
  - **`get_practice_dashboard`** — one-call "state of the practice right now": overdue/blocked/due-soon work, what clients are sitting on, unassigned steps, unbilled time, open proposal pipeline. *"Give me my morning briefing."*
63
63
  - **`get_practice_details`** — consolidated practice overview (counts, connections, settings)
64
64
  - **`whoami`** — show the authenticated user (name, email, code), tenant (name, code, status), and practice name. Useful for verifying which account is connected.
65
+ - **`list_practices`** — list the practices you belong to, marking the active one. *"Which practices can I access?"*
66
+ - **`set_active_practice`** — choose which practice to work in, or switch mid-session. *"Switch to Oceans."* Needed when you belong to more than one practice.
65
67
 
66
68
  **Clients**
67
69
  - **`list_clients`** — list and filter clients by search, status, type, assignee, services, saved filters
package/dist/http.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as buildServer } from "./src-CTHTAM7g.mjs";
2
+ import { t as buildServer } from "./src-BRf2g74U.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
5
  import { createServer } from "node:http";
@@ -195,7 +195,6 @@ async function createSession(req) {
195
195
  }
196
196
  const tenantHeader = req.headers["x-sodium-tenant"];
197
197
  const tenant = (Array.isArray(tenantHeader) ? tenantHeader[0] : tenantHeader) ?? process.env.SODIUM_TENANT;
198
- if (!tenant) throw new HttpError(400, "x-sodium-tenant header is required (or set SODIUM_TENANT).");
199
198
  const server = await buildServer({
200
199
  context: {
201
200
  bearerToken: apiToken,
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as buildServer } from "./src-CTHTAM7g.mjs";
2
+ import { t as buildServer } from "./src-BRf2g74U.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
5
  import { parseArgs } from "node:util";
@@ -2055,6 +2055,22 @@ const listTeams = (options) => (options.client ?? client).get({
2055
2055
  ...options
2056
2056
  });
2057
2057
  /**
2058
+ * List Tenants
2059
+ *
2060
+ * Returns a list of all tenants that the authenticated user is a member of.
2061
+ */
2062
+ const listTenants = (options) => (options?.client ?? client).get({
2063
+ security: [{
2064
+ name: "x-api-key",
2065
+ type: "apiKey"
2066
+ }, {
2067
+ scheme: "bearer",
2068
+ type: "http"
2069
+ }],
2070
+ url: "/tenants",
2071
+ ...options
2072
+ });
2073
+ /**
2058
2074
  * Get Tenant
2059
2075
  *
2060
2076
  * Retrieves the details of a tenant using its Code identifier.
@@ -2203,9 +2219,11 @@ var SodiumApiClient = class {
2203
2219
  serverVersion;
2204
2220
  mcpClient = null;
2205
2221
  http;
2222
+ activeTenant;
2206
2223
  constructor(ctx, options) {
2207
2224
  this.ctx = ctx;
2208
2225
  this.serverVersion = options.serverVersion;
2226
+ this.activeTenant = ctx.tenant ?? "";
2209
2227
  this.http = createClient$1(createConfig({
2210
2228
  baseUrl: ctx.baseUrl,
2211
2229
  headers: {
@@ -2214,6 +2232,28 @@ var SodiumApiClient = class {
2214
2232
  }
2215
2233
  }));
2216
2234
  }
2235
+ get tenant() {
2236
+ if (!this.activeTenant) throw new Error("No practice selected. Call set_active_practice with a code from list_practices first.");
2237
+ return this.activeTenant;
2238
+ }
2239
+ hasActiveTenant() {
2240
+ return this.activeTenant.length > 0;
2241
+ }
2242
+ getActiveTenant() {
2243
+ return this.activeTenant;
2244
+ }
2245
+ setActiveTenant(code) {
2246
+ this.activeTenant = code;
2247
+ }
2248
+ async listTenants() {
2249
+ const correlationId = randomUUID();
2250
+ const { data, error, response } = await listTenants({
2251
+ headers: { "X-Correlation-Id": correlationId },
2252
+ client: this.http
2253
+ });
2254
+ if (error !== void 0 || !data) throw this.toError(response, error, correlationId, "list practices");
2255
+ return data;
2256
+ }
2217
2257
  buildAuthHeader() {
2218
2258
  if (this.ctx.bearerToken) return { Authorization: `Bearer ${this.ctx.bearerToken}` };
2219
2259
  if (this.ctx.apiKey) return { "x-api-key": this.ctx.apiKey };
@@ -2231,7 +2271,7 @@ var SodiumApiClient = class {
2231
2271
  async getPracticeDetails() {
2232
2272
  const correlationId = randomUUID();
2233
2273
  const { data, error, response } = await getPracticeDetails({
2234
- path: { tenant: this.ctx.tenant },
2274
+ path: { tenant: this.tenant },
2235
2275
  headers: { "X-Correlation-Id": correlationId },
2236
2276
  client: this.http
2237
2277
  });
@@ -2241,7 +2281,7 @@ var SodiumApiClient = class {
2241
2281
  async getTenantDetails() {
2242
2282
  const correlationId = randomUUID();
2243
2283
  const { data, error, response } = await getTenantByCode({
2244
- path: { code: this.ctx.tenant },
2284
+ path: { code: this.tenant },
2245
2285
  headers: { "X-Correlation-Id": correlationId },
2246
2286
  client: this.http
2247
2287
  });
@@ -2260,7 +2300,7 @@ var SodiumApiClient = class {
2260
2300
  async listClients(query = {}) {
2261
2301
  const correlationId = randomUUID();
2262
2302
  const { data, error, response } = await listClients({
2263
- path: { tenant: this.ctx.tenant },
2303
+ path: { tenant: this.tenant },
2264
2304
  query: {
2265
2305
  ...query,
2266
2306
  limit: query.limit ?? 10,
@@ -2276,7 +2316,7 @@ var SodiumApiClient = class {
2276
2316
  const correlationId = randomUUID();
2277
2317
  const { data, error, response } = await getClient({
2278
2318
  path: {
2279
- tenant: this.ctx.tenant,
2319
+ tenant: this.tenant,
2280
2320
  code
2281
2321
  },
2282
2322
  headers: { "X-Correlation-Id": correlationId },
@@ -2289,7 +2329,7 @@ var SodiumApiClient = class {
2289
2329
  const correlationId = randomUUID();
2290
2330
  const { data, error, response } = await listClientContactsForClient({
2291
2331
  path: {
2292
- tenant: this.ctx.tenant,
2332
+ tenant: this.tenant,
2293
2333
  client: clientCode
2294
2334
  },
2295
2335
  query: {
@@ -2306,7 +2346,7 @@ var SodiumApiClient = class {
2306
2346
  const correlationId = randomUUID();
2307
2347
  const { data, error, response } = await listClientBillableServicesForClient({
2308
2348
  path: {
2309
- tenant: this.ctx.tenant,
2349
+ tenant: this.tenant,
2310
2350
  client: clientCode
2311
2351
  },
2312
2352
  query: {
@@ -2323,7 +2363,7 @@ var SodiumApiClient = class {
2323
2363
  const correlationId = randomUUID();
2324
2364
  const { data, error, response } = await getBusinessDetailsForClient({
2325
2365
  path: {
2326
- tenant: this.ctx.tenant,
2366
+ tenant: this.tenant,
2327
2367
  client: clientCode
2328
2368
  },
2329
2369
  headers: { "X-Correlation-Id": correlationId },
@@ -2336,7 +2376,7 @@ var SodiumApiClient = class {
2336
2376
  const correlationId = randomUUID();
2337
2377
  const { data, error, response } = await getClientDates({
2338
2378
  path: {
2339
- tenant: this.ctx.tenant,
2379
+ tenant: this.tenant,
2340
2380
  code: clientCode
2341
2381
  },
2342
2382
  headers: { "X-Correlation-Id": correlationId },
@@ -2348,7 +2388,7 @@ var SodiumApiClient = class {
2348
2388
  async listUsers(query = {}) {
2349
2389
  const correlationId = randomUUID();
2350
2390
  const { data, error, response } = await listTenantUsers({
2351
- path: { tenant: this.ctx.tenant },
2391
+ path: { tenant: this.tenant },
2352
2392
  query: {
2353
2393
  ...query,
2354
2394
  limit: query.limit ?? 10,
@@ -2363,7 +2403,7 @@ var SodiumApiClient = class {
2363
2403
  async listServices(query = {}) {
2364
2404
  const correlationId = randomUUID();
2365
2405
  const { data, error, response } = await listBillableServices({
2366
- path: { tenant: this.ctx.tenant },
2406
+ path: { tenant: this.tenant },
2367
2407
  query: {
2368
2408
  ...query,
2369
2409
  limit: query.limit ?? 10,
@@ -2379,7 +2419,7 @@ var SodiumApiClient = class {
2379
2419
  const correlationId = randomUUID();
2380
2420
  const { data, error, response } = await getBillableService({
2381
2421
  path: {
2382
- tenant: this.ctx.tenant,
2422
+ tenant: this.tenant,
2383
2423
  code
2384
2424
  },
2385
2425
  headers: { "X-Correlation-Id": correlationId },
@@ -2391,7 +2431,7 @@ var SodiumApiClient = class {
2391
2431
  async listTasks(query = {}) {
2392
2432
  const correlationId = randomUUID();
2393
2433
  const { data, error, response } = await listTaskItems({
2394
- path: { tenant: this.ctx.tenant },
2434
+ path: { tenant: this.tenant },
2395
2435
  query: {
2396
2436
  ...query,
2397
2437
  limit: query.limit ?? 10,
@@ -2407,7 +2447,7 @@ var SodiumApiClient = class {
2407
2447
  const correlationId = randomUUID();
2408
2448
  const { data, error, response } = await getTaskItem({
2409
2449
  path: {
2410
- tenant: this.ctx.tenant,
2450
+ tenant: this.tenant,
2411
2451
  code
2412
2452
  },
2413
2453
  headers: { "X-Correlation-Id": correlationId },
@@ -2420,7 +2460,7 @@ var SodiumApiClient = class {
2420
2460
  const correlationId = randomUUID();
2421
2461
  const { data, error, response } = await listTaskItemNotes({
2422
2462
  path: {
2423
- tenant: this.ctx.tenant,
2463
+ tenant: this.tenant,
2424
2464
  taskCode
2425
2465
  },
2426
2466
  query: {
@@ -2437,7 +2477,7 @@ var SodiumApiClient = class {
2437
2477
  async listEngagements(query = {}) {
2438
2478
  const correlationId = randomUUID();
2439
2479
  const { data, error, response } = await listEngagements({
2440
- path: { tenant: this.ctx.tenant },
2480
+ path: { tenant: this.tenant },
2441
2481
  query: {
2442
2482
  ...query,
2443
2483
  limit: query.limit ?? 10,
@@ -2453,7 +2493,7 @@ var SodiumApiClient = class {
2453
2493
  const correlationId = randomUUID();
2454
2494
  const { data, error, response } = await getEngagement({
2455
2495
  path: {
2456
- tenant: this.ctx.tenant,
2496
+ tenant: this.tenant,
2457
2497
  code
2458
2498
  },
2459
2499
  headers: { "X-Correlation-Id": correlationId },
@@ -2466,7 +2506,7 @@ var SodiumApiClient = class {
2466
2506
  const correlationId = randomUUID();
2467
2507
  const { data, error, response } = await getEngagementEmails({
2468
2508
  path: {
2469
- tenant: this.ctx.tenant,
2509
+ tenant: this.tenant,
2470
2510
  code
2471
2511
  },
2472
2512
  headers: { "X-Correlation-Id": correlationId },
@@ -2479,7 +2519,7 @@ var SodiumApiClient = class {
2479
2519
  const correlationId = randomUUID();
2480
2520
  const { data, error, response } = await getTaskWorkflowGroups({
2481
2521
  path: {
2482
- tenant: this.ctx.tenant,
2522
+ tenant: this.tenant,
2483
2523
  taskCode
2484
2524
  },
2485
2525
  headers: { "X-Correlation-Id": correlationId },
@@ -2492,7 +2532,7 @@ var SodiumApiClient = class {
2492
2532
  const correlationId = randomUUID();
2493
2533
  const { data, error, response } = await createTaskItemNote({
2494
2534
  path: {
2495
- tenant: this.ctx.tenant,
2535
+ tenant: this.tenant,
2496
2536
  taskCode
2497
2537
  },
2498
2538
  body,
@@ -2506,7 +2546,7 @@ var SodiumApiClient = class {
2506
2546
  const correlationId = randomUUID();
2507
2547
  const { data, error, response } = await createClientNoteForClient({
2508
2548
  path: {
2509
- tenant: this.ctx.tenant,
2549
+ tenant: this.tenant,
2510
2550
  client: clientCode
2511
2551
  },
2512
2552
  body,
@@ -2519,7 +2559,7 @@ var SodiumApiClient = class {
2519
2559
  async createClient(body) {
2520
2560
  const correlationId = randomUUID();
2521
2561
  const { data, error, response } = await createClient({
2522
- path: { tenant: this.ctx.tenant },
2562
+ path: { tenant: this.tenant },
2523
2563
  body,
2524
2564
  headers: { "X-Correlation-Id": correlationId },
2525
2565
  client: this.http
@@ -2531,7 +2571,7 @@ var SodiumApiClient = class {
2531
2571
  const correlationId = randomUUID();
2532
2572
  const { data, error, response } = await createContactForClient({
2533
2573
  path: {
2534
- tenant: this.ctx.tenant,
2574
+ tenant: this.tenant,
2535
2575
  client: clientCode
2536
2576
  },
2537
2577
  body,
@@ -2545,7 +2585,7 @@ var SodiumApiClient = class {
2545
2585
  const correlationId = randomUUID();
2546
2586
  const { data, error, response } = await listClientNotesForClient({
2547
2587
  path: {
2548
- tenant: this.ctx.tenant,
2588
+ tenant: this.tenant,
2549
2589
  client: clientCode
2550
2590
  },
2551
2591
  query: {
@@ -2562,7 +2602,7 @@ var SodiumApiClient = class {
2562
2602
  async listCustomFieldDefinitions(query = {}) {
2563
2603
  const correlationId = randomUUID();
2564
2604
  const { data, error, response } = await listCustomFieldDefinitions({
2565
- path: { tenant: this.ctx.tenant },
2605
+ path: { tenant: this.tenant },
2566
2606
  query: {
2567
2607
  ...query,
2568
2608
  limit: query.limit ?? 50,
@@ -2578,7 +2618,7 @@ var SodiumApiClient = class {
2578
2618
  const correlationId = randomUUID();
2579
2619
  const { data, error, response } = await getCustomFieldDefinition({
2580
2620
  path: {
2581
- tenant: this.ctx.tenant,
2621
+ tenant: this.tenant,
2582
2622
  code
2583
2623
  },
2584
2624
  headers: { "X-Correlation-Id": correlationId },
@@ -2591,7 +2631,7 @@ var SodiumApiClient = class {
2591
2631
  const correlationId = randomUUID();
2592
2632
  const { data, error, response } = await getClientCustomFieldValues({
2593
2633
  path: {
2594
- tenant: this.ctx.tenant,
2634
+ tenant: this.tenant,
2595
2635
  client: clientCode
2596
2636
  },
2597
2637
  headers: { "X-Correlation-Id": correlationId },
@@ -2604,7 +2644,7 @@ var SodiumApiClient = class {
2604
2644
  const correlationId = randomUUID();
2605
2645
  const { error, response } = await setClientCustomFieldValues({
2606
2646
  path: {
2607
- tenant: this.ctx.tenant,
2647
+ tenant: this.tenant,
2608
2648
  client: clientCode
2609
2649
  },
2610
2650
  body: values,
@@ -2616,7 +2656,7 @@ var SodiumApiClient = class {
2616
2656
  async listContacts(query = {}) {
2617
2657
  const correlationId = randomUUID();
2618
2658
  const { data, error, response } = await listContacts({
2619
- path: { tenant: this.ctx.tenant },
2659
+ path: { tenant: this.tenant },
2620
2660
  query: {
2621
2661
  ...query,
2622
2662
  limit: query.limit ?? 10,
@@ -2632,7 +2672,7 @@ var SodiumApiClient = class {
2632
2672
  const correlationId = randomUUID();
2633
2673
  const { data, error, response } = await getContact({
2634
2674
  path: {
2635
- tenant: this.ctx.tenant,
2675
+ tenant: this.tenant,
2636
2676
  code
2637
2677
  },
2638
2678
  headers: { "X-Correlation-Id": correlationId },
@@ -2644,7 +2684,7 @@ var SodiumApiClient = class {
2644
2684
  async createContact(body) {
2645
2685
  const correlationId = randomUUID();
2646
2686
  const { data, error, response } = await createContact({
2647
- path: { tenant: this.ctx.tenant },
2687
+ path: { tenant: this.tenant },
2648
2688
  body,
2649
2689
  headers: { "X-Correlation-Id": correlationId },
2650
2690
  client: this.http
@@ -2656,7 +2696,7 @@ var SodiumApiClient = class {
2656
2696
  const correlationId = randomUUID();
2657
2697
  const { data, error, response } = await updateContact({
2658
2698
  path: {
2659
- tenant: this.ctx.tenant,
2699
+ tenant: this.tenant,
2660
2700
  code
2661
2701
  },
2662
2702
  body,
@@ -2669,7 +2709,7 @@ var SodiumApiClient = class {
2669
2709
  async getServiceDeliveryReport(query = {}) {
2670
2710
  const correlationId = randomUUID();
2671
2711
  const { data, error, response } = await getServiceDeliveryReport({
2672
- path: { tenant: this.ctx.tenant },
2712
+ path: { tenant: this.tenant },
2673
2713
  query: {
2674
2714
  ...query,
2675
2715
  limit: query.limit ?? 25,
@@ -2684,7 +2724,7 @@ var SodiumApiClient = class {
2684
2724
  async getServiceDeliverySteps(query) {
2685
2725
  const correlationId = randomUUID();
2686
2726
  const { data, error, response } = await getServiceDeliveryStepBottlenecks({
2687
- path: { tenant: this.ctx.tenant },
2727
+ path: { tenant: this.tenant },
2688
2728
  query,
2689
2729
  headers: { "X-Correlation-Id": correlationId },
2690
2730
  client: this.http
@@ -2695,7 +2735,7 @@ var SodiumApiClient = class {
2695
2735
  async getDeadlineComplianceReport(query = {}) {
2696
2736
  const correlationId = randomUUID();
2697
2737
  const { data, error, response } = await getDeadlineComplianceReport({
2698
- path: { tenant: this.ctx.tenant },
2738
+ path: { tenant: this.tenant },
2699
2739
  query: {
2700
2740
  ...query,
2701
2741
  limit: query.limit ?? 25,
@@ -2710,7 +2750,7 @@ var SodiumApiClient = class {
2710
2750
  async getClientResponsivenessReport(query = {}) {
2711
2751
  const correlationId = randomUUID();
2712
2752
  const { data, error, response } = await getClientResponsivenessReport({
2713
- path: { tenant: this.ctx.tenant },
2753
+ path: { tenant: this.tenant },
2714
2754
  query: {
2715
2755
  ...query,
2716
2756
  limit: query.limit ?? 25,
@@ -2725,7 +2765,7 @@ var SodiumApiClient = class {
2725
2765
  async getTeamWorkloadReport(query = {}) {
2726
2766
  const correlationId = randomUUID();
2727
2767
  const { data, error, response } = await getTeamWorkloadReport({
2728
- path: { tenant: this.ctx.tenant },
2768
+ path: { tenant: this.tenant },
2729
2769
  query: {
2730
2770
  ...query,
2731
2771
  limit: query.limit ?? 25,
@@ -2740,7 +2780,7 @@ var SodiumApiClient = class {
2740
2780
  async getWipAgeingReport(query = {}) {
2741
2781
  const correlationId = randomUUID();
2742
2782
  const { data, error, response } = await getWipAgeingReport({
2743
- path: { tenant: this.ctx.tenant },
2783
+ path: { tenant: this.tenant },
2744
2784
  query: {
2745
2785
  ...query,
2746
2786
  limit: query.limit ?? 25,
@@ -2755,7 +2795,7 @@ var SodiumApiClient = class {
2755
2795
  async getWorkflowStepAnalysis(query) {
2756
2796
  const correlationId = randomUUID();
2757
2797
  const { data, error, response } = await getWorkflowStepAnalysisReport({
2758
- path: { tenant: this.ctx.tenant },
2798
+ path: { tenant: this.tenant },
2759
2799
  query,
2760
2800
  headers: { "X-Correlation-Id": correlationId },
2761
2801
  client: this.http
@@ -2766,7 +2806,7 @@ var SodiumApiClient = class {
2766
2806
  async listWorkflowOccurrences(query) {
2767
2807
  const correlationId = randomUUID();
2768
2808
  const { data, error, response } = await getWorkflowStepAnalysisOccurrences({
2769
- path: { tenant: this.ctx.tenant },
2809
+ path: { tenant: this.tenant },
2770
2810
  query: {
2771
2811
  ...query,
2772
2812
  limit: query.limit ?? 10,
@@ -2781,7 +2821,7 @@ var SodiumApiClient = class {
2781
2821
  async getServiceTimeReport(query = {}) {
2782
2822
  const correlationId = randomUUID();
2783
2823
  const { data, error, response } = await getServiceTimeReport({
2784
- path: { tenant: this.ctx.tenant },
2824
+ path: { tenant: this.tenant },
2785
2825
  query: {
2786
2826
  ...query,
2787
2827
  limit: query.limit ?? 25,
@@ -2796,7 +2836,7 @@ var SodiumApiClient = class {
2796
2836
  async listWorkflows(query = {}) {
2797
2837
  const correlationId = randomUUID();
2798
2838
  const { data, error, response } = await listWorkflows({
2799
- path: { tenant: this.ctx.tenant },
2839
+ path: { tenant: this.tenant },
2800
2840
  query: {
2801
2841
  ...query,
2802
2842
  limit: query.limit ?? 10,
@@ -2812,7 +2852,7 @@ var SodiumApiClient = class {
2812
2852
  const correlationId = randomUUID();
2813
2853
  const { data, error, response } = await getWorkflow({
2814
2854
  path: {
2815
- tenant: this.ctx.tenant,
2855
+ tenant: this.tenant,
2816
2856
  code
2817
2857
  },
2818
2858
  headers: { "X-Correlation-Id": correlationId },
@@ -2824,7 +2864,7 @@ var SodiumApiClient = class {
2824
2864
  async listTeams(query = {}) {
2825
2865
  const correlationId = randomUUID();
2826
2866
  const { data, error, response } = await listTeams({
2827
- path: { tenant: this.ctx.tenant },
2867
+ path: { tenant: this.tenant },
2828
2868
  query: {
2829
2869
  ...query,
2830
2870
  limit: query.limit ?? 10,
@@ -2839,7 +2879,7 @@ var SodiumApiClient = class {
2839
2879
  async listTaskCategories(query = {}) {
2840
2880
  const correlationId = randomUUID();
2841
2881
  const { data, error, response } = await listTaskCategories({
2842
- path: { tenant: this.ctx.tenant },
2882
+ path: { tenant: this.tenant },
2843
2883
  query: {
2844
2884
  ...query,
2845
2885
  limit: query.limit ?? 10,
@@ -2854,7 +2894,7 @@ var SodiumApiClient = class {
2854
2894
  async listSavedTaskFilters(query = {}) {
2855
2895
  const correlationId = randomUUID();
2856
2896
  const { data, error, response } = await listSavedTaskFilters({
2857
- path: { tenant: this.ctx.tenant },
2897
+ path: { tenant: this.tenant },
2858
2898
  query: {
2859
2899
  ...query,
2860
2900
  limit: query.limit ?? 10,
@@ -2869,7 +2909,7 @@ var SodiumApiClient = class {
2869
2909
  async listSavedClientFilters(query = {}) {
2870
2910
  const correlationId = randomUUID();
2871
2911
  const { data, error, response } = await listSavedClientFilters({
2872
- path: { tenant: this.ctx.tenant },
2912
+ path: { tenant: this.tenant },
2873
2913
  query: {
2874
2914
  ...query,
2875
2915
  limit: query.limit ?? 10,
@@ -2884,7 +2924,7 @@ var SodiumApiClient = class {
2884
2924
  async searchCompaniesHouse(query) {
2885
2925
  const correlationId = randomUUID();
2886
2926
  const { data, error, response } = await searchCompanies({
2887
- path: { tenant: this.ctx.tenant },
2927
+ path: { tenant: this.tenant },
2888
2928
  query,
2889
2929
  headers: { "X-Correlation-Id": correlationId },
2890
2930
  client: this.http
@@ -2896,7 +2936,7 @@ var SodiumApiClient = class {
2896
2936
  const correlationId = randomUUID();
2897
2937
  const { data, error, response } = await getCompanyDetails({
2898
2938
  path: {
2899
- tenant: this.ctx.tenant,
2939
+ tenant: this.tenant,
2900
2940
  companyNumber
2901
2941
  },
2902
2942
  headers: { "X-Correlation-Id": correlationId },
@@ -2909,7 +2949,7 @@ var SodiumApiClient = class {
2909
2949
  const correlationId = randomUUID();
2910
2950
  const { data, error, response } = await getCompanyKeyDates({
2911
2951
  path: {
2912
- tenant: this.ctx.tenant,
2952
+ tenant: this.tenant,
2913
2953
  companyNumber
2914
2954
  },
2915
2955
  headers: { "X-Correlation-Id": correlationId },
@@ -2922,7 +2962,7 @@ var SodiumApiClient = class {
2922
2962
  const correlationId = randomUUID();
2923
2963
  const { data, error, response } = await getCompanyOfficers({
2924
2964
  path: {
2925
- tenant: this.ctx.tenant,
2965
+ tenant: this.tenant,
2926
2966
  companyNumber
2927
2967
  },
2928
2968
  headers: { "X-Correlation-Id": correlationId },
@@ -2934,7 +2974,7 @@ var SodiumApiClient = class {
2934
2974
  async listDocumentRequests(query = {}) {
2935
2975
  const correlationId = randomUUID();
2936
2976
  const { data, error, response } = await listAllDocumentRequests({
2937
- path: { tenant: this.ctx.tenant },
2977
+ path: { tenant: this.tenant },
2938
2978
  query: {
2939
2979
  ...query,
2940
2980
  limit: query.limit ?? 10,
@@ -2949,7 +2989,7 @@ var SodiumApiClient = class {
2949
2989
  async listDataFormRequests(query = {}) {
2950
2990
  const correlationId = randomUUID();
2951
2991
  const { data, error, response } = await listDataFormRequests({
2952
- path: { tenant: this.ctx.tenant },
2992
+ path: { tenant: this.tenant },
2953
2993
  query: {
2954
2994
  ...query,
2955
2995
  limit: query.limit ?? 10,
@@ -2964,7 +3004,7 @@ var SodiumApiClient = class {
2964
3004
  async listTimeEntries(query = {}) {
2965
3005
  const correlationId = randomUUID();
2966
3006
  const { data, error, response } = await listTimeEntries({
2967
- path: { tenant: this.ctx.tenant },
3007
+ path: { tenant: this.tenant },
2968
3008
  query: {
2969
3009
  ...query,
2970
3010
  limit: query.limit ?? 10,
@@ -2979,7 +3019,7 @@ var SodiumApiClient = class {
2979
3019
  async createTimeEntry(body) {
2980
3020
  const correlationId = randomUUID();
2981
3021
  const { data, error, response } = await createTimeEntry({
2982
- path: { tenant: this.ctx.tenant },
3022
+ path: { tenant: this.tenant },
2983
3023
  body,
2984
3024
  headers: { "X-Correlation-Id": correlationId },
2985
3025
  client: this.http
@@ -2990,7 +3030,7 @@ var SodiumApiClient = class {
2990
3030
  async listRecurringTasks(query = {}) {
2991
3031
  const correlationId = randomUUID();
2992
3032
  const { data, error, response } = await listRecurringTaskItems({
2993
- path: { tenant: this.ctx.tenant },
3033
+ path: { tenant: this.tenant },
2994
3034
  query: {
2995
3035
  ...query,
2996
3036
  limit: query.limit ?? 10,
@@ -3005,7 +3045,7 @@ var SodiumApiClient = class {
3005
3045
  async listSentEmails(query = {}) {
3006
3046
  const correlationId = randomUUID();
3007
3047
  const { data, error, response } = await listEmails({
3008
- path: { tenant: this.ctx.tenant },
3048
+ path: { tenant: this.tenant },
3009
3049
  query: {
3010
3050
  ...query,
3011
3051
  limit: query.limit ?? 10,
@@ -3021,7 +3061,7 @@ var SodiumApiClient = class {
3021
3061
  const correlationId = randomUUID();
3022
3062
  const { data, error, response } = await getEmailDetails({
3023
3063
  path: {
3024
- tenant: this.ctx.tenant,
3064
+ tenant: this.tenant,
3025
3065
  emailId
3026
3066
  },
3027
3067
  headers: { "X-Correlation-Id": correlationId },
@@ -3034,7 +3074,7 @@ var SodiumApiClient = class {
3034
3074
  const correlationId = randomUUID();
3035
3075
  const { data, error, response } = await getClientEmails({
3036
3076
  path: {
3037
- tenant: this.ctx.tenant,
3077
+ tenant: this.tenant,
3038
3078
  client: clientCode
3039
3079
  },
3040
3080
  query: {
@@ -3051,7 +3091,7 @@ var SodiumApiClient = class {
3051
3091
  async listAmlClients(query = {}) {
3052
3092
  const correlationId = randomUUID();
3053
3093
  const { data, error, response } = await getAmlClients({
3054
- path: { tenant: this.ctx.tenant },
3094
+ path: { tenant: this.tenant },
3055
3095
  query: {
3056
3096
  ...query,
3057
3097
  limit: query.limit ?? 10,
@@ -3067,7 +3107,7 @@ var SodiumApiClient = class {
3067
3107
  const correlationId = randomUUID();
3068
3108
  const { data, error, response } = await getAmlClient({
3069
3109
  path: {
3070
- tenant: this.ctx.tenant,
3110
+ tenant: this.tenant,
3071
3111
  clientId
3072
3112
  },
3073
3113
  headers: { "X-Correlation-Id": correlationId },
@@ -3080,7 +3120,7 @@ var SodiumApiClient = class {
3080
3120
  const correlationId = randomUUID();
3081
3121
  const { data, error, response } = await getAmlRiskAssessments({
3082
3122
  path: {
3083
- tenant: this.ctx.tenant,
3123
+ tenant: this.tenant,
3084
3124
  clientId
3085
3125
  },
3086
3126
  query: {
@@ -3097,7 +3137,7 @@ var SodiumApiClient = class {
3097
3137
  async listBillingLineItems(query = {}) {
3098
3138
  const correlationId = randomUUID();
3099
3139
  const { data, error, response } = await listBillingLineItems({
3100
- path: { tenant: this.ctx.tenant },
3140
+ path: { tenant: this.tenant },
3101
3141
  query: {
3102
3142
  ...query,
3103
3143
  limit: query.limit ?? 10,
@@ -3113,7 +3153,7 @@ var SodiumApiClient = class {
3113
3153
  const correlationId = randomUUID();
3114
3154
  const { data, error, response } = await updateWorkflowStep({
3115
3155
  path: {
3116
- tenant: this.ctx.tenant,
3156
+ tenant: this.tenant,
3117
3157
  taskCode,
3118
3158
  groupNumber,
3119
3159
  stepNumber
@@ -3128,7 +3168,7 @@ var SodiumApiClient = class {
3128
3168
  async listPendingWorkflowSteps(query = {}) {
3129
3169
  const correlationId = randomUUID();
3130
3170
  const { data, error, response } = await listPendingWorkflowSteps({
3131
- path: { tenant: this.ctx.tenant },
3171
+ path: { tenant: this.tenant },
3132
3172
  query: {
3133
3173
  ...query,
3134
3174
  limit: query.limit ?? 10,
@@ -3143,7 +3183,7 @@ var SodiumApiClient = class {
3143
3183
  async getEngagementPipelineSummary(query = {}) {
3144
3184
  const correlationId = randomUUID();
3145
3185
  const { data, error, response } = await getEngagementSummary({
3146
- path: { tenant: this.ctx.tenant },
3186
+ path: { tenant: this.tenant },
3147
3187
  query,
3148
3188
  headers: { "X-Correlation-Id": correlationId },
3149
3189
  client: this.http
@@ -3154,7 +3194,7 @@ var SodiumApiClient = class {
3154
3194
  async getUnbilledTimeClients(query = {}) {
3155
3195
  const correlationId = randomUUID();
3156
3196
  const { data, error, response } = await getUnbilledTimeClients({
3157
- path: { tenant: this.ctx.tenant },
3197
+ path: { tenant: this.tenant },
3158
3198
  query: {
3159
3199
  ...query,
3160
3200
  limit: query.limit ?? 25,
@@ -3170,7 +3210,7 @@ var SodiumApiClient = class {
3170
3210
  const correlationId = randomUUID();
3171
3211
  const { data, error, response } = await getTaskItemHistory({
3172
3212
  path: {
3173
- tenant: this.ctx.tenant,
3213
+ tenant: this.tenant,
3174
3214
  code
3175
3215
  },
3176
3216
  headers: { "X-Correlation-Id": correlationId },
@@ -3183,7 +3223,7 @@ var SodiumApiClient = class {
3183
3223
  const correlationId = randomUUID();
3184
3224
  const { data, error, response } = await getClientAgentAuthorisationStatuses({
3185
3225
  path: {
3186
- tenant: this.ctx.tenant,
3226
+ tenant: this.tenant,
3187
3227
  client: clientCode
3188
3228
  },
3189
3229
  headers: { "X-Correlation-Id": correlationId },
@@ -3195,7 +3235,7 @@ var SodiumApiClient = class {
3195
3235
  async listDataForms(query = {}) {
3196
3236
  const correlationId = randomUUID();
3197
3237
  const { data, error, response } = await listDataForms({
3198
- path: { tenant: this.ctx.tenant },
3238
+ path: { tenant: this.tenant },
3199
3239
  query: {
3200
3240
  ...query,
3201
3241
  limit: query.limit ?? 10,
@@ -3210,7 +3250,7 @@ var SodiumApiClient = class {
3210
3250
  async listClientDocuments(query = {}) {
3211
3251
  const correlationId = randomUUID();
3212
3252
  const { data, error, response } = await listAllClientDocuments({
3213
- path: { tenant: this.ctx.tenant },
3253
+ path: { tenant: this.tenant },
3214
3254
  query: {
3215
3255
  ...query,
3216
3256
  limit: query.limit ?? 10,
@@ -3225,7 +3265,7 @@ var SodiumApiClient = class {
3225
3265
  async listPortalUsers() {
3226
3266
  const correlationId = randomUUID();
3227
3267
  const { data, error, response } = await listPortalUsers({
3228
- path: { tenant: this.ctx.tenant },
3268
+ path: { tenant: this.tenant },
3229
3269
  headers: { "X-Correlation-Id": correlationId },
3230
3270
  client: this.http
3231
3271
  });
@@ -3235,7 +3275,7 @@ var SodiumApiClient = class {
3235
3275
  async listServicePackages(query = {}) {
3236
3276
  const correlationId = randomUUID();
3237
3277
  const { data, error, response } = await listServicePackages({
3238
- path: { tenant: this.ctx.tenant },
3278
+ path: { tenant: this.tenant },
3239
3279
  query: {
3240
3280
  ...query,
3241
3281
  limit: query.limit ?? 10,
@@ -3250,7 +3290,7 @@ var SodiumApiClient = class {
3250
3290
  async listEmailBroadcasts(query = {}) {
3251
3291
  const correlationId = randomUUID();
3252
3292
  const { data, error, response } = await listEmailBroadcasts({
3253
- path: { tenant: this.ctx.tenant },
3293
+ path: { tenant: this.tenant },
3254
3294
  query: {
3255
3295
  ...query,
3256
3296
  limit: query.limit ?? 10,
@@ -3266,7 +3306,7 @@ var SodiumApiClient = class {
3266
3306
  const correlationId = randomUUID();
3267
3307
  const { data, error, response } = await getEmailBroadcast({
3268
3308
  path: {
3269
- tenant: this.ctx.tenant,
3309
+ tenant: this.tenant,
3270
3310
  code
3271
3311
  },
3272
3312
  headers: { "X-Correlation-Id": correlationId },
@@ -3279,7 +3319,7 @@ var SodiumApiClient = class {
3279
3319
  const correlationId = randomUUID();
3280
3320
  const { data, error, response } = await getEmailBroadcastRecipients({
3281
3321
  path: {
3282
- tenant: this.ctx.tenant,
3322
+ tenant: this.tenant,
3283
3323
  code
3284
3324
  },
3285
3325
  query: {
@@ -3296,7 +3336,7 @@ var SodiumApiClient = class {
3296
3336
  async listInvoiceSubmissions(query = {}) {
3297
3337
  const correlationId = randomUUID();
3298
3338
  const { data, error, response } = await listInvoiceSubmissions({
3299
- path: { tenant: this.ctx.tenant },
3339
+ path: { tenant: this.tenant },
3300
3340
  query: {
3301
3341
  ...query,
3302
3342
  limit: query.limit ?? 10,
@@ -3312,7 +3352,7 @@ var SodiumApiClient = class {
3312
3352
  const correlationId = randomUUID();
3313
3353
  const { data, error, response } = await listClientLinksForClient({
3314
3354
  path: {
3315
- tenant: this.ctx.tenant,
3355
+ tenant: this.tenant,
3316
3356
  client: clientCode
3317
3357
  },
3318
3358
  query: {
@@ -3330,7 +3370,7 @@ var SodiumApiClient = class {
3330
3370
  const correlationId = randomUUID();
3331
3371
  const { data, error, response } = await getMailboxConversation({
3332
3372
  path: {
3333
- tenant: this.ctx.tenant,
3373
+ tenant: this.tenant,
3334
3374
  code: configCode,
3335
3375
  conversationId
3336
3376
  },
@@ -3344,7 +3384,7 @@ var SodiumApiClient = class {
3344
3384
  const correlationId = randomUUID();
3345
3385
  const { data, error, response } = await createClientBillableServiceForClient({
3346
3386
  path: {
3347
- tenant: this.ctx.tenant,
3387
+ tenant: this.tenant,
3348
3388
  client: clientCode
3349
3389
  },
3350
3390
  body,
@@ -3358,7 +3398,7 @@ var SodiumApiClient = class {
3358
3398
  const correlationId = randomUUID();
3359
3399
  const { error, response } = await updateClientBillableServiceStage({
3360
3400
  path: {
3361
- tenant: this.ctx.tenant,
3401
+ tenant: this.tenant,
3362
3402
  client: clientCode,
3363
3403
  code: clientServiceCode
3364
3404
  },
@@ -3372,7 +3412,7 @@ var SodiumApiClient = class {
3372
3412
  const correlationId = randomUUID();
3373
3413
  const { data, error, response } = await createDocumentRequestForClient({
3374
3414
  path: {
3375
- tenant: this.ctx.tenant,
3415
+ tenant: this.tenant,
3376
3416
  client: clientCode
3377
3417
  },
3378
3418
  body,
@@ -3386,7 +3426,7 @@ var SodiumApiClient = class {
3386
3426
  const correlationId = randomUUID();
3387
3427
  const { data, error, response } = await sendDataFormToClient({
3388
3428
  path: {
3389
- tenant: this.ctx.tenant,
3429
+ tenant: this.tenant,
3390
3430
  code: formCode
3391
3431
  },
3392
3432
  body,
@@ -3399,7 +3439,7 @@ var SodiumApiClient = class {
3399
3439
  async createEngagement(body) {
3400
3440
  const correlationId = randomUUID();
3401
3441
  const { data, error, response } = await createEngagement({
3402
- path: { tenant: this.ctx.tenant },
3442
+ path: { tenant: this.tenant },
3403
3443
  body,
3404
3444
  headers: { "X-Correlation-Id": correlationId },
3405
3445
  client: this.http
@@ -3411,7 +3451,7 @@ var SodiumApiClient = class {
3411
3451
  const correlationId = randomUUID();
3412
3452
  const { error, response } = await saveClientDates({
3413
3453
  path: {
3414
- tenant: this.ctx.tenant,
3454
+ tenant: this.tenant,
3415
3455
  code: clientCode
3416
3456
  },
3417
3457
  body: dates,
@@ -3424,7 +3464,7 @@ var SodiumApiClient = class {
3424
3464
  const correlationId = randomUUID();
3425
3465
  const { data, error, response } = await updateBusinessDetailsForClient({
3426
3466
  path: {
3427
- tenant: this.ctx.tenant,
3467
+ tenant: this.tenant,
3428
3468
  client: clientCode
3429
3469
  },
3430
3470
  body,
@@ -3437,7 +3477,7 @@ var SodiumApiClient = class {
3437
3477
  async createSavedTaskFilter(body) {
3438
3478
  const correlationId = randomUUID();
3439
3479
  const { data, error, response } = await createSavedTaskFilter({
3440
- path: { tenant: this.ctx.tenant },
3480
+ path: { tenant: this.tenant },
3441
3481
  body,
3442
3482
  headers: { "X-Correlation-Id": correlationId },
3443
3483
  client: this.http
@@ -3448,7 +3488,7 @@ var SodiumApiClient = class {
3448
3488
  async createTask(body) {
3449
3489
  const correlationId = randomUUID();
3450
3490
  const { data, error, response } = await createTaskItem({
3451
- path: { tenant: this.ctx.tenant },
3491
+ path: { tenant: this.tenant },
3452
3492
  body,
3453
3493
  headers: { "X-Correlation-Id": correlationId },
3454
3494
  client: this.http
@@ -3460,7 +3500,7 @@ var SodiumApiClient = class {
3460
3500
  const correlationId = randomUUID();
3461
3501
  const { data, error, response } = await updateTaskItem({
3462
3502
  path: {
3463
- tenant: this.ctx.tenant,
3503
+ tenant: this.tenant,
3464
3504
  code
3465
3505
  },
3466
3506
  body,
@@ -3493,7 +3533,7 @@ var SodiumApiClient = class {
3493
3533
  //#endregion
3494
3534
  //#region ../mcp-core/src/context/instructions.ts
3495
3535
  const ROSTER_CAP = 20;
3496
- async function buildInstructions(api, writesEnabled) {
3536
+ async function buildInstructions(api, writesEnabled, selection) {
3497
3537
  const [user, tenant, practice, team] = await Promise.allSettled([
3498
3538
  api.getCurrentUser(),
3499
3539
  api.getTenantDetails(),
@@ -3535,6 +3575,14 @@ async function buildInstructions(api, writesEnabled) {
3535
3575
  }
3536
3576
  if (tenant.status === "fulfilled") lines.push(`Tenant: ${tenant.value.name} (${tenant.value.code})`);
3537
3577
  if (practice.status === "fulfilled") lines.push(`Practice: ${practice.value.name}`);
3578
+ if (selection.kind === "choice") {
3579
+ lines.push("", "PRACTICE SELECTION REQUIRED — this user belongs to more than one practice and none is active yet.", "Before using any client/task/other data tool, ask the user which practice to work in and call set_active_practice with its code.");
3580
+ if (selection.practices.length > 0) {
3581
+ lines.push("Practices available:");
3582
+ for (const p of selection.practices) lines.push(`- ${p.name} (${p.code})`);
3583
+ } else lines.push("Call list_practices to see the available practices.");
3584
+ } else if (selection.kind === "none") lines.push("", "This user does not belong to any usable practice. Tell them their Sodium account has no active practice and there is nothing to show.");
3585
+ else if (selection.kind === "auto") lines.push("", `Working in ${selection.practice.name} (${selection.practice.code}) — the only practice this user belongs to. Call set_active_practice only if they ask to switch.`);
3538
3586
  lines.push("", writesEnabled ? "Write mode: ENABLED. Create/update tools are available; destructive and bulk operations are not." : "Write mode: DISABLED. Read-only — tell the user to relaunch with --enable-writes if they want changes made.");
3539
3587
  if (team.status === "fulfilled") {
3540
3588
  const members = team.value.data ?? [];
@@ -3553,6 +3601,102 @@ async function buildInstructions(api, writesEnabled) {
3553
3601
  return lines.join("\n");
3554
3602
  }
3555
3603
  //#endregion
3604
+ //#region ../mcp-core/src/context/tenant-selection.ts
3605
+ function isUsablePractice(t) {
3606
+ return t.status !== "LapsedTrialist" && t.status !== "LapsedCustomer";
3607
+ }
3608
+ async function resolveTenant(api) {
3609
+ let memberships;
3610
+ try {
3611
+ memberships = await api.listTenants();
3612
+ } catch {
3613
+ return {
3614
+ kind: "choice",
3615
+ practices: []
3616
+ };
3617
+ }
3618
+ const usable = memberships.filter(isUsablePractice);
3619
+ if (usable.length === 0) return { kind: "none" };
3620
+ if (usable.length === 1) {
3621
+ api.setActiveTenant(usable[0].code);
3622
+ return {
3623
+ kind: "auto",
3624
+ practice: usable[0]
3625
+ };
3626
+ }
3627
+ return {
3628
+ kind: "choice",
3629
+ practices: usable
3630
+ };
3631
+ }
3632
+ //#endregion
3633
+ //#region ../mcp-core/src/tools/list-practices.ts
3634
+ async function handleListPractices(api) {
3635
+ try {
3636
+ const memberships = await api.listTenants();
3637
+ const active = api.getActiveTenant();
3638
+ if (memberships.length === 0) return { content: [{
3639
+ type: "text",
3640
+ text: "You do not belong to any practices."
3641
+ }] };
3642
+ return { content: [{
3643
+ type: "text",
3644
+ text: `Practices you belong to:\n${memberships.map((t) => {
3645
+ const flags = [t.code === active ? "ACTIVE" : null, isUsablePractice(t) ? null : "unavailable"].filter(Boolean);
3646
+ const suffix = flags.length > 0 ? ` — ${flags.join(", ")}` : "";
3647
+ return `- ${t.name} (${t.code})${suffix}`;
3648
+ }).join("\n")}\n\nUse set_active_practice with a code to switch.`
3649
+ }] };
3650
+ } catch (error) {
3651
+ return {
3652
+ content: [{
3653
+ type: "text",
3654
+ text: `Could not list practices: ${error instanceof Error ? error.message : String(error)}`
3655
+ }],
3656
+ isError: true
3657
+ };
3658
+ }
3659
+ }
3660
+ //#endregion
3661
+ //#region ../mcp-core/src/tools/set-active-practice.ts
3662
+ const SetActivePracticeInputSchema = { code: z.string().describe("The practice code to work in, from list_practices (e.g. 'oceans').") };
3663
+ async function handleSetActivePractice(api, args) {
3664
+ try {
3665
+ const memberships = await api.listTenants();
3666
+ const match = memberships.find((t) => t.code === args.code);
3667
+ if (!match) {
3668
+ const known = memberships.map((t) => t.code).join(", ") || "(none)";
3669
+ return {
3670
+ content: [{
3671
+ type: "text",
3672
+ text: `'${args.code}' is not a practice you belong to. Your practices: ${known}.`
3673
+ }],
3674
+ isError: true
3675
+ };
3676
+ }
3677
+ if (!isUsablePractice(match)) return {
3678
+ content: [{
3679
+ type: "text",
3680
+ text: `'${match.name}' (${match.code}) is not currently available and cannot be selected.`
3681
+ }],
3682
+ isError: true
3683
+ };
3684
+ api.setActiveTenant(match.code);
3685
+ return { content: [{
3686
+ type: "text",
3687
+ text: `Now working in ${match.name} (${match.code}).`
3688
+ }] };
3689
+ } catch (error) {
3690
+ return {
3691
+ content: [{
3692
+ type: "text",
3693
+ text: `Could not switch practice: ${error instanceof Error ? error.message : String(error)}`
3694
+ }],
3695
+ isError: true
3696
+ };
3697
+ }
3698
+ }
3699
+ //#endregion
3556
3700
  //#region ../mcp-core/src/tools/get-practice-details.ts
3557
3701
  function format$4(tenant, practice) {
3558
3702
  const lines = [];
@@ -8621,7 +8765,8 @@ function registerWriteTool(server, ctx, name, config, cb) {
8621
8765
  }
8622
8766
  async function buildServer(config) {
8623
8767
  const api = new SodiumApiClient(config.context, { serverVersion: config.serverVersion });
8624
- const instructions = await buildInstructions(api, config.context.writesEnabled);
8768
+ const selection = api.hasActiveTenant() ? { kind: "explicit" } : await resolveTenant(api);
8769
+ const instructions = await buildInstructions(api, config.context.writesEnabled, selection);
8625
8770
  const server = new McpServer({
8626
8771
  name: config.serverName,
8627
8772
  version: config.serverVersion,
@@ -8665,6 +8810,27 @@ async function buildServer(config) {
8665
8810
  openWorldHint: true
8666
8811
  }
8667
8812
  }, () => handleWhoami(api));
8813
+ server.registerTool("list_practices", {
8814
+ title: "List the practices you can work in",
8815
+ description: "List the practices (tenants) the signed-in user belongs to, marking which one is currently active. Use this when the user belongs to more than one practice and you need to confirm which to work in, when the user asks 'which practices can I access?', or before set_active_practice. Practices flagged 'unavailable' cannot be selected.",
8816
+ inputSchema: {},
8817
+ annotations: {
8818
+ readOnlyHint: true,
8819
+ idempotentHint: true,
8820
+ openWorldHint: true
8821
+ }
8822
+ }, () => handleListPractices(api));
8823
+ server.registerTool("set_active_practice", {
8824
+ title: "Choose which practice to work in",
8825
+ description: "Set the practice all subsequent tools operate on for this session. Required before other tools can run if the user belongs to more than one practice and none is active yet. Also use it to switch practice mid-session ('switch to Oceans', 'now look at Greggs'). Pass a practice code from list_practices. Only practices the user belongs to and that are currently available can be selected.",
8826
+ inputSchema: SetActivePracticeInputSchema,
8827
+ annotations: {
8828
+ readOnlyHint: false,
8829
+ destructiveHint: false,
8830
+ idempotentHint: true,
8831
+ openWorldHint: true
8832
+ }
8833
+ }, (args) => handleSetActivePractice(api, args));
8668
8834
  server.registerTool("list_clients", {
8669
8835
  title: "List / search / filter clients",
8670
8836
  description: "List clients with any combination of: search (code/name/internal reference, 3+ chars), status (Active/Inactive/Prospect/LostProspect), type (PrivateLimitedCompany/PublicLimitedCompany/LimitedLiabilityPartnership/Partnership/Individual/Trust/Charity/SoleTrader), manager/partner/associate user codes, service codes, a saved filter code, sort, and pagination. Use search for 'find ACME'-style queries. Use type for 'list limited companies' (pass PrivateLimitedCompany + PublicLimitedCompany). Use status: ['Active'] to exclude prospects/inactive. Returns up to 50 clients per page — paginate via offset for more. For 'how many X?' questions, pass limit=0 to get just the total count without fetching any client data. Follow up with get_client_summary for full detail on a specific client.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sodiumhq/mcp-pm",
3
- "version": "0.1.0-beta.4441",
3
+ "version": "0.1.0-beta.4445",
4
4
  "description": "Sodium Practice Management MCP server — lets AI assistants interact with your Sodium tenant",
5
5
  "type": "module",
6
6
  "bin": {