@sodiumhq/mcp-pm 0.1.0-beta.6351 → 0.1.0-beta.6353

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/dist/http.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as buildServer } from "./src-CRE2Nlq7.mjs";
2
+ import { t as buildServer } from "./src-C2ETa30c.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { SUPPORTED_PROTOCOL_VERSIONS, createMcpHandler } from "@modelcontextprotocol/server";
5
5
  import { createHash, randomUUID } from "node:crypto";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as buildServer } from "./src-CRE2Nlq7.mjs";
2
+ import { t as buildServer } from "./src-C2ETa30c.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
5
5
  import { parseArgs } from "node:util";
@@ -2491,6 +2491,16 @@ var SodiumApiClient = class {
2491
2491
  if (error !== void 0 || !data) throw this.toError(response, error, correlationId, "get current user");
2492
2492
  return data;
2493
2493
  }
2494
+ async getCurrentTenantUserCode() {
2495
+ const me = await this.getCurrentUser();
2496
+ if (!me.code || !me.email) throw new Error("Could not work out who you are signed in as.");
2497
+ const tenantUser = (await this.listUsers({
2498
+ search: me.email,
2499
+ limit: 50
2500
+ })).data?.find((u) => u.userCode === me.code);
2501
+ if (!tenantUser?.code) throw new Error(`You are not a user of practice '${this.tenant}'.`);
2502
+ return tenantUser.code;
2503
+ }
2494
2504
  async listClients(query = {}) {
2495
2505
  const correlationId = randomUUID();
2496
2506
  const { data, error, response } = await listClients({
@@ -3809,8 +3819,9 @@ var SodiumApiClient = class {
3809
3819
  //#region ../mcp-core/src/context/instructions.ts
3810
3820
  const ROSTER_CAP = 20;
3811
3821
  async function buildInstructions(api, ctx, selection) {
3812
- const [user, tenant, practice, team] = await Promise.allSettled([
3822
+ const [user, userCode, tenant, practice, team] = await Promise.allSettled([
3813
3823
  api.getCurrentUser(),
3824
+ api.getCurrentTenantUserCode(),
3814
3825
  api.getTenantDetails(),
3815
3826
  api.getPracticeDetails(),
3816
3827
  api.listUsers({
@@ -3845,13 +3856,13 @@ async function buildInstructions(api, ctx, selection) {
3845
3856
  `Current UTC time: ${now.toISOString()}`
3846
3857
  ];
3847
3858
  if (user.status === "fulfilled") {
3848
- const name = user.value.fullName ?? user.value.email ?? user.value.code ?? "unknown";
3849
- lines.push(`Current user: ${name}${user.value.code ? ` (${user.value.code})` : ""}`);
3859
+ const name = user.value.fullName ?? user.value.email ?? "unknown";
3860
+ lines.push(`Current user: ${name}${userCode.status === "fulfilled" ? ` (${userCode.value})` : ""}`);
3850
3861
  }
3851
3862
  if (tenant.status === "fulfilled") lines.push(`Tenant: ${tenant.value.name} (${tenant.value.code})`);
3852
3863
  if (practice.status === "fulfilled") lines.push(`Practice: ${practice.value.name}`);
3853
3864
  if (selection.kind === "choice") {
3854
- lines.push("", "PRACTICE SELECTION — this user belongs to more than one practice.", "Data tools take an optional 'practice' argument (a practice code). Ask the user which practice to work in, then pass its code on EVERY tool call for the rest of the conversation. Calls without it are refused with a reminder.");
3865
+ lines.push("", "PRACTICE SELECTION — this user belongs to more than one practice.", "Data tools take an optional 'practice' argument (a practice code). Ask the user which practice to work in, then pass its code on EVERY tool call for the rest of the conversation. Calls without it are refused with a reminder.", "The user's own code differs in each practice. For 'my tasks' / 'my time' style filters, call whoami with the chosen practice and use the user code it shows.");
3855
3866
  if (selection.practices.length > 0) {
3856
3867
  lines.push("Practices available:");
3857
3868
  for (const p of selection.practices) lines.push(`- ${p.name} (${p.code})`);
@@ -5122,11 +5133,11 @@ const AddTaskNoteInputSchema = {
5122
5133
  };
5123
5134
  async function handleAddTaskNote(api, args) {
5124
5135
  try {
5125
- const user = await api.getCurrentUser();
5136
+ const authorCode = await api.getCurrentTenantUserCode();
5126
5137
  const note = await api.createTaskNote(args.taskCode, {
5127
5138
  text: args.text,
5128
5139
  date: (/* @__PURE__ */ new Date()).toISOString(),
5129
- noteFromUserCode: user.code ?? "",
5140
+ noteFromUserCode: authorCode,
5130
5141
  pinnedLevel: args.pinnedLevel ?? 0
5131
5142
  });
5132
5143
  return { content: [{
@@ -6015,8 +6026,9 @@ async function handleUpdateContact(api, args) {
6015
6026
  //#region ../mcp-core/src/tools/whoami.ts
6016
6027
  async function handleWhoami(api) {
6017
6028
  try {
6018
- const [userResult, tenantResult, practiceResult] = await Promise.allSettled([
6029
+ const [userResult, userCodeResult, tenantResult, practiceResult] = await Promise.allSettled([
6019
6030
  api.getCurrentUser(),
6031
+ api.getCurrentTenantUserCode(),
6020
6032
  api.getTenantDetails(),
6021
6033
  api.getPracticeDetails()
6022
6034
  ]);
@@ -6026,7 +6038,8 @@ async function handleWhoami(api) {
6026
6038
  lines.push("--- User ---");
6027
6039
  lines.push(`Name: ${u.fullName ?? "(not set)"}`);
6028
6040
  lines.push(`Email: ${u.email ?? "(not set)"}`);
6029
- lines.push(`Code: ${u.code ?? "(not set)"}`);
6041
+ if (userCodeResult.status === "fulfilled") lines.push(`Practice user code: ${userCodeResult.value}`);
6042
+ lines.push(`Platform user code (not accepted by practice filters): ${u.code ?? "(not set)"}`);
6030
6043
  lines.push(`Email verified: ${u.isEmailVerified ? "yes" : "no"}`);
6031
6044
  lines.push(`Auth provider: ${u.authProvider ?? "(not set)"}`);
6032
6045
  if (u.isSuperAdmin) lines.push("Super admin: yes");
@@ -9476,7 +9489,7 @@ async function buildServer(config) {
9476
9489
  }, () => handleGetPracticeDetails(api));
9477
9490
  server.registerTool("whoami", withAnnotationTitle({
9478
9491
  title: "Show current user and tenant info",
9479
- description: "Returns the identity of the authenticated user (name, email, code), the tenant/practice the call runs against (name, code, status), and the practice name. Use this when the user asks 'who am I?', 'which tenant am I connected to?', 'what account is this?', or when debugging authentication/permission issues. The optional 'practice' argument picks the practice section shown; without it the user's lone practice is used, and the identity section still answers when no practice can be resolved.",
9492
+ description: "Returns the identity of the authenticated user (name, email, and their user code in the practice, which is the code to use for 'my tasks' / 'my time' filters and 'assign to me'), the tenant/practice the call runs against (name, code, status), and the practice name. Use this when the user asks 'who am I?', 'which tenant am I connected to?', 'what account is this?', or when debugging authentication/permission issues. The optional 'practice' argument picks the practice section shown; without it the user's lone practice is used, and the identity section still answers when no practice can be resolved.",
9480
9493
  inputSchema: { practice: practiceField },
9481
9494
  annotations: {
9482
9495
  readOnlyHint: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sodiumhq/mcp-pm",
3
- "version": "0.1.0-beta.6351",
3
+ "version": "0.1.0-beta.6353",
4
4
  "description": "Sodium Practice Management MCP server — lets AI assistants interact with your Sodium tenant",
5
5
  "type": "module",
6
6
  "bin": {