mcp-efficiency-engine 0.1.5 → 0.1.6

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/.vscode/mcp.json CHANGED
@@ -7,16 +7,23 @@
7
7
  "command": "codebase-memory-mcp"
8
8
  },
9
9
  "codegraph": {
10
- "command": "codegraph",
10
+ "command": "pwsh",
11
11
  "args": [
12
- "serve",
13
- "--mcp"
12
+ "-NoProfile",
13
+ "-ExecutionPolicy",
14
+ "Bypass",
15
+ "-File",
16
+ "scripts/ops/start-codegraph-mcp.ps1"
14
17
  ]
15
18
  },
16
19
  "gitnexus": {
17
- "command": "gitnexus",
20
+ "command": "pwsh",
18
21
  "args": [
19
- "mcp"
22
+ "-NoProfile",
23
+ "-ExecutionPolicy",
24
+ "Bypass",
25
+ "-File",
26
+ "scripts/ops/start-gitnexus-mcp.ps1"
20
27
  ],
21
28
  "env": {
22
29
  "GITNEXUS_SEMANTIC_EXACT_SCAN_LIMIT": "50000",
package/README.md CHANGED
@@ -233,6 +233,17 @@ py -3 .\scripts\intake\run-routing-evals.py
233
233
  .\scripts\ops\bye.ps1
234
234
  ```
235
235
 
236
+ Telemetría de terminal (PowerShell, opcional):
237
+
238
+ ```powershell
239
+ mcpee observe-on
240
+ # ... comandos interactivos ...
241
+ mcpee observe-off
242
+ ```
243
+
244
+ - `mcpee observe-on` instala un hook global de perfil PowerShell para emitir un evento de telemetría por comando usando `scripts/ops/emit-terminal-command-telemetry.py`.
245
+ - `mcpee observe-off` elimina el hook global y restaura el perfil sin instrumentación.
246
+
236
247
  Validación extendida recomendada:
237
248
 
238
249
  ```powershell
package/bin/mcpee.js CHANGED
@@ -12,8 +12,77 @@ const commandMap = {
12
12
  hi: "scripts/ops/hi.ps1",
13
13
  bye: "scripts/ops/bye.ps1",
14
14
  intake: "scripts/intake/run-repo-intake.ps1",
15
+ "observe-on": "scripts/ops/install-terminal-telemetry-hook.ps1",
16
+ "observe-off": "scripts/ops/uninstall-terminal-telemetry-hook.ps1",
15
17
  };
16
18
 
19
+ function resolveSessionId() {
20
+ const explicitSessionId = (process.env.MCP_SESSION_ID || "").trim();
21
+ if (explicitSessionId) {
22
+ return explicitSessionId;
23
+ }
24
+
25
+ const sessionLogHint = (process.env.VSCODE_TARGET_SESSION_LOG || "").trim();
26
+ if (sessionLogHint) {
27
+ const match = sessionLogHint.match(/[0-9a-fA-F-]{36}/);
28
+ if (match && match[0]) {
29
+ return match[0];
30
+ }
31
+ }
32
+
33
+ return "mcpee-cli";
34
+ }
35
+
36
+ function resolvePythonCandidates() {
37
+ if (process.platform === "win32") {
38
+ return [
39
+ ["py", ["-3"]],
40
+ ["python", []],
41
+ ["python3", []],
42
+ ];
43
+ }
44
+
45
+ return [
46
+ ["python3", []],
47
+ ["python", []],
48
+ ];
49
+ }
50
+
51
+ function runCopilotUsageIngest(repoRootPath) {
52
+ const sessionLogHint = (process.env.VSCODE_TARGET_SESSION_LOG || "").trim();
53
+ if (!sessionLogHint) {
54
+ return;
55
+ }
56
+
57
+ const ingestScriptPath = path.join(repoRootPath, "scripts", "learning", "ingest-copilot-session-usage.py");
58
+ if (!fs.existsSync(ingestScriptPath)) {
59
+ return;
60
+ }
61
+
62
+ for (const [pythonCommand, pythonPrefixArgs] of resolvePythonCandidates()) {
63
+ const ingestResult = spawnSync(
64
+ pythonCommand,
65
+ [
66
+ ...pythonPrefixArgs,
67
+ ingestScriptPath,
68
+ "--session-log",
69
+ sessionLogHint,
70
+ ],
71
+ {
72
+ cwd: repoRootPath,
73
+ stdio: "ignore",
74
+ },
75
+ );
76
+
77
+ if (ingestResult.error && ingestResult.error.code === "ENOENT") {
78
+ continue;
79
+ }
80
+
81
+ // La ingesta es best-effort: si falla no bloquea el comando principal.
82
+ return;
83
+ }
84
+ }
85
+
17
86
  function resolveExecutionRoot(scriptRelativePath) {
18
87
  const configuredTarget = process.env.MCPEE_TARGET_DIR ? path.resolve(process.env.MCPEE_TARGET_DIR) : "";
19
88
  const cwdRoot = process.cwd();
@@ -41,6 +110,8 @@ function printHelp() {
41
110
  " hi Ejecuta el preflight diario.",
42
111
  " bye Ejecuta el cierre diario.",
43
112
  " intake Ejecuta el repo intake.",
113
+ " observe-on Activa telemetria global del terminal (hook PowerShell).",
114
+ " observe-off Desactiva telemetria global del terminal.",
44
115
  "",
45
116
  "Ejemplos:",
46
117
  " npx mcp-efficiency-engine bootstrap",
@@ -61,6 +132,10 @@ function runPowerShellScript(scriptRelativePath, forwardedArgs) {
61
132
  const executionRoot = resolveExecutionRoot(scriptRelativePath);
62
133
  const scriptPath = path.join(executionRoot, scriptRelativePath);
63
134
  const tracerScriptPath = path.join(repoRoot, "scripts", "ops", "trace-command.py");
135
+ const sessionId = resolveSessionId();
136
+
137
+ runCopilotUsageIngest(repoRoot);
138
+
64
139
  if (!fs.existsSync(scriptPath)) {
65
140
  process.stderr.write(`Script no encontrado: ${scriptRelativePath}\n`);
66
141
  return 1;
@@ -70,37 +145,42 @@ function runPowerShellScript(scriptRelativePath, forwardedArgs) {
70
145
  for (const shellCommand of shellCandidates) {
71
146
  if (fs.existsSync(tracerScriptPath)) {
72
147
  const operation = `mcpee.${path.basename(scriptRelativePath, path.extname(scriptRelativePath))}`;
73
- const tracedResult = spawnSync(
74
- "py",
75
- [
76
- "-3",
77
- tracerScriptPath,
78
- "--operation",
79
- operation,
80
- "--session-id",
81
- "mcpee-cli",
82
- "--cwd",
83
- executionRoot,
84
- "--",
85
- shellCommand,
86
- "-NoProfile",
87
- "-ExecutionPolicy",
88
- "Bypass",
89
- "-File",
90
- scriptPath,
91
- ...forwardedArgs,
92
- ],
93
- {
94
- cwd: repoRoot,
95
- stdio: "inherit",
96
- },
97
- );
98
-
99
- if (!tracedResult.error || tracedResult.error.code !== "ENOENT") {
148
+ for (const [pythonCommand, pythonPrefixArgs] of resolvePythonCandidates()) {
149
+ const tracedResult = spawnSync(
150
+ pythonCommand,
151
+ [
152
+ ...pythonPrefixArgs,
153
+ tracerScriptPath,
154
+ "--operation",
155
+ operation,
156
+ "--session-id",
157
+ sessionId,
158
+ "--cwd",
159
+ executionRoot,
160
+ "--",
161
+ shellCommand,
162
+ "-NoProfile",
163
+ "-ExecutionPolicy",
164
+ "Bypass",
165
+ "-File",
166
+ scriptPath,
167
+ ...forwardedArgs,
168
+ ],
169
+ {
170
+ cwd: repoRoot,
171
+ stdio: "inherit",
172
+ },
173
+ );
174
+
175
+ if (tracedResult.error && tracedResult.error.code === "ENOENT") {
176
+ continue;
177
+ }
178
+
100
179
  if (tracedResult.error) {
101
180
  process.stderr.write(`${tracedResult.error.message}\n`);
102
181
  return 1;
103
182
  }
183
+
104
184
  return tracedResult.status ?? 0;
105
185
  }
106
186
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-efficiency-engine",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Motor de orquestacion para agentes MCP con routing por dominio y bootstrap portable.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -0,0 +1,84 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import hashlib
5
+ import sys
6
+ from pathlib import Path
7
+
8
+
9
+ def _bootstrap_repo_root() -> Path:
10
+ repo_root = Path(__file__).resolve().parents[2]
11
+ if str(repo_root) not in sys.path:
12
+ sys.path.insert(0, str(repo_root))
13
+ return repo_root
14
+
15
+
16
+ def _hash_command(command: str) -> str:
17
+ return hashlib.sha256(command.encode("utf-8")).hexdigest()[:16]
18
+
19
+
20
+ def main() -> int:
21
+ parser = argparse.ArgumentParser(description="Emit telemetry for an already executed terminal command.")
22
+ parser.add_argument("--session-id", default="terminal-session", help="Session identifier")
23
+ parser.add_argument("--cwd", default=".", help="Current working directory")
24
+ parser.add_argument("--command", default="", help="Executed command text")
25
+ parser.add_argument("--success", default="true", help="Whether command succeeded (true/false)")
26
+ parser.add_argument("--exit-code", type=int, default=0, help="Exit code for native commands")
27
+ args = parser.parse_args()
28
+
29
+ command_text = (args.command or "").strip()
30
+ if not command_text:
31
+ return 0
32
+
33
+ repo_root = _bootstrap_repo_root()
34
+ from telemetry import build_telemetry_collector
35
+
36
+ collector = build_telemetry_collector(repo_root)
37
+
38
+ success = str(args.success).strip().lower() in {"1", "true", "yes", "ok"}
39
+ normalized_cwd = str(Path(args.cwd).resolve())
40
+
41
+ with collector.start_execution(
42
+ operation="terminal.command",
43
+ session_id=str(args.session_id).strip() or "terminal-session",
44
+ model="powershell",
45
+ provider="local-shell",
46
+ ):
47
+ with collector.start_span(
48
+ name="terminal.executed_command",
49
+ kind="TOOL",
50
+ attributes={
51
+ "cwd": normalized_cwd,
52
+ "command_hash": _hash_command(command_text),
53
+ "success": success,
54
+ "exit_code": int(args.exit_code),
55
+ },
56
+ ):
57
+ collector.record_event(
58
+ "RoutingResolved",
59
+ {
60
+ "source": "terminal-hook",
61
+ "cwd": normalized_cwd,
62
+ "success": success,
63
+ "exit_code": int(args.exit_code),
64
+ },
65
+ level="INFO",
66
+ )
67
+ collector.record_metric("terminal_command_count", 1.0, unit="count")
68
+ collector.record_metric("terminal_last_exit_code", float(int(args.exit_code)), unit="code")
69
+ if not success:
70
+ collector.record_event(
71
+ "ExceptionThrown",
72
+ {
73
+ "source": "terminal-hook",
74
+ "message": "command_reported_failure",
75
+ "exit_code": int(args.exit_code),
76
+ },
77
+ level="ERROR",
78
+ )
79
+
80
+ return 0
81
+
82
+
83
+ if __name__ == "__main__":
84
+ raise SystemExit(main())
@@ -0,0 +1,152 @@
1
+ param(
2
+ [switch]$AllHosts,
3
+ [switch]$CurrentProcess,
4
+ [string]$SessionId = ''
5
+ )
6
+
7
+ Set-StrictMode -Version Latest
8
+ $ErrorActionPreference = 'Stop'
9
+
10
+ $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
11
+ $sessionIdResolved = if ([string]::IsNullOrWhiteSpace($SessionId)) {
12
+ if (-not [string]::IsNullOrWhiteSpace($env:MCP_SESSION_ID)) { $env:MCP_SESSION_ID }
13
+ elseif (-not [string]::IsNullOrWhiteSpace($env:VSCODE_TARGET_SESSION_LOG) -and $env:VSCODE_TARGET_SESSION_LOG -match '([0-9a-fA-F-]{36})') { $Matches[1] }
14
+ else { 'terminal-session' }
15
+ }
16
+ else {
17
+ $SessionId
18
+ }
19
+
20
+ $hookBlock = @"
21
+ # >>> MCPEE_TERMINAL_TELEMETRY_START >>>
22
+ `$global:MCPEE_TELEMETRY_REPO_ROOT = '$repoRoot'
23
+ `$global:MCPEE_TELEMETRY_SESSION_ID = '$sessionIdResolved'
24
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = -1
25
+ `$global:MCPEE_TELEMETRY_LAST_STAMP = ''
26
+
27
+ function global:Get-McpeeTelemetryPythonCommand {
28
+ if (Get-Command py -ErrorAction SilentlyContinue) {
29
+ return @('py', '-3')
30
+ }
31
+ if (Get-Command python -ErrorAction SilentlyContinue) {
32
+ return @('python')
33
+ }
34
+ if (Get-Command python3 -ErrorAction SilentlyContinue) {
35
+ return @('python3')
36
+ }
37
+ return @()
38
+ }
39
+
40
+ function global:Invoke-McpeeTerminalTelemetry {
41
+ try {
42
+ `$last = Get-History -Count 1 -ErrorAction SilentlyContinue
43
+ if (`$null -eq `$last) { return }
44
+
45
+ `$historyId = [int]`$last.Id
46
+ if (`$historyId -le [int]`$global:MCPEE_TELEMETRY_LAST_HISTORY_ID) { return }
47
+
48
+ `$commandText = [string]`$last.CommandLine
49
+ if ([string]::IsNullOrWhiteSpace(`$commandText)) { return }
50
+
51
+ `$commandTrim = `$commandText.Trim()
52
+ if (`$commandTrim -match 'Invoke-McpeeTerminalTelemetry|emit-terminal-command-telemetry\.py') {
53
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = `$historyId
54
+ return
55
+ }
56
+
57
+ `$stamp = ('{0}:{1}' -f `$historyId, `$commandTrim)
58
+ if (`$stamp -eq `$global:MCPEE_TELEMETRY_LAST_STAMP) {
59
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = `$historyId
60
+ return
61
+ }
62
+
63
+ `$py = Get-McpeeTelemetryPythonCommand
64
+ if (`$py.Count -eq 0) {
65
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = `$historyId
66
+ `$global:MCPEE_TELEMETRY_LAST_STAMP = `$stamp
67
+ return
68
+ }
69
+
70
+ `$scriptPath = Join-Path `$global:MCPEE_TELEMETRY_REPO_ROOT 'scripts/ops/emit-terminal-command-telemetry.py'
71
+ if (-not (Test-Path `$scriptPath)) {
72
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = `$historyId
73
+ `$global:MCPEE_TELEMETRY_LAST_STAMP = `$stamp
74
+ return
75
+ }
76
+
77
+ `$success = if (`$?) { 'true' } else { 'false' }
78
+ `$nativeExit = if (`$null -eq `$LASTEXITCODE) { 0 } else { [int]`$LASTEXITCODE }
79
+
80
+ `$pyArgs = @()
81
+ if (`$py.Count -gt 1) {
82
+ `$pyArgs = `$py[1..(`$py.Count-1)]
83
+ }
84
+
85
+ & `$py[0] @(`$pyArgs) `$scriptPath --session-id `$global:MCPEE_TELEMETRY_SESSION_ID --cwd `$PWD.Path --command `$commandTrim --success `$success --exit-code `$nativeExit *> `$null
86
+
87
+ `$global:MCPEE_TELEMETRY_LAST_HISTORY_ID = `$historyId
88
+ `$global:MCPEE_TELEMETRY_LAST_STAMP = `$stamp
89
+ }
90
+ catch {
91
+ # Hook de telemetria best-effort: nunca romper la consola.
92
+ }
93
+ }
94
+
95
+ if (-not (Test-Path Function:\global:MCPEE_ORIGINAL_PROMPT)) {
96
+ `$originalPromptBody = if (Test-Path Function:\global:prompt) { (Get-Command prompt -CommandType Function).ScriptBlock.ToString() } else { '"PS " + `$executionContext.SessionState.Path.CurrentLocation + "> "' }
97
+ Set-Item -Path Function:\global:MCPEE_ORIGINAL_PROMPT -Value ([ScriptBlock]::Create(`$originalPromptBody)) -Force
98
+ }
99
+
100
+ function global:prompt {
101
+ Invoke-McpeeTerminalTelemetry
102
+ & global:MCPEE_ORIGINAL_PROMPT
103
+ }
104
+ # <<< MCPEE_TERMINAL_TELEMETRY_END <<<
105
+ "@
106
+
107
+ function Install-InProfile {
108
+ param([string]$ProfilePath)
109
+
110
+ $dir = Split-Path $ProfilePath -Parent
111
+ if (-not (Test-Path $dir)) {
112
+ New-Item -ItemType Directory -Path $dir -Force | Out-Null
113
+ }
114
+
115
+ if (-not (Test-Path $ProfilePath)) {
116
+ New-Item -ItemType File -Path $ProfilePath -Force | Out-Null
117
+ }
118
+
119
+ $content = Get-Content -Path $ProfilePath -Raw -ErrorAction SilentlyContinue
120
+ if ($null -eq $content) { $content = '' }
121
+
122
+ if ($content -match 'MCPEE_TERMINAL_TELEMETRY_START') {
123
+ $updated = [regex]::Replace(
124
+ $content,
125
+ '(?s)# >>> MCPEE_TERMINAL_TELEMETRY_START >>>.*?# <<< MCPEE_TERMINAL_TELEMETRY_END <<<',
126
+ $hookBlock
127
+ )
128
+ Set-Content -Path $ProfilePath -Value $updated -Encoding UTF8
129
+ }
130
+ else {
131
+ if (-not [string]::IsNullOrWhiteSpace($content) -and -not $content.EndsWith("`n")) {
132
+ $content += "`r`n"
133
+ }
134
+ $content += "`r`n$hookBlock`r`n"
135
+ Set-Content -Path $ProfilePath -Value $content -Encoding UTF8
136
+ }
137
+
138
+ Write-Host "[ok] Hook instalado/actualizado en: $ProfilePath"
139
+ }
140
+
141
+ if ($CurrentProcess) {
142
+ Invoke-Expression $hookBlock
143
+ Write-Host '[ok] Hook cargado en la sesion actual.'
144
+ }
145
+
146
+ Install-InProfile -ProfilePath $PROFILE.CurrentUserCurrentHost
147
+ if ($AllHosts) {
148
+ Install-InProfile -ProfilePath $PROFILE.CurrentUserAllHosts
149
+ }
150
+
151
+ Write-Host '[ok] Telemetria global de terminal activada (best-effort).'
152
+ Write-Host '[hint] Para desinstalar usa: mcpee observe-off'
@@ -0,0 +1,98 @@
1
+ param(
2
+ [string]$SourceConnectionString = 'Server=(localdb)\MSSQLLocalDB;Database=TechRidersDev;Trusted_Connection=True;MultipleActiveResultSets=True;TrustServerCertificate=True',
3
+ [string]$TargetServer = 'sql-techriders-dev-ohbnpr4l4fihc.database.windows.net',
4
+ [string]$TargetDatabase = 'sqldb-techriders-dev',
5
+ [string]$TargetUser = 'sqladminuser'
6
+ )
7
+
8
+ $ErrorActionPreference = 'Stop'
9
+ Add-Type -AssemblyName System.Data
10
+
11
+ if ([string]::IsNullOrWhiteSpace($env:SQL_ADMIN_PASSWORD)) {
12
+ throw 'Missing SQL_ADMIN_PASSWORD environment variable.'
13
+ }
14
+
15
+ $targetConnectionString = "Server=tcp:$TargetServer,1433;Initial Catalog=$TargetDatabase;Persist Security Info=False;User ID=$TargetUser;Password=$($env:SQL_ADMIN_PASSWORD);MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
16
+
17
+ $sourceConn = New-Object System.Data.SqlClient.SqlConnection $SourceConnectionString
18
+ $targetConn = New-Object System.Data.SqlClient.SqlConnection $targetConnectionString
19
+
20
+ try {
21
+ $sourceConn.Open()
22
+ $targetConn.Open()
23
+
24
+ $tableCmd = $sourceConn.CreateCommand()
25
+ $tableCmd.CommandText = @"
26
+ SELECT s.name AS SchemaName, t.name AS TableName
27
+ FROM sys.tables t
28
+ JOIN sys.schemas s ON s.schema_id = t.schema_id
29
+ WHERE t.is_ms_shipped = 0
30
+ ORDER BY s.name, t.name;
31
+ "@
32
+
33
+ $reader = $tableCmd.ExecuteReader()
34
+ $tables = New-Object System.Collections.Generic.List[object]
35
+ while ($reader.Read()) {
36
+ $schema = $reader.GetString(0)
37
+ $table = $reader.GetString(1)
38
+ if ($table -ne '__EFMigrationsHistory') {
39
+ $tables.Add([PSCustomObject]@{ Schema = $schema; Table = $table })
40
+ }
41
+ }
42
+ $reader.Close()
43
+
44
+ if ($tables.Count -eq 0) {
45
+ throw 'No source user tables found.'
46
+ }
47
+
48
+ foreach ($t in $tables) {
49
+ $fullName = "[$($t.Schema)].[$($t.Table)]"
50
+ $disableCmd = $targetConn.CreateCommand()
51
+ $disableCmd.CommandText = "ALTER TABLE $fullName NOCHECK CONSTRAINT ALL;"
52
+ [void]$disableCmd.ExecuteNonQuery()
53
+ }
54
+
55
+ $summary = New-Object System.Collections.Generic.List[object]
56
+
57
+ foreach ($t in $tables) {
58
+ $fullName = "[$($t.Schema)].[$($t.Table)]"
59
+
60
+ $deleteCmd = $targetConn.CreateCommand()
61
+ $deleteCmd.CommandText = "DELETE FROM $fullName;"
62
+ [void]$deleteCmd.ExecuteNonQuery()
63
+
64
+ $selectCmd = $sourceConn.CreateCommand()
65
+ $selectCmd.CommandText = "SELECT * FROM $fullName;"
66
+
67
+ $adapter = New-Object System.Data.SqlClient.SqlDataAdapter $selectCmd
68
+ $dataTable = New-Object System.Data.DataTable
69
+ [void]$adapter.Fill($dataTable)
70
+
71
+ if ($dataTable.Rows.Count -gt 0) {
72
+ $bulkCopy = New-Object System.Data.SqlClient.SqlBulkCopy($targetConn, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity, $null)
73
+ $bulkCopy.DestinationTableName = $fullName
74
+ $bulkCopy.BulkCopyTimeout = 0
75
+ foreach ($col in $dataTable.Columns) {
76
+ [void]$bulkCopy.ColumnMappings.Add($col.ColumnName, $col.ColumnName)
77
+ }
78
+ $bulkCopy.WriteToServer($dataTable)
79
+ $bulkCopy.Close()
80
+ }
81
+
82
+ $summary.Add([PSCustomObject]@{ Table = $fullName; Rows = $dataTable.Rows.Count })
83
+ }
84
+
85
+ foreach ($t in $tables) {
86
+ $fullName = "[$($t.Schema)].[$($t.Table)]"
87
+ $enableCmd = $targetConn.CreateCommand()
88
+ $enableCmd.CommandText = "ALTER TABLE $fullName WITH CHECK CHECK CONSTRAINT ALL;"
89
+ [void]$enableCmd.ExecuteNonQuery()
90
+ }
91
+
92
+ $summary | Sort-Object Table | Format-Table -AutoSize | Out-String | Write-Output
93
+ Write-Output 'MIGRATION_COMPLETED'
94
+ }
95
+ finally {
96
+ if ($sourceConn.State -eq 'Open') { $sourceConn.Close() }
97
+ if ($targetConn.State -eq 'Open') { $targetConn.Close() }
98
+ }
@@ -0,0 +1,67 @@
1
+ param(
2
+ [switch]$DryRun
3
+ )
4
+
5
+ $ErrorActionPreference = 'Stop'
6
+
7
+ function Resolve-RepoRoot {
8
+ return (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
9
+ }
10
+
11
+ function Has-CodegraphIndex([string]$path) {
12
+ return (Test-Path (Join-Path $path '.codegraph'))
13
+ }
14
+
15
+ function Resolve-TargetPath {
16
+ param([string]$RepoRoot)
17
+
18
+ $envPath = [Environment]::GetEnvironmentVariable('CODEGRAPH_PROJECT_PATH')
19
+ if (-not [string]::IsNullOrWhiteSpace($envPath)) {
20
+ $resolvedEnvPath = $null
21
+ try {
22
+ $resolvedEnvPath = (Resolve-Path $envPath).Path
23
+ }
24
+ catch {
25
+ $resolvedEnvPath = $null
26
+ }
27
+
28
+ if ($resolvedEnvPath -and (Has-CodegraphIndex $resolvedEnvPath)) {
29
+ return $resolvedEnvPath
30
+ }
31
+ }
32
+
33
+ $projectCandidates = @()
34
+ $projectsRoot = Join-Path $RepoRoot 'projects'
35
+ if (Test-Path $projectsRoot) {
36
+ foreach ($projectDir in Get-ChildItem -Path $projectsRoot -Directory -ErrorAction SilentlyContinue) {
37
+ if (Has-CodegraphIndex $projectDir.FullName) {
38
+ $projectCandidates += $projectDir.FullName
39
+ }
40
+ }
41
+ }
42
+
43
+ if ($projectCandidates.Count -eq 1) {
44
+ return $projectCandidates[0]
45
+ }
46
+
47
+ if (Has-CodegraphIndex $RepoRoot) {
48
+ return $RepoRoot
49
+ }
50
+
51
+ if ($projectCandidates.Count -gt 1) {
52
+ return $projectCandidates[0]
53
+ }
54
+
55
+ return $RepoRoot
56
+ }
57
+
58
+ $repoRoot = Resolve-RepoRoot
59
+ $targetPath = Resolve-TargetPath -RepoRoot $repoRoot
60
+
61
+ if ($DryRun) {
62
+ Write-Output $targetPath
63
+ exit 0
64
+ }
65
+
66
+ & codegraph serve --mcp --path $targetPath
67
+ exit $LASTEXITCODE
@@ -0,0 +1,85 @@
1
+ param(
2
+ [switch]$DryRun
3
+ )
4
+
5
+ $ErrorActionPreference = 'Stop'
6
+
7
+ function Resolve-RepoRoot {
8
+ return (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
9
+ }
10
+
11
+ function Is-GitRepo([string]$path) {
12
+ return (Test-Path (Join-Path $path '.git'))
13
+ }
14
+
15
+ function Has-GitNexusIndex([string]$path) {
16
+ return (Test-Path (Join-Path $path '.gitnexus'))
17
+ }
18
+
19
+ function Resolve-TargetPath {
20
+ param([string]$RepoRoot)
21
+
22
+ $envPath = [Environment]::GetEnvironmentVariable('GITNEXUS_PROJECT_PATH')
23
+ if (-not [string]::IsNullOrWhiteSpace($envPath)) {
24
+ $resolvedEnvPath = $null
25
+ try {
26
+ $resolvedEnvPath = (Resolve-Path $envPath).Path
27
+ }
28
+ catch {
29
+ $resolvedEnvPath = $null
30
+ }
31
+
32
+ if ($resolvedEnvPath -and (Is-GitRepo $resolvedEnvPath)) {
33
+ return $resolvedEnvPath
34
+ }
35
+ }
36
+
37
+ $projectCandidates = @()
38
+ $indexedProjectCandidates = @()
39
+ $projectsRoot = Join-Path $RepoRoot 'projects'
40
+
41
+ if (Test-Path $projectsRoot) {
42
+ foreach ($projectDir in Get-ChildItem -Path $projectsRoot -Directory -ErrorAction SilentlyContinue) {
43
+ if (Is-GitRepo $projectDir.FullName) {
44
+ $projectCandidates += $projectDir.FullName
45
+ if (Has-GitNexusIndex $projectDir.FullName) {
46
+ $indexedProjectCandidates += $projectDir.FullName
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ if ($indexedProjectCandidates.Count -eq 1) {
53
+ return $indexedProjectCandidates[0]
54
+ }
55
+
56
+ if ((Has-GitNexusIndex $RepoRoot) -and (Is-GitRepo $RepoRoot)) {
57
+ return $RepoRoot
58
+ }
59
+
60
+ if ($indexedProjectCandidates.Count -gt 1) {
61
+ return $indexedProjectCandidates[0]
62
+ }
63
+
64
+ if ($projectCandidates.Count -eq 1) {
65
+ return $projectCandidates[0]
66
+ }
67
+
68
+ if ($projectCandidates.Count -gt 1) {
69
+ return $projectCandidates[0]
70
+ }
71
+
72
+ return $RepoRoot
73
+ }
74
+
75
+ $repoRoot = Resolve-RepoRoot
76
+ $targetPath = Resolve-TargetPath -RepoRoot $repoRoot
77
+
78
+ if ($DryRun) {
79
+ Write-Output $targetPath
80
+ exit 0
81
+ }
82
+
83
+ Set-Location $targetPath
84
+ & gitnexus mcp
85
+ exit $LASTEXITCODE
@@ -0,0 +1,53 @@
1
+ param(
2
+ [switch]$AllHosts,
3
+ [switch]$CurrentProcess
4
+ )
5
+
6
+ Set-StrictMode -Version Latest
7
+ $ErrorActionPreference = 'Stop'
8
+
9
+ function Remove-FromProfile {
10
+ param([string]$ProfilePath)
11
+
12
+ if (-not (Test-Path $ProfilePath)) {
13
+ return
14
+ }
15
+
16
+ $content = Get-Content -Path $ProfilePath -Raw -ErrorAction SilentlyContinue
17
+ if ($null -eq $content) {
18
+ return
19
+ }
20
+
21
+ if ($content -match 'MCPEE_TERMINAL_TELEMETRY_START') {
22
+ $updated = [regex]::Replace(
23
+ $content,
24
+ '(?s)\r?\n?# >>> MCPEE_TERMINAL_TELEMETRY_START >>>.*?# <<< MCPEE_TERMINAL_TELEMETRY_END <<<\r?\n?',
25
+ "`r`n"
26
+ )
27
+ Set-Content -Path $ProfilePath -Value $updated -Encoding UTF8
28
+ Write-Host "[ok] Hook eliminado de: $ProfilePath"
29
+ }
30
+ }
31
+
32
+ if ($CurrentProcess) {
33
+ Remove-Item Function:\global:prompt -ErrorAction SilentlyContinue
34
+ if (Test-Path Function:\global:MCPEE_ORIGINAL_PROMPT) {
35
+ Set-Item -Path Function:\global:prompt -Value ((Get-Command MCPEE_ORIGINAL_PROMPT -CommandType Function).ScriptBlock) -Force
36
+ Remove-Item Function:\global:MCPEE_ORIGINAL_PROMPT -ErrorAction SilentlyContinue
37
+ }
38
+
39
+ Remove-Item Function:\global:Invoke-McpeeTerminalTelemetry -ErrorAction SilentlyContinue
40
+ Remove-Item Function:\global:Get-McpeeTelemetryPythonCommand -ErrorAction SilentlyContinue
41
+ Remove-Variable MCPEE_TELEMETRY_REPO_ROOT -Scope Global -ErrorAction SilentlyContinue
42
+ Remove-Variable MCPEE_TELEMETRY_SESSION_ID -Scope Global -ErrorAction SilentlyContinue
43
+ Remove-Variable MCPEE_TELEMETRY_LAST_HISTORY_ID -Scope Global -ErrorAction SilentlyContinue
44
+ Remove-Variable MCPEE_TELEMETRY_LAST_STAMP -Scope Global -ErrorAction SilentlyContinue
45
+ Write-Host '[ok] Hook desactivado en la sesion actual.'
46
+ }
47
+
48
+ Remove-FromProfile -ProfilePath $PROFILE.CurrentUserCurrentHost
49
+ if ($AllHosts) {
50
+ Remove-FromProfile -ProfilePath $PROFILE.CurrentUserAllHosts
51
+ }
52
+
53
+ Write-Host '[ok] Telemetria global de terminal desactivada.'