@hypertabai/mcp 0.2.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.
Files changed (50) hide show
  1. package/README.md +120 -0
  2. package/dist/__tests__/config-writer.test.d.ts +2 -0
  3. package/dist/__tests__/config-writer.test.d.ts.map +1 -0
  4. package/dist/__tests__/config-writer.test.js +186 -0
  5. package/dist/__tests__/config-writer.test.js.map +1 -0
  6. package/dist/__tests__/index.test.d.ts +2 -0
  7. package/dist/__tests__/index.test.d.ts.map +1 -0
  8. package/dist/__tests__/index.test.js +113 -0
  9. package/dist/__tests__/index.test.js.map +1 -0
  10. package/dist/__tests__/install.test.d.ts +2 -0
  11. package/dist/__tests__/install.test.d.ts.map +1 -0
  12. package/dist/__tests__/install.test.js +211 -0
  13. package/dist/__tests__/install.test.js.map +1 -0
  14. package/dist/__tests__/platforms.test.d.ts +2 -0
  15. package/dist/__tests__/platforms.test.d.ts.map +1 -0
  16. package/dist/__tests__/platforms.test.js +109 -0
  17. package/dist/__tests__/platforms.test.js.map +1 -0
  18. package/dist/__tests__/uninstall.test.d.ts +2 -0
  19. package/dist/__tests__/uninstall.test.d.ts.map +1 -0
  20. package/dist/__tests__/uninstall.test.js +117 -0
  21. package/dist/__tests__/uninstall.test.js.map +1 -0
  22. package/dist/connect.d.ts +8 -0
  23. package/dist/connect.d.ts.map +1 -0
  24. package/dist/connect.js +49 -0
  25. package/dist/connect.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +78 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/install/config-writer.d.ts +49 -0
  31. package/dist/install/config-writer.d.ts.map +1 -0
  32. package/dist/install/config-writer.js +156 -0
  33. package/dist/install/config-writer.js.map +1 -0
  34. package/dist/install/index.d.ts +17 -0
  35. package/dist/install/index.d.ts.map +1 -0
  36. package/dist/install/index.js +94 -0
  37. package/dist/install/index.js.map +1 -0
  38. package/dist/install/platforms.d.ts +38 -0
  39. package/dist/install/platforms.d.ts.map +1 -0
  40. package/dist/install/platforms.js +162 -0
  41. package/dist/install/platforms.js.map +1 -0
  42. package/dist/install/skill-writer.d.ts +24 -0
  43. package/dist/install/skill-writer.d.ts.map +1 -0
  44. package/dist/install/skill-writer.js +86 -0
  45. package/dist/install/skill-writer.js.map +1 -0
  46. package/dist/install/uninstall.d.ts +11 -0
  47. package/dist/install/uninstall.d.ts.map +1 -0
  48. package/dist/install/uninstall.js +81 -0
  49. package/dist/install/uninstall.js.map +1 -0
  50. package/package.json +38 -0
@@ -0,0 +1,211 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { runInstall } from '../install/index.js';
6
+ const SAMPLE_SKILL = `---
7
+ name: hypertab
8
+ description: Hypertab MCP skill
9
+ version: 1.0.0
10
+ ---
11
+
12
+ # Hypertab
13
+ Skill body.
14
+ `;
15
+ function okFetch(body, status = 200) {
16
+ return (async () => new Response(body, {
17
+ status,
18
+ headers: { 'content-type': 'text/markdown' },
19
+ }));
20
+ }
21
+ function failingFetch() {
22
+ return (async () => {
23
+ throw new Error('network down');
24
+ });
25
+ }
26
+ function captureStreams() {
27
+ const out = [];
28
+ const err = [];
29
+ return {
30
+ stdout: { write: (chunk) => out.push(chunk) },
31
+ stderr: { write: (chunk) => err.push(chunk) },
32
+ out,
33
+ err,
34
+ };
35
+ }
36
+ let workDir;
37
+ function testPlatform(opts = {}) {
38
+ const id = opts.id ?? 'claude-code';
39
+ const configFile = join(workDir, `${id}.json`);
40
+ const skillFile = join(workDir, id, 'skill', 'SKILL.md');
41
+ return {
42
+ id,
43
+ name: opts.name ?? id,
44
+ description: '',
45
+ supportsUserScope: opts.supportsUserScope ?? true,
46
+ supportsProjectScope: opts.supportsProjectScope ?? true,
47
+ configPath: () => configFile,
48
+ serversKey: 'mcpServers',
49
+ serverName: 'hypertab',
50
+ buildServerEntry: (url, apiKey) => ({
51
+ type: 'http',
52
+ url,
53
+ headers: { Authorization: `Bearer ${apiKey}` },
54
+ }),
55
+ supportsSkill: opts.supportsSkill ?? true,
56
+ skillPath: (opts.supportsSkill ?? true) ? () => skillFile : undefined,
57
+ restartInstruction: 'Restart the agent.',
58
+ };
59
+ }
60
+ beforeEach(() => {
61
+ workDir = mkdtempSync(join(tmpdir(), 'hypertab-install-'));
62
+ });
63
+ afterEach(() => {
64
+ rmSync(workDir, { recursive: true, force: true });
65
+ });
66
+ describe('runInstall', () => {
67
+ it('writes config and skill for claude-code with a valid key', async () => {
68
+ const platform = testPlatform();
69
+ const streams = captureStreams();
70
+ const code = await runInstall({
71
+ platform,
72
+ apiKey: 'ht_sk_valid123',
73
+ scope: 'user',
74
+ ...streams,
75
+ env: {},
76
+ fetchImpl: okFetch(SAMPLE_SKILL),
77
+ });
78
+ expect(code).toBe(0);
79
+ expect(existsSync(join(workDir, 'claude-code.json'))).toBe(true);
80
+ expect(existsSync(join(workDir, 'claude-code', 'skill', 'SKILL.md'))).toBe(true);
81
+ const config = JSON.parse(readFileSync(join(workDir, 'claude-code.json'), 'utf8'));
82
+ expect(config.mcpServers.hypertab.headers.Authorization).toBe('Bearer ht_sk_valid123');
83
+ const skill = readFileSync(join(workDir, 'claude-code', 'skill', 'SKILL.md'), 'utf8');
84
+ expect(skill).toBe(SAMPLE_SKILL);
85
+ expect(streams.out.join('')).toContain('Installed Hypertab MCP');
86
+ expect(streams.err.join('')).toContain('HYPERTAB_API_KEY env var is safer');
87
+ });
88
+ it('uses HYPERTAB_API_KEY env var when flag is not set', async () => {
89
+ const streams = captureStreams();
90
+ const code = await runInstall({
91
+ platform: testPlatform(),
92
+ scope: 'user',
93
+ ...streams,
94
+ env: { HYPERTAB_API_KEY: 'ht_sk_fromenv' },
95
+ fetchImpl: okFetch(SAMPLE_SKILL),
96
+ });
97
+ expect(code).toBe(0);
98
+ const config = JSON.parse(readFileSync(join(workDir, 'claude-code.json'), 'utf8'));
99
+ expect(config.mcpServers.hypertab.headers.Authorization).toBe('Bearer ht_sk_fromenv');
100
+ expect(streams.err.join('')).not.toContain('HYPERTAB_API_KEY env var is safer');
101
+ });
102
+ it('falls back to the interactive prompt when neither flag nor env var is set', async () => {
103
+ const streams = captureStreams();
104
+ const code = await runInstall({
105
+ platform: testPlatform(),
106
+ scope: 'user',
107
+ ...streams,
108
+ env: {},
109
+ promptFn: async () => 'ht_sk_prompted',
110
+ fetchImpl: okFetch(SAMPLE_SKILL),
111
+ });
112
+ expect(code).toBe(0);
113
+ const config = JSON.parse(readFileSync(join(workDir, 'claude-code.json'), 'utf8'));
114
+ expect(config.mcpServers.hypertab.headers.Authorization).toBe('Bearer ht_sk_prompted');
115
+ });
116
+ it('rejects keys that do not start with ht_sk_', async () => {
117
+ const streams = captureStreams();
118
+ const code = await runInstall({
119
+ platform: testPlatform(),
120
+ apiKey: 'wrong_prefix_abc',
121
+ scope: 'user',
122
+ ...streams,
123
+ env: {},
124
+ fetchImpl: okFetch(SAMPLE_SKILL),
125
+ });
126
+ expect(code).toBe(1);
127
+ expect(streams.err.join('')).toContain("must start with 'ht_sk_'");
128
+ expect(existsSync(join(workDir, 'claude-code.json'))).toBe(false);
129
+ });
130
+ it('still writes the config when the skill fetch fails', async () => {
131
+ const streams = captureStreams();
132
+ const code = await runInstall({
133
+ platform: testPlatform(),
134
+ apiKey: 'ht_sk_valid123',
135
+ scope: 'user',
136
+ ...streams,
137
+ env: {},
138
+ fetchImpl: failingFetch(),
139
+ });
140
+ expect(code).toBe(0);
141
+ expect(existsSync(join(workDir, 'claude-code.json'))).toBe(true);
142
+ expect(existsSync(join(workDir, 'claude-code', 'skill', 'SKILL.md'))).toBe(false);
143
+ expect(streams.out.join('')).toMatch(/Skill:\s+FAILED/);
144
+ });
145
+ it('skips skill install with a note for platforms that do not support skills', async () => {
146
+ const platform = testPlatform({ id: 'cursor', supportsSkill: false });
147
+ const streams = captureStreams();
148
+ const code = await runInstall({
149
+ platform,
150
+ apiKey: 'ht_sk_valid123',
151
+ scope: 'user',
152
+ ...streams,
153
+ env: {},
154
+ fetchImpl: okFetch(SAMPLE_SKILL),
155
+ });
156
+ expect(code).toBe(0);
157
+ expect(existsSync(join(workDir, 'cursor.json'))).toBe(true);
158
+ expect(existsSync(join(workDir, 'cursor', 'skill', 'SKILL.md'))).toBe(false);
159
+ expect(streams.out.join('')).toContain('Skill: skipped');
160
+ });
161
+ it('rejects project scope for platforms that only support user scope', async () => {
162
+ const platform = testPlatform({ id: 'windsurf', supportsProjectScope: false });
163
+ const streams = captureStreams();
164
+ const code = await runInstall({
165
+ platform,
166
+ apiKey: 'ht_sk_valid123',
167
+ scope: 'project',
168
+ ...streams,
169
+ env: {},
170
+ });
171
+ expect(code).toBe(1);
172
+ expect(streams.err.join('')).toContain('does not support project scope');
173
+ });
174
+ it('masks the API key in output (never echoes full)', async () => {
175
+ const streams = captureStreams();
176
+ await runInstall({
177
+ platform: testPlatform(),
178
+ apiKey: 'ht_sk_fullsecretvalueabc123',
179
+ scope: 'user',
180
+ ...streams,
181
+ env: {},
182
+ fetchImpl: okFetch(SAMPLE_SKILL),
183
+ });
184
+ const combined = streams.out.join('') + streams.err.join('');
185
+ expect(combined).not.toContain('ht_sk_fullsecretvalueabc123');
186
+ expect(combined).toMatch(/ht_sk_full/);
187
+ });
188
+ it('is idempotent — second run with the same key is a no-op', async () => {
189
+ const platform = testPlatform();
190
+ const s1 = captureStreams();
191
+ await runInstall({
192
+ platform,
193
+ apiKey: 'ht_sk_same',
194
+ scope: 'user',
195
+ ...s1,
196
+ env: {},
197
+ fetchImpl: okFetch(SAMPLE_SKILL),
198
+ });
199
+ const s2 = captureStreams();
200
+ await runInstall({
201
+ platform,
202
+ apiKey: 'ht_sk_same',
203
+ scope: 'user',
204
+ ...s2,
205
+ env: {},
206
+ fetchImpl: okFetch(SAMPLE_SKILL),
207
+ });
208
+ expect(s2.out.join('')).toContain('no-change');
209
+ });
210
+ });
211
+ //# sourceMappingURL=install.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../src/__tests__/install.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platforms.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platforms.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/platforms.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getPlatform, PLATFORM_IDS, PLATFORMS, resolveCanonical } from '../install/platforms.js';
3
+ const URL = 'https://api.hypertab.ai/mcp';
4
+ const KEY = 'ht_sk_test12345';
5
+ describe('platform registry', () => {
6
+ it('exposes all 7 supported client IDs', () => {
7
+ expect(PLATFORM_IDS).toEqual(expect.arrayContaining(['claude-code', 'claude-desktop', 'cursor', 'windsurf', 'antigravity', 'vscode', 'cowork']));
8
+ expect(PLATFORM_IDS).toHaveLength(7);
9
+ });
10
+ it('getPlatform throws a helpful error for unknown clients', () => {
11
+ expect(() => getPlatform('sublime-text')).toThrow(/Unknown client/);
12
+ expect(() => getPlatform('sublime-text')).toThrow(/claude-code/);
13
+ });
14
+ it('getPlatform returns the exact registry entry', () => {
15
+ expect(getPlatform('claude-code').id).toBe('claude-code');
16
+ expect(getPlatform('cursor').id).toBe('cursor');
17
+ });
18
+ });
19
+ describe('aliases', () => {
20
+ it('vscode is an alias for claude-code', () => {
21
+ const vscode = getPlatform('vscode');
22
+ expect(vscode.aliasOf).toBe('claude-code');
23
+ expect(vscode.name).toBe('VS Code');
24
+ expect(resolveCanonical(vscode).id).toBe('claude-code');
25
+ });
26
+ it('cowork is an alias for claude-code', () => {
27
+ const cowork = getPlatform('cowork');
28
+ expect(cowork.aliasOf).toBe('claude-code');
29
+ expect(resolveCanonical(cowork).id).toBe('claude-code');
30
+ });
31
+ it('aliases inherit config paths and server entry shape from their canonical', () => {
32
+ const cc = getPlatform('claude-code');
33
+ const vs = getPlatform('vscode');
34
+ expect(vs.configPath('user')).toBe(cc.configPath('user'));
35
+ expect(vs.configPath('project')).toBe(cc.configPath('project'));
36
+ expect(vs.buildServerEntry(URL, KEY)).toEqual(cc.buildServerEntry(URL, KEY));
37
+ });
38
+ it('resolveCanonical is a no-op for canonical platforms', () => {
39
+ const cc = getPlatform('claude-code');
40
+ expect(resolveCanonical(cc)).toBe(cc);
41
+ });
42
+ });
43
+ describe('server entry shapes', () => {
44
+ it('claude-code uses { type, url, headers }', () => {
45
+ expect(getPlatform('claude-code').buildServerEntry(URL, KEY)).toEqual({
46
+ type: 'http',
47
+ url: URL,
48
+ headers: { Authorization: `Bearer ${KEY}` },
49
+ });
50
+ });
51
+ it('cursor uses { url, headers } with no type field', () => {
52
+ const entry = getPlatform('cursor').buildServerEntry(URL, KEY);
53
+ expect(entry).toEqual({ url: URL, headers: { Authorization: `Bearer ${KEY}` } });
54
+ expect(entry.type).toBeUndefined();
55
+ });
56
+ it('windsurf uses { serverUrl, headers }', () => {
57
+ const entry = getPlatform('windsurf').buildServerEntry(URL, KEY);
58
+ expect(entry).toEqual({ serverUrl: URL, headers: { Authorization: `Bearer ${KEY}` } });
59
+ });
60
+ it('all platforms wrap the API key as a Bearer token', () => {
61
+ for (const id of PLATFORM_IDS) {
62
+ const entry = PLATFORMS[id].buildServerEntry(URL, KEY);
63
+ expect(entry.headers?.Authorization).toBe(`Bearer ${KEY}`);
64
+ }
65
+ });
66
+ });
67
+ describe('scope support', () => {
68
+ it('claude-code supports both user and project scopes', () => {
69
+ const cc = getPlatform('claude-code');
70
+ expect(cc.supportsUserScope).toBe(true);
71
+ expect(cc.supportsProjectScope).toBe(true);
72
+ expect(() => cc.configPath('user')).not.toThrow();
73
+ expect(() => cc.configPath('project')).not.toThrow();
74
+ });
75
+ it('claude-desktop supports user scope only', () => {
76
+ const cd = getPlatform('claude-desktop');
77
+ expect(cd.supportsUserScope).toBe(true);
78
+ expect(cd.supportsProjectScope).toBe(false);
79
+ expect(() => cd.configPath('project')).toThrow();
80
+ });
81
+ it('windsurf supports user scope only', () => {
82
+ const ws = getPlatform('windsurf');
83
+ expect(ws.supportsUserScope).toBe(true);
84
+ expect(ws.supportsProjectScope).toBe(false);
85
+ expect(() => ws.configPath('project')).toThrow();
86
+ });
87
+ it('cursor supports both scopes', () => {
88
+ const c = getPlatform('cursor');
89
+ expect(c.supportsUserScope).toBe(true);
90
+ expect(c.supportsProjectScope).toBe(true);
91
+ });
92
+ });
93
+ describe('skill support', () => {
94
+ it('only claude-code and its aliases support skills', () => {
95
+ expect(getPlatform('claude-code').supportsSkill).toBe(true);
96
+ expect(getPlatform('vscode').supportsSkill).toBe(true);
97
+ expect(getPlatform('cowork').supportsSkill).toBe(true);
98
+ });
99
+ it('other platforms do not support skills', () => {
100
+ for (const id of ['claude-desktop', 'cursor', 'windsurf', 'antigravity']) {
101
+ expect(getPlatform(id).supportsSkill).toBe(false);
102
+ }
103
+ });
104
+ it('skill path for claude-code project scope is under .claude/skills/hypertab', () => {
105
+ const p = getPlatform('claude-code').skillPath?.('project');
106
+ expect(p).toMatch(/\.claude[\/\\]skills[\/\\]hypertab[\/\\]SKILL\.md$/);
107
+ });
108
+ });
109
+ //# sourceMappingURL=platforms.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platforms.test.js","sourceRoot":"","sources":["../../src/__tests__/platforms.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=uninstall.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/uninstall.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,117 @@
1
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { runUninstall } from '../install/uninstall.js';
6
+ function captureStreams() {
7
+ const out = [];
8
+ const err = [];
9
+ return {
10
+ stdout: { write: (chunk) => out.push(chunk) },
11
+ stderr: { write: (chunk) => err.push(chunk) },
12
+ out,
13
+ err,
14
+ };
15
+ }
16
+ let workDir;
17
+ function testPlatform(opts = {}) {
18
+ const id = opts.id ?? 'claude-code';
19
+ const configFile = join(workDir, `${id}.json`);
20
+ const skillFile = join(workDir, id, 'skill', 'SKILL.md');
21
+ return {
22
+ id,
23
+ name: id,
24
+ description: '',
25
+ supportsUserScope: true,
26
+ supportsProjectScope: true,
27
+ configPath: () => configFile,
28
+ serversKey: 'mcpServers',
29
+ serverName: 'hypertab',
30
+ buildServerEntry: (url, apiKey) => ({
31
+ type: 'http',
32
+ url,
33
+ headers: { Authorization: `Bearer ${apiKey}` },
34
+ }),
35
+ supportsSkill: opts.supportsSkill ?? true,
36
+ skillPath: (opts.supportsSkill ?? true) ? () => skillFile : undefined,
37
+ restartInstruction: 'Restart.',
38
+ };
39
+ }
40
+ function seedConfig(platform) {
41
+ const configFile = platform.configPath('user');
42
+ const skill = platform.skillPath?.('user');
43
+ const parent = dirname(configFile);
44
+ if (!existsSync(parent))
45
+ mkdirSync(parent, { recursive: true });
46
+ writeFileSync(configFile, JSON.stringify({
47
+ mcpServers: {
48
+ other: { command: 'keep-me' },
49
+ hypertab: { type: 'http', url: 'https://api.hypertab.ai/mcp' },
50
+ },
51
+ }, null, 2));
52
+ if (skill) {
53
+ const skillParent = dirname(skill);
54
+ if (!existsSync(skillParent))
55
+ mkdirSync(skillParent, { recursive: true });
56
+ writeFileSync(skill, '---\nname: hypertab\n---\nold skill\n');
57
+ }
58
+ }
59
+ beforeEach(() => {
60
+ workDir = mkdtempSync(join(tmpdir(), 'hypertab-uninstall-'));
61
+ });
62
+ afterEach(() => {
63
+ rmSync(workDir, { recursive: true, force: true });
64
+ });
65
+ describe('runUninstall', () => {
66
+ it('removes the config entry and deletes the skill by default', async () => {
67
+ const platform = testPlatform();
68
+ seedConfig(platform);
69
+ const streams = captureStreams();
70
+ const code = await runUninstall({ platform, scope: 'user', ...streams });
71
+ expect(code).toBe(0);
72
+ const cfg = JSON.parse(readFileSync(platform.configPath('user'), 'utf8'));
73
+ expect(cfg.mcpServers.hypertab).toBeUndefined();
74
+ expect(cfg.mcpServers.other).toEqual({ command: 'keep-me' });
75
+ expect(existsSync(platform.skillPath('user'))).toBe(false);
76
+ const joined = streams.out.join('');
77
+ expect(joined).toContain('Uninstalled Hypertab MCP');
78
+ expect(joined).toContain('(removed');
79
+ });
80
+ it('keeps the skill file when --keep-skill is passed', async () => {
81
+ const platform = testPlatform();
82
+ seedConfig(platform);
83
+ const streams = captureStreams();
84
+ const code = await runUninstall({ platform, scope: 'user', keepSkill: true, ...streams });
85
+ expect(code).toBe(0);
86
+ expect(existsSync(platform.skillPath('user'))).toBe(true);
87
+ expect(streams.out.join('')).toContain('(kept, --keep-skill)');
88
+ });
89
+ it('reports "not-installed" when hypertab was never added', async () => {
90
+ const platform = testPlatform();
91
+ const configFile = platform.configPath('user');
92
+ writeFileSync(configFile, JSON.stringify({ mcpServers: { other: { command: 'x' } } }, null, 2));
93
+ const streams = captureStreams();
94
+ const code = await runUninstall({ platform, scope: 'user', ...streams });
95
+ expect(code).toBe(0);
96
+ const cfg = JSON.parse(readFileSync(configFile, 'utf8'));
97
+ expect(cfg.mcpServers.other).toEqual({ command: 'x' });
98
+ expect(streams.out.join('')).toContain('nothing to remove');
99
+ });
100
+ it('reports file-missing when the config file does not exist', async () => {
101
+ const platform = testPlatform();
102
+ const streams = captureStreams();
103
+ const code = await runUninstall({ platform, scope: 'user', ...streams });
104
+ expect(code).toBe(0);
105
+ expect(streams.out.join('')).toContain('file did not exist');
106
+ });
107
+ it('platforms without skill support report n/a for skill', async () => {
108
+ const platform = testPlatform({ id: 'cursor', supportsSkill: false });
109
+ seedConfig(platform);
110
+ const streams = captureStreams();
111
+ const code = await runUninstall({ platform, scope: 'user', ...streams });
112
+ expect(code).toBe(0);
113
+ const joined = streams.out.join('');
114
+ expect(joined).toContain('Skill: n/a');
115
+ });
116
+ });
117
+ //# sourceMappingURL=uninstall.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.test.js","sourceRoot":"","sources":["../../src/__tests__/uninstall.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type TransportType = 'streamable-http' | 'sse' | 'stdio';
2
+ export interface ConnectOptions {
3
+ apiKey: string;
4
+ url: string;
5
+ transport: TransportType;
6
+ }
7
+ export declare function runConnect(opts: ConnectOptions): Promise<number>;
8
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,KAAK,GAAG,OAAO,CAAA;AAE/D,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,aAAa,CAAA;CACxB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6CtE"}
@@ -0,0 +1,49 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
3
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
4
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
5
+ export async function runConnect(opts) {
6
+ if (!opts.apiKey.startsWith('ht_sk_')) {
7
+ console.error('Error: API key must start with ht_sk_');
8
+ return 1;
9
+ }
10
+ try {
11
+ const client = new Client({ name: '@hypertabai/mcp', version: '0.2.0' }, { capabilities: {} });
12
+ if (opts.transport === 'stdio') {
13
+ const transport = new StdioClientTransport({ command: 'node', args: ['--version'] });
14
+ await client.connect(transport);
15
+ }
16
+ else if (opts.transport === 'sse') {
17
+ const transport = new SSEClientTransport(new URL(opts.url), {
18
+ requestInit: { headers: { Authorization: `Bearer ${opts.apiKey}` } },
19
+ });
20
+ await client.connect(transport);
21
+ }
22
+ else {
23
+ const transport = new StreamableHTTPClientTransport(new URL(opts.url), {
24
+ requestInit: { headers: { Authorization: `Bearer ${opts.apiKey}` } },
25
+ });
26
+ await client.connect(transport);
27
+ }
28
+ const tools = await client.listTools();
29
+ console.log(`Connected to Hypertab. ${tools.tools.length} tools available:`);
30
+ for (const tool of tools.tools) {
31
+ console.log(` - ${tool.name}: ${tool.description?.slice(0, 80) ?? ''}`);
32
+ }
33
+ console.log('\nMCP client connected. Press Ctrl+C to disconnect.');
34
+ await new Promise((resolve) => {
35
+ process.on('SIGINT', () => {
36
+ console.log('\nDisconnecting...');
37
+ resolve();
38
+ });
39
+ process.on('SIGTERM', resolve);
40
+ });
41
+ await client.close();
42
+ return 0;
43
+ }
44
+ catch (err) {
45
+ console.error('Connection failed:', err instanceof Error ? err.message : err);
46
+ return 1;
47
+ }
48
+ }
49
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { runConnect } from './connect.js';
4
+ import { runInstall } from './install/index.js';
5
+ import { getPlatform, PLATFORM_IDS } from './install/platforms.js';
6
+ import { runUninstall } from './install/uninstall.js';
7
+ const DEFAULT_URL = 'https://api.hypertab.ai/mcp';
8
+ const VERSION = '0.2.0';
9
+ const program = new Command()
10
+ .name('hypertab')
11
+ .description('Hypertab MCP — install and run the Hypertab MCP server for any AI agent')
12
+ .version(VERSION);
13
+ program
14
+ .command('install')
15
+ .description('Install the Hypertab MCP config (and skill where supported) for an AI agent')
16
+ .requiredOption('-c, --client <id>', `Target client: ${PLATFORM_IDS.join(' | ')}`)
17
+ .option('-k, --api-key <key>', 'Hypertab API key (ht_sk_...). Prefer HYPERTAB_API_KEY env var for safety.')
18
+ .option('-s, --scope <scope>', 'Config scope: user | project', 'user')
19
+ .option('-u, --url <url>', 'Override MCP server URL', DEFAULT_URL)
20
+ .option('--skill-url <url>', 'Override the Hypertab skill.md source URL (for self-hosted mirrors or testing)')
21
+ .action(async (opts) => {
22
+ const scope = opts.scope === 'project' ? 'project' : 'user';
23
+ let platform;
24
+ try {
25
+ platform = getPlatform(opts.client);
26
+ }
27
+ catch (e) {
28
+ process.stderr.write(`Error: ${e.message}\n`);
29
+ process.exit(1);
30
+ }
31
+ const code = await runInstall({
32
+ platform,
33
+ apiKey: opts.apiKey,
34
+ scope,
35
+ url: opts.url,
36
+ skillUrl: opts.skillUrl,
37
+ });
38
+ process.exit(code);
39
+ });
40
+ program
41
+ .command('uninstall')
42
+ .description('Remove the Hypertab MCP config (and skill where supported) from an AI agent')
43
+ .requiredOption('-c, --client <id>', `Target client: ${PLATFORM_IDS.join(' | ')}`)
44
+ .option('-s, --scope <scope>', 'Config scope: user | project', 'user')
45
+ .option('--keep-skill', 'Keep the installed skill file at ~/.claude/skills/hypertab/SKILL.md (Claude Code only)')
46
+ .action(async (opts) => {
47
+ const scope = opts.scope === 'project' ? 'project' : 'user';
48
+ let platform;
49
+ try {
50
+ platform = getPlatform(opts.client);
51
+ }
52
+ catch (e) {
53
+ process.stderr.write(`Error: ${e.message}\n`);
54
+ process.exit(1);
55
+ }
56
+ const code = await runUninstall({
57
+ platform,
58
+ scope,
59
+ keepSkill: opts.keepSkill,
60
+ });
61
+ process.exit(code);
62
+ });
63
+ program
64
+ .command('connect')
65
+ .description('Connect to Hypertab as an MCP client (for testing / debug)')
66
+ .requiredOption('-k, --api-key <key>', 'Hypertab API key (ht_sk_...)')
67
+ .option('-u, --url <url>', 'MCP server URL', DEFAULT_URL)
68
+ .option('-t, --transport <type>', 'Transport: streamable-http | sse | stdio', 'streamable-http')
69
+ .action(async (opts) => {
70
+ const code = await runConnect({
71
+ apiKey: opts.apiKey,
72
+ url: opts.url,
73
+ transport: opts.transport,
74
+ });
75
+ process.exit(code);
76
+ });
77
+ program.parse(process.argv);
78
+ //# sourceMappingURL=index.js.map