@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
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # @hypertabai/mcp
2
+
3
+ One-command installer for the Hypertab MCP server. Connects any MCP-capable AI agent to your Hypertab workspace in a single step — no JSON editing, no manual skill downloads.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ # Installs for Claude Code in the current project (user scope is default)
9
+ npx @hypertabai/mcp install --client claude-code --api-key ht_sk_...
10
+ ```
11
+
12
+ Restart your agent. Done.
13
+
14
+ ## Supported clients
15
+
16
+ | `--client` | Target | Scopes | Installs skill? |
17
+ |---|---|---|---|
18
+ | `claude-code` | Claude Code CLI | user, project | yes |
19
+ | `claude-desktop` | Claude Desktop app | user | no |
20
+ | `cursor` | Cursor | user, project | no |
21
+ | `windsurf` | Windsurf | user | no |
22
+ | `antigravity` | Google Antigravity | user, project | no |
23
+ | `vscode` | VS Code (via Claude Code plugin) | user, project | yes |
24
+ | `cowork` | Claude Cowork | user, project | yes |
25
+
26
+ `vscode` and `cowork` are display aliases for `claude-code` — they write to the same config file the Claude Code plugin already reads.
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ # Interactive (safest — key is prompted, not in argv or env)
32
+ npx @hypertabai/mcp install --client cursor
33
+
34
+ # Via env var (recommended for CI)
35
+ HYPERTAB_API_KEY=ht_sk_... npx @hypertabai/mcp install --client claude-code
36
+
37
+ # Via flag (easiest copy-paste; prints a security tip)
38
+ npx @hypertabai/mcp install --client claude-code --api-key ht_sk_...
39
+
40
+ # Project scope (writes to ./.mcp.json instead of ~/.claude.json)
41
+ npx @hypertabai/mcp install --client claude-code --scope project
42
+ ```
43
+
44
+ ## What it does
45
+
46
+ 1. Resolves the right config file for your chosen client and operating system.
47
+ 2. Deep-merges a `hypertab` entry into that file's server map — **never touches your other MCP servers**.
48
+ 3. Creates a `.bak` of the original config on first run.
49
+ 4. Writes atomically via `.tmp` + rename.
50
+ 5. For Claude Code (and aliases), also fetches and installs the Hypertab skill at `~/.claude/skills/hypertab/SKILL.md`.
51
+ 6. Prints the file paths it touched and the next step (restart your agent).
52
+
53
+ Re-running the command is safe: identical configs are a no-op; updated keys rewrite only the `Authorization` header.
54
+
55
+ ## Key handling
56
+
57
+ Priority order for the API key:
58
+
59
+ 1. `--api-key <key>` flag (visible to `ps`; prints a tip suggesting the env var instead)
60
+ 2. `HYPERTAB_API_KEY` environment variable
61
+ 3. Interactive prompt (TTY only)
62
+
63
+ The installer never echoes your full key in output — only the `ht_sk_xxxx…xxxx` prefix.
64
+
65
+ ## Uninstalling
66
+
67
+ ```bash
68
+ npx @hypertabai/mcp uninstall --client claude-code --scope project
69
+ ```
70
+
71
+ Removes the `hypertab` entry from the target agent's MCP config (never touches other servers) and deletes the skill file at `~/.claude/skills/hypertab/SKILL.md` if it was installed. Use `--keep-skill` to preserve the skill file while still removing the MCP server entry.
72
+
73
+ Idempotent: running uninstall on an already-clean config is a no-op that prints `nothing to remove`.
74
+
75
+ To remove Hypertab from every agent you installed it for, run uninstall once per `--client` / `--scope` combination.
76
+
77
+ ## Testing the connection
78
+
79
+ ```bash
80
+ npx @hypertabai/mcp connect --api-key ht_sk_...
81
+ ```
82
+
83
+ Lists every Hypertab tool the server exposes. Useful for verifying credentials before wiring up an agent.
84
+
85
+ ## Flags
86
+
87
+ ### `install`
88
+
89
+ | Flag | Default | Description |
90
+ |---|---|---|
91
+ | `-c, --client <id>` | required | Target agent (see table above) |
92
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` or prompt | Hypertab API key |
93
+ | `-s, --scope <scope>` | `user` | `user` or `project` |
94
+ | `-u, --url <url>` | `https://api.hypertab.ai/mcp` | MCP server URL override |
95
+
96
+ ### `uninstall`
97
+
98
+ | Flag | Default | Description |
99
+ |---|---|---|
100
+ | `-c, --client <id>` | required | Target agent to remove hypertab from |
101
+ | `-s, --scope <scope>` | `user` | `user` or `project` |
102
+ | `--keep-skill` | false | Preserve the installed skill file (Claude Code only) |
103
+
104
+ ### `connect`
105
+
106
+ | Flag | Default | Description |
107
+ |---|---|---|
108
+ | `-k, --api-key <key>` | required | Hypertab API key |
109
+ | `-u, --url <url>` | `https://api.hypertab.ai/mcp` | MCP server URL |
110
+ | `-t, --transport <type>` | `streamable-http` | `streamable-http`, `sse`, or `stdio` |
111
+
112
+ ## Troubleshooting
113
+
114
+ **"Failed to parse existing config"** — your client's existing config file has invalid JSON. Fix it or delete it and re-run.
115
+
116
+ **"Could not fetch skill.md"** — network issue or the skill endpoint is misconfigured. Your MCP server was still installed; re-run the command later to retry the skill download.
117
+
118
+ **Server doesn't appear after install** — restart your client completely. Claude Code, Cursor, and Windsurf only load new MCP servers at startup.
119
+
120
+ **Antigravity / Cursor doesn't load the server** — vendor config shapes occasionally change. Grab the raw JSON from your Hypertab app's "MCP connections" page, hand-edit if needed, and [open an issue](https://github.com/hypertab/hypertab/issues).
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config-writer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-writer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config-writer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,186 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } 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 { removePlatformConfig, stripJsonComments, writePlatformConfig } from '../install/config-writer.js';
6
+ function tmpPlatform(configFile) {
7
+ return {
8
+ id: 'test',
9
+ name: 'Test',
10
+ description: 'Test',
11
+ supportsUserScope: true,
12
+ supportsProjectScope: true,
13
+ configPath: (_scope) => configFile,
14
+ serversKey: 'mcpServers',
15
+ serverName: 'hypertab',
16
+ buildServerEntry: (url, apiKey) => ({
17
+ type: 'http',
18
+ url,
19
+ headers: { Authorization: `Bearer ${apiKey}` },
20
+ }),
21
+ supportsSkill: false,
22
+ restartInstruction: '',
23
+ };
24
+ }
25
+ const ENTRY = {
26
+ type: 'http',
27
+ url: 'https://api.hypertab.ai/mcp',
28
+ headers: { Authorization: 'Bearer ht_sk_test' },
29
+ };
30
+ let dir;
31
+ beforeEach(() => {
32
+ dir = mkdtempSync(join(tmpdir(), 'hypertab-cfg-'));
33
+ });
34
+ afterEach(() => {
35
+ rmSync(dir, { recursive: true, force: true });
36
+ });
37
+ describe('writePlatformConfig', () => {
38
+ it('creates a new config file when none exists', () => {
39
+ const file = join(dir, 'mcp.json');
40
+ const result = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
41
+ expect(result.action).toBe('created');
42
+ expect(result.backupCreated).toBe(false);
43
+ expect(existsSync(file)).toBe(true);
44
+ const written = JSON.parse(readFileSync(file, 'utf8'));
45
+ expect(written).toEqual({ mcpServers: { hypertab: ENTRY } });
46
+ });
47
+ it('merges into an existing file without touching other servers', () => {
48
+ const file = join(dir, 'mcp.json');
49
+ const existing = {
50
+ mcpServers: {
51
+ other: { command: 'some-server', args: [] },
52
+ another: { type: 'http', url: 'https://x' },
53
+ },
54
+ };
55
+ writeFileSync(file, JSON.stringify(existing, null, 2));
56
+ const result = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
57
+ expect(result.action).toBe('updated');
58
+ expect(result.backupCreated).toBe(true);
59
+ expect(existsSync(`${file}.bak`)).toBe(true);
60
+ const written = JSON.parse(readFileSync(file, 'utf8'));
61
+ expect(written.mcpServers.other).toEqual(existing.mcpServers.other);
62
+ expect(written.mcpServers.another).toEqual(existing.mcpServers.another);
63
+ expect(written.mcpServers.hypertab).toEqual(ENTRY);
64
+ });
65
+ it('returns no-change when the entry already matches', () => {
66
+ const file = join(dir, 'mcp.json');
67
+ writeFileSync(file, JSON.stringify({ mcpServers: { hypertab: ENTRY } }, null, 2));
68
+ const result = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
69
+ expect(result.action).toBe('no-change');
70
+ expect(result.backupCreated).toBe(false);
71
+ expect(existsSync(`${file}.bak`)).toBe(false);
72
+ });
73
+ it('updates in place when the hypertab entry changed (e.g. new key)', () => {
74
+ const file = join(dir, 'mcp.json');
75
+ const oldEntry = {
76
+ type: 'http',
77
+ url: 'https://api.hypertab.ai/mcp',
78
+ headers: { Authorization: 'Bearer ht_sk_old' },
79
+ };
80
+ writeFileSync(file, JSON.stringify({ mcpServers: { hypertab: oldEntry } }, null, 2));
81
+ const result = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
82
+ expect(result.action).toBe('updated');
83
+ const written = JSON.parse(readFileSync(file, 'utf8'));
84
+ expect(written.mcpServers.hypertab.headers.Authorization).toBe('Bearer ht_sk_test');
85
+ });
86
+ it('only creates the backup on first touch (not on subsequent updates)', () => {
87
+ const file = join(dir, 'mcp.json');
88
+ writeFileSync(file, JSON.stringify({ mcpServers: {} }, null, 2));
89
+ const first = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
90
+ expect(first.backupCreated).toBe(true);
91
+ const second = writePlatformConfig({
92
+ platform: tmpPlatform(file),
93
+ scope: 'user',
94
+ entry: { ...ENTRY, url: 'https://api.hypertab.ai/mcp/v2' },
95
+ });
96
+ expect(second.action).toBe('updated');
97
+ expect(second.backupCreated).toBe(false);
98
+ });
99
+ it('creates parent directories if missing', () => {
100
+ const file = join(dir, 'nested', 'deep', 'mcp.json');
101
+ const result = writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
102
+ expect(result.action).toBe('created');
103
+ expect(existsSync(file)).toBe(true);
104
+ });
105
+ it('preserves other top-level keys in the config file', () => {
106
+ const file = join(dir, 'mcp.json');
107
+ writeFileSync(file, JSON.stringify({ theme: 'dark', version: 2, mcpServers: { other: { command: 'x' } } }, null, 2));
108
+ writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY });
109
+ const written = JSON.parse(readFileSync(file, 'utf8'));
110
+ expect(written.theme).toBe('dark');
111
+ expect(written.version).toBe(2);
112
+ expect(written.mcpServers.other).toEqual({ command: 'x' });
113
+ });
114
+ it('throws a helpful error on malformed JSON', () => {
115
+ const file = join(dir, 'mcp.json');
116
+ writeFileSync(file, '{ "mcpServers": { "other": }');
117
+ expect(() => writePlatformConfig({ platform: tmpPlatform(file), scope: 'user', entry: ENTRY })).toThrow(/Failed to parse existing config/);
118
+ });
119
+ });
120
+ describe('removePlatformConfig', () => {
121
+ it('removes the hypertab entry while preserving other servers', () => {
122
+ const file = join(dir, 'mcp.json');
123
+ writeFileSync(file, JSON.stringify({
124
+ mcpServers: {
125
+ other: { command: 'other-server' },
126
+ hypertab: ENTRY,
127
+ more: { type: 'http', url: 'https://x' },
128
+ },
129
+ }, null, 2));
130
+ const result = removePlatformConfig({ platform: tmpPlatform(file), scope: 'user' });
131
+ expect(result.action).toBe('removed');
132
+ expect(result.backupCreated).toBe(true);
133
+ const written = JSON.parse(readFileSync(file, 'utf8'));
134
+ expect(written.mcpServers.hypertab).toBeUndefined();
135
+ expect(written.mcpServers.other).toEqual({ command: 'other-server' });
136
+ expect(written.mcpServers.more).toEqual({ type: 'http', url: 'https://x' });
137
+ });
138
+ it('returns not-installed when hypertab was never added', () => {
139
+ const file = join(dir, 'mcp.json');
140
+ writeFileSync(file, JSON.stringify({ mcpServers: { other: { command: 'x' } } }, null, 2));
141
+ const result = removePlatformConfig({ platform: tmpPlatform(file), scope: 'user' });
142
+ expect(result.action).toBe('not-installed');
143
+ expect(result.backupCreated).toBe(false);
144
+ // File should be untouched
145
+ const written = JSON.parse(readFileSync(file, 'utf8'));
146
+ expect(written.mcpServers.other).toEqual({ command: 'x' });
147
+ });
148
+ it('returns file-missing when the config file does not exist', () => {
149
+ const file = join(dir, 'nonexistent.json');
150
+ const result = removePlatformConfig({ platform: tmpPlatform(file), scope: 'user' });
151
+ expect(result.action).toBe('file-missing');
152
+ expect(existsSync(file)).toBe(false);
153
+ });
154
+ it('leaves an empty mcpServers map rather than deleting the key', () => {
155
+ const file = join(dir, 'mcp.json');
156
+ writeFileSync(file, JSON.stringify({ mcpServers: { hypertab: ENTRY } }, null, 2));
157
+ removePlatformConfig({ platform: tmpPlatform(file), scope: 'user' });
158
+ const written = JSON.parse(readFileSync(file, 'utf8'));
159
+ expect(written.mcpServers).toEqual({});
160
+ });
161
+ it('preserves other top-level keys in the config file', () => {
162
+ const file = join(dir, 'mcp.json');
163
+ writeFileSync(file, JSON.stringify({ theme: 'dark', version: 2, mcpServers: { hypertab: ENTRY, other: { command: 'x' } } }, null, 2));
164
+ removePlatformConfig({ platform: tmpPlatform(file), scope: 'user' });
165
+ const written = JSON.parse(readFileSync(file, 'utf8'));
166
+ expect(written.theme).toBe('dark');
167
+ expect(written.version).toBe(2);
168
+ expect(written.mcpServers.other).toEqual({ command: 'x' });
169
+ expect(written.mcpServers.hypertab).toBeUndefined();
170
+ });
171
+ });
172
+ describe('stripJsonComments', () => {
173
+ it('removes single-line // comments', () => {
174
+ expect(stripJsonComments('{ "a": 1 // trailing\n, "b": 2 }')).toBe('{ "a": 1 \n, "b": 2 }');
175
+ });
176
+ it('removes block /* */ comments', () => {
177
+ expect(stripJsonComments('{ /* header */ "a": 1 }')).toBe('{ "a": 1 }');
178
+ });
179
+ it('does not strip // inside strings', () => {
180
+ expect(stripJsonComments('{ "url": "http://x.com" }')).toBe('{ "url": "http://x.com" }');
181
+ });
182
+ it('handles escaped quotes inside strings', () => {
183
+ expect(stripJsonComments('{ "msg": "a \\"b\\" //not a comment" }')).toBe('{ "msg": "a \\"b\\" //not a comment" }');
184
+ });
185
+ });
186
+ //# sourceMappingURL=config-writer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-writer.test.js","sourceRoot":"","sources":["../../src/__tests__/config-writer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,113 @@
1
+ import { Command } from 'commander';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { PLATFORM_IDS } from '../install/platforms.js';
4
+ const DEFAULT_URL = 'https://api.hypertab.ai/mcp';
5
+ /**
6
+ * Mirrors the subcommand structure in src/index.ts so we can parse args
7
+ * synchronously and assert on the opts without running any side effects.
8
+ */
9
+ function buildProgram() {
10
+ const program = new Command().name('hypertab').version('0.2.0').exitOverride().configureOutput({
11
+ writeOut: () => { },
12
+ writeErr: () => { },
13
+ });
14
+ program
15
+ .command('install')
16
+ .requiredOption('-c, --client <id>', `Target client: ${PLATFORM_IDS.join(' | ')}`)
17
+ .option('-k, --api-key <key>', 'Hypertab API key')
18
+ .option('-s, --scope <scope>', 'Config scope', 'user')
19
+ .option('-u, --url <url>', 'MCP server URL', DEFAULT_URL)
20
+ .action(() => { });
21
+ program
22
+ .command('connect')
23
+ .requiredOption('-k, --api-key <key>', 'Hypertab API key')
24
+ .option('-u, --url <url>', 'MCP server URL', DEFAULT_URL)
25
+ .option('-t, --transport <type>', 'Transport type', 'streamable-http')
26
+ .action(() => { });
27
+ return program;
28
+ }
29
+ function parseInstall(args) {
30
+ const program = buildProgram();
31
+ program.parse(['node', 'hypertab', 'install', ...args]);
32
+ const installCmd = program.commands.find((c) => c.name() === 'install');
33
+ if (!installCmd)
34
+ throw new Error('install command missing');
35
+ return installCmd.opts();
36
+ }
37
+ function parseConnect(args) {
38
+ const program = buildProgram();
39
+ program.parse(['node', 'hypertab', 'connect', ...args]);
40
+ const connectCmd = program.commands.find((c) => c.name() === 'connect');
41
+ if (!connectCmd)
42
+ throw new Error('connect command missing');
43
+ return connectCmd.opts();
44
+ }
45
+ describe('CLI structure', () => {
46
+ it('exposes install and connect subcommands', () => {
47
+ const program = buildProgram();
48
+ const names = program.commands.map((c) => c.name());
49
+ expect(names).toContain('install');
50
+ expect(names).toContain('connect');
51
+ });
52
+ });
53
+ describe('install subcommand parsing', () => {
54
+ it('requires --client', () => {
55
+ const program = buildProgram();
56
+ expect(() => program.parse(['node', 'hypertab', 'install'])).toThrow();
57
+ });
58
+ it('parses --client and --api-key', () => {
59
+ const opts = parseInstall(['-c', 'claude-code', '-k', 'ht_sk_test']);
60
+ expect(opts.client).toBe('claude-code');
61
+ expect(opts.apiKey).toBe('ht_sk_test');
62
+ });
63
+ it('defaults scope to user', () => {
64
+ const opts = parseInstall(['-c', 'cursor']);
65
+ expect(opts.scope).toBe('user');
66
+ });
67
+ it('accepts --scope project', () => {
68
+ const opts = parseInstall(['-c', 'claude-code', '--scope', 'project']);
69
+ expect(opts.scope).toBe('project');
70
+ });
71
+ it('defaults --url to the hosted MCP endpoint', () => {
72
+ const opts = parseInstall(['-c', 'claude-code']);
73
+ expect(opts.url).toBe(DEFAULT_URL);
74
+ });
75
+ it('api-key is optional (env var or prompt can provide)', () => {
76
+ // Does not throw when --api-key is omitted.
77
+ expect(() => parseInstall(['-c', 'claude-code'])).not.toThrow();
78
+ });
79
+ it('accepts every valid client id', () => {
80
+ for (const id of PLATFORM_IDS) {
81
+ const opts = parseInstall(['-c', id]);
82
+ expect(opts.client).toBe(id);
83
+ }
84
+ });
85
+ });
86
+ describe('connect subcommand parsing', () => {
87
+ it('requires --api-key', () => {
88
+ const program = buildProgram();
89
+ expect(() => program.parse(['node', 'hypertab', 'connect'])).toThrow();
90
+ });
91
+ it('parses --api-key, --url, --transport', () => {
92
+ const opts = parseConnect(['-k', 'ht_sk_test', '-u', 'https://local/mcp', '-t', 'sse']);
93
+ expect(opts.apiKey).toBe('ht_sk_test');
94
+ expect(opts.url).toBe('https://local/mcp');
95
+ expect(opts.transport).toBe('sse');
96
+ });
97
+ it('defaults transport to streamable-http', () => {
98
+ const opts = parseConnect(['-k', 'ht_sk_test']);
99
+ expect(opts.transport).toBe('streamable-http');
100
+ });
101
+ });
102
+ describe('API key format validation (unit)', () => {
103
+ it('rejects keys without ht_sk_ prefix', () => {
104
+ expect('sk_bad'.startsWith('ht_sk_')).toBe(false);
105
+ });
106
+ it('accepts valid hypertab keys', () => {
107
+ expect('ht_sk_valid'.startsWith('ht_sk_')).toBe(true);
108
+ });
109
+ it('rejects empty strings', () => {
110
+ expect(''.startsWith('ht_sk_')).toBe(false);
111
+ });
112
+ });
113
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=install.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/install.test.ts"],"names":[],"mappings":""}