sigmap 7.28.0 → 7.29.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/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/gen-context.js +200 -2
- package/llms-full.txt +4 -2
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/src/mcp/install.js +142 -0
- package/src/mcp/server.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,20 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [7.29.0] — 2026-06-23
|
|
14
|
+
|
|
15
|
+
Minor release — **v8.0 E4:** one-command, per-client MCP install so a cold user reaches a working MCP setup fast (the v8.0 <5-minute-quickstart exit gate).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **`sigmap mcp install <client>` (#385):** targeted MCP wiring for a single client — `claude`, `cursor`, `windsurf`, `vscode`, `zed`, `codex`, `gemini`, `opencode`, or portable `mcp` (`.mcp.json`). Unlike `sigmap --setup` (which wires *every* editor at once and only updates configs that already exist), this **creates** the config dir/file when absent, is idempotent (re-running reports already-registered, never duplicates), and emits the correct shape per client — `mcpServers` JSON, Zed `context_servers`, or Codex YAML. `--global` selects the user-level config for clients that have both a project and a global scope (Windsurf, OpenCode). Composed in the zero-dep `src/mcp/install.js` — no system-shell spawns, no install scripts.
|
|
19
|
+
- **`sigmap mcp list` (#385):** lists every supported MCP client and its resolved config path (`--json` for a machine-readable array).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Regenerated `llms-full.txt` so the published surface lists the new `mcp install`/`mcp list` commands.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- Hardened two `--ci --min-coverage` integration tests (#385) that were order- and environment-dependent — they hard-coded an "unreachable" 99% threshold, but once the suite generates a full `src/` context the repo's measured coverage reaches 99–100%. They now pin the threshold relative to the actual measured coverage, so the gate-fails-above-achievable property holds deterministically everywhere.
|
|
26
|
+
|
|
13
27
|
## [7.28.0] — 2026-06-23
|
|
14
28
|
|
|
15
29
|
Minor release — **v8.0 E3:** a one-shot setup doctor so a cold user reaches a useful answer fast.
|
package/README.md
CHANGED
|
@@ -91,8 +91,8 @@ Ask → Rank → Context → Validate → Judge → Learn
|
|
|
91
91
|
|
|
92
92
|
<!--SM:benchmarkBlock-->
|
|
93
93
|
```
|
|
94
|
-
Benchmark : sigmap-v7.
|
|
95
|
-
Date : 2026-06-
|
|
94
|
+
Benchmark : sigmap-v7.29-main (21 repositories, including R language)
|
|
95
|
+
Date : 2026-06-23
|
|
96
96
|
|
|
97
97
|
Hit@5 : 75.6% (baseline 13.6% — 5.6× lift)
|
|
98
98
|
Token reduction: 97.0% (across 21 repos)
|
package/gen-context.js
CHANGED
|
@@ -12528,6 +12528,152 @@ __factories["./src/mcp/handlers"] = function(module, exports) {
|
|
|
12528
12528
|
|
|
12529
12529
|
};
|
|
12530
12530
|
|
|
12531
|
+
// ── ./src/mcp/install ──
|
|
12532
|
+
__factories["./src/mcp/install"] = function(module, exports) {
|
|
12533
|
+
|
|
12534
|
+
/**
|
|
12535
|
+
* Per-client MCP install (v8.0 E4).
|
|
12536
|
+
*
|
|
12537
|
+
* `sigmap --setup` wires *every* known editor at once and only touches config
|
|
12538
|
+
* files that already exist (to avoid creating clutter for editors the user does
|
|
12539
|
+
* not use). This module is the targeted counterpart: `sigmap mcp install <client>`
|
|
12540
|
+
* picks one client, and — because the user explicitly asked for it — CREATES the
|
|
12541
|
+
* config dir/file if it is missing. Idempotent: re-running never duplicates the
|
|
12542
|
+
* entry. Zero dependencies; only `fs`/`path`/`os`.
|
|
12543
|
+
*/
|
|
12544
|
+
|
|
12545
|
+
const fs = require('fs');
|
|
12546
|
+
const path = require('path');
|
|
12547
|
+
const os = require('os');
|
|
12548
|
+
|
|
12549
|
+
// Config shapes the supported clients use.
|
|
12550
|
+
// - 'json' → { mcpServers: { sigmap: { command, args } } }
|
|
12551
|
+
// - 'zed' → { context_servers: { sigmap: { command: { path, args } } } }
|
|
12552
|
+
// - 'yaml' → Codex CLI ~/.codex/config.yaml (mcpServers block, appended)
|
|
12553
|
+
const CLIENTS = {
|
|
12554
|
+
claude: { label: 'Claude Code', format: 'json', scope: 'project', project: ['.claude', 'settings.json'] },
|
|
12555
|
+
cursor: { label: 'Cursor', format: 'json', scope: 'project', project: ['.cursor', 'mcp.json'] },
|
|
12556
|
+
windsurf: { label: 'Windsurf', format: 'json', scope: 'both',
|
|
12557
|
+
project: ['.windsurf', 'mcp.json'],
|
|
12558
|
+
global: ['.codeium', 'windsurf', 'mcp_config.json'] },
|
|
12559
|
+
vscode: { label: 'VS Code', format: 'json', scope: 'project', project: ['.vscode', 'mcp.json'] },
|
|
12560
|
+
opencode: { label: 'OpenCode', format: 'json', scope: 'both',
|
|
12561
|
+
project: ['opencode.json'],
|
|
12562
|
+
global: ['.config', 'opencode', 'config.json'] },
|
|
12563
|
+
gemini: { label: 'Gemini CLI', format: 'json', scope: 'global', global: ['.gemini', 'settings.json'] },
|
|
12564
|
+
zed: { label: 'Zed', format: 'zed', scope: 'global', global: ['.config', 'zed', 'settings.json'] },
|
|
12565
|
+
codex: { label: 'Codex CLI', format: 'yaml', scope: 'global', global: ['.codex', 'config.yaml'] },
|
|
12566
|
+
mcp: { label: 'Portable (.mcp.json)', format: 'json', scope: 'project', project: ['.mcp.json'] },
|
|
12567
|
+
};
|
|
12568
|
+
|
|
12569
|
+
/** Resolve the absolute config path for a client, honoring `global`. */
|
|
12570
|
+
function resolveTarget(spec, cwd, home, useGlobal) {
|
|
12571
|
+
const wantGlobal = useGlobal || spec.scope === 'global';
|
|
12572
|
+
if (wantGlobal && spec.global) return path.join(home, ...spec.global);
|
|
12573
|
+
if (spec.project) return path.join(cwd, ...spec.project);
|
|
12574
|
+
if (spec.global) return path.join(home, ...spec.global);
|
|
12575
|
+
return null;
|
|
12576
|
+
}
|
|
12577
|
+
|
|
12578
|
+
/** List supported clients with their resolved target paths. */
|
|
12579
|
+
function listClients(opts = {}) {
|
|
12580
|
+
const cwd = opts.cwd || process.cwd();
|
|
12581
|
+
const home = opts.home || os.homedir();
|
|
12582
|
+
return Object.keys(CLIENTS).map((key) => {
|
|
12583
|
+
const spec = CLIENTS[key];
|
|
12584
|
+
return {
|
|
12585
|
+
client: key,
|
|
12586
|
+
label: spec.label,
|
|
12587
|
+
scope: spec.scope,
|
|
12588
|
+
format: spec.format,
|
|
12589
|
+
target: resolveTarget(spec, cwd, home, false),
|
|
12590
|
+
globalTarget: spec.scope === 'both' ? resolveTarget(spec, cwd, home, true) : null,
|
|
12591
|
+
};
|
|
12592
|
+
});
|
|
12593
|
+
}
|
|
12594
|
+
|
|
12595
|
+
function serverArgs(scriptPath) {
|
|
12596
|
+
return [path.resolve(scriptPath), '--mcp'];
|
|
12597
|
+
}
|
|
12598
|
+
|
|
12599
|
+
/** Install into a JSON `mcpServers` config (create file/dir if absent). */
|
|
12600
|
+
function _installJson(filePath, scriptPath) {
|
|
12601
|
+
let settings = {};
|
|
12602
|
+
if (fs.existsSync(filePath)) {
|
|
12603
|
+
try { settings = JSON.parse(fs.readFileSync(filePath, 'utf8')) || {}; }
|
|
12604
|
+
catch (_) { settings = {}; }
|
|
12605
|
+
}
|
|
12606
|
+
if (!settings.mcpServers) settings.mcpServers = {};
|
|
12607
|
+
if (settings.mcpServers.sigmap) return 'already';
|
|
12608
|
+
settings.mcpServers.sigmap = { command: 'node', args: serverArgs(scriptPath) };
|
|
12609
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
12610
|
+
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n');
|
|
12611
|
+
return 'installed';
|
|
12612
|
+
}
|
|
12613
|
+
|
|
12614
|
+
/** Install into Zed's `context_servers` config (create file/dir if absent). */
|
|
12615
|
+
function _installZed(filePath, scriptPath) {
|
|
12616
|
+
let settings = {};
|
|
12617
|
+
if (fs.existsSync(filePath)) {
|
|
12618
|
+
try { settings = JSON.parse(fs.readFileSync(filePath, 'utf8')) || {}; }
|
|
12619
|
+
catch (_) { settings = {}; }
|
|
12620
|
+
}
|
|
12621
|
+
if (!settings.context_servers) settings.context_servers = {};
|
|
12622
|
+
if (settings.context_servers.sigmap) return 'already';
|
|
12623
|
+
settings.context_servers.sigmap = { command: { path: 'node', args: serverArgs(scriptPath) } };
|
|
12624
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
12625
|
+
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n');
|
|
12626
|
+
return 'installed';
|
|
12627
|
+
}
|
|
12628
|
+
|
|
12629
|
+
/** Install into Codex CLI YAML (append block; create file if absent). */
|
|
12630
|
+
function _installYaml(filePath, scriptPath) {
|
|
12631
|
+
let raw = '';
|
|
12632
|
+
if (fs.existsSync(filePath)) {
|
|
12633
|
+
raw = fs.readFileSync(filePath, 'utf8');
|
|
12634
|
+
if (raw.includes('sigmap')) return 'already';
|
|
12635
|
+
}
|
|
12636
|
+
const block = [
|
|
12637
|
+
'mcpServers:',
|
|
12638
|
+
' sigmap:',
|
|
12639
|
+
' command: node',
|
|
12640
|
+
' args:',
|
|
12641
|
+
` - ${path.resolve(scriptPath)}`,
|
|
12642
|
+
' - --mcp',
|
|
12643
|
+
].join('\n');
|
|
12644
|
+
const next = raw ? raw.trimEnd() + '\n\n' + block + '\n' : block + '\n';
|
|
12645
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
12646
|
+
fs.writeFileSync(filePath, next);
|
|
12647
|
+
return 'installed';
|
|
12648
|
+
}
|
|
12649
|
+
|
|
12650
|
+
/**
|
|
12651
|
+
* Install the sigmap MCP server for a single client.
|
|
12652
|
+
* @returns { client, label, path, status } where status is
|
|
12653
|
+
* 'installed' | 'already' | 'unknown'.
|
|
12654
|
+
*/
|
|
12655
|
+
function installClient(client, opts = {}) {
|
|
12656
|
+
const spec = CLIENTS[client];
|
|
12657
|
+
if (!spec) {
|
|
12658
|
+
return { client, status: 'unknown', valid: Object.keys(CLIENTS) };
|
|
12659
|
+
}
|
|
12660
|
+
const cwd = opts.cwd || process.cwd();
|
|
12661
|
+
const home = opts.home || os.homedir();
|
|
12662
|
+
const scriptPath = opts.scriptPath || path.join(cwd, 'gen-context.js');
|
|
12663
|
+
const filePath = resolveTarget(spec, cwd, home, opts.global);
|
|
12664
|
+
|
|
12665
|
+
let status;
|
|
12666
|
+
if (spec.format === 'zed') status = _installZed(filePath, scriptPath);
|
|
12667
|
+
else if (spec.format === 'yaml') status = _installYaml(filePath, scriptPath);
|
|
12668
|
+
else status = _installJson(filePath, scriptPath);
|
|
12669
|
+
|
|
12670
|
+
return { client, label: spec.label, path: filePath, status };
|
|
12671
|
+
}
|
|
12672
|
+
|
|
12673
|
+
module.exports = { CLIENTS, listClients, installClient, resolveTarget };
|
|
12674
|
+
|
|
12675
|
+
};
|
|
12676
|
+
|
|
12531
12677
|
// ── ./src/mcp/server ──
|
|
12532
12678
|
__factories["./src/mcp/server"] = function(module, exports) {
|
|
12533
12679
|
|
|
@@ -12549,7 +12695,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
12549
12695
|
|
|
12550
12696
|
const SERVER_INFO = {
|
|
12551
12697
|
name: 'sigmap',
|
|
12552
|
-
version: '7.
|
|
12698
|
+
version: '7.29.0',
|
|
12553
12699
|
description: 'SigMap MCP server — code signatures on demand',
|
|
12554
12700
|
};
|
|
12555
12701
|
|
|
@@ -16378,7 +16524,7 @@ function __tryGit(args, opts = {}) {
|
|
|
16378
16524
|
catch (_) { return ''; }
|
|
16379
16525
|
}
|
|
16380
16526
|
|
|
16381
|
-
const VERSION = '7.
|
|
16527
|
+
const VERSION = '7.29.0';
|
|
16382
16528
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
16383
16529
|
|
|
16384
16530
|
function requireSourceOrBundled(key) {
|
|
@@ -18192,6 +18338,8 @@ Usage:
|
|
|
18192
18338
|
${cmd} note List recent notes (also: note --list <N>)
|
|
18193
18339
|
${cmd} status Show repo state — branch, dirty files, index freshness, notes
|
|
18194
18340
|
${cmd} doctor Diagnose config, index, freshness, coverage, MCP wiring — with fixes (--json; exits 1 on hard failure)
|
|
18341
|
+
${cmd} mcp list List MCP clients and their config paths (--json)
|
|
18342
|
+
${cmd} mcp install <client> Wire MCP for one client (claude|cursor|windsurf|vscode|zed|codex|gemini|opencode|mcp); --global for user-level
|
|
18195
18343
|
${cmd} --init Write example config + .contextignore scaffold
|
|
18196
18344
|
${cmd} --help Show this message
|
|
18197
18345
|
${cmd} --version Show version
|
|
@@ -19616,6 +19764,56 @@ function main() {
|
|
|
19616
19764
|
process.exit(0);
|
|
19617
19765
|
}
|
|
19618
19766
|
|
|
19767
|
+
// `sigmap mcp install <client>` / `sigmap mcp list` — one-command per-client
|
|
19768
|
+
// MCP wiring (v8.0 E4). Unlike `--setup` (wires every editor, only touches
|
|
19769
|
+
// existing configs), this targets one client and creates the config if absent.
|
|
19770
|
+
if (args[0] === 'mcp') {
|
|
19771
|
+
const { listClients, installClient } = requireSourceOrBundled('./src/mcp/install');
|
|
19772
|
+
const sub = args[1];
|
|
19773
|
+
|
|
19774
|
+
if (sub === 'list') {
|
|
19775
|
+
const clients = listClients({ cwd });
|
|
19776
|
+
if (args.includes('--json')) {
|
|
19777
|
+
process.stdout.write(JSON.stringify(clients, null, 2) + '\n');
|
|
19778
|
+
process.exit(0);
|
|
19779
|
+
}
|
|
19780
|
+
console.log('Supported MCP clients:\n');
|
|
19781
|
+
for (const c of clients) {
|
|
19782
|
+
const scope = c.scope === 'both' ? 'project (or --global)' : c.scope;
|
|
19783
|
+
console.log(` ${c.client.padEnd(10)} ${c.label}`);
|
|
19784
|
+
console.log(` ${_displayPath(c.target, cwd)} [${scope}]`);
|
|
19785
|
+
}
|
|
19786
|
+
console.log('\nInstall with: sigmap mcp install <client>');
|
|
19787
|
+
process.exit(0);
|
|
19788
|
+
}
|
|
19789
|
+
|
|
19790
|
+
if (sub === 'install') {
|
|
19791
|
+
const client = args[2];
|
|
19792
|
+
if (!client || client.startsWith('--')) {
|
|
19793
|
+
console.error('[sigmap] usage: sigmap mcp install <client> (see: sigmap mcp list)');
|
|
19794
|
+
process.exit(1);
|
|
19795
|
+
}
|
|
19796
|
+
const result = installClient(client, {
|
|
19797
|
+
cwd,
|
|
19798
|
+
scriptPath,
|
|
19799
|
+
global: args.includes('--global'),
|
|
19800
|
+
});
|
|
19801
|
+
if (result.status === 'unknown') {
|
|
19802
|
+
console.error(`[sigmap] unknown client "${client}". Valid: ${result.valid.join(', ')}`);
|
|
19803
|
+
process.exit(1);
|
|
19804
|
+
}
|
|
19805
|
+
if (result.status === 'already') {
|
|
19806
|
+
console.log(`[sigmap] ${result.label}: sigmap already registered in ${_displayPath(result.path, cwd)}`);
|
|
19807
|
+
} else {
|
|
19808
|
+
console.log(`[sigmap] ${result.label}: registered MCP server in ${_displayPath(result.path, cwd)}`);
|
|
19809
|
+
}
|
|
19810
|
+
process.exit(0);
|
|
19811
|
+
}
|
|
19812
|
+
|
|
19813
|
+
console.error('[sigmap] usage: sigmap mcp install <client> | sigmap mcp list');
|
|
19814
|
+
process.exit(1);
|
|
19815
|
+
}
|
|
19816
|
+
|
|
19619
19817
|
// `sigmap doctor` — diagnose config, index, freshness, coverage, and MCP
|
|
19620
19818
|
// wiring; print an actionable fix for anything wrong. Exit 1 on a hard
|
|
19621
19819
|
// failure (no context file / invalid config) so it is usable in CI.
|
package/llms-full.txt
CHANGED
|
@@ -9,13 +9,13 @@ the files relevant to the task — cutting tokens ~97% while keeping answers
|
|
|
9
9
|
grounded. Deterministic, offline, no embeddings or vector database. Works with
|
|
10
10
|
Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
11
11
|
|
|
12
|
-
# Version: 7.
|
|
12
|
+
# Version: 7.29.0 | Benchmark: sigmap-v7.29-main (2026-06-23)
|
|
13
13
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
14
14
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## Core metrics (benchmark: sigmap-v7.
|
|
18
|
+
## Core metrics (benchmark: sigmap-v7.29-main, 2026-06-23)
|
|
19
19
|
|
|
20
20
|
| Metric | Without SigMap | With SigMap |
|
|
21
21
|
|--------|----------------|-------------|
|
|
@@ -116,6 +116,8 @@ sigmap note "<text>" Append a note to the cross-session deci
|
|
|
116
116
|
sigmap note List recent notes (also: note --list <N>)
|
|
117
117
|
sigmap status Show repo state — branch, dirty files, index freshness, notes
|
|
118
118
|
sigmap doctor Diagnose config, index, freshness, coverage, MCP wiring — with fixes (--json; exits 1 on hard failure)
|
|
119
|
+
sigmap mcp list List MCP clients and their config paths (--json)
|
|
120
|
+
sigmap mcp install <client> Wire MCP for one client (claude|cursor|windsurf|vscode|zed|codex|gemini|opencode|mcp); --global for user-level
|
|
119
121
|
sigmap --init Write example config + .contextignore scaffold
|
|
120
122
|
sigmap --help Show this message
|
|
121
123
|
sigmap --version Show version
|
package/llms.txt
CHANGED
|
@@ -9,7 +9,7 @@ the files relevant to the task — cutting tokens ~97% while keeping answers
|
|
|
9
9
|
grounded. Deterministic, offline, no embeddings or vector database. Works with
|
|
10
10
|
Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
11
11
|
|
|
12
|
-
# Version: 7.
|
|
12
|
+
# Version: 7.29.0 | Benchmark: sigmap-v7.29-main (2026-06-23)
|
|
13
13
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
14
14
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
15
15
|
|
|
@@ -21,7 +21,7 @@ Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
|
21
21
|
- No blast-radius awareness before editing a hub file — `--impact` shows every file a change touches.
|
|
22
22
|
- Pasted stack traces, CI logs, and JSON bloat the prompt — `squeeze` minimizes them and enriches the top frame from the symbol index.
|
|
23
23
|
|
|
24
|
-
## Core metrics (benchmark: sigmap-v7.
|
|
24
|
+
## Core metrics (benchmark: sigmap-v7.29-main, 2026-06-23)
|
|
25
25
|
|
|
26
26
|
- hit@5 retrieval: 75.6% vs 13.6% random baseline (5.6× lift)
|
|
27
27
|
- Token reduction: 97.0% average across benchmark repos
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.29.0",
|
|
4
4
|
"description": "97% token reduction for AI coding. Extracts function & class signatures with TF-IDF ranking to feed only the right files to Claude, Cursor, Copilot, Aider, Windsurf, local LLMs & MCP. Zero dependencies, runs offline via npx.",
|
|
5
5
|
"main": "packages/core/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Per-client MCP install (v8.0 E4).
|
|
5
|
+
*
|
|
6
|
+
* `sigmap --setup` wires *every* known editor at once and only touches config
|
|
7
|
+
* files that already exist (to avoid creating clutter for editors the user does
|
|
8
|
+
* not use). This module is the targeted counterpart: `sigmap mcp install <client>`
|
|
9
|
+
* picks one client, and — because the user explicitly asked for it — CREATES the
|
|
10
|
+
* config dir/file if it is missing. Idempotent: re-running never duplicates the
|
|
11
|
+
* entry. Zero dependencies; only `fs`/`path`/`os`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
|
|
18
|
+
// Config shapes the supported clients use.
|
|
19
|
+
// - 'json' → { mcpServers: { sigmap: { command, args } } }
|
|
20
|
+
// - 'zed' → { context_servers: { sigmap: { command: { path, args } } } }
|
|
21
|
+
// - 'yaml' → Codex CLI ~/.codex/config.yaml (mcpServers block, appended)
|
|
22
|
+
const CLIENTS = {
|
|
23
|
+
claude: { label: 'Claude Code', format: 'json', scope: 'project', project: ['.claude', 'settings.json'] },
|
|
24
|
+
cursor: { label: 'Cursor', format: 'json', scope: 'project', project: ['.cursor', 'mcp.json'] },
|
|
25
|
+
windsurf: { label: 'Windsurf', format: 'json', scope: 'both',
|
|
26
|
+
project: ['.windsurf', 'mcp.json'],
|
|
27
|
+
global: ['.codeium', 'windsurf', 'mcp_config.json'] },
|
|
28
|
+
vscode: { label: 'VS Code', format: 'json', scope: 'project', project: ['.vscode', 'mcp.json'] },
|
|
29
|
+
opencode: { label: 'OpenCode', format: 'json', scope: 'both',
|
|
30
|
+
project: ['opencode.json'],
|
|
31
|
+
global: ['.config', 'opencode', 'config.json'] },
|
|
32
|
+
gemini: { label: 'Gemini CLI', format: 'json', scope: 'global', global: ['.gemini', 'settings.json'] },
|
|
33
|
+
zed: { label: 'Zed', format: 'zed', scope: 'global', global: ['.config', 'zed', 'settings.json'] },
|
|
34
|
+
codex: { label: 'Codex CLI', format: 'yaml', scope: 'global', global: ['.codex', 'config.yaml'] },
|
|
35
|
+
mcp: { label: 'Portable (.mcp.json)', format: 'json', scope: 'project', project: ['.mcp.json'] },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Resolve the absolute config path for a client, honoring `global`. */
|
|
39
|
+
function resolveTarget(spec, cwd, home, useGlobal) {
|
|
40
|
+
const wantGlobal = useGlobal || spec.scope === 'global';
|
|
41
|
+
if (wantGlobal && spec.global) return path.join(home, ...spec.global);
|
|
42
|
+
if (spec.project) return path.join(cwd, ...spec.project);
|
|
43
|
+
if (spec.global) return path.join(home, ...spec.global);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** List supported clients with their resolved target paths. */
|
|
48
|
+
function listClients(opts = {}) {
|
|
49
|
+
const cwd = opts.cwd || process.cwd();
|
|
50
|
+
const home = opts.home || os.homedir();
|
|
51
|
+
return Object.keys(CLIENTS).map((key) => {
|
|
52
|
+
const spec = CLIENTS[key];
|
|
53
|
+
return {
|
|
54
|
+
client: key,
|
|
55
|
+
label: spec.label,
|
|
56
|
+
scope: spec.scope,
|
|
57
|
+
format: spec.format,
|
|
58
|
+
target: resolveTarget(spec, cwd, home, false),
|
|
59
|
+
globalTarget: spec.scope === 'both' ? resolveTarget(spec, cwd, home, true) : null,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function serverArgs(scriptPath) {
|
|
65
|
+
return [path.resolve(scriptPath), '--mcp'];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Install into a JSON `mcpServers` config (create file/dir if absent). */
|
|
69
|
+
function _installJson(filePath, scriptPath) {
|
|
70
|
+
let settings = {};
|
|
71
|
+
if (fs.existsSync(filePath)) {
|
|
72
|
+
try { settings = JSON.parse(fs.readFileSync(filePath, 'utf8')) || {}; }
|
|
73
|
+
catch (_) { settings = {}; }
|
|
74
|
+
}
|
|
75
|
+
if (!settings.mcpServers) settings.mcpServers = {};
|
|
76
|
+
if (settings.mcpServers.sigmap) return 'already';
|
|
77
|
+
settings.mcpServers.sigmap = { command: 'node', args: serverArgs(scriptPath) };
|
|
78
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
79
|
+
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n');
|
|
80
|
+
return 'installed';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Install into Zed's `context_servers` config (create file/dir if absent). */
|
|
84
|
+
function _installZed(filePath, scriptPath) {
|
|
85
|
+
let settings = {};
|
|
86
|
+
if (fs.existsSync(filePath)) {
|
|
87
|
+
try { settings = JSON.parse(fs.readFileSync(filePath, 'utf8')) || {}; }
|
|
88
|
+
catch (_) { settings = {}; }
|
|
89
|
+
}
|
|
90
|
+
if (!settings.context_servers) settings.context_servers = {};
|
|
91
|
+
if (settings.context_servers.sigmap) return 'already';
|
|
92
|
+
settings.context_servers.sigmap = { command: { path: 'node', args: serverArgs(scriptPath) } };
|
|
93
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
94
|
+
fs.writeFileSync(filePath, JSON.stringify(settings, null, 2) + '\n');
|
|
95
|
+
return 'installed';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Install into Codex CLI YAML (append block; create file if absent). */
|
|
99
|
+
function _installYaml(filePath, scriptPath) {
|
|
100
|
+
let raw = '';
|
|
101
|
+
if (fs.existsSync(filePath)) {
|
|
102
|
+
raw = fs.readFileSync(filePath, 'utf8');
|
|
103
|
+
if (raw.includes('sigmap')) return 'already';
|
|
104
|
+
}
|
|
105
|
+
const block = [
|
|
106
|
+
'mcpServers:',
|
|
107
|
+
' sigmap:',
|
|
108
|
+
' command: node',
|
|
109
|
+
' args:',
|
|
110
|
+
` - ${path.resolve(scriptPath)}`,
|
|
111
|
+
' - --mcp',
|
|
112
|
+
].join('\n');
|
|
113
|
+
const next = raw ? raw.trimEnd() + '\n\n' + block + '\n' : block + '\n';
|
|
114
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
115
|
+
fs.writeFileSync(filePath, next);
|
|
116
|
+
return 'installed';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Install the sigmap MCP server for a single client.
|
|
121
|
+
* @returns { client, label, path, status } where status is
|
|
122
|
+
* 'installed' | 'already' | 'unknown'.
|
|
123
|
+
*/
|
|
124
|
+
function installClient(client, opts = {}) {
|
|
125
|
+
const spec = CLIENTS[client];
|
|
126
|
+
if (!spec) {
|
|
127
|
+
return { client, status: 'unknown', valid: Object.keys(CLIENTS) };
|
|
128
|
+
}
|
|
129
|
+
const cwd = opts.cwd || process.cwd();
|
|
130
|
+
const home = opts.home || os.homedir();
|
|
131
|
+
const scriptPath = opts.scriptPath || path.join(cwd, 'gen-context.js');
|
|
132
|
+
const filePath = resolveTarget(spec, cwd, home, opts.global);
|
|
133
|
+
|
|
134
|
+
let status;
|
|
135
|
+
if (spec.format === 'zed') status = _installZed(filePath, scriptPath);
|
|
136
|
+
else if (spec.format === 'yaml') status = _installYaml(filePath, scriptPath);
|
|
137
|
+
else status = _installJson(filePath, scriptPath);
|
|
138
|
+
|
|
139
|
+
return { client, label: spec.label, path: filePath, status };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = { CLIENTS, listClients, installClient, resolveTarget };
|
package/src/mcp/server.js
CHANGED