@sodiumhq/mcp-pm 0.1.0-beta.2596 → 0.1.0-beta.2600

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
@@ -1,6 +1,8 @@
1
1
  # @sodiumhq/mcp-pm
2
2
 
3
- Model Context Protocol (MCP) server for [Sodium Practice Management](https://sodiumhq.com). Lets AI assistants like Claude Desktop, Claude Code, Cursor, and ChatGPT Desktop interact with your Sodium tenant.
3
+ Model Context Protocol (MCP) server for [Sodium Practice Management](https://sodiumhq.com). Lets AI assistants like Claude Desktop, Claude Code, Cursor, and VS Code interact with your Sodium tenant.
4
+
5
+ > **Full setup guide and example prompts:** [sodiumhq.com/features/mcp](https://sodiumhq.com/features/mcp)
4
6
 
5
7
  ## Status
6
8
 
@@ -8,13 +10,15 @@ Model Context Protocol (MCP) server for [Sodium Practice Management](https://sod
8
10
 
9
11
  ## Quick start
10
12
 
11
- ### 1. Generate an API key
13
+ ### 1. Grab your API key and tenant code
14
+
15
+ In Sodium, open the **profile menu** (top right) and click **API Keys**. Create a new key and copy it.
12
16
 
13
- In Sodium, go to **Settings API Keys** and create a new key. Copy it along with your tenant code.
17
+ Your **tenant code** is the subdomain in the URL you use to log in if you sign in at `acme.sodiumhq.com`, your tenant code is `acme`.
14
18
 
15
19
  ### 2. Configure your MCP client
16
20
 
17
- **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
21
+ **Claude Desktop** — edit `~/Library/Application Support/Claude/claude_desktop_config.json` on Mac, or `%APPDATA%\Claude\claude_desktop_config.json` on Windows:
18
22
 
19
23
  ```json
20
24
  {
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
5
  import { randomUUID } from "node:crypto";
@@ -952,14 +953,32 @@ var SodiumApiError = class extends Error {
952
953
  this.name = "SodiumApiError";
953
954
  }
954
955
  };
956
+ function sanitizeToken(value) {
957
+ return value.replace(/[\s()\/]+/g, "-").replace(/[^\w.\-]/g, "") || "unknown";
958
+ }
955
959
  var SodiumApiClient = class {
956
- constructor(ctx) {
960
+ serverVersion;
961
+ mcpClient = null;
962
+ constructor(ctx, options) {
957
963
  this.ctx = ctx;
964
+ this.serverVersion = options.serverVersion;
958
965
  client.setConfig({
959
966
  baseUrl: ctx.baseUrl,
960
- headers: { "x-api-key": ctx.apiKey }
967
+ headers: {
968
+ "x-api-key": ctx.apiKey,
969
+ "User-Agent": this.buildUserAgent()
970
+ }
961
971
  });
962
972
  }
973
+ setMcpClientInfo(info) {
974
+ this.mcpClient = info;
975
+ client.setConfig({ headers: { "User-Agent": this.buildUserAgent() } });
976
+ }
977
+ buildUserAgent() {
978
+ const base = `sodiumhq-mcp-pm/${this.serverVersion}`;
979
+ if (!this.mcpClient) return base;
980
+ return `${base} (client=${sanitizeToken(this.mcpClient.name)}/${sanitizeToken(this.mcpClient.version)})`;
981
+ }
963
982
  async getPracticeDetails() {
964
983
  const correlationId = randomUUID();
965
984
  const { data, error, response } = await getPracticeDetails({
@@ -1197,7 +1216,17 @@ async function buildInstructions(api) {
1197
1216
  ]);
1198
1217
  const now = /* @__PURE__ */ new Date();
1199
1218
  const lines = [
1200
- "You are assisting a user of Sodium Practice Management.",
1219
+ "You are assisting a user of Sodium Practice Management — software used by accountancy practices to run their business.",
1220
+ "",
1221
+ "IMPORTANT — who the user is and whose data this is:",
1222
+ "- The user is a member of an accountancy practice (accountant, bookkeeper, partner, or practice staff). They are NEVER the end client.",
1223
+ "- 'Clients' in this system are the businesses and individuals the practice provides services to (accounts, tax, payroll, bookkeeping, advisory, etc.).",
1224
+ "- When the user names an entity (e.g. 'ACME Ltd', 'Greggs Carpentry'), they are almost always referring to one of THEIR CLIENTS — not themselves or their own practice.",
1225
+ "- Tasks, proposals, engagement letters, services and statutory dates in this system describe work the practice does FOR clients.",
1226
+ "",
1227
+ "Always answer from the practice's point of view:",
1228
+ "- For prompts like 'brief me on my call with X' or 'summarise X', produce a practice-side view: what services the practice delivers to X, what work is outstanding, what the user should raise or action with the client.",
1229
+ "- Never frame output as if the named entity is the one being briefed — it is the practice (the user) being briefed ABOUT the client.",
1201
1230
  "",
1202
1231
  `Today: ${now.toISOString().slice(0, 10)} (${now.toLocaleDateString("en-GB", { weekday: "long" })})`,
1203
1232
  `Current UTC time: ${now.toISOString()}`
@@ -2094,7 +2123,7 @@ function describeFilters(args) {
2094
2123
  //#endregion
2095
2124
  //#region ../mcp-core/src/server.ts
2096
2125
  async function buildServer(config) {
2097
- const api = new SodiumApiClient(config.context);
2126
+ const api = new SodiumApiClient(config.context, { serverVersion: config.serverVersion });
2098
2127
  const instructions = await buildInstructions(api);
2099
2128
  const server = new McpServer({
2100
2129
  name: config.serverName,
@@ -2103,6 +2132,13 @@ async function buildServer(config) {
2103
2132
  instructions,
2104
2133
  capabilities: { tools: {} }
2105
2134
  });
2135
+ server.server.oninitialized = () => {
2136
+ const info = server.server.getClientVersion();
2137
+ if (info?.name && info?.version) api.setMcpClientInfo({
2138
+ name: info.name,
2139
+ version: info.version
2140
+ });
2141
+ };
2106
2142
  server.registerTool("get_practice_details", {
2107
2143
  title: "Get practice details",
2108
2144
  description: "Get a consolidated overview of the practice including name, contact details, client/service/user counts, connections, and settings. Use this when the user asks about their practice, tenant, or wants a summary of their account.",
@@ -2221,7 +2257,7 @@ function loadContext() {
2221
2257
  }
2222
2258
  //#endregion
2223
2259
  //#region src/index.ts
2224
- const VERSION = "0.0.1";
2260
+ const VERSION = createRequire(import.meta.url)("../package.json").version;
2225
2261
  async function main() {
2226
2262
  const context = loadContext();
2227
2263
  const server = await buildServer({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sodiumhq/mcp-pm",
3
- "version": "0.1.0-beta.2596",
3
+ "version": "0.1.0-beta.2600",
4
4
  "description": "Sodium Practice Management MCP server — lets AI assistants interact with your Sodium tenant",
5
5
  "type": "module",
6
6
  "bin": {