livetap 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -28,32 +28,24 @@ Then ask your agent:
28
28
 
29
29
  ## Setup with Claude Code (for AI agents)
30
30
 
31
- If you are Claude Code or another AI agent and a user asks you to install and use livetap, follow these steps exactly:
31
+ If you are Claude Code or another AI agent, run `npx livetap --llm-help` for structured setup instructions.
32
32
 
33
- ### Step 1: Install
33
+ Quick version:
34
34
 
35
35
  ```bash
36
- bun add livetap
37
- bun pm trust livetap
38
- ```
39
-
40
- The postinstall script creates `.mcp.json` in the project root. Verify it exists:
41
-
42
- ```bash
43
- cat .mcp.json
36
+ npm install livetap # Step 1: install
37
+ npx livetap setup # Step 2: creates .mcp.json
38
+ # Step 3: tell user to restart Claude Code with:
39
+ # claude --dangerously-load-development-channels server:livetap --continue
44
40
  ```
45
41
 
46
- It should contain a `livetap` MCP server entry.
47
-
48
- ### Step 2: Tell the user to restart
49
-
50
- You CANNOT restart yourself. Tell the user:
51
-
52
- > "livetap is installed. To enable live data streaming, please restart me with:
53
- > `claude --dangerously-load-development-channels server:livetap`
54
- > Then ask me to connect to your data source."
42
+ **IMPORTANT do NOT:**
43
+ - Add livetap to `~/.claude/mcp.json` — it goes in `.mcp.json` in the project root
44
+ - Configure livetap as `type: "http"` it is a stdio MCP server (command + args)
45
+ - Start the daemon manually — the MCP proxy auto-starts it on Claude restart
46
+ - Guess field names always `read_stream` first to see actual payload structure
55
47
 
56
- ### Step 3: After restart — use MCP tools
48
+ ### After restart — use MCP tools
57
49
 
58
50
  Once restarted with the channel flag, you have 12 MCP tools available. Follow this workflow:
59
51
 
package/bin/livetap.ts CHANGED
@@ -16,6 +16,7 @@ const commands: Record<string, () => Promise<void>> = {
16
16
  watch: () => import('../src/cli/watch.js').then((m) => m.run(args)),
17
17
  unwatch: () => import('../src/cli/unwatch.js').then((m) => m.run(args)),
18
18
  watchers: () => import('../src/cli/watchers.js').then((m) => m.run(args)),
19
+ setup: () => import('../src/cli/setup.js').then((m) => m.run(args)),
19
20
  mcp: () => import('../src/mcp/channel.js'),
20
21
  help: () => import('../src/cli/help.js').then((m) => m.run(args)),
21
22
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "livetap",
3
- "version": "0.1.2",
4
- "description": "Push live data streams into your AI coding agent. Connect MQTT brokers, WebSocket feeds, or tail log files.",
3
+ "version": "0.1.4",
4
+ "description": "Push live data streams into your AI coding agent. LLM/AI agent? Run: npx livetap --llm-help",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "livetap": "./bin/livetap.js"
8
8
  },
9
9
  "scripts": {
10
- "postinstall": "bun ./scripts/postinstall.ts",
11
10
  "test": "bun test"
12
11
  },
13
12
  "keywords": [
@@ -24,7 +23,6 @@
24
23
  "files": [
25
24
  "bin/",
26
25
  "src/",
27
- "scripts/postinstall.ts",
28
26
  "README.md",
29
27
  "LICENSE"
30
28
  ],
@@ -0,0 +1,70 @@
1
+ /**
2
+ * livetap setup — creates .mcp.json and prints restart instructions.
3
+ * Works with both npm and bun. Node-compatible (no bun APIs).
4
+ */
5
+
6
+ import { existsSync, readFileSync, writeFileSync } from 'fs'
7
+ import { resolve } from 'path'
8
+
9
+ export async function run(_args: string[]) {
10
+ const root = process.cwd()
11
+ const mcpPath = resolve(root, '.mcp.json')
12
+
13
+ // Find the channel.ts path relative to where livetap is installed
14
+ const channelPaths = [
15
+ resolve(root, 'node_modules', 'livetap', 'src', 'mcp', 'channel.ts'),
16
+ resolve(root, 'node_modules', '.store', 'livetap', 'src', 'mcp', 'channel.ts'),
17
+ // Local dev: running from the repo itself
18
+ resolve(root, 'src', 'mcp', 'channel.ts'),
19
+ ]
20
+
21
+ let channelPath = channelPaths.find((p) => existsSync(p))
22
+ if (!channelPath) {
23
+ // Try to resolve from require
24
+ try {
25
+ const pkg = require.resolve('livetap/package.json')
26
+ channelPath = resolve(pkg, '..', 'src', 'mcp', 'channel.ts')
27
+ if (!existsSync(channelPath)) channelPath = undefined
28
+ } catch { /* not found */ }
29
+ }
30
+
31
+ if (!channelPath) {
32
+ console.error('Error: Could not find livetap channel.ts. Is livetap installed?')
33
+ console.error('Run: npm install livetap')
34
+ process.exit(1)
35
+ }
36
+
37
+ const mcpEntry = {
38
+ livetap: {
39
+ command: 'bun',
40
+ args: [channelPath],
41
+ },
42
+ }
43
+
44
+ // Read or create .mcp.json
45
+ let config: any = {}
46
+ if (existsSync(mcpPath)) {
47
+ try {
48
+ config = JSON.parse(readFileSync(mcpPath, 'utf-8'))
49
+ } catch {
50
+ console.error('Warning: .mcp.json exists but is malformed. Overwriting.')
51
+ }
52
+ }
53
+
54
+ if (config.mcpServers?.livetap) {
55
+ console.log('✓ livetap already configured in .mcp.json')
56
+ } else {
57
+ if (!config.mcpServers) config.mcpServers = {}
58
+ config.mcpServers.livetap = mcpEntry.livetap
59
+ writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\n')
60
+ console.log('✓ .mcp.json created with livetap MCP server entry')
61
+ }
62
+
63
+ console.log('')
64
+ console.log('→ Next step: restart Claude Code with:')
65
+ console.log(' claude --dangerously-load-development-channels server:livetap --continue')
66
+ console.log('')
67
+ console.log('→ After restart, MCP tools are available. Ask Claude to:')
68
+ console.log(' "Connect to mqtt://broker.emqx.io:1883/sensors/#"')
69
+ console.log(' "Watch for temperature > 50 and summarize alerts"')
70
+ }
@@ -15,8 +15,9 @@ export function generateHelpText(): string {
15
15
  'Usage:',
16
16
  ]
17
17
 
18
- // Group: daemon, connections, sampling, watchers
18
+ // Group: setup, daemon, connections, sampling, watchers
19
19
  const groups: { label: string; commands: string[] }[] = [
20
+ { label: '', commands: ['setup'] },
20
21
  { label: '', commands: ['start', 'stop', 'status'] },
21
22
  { label: '', commands: ['tap', 'untap', 'taps'] },
22
23
  { label: '', commands: ['sip'] },
@@ -50,8 +51,23 @@ export function generateHelpText(): string {
50
51
  export function generateLlmHelp(): object {
51
52
  return {
52
53
  name: 'livetap',
53
- version: '0.1.0',
54
+ version: '0.1.4',
54
55
  description: 'Push live data streams into your AI coding agent',
56
+ setup: {
57
+ steps: [
58
+ 'Step 1: npm install livetap (skip if already installed)',
59
+ 'Step 2: npx livetap setup (creates .mcp.json in project root — do NOT create it manually)',
60
+ 'Step 3: Tell user to restart Claude Code: claude --dangerously-load-development-channels server:livetap --continue',
61
+ 'Step 4: After restart, use create_connection to connect, read_stream to sample, create_watcher to alert',
62
+ ],
63
+ do_not: [
64
+ 'Do NOT add livetap to ~/.claude/mcp.json — it goes in .mcp.json in the project root',
65
+ 'Do NOT configure livetap as type:http — it is a stdio MCP server (command + args)',
66
+ 'Do NOT start the daemon manually — the MCP proxy auto-starts it on Claude restart',
67
+ 'Do NOT guess field names — always read_stream first to see actual payload structure',
68
+ 'Do NOT use npm init — use the existing project directory',
69
+ ],
70
+ },
55
71
  commands: CLI_COMMANDS,
56
72
  mcp_tools: TOOLS,
57
73
  }
@@ -22,6 +22,12 @@ export interface CatalogCommand {
22
22
  * are generated from this array.
23
23
  */
24
24
  export const CLI_COMMANDS: CatalogCommand[] = [
25
+ // --- Setup ---
26
+ {
27
+ name: 'setup',
28
+ usage: 'livetap setup',
29
+ description: 'Configure .mcp.json for Claude Code and print restart instructions. Run this after npm install.',
30
+ },
25
31
  // --- Daemon ---
26
32
  {
27
33
  name: 'start',
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * Postinstall script — auto-configures .mcp.json for Claude Code.
4
- * Runs after `bun add livetap` or `npm install livetap`.
5
- */
6
-
7
- import { existsSync, readFileSync, writeFileSync } from 'fs'
8
- import { resolve } from 'path'
9
-
10
- const MCP_ENTRY = {
11
- livetap: {
12
- command: 'bun',
13
- args: [resolve(import.meta.dir, '..', 'src', 'mcp', 'channel.ts')],
14
- },
15
- }
16
-
17
- function findProjectRoot(): string {
18
- // If we're inside node_modules, walk up past it to find the project root
19
- const scriptDir = resolve(import.meta.dir)
20
- const nmIdx = scriptDir.lastIndexOf('node_modules')
21
- if (nmIdx !== -1) {
22
- const root = scriptDir.slice(0, nmIdx).replace(/\/$/, '')
23
- if (existsSync(resolve(root, 'package.json'))) return root
24
- }
25
- // Fallback to cwd (e.g. when running postinstall directly for testing)
26
- return process.cwd()
27
- }
28
-
29
- function run() {
30
- // Skip in CI or when explicitly disabled
31
- if (process.env.CI || process.env.LIVETAP_SKIP_POSTINSTALL) return
32
-
33
- const root = findProjectRoot()
34
- const mcpPath = resolve(root, '.mcp.json')
35
-
36
- let config: any = {}
37
- if (existsSync(mcpPath)) {
38
- try {
39
- config = JSON.parse(readFileSync(mcpPath, 'utf-8'))
40
- } catch {
41
- console.warn('\n ⚠ .mcp.json exists but is malformed. Skipping auto-config.')
42
- console.warn(' Add the livetap entry manually (see below).\n')
43
- printManualInstructions()
44
- return
45
- }
46
- }
47
-
48
- // Don't overwrite if livetap entry already exists
49
- if (config.mcpServers?.livetap) {
50
- console.log('\n ✓ livetap already configured in .mcp.json\n')
51
- printRestartInstructions()
52
- return
53
- }
54
-
55
- // Add livetap entry
56
- if (!config.mcpServers) config.mcpServers = {}
57
- config.mcpServers.livetap = MCP_ENTRY.livetap
58
- writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\n')
59
-
60
- console.log('\n ✓ livetap added to .mcp.json\n')
61
- printRestartInstructions()
62
- }
63
-
64
- function printRestartInstructions() {
65
- console.log(' To enable live data streaming in Claude Code, restart with:\n')
66
- console.log(' claude --dangerously-load-development-channels server:livetap\n')
67
- console.log(' Then ask Claude: "Connect to mqtt://broker.emqx.io:1883/sensors/#"\n')
68
- }
69
-
70
- function printManualInstructions() {
71
- console.log(' Add to .mcp.json:\n')
72
- console.log(' ' + JSON.stringify({ mcpServers: MCP_ENTRY }, null, 2).split('\n').join('\n ') + '\n')
73
- }
74
-
75
- run()