@loopops/mcp-server 3.2.0 → 3.3.0

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.
@@ -272,10 +272,11 @@ function persistRotatedRefreshToken(newToken) {
272
272
  */
273
273
  async function diagnoseRefreshFailure(status, body) {
274
274
  const head = `Okta refresh failed (HTTP ${status}). Detail: ${body.slice(0, 300)}`;
275
- const generic = "Your refresh token may be revoked or idle-expired. Re-run " +
276
- "`npx @loopops/mcp-cli@latest login` (the `@latest` pin bypasses the " +
277
- "npx cache, which can serve a stale cli with old tenant defaults for " +
278
- "up to 24h after a publish).";
275
+ const generic = "Your refresh token may be revoked or idle-expired.\n" +
276
+ " Diagnose: `npx @loopops/mcp-cli@latest doctor` checks tenant config + token.\n" +
277
+ " Fix: `npx @loopops/mcp-cli@latest login` re-authenticates from scratch.\n" +
278
+ "(The `@latest` pin matters: bare `npx @loopops/mcp-cli` may serve a " +
279
+ "cached older cli with stale tenant defaults for up to 24h after a publish.)";
279
280
  if (!apiUrl)
280
281
  return `${head}\n\n${generic}`;
281
282
  try {
package/dist/index.js CHANGED
@@ -1,14 +1,26 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
2
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
7
  import { z } from "zod";
5
8
  import { trpcQuery } from "./api-client.js";
9
+ import { registerIdentityTools } from "./tools/identity.js";
6
10
  import { registerReportingTools } from "./tools/reporting.js";
7
11
  import { registerConfigTools } from "./tools/config.js";
8
12
  import { registerEngTools } from "./tools/eng.js";
9
13
  import { registerCrmTools } from "./tools/crm.js";
10
14
  import { registerEngageTools } from "./tools/engage.js";
11
15
  import { registerAccountMasterTools } from "./tools/account-master.js";
16
+ // Read our own package.json at runtime so the version baked into MCP
17
+ // initialize-handshake `serverInfo.version` matches the published npm
18
+ // version. Was hardcoded "1.0.0" — confusing in Claude Desktop logs and
19
+ // any other MCP client that displays server version. `package.json` is
20
+ // always included in npm tarballs, so the relative path `../package.json`
21
+ // (from dist/index.js) resolves cleanly post-publish.
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
12
24
  const skillsResponseSchema = z.object({
13
25
  role: z.string(),
14
26
  skills: z.array(z.string()),
@@ -34,8 +46,9 @@ const allowedSkills = new Set(skills);
34
46
  console.error(`[MCP] Connected — role: ${role}, ${skills.length} skills`);
35
47
  const server = new McpServer({
36
48
  name: "loop-operations",
37
- version: "1.0.0",
49
+ version: pkg.version,
38
50
  });
51
+ registerIdentityTools(server, allowedSkills);
39
52
  registerReportingTools(server, allowedSkills);
40
53
  registerConfigTools(server, allowedSkills);
41
54
  registerEngTools(server, allowedSkills);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Identity / connection-check tools.
3
+ *
4
+ * Currently just `mcp_whoami` — a data-independent first-call sanity check.
5
+ * Returns the caller's email, MCP role, SF user link state, and tool count.
6
+ * Designed for the onboarding flow: after install + restart, asking Claude
7
+ * "are you connected?" should resolve to this and confirm everything wired
8
+ * correctly without depending on having any actual Loop data yet.
9
+ */
10
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
+ export declare function registerIdentityTools(server: McpServer, allowed: Set<string>): void;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Identity / connection-check tools.
3
+ *
4
+ * Currently just `mcp_whoami` — a data-independent first-call sanity check.
5
+ * Returns the caller's email, MCP role, SF user link state, and tool count.
6
+ * Designed for the onboarding flow: after install + restart, asking Claude
7
+ * "are you connected?" should resolve to this and confirm everything wired
8
+ * correctly without depending on having any actual Loop data yet.
9
+ */
10
+ import { trpcQuery } from "../api-client.js";
11
+ import { safeTool } from "./_helpers.js";
12
+ export function registerIdentityTools(server, allowed) {
13
+ if (allowed.has("mcp_whoami")) {
14
+ server.tool("mcp_whoami", [
15
+ "Connection sanity check. Returns your email, MCP role, Salesforce user link state,",
16
+ "and the number of tools available to you. Use as a first-call verification after",
17
+ "install — works regardless of whether you have any Loop data yet, so it's a clean",
18
+ "way to confirm the auth chain (Okta → Loop → role resolution) is wired correctly.",
19
+ ].join(" "), {}, safeTool(async () => trpcQuery("mcp.whoami")));
20
+ }
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loopops/mcp-server",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Loop Operations MCP Server — AI skills for RevOps",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",