trace-mcp 1.25.0 → 1.26.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.
- package/README.md +4 -0
- package/dist/cli.js +2021 -1504
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +35 -0
- package/dist/index.js +1048 -942
- package/dist/index.js.map +1 -1
- package/hooks/trace-mcp-launcher.cmd +7 -0
- package/hooks/trace-mcp-launcher.ps1 +162 -0
- package/hooks/trace-mcp-launcher.sh +169 -0
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
REM trace-mcp-launcher v0.2.0 (Windows)
|
|
3
|
+
REM Tiny .cmd shim that invokes the PowerShell launcher. MCP clients spawn
|
|
4
|
+
REM this .cmd because they rely on %PATHEXT% resolution which prefers .cmd.
|
|
5
|
+
REM Do not edit — re-run `trace-mcp init` to refresh.
|
|
6
|
+
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%~dp0trace-mcp-launcher.ps1" %*
|
|
7
|
+
exit /b %ERRORLEVEL%
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# trace-mcp-launcher v0.2.0 (Windows)
|
|
2
|
+
# Stable shim backend: resolves node + cli.js at runtime from launcher.env,
|
|
3
|
+
# with a probe fallback for nvm-windows/nvs/Volta/system installs.
|
|
4
|
+
# Managed by trace-mcp — do not edit by hand. Re-run `trace-mcp init` to refresh.
|
|
5
|
+
|
|
6
|
+
#Requires -Version 5.1
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = 'Stop'
|
|
9
|
+
|
|
10
|
+
$TraceHome = if ($env:TRACE_MCP_HOME) { $env:TRACE_MCP_HOME } else { Join-Path $env:USERPROFILE '.trace-mcp' }
|
|
11
|
+
$ConfigPath = Join-Path $TraceHome 'launcher.env'
|
|
12
|
+
$LogPath = Join-Path $TraceHome 'launcher.log'
|
|
13
|
+
|
|
14
|
+
function Write-LauncherLog {
|
|
15
|
+
param([string]$Message)
|
|
16
|
+
try {
|
|
17
|
+
$stamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
|
|
18
|
+
Add-Content -Path $LogPath -Value "[$stamp] $Message" -ErrorAction SilentlyContinue
|
|
19
|
+
} catch {
|
|
20
|
+
# Never abort on log failure.
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function Die {
|
|
25
|
+
param([string]$Message)
|
|
26
|
+
Write-LauncherLog "ERROR: $Message"
|
|
27
|
+
[Console]::Error.WriteLine("trace-mcp launcher: $Message")
|
|
28
|
+
[Console]::Error.WriteLine('Recovery: npm i -g trace-mcp && trace-mcp init')
|
|
29
|
+
[Console]::Error.WriteLine(' (or set TRACE_MCP_NODE_OVERRIDE / TRACE_MCP_CLI_OVERRIDE)')
|
|
30
|
+
exit 127
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# --- 1. Parse config safely (no Invoke-Expression, whitelist keys) ---
|
|
34
|
+
$NodePath = ''
|
|
35
|
+
$CliPath = ''
|
|
36
|
+
|
|
37
|
+
if (Test-Path -LiteralPath $ConfigPath -PathType Leaf) {
|
|
38
|
+
foreach ($line in [System.IO.File]::ReadAllLines($ConfigPath)) {
|
|
39
|
+
$trimmed = $line.TrimStart()
|
|
40
|
+
if (-not $trimmed -or $trimmed.StartsWith('#')) { continue }
|
|
41
|
+
$idx = $trimmed.IndexOf('=')
|
|
42
|
+
if ($idx -le 0) { continue }
|
|
43
|
+
$key = $trimmed.Substring(0, $idx).Trim()
|
|
44
|
+
$val = $trimmed.Substring($idx + 1).Trim()
|
|
45
|
+
# Strip exactly one pair of surrounding double-quotes if present.
|
|
46
|
+
if ($val.Length -ge 2 -and $val.StartsWith('"') -and $val.EndsWith('"')) {
|
|
47
|
+
$val = $val.Substring(1, $val.Length - 2)
|
|
48
|
+
}
|
|
49
|
+
switch ($key) {
|
|
50
|
+
'TRACE_MCP_NODE' { $NodePath = $val }
|
|
51
|
+
'TRACE_MCP_CLI' { $CliPath = $val }
|
|
52
|
+
# TRACE_MCP_VERSION ignored (informational only)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# --- 2. Env overrides ---
|
|
58
|
+
if ($env:TRACE_MCP_NODE_OVERRIDE) { $NodePath = $env:TRACE_MCP_NODE_OVERRIDE }
|
|
59
|
+
if ($env:TRACE_MCP_CLI_OVERRIDE) { $CliPath = $env:TRACE_MCP_CLI_OVERRIDE }
|
|
60
|
+
|
|
61
|
+
function Test-NodeBinary {
|
|
62
|
+
param([string]$Path)
|
|
63
|
+
if (-not $Path) { return $false }
|
|
64
|
+
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $false }
|
|
65
|
+
return $true
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function Test-CliFile {
|
|
69
|
+
param([string]$Path)
|
|
70
|
+
if (-not $Path) { return $false }
|
|
71
|
+
return (Test-Path -LiteralPath $Path -PathType Leaf)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# --- 3. Fast path: config is good → exec directly ---
|
|
75
|
+
if ((Test-NodeBinary $NodePath) -and (Test-CliFile $CliPath)) {
|
|
76
|
+
Write-LauncherLog "exec(config) node=$NodePath cli=$CliPath argc=$($args.Count)"
|
|
77
|
+
& $NodePath $CliPath @args
|
|
78
|
+
exit $LASTEXITCODE
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# --- 4. Probe fallback (stable sources only) ---
|
|
82
|
+
|
|
83
|
+
function Find-Node {
|
|
84
|
+
# 4a. System-wide official installer
|
|
85
|
+
$candidates = @(
|
|
86
|
+
(Join-Path $env:ProgramFiles 'nodejs\node.exe'),
|
|
87
|
+
(Join-Path ${env:ProgramFiles(x86)} 'nodejs\node.exe'),
|
|
88
|
+
(Join-Path $env:LOCALAPPDATA 'Programs\nodejs\node.exe')
|
|
89
|
+
)
|
|
90
|
+
foreach ($c in $candidates) {
|
|
91
|
+
if ($c -and (Test-NodeBinary $c)) { return $c }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# 4b. Volta (stable shim dir)
|
|
95
|
+
$volta = Join-Path $env:USERPROFILE '.volta\bin\node.exe'
|
|
96
|
+
if (Test-NodeBinary $volta) { return $volta }
|
|
97
|
+
|
|
98
|
+
# 4c. nvm-windows: $APPDATA\nvm\<ver>\node.exe; active one symlinked via %NVM_SYMLINK%
|
|
99
|
+
if ($env:NVM_SYMLINK) {
|
|
100
|
+
$nvmActive = Join-Path $env:NVM_SYMLINK 'node.exe'
|
|
101
|
+
if (Test-NodeBinary $nvmActive) { return $nvmActive }
|
|
102
|
+
}
|
|
103
|
+
$nvmRoot = Join-Path $env:APPDATA 'nvm'
|
|
104
|
+
if (Test-Path -LiteralPath $nvmRoot -PathType Container) {
|
|
105
|
+
$latest = Get-ChildItem -LiteralPath $nvmRoot -Directory -ErrorAction SilentlyContinue |
|
|
106
|
+
Where-Object { $_.Name -match '^v?\d+\.\d+\.\d+$' } |
|
|
107
|
+
Sort-Object -Property Name -Descending |
|
|
108
|
+
Select-Object -First 1
|
|
109
|
+
if ($latest) {
|
|
110
|
+
$candidate = Join-Path $latest.FullName 'node.exe'
|
|
111
|
+
if (Test-NodeBinary $candidate) { return $candidate }
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# 4d. nvs: %LOCALAPPDATA%\nvs\default\<arch>\<ver>\node.exe (default alias)
|
|
116
|
+
$nvsDefault = Join-Path $env:LOCALAPPDATA 'nvs\default'
|
|
117
|
+
if (Test-Path -LiteralPath $nvsDefault -PathType Container) {
|
|
118
|
+
$nodeExe = Get-ChildItem -LiteralPath $nvsDefault -Recurse -Filter 'node.exe' -ErrorAction SilentlyContinue |
|
|
119
|
+
Select-Object -First 1
|
|
120
|
+
if ($nodeExe) { return $nodeExe.FullName }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return $null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function Find-Cli {
|
|
127
|
+
param([string]$NodeExe)
|
|
128
|
+
# npm-global layout on Windows places global modules in %APPDATA%\npm\node_modules\,
|
|
129
|
+
# not next to node.exe. Check both layouts for robustness.
|
|
130
|
+
$candidates = @(
|
|
131
|
+
(Join-Path $env:APPDATA 'npm\node_modules\trace-mcp\dist\cli.js'),
|
|
132
|
+
(Join-Path (Split-Path -Parent $NodeExe) 'node_modules\trace-mcp\dist\cli.js'),
|
|
133
|
+
# Unix-style layout (some cross-platform setups)
|
|
134
|
+
(Join-Path (Split-Path -Parent $NodeExe) '..\lib\node_modules\trace-mcp\dist\cli.js')
|
|
135
|
+
)
|
|
136
|
+
foreach ($c in $candidates) {
|
|
137
|
+
if (Test-Path -LiteralPath $c -PathType Leaf) {
|
|
138
|
+
return (Resolve-Path -LiteralPath $c).Path
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return $null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (-not (Test-NodeBinary $NodePath)) {
|
|
145
|
+
$NodePath = Find-Node
|
|
146
|
+
if (-not $NodePath) {
|
|
147
|
+
Die 'node binary not found — install Node.js (nodejs.org / nvs / nvm-windows / volta) or set TRACE_MCP_NODE_OVERRIDE'
|
|
148
|
+
}
|
|
149
|
+
Write-LauncherLog "probe: node=$NodePath"
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (-not (Test-CliFile $CliPath)) {
|
|
153
|
+
$CliPath = Find-Cli $NodePath
|
|
154
|
+
if (-not $CliPath) {
|
|
155
|
+
Die "trace-mcp package not found for node=$NodePath — run: npm i -g trace-mcp && trace-mcp init"
|
|
156
|
+
}
|
|
157
|
+
Write-LauncherLog "probe: cli=$CliPath"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
Write-LauncherLog "exec(probe) node=$NodePath cli=$CliPath argc=$($args.Count)"
|
|
161
|
+
& $NodePath $CliPath @args
|
|
162
|
+
exit $LASTEXITCODE
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# trace-mcp-launcher v0.2.0
|
|
3
|
+
# Stable shim: MCP clients invoke this path forever; it resolves node + cli.js
|
|
4
|
+
# at runtime from a config file written by `trace-mcp init`, with a minimal
|
|
5
|
+
# probe fallback for when the config is stale (e.g. Node was reinstalled).
|
|
6
|
+
#
|
|
7
|
+
# Managed by trace-mcp — do not edit by hand. Re-run `trace-mcp init` to refresh.
|
|
8
|
+
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
TRACE_HOME="${TRACE_MCP_HOME:-$HOME/.trace-mcp}"
|
|
12
|
+
CONFIG="$TRACE_HOME/launcher.env"
|
|
13
|
+
LOG="$TRACE_HOME/launcher.log"
|
|
14
|
+
|
|
15
|
+
log() {
|
|
16
|
+
# Best-effort append; never abort on log failure.
|
|
17
|
+
printf '[%s] %s\n' "$(date -u +%FT%TZ 2>/dev/null || echo '-')" "$1" >> "$LOG" 2>/dev/null || true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
die() {
|
|
21
|
+
log "ERROR: $1"
|
|
22
|
+
printf 'trace-mcp launcher: %s\n' "$1" >&2
|
|
23
|
+
printf 'Recovery: npm i -g trace-mcp && trace-mcp init\n' >&2
|
|
24
|
+
printf ' (or set TRACE_MCP_NODE_OVERRIDE / TRACE_MCP_CLI_OVERRIDE)\n' >&2
|
|
25
|
+
exit 127
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# --- 1. Parse config safely (no `source` — RCE-safe, whitelist keys) ---
|
|
29
|
+
NODE_PATH=""
|
|
30
|
+
CLI_PATH=""
|
|
31
|
+
|
|
32
|
+
if [ -r "$CONFIG" ]; then
|
|
33
|
+
# Read line by line, split on first `=`, whitelist allowed keys, strip one
|
|
34
|
+
# layer of surrounding quotes. Unknown keys and shell metacharacters in
|
|
35
|
+
# values are never evaluated — values are treated as opaque strings.
|
|
36
|
+
while IFS='=' read -r key value || [ -n "$key" ]; do
|
|
37
|
+
# Skip comments and blank lines
|
|
38
|
+
case "$key" in
|
|
39
|
+
''|\#*) continue ;;
|
|
40
|
+
esac
|
|
41
|
+
# Strip surrounding double-quotes (emitted by init for safety)
|
|
42
|
+
value="${value%\"}"
|
|
43
|
+
value="${value#\"}"
|
|
44
|
+
case "$key" in
|
|
45
|
+
TRACE_MCP_NODE) NODE_PATH="$value" ;;
|
|
46
|
+
TRACE_MCP_CLI) CLI_PATH="$value" ;;
|
|
47
|
+
# TRACE_MCP_VERSION exists but is informational only
|
|
48
|
+
esac
|
|
49
|
+
done < "$CONFIG"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# --- 2. Env overrides (escape hatch for debugging) ---
|
|
53
|
+
if [ -n "${TRACE_MCP_NODE_OVERRIDE:-}" ]; then NODE_PATH="$TRACE_MCP_NODE_OVERRIDE"; fi
|
|
54
|
+
if [ -n "${TRACE_MCP_CLI_OVERRIDE:-}" ]; then CLI_PATH="$TRACE_MCP_CLI_OVERRIDE"; fi
|
|
55
|
+
|
|
56
|
+
# --- 3. Fast path: config is good → exec directly ---
|
|
57
|
+
if [ -n "$NODE_PATH" ] && [ -x "$NODE_PATH" ] && [ -n "$CLI_PATH" ] && [ -f "$CLI_PATH" ]; then
|
|
58
|
+
log "exec(config) node=$NODE_PATH cli=$CLI_PATH argc=$#"
|
|
59
|
+
exec "$NODE_PATH" "$CLI_PATH" "$@"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# --- 4. Probe fallback (stable sources only, no version globs) ---
|
|
63
|
+
|
|
64
|
+
# Resolve node from an nvm-layout tree ($1 = root, e.g. ~/.nvm or ~/Library/.../Herd/config/nvm).
|
|
65
|
+
# Handles: concrete aliases (v22.22.2), chained aliases (default → lts/hydrogen), and
|
|
66
|
+
# major-only shortcuts (default=22 → glob versions/node/v22.*).
|
|
67
|
+
node_from_nvm_tree() {
|
|
68
|
+
local root="$1"
|
|
69
|
+
[ -f "$root/alias/default" ] || return 1
|
|
70
|
+
|
|
71
|
+
local ver
|
|
72
|
+
ver=$(head -1 "$root/alias/default" 2>/dev/null)
|
|
73
|
+
# Follow up to 2 levels of alias indirection (default → lts/hydrogen → v18.x.y)
|
|
74
|
+
local i
|
|
75
|
+
for i in 1 2; do
|
|
76
|
+
if [ -n "$ver" ] && [ -f "$root/alias/$ver" ]; then
|
|
77
|
+
ver=$(head -1 "$root/alias/$ver" 2>/dev/null)
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
[ -n "$ver" ] || return 1
|
|
81
|
+
|
|
82
|
+
# Exact-match: v22.22.2 or bare v22.22.2 (no leading v is legal too)
|
|
83
|
+
if [ -x "$root/versions/node/$ver/bin/node" ]; then
|
|
84
|
+
echo "$root/versions/node/$ver/bin/node"
|
|
85
|
+
return 0
|
|
86
|
+
fi
|
|
87
|
+
if [ -x "$root/versions/node/v$ver/bin/node" ]; then
|
|
88
|
+
echo "$root/versions/node/v$ver/bin/node"
|
|
89
|
+
return 0
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Major-only shortcut: alias=`22` → expand to newest v22.* (sort -V = version-sort)
|
|
93
|
+
if [[ "$ver" =~ ^[0-9]+$ ]]; then
|
|
94
|
+
local match
|
|
95
|
+
match=$(ls -d "$root/versions/node/v$ver".* 2>/dev/null | sort -V | tail -1)
|
|
96
|
+
if [ -n "$match" ] && [ -x "$match/bin/node" ]; then
|
|
97
|
+
echo "$match/bin/node"
|
|
98
|
+
return 0
|
|
99
|
+
fi
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
return 1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
probe_node() {
|
|
106
|
+
# 4a. System-wide stable paths (Homebrew, /usr/local)
|
|
107
|
+
for candidate in /opt/homebrew/bin/node /usr/local/bin/node; do
|
|
108
|
+
if [ -x "$candidate" ]; then
|
|
109
|
+
echo "$candidate"
|
|
110
|
+
return 0
|
|
111
|
+
fi
|
|
112
|
+
done
|
|
113
|
+
|
|
114
|
+
# 4b. Volta — stable symlink regardless of active version
|
|
115
|
+
if [ -x "$HOME/.volta/bin/node" ]; then
|
|
116
|
+
echo "$HOME/.volta/bin/node"
|
|
117
|
+
return 0
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# 4c. nvm default alias (dereference chained aliases; handle major-only shortcuts)
|
|
121
|
+
if node_from_nvm_tree "$HOME/.nvm"; then return 0; fi
|
|
122
|
+
|
|
123
|
+
# 4d. Herd (same nvm-compatible tree)
|
|
124
|
+
if node_from_nvm_tree "$HOME/Library/Application Support/Herd/config/nvm"; then return 0; fi
|
|
125
|
+
|
|
126
|
+
# 4e. fnm default alias (three possible locations)
|
|
127
|
+
for fnm_dir in \
|
|
128
|
+
"$HOME/.local/share/fnm/aliases/default" \
|
|
129
|
+
"$HOME/.fnm/aliases/default" \
|
|
130
|
+
"$HOME/Library/Application Support/fnm/aliases/default"; do
|
|
131
|
+
if [ -x "$fnm_dir/bin/node" ]; then
|
|
132
|
+
echo "$fnm_dir/bin/node"
|
|
133
|
+
return 0
|
|
134
|
+
fi
|
|
135
|
+
done
|
|
136
|
+
|
|
137
|
+
return 1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
probe_cli() {
|
|
141
|
+
# Standard layout across nvm/Herd/brew/npm: dist/cli.js sits under
|
|
142
|
+
# <node_prefix>/lib/node_modules/trace-mcp/dist/cli.js
|
|
143
|
+
local node_bin="$1"
|
|
144
|
+
local candidate
|
|
145
|
+
candidate="$(dirname "$node_bin")/../lib/node_modules/trace-mcp/dist/cli.js"
|
|
146
|
+
if [ -f "$candidate" ]; then
|
|
147
|
+
# Normalise the .. path for cleaner logging (best-effort; leave as-is if realpath is missing)
|
|
148
|
+
if command -v realpath >/dev/null 2>&1; then
|
|
149
|
+
realpath "$candidate" 2>/dev/null || echo "$candidate"
|
|
150
|
+
else
|
|
151
|
+
echo "$candidate"
|
|
152
|
+
fi
|
|
153
|
+
return 0
|
|
154
|
+
fi
|
|
155
|
+
return 1
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if [ -z "$NODE_PATH" ] || [ ! -x "$NODE_PATH" ]; then
|
|
159
|
+
NODE_PATH=$(probe_node) || die "node binary not found — install Node.js (brew install node / nvm / volta) or set TRACE_MCP_NODE_OVERRIDE"
|
|
160
|
+
log "probe: node=$NODE_PATH"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
if [ -z "$CLI_PATH" ] || [ ! -f "$CLI_PATH" ]; then
|
|
164
|
+
CLI_PATH=$(probe_cli "$NODE_PATH") || die "trace-mcp package not found next to node=$NODE_PATH — run: npm i -g trace-mcp && trace-mcp init"
|
|
165
|
+
log "probe: cli=$CLI_PATH"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
log "exec(probe) node=$NODE_PATH cli=$CLI_PATH argc=$#"
|
|
169
|
+
exec "$NODE_PATH" "$CLI_PATH" "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trace-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"mcpName": "io.github.nikolai-vysotskyi/trace-mcp",
|
|
5
5
|
"description": "Framework-aware code intelligence MCP server — 60 framework integrations, 81 languages, up to 99% token reduction",
|
|
6
6
|
"type": "module",
|