mikser-io-mcp 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -8
- package/index.js +16 -10
- package/package.json +6 -2
- package/scripts/chatgpt.js +106 -0
- package/scripts/claude.js +122 -0
- package/scripts/index.js +57 -0
package/README.md
CHANGED
|
@@ -15,27 +15,67 @@ MCP (Model Context Protocol) substrate and tools for [mikser-io](https://github.
|
|
|
15
15
|
npm install mikser-io-mcp
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Peer dependencies: `mikser-io ^
|
|
18
|
+
Peer dependencies: `mikser-io ^9.0.0`, `zod ^4.0.0`.
|
|
19
19
|
|
|
20
20
|
## Activate
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Import the `mcp` factory and call it **first** in your mikser project's plugins array — the closure runs synchronously and creates `runtime.options.mcp` so any plugins that register tools (api, layouts, refs, vector, etc.) can gate on it at their own `onLoaded` hook:
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
25
|
// mikser.config.js
|
|
26
|
+
import { mcp } from 'mikser-io-mcp'
|
|
27
|
+
|
|
26
28
|
export default {
|
|
27
|
-
plugins: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
plugins: [
|
|
30
|
+
mcp({
|
|
31
|
+
path: '/mcp', // optional; default '/mcp' (also serves as the base for `endpoints` below)
|
|
32
|
+
endpoints: { /* … */ } // optional; same shape as the in-core era
|
|
33
|
+
}),
|
|
34
|
+
/* … your other plugins */
|
|
35
|
+
],
|
|
32
36
|
}
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
Calling `mcp()` with no options is a no-op activation — the factory runs but creates no substrate and mounts no transport. To skip MCP entirely, leave the factory call out of `plugins`.
|
|
36
40
|
|
|
37
41
|
Run mikser with `--server`; the MCP transport mounts at the configured path on the same Express server the api / preview / data plugins use.
|
|
38
42
|
|
|
43
|
+
## Register with a client
|
|
44
|
+
|
|
45
|
+
Once the plugin is installed in your mikser project, the package ships a CLI you can invoke via `npx` to connect MCP-speaking clients. Connector name + description are read automatically from the project's `package.json`.
|
|
46
|
+
|
|
47
|
+
### Claude Desktop
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx mikser-io-mcp register claude # default URL http://localhost:3001/mcp
|
|
51
|
+
npx mikser-io-mcp register claude --url http://localhost:4000/mcp # custom port
|
|
52
|
+
npx mikser-io-mcp register claude --dry-run # show what would change
|
|
53
|
+
npx mikser-io-mcp register claude --force # overwrite a different existing entry
|
|
54
|
+
npx mikser-io-mcp register claude --unregister # remove the entry
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Writes a `mcpServers` entry into Claude Desktop's per-OS config file:
|
|
58
|
+
|
|
59
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
60
|
+
- Windows: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
61
|
+
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
62
|
+
|
|
63
|
+
The entry launches `supergateway` (npx-installed on demand) as a stdio→streamable-HTTP bridge to your running mikser server. Fully quit + reopen Claude Desktop after registering.
|
|
64
|
+
|
|
65
|
+
### ChatGPT
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx mikser-io-mcp register chatgpt --url https://YOUR-TUNNEL.example/mcp
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
ChatGPT's MCP integration is server-side — OpenAI's servers connect to your MCP endpoint directly. `localhost` is unreachable; you must expose mikser via a public tunnel (`ngrok http 3001`, Cloudflare Tunnel, etc.) before running this.
|
|
72
|
+
|
|
73
|
+
The script doesn't write a file (ChatGPT has no local config). It prints the three fields (Name, Description, MCP Server URL) you paste into ChatGPT's UI: Settings → Connectors → Advanced → Developer mode → Create.
|
|
74
|
+
|
|
75
|
+
Notes:
|
|
76
|
+
- ChatGPT Developer mode + custom MCP connectors are **beta** and require a Plus / Pro / Business / Enterprise / Edu account.
|
|
77
|
+
- Connectors don't auto-enable per chat — toggle on each new conversation.
|
|
78
|
+
|
|
39
79
|
## Documentation
|
|
40
80
|
|
|
41
81
|
- [Full MCP tour, twelve worked scenarios, every tool and resource](./documentation/mcp.md)
|
package/index.js
CHANGED
|
@@ -655,20 +655,25 @@ function pinoLevelNumber(name) {
|
|
|
655
655
|
// endpoints: { ... } // same shape as the previous mcp.endpoints
|
|
656
656
|
// }
|
|
657
657
|
//
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
|
|
658
|
+
// Presence in the plugins array IS the activation signal. The `mcp`
|
|
659
|
+
// config block is for tuning (path, endpoints, renderTimeout). When
|
|
660
|
+
// absent, defaults apply. For conditional activation, toggle the
|
|
661
|
+
// plugins array — `...(process.env.MCP ? ['mcp'] : [])` — same shape
|
|
662
|
+
// other plugins use.
|
|
663
|
+
export function mcp(options = {}) {
|
|
664
|
+
return (core) => {
|
|
662
665
|
// Use the runtime singleton imported above for substrate-internal
|
|
663
666
|
// code paths (createMcpSubstrate etc. reference it directly via
|
|
664
667
|
// closure). The factory arg `core.runtime` is the same object;
|
|
665
668
|
// they're both mikser-io's exported runtime singleton.
|
|
666
669
|
const { onLoaded, useLogger } = core
|
|
667
670
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
671
|
+
// Mirror plugin options into runtime.config.mcp so non-plugin
|
|
672
|
+
// helpers (mountMcpOnExpress and friends, called by embedders that
|
|
673
|
+
// wire MCP up directly without `plugins:`) keep finding their
|
|
674
|
+
// config there. Plugin-side reads use `options.X` and never touch
|
|
675
|
+
// runtime.config.mcp.
|
|
676
|
+
runtime.config.mcp = options
|
|
672
677
|
|
|
673
678
|
// Contribute MCP transport headers to engine's CORS arrays so
|
|
674
679
|
// browser-side MCP clients (basic-host, mcp-ui, etc.) can read
|
|
@@ -686,7 +691,7 @@ export default (core) => {
|
|
|
686
691
|
// runtime.options.mcp by the time those run. The mcp plugin MUST
|
|
687
692
|
// be FIRST in the user's plugins array for that contract to hold.
|
|
688
693
|
runtime.options.mcp = createMcpSubstrate()
|
|
689
|
-
runtime.options.mcpPath =
|
|
694
|
+
runtime.options.mcpPath = options.path ?? '/mcp'
|
|
690
695
|
|
|
691
696
|
// Compose the MCP-UI surface in the same package — shell
|
|
692
697
|
// resource, mikser_preview_ui, mikser_ui_action, mikser_preview_render,
|
|
@@ -916,7 +921,7 @@ export default (core) => {
|
|
|
916
921
|
const mcp = runtime.options.mcp
|
|
917
922
|
|
|
918
923
|
const { render: mcpRender } = useRenderer(runtime, {
|
|
919
|
-
defaultTimeout:
|
|
924
|
+
defaultTimeout: options.renderTimeout ?? 30_000,
|
|
920
925
|
})
|
|
921
926
|
|
|
922
927
|
const ok = (data) => ({
|
|
@@ -1062,4 +1067,5 @@ export default (core) => {
|
|
|
1062
1067
|
})
|
|
1063
1068
|
|
|
1064
1069
|
return { name: 'mcp' }
|
|
1070
|
+
}
|
|
1065
1071
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mikser-io-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "MCP (Model Context Protocol) substrate and tools for mikser-io. Extracted from core to iterate on its own release cadence.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mikser-io-mcp": "./scripts/index.js"
|
|
9
|
+
},
|
|
7
10
|
"files": [
|
|
8
11
|
"index.js",
|
|
9
12
|
"preview.js",
|
|
10
13
|
"public",
|
|
14
|
+
"scripts",
|
|
11
15
|
"README.md",
|
|
12
16
|
"LICENSE"
|
|
13
17
|
],
|
|
@@ -37,7 +41,7 @@
|
|
|
37
41
|
"minimatch": "^10.0.3"
|
|
38
42
|
},
|
|
39
43
|
"peerDependencies": {
|
|
40
|
-
"mikser-io": "^
|
|
44
|
+
"mikser-io": "^9.0.0",
|
|
41
45
|
"zod": "^4.0.0"
|
|
42
46
|
},
|
|
43
47
|
"devDependencies": {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// register chatgpt — print copy-paste instructions for adding mikser
|
|
2
|
+
// to ChatGPT Desktop as a custom MCP connector.
|
|
3
|
+
//
|
|
4
|
+
// ChatGPT does NOT use a local config file. Connectors live in the
|
|
5
|
+
// user's OpenAI account, configured through the UI. OpenAI's servers
|
|
6
|
+
// connect to the MCP endpoint directly, so localhost won't work — a
|
|
7
|
+
// publicly-reachable HTTPS URL is mandatory.
|
|
8
|
+
//
|
|
9
|
+
// This script can't drop a file. The most it can do is render the
|
|
10
|
+
// exact name / description / URL the user pastes into the UI.
|
|
11
|
+
|
|
12
|
+
import { readFileSync, existsSync } from 'node:fs'
|
|
13
|
+
import { resolve } from 'node:path'
|
|
14
|
+
|
|
15
|
+
function parseArgs(args) {
|
|
16
|
+
const opts = {}
|
|
17
|
+
let expectUrl = false
|
|
18
|
+
for (const a of args) {
|
|
19
|
+
if (a.startsWith('--url=')) opts.url = a.slice(6)
|
|
20
|
+
else if (a === '--url') expectUrl = true
|
|
21
|
+
else if (expectUrl) { opts.url = a; expectUrl = false }
|
|
22
|
+
}
|
|
23
|
+
return opts
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readProjectMeta() {
|
|
27
|
+
const pkgPath = resolve(process.cwd(), 'package.json')
|
|
28
|
+
if (!existsSync(pkgPath)) {
|
|
29
|
+
throw new Error(`No package.json in ${process.cwd()} — run this from inside a mikser project directory.`)
|
|
30
|
+
}
|
|
31
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
32
|
+
if (!pkg.name) throw new Error('package.json has no "name" field — set one before registering.')
|
|
33
|
+
return {
|
|
34
|
+
name: pkg.name,
|
|
35
|
+
description: pkg.description ?? `MCP connector for ${pkg.name}.`,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function runChatGPT(args) {
|
|
40
|
+
const opts = parseArgs(args)
|
|
41
|
+
|
|
42
|
+
if (!opts.url) {
|
|
43
|
+
process.stderr.write(
|
|
44
|
+
`! ChatGPT needs a publicly-reachable HTTPS URL.
|
|
45
|
+
|
|
46
|
+
OpenAI's servers connect to your MCP endpoint directly — there's no stdio
|
|
47
|
+
bridge, no localhost. You'll need to expose mikser via a tunnel first:
|
|
48
|
+
|
|
49
|
+
ngrok http 3001
|
|
50
|
+
# or:
|
|
51
|
+
cloudflared tunnel --url http://localhost:3001
|
|
52
|
+
|
|
53
|
+
Then re-run with the public URL:
|
|
54
|
+
|
|
55
|
+
npx mikser-io-mcp register chatgpt --url https://YOUR-TUNNEL.example/mcp
|
|
56
|
+
|
|
57
|
+
ChatGPT's Developer mode + custom MCP connectors are currently in BETA
|
|
58
|
+
and require a Plus / Pro / Business / Enterprise / Edu account. See
|
|
59
|
+
https://help.openai.com/en/articles/12584461 for the current state.
|
|
60
|
+
`
|
|
61
|
+
)
|
|
62
|
+
process.exit(1)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { name, description } = readProjectMeta()
|
|
66
|
+
|
|
67
|
+
process.stdout.write(
|
|
68
|
+
`✓ Connector details for "${name}"
|
|
69
|
+
|
|
70
|
+
ChatGPT doesn't have a local config file — connectors are added through
|
|
71
|
+
the UI. Copy the three fields below.
|
|
72
|
+
|
|
73
|
+
Open ChatGPT (Desktop or web) and navigate to:
|
|
74
|
+
Settings → Connectors → Advanced → Developer mode (toggle ON)
|
|
75
|
+
Click + Create
|
|
76
|
+
|
|
77
|
+
Paste these into the form:
|
|
78
|
+
|
|
79
|
+
Name: ${name}
|
|
80
|
+
Description: ${description}
|
|
81
|
+
MCP Server URL: ${opts.url}
|
|
82
|
+
Authentication: None (or your scheme of choice for production)
|
|
83
|
+
|
|
84
|
+
Click Create. Then to use it:
|
|
85
|
+
|
|
86
|
+
1. Start a NEW chat (saved connectors are off-by-default per chat)
|
|
87
|
+
2. Open the composer's Developer Mode tool picker
|
|
88
|
+
3. Enable "${name}"
|
|
89
|
+
4. Try: "Use mikser_query_entities to show me everything in this catalog"
|
|
90
|
+
|
|
91
|
+
Notes:
|
|
92
|
+
- Mikser must be running and the URL must be reachable from
|
|
93
|
+
OpenAI's servers (not just your machine).
|
|
94
|
+
- Connectors do NOT auto-enable per chat — toggle on for each new
|
|
95
|
+
conversation.
|
|
96
|
+
- Developer mode + arbitrary custom MCP connectors are BETA. Plus /
|
|
97
|
+
Pro / Business / Enterprise / Edu only; Free tier excluded.
|
|
98
|
+
- "ChatGPT Apps" is the GA but read-only variant of MCP integration;
|
|
99
|
+
this script targets the full read+write Developer mode beta.
|
|
100
|
+
|
|
101
|
+
Reference:
|
|
102
|
+
https://help.openai.com/en/articles/12584461
|
|
103
|
+
https://developers.openai.com/apps-sdk/deploy/connect-chatgpt
|
|
104
|
+
`
|
|
105
|
+
)
|
|
106
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// register claude — drop a connector entry into Claude Desktop's
|
|
2
|
+
// config file so the app picks up the local mikser server.
|
|
3
|
+
//
|
|
4
|
+
// Claude Desktop launches MCP servers as stdio subprocesses, so we
|
|
5
|
+
// register supergateway as the launcher — it bridges Claude's stdio
|
|
6
|
+
// to mikser's streamable-HTTP endpoint. The mikser server must be
|
|
7
|
+
// running for Claude to find anything.
|
|
8
|
+
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs'
|
|
10
|
+
import { homedir, platform } from 'node:os'
|
|
11
|
+
import { join, dirname, resolve } from 'node:path'
|
|
12
|
+
|
|
13
|
+
const DEFAULT_URL = 'http://localhost:3001/mcp'
|
|
14
|
+
|
|
15
|
+
function configPath() {
|
|
16
|
+
const home = homedir()
|
|
17
|
+
switch (platform()) {
|
|
18
|
+
case 'darwin': return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
|
|
19
|
+
case 'win32': return join(process.env.APPDATA ?? join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json')
|
|
20
|
+
case 'linux': return join(home, '.config', 'Claude', 'claude_desktop_config.json')
|
|
21
|
+
default: throw new Error(`register-mcp: unsupported platform "${platform()}"`)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseArgs(args) {
|
|
26
|
+
const opts = {}
|
|
27
|
+
let expectUrl = false
|
|
28
|
+
for (const a of args) {
|
|
29
|
+
if (a === '--unregister') opts.unregister = true
|
|
30
|
+
else if (a === '--dry-run') opts.dryRun = true
|
|
31
|
+
else if (a === '--force') opts.force = true
|
|
32
|
+
else if (a.startsWith('--url=')) opts.url = a.slice(6)
|
|
33
|
+
else if (a === '--url') expectUrl = true
|
|
34
|
+
else if (expectUrl) { opts.url = a; expectUrl = false }
|
|
35
|
+
}
|
|
36
|
+
return opts
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readProjectName() {
|
|
40
|
+
const pkgPath = resolve(process.cwd(), 'package.json')
|
|
41
|
+
if (!existsSync(pkgPath)) {
|
|
42
|
+
throw new Error(`No package.json in ${process.cwd()} — run this from inside a mikser project directory.`)
|
|
43
|
+
}
|
|
44
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
45
|
+
if (!pkg.name) throw new Error('package.json has no "name" field — set one before registering.')
|
|
46
|
+
return pkg.name
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function runClaude(args) {
|
|
50
|
+
const opts = parseArgs(args)
|
|
51
|
+
const name = readProjectName()
|
|
52
|
+
const url = opts.url ?? DEFAULT_URL
|
|
53
|
+
|
|
54
|
+
const entry = {
|
|
55
|
+
command: 'npx',
|
|
56
|
+
args: ['-y', 'supergateway', '--streamableHttp', url],
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const path = configPath()
|
|
60
|
+
let config = {}
|
|
61
|
+
let existed = false
|
|
62
|
+
|
|
63
|
+
if (existsSync(path)) {
|
|
64
|
+
existed = true
|
|
65
|
+
try {
|
|
66
|
+
config = JSON.parse(readFileSync(path, 'utf8'))
|
|
67
|
+
} catch (err) {
|
|
68
|
+
process.stderr.write(`! Existing Claude Desktop config at\n ${path}\nis not valid JSON. Refusing to overwrite — fix it manually first.\n Error: ${err.message}\n`)
|
|
69
|
+
process.exit(1)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
config.mcpServers = config.mcpServers || {}
|
|
74
|
+
|
|
75
|
+
// Unregister branch.
|
|
76
|
+
if (opts.unregister) {
|
|
77
|
+
if (!(name in config.mcpServers)) {
|
|
78
|
+
process.stdout.write(`✓ "${name}" is not registered. Nothing to do.\n`)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
if (opts.dryRun) {
|
|
82
|
+
process.stdout.write(`[dry-run] Would remove "${name}" from ${path}\n`)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
delete config.mcpServers[name]
|
|
86
|
+
writeFileSync(path, JSON.stringify(config, null, 2) + '\n')
|
|
87
|
+
process.stdout.write(`✓ Removed "${name}" from ${path}\n Restart Claude Desktop to apply.\n`)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Idempotent — bail if already matching.
|
|
92
|
+
const existing = config.mcpServers[name]
|
|
93
|
+
if (existing && JSON.stringify(existing) === JSON.stringify(entry)) {
|
|
94
|
+
process.stdout.write(`✓ "${name}" is already registered with the matching config.\n Nothing to change. (Use --force to re-write anyway.)\n`)
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
if (existing && !opts.force) {
|
|
98
|
+
process.stderr.write(`! "${name}" is already registered but with a different config:\n ${JSON.stringify(existing)}\n Wanted:\n ${JSON.stringify(entry)}\n Re-run with --force to overwrite.\n`)
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
if (opts.dryRun) {
|
|
102
|
+
process.stdout.write(`[dry-run] Would ${existing ? 'overwrite' : 'add'} "${name}" in ${path}:\n${JSON.stringify(entry, null, 2)}\n`)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
config.mcpServers[name] = entry
|
|
107
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
108
|
+
writeFileSync(path, JSON.stringify(config, null, 2) + '\n')
|
|
109
|
+
|
|
110
|
+
process.stdout.write(
|
|
111
|
+
`✓ Registered "${name}" in
|
|
112
|
+
${path}
|
|
113
|
+
${existed ? '(merged into existing config)' : '(created new config file)'}
|
|
114
|
+
|
|
115
|
+
Next steps:
|
|
116
|
+
1. Make sure mikser is running and reachable at ${url}
|
|
117
|
+
2. Restart Claude Desktop (fully quit, then reopen)
|
|
118
|
+
3. The mikser tools should appear in Claude's tool list
|
|
119
|
+
|
|
120
|
+
To remove: npx mikser-io-mcp register claude --unregister
|
|
121
|
+
`)
|
|
122
|
+
}
|
package/scripts/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Bin entry for mikser-io-mcp. Dispatches subcommands.
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// npx mikser-io-mcp register claude [--url URL] [--dry-run] [--force] [--unregister]
|
|
6
|
+
// npx mikser-io-mcp register chatgpt --url URL [--dry-run]
|
|
7
|
+
//
|
|
8
|
+
// Run from inside a mikser project directory — registration scripts
|
|
9
|
+
// read ./package.json for the project name (used as the connector
|
|
10
|
+
// label).
|
|
11
|
+
|
|
12
|
+
import { runClaude } from './claude.js'
|
|
13
|
+
import { runChatGPT } from './chatgpt.js'
|
|
14
|
+
|
|
15
|
+
function usage(code = 0) {
|
|
16
|
+
process.stdout.write(`mikser-io-mcp — register this project with an MCP-speaking client
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
npx mikser-io-mcp register claude [options]
|
|
20
|
+
npx mikser-io-mcp register chatgpt --url <URL>
|
|
21
|
+
|
|
22
|
+
Common options:
|
|
23
|
+
--url=<URL> MCP endpoint URL. Default for claude: http://localhost:3001/mcp.
|
|
24
|
+
REQUIRED for chatgpt (must be publicly reachable HTTPS).
|
|
25
|
+
--dry-run Show what would change without writing.
|
|
26
|
+
|
|
27
|
+
Claude-only options:
|
|
28
|
+
--unregister Remove this project's entry from Claude Desktop's config.
|
|
29
|
+
--force Overwrite an existing entry that doesn't match.
|
|
30
|
+
|
|
31
|
+
Run from inside a mikser project directory — the project's package.json
|
|
32
|
+
is read for the connector name.
|
|
33
|
+
`)
|
|
34
|
+
process.exit(code)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const [, , cmd, host, ...rest] = process.argv
|
|
38
|
+
|
|
39
|
+
if (!cmd) usage(0)
|
|
40
|
+
if (cmd === '-h' || cmd === '--help') usage(0)
|
|
41
|
+
|
|
42
|
+
if (cmd !== 'register') {
|
|
43
|
+
process.stderr.write(`Unknown command: ${cmd}\n\n`)
|
|
44
|
+
usage(1)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (host === 'claude') {
|
|
48
|
+
await runClaude(rest)
|
|
49
|
+
} else if (host === 'chatgpt') {
|
|
50
|
+
await runChatGPT(rest)
|
|
51
|
+
} else if (!host) {
|
|
52
|
+
process.stderr.write(`'register' needs a target host: claude | chatgpt\n\n`)
|
|
53
|
+
usage(1)
|
|
54
|
+
} else {
|
|
55
|
+
process.stderr.write(`Unknown host: ${host}. Supported: claude, chatgpt.\n\n`)
|
|
56
|
+
usage(1)
|
|
57
|
+
}
|