@vibescope/mcp-server 0.3.3 → 0.3.5

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/cli-init.js CHANGED
@@ -173,24 +173,27 @@ function detectAgents() {
173
173
  // Agent Configurators
174
174
  // ============================================================================
175
175
  async function configureClaudeCode(apiKey) {
176
- // Try using `claude mcp add` command
177
- try {
178
- execSync('claude --version', { stdio: 'pipe', timeout: 5000 });
179
- // Use project scope for claude mcp add
180
- try {
181
- execSync(`claude mcp add vibescope -e VIBESCOPE_API_KEY=${apiKey} -- npx -y -p @vibescope/mcp-server@latest vibescope-mcp`, { stdio: 'pipe', timeout: 15000 });
182
- console.log(` ${icon.check} Claude Code configured via ${c.cyan}claude mcp add${c.reset}`);
183
- return;
184
- }
185
- catch {
186
- // claude mcp add not available (older version), fall through to manual config
187
- }
188
- }
189
- catch { /* claude CLI not available */ }
190
- // Fallback: write .mcp.json
176
+ // Write project-level .mcp.json (works reliably across all platforms)
191
177
  const configPath = join(process.cwd(), '.mcp.json');
192
178
  writeMcpJson(configPath, apiKey);
193
179
  console.log(` ${icon.check} Wrote ${c.cyan}.mcp.json${c.reset} (Claude Code project config)`);
180
+ // Also offer to write user-level config for global access
181
+ const globalConfig = platform() === 'win32'
182
+ ? join(homedir(), '.claude', 'settings.json')
183
+ : join(homedir(), '.claude', 'settings.json');
184
+ const addGlobal = await promptConfirm(` Also add Vibescope globally (all projects)?`, true);
185
+ if (addGlobal) {
186
+ const existing = readJsonFile(globalConfig);
187
+ const mcpServers = existing.mcpServers || {};
188
+ mcpServers['vibescope'] = {
189
+ command: 'npx',
190
+ args: ['-y', '-p', '@vibescope/mcp-server@latest', 'vibescope-mcp'],
191
+ env: { VIBESCOPE_API_KEY: apiKey },
192
+ };
193
+ existing.mcpServers = mcpServers;
194
+ writeJsonFile(globalConfig, existing);
195
+ console.log(` ${icon.check} Wrote ${c.cyan}~/.claude/settings.json${c.reset} (global config)`);
196
+ }
194
197
  }
195
198
  async function configureCursor(apiKey) {
196
199
  const configPath = join(process.cwd(), '.cursor', 'mcp.json');
@@ -28,6 +28,7 @@ export * from './file-checkouts.js';
28
28
  export * from './roles.js';
29
29
  export * from './connectors.js';
30
30
  export * from './cloud-agents.js';
31
+ export * from './version.js';
31
32
  import type { HandlerRegistry } from './types.js';
32
33
  /**
33
34
  * Build the complete handler registry from all modules
@@ -28,6 +28,7 @@ export * from './file-checkouts.js';
28
28
  export * from './roles.js';
29
29
  export * from './connectors.js';
30
30
  export * from './cloud-agents.js';
31
+ export * from './version.js';
31
32
  import { milestoneHandlers } from './milestones.js';
32
33
  import { sessionHandlers } from './session.js';
33
34
  import { ideaHandlers } from './ideas.js';
@@ -51,6 +52,7 @@ import { fileCheckoutHandlers } from './file-checkouts.js';
51
52
  import { roleHandlers } from './roles.js';
52
53
  import { connectorHandlers } from './connectors.js';
53
54
  import { cloudAgentHandlers } from './cloud-agents.js';
55
+ import { versionHandlers } from './version.js';
54
56
  /**
55
57
  * Build the complete handler registry from all modules
56
58
  */
@@ -79,5 +81,6 @@ export function buildHandlerRegistry() {
79
81
  ...roleHandlers,
80
82
  ...connectorHandlers,
81
83
  ...cloudAgentHandlers,
84
+ ...versionHandlers,
82
85
  };
83
86
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Version management handlers
3
+ */
4
+ import type { HandlerRegistry } from './types.js';
5
+ export declare const versionHandlers: HandlerRegistry;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Version management handlers
3
+ */
4
+ import { execSync } from 'child_process';
5
+ import { success, error } from './types.js';
6
+ import { checkVersion, getLocalVersion } from '../version.js';
7
+ const PACKAGE_NAME = '@vibescope/mcp-server';
8
+ export const versionHandlers = {
9
+ check_mcp_version: async (_args, _ctx) => {
10
+ const info = await checkVersion();
11
+ if (info.error) {
12
+ return success({
13
+ current_version: info.current,
14
+ latest_version: info.latest,
15
+ update_available: false,
16
+ warning: info.error,
17
+ });
18
+ }
19
+ return success({
20
+ current_version: info.current,
21
+ latest_version: info.latest,
22
+ update_available: info.updateAvailable,
23
+ message: info.updateAvailable
24
+ ? `Update available! v${info.current} → v${info.latest}. Ask the user if they would like to update using the update_mcp_server tool.`
25
+ : `Vibescope MCP server is up to date (v${info.current}).`,
26
+ });
27
+ },
28
+ update_mcp_server: async (args, _ctx) => {
29
+ const useGlobal = args.global !== false; // default true
30
+ const flag = useGlobal ? '-g ' : '';
31
+ const command = `npm install ${flag}${PACKAGE_NAME}@latest`;
32
+ try {
33
+ const output = execSync(command, {
34
+ encoding: 'utf-8',
35
+ timeout: 60000,
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ });
38
+ // Check the new version
39
+ const newVersion = getLocalVersion();
40
+ return success({
41
+ updated: true,
42
+ command_run: command,
43
+ output: output.trim(),
44
+ new_version: newVersion,
45
+ message: 'Update complete. The MCP server must be restarted to use the new version. Please ask the user to restart their editor/MCP client, or reconnect the MCP server.',
46
+ });
47
+ }
48
+ catch (err) {
49
+ const message = err instanceof Error ? err.message : String(err);
50
+ return error(`Failed to update: ${message}. The user may need to run manually: ${command}`);
51
+ }
52
+ },
53
+ };
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { RateLimiter, getErrorMessage, } from './utils.js';
9
9
  import { buildHandlerRegistry } from './handlers/index.js';
10
10
  import { tools } from './tools/index.js';
11
11
  import { createTokenUsage, trackTokenUsage as trackTokens, } from './token-tracking.js';
12
+ import { getUpdateWarning } from './version.js';
12
13
  // ============================================================================
13
14
  // Agent Instance Tracking
14
15
  // ============================================================================
@@ -210,6 +211,11 @@ async function main() {
210
211
  console.error('Invalid API key');
211
212
  process.exit(1);
212
213
  }
214
+ // Check for updates (non-blocking, with timeout)
215
+ const updateWarning = await getUpdateWarning();
216
+ const serverInstructions = updateWarning
217
+ ? `${updateWarning}\n\nVibescope MCP server - AI project tracking and coordination tools.`
218
+ : 'Vibescope MCP server - AI project tracking and coordination tools.';
213
219
  const server = new Server({
214
220
  name: 'vibescope',
215
221
  version: '0.1.0',
@@ -217,6 +223,7 @@ async function main() {
217
223
  capabilities: {
218
224
  tools: {},
219
225
  },
226
+ instructions: serverInstructions,
220
227
  });
221
228
  // List available tools
222
229
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -30,6 +30,7 @@ import { sprintTools } from './sprints.js';
30
30
  import { gitIssueTools } from './git-issues.js';
31
31
  import { connectorTools } from './connectors.js';
32
32
  import { cloudAgentTools } from './cloud-agents.js';
33
+ import { versionTools } from './version.js';
33
34
  /**
34
35
  * All MCP tool definitions combined
35
36
  */
@@ -67,5 +68,6 @@ export declare const toolCategories: {
67
68
  readonly gitIssues: string[];
68
69
  readonly connectors: string[];
69
70
  readonly cloudAgents: string[];
71
+ readonly version: string[];
70
72
  };
71
- export { sessionTools, costTools, discoveryTools, worktreeTools, projectTools, taskTools, progressTools, blockerTools, decisionTools, ideaTools, findingTools, validationTools, deploymentTools, fallbackTools, requestTools, milestoneTools, bodiesOfWorkTools, organizationTools, fileCheckoutTools, roleTools, sprintTools, gitIssueTools, connectorTools, cloudAgentTools, };
73
+ export { sessionTools, costTools, discoveryTools, worktreeTools, projectTools, taskTools, progressTools, blockerTools, decisionTools, ideaTools, findingTools, validationTools, deploymentTools, fallbackTools, requestTools, milestoneTools, bodiesOfWorkTools, organizationTools, fileCheckoutTools, roleTools, sprintTools, gitIssueTools, connectorTools, cloudAgentTools, versionTools, };
@@ -29,6 +29,7 @@ import { sprintTools } from './sprints.js';
29
29
  import { gitIssueTools } from './git-issues.js';
30
30
  import { connectorTools } from './connectors.js';
31
31
  import { cloudAgentTools } from './cloud-agents.js';
32
+ import { versionTools } from './version.js';
32
33
  /**
33
34
  * All MCP tool definitions combined
34
35
  */
@@ -57,6 +58,7 @@ export const tools = [
57
58
  ...gitIssueTools,
58
59
  ...connectorTools,
59
60
  ...cloudAgentTools,
61
+ ...versionTools,
60
62
  ];
61
63
  /**
62
64
  * Build the complete tool list from all domain modules
@@ -93,6 +95,7 @@ export const toolCategories = {
93
95
  gitIssues: gitIssueTools.map((t) => t.name),
94
96
  connectors: connectorTools.map((t) => t.name),
95
97
  cloudAgents: cloudAgentTools.map((t) => t.name),
98
+ version: versionTools.map((t) => t.name),
96
99
  };
97
100
  // Re-export domain tools for selective imports
98
- export { sessionTools, costTools, discoveryTools, worktreeTools, projectTools, taskTools, progressTools, blockerTools, decisionTools, ideaTools, findingTools, validationTools, deploymentTools, fallbackTools, requestTools, milestoneTools, bodiesOfWorkTools, organizationTools, fileCheckoutTools, roleTools, sprintTools, gitIssueTools, connectorTools, cloudAgentTools, };
101
+ export { sessionTools, costTools, discoveryTools, worktreeTools, projectTools, taskTools, progressTools, blockerTools, decisionTools, ideaTools, findingTools, validationTools, deploymentTools, fallbackTools, requestTools, milestoneTools, bodiesOfWorkTools, organizationTools, fileCheckoutTools, roleTools, sprintTools, gitIssueTools, connectorTools, cloudAgentTools, versionTools, };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Version management tool definitions
3
+ */
4
+ import type { Tool } from './types.js';
5
+ export declare const versionTools: Tool[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Version management tool definitions
3
+ */
4
+ export const versionTools = [
5
+ {
6
+ name: 'check_mcp_version',
7
+ description: 'Check if the Vibescope MCP server is up to date. Compares the locally installed version against the latest published version on npm. Call this when starting a session or when the server instructions indicate an update is available.',
8
+ inputSchema: {
9
+ type: 'object',
10
+ properties: {},
11
+ required: [],
12
+ },
13
+ },
14
+ {
15
+ name: 'update_mcp_server',
16
+ description: 'Update the Vibescope MCP server to the latest version. Runs npm install to fetch the latest version. After updating, the server must be restarted (the agent should ask the user to restart their MCP client/editor). Only call this when the user agrees to update.',
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: {
20
+ global: {
21
+ type: 'boolean',
22
+ description: 'If true, update the global installation (npm install -g). If false, update locally. Default: true.',
23
+ },
24
+ },
25
+ required: [],
26
+ },
27
+ },
28
+ ];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Version checking utilities
3
+ *
4
+ * Compares the locally installed version against the latest published
5
+ * version on npm to detect available updates.
6
+ */
7
+ export interface VersionInfo {
8
+ current: string;
9
+ latest: string | null;
10
+ updateAvailable: boolean;
11
+ error?: string;
12
+ }
13
+ /**
14
+ * Get the current locally installed version from package.json
15
+ */
16
+ export declare function getLocalVersion(): string;
17
+ /**
18
+ * Fetch the latest published version from npm registry
19
+ */
20
+ export declare function getLatestVersion(): Promise<string | null>;
21
+ /**
22
+ * Check if an update is available
23
+ */
24
+ export declare function checkVersion(): Promise<VersionInfo>;
25
+ /**
26
+ * Get the update warning message for server instructions, or null if up to date
27
+ */
28
+ export declare function getUpdateWarning(): Promise<string | null>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Version checking utilities
3
+ *
4
+ * Compares the locally installed version against the latest published
5
+ * version on npm to detect available updates.
6
+ */
7
+ import { readFileSync } from 'fs';
8
+ import { resolve, dirname } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@vibescope/mcp-server';
11
+ const PACKAGE_NAME = '@vibescope/mcp-server';
12
+ /**
13
+ * Get the current locally installed version from package.json
14
+ */
15
+ export function getLocalVersion() {
16
+ try {
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ const pkgPath = resolve(__dirname, '..', 'package.json');
19
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
20
+ return pkg.version;
21
+ }
22
+ catch {
23
+ return 'unknown';
24
+ }
25
+ }
26
+ /**
27
+ * Fetch the latest published version from npm registry
28
+ */
29
+ export async function getLatestVersion() {
30
+ try {
31
+ const controller = new AbortController();
32
+ const timeout = setTimeout(() => controller.abort(), 5000);
33
+ const response = await fetch(`${NPM_REGISTRY_URL}/latest`, {
34
+ signal: controller.signal,
35
+ headers: { 'Accept': 'application/json' },
36
+ });
37
+ clearTimeout(timeout);
38
+ if (!response.ok)
39
+ return null;
40
+ const data = (await response.json());
41
+ return data.version ?? null;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ /**
48
+ * Compare semver strings. Returns true if latest > current.
49
+ */
50
+ function isNewer(current, latest) {
51
+ const parse = (v) => v.split('.').map(Number);
52
+ const c = parse(current);
53
+ const l = parse(latest);
54
+ for (let i = 0; i < 3; i++) {
55
+ if ((l[i] ?? 0) > (c[i] ?? 0))
56
+ return true;
57
+ if ((l[i] ?? 0) < (c[i] ?? 0))
58
+ return false;
59
+ }
60
+ return false;
61
+ }
62
+ /**
63
+ * Check if an update is available
64
+ */
65
+ export async function checkVersion() {
66
+ const current = getLocalVersion();
67
+ const latest = await getLatestVersion();
68
+ if (!latest) {
69
+ return {
70
+ current,
71
+ latest: null,
72
+ updateAvailable: false,
73
+ error: 'Could not reach npm registry to check for updates',
74
+ };
75
+ }
76
+ return {
77
+ current,
78
+ latest,
79
+ updateAvailable: isNewer(current, latest),
80
+ };
81
+ }
82
+ /**
83
+ * Get the update warning message for server instructions, or null if up to date
84
+ */
85
+ export async function getUpdateWarning() {
86
+ const info = await checkVersion();
87
+ if (info.updateAvailable && info.latest) {
88
+ return `⚠️ UPDATE AVAILABLE: Vibescope MCP server v${info.current} is outdated. Latest version is v${info.latest}. Before starting work, inform the user that an update is available and recommend running the \`check_mcp_version\` tool, or ask them to update with: npm install -g ${PACKAGE_NAME}@latest (or npx @vibescope/mcp-server@latest for auto-update on next run).`;
89
+ }
90
+ return null;
91
+ }
package/docs/TOOLS.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  > Auto-generated from tool definitions. Do not edit manually.
4
4
  >
5
- > Generated: 2026-02-06
5
+ > Generated: 2026-02-12
6
6
  >
7
- > Total tools: 154
7
+ > Total tools: 156
8
8
 
9
9
  ## Table of Contents
10
10
 
@@ -2457,3 +2457,27 @@ Use this to check the state of cloud agents before/after cleanup.
2457
2457
  | `status` | `"starting" | "running" | "stopped" | "failed" | "all"` | No | Filter by status (default: all) |
2458
2458
 
2459
2459
  ---
2460
+
2461
+ ## Uncategorized
2462
+
2463
+ *Tools not yet assigned to a category*
2464
+
2465
+ ### check_mcp_version
2466
+
2467
+ Check if the Vibescope MCP server is up to date. Compares the locally installed version against the latest published version on npm. Call this when starting a session or when the server instructions indicate an update is available.
2468
+
2469
+ **Parameters:** None
2470
+
2471
+ ---
2472
+
2473
+ ### update_mcp_server
2474
+
2475
+ Update the Vibescope MCP server to the latest version. Runs npm install to fetch the latest version. After updating, the server must be restarted (the agent should ask the user to restart their MCP client/editor). Only call this when the user agrees to update.
2476
+
2477
+ **Parameters:**
2478
+
2479
+ | Parameter | Type | Required | Description |
2480
+ |-----------|------|----------|-------------|
2481
+ | `global` | `boolean` | No | If true, update the global installation (npm install -g). If false, update locally. Default: true. |
2482
+
2483
+ ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibescope/mcp-server",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "MCP server for Vibescope - AI project tracking tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/cli-init.ts CHANGED
@@ -204,26 +204,29 @@ function detectAgents(): Agent[] {
204
204
  // ============================================================================
205
205
 
206
206
  async function configureClaudeCode(apiKey: string): Promise<void> {
207
- // Try using `claude mcp add` command
208
- try {
209
- execSync('claude --version', { stdio: 'pipe', timeout: 5000 });
210
- // Use project scope for claude mcp add
211
- try {
212
- execSync(
213
- `claude mcp add vibescope -e VIBESCOPE_API_KEY=${apiKey} -- npx -y -p @vibescope/mcp-server@latest vibescope-mcp`,
214
- { stdio: 'pipe', timeout: 15000 }
215
- );
216
- console.log(` ${icon.check} Claude Code configured via ${c.cyan}claude mcp add${c.reset}`);
217
- return;
218
- } catch {
219
- // claude mcp add not available (older version), fall through to manual config
220
- }
221
- } catch { /* claude CLI not available */ }
222
-
223
- // Fallback: write .mcp.json
207
+ // Write project-level .mcp.json (works reliably across all platforms)
224
208
  const configPath = join(process.cwd(), '.mcp.json');
225
209
  writeMcpJson(configPath, apiKey);
226
210
  console.log(` ${icon.check} Wrote ${c.cyan}.mcp.json${c.reset} (Claude Code project config)`);
211
+
212
+ // Also offer to write user-level config for global access
213
+ const globalConfig = platform() === 'win32'
214
+ ? join(homedir(), '.claude', 'settings.json')
215
+ : join(homedir(), '.claude', 'settings.json');
216
+
217
+ const addGlobal = await promptConfirm(` Also add Vibescope globally (all projects)?`, true);
218
+ if (addGlobal) {
219
+ const existing = readJsonFile(globalConfig);
220
+ const mcpServers = (existing.mcpServers as Record<string, unknown>) || {};
221
+ mcpServers['vibescope'] = {
222
+ command: 'npx',
223
+ args: ['-y', '-p', '@vibescope/mcp-server@latest', 'vibescope-mcp'],
224
+ env: { VIBESCOPE_API_KEY: apiKey },
225
+ };
226
+ existing.mcpServers = mcpServers;
227
+ writeJsonFile(globalConfig, existing);
228
+ console.log(` ${icon.check} Wrote ${c.cyan}~/.claude/settings.json${c.reset} (global config)`);
229
+ }
227
230
  }
228
231
 
229
232
  async function configureCursor(apiKey: string): Promise<void> {
@@ -29,6 +29,7 @@ export * from './file-checkouts.js';
29
29
  export * from './roles.js';
30
30
  export * from './connectors.js';
31
31
  export * from './cloud-agents.js';
32
+ export * from './version.js';
32
33
 
33
34
  import type { HandlerRegistry } from './types.js';
34
35
  import { milestoneHandlers } from './milestones.js';
@@ -54,6 +55,7 @@ import { fileCheckoutHandlers } from './file-checkouts.js';
54
55
  import { roleHandlers } from './roles.js';
55
56
  import { connectorHandlers } from './connectors.js';
56
57
  import { cloudAgentHandlers } from './cloud-agents.js';
58
+ import { versionHandlers } from './version.js';
57
59
 
58
60
  /**
59
61
  * Build the complete handler registry from all modules
@@ -83,5 +85,6 @@ export function buildHandlerRegistry(): HandlerRegistry {
83
85
  ...roleHandlers,
84
86
  ...connectorHandlers,
85
87
  ...cloudAgentHandlers,
88
+ ...versionHandlers,
86
89
  };
87
90
  }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Version management handlers
3
+ */
4
+
5
+ import { execSync } from 'child_process';
6
+ import type { HandlerRegistry } from './types.js';
7
+ import { success, error } from './types.js';
8
+ import { checkVersion, getLocalVersion } from '../version.js';
9
+
10
+ const PACKAGE_NAME = '@vibescope/mcp-server';
11
+
12
+ export const versionHandlers: HandlerRegistry = {
13
+ check_mcp_version: async (_args, _ctx) => {
14
+ const info = await checkVersion();
15
+
16
+ if (info.error) {
17
+ return success({
18
+ current_version: info.current,
19
+ latest_version: info.latest,
20
+ update_available: false,
21
+ warning: info.error,
22
+ });
23
+ }
24
+
25
+ return success({
26
+ current_version: info.current,
27
+ latest_version: info.latest,
28
+ update_available: info.updateAvailable,
29
+ message: info.updateAvailable
30
+ ? `Update available! v${info.current} → v${info.latest}. Ask the user if they would like to update using the update_mcp_server tool.`
31
+ : `Vibescope MCP server is up to date (v${info.current}).`,
32
+ });
33
+ },
34
+
35
+ update_mcp_server: async (args, _ctx) => {
36
+ const useGlobal = args.global !== false; // default true
37
+ const flag = useGlobal ? '-g ' : '';
38
+ const command = `npm install ${flag}${PACKAGE_NAME}@latest`;
39
+
40
+ try {
41
+ const output = execSync(command, {
42
+ encoding: 'utf-8',
43
+ timeout: 60000,
44
+ stdio: ['pipe', 'pipe', 'pipe'],
45
+ });
46
+
47
+ // Check the new version
48
+ const newVersion = getLocalVersion();
49
+
50
+ return success({
51
+ updated: true,
52
+ command_run: command,
53
+ output: output.trim(),
54
+ new_version: newVersion,
55
+ message:
56
+ 'Update complete. The MCP server must be restarted to use the new version. Please ask the user to restart their editor/MCP client, or reconnect the MCP server.',
57
+ });
58
+ } catch (err) {
59
+ const message = err instanceof Error ? err.message : String(err);
60
+ return error(`Failed to update: ${message}. The user may need to run manually: ${command}`);
61
+ }
62
+ },
63
+ };
package/src/index.ts CHANGED
@@ -43,6 +43,7 @@ import {
43
43
  setCurrentModel,
44
44
  type TokenUsage,
45
45
  } from './token-tracking.js';
46
+ import { getUpdateWarning } from './version.js';
46
47
 
47
48
  // ============================================================================
48
49
  // Agent Instance Tracking
@@ -654,6 +655,13 @@ async function main() {
654
655
  process.exit(1);
655
656
  }
656
657
 
658
+ // Check for updates (non-blocking, with timeout)
659
+ const updateWarning = await getUpdateWarning();
660
+
661
+ const serverInstructions = updateWarning
662
+ ? `${updateWarning}\n\nVibescope MCP server - AI project tracking and coordination tools.`
663
+ : 'Vibescope MCP server - AI project tracking and coordination tools.';
664
+
657
665
  const server = new Server(
658
666
  {
659
667
  name: 'vibescope',
@@ -663,6 +671,7 @@ async function main() {
663
671
  capabilities: {
664
672
  tools: {},
665
673
  },
674
+ instructions: serverInstructions,
666
675
  }
667
676
  );
668
677
 
@@ -33,6 +33,7 @@ import { sprintTools } from './sprints.js';
33
33
  import { gitIssueTools } from './git-issues.js';
34
34
  import { connectorTools } from './connectors.js';
35
35
  import { cloudAgentTools } from './cloud-agents.js';
36
+ import { versionTools } from './version.js';
36
37
 
37
38
  /**
38
39
  * All MCP tool definitions combined
@@ -62,6 +63,7 @@ export const tools: Tool[] = [
62
63
  ...gitIssueTools,
63
64
  ...connectorTools,
64
65
  ...cloudAgentTools,
66
+ ...versionTools,
65
67
  ];
66
68
 
67
69
  /**
@@ -100,6 +102,7 @@ export const toolCategories = {
100
102
  gitIssues: gitIssueTools.map((t) => t.name),
101
103
  connectors: connectorTools.map((t) => t.name),
102
104
  cloudAgents: cloudAgentTools.map((t) => t.name),
105
+ version: versionTools.map((t) => t.name),
103
106
  } as const;
104
107
 
105
108
  // Re-export domain tools for selective imports
@@ -128,4 +131,5 @@ export {
128
131
  gitIssueTools,
129
132
  connectorTools,
130
133
  cloudAgentTools,
134
+ versionTools,
131
135
  };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Version management tool definitions
3
+ */
4
+
5
+ import type { Tool } from './types.js';
6
+
7
+ export const versionTools: Tool[] = [
8
+ {
9
+ name: 'check_mcp_version',
10
+ description:
11
+ 'Check if the Vibescope MCP server is up to date. Compares the locally installed version against the latest published version on npm. Call this when starting a session or when the server instructions indicate an update is available.',
12
+ inputSchema: {
13
+ type: 'object' as const,
14
+ properties: {},
15
+ required: [],
16
+ },
17
+ },
18
+ {
19
+ name: 'update_mcp_server',
20
+ description:
21
+ 'Update the Vibescope MCP server to the latest version. Runs npm install to fetch the latest version. After updating, the server must be restarted (the agent should ask the user to restart their MCP client/editor). Only call this when the user agrees to update.',
22
+ inputSchema: {
23
+ type: 'object' as const,
24
+ properties: {
25
+ global: {
26
+ type: 'boolean',
27
+ description:
28
+ 'If true, update the global installation (npm install -g). If false, update locally. Default: true.',
29
+ },
30
+ },
31
+ required: [],
32
+ },
33
+ },
34
+ ];
package/src/version.ts ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Version checking utilities
3
+ *
4
+ * Compares the locally installed version against the latest published
5
+ * version on npm to detect available updates.
6
+ */
7
+
8
+ import { readFileSync } from 'fs';
9
+ import { resolve, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@vibescope/mcp-server';
13
+ const PACKAGE_NAME = '@vibescope/mcp-server';
14
+
15
+ export interface VersionInfo {
16
+ current: string;
17
+ latest: string | null;
18
+ updateAvailable: boolean;
19
+ error?: string;
20
+ }
21
+
22
+ /**
23
+ * Get the current locally installed version from package.json
24
+ */
25
+ export function getLocalVersion(): string {
26
+ try {
27
+ const __dirname = dirname(fileURLToPath(import.meta.url));
28
+ const pkgPath = resolve(__dirname, '..', 'package.json');
29
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
30
+ return pkg.version;
31
+ } catch {
32
+ return 'unknown';
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Fetch the latest published version from npm registry
38
+ */
39
+ export async function getLatestVersion(): Promise<string | null> {
40
+ try {
41
+ const controller = new AbortController();
42
+ const timeout = setTimeout(() => controller.abort(), 5000);
43
+
44
+ const response = await fetch(`${NPM_REGISTRY_URL}/latest`, {
45
+ signal: controller.signal,
46
+ headers: { 'Accept': 'application/json' },
47
+ });
48
+
49
+ clearTimeout(timeout);
50
+
51
+ if (!response.ok) return null;
52
+
53
+ const data = (await response.json()) as { version?: string };
54
+ return data.version ?? null;
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Compare semver strings. Returns true if latest > current.
62
+ */
63
+ function isNewer(current: string, latest: string): boolean {
64
+ const parse = (v: string) => v.split('.').map(Number);
65
+ const c = parse(current);
66
+ const l = parse(latest);
67
+
68
+ for (let i = 0; i < 3; i++) {
69
+ if ((l[i] ?? 0) > (c[i] ?? 0)) return true;
70
+ if ((l[i] ?? 0) < (c[i] ?? 0)) return false;
71
+ }
72
+ return false;
73
+ }
74
+
75
+ /**
76
+ * Check if an update is available
77
+ */
78
+ export async function checkVersion(): Promise<VersionInfo> {
79
+ const current = getLocalVersion();
80
+ const latest = await getLatestVersion();
81
+
82
+ if (!latest) {
83
+ return {
84
+ current,
85
+ latest: null,
86
+ updateAvailable: false,
87
+ error: 'Could not reach npm registry to check for updates',
88
+ };
89
+ }
90
+
91
+ return {
92
+ current,
93
+ latest,
94
+ updateAvailable: isNewer(current, latest),
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Get the update warning message for server instructions, or null if up to date
100
+ */
101
+ export async function getUpdateWarning(): Promise<string | null> {
102
+ const info = await checkVersion();
103
+
104
+ if (info.updateAvailable && info.latest) {
105
+ return `⚠️ UPDATE AVAILABLE: Vibescope MCP server v${info.current} is outdated. Latest version is v${info.latest}. Before starting work, inform the user that an update is available and recommend running the \`check_mcp_version\` tool, or ask them to update with: npm install -g ${PACKAGE_NAME}@latest (or npx @vibescope/mcp-server@latest for auto-update on next run).`;
106
+ }
107
+
108
+ return null;
109
+ }