@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 +18 -15
- package/dist/handlers/index.d.ts +1 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/version.d.ts +5 -0
- package/dist/handlers/version.js +53 -0
- package/dist/index.js +7 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +4 -1
- package/dist/tools/version.d.ts +5 -0
- package/dist/tools/version.js +28 -0
- package/dist/version.d.ts +28 -0
- package/dist/version.js +91 -0
- package/docs/TOOLS.md +26 -2
- package/package.json +1 -1
- package/src/cli-init.ts +20 -17
- package/src/handlers/index.ts +3 -0
- package/src/handlers/version.ts +63 -0
- package/src/index.ts +9 -0
- package/src/tools/index.ts +4 -0
- package/src/tools/version.ts +34 -0
- package/src/version.ts +109 -0
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
|
-
//
|
|
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');
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -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
|
package/dist/handlers/index.js
CHANGED
|
@@ -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,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 () => {
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -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, };
|
package/dist/tools/index.js
CHANGED
|
@@ -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,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>;
|
package/dist/version.js
ADDED
|
@@ -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-
|
|
5
|
+
> Generated: 2026-02-12
|
|
6
6
|
>
|
|
7
|
-
> Total tools:
|
|
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
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
|
-
//
|
|
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> {
|
package/src/handlers/index.ts
CHANGED
|
@@ -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
|
|
package/src/tools/index.ts
CHANGED
|
@@ -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
|
+
}
|