@harness-nexus/cli 0.1.0-alpha.1

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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/config.d.ts +24 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +38 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/daemon/acp/adapters.d.ts +7 -0
  8. package/dist/daemon/acp/adapters.d.ts.map +1 -0
  9. package/dist/daemon/acp/adapters.js +34 -0
  10. package/dist/daemon/acp/adapters.js.map +1 -0
  11. package/dist/daemon/acp/agent-connection.d.ts +45 -0
  12. package/dist/daemon/acp/agent-connection.d.ts.map +1 -0
  13. package/dist/daemon/acp/agent-connection.js +158 -0
  14. package/dist/daemon/acp/agent-connection.js.map +1 -0
  15. package/dist/daemon/chat.d.ts +22 -0
  16. package/dist/daemon/chat.d.ts.map +1 -0
  17. package/dist/daemon/chat.js +280 -0
  18. package/dist/daemon/chat.js.map +1 -0
  19. package/dist/daemon/client.d.ts +23 -0
  20. package/dist/daemon/client.d.ts.map +1 -0
  21. package/dist/daemon/client.js +117 -0
  22. package/dist/daemon/client.js.map +1 -0
  23. package/dist/daemon/jobs.d.ts +19 -0
  24. package/dist/daemon/jobs.d.ts.map +1 -0
  25. package/dist/daemon/jobs.js +65 -0
  26. package/dist/daemon/jobs.js.map +1 -0
  27. package/dist/errors.d.ts +11 -0
  28. package/dist/errors.d.ts.map +1 -0
  29. package/dist/errors.js +11 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +481 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/install/adapter-factory.d.ts +24 -0
  36. package/dist/install/adapter-factory.d.ts.map +1 -0
  37. package/dist/install/adapter-factory.js +80 -0
  38. package/dist/install/adapter-factory.js.map +1 -0
  39. package/dist/install/adapters/codex.d.ts +16 -0
  40. package/dist/install/adapters/codex.d.ts.map +1 -0
  41. package/dist/install/adapters/codex.js +172 -0
  42. package/dist/install/adapters/codex.js.map +1 -0
  43. package/dist/install/adapters/deepseek.d.ts +26 -0
  44. package/dist/install/adapters/deepseek.d.ts.map +1 -0
  45. package/dist/install/adapters/deepseek.js +246 -0
  46. package/dist/install/adapters/deepseek.js.map +1 -0
  47. package/dist/install/adapters/hermes.d.ts +16 -0
  48. package/dist/install/adapters/hermes.d.ts.map +1 -0
  49. package/dist/install/adapters/hermes.js +267 -0
  50. package/dist/install/adapters/hermes.js.map +1 -0
  51. package/dist/install/adapters/stub.d.ts +2 -0
  52. package/dist/install/adapters/stub.d.ts.map +1 -0
  53. package/dist/install/adapters/stub.js +22 -0
  54. package/dist/install/adapters/stub.js.map +1 -0
  55. package/dist/install/install-state.d.ts +31 -0
  56. package/dist/install/install-state.d.ts.map +1 -0
  57. package/dist/install/install-state.js +29 -0
  58. package/dist/install/install-state.js.map +1 -0
  59. package/dist/install/installer.d.ts +16 -0
  60. package/dist/install/installer.d.ts.map +1 -0
  61. package/dist/install/installer.js +96 -0
  62. package/dist/install/installer.js.map +1 -0
  63. package/dist/install/planner.d.ts +26 -0
  64. package/dist/install/planner.d.ts.map +1 -0
  65. package/dist/install/planner.js +25 -0
  66. package/dist/install/planner.js.map +1 -0
  67. package/dist/install/registry.d.ts +21 -0
  68. package/dist/install/registry.d.ts.map +1 -0
  69. package/dist/install/registry.js +31 -0
  70. package/dist/install/registry.js.map +1 -0
  71. package/dist/install/resolver.d.ts +15 -0
  72. package/dist/install/resolver.d.ts.map +1 -0
  73. package/dist/install/resolver.js +57 -0
  74. package/dist/install/resolver.js.map +1 -0
  75. package/dist/install/types.d.ts +93 -0
  76. package/dist/install/types.d.ts.map +1 -0
  77. package/dist/install/types.js +2 -0
  78. package/dist/install/types.js.map +1 -0
  79. package/dist/install/uninstaller.d.ts +29 -0
  80. package/dist/install/uninstaller.d.ts.map +1 -0
  81. package/dist/install/uninstaller.js +107 -0
  82. package/dist/install/uninstaller.js.map +1 -0
  83. package/dist/inventory/common.d.ts +86 -0
  84. package/dist/inventory/common.d.ts.map +1 -0
  85. package/dist/inventory/common.js +137 -0
  86. package/dist/inventory/common.js.map +1 -0
  87. package/dist/inventory/scan.d.ts +23 -0
  88. package/dist/inventory/scan.d.ts.map +1 -0
  89. package/dist/inventory/scan.js +117 -0
  90. package/dist/inventory/scan.js.map +1 -0
  91. package/dist/inventory/scanners/claude-code.d.ts +3 -0
  92. package/dist/inventory/scanners/claude-code.d.ts.map +1 -0
  93. package/dist/inventory/scanners/claude-code.js +191 -0
  94. package/dist/inventory/scanners/claude-code.js.map +1 -0
  95. package/dist/inventory/scanners/codex.d.ts +14 -0
  96. package/dist/inventory/scanners/codex.d.ts.map +1 -0
  97. package/dist/inventory/scanners/codex.js +201 -0
  98. package/dist/inventory/scanners/codex.js.map +1 -0
  99. package/dist/inventory/scanners/deepseek.d.ts +9 -0
  100. package/dist/inventory/scanners/deepseek.d.ts.map +1 -0
  101. package/dist/inventory/scanners/deepseek.js +200 -0
  102. package/dist/inventory/scanners/deepseek.js.map +1 -0
  103. package/dist/inventory/scanners/hermes.d.ts +3 -0
  104. package/dist/inventory/scanners/hermes.d.ts.map +1 -0
  105. package/dist/inventory/scanners/hermes.js +194 -0
  106. package/dist/inventory/scanners/hermes.js.map +1 -0
  107. package/dist/inventory/types.d.ts +33 -0
  108. package/dist/inventory/types.d.ts.map +1 -0
  109. package/dist/inventory/types.js +2 -0
  110. package/dist/inventory/types.js.map +1 -0
  111. package/dist/mcp/serve.d.ts +8 -0
  112. package/dist/mcp/serve.d.ts.map +1 -0
  113. package/dist/mcp/serve.js +118 -0
  114. package/dist/mcp/serve.js.map +1 -0
  115. package/package.json +50 -0
@@ -0,0 +1,200 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { MAX_ITEM_BYTES, isPlatformMcpName, mcpMeta, previewOf, readTextBounded, skillDirFiles, summarize, } from '../common.js';
4
+ /**
5
+ * DeepSeek Harness (dsh) scanner (Phase 8 T1). Ground truth mirrors the T1
6
+ * adapter:
7
+ * skills → ~/.dsh/skills/<name>/SKILL.md (+ bundle files)
8
+ * commands → flat ~/.dsh/skills/<name>.md (the /name invocation surface)
9
+ * mcp → `- insert:` rows mounting '@deepseek-ai/dsh-mcp-client' in the
10
+ * home ~/.dsh/cordis.patch.yml (applies to every profile)
11
+ * Rules (persona is a config row), sub-agents (programmatic providers) and
12
+ * hooks (opt-in bridge packages) have no declarative home shape — not scanned.
13
+ *
14
+ * The patch parse is tolerant text surgery over the README field spellings,
15
+ * not a YAML parser — same tradeoff as the Codex TOML parser.
16
+ */
17
+ const MCP_BRIDGE = '@deepseek-ai/dsh-mcp-client';
18
+ /**
19
+ * Extract dsh-mcp-client mount rows from a cordis patch document, keyed by
20
+ * `serverName` (the user-meaningful server name; tools surface as
21
+ * `mcp__<serverName>__<tool>`).
22
+ */
23
+ export function parseDeepseekMcpServers(patch) {
24
+ const out = {};
25
+ // Segment into items at every `- key:` list line; MCP mounts are the items
26
+ // whose `name` key is the bridge package.
27
+ const items = [];
28
+ let current = null;
29
+ for (const line of patch.split('\n')) {
30
+ if (/^\s*-\s+\w+:/.test(line)) {
31
+ current = [];
32
+ items.push(current);
33
+ }
34
+ if (current !== null && !/^\s*#/.test(line))
35
+ current.push(line);
36
+ }
37
+ for (const item of items) {
38
+ const text = item.join('\n');
39
+ const name = /(?:^|\n)\s*(?:-\s+)?name:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
40
+ if (name !== MCP_BRIDGE)
41
+ continue;
42
+ const serverName = /serverName:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
43
+ if (serverName === undefined || serverName === '')
44
+ continue;
45
+ const entry = {};
46
+ const command = /command:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
47
+ if (command !== undefined)
48
+ entry.command = command;
49
+ const url = /url:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
50
+ if (url !== undefined)
51
+ entry.url = url;
52
+ const argsLine = /args:\s*\[(.*)\]/.exec(text)?.[1];
53
+ if (argsLine !== undefined) {
54
+ const args = [...argsLine.matchAll(/'([^']*)'|"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1] ?? m[2].replace(/\\"/g, '"'));
55
+ if (args.length > 0)
56
+ entry.args = args;
57
+ }
58
+ out[serverName] = entry;
59
+ }
60
+ return out;
61
+ }
62
+ function readPatch(home) {
63
+ try {
64
+ return fs.readFileSync(path.join(home, 'cordis.patch.yml'), 'utf8');
65
+ }
66
+ catch {
67
+ return '';
68
+ }
69
+ }
70
+ export const deepseekScanner = {
71
+ target: 'deepseek',
72
+ homeOf: (homeDir) => path.join(homeDir, '.dsh'),
73
+ discover(home) {
74
+ if (!fs.existsSync(home))
75
+ return null;
76
+ const items = [];
77
+ const skillsDir = path.join(home, 'skills');
78
+ if (fs.existsSync(skillsDir)) {
79
+ for (const entry of fs
80
+ .readdirSync(skillsDir, { withFileTypes: true })
81
+ .sort((a, b) => a.name.localeCompare(b.name))) {
82
+ // Bundles (<name>/SKILL.md) are skills; flat <name>.md files are the
83
+ // /name command surface — the split our adapter emits, preserved on
84
+ // the round trip.
85
+ if (entry.isDirectory()) {
86
+ const dir = path.join(skillsDir, entry.name);
87
+ const files = skillDirFiles(dir);
88
+ const skillMd = readTextBounded(path.join(dir, 'SKILL.md'));
89
+ if (!skillMd.ok) {
90
+ items.push({
91
+ kind: 'skill',
92
+ name: entry.name,
93
+ absPath: dir,
94
+ relPath: `skills/${entry.name}`,
95
+ importable: false,
96
+ note: files.length === 0 ? 'empty' : `SKILL.md ${skillMd.error}`,
97
+ });
98
+ continue;
99
+ }
100
+ const totalBytes = files.reduce((sum, f) => sum + fs.statSync(path.join(dir, f)).size, 0);
101
+ items.push({
102
+ kind: 'skill',
103
+ name: entry.name,
104
+ absPath: dir,
105
+ relPath: `skills/${entry.name}`,
106
+ importable: totalBytes <= MAX_ITEM_BYTES,
107
+ ...(totalBytes > MAX_ITEM_BYTES ? { note: 'too-large' } : {}),
108
+ summary: summarize(skillMd.content),
109
+ preview: previewOf(skillMd.content),
110
+ meta: { multi: files.length > 1 },
111
+ });
112
+ }
113
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
114
+ const name = entry.name.slice(0, -3);
115
+ const abs = path.join(skillsDir, entry.name);
116
+ const text = readTextBounded(abs);
117
+ items.push({
118
+ kind: 'command',
119
+ name,
120
+ absPath: abs,
121
+ relPath: `skills/${entry.name}`,
122
+ importable: text.ok,
123
+ ...(text.ok ? { summary: summarize(text.content) } : { note: text.error }),
124
+ ...(text.ok ? { preview: previewOf(text.content) } : {}),
125
+ });
126
+ }
127
+ }
128
+ }
129
+ for (const [serverName, entry] of Object.entries(parseDeepseekMcpServers(readPatch(home)))) {
130
+ items.push({
131
+ kind: 'mcp',
132
+ name: serverName,
133
+ absPath: path.join(home, 'cordis.patch.yml'),
134
+ relPath: 'cordis.patch.yml#insert',
135
+ importable: Boolean(entry.command ?? entry.url),
136
+ ...((entry.command ?? entry.url) ? {} : { note: 'unsupported shape' }),
137
+ meta: mcpMeta(entry),
138
+ ...(isPlatformMcpName(serverName) ? { platform: true } : {}),
139
+ });
140
+ }
141
+ return items;
142
+ },
143
+ platformMarkers(home) {
144
+ return Object.keys(parseDeepseekMcpServers(readPatch(home))).filter(isPlatformMcpName);
145
+ },
146
+ async collect(home, item) {
147
+ if (item.kind === 'skill') {
148
+ const files = {};
149
+ for (const rel of skillDirFiles(item.absPath)) {
150
+ const text = readTextBounded(path.join(item.absPath, rel));
151
+ if (!text.ok)
152
+ return { kind: 'skill', name: item.name, ok: false, error: `${rel}: ${text.error}` };
153
+ files[rel] = text.content;
154
+ }
155
+ if (!('SKILL.md' in files)) {
156
+ return { kind: 'skill', name: item.name, ok: false, error: 'SKILL.md missing' };
157
+ }
158
+ return { kind: 'skill', name: item.name, ok: true, artifact: { kind: 'skill', files } };
159
+ }
160
+ if (item.kind === 'command') {
161
+ const text = readTextBounded(item.absPath);
162
+ if (!text.ok)
163
+ return { kind: 'command', name: item.name, ok: false, error: text.error };
164
+ return {
165
+ kind: 'command',
166
+ name: item.name,
167
+ ok: true,
168
+ artifact: { kind: 'command', content: text.content },
169
+ };
170
+ }
171
+ const entry = parseDeepseekMcpServers(readPatch(home))[item.name];
172
+ if (!entry)
173
+ return { kind: 'mcp', name: item.name, ok: false, error: 'entry missing' };
174
+ if (entry.command) {
175
+ return {
176
+ kind: 'mcp',
177
+ name: item.name,
178
+ ok: true,
179
+ artifact: {
180
+ kind: 'mcp',
181
+ transport: {
182
+ type: 'stdio',
183
+ command: entry.command,
184
+ ...(entry.args ? { args: entry.args } : {}),
185
+ },
186
+ },
187
+ };
188
+ }
189
+ if (entry.url) {
190
+ return {
191
+ kind: 'mcp',
192
+ name: item.name,
193
+ ok: true,
194
+ artifact: { kind: 'mcp', transport: { type: 'streamable-http', url: entry.url } },
195
+ };
196
+ }
197
+ return { kind: 'mcp', name: item.name, ok: false, error: 'unsupported shape' };
198
+ },
199
+ };
200
+ //# sourceMappingURL=deepseek.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../../src/inventory/scanners/deepseek.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { TargetScanner } from '../types.js';
2
+ export declare const hermesScanner: TargetScanner;
3
+ //# sourceMappingURL=hermes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../../src/inventory/scanners/hermes.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,aAAa,CAAC;AA8D9D,eAAO,MAAM,aAAa,EAAE,aA6I3B,CAAC"}
@@ -0,0 +1,194 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import yaml from 'js-yaml';
4
+ import { MAX_ITEM_BYTES, isPlatformMcpName, mcpMeta, previewOf, readTextBounded, redactSecretMap, skillDirFiles, summarize, } from '../common.js';
5
+ /**
6
+ * Hermes scanner (Phase 8 C3). Ground truth mirrors the 3.4 adapter:
7
+ * skills → ~/.hermes/plugins/<slug>/skills/<name>/SKILL.md — BOTH ours
8
+ * (plugin.yaml author 'Harness Nexus') and third-party plugins
9
+ * mcp → `mcp_servers:` map in ~/.hermes/config.yaml (YAML)
10
+ * rules → ~/.hermes/AGENTS.md (Hermes auto-loads it; the adapter writes it)
11
+ * sub_agents/hooks have no file format — not scanned.
12
+ */
13
+ /** Read config.yaml's mcp_servers map, tolerating absence/garbage. */
14
+ function parseHermesMcpServers(home) {
15
+ try {
16
+ const parsed = yaml.load(fs.readFileSync(path.join(home, 'config.yaml'), 'utf8'));
17
+ return parsed?.mcp_servers ?? {};
18
+ }
19
+ catch {
20
+ return {};
21
+ }
22
+ }
23
+ /** True iff the plugin bundle is ours (plugin.yaml author). */
24
+ function isHarnessPlugin(pluginDir) {
25
+ try {
26
+ const manifest = yaml.load(fs.readFileSync(path.join(pluginDir, 'plugin.yaml'), 'utf8'));
27
+ return manifest?.author === 'Harness Nexus';
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ function scanSkillDir(dir, relPath, platform) {
34
+ const files = skillDirFiles(dir);
35
+ const skillMd = readTextBounded(path.join(dir, 'SKILL.md'));
36
+ if (!skillMd.ok) {
37
+ return {
38
+ error: files.length === 0 ? 'empty' : `SKILL.md ${skillMd.error}`,
39
+ };
40
+ }
41
+ const totalBytes = files.reduce((sum, f) => sum + fs.statSync(path.join(dir, f)).size, 0);
42
+ return {
43
+ kind: 'skill',
44
+ name: path.basename(dir),
45
+ absPath: dir,
46
+ relPath,
47
+ importable: totalBytes <= MAX_ITEM_BYTES,
48
+ ...(totalBytes > MAX_ITEM_BYTES ? { note: 'too-large' } : {}),
49
+ summary: summarize(skillMd.content) ?? '(no description)',
50
+ preview: previewOf(skillMd.content) ?? '',
51
+ meta: { multi: files.length > 1 },
52
+ ...(platform ? { platform: true } : {}),
53
+ };
54
+ }
55
+ export const hermesScanner = {
56
+ target: 'hermes',
57
+ homeOf: (homeDir) => path.join(homeDir, '.hermes'),
58
+ discover(home) {
59
+ if (!fs.existsSync(home))
60
+ return null;
61
+ const items = [];
62
+ const pluginsDir = path.join(home, 'plugins');
63
+ if (fs.existsSync(pluginsDir)) {
64
+ for (const entry of fs
65
+ .readdirSync(pluginsDir, { withFileTypes: true })
66
+ .sort((a, b) => a.name.localeCompare(b.name))) {
67
+ if (!entry.isDirectory())
68
+ continue;
69
+ const pluginDir = path.join(pluginsDir, entry.name);
70
+ const ours = isHarnessPlugin(pluginDir);
71
+ const skillsDir = path.join(pluginDir, 'skills');
72
+ if (!fs.existsSync(skillsDir))
73
+ continue;
74
+ for (const skill of fs
75
+ .readdirSync(skillsDir, { withFileTypes: true })
76
+ .sort((a, b) => a.name.localeCompare(b.name))) {
77
+ if (!skill.isDirectory())
78
+ continue;
79
+ const found = scanSkillDir(path.join(skillsDir, skill.name), `plugins/${entry.name}/skills/${skill.name}`, ours);
80
+ if ('error' in found) {
81
+ items.push({
82
+ kind: 'skill',
83
+ name: skill.name,
84
+ absPath: path.join(skillsDir, skill.name),
85
+ relPath: `plugins/${entry.name}/skills/${skill.name}`,
86
+ importable: false,
87
+ note: found.error,
88
+ });
89
+ }
90
+ else {
91
+ items.push(found);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ for (const [key, entry] of Object.entries(parseHermesMcpServers(home))) {
97
+ if (!entry || typeof entry !== 'object')
98
+ continue;
99
+ items.push({
100
+ kind: 'mcp',
101
+ name: key,
102
+ absPath: path.join(home, 'config.yaml'),
103
+ relPath: 'config.yaml#mcp_servers',
104
+ importable: Boolean(entry.command ?? entry.url),
105
+ ...((entry.command ?? entry.url) ? {} : { note: 'unsupported shape' }),
106
+ meta: mcpMeta(entry),
107
+ ...(isPlatformMcpName(key) ? { platform: true } : {}),
108
+ });
109
+ }
110
+ const agentsMd = path.join(home, 'AGENTS.md');
111
+ if (fs.existsSync(agentsMd)) {
112
+ const text = readTextBounded(agentsMd);
113
+ items.push({
114
+ kind: 'rule',
115
+ name: 'AGENTS',
116
+ absPath: agentsMd,
117
+ relPath: 'AGENTS.md',
118
+ importable: text.ok,
119
+ ...(text.ok
120
+ ? {
121
+ summary: summarize(text.content) ?? '(empty)',
122
+ preview: previewOf(text.content) ?? '',
123
+ }
124
+ : { note: text.error }),
125
+ });
126
+ }
127
+ return items;
128
+ },
129
+ platformMarkers(home) {
130
+ return Object.keys(parseHermesMcpServers(home)).filter(isPlatformMcpName);
131
+ },
132
+ async collect(home, item) {
133
+ if (item.kind === 'skill') {
134
+ const files = {};
135
+ for (const rel of skillDirFiles(item.absPath)) {
136
+ const text = readTextBounded(path.join(item.absPath, rel));
137
+ if (!text.ok)
138
+ return { kind: 'skill', name: item.name, ok: false, error: `${rel}: ${text.error}` };
139
+ files[rel] = text.content;
140
+ }
141
+ if (!('SKILL.md' in files)) {
142
+ return { kind: 'skill', name: item.name, ok: false, error: 'SKILL.md missing' };
143
+ }
144
+ return { kind: 'skill', name: item.name, ok: true, artifact: { kind: 'skill', files } };
145
+ }
146
+ if (item.kind === 'rule') {
147
+ const text = readTextBounded(item.absPath);
148
+ if (!text.ok)
149
+ return { kind: 'rule', name: item.name, ok: false, error: text.error };
150
+ return {
151
+ kind: 'rule',
152
+ name: item.name,
153
+ ok: true,
154
+ artifact: { kind: 'rule', content: text.content },
155
+ };
156
+ }
157
+ const entry = parseHermesMcpServers(home)[item.name];
158
+ if (!entry)
159
+ return { kind: 'mcp', name: item.name, ok: false, error: 'entry missing' };
160
+ if (entry.command) {
161
+ return {
162
+ kind: 'mcp',
163
+ name: item.name,
164
+ ok: true,
165
+ artifact: {
166
+ kind: 'mcp',
167
+ transport: {
168
+ type: 'stdio',
169
+ command: entry.command,
170
+ ...(entry.args ? { args: entry.args } : {}),
171
+ ...(entry.env ? { env: redactSecretMap(entry.env) } : {}),
172
+ },
173
+ },
174
+ };
175
+ }
176
+ if (entry.url) {
177
+ return {
178
+ kind: 'mcp',
179
+ name: item.name,
180
+ ok: true,
181
+ artifact: {
182
+ kind: 'mcp',
183
+ transport: {
184
+ type: entry.type === 'sse' ? 'sse' : 'streamable-http',
185
+ url: entry.url,
186
+ ...(entry.headers ? { headers: redactSecretMap(entry.headers) } : {}),
187
+ },
188
+ },
189
+ };
190
+ }
191
+ return { kind: 'mcp', name: item.name, ok: false, error: 'unsupported shape' };
192
+ },
193
+ };
194
+ //# sourceMappingURL=hermes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hermes.js","sourceRoot":"","sources":["../../../src/inventory/scanners/hermes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,GAEV,MAAM,cAAc,CAAC;AAGtB;;;;;;;GAOG;AAEH,sEAAsE;AACtE,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAExE,CAAC;QACT,OAAO,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,SAAS,eAAe,CAAC,SAAiB;IACxC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAE/E,CAAC;QACT,OAAO,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACnB,GAAW,EACX,OAAe,EACf,QAAiB;IAEjB,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,KAAK,EAAE;SAClE,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1F,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxB,OAAO,EAAE,GAAG;QACZ,OAAO;QACP,UAAU,EAAE,UAAU,IAAI,cAAc;QACxC,GAAG,CAAC,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,kBAAkB;QACzD,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;QACzC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;IAElD,QAAQ,CAAC,IAAI;QACX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,KAAK,GAAqB,EAAE,CAAC;QAEnC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,EAAE;iBACnB,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAChD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;oBAAE,SAAS;gBACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;gBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,SAAS;gBACxC,KAAK,MAAM,KAAK,IAAI,EAAE;qBACnB,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;qBAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAChD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;wBAAE,SAAS;oBACnC,MAAM,KAAK,GAAG,YAAY,CACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAChC,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,IAAI,EAAE,EAC5C,IAAI,CACL,CAAC;oBACF,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;wBACrB,KAAK,CAAC,IAAI,CAAC;4BACT,IAAI,EAAE,OAAO;4BACb,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC;4BACzC,OAAO,EAAE,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,IAAI,EAAE;4BACrD,UAAU,EAAE,KAAK;4BACjB,IAAI,EAAE,KAAK,CAAC,KAAK;yBAClB,CAAC,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACN,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACpB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAS;YAClD,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;gBACvC,OAAO,EAAE,yBAAyB;gBAClC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC;gBAC/C,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;gBACtE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;gBACpB,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,QAAQ;gBACjB,OAAO,EAAE,WAAW;gBACpB,UAAU,EAAE,IAAI,CAAC,EAAE;gBACnB,GAAG,CAAC,IAAI,CAAC,EAAE;oBACT,CAAC,CAAC;wBACE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS;wBAC7C,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;qBACvC;oBACH,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe,CAAC,IAAI;QAClB,OAAO,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI;QACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAA2B,EAAE,CAAC;YACzC,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC3D,IAAI,CAAC,IAAI,CAAC,EAAE;oBACV,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBACvF,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;YAClF,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1F,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,EAAE;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACrF,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aAClD,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QACvF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,SAAS,EAAE;wBACT,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC3C,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YACd,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,SAAS,EAAE;wBACT,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB;wBACtD,GAAG,EAAE,KAAK,CAAC,GAAG;wBACd,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACtE;iBACF;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;IACjF,CAAC;CACF,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { AgentTarget, InventoryArtifact, InventoryItemKind } from '@harness-nexus/shared';
2
+ import type { DiscoveredItem } from './common.js';
3
+ /** One row of an `inventory:payload` event (success or per-item error). */
4
+ export interface PayloadItem {
5
+ kind: InventoryItemKind;
6
+ name: string;
7
+ ok: boolean;
8
+ error?: string;
9
+ artifact?: InventoryArtifact;
10
+ }
11
+ /**
12
+ * A per-target scanner. `discover` re-runs on every collect — the daemon never
13
+ * trusts server-supplied paths.
14
+ */
15
+ export interface TargetScanner {
16
+ target: AgentTarget;
17
+ /** The agent's home dir (may not exist — discover then returns null). */
18
+ homeOf(homeDir: string): string;
19
+ discover(home: string): DiscoveredItem[] | null;
20
+ /** Whole-home platform markers beyond the ledger (e.g. shim MCP names). */
21
+ platformMarkers(home: string): string[];
22
+ collect(home: string, item: DiscoveredItem): Promise<PayloadItem>;
23
+ }
24
+ /** The config-file MCP entry shape all three parsers normalize to. */
25
+ export interface RawMcpEntry {
26
+ type?: string;
27
+ command?: string;
28
+ args?: string[];
29
+ env?: Record<string, string>;
30
+ url?: string;
31
+ headers?: Record<string, string>;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/inventory/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,yEAAyE;IACzE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC;IAChD,2EAA2E;IAC3E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACnE;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/inventory/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export interface McpServeOptions {
2
+ profileId: string;
3
+ server: string;
4
+ /** Machine PAT (from `hnx enroll`) or a user PAT. */
5
+ token: string;
6
+ }
7
+ export declare function runMcpServe(opts: McpServeOptions): Promise<void>;
8
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"AAqDA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFtE"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * `hnx mcp serve` — the client MCP shim (Phase 8 C2).
3
+ *
4
+ * Spawned BY an Agent tool as a per-session stdio MCP server (the tool's MCP
5
+ * config carries one stdio entry per profile). The shim:
6
+ * 1. fetches its resolved config from the platform
7
+ * (`GET /api/client/mcp-config?profile=<id>` — machine PAT or user PAT);
8
+ * 2. dials every CLIENT-dialed upstream locally via `mcp-runtime` (stdio /
9
+ * SSE / HTTP; credential plaintext lives in this process's memory only);
10
+ * 3. dials the platform `/mcp?profile=<id>` outlet as one PASSTHROUGH
11
+ * upstream when the profile has server-dialed entries (their tools are
12
+ * already namespaced server-side);
13
+ * 4. serves the merged, namespaced tool set over stdio until the tool
14
+ * closes our stdin.
15
+ *
16
+ * Config applies at process start — changes take effect next agent session.
17
+ * NEVER write to stdout (it carries the MCP protocol); all logs go to stderr.
18
+ * Uses the low-level `Server` (not `McpServer`) so upstream tools' raw JSON
19
+ * inputSchemas pass through verbatim — no zod round-trip, no schema drift.
20
+ */
21
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
22
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
23
+ import { ListToolsRequestSchema, CallToolRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
24
+ import { UpstreamPool, } from '@harness-nexus/mcp-runtime';
25
+ import { HarnessNexusClient, HarnessNexusError } from '@harness-nexus/sdk';
26
+ import { InstallError } from '../errors.js';
27
+ import { DAEMON_VERSION } from '../daemon/client.js';
28
+ /** stderr-only logger for the pool (stdout belongs to the MCP protocol). */
29
+ const stderrLog = {
30
+ info(_obj, msg) {
31
+ // eslint-disable-next-line no-console
32
+ console.error(`[hnx-mcp] ${msg}`);
33
+ },
34
+ warn(obj, msg) {
35
+ const detail = 'err' in obj && obj.err instanceof Error ? `: ${obj.err.message}` : '';
36
+ // eslint-disable-next-line no-console
37
+ console.error(`[hnx-mcp] WARN ${msg}${detail}`);
38
+ },
39
+ debug() {
40
+ /* quiet by default */
41
+ },
42
+ };
43
+ export async function runMcpServe(opts) {
44
+ const client = new HarnessNexusClient({ baseUrl: opts.server, token: opts.token });
45
+ let config;
46
+ try {
47
+ config = await client.getClientMcpConfig(opts.profileId);
48
+ }
49
+ catch (e) {
50
+ throw new InstallError(`Failed to fetch MCP config for profile '${opts.profileId}': ${e instanceof HarnessNexusError
51
+ ? `${e.code}: ${e.message}`
52
+ : e instanceof Error
53
+ ? e.message
54
+ : String(e)}`, 'RESOLVE_FAILED', e);
55
+ }
56
+ // Client-dialed upstreams (transports arrive resolved — memory-only secrets).
57
+ // Cast: zod-inferred optionals (`| undefined`) vs the runtime's exact-optional
58
+ // shape — identical at runtime, validated at the API boundary.
59
+ const defs = [];
60
+ for (const s of config.servers) {
61
+ if (s.dialSite !== 'client')
62
+ continue;
63
+ defs.push({ id: s.id, name: s.name, transport: s.transport });
64
+ }
65
+ // The platform outlet as ONE passthrough upstream (tools already namespaced).
66
+ if (config.platform !== null) {
67
+ defs.push({
68
+ id: '__outlet__',
69
+ name: 'harness-nexus',
70
+ transport: {
71
+ type: 'streamable-http',
72
+ url: `${config.platform.baseUrl.replace(/\/$/, '')}/mcp?profile=${encodeURIComponent(config.profileId)}`,
73
+ headers: { Authorization: `Bearer ${opts.token}` },
74
+ },
75
+ namespaced: true,
76
+ });
77
+ }
78
+ const pool = new UpstreamPool({
79
+ logger: stderrLog,
80
+ clientName: 'hnx-mcp-serve',
81
+ clientVersion: DAEMON_VERSION,
82
+ });
83
+ await pool.sync(defs);
84
+ await pool.settle();
85
+ for (const s of pool.statuses()) {
86
+ if (s.status === 'error') {
87
+ stderrLog.warn({}, `upstream "${s.name}" failed: ${s.detail ?? 'unknown error'} (skipped)`);
88
+ }
89
+ }
90
+ const server = new Server({ name: 'hnx-mcp-serve', version: DAEMON_VERSION }, { capabilities: { tools: {} } });
91
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
92
+ tools: pool.listTools().map((t) => ({
93
+ name: t.name,
94
+ ...(t.description !== undefined ? { description: t.description } : {}),
95
+ inputSchema: t.inputSchema,
96
+ })),
97
+ }));
98
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
99
+ const { name, arguments: args } = req.params;
100
+ try {
101
+ const result = await pool.callTool(name, args);
102
+ return result;
103
+ }
104
+ catch (e) {
105
+ const text = e instanceof Error ? e.message : String(e);
106
+ return { content: [{ type: 'text', text }], isError: true };
107
+ }
108
+ });
109
+ const transport = new StdioServerTransport();
110
+ await server.connect(transport);
111
+ stderrLog.info({}, `serving profile ${config.profileId} (${pool.listTools().length} tools)`);
112
+ await new Promise((resolve) => {
113
+ server.onclose = () => {
114
+ void pool.shutdown().finally(resolve);
115
+ };
116
+ });
117
+ }
118
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"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"}