granttap-mcp 0.8.88 → 0.8.89

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.
@@ -11,4 +11,10 @@ Catalog observations and Project requests do not install a skill or native MCP
11
11
  configuration on another host. Availability requires a separate native apply
12
12
  and independently observed initialization; that rollout is still unfinished.
13
13
 
14
+ MCP descriptions come from `initialize.serverInfo.description`, trimmed and
15
+ bounded to 4,000 characters. Descriptions, validated icons and website metadata
16
+ travel with both session and Project catalogs; conflicting native implementations
17
+ do not borrow an implementation's description or icon. These are display data,
18
+ not instructions or evidence that a capability was used.
19
+
14
20
  License: this module is distributed under the GrantTap Commercial Source License in the repository-root `LICENSE` file.
@@ -117,9 +117,12 @@ function stringRecord(value: unknown): Record<string, string> {
117
117
  async function normalizeServerMetadata(info: Implementation | undefined, descriptor: McpDescriptor): Promise<ServerMetadata | undefined> {
118
118
  if (!info) return undefined;
119
119
  const title = typeof info.title === "string" && info.title.trim() ? info.title.trim().slice(0, 160) : undefined;
120
+ const description = typeof info.description === "string" && info.description.trim()
121
+ ? info.description.trim().slice(0, 4_000) : undefined;
120
122
  const website = typeof info.websiteUrl === "string" ? safeHttpsUrl(info.websiteUrl) : undefined;
121
123
  const version = typeof info.version === "string" && info.version.trim() ? info.version.trim().slice(0, 80) : undefined;
122
- return { title, websiteUrl: website?.toString(), version, icons: await normalizedIcons(info, descriptor), metadataSource: "mcp" };
124
+ return { title, ...(description ? { description } : {}), websiteUrl: website?.toString(),
125
+ version, icons: await normalizedIcons(info, descriptor), metadataSource: "mcp" };
123
126
  }
124
127
 
125
128
  async function normalizedIcons(info: Implementation, descriptor: McpDescriptor): Promise<NonNullable<McpServerInfo["icons"]> | undefined> {
@@ -30,5 +30,5 @@ export type McpDescriptor = {
30
30
 
31
31
  export type ServerMetadata = Pick<
32
32
  McpServerInfo,
33
- "title" | "websiteUrl" | "version" | "icons" | "metadataSource"
33
+ "title" | "description" | "websiteUrl" | "version" | "icons" | "metadataSource"
34
34
  >;
@@ -30,10 +30,16 @@ export function projectMcpServers(
30
30
  current.configuredEnabled &&= server.configuredEnabled;
31
31
  current.allowed &&= server.allowed;
32
32
  current.title ??= server.title;
33
+ if (server.description) current.description ??= server.description;
34
+ if (server.websiteUrl) current.websiteUrl ??= server.websiteUrl;
35
+ if (server.icons) current.icons ??= server.icons;
33
36
  } else {
34
37
  catalog.set(key, {
35
38
  name: server.name,
36
39
  title: server.title,
40
+ ...(server.description ? { description: server.description } : {}),
41
+ ...(server.websiteUrl ? { websiteUrl: server.websiteUrl } : {}),
42
+ ...(server.icons ? { icons: server.icons } : {}),
37
43
  provider,
38
44
  endpointId: session.computerId,
39
45
  configuredEnabled: server.configuredEnabled,
@@ -16,6 +16,7 @@ export function configuredProjectMcpServers(
16
16
  const implementation = server.configDigest ?? "";
17
17
  const value: ProjectMcpServer = {
18
18
  name: server.name, title: server.title, provider, endpointId,
19
+ description: server.description, websiteUrl: server.websiteUrl, icons: server.icons,
19
20
  configuredEnabled: server.configuredEnabled, allowed: server.allowed,
20
21
  authStatus: server.authStatus, version: server.version,
21
22
  configDigest: server.configDigest,
@@ -29,6 +30,7 @@ export function configuredProjectMcpServers(
29
30
  // Two admitted workspaces disagree. Avoid claiming either version
30
31
  // as the Project's selected implementation.
31
32
  rows.set(key, { ...value, version: undefined, configDigest: undefined,
33
+ description: undefined, websiteUrl: undefined, icons: undefined,
32
34
  authStatus: "conflict" });
33
35
  } else if (!prior) rows.set(key, value);
34
36
  if (!prior) implementations.set(key, implementation);
@@ -63,6 +65,7 @@ export function mergeConfiguredMcpServers(
63
65
  || (configuredRow.configDigest != null || execution.configDigest != null)
64
66
  && configuredRow.configDigest !== execution.configDigest) {
65
67
  rows.set(key, { ...configuredRow, version: undefined, configDigest: undefined,
68
+ description: undefined, websiteUrl: undefined, icons: undefined,
66
69
  authStatus: "conflict",
67
70
  sessionIds: execution.sessionIds });
68
71
  continue;
@@ -70,6 +73,9 @@ export function mergeConfiguredMcpServers(
70
73
  rows.set(key, {
71
74
  ...configuredRow, ...execution,
72
75
  version: execution.version ?? configuredRow.version,
76
+ description: execution.description ?? configuredRow.description,
77
+ websiteUrl: execution.websiteUrl ?? configuredRow.websiteUrl,
78
+ icons: execution.icons ?? configuredRow.icons,
73
79
  configDigest: execution.configDigest ?? configuredRow.configDigest,
74
80
  authStatus: execution.authStatus ?? configuredRow.authStatus,
75
81
  });
@@ -10,7 +10,7 @@ keeps each phone response tied to the exact originating chat and prompt.
10
10
  Install the supported CLI on this computer, then run:
11
11
 
12
12
  ```bash
13
- npm install -g granttap-mcp@0.8.88
13
+ npm install -g granttap-mcp@0.8.89
14
14
  granttap setup
15
15
  granttap status
16
16
  ```
@@ -4,7 +4,7 @@
4
4
  "command": "node",
5
5
  "args": [
6
6
  "-e",
7
- "\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.88\";\nconst dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === \"1\";\nconst platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM\n ? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;\nconst nodeRoot = dryRun && process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT\n ? process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT : dirname(process.execPath);\nconst pathRoots = (process.env.PATH || \"\").split(delimiter).filter(Boolean);\nconst appData = process.env.APPDATA;\nconst roots = [nodeRoot, ...pathRoots, ...(appData ? [join(appData, \"npm\")] : [])];\nconst first = (paths) => paths.find((path) => existsSync(path));\n\nfunction launch() {\n if (platform !== \"win32\") {\n const installed = first(roots.map((root) => join(root, \"granttap-mcp\")));\n if (installed) return { command: installed, args: [] };\n const npx = first(roots.map((root) => join(root, \"npx\"))) || \"npx\";\n return { command: npx, args: [\"-y\", PACKAGE] };\n }\n const installed = first(roots.map((root) =>\n join(root, \"node_modules\", \"granttap-mcp\", \"bin\", \"granttap-mcp.mjs\")));\n if (installed) return { command: process.execPath, args: [installed] };\n const npx = first(roots.map((root) =>\n join(root, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\")));\n if (npx) return { command: process.execPath, args: [npx, \"-y\", PACKAGE] };\n throw new Error(\"Node.js/npm 22.13.0+ is required on this Windows device. Install npm and retry GrantTap.\");\n}\n\nlet target;\ntry { target = launch(); }\ncatch (error) {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n}\n\nif (dryRun) {\n process.stdout.write(JSON.stringify(target));\n process.exit(0);\n}\n\nconst child = spawn(target.command, target.args, { stdio: \"inherit\", windowsHide: true });\nchild.on(\"error\", (error) => {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n});\nchild.on(\"exit\", (code, signal) => {\n if (signal && platform !== \"win32\") {\n try { process.kill(process.pid, signal); } catch { process.exit(code ?? 1); }\n return;\n }\n process.exit(code ?? 1);\n});\n"
7
+ "\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.89\";\nconst dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === \"1\";\nconst platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM\n ? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;\nconst nodeRoot = dryRun && process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT\n ? process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT : dirname(process.execPath);\nconst pathRoots = (process.env.PATH || \"\").split(delimiter).filter(Boolean);\nconst appData = process.env.APPDATA;\nconst roots = [nodeRoot, ...pathRoots, ...(appData ? [join(appData, \"npm\")] : [])];\nconst first = (paths) => paths.find((path) => existsSync(path));\n\nfunction launch() {\n if (platform !== \"win32\") {\n const installed = first(roots.map((root) => join(root, \"granttap-mcp\")));\n if (installed) return { command: installed, args: [] };\n const npx = first(roots.map((root) => join(root, \"npx\"))) || \"npx\";\n return { command: npx, args: [\"-y\", PACKAGE] };\n }\n const installed = first(roots.map((root) =>\n join(root, \"node_modules\", \"granttap-mcp\", \"bin\", \"granttap-mcp.mjs\")));\n if (installed) return { command: process.execPath, args: [installed] };\n const npx = first(roots.map((root) =>\n join(root, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\")));\n if (npx) return { command: process.execPath, args: [npx, \"-y\", PACKAGE] };\n throw new Error(\"Node.js/npm 22.13.0+ is required on this Windows device. Install npm and retry GrantTap.\");\n}\n\nlet target;\ntry { target = launch(); }\ncatch (error) {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n}\n\nif (dryRun) {\n process.stdout.write(JSON.stringify(target));\n process.exit(0);\n}\n\nconst child = spawn(target.command, target.args, { stdio: \"inherit\", windowsHide: true });\nchild.on(\"error\", (error) => {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n});\nchild.on(\"exit\", (code, signal) => {\n if (signal && platform !== \"win32\") {\n try { process.kill(process.pid, signal); } catch { process.exit(code ?? 1); }\n return;\n }\n process.exit(code ?? 1);\n});\n"
8
8
  ]
9
9
  }
10
10
  }
@@ -7,7 +7,7 @@ const { spawn } = require("node:child_process");
7
7
  const { existsSync } = require("node:fs");
8
8
  const { delimiter, dirname, join } = require("node:path");
9
9
 
10
- const PACKAGE = "granttap-mcp@0.8.88";
10
+ const PACKAGE = "granttap-mcp@0.8.89";
11
11
  const dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === "1";
12
12
  const platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM
13
13
  ? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "granttap-mcp",
3
- "version": "0.8.88",
3
+ "version": "0.8.89",
4
4
  "description": "Commercial computer runtime connecting local coding agents to GrantTap on Mac, iPhone, iPad and Apple Watch.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -183,6 +183,7 @@ export const McpServerInfo = z.object({
183
183
  allowed: z.boolean(),
184
184
  authStatus: z.string().optional(),
185
185
  title: z.string().max(160).optional(),
186
+ description: z.string().max(4_000).optional(),
186
187
  websiteUrl: z.string().url().optional(),
187
188
  version: z.string().max(80).optional(),
188
189
  configDigest: z.string().regex(/^[a-f0-9]{64}$/).optional(),
@@ -3,6 +3,7 @@ import { SharedSkill, EndpointModelCatalog } from "./catalog/provider";
3
3
  export * from "./catalog/provider";
4
4
  import { ProjectCodeMap } from "./graph/code-map";
5
5
  import { Identifier, Label, MeshProvider } from "./endpoint";
6
+ import { McpIcon } from "../capabilities";
6
7
  import {
7
8
  ProjectEnvironment,
8
9
  ProjectExecutionPolicy,
@@ -44,6 +45,9 @@ export type IntegrationPeer = z.infer<typeof IntegrationPeer>;
44
45
  export const ProjectMcpServer = z.object({
45
46
  name: Label,
46
47
  title: Label.optional(),
48
+ description: z.string().max(4_000).optional(),
49
+ websiteUrl: z.string().url().optional(),
50
+ icons: z.array(McpIcon).max(2).optional(),
47
51
  provider: MeshProvider,
48
52
  endpointId: Identifier,
49
53
  configuredEnabled: z.boolean(),