@mimeticinc/mim-cli 0.1.0 → 0.1.2

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.
@@ -0,0 +1,220 @@
1
+ import {
2
+ defaultMimProject,
3
+ loadMimConfig,
4
+ mimApiBaseUrl,
5
+ mimAuthToken,
6
+ normalizeMimApiBaseUrl,
7
+ trackMimUsageEvent
8
+ } from "./chunk-RXBIMVUG.js";
9
+
10
+ // src/mim-mcp-stdio.ts
11
+ import { randomUUID } from "crypto";
12
+ import { pathToFileURL } from "url";
13
+ function mimMcpUsage() {
14
+ return `mim-mcp
15
+
16
+ Proxies MCP stdio requests to TryMimetic growth context.
17
+
18
+ Usage:
19
+ mim-mcp --project my-site
20
+ mim-mcp --url https://trymimetic.com/api/mim/mcp --project my-site
21
+
22
+ Environment:
23
+ MIM_API_TOKEN Mimetic API token. Defaults to credentials from \`mim auth login\`.
24
+ MIM_API_BASE_URL TryMimetic API origin. Default: https://trymimetic.com.
25
+ MIM_MCP_URL Full MCP endpoint. Default: MIM_API_BASE_URL + /api/mim/mcp.
26
+ MIM_PROJECT Default project/site key.
27
+ MIM_MCP_TIMEOUT_MS Request timeout. Default: 30000.
28
+ `;
29
+ }
30
+ function readValue(args, index, flag) {
31
+ const value = args[index + 1];
32
+ if (!value || value.startsWith("-")) throw new Error(`${flag} requires a value`);
33
+ return [value, index + 1];
34
+ }
35
+ function normalizeMcpUrl(value, source) {
36
+ return normalizeMimApiBaseUrl(value, source);
37
+ }
38
+ function parseMimMcpOptions(args = process.argv.slice(2), env = process.env) {
39
+ const config = loadMimConfig(env);
40
+ let apiBaseUrl = mimApiBaseUrl(config, env);
41
+ let mcpUrl = env.MIM_MCP_URL?.trim() || "";
42
+ let project = defaultMimProject(config, env);
43
+ let token = mimAuthToken(config, env);
44
+ let timeoutMs = Number(env.MIM_MCP_TIMEOUT_MS || "30000");
45
+ for (let i = 0; i < args.length; i += 1) {
46
+ const arg = args[i];
47
+ if (arg === "--url" || arg === "--mcp-url") {
48
+ const [value, next] = readValue(args, i, arg);
49
+ mcpUrl = value;
50
+ i = next;
51
+ } else if (arg === "--api-base-url") {
52
+ const [value, next] = readValue(args, i, arg);
53
+ apiBaseUrl = normalizeMimApiBaseUrl(value, arg);
54
+ i = next;
55
+ } else if (arg === "--project") {
56
+ const [value, next] = readValue(args, i, arg);
57
+ project = value;
58
+ i = next;
59
+ } else if (arg === "--token") {
60
+ const [value, next] = readValue(args, i, arg);
61
+ token = value;
62
+ i = next;
63
+ } else if (arg === "--timeout-ms") {
64
+ const [value, next] = readValue(args, i, arg);
65
+ timeoutMs = Number(value);
66
+ i = next;
67
+ } else if (arg === "-h" || arg === "--help") {
68
+ process.stdout.write(mimMcpUsage());
69
+ process.exit(0);
70
+ } else {
71
+ throw new Error(`unknown mim-mcp option: ${arg}`);
72
+ }
73
+ }
74
+ if (!token) throw new Error("Mimetic auth is required; run `mim auth login` or set MIM_API_TOKEN");
75
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) throw new Error("--timeout-ms must be a positive integer");
76
+ return {
77
+ apiBaseUrl,
78
+ mcpUrl: mcpUrl ? normalizeMcpUrl(mcpUrl, "MIM_MCP_URL") : `${apiBaseUrl}/api/mim/mcp`,
79
+ token,
80
+ project,
81
+ timeoutMs,
82
+ traceId: randomUUID()
83
+ };
84
+ }
85
+ function jsonRpcError(id, code, message) {
86
+ return JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
87
+ }
88
+ function requestId(payload) {
89
+ if (Array.isArray(payload)) return null;
90
+ if (payload && typeof payload === "object" && "id" in payload) {
91
+ return payload.id ?? null;
92
+ }
93
+ return null;
94
+ }
95
+ function toolName(payload) {
96
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return "";
97
+ const request = payload;
98
+ if (request.method !== "tools/call" || !request.params || typeof request.params !== "object") return "";
99
+ const name = request.params.name;
100
+ return typeof name === "string" ? name : "";
101
+ }
102
+ async function fetchWithTimeout(fetchImpl, url, init, timeoutMs) {
103
+ const controller = new AbortController();
104
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
105
+ try {
106
+ return await fetchImpl(url, { ...init, signal: controller.signal });
107
+ } finally {
108
+ clearTimeout(timeout);
109
+ }
110
+ }
111
+ async function proxyMimMcpMessage(raw, options, fetchImpl = fetch) {
112
+ const line = raw.trim();
113
+ if (!line) return null;
114
+ let payload;
115
+ try {
116
+ payload = JSON.parse(line);
117
+ } catch {
118
+ return jsonRpcError(null, -32700, "parse error");
119
+ }
120
+ const started = Date.now();
121
+ const tool = toolName(payload);
122
+ let status = "success";
123
+ let httpStatus = 200;
124
+ try {
125
+ const response = await fetchWithTimeout(
126
+ fetchImpl,
127
+ options.mcpUrl,
128
+ {
129
+ method: "POST",
130
+ headers: {
131
+ accept: "application/json",
132
+ authorization: `Bearer ${options.token}`,
133
+ "content-type": "application/json",
134
+ "x-mim-client": "mim-mcp",
135
+ "x-mim-client-version": "0.1.0",
136
+ "x-mim-trace-id": options.traceId,
137
+ ...options.project ? { "x-mim-project": options.project } : {}
138
+ },
139
+ body: JSON.stringify(payload)
140
+ },
141
+ options.timeoutMs
142
+ );
143
+ httpStatus = response.status;
144
+ const text = await response.text();
145
+ if (!response.ok) {
146
+ status = "error";
147
+ const message = response.status === 401 || response.status === 403 ? "Mimetic MCP authentication failed" : `Mimetic MCP HTTP request failed with ${response.status}`;
148
+ return jsonRpcError(requestId(payload), -32e3, message);
149
+ }
150
+ if (!text.trim()) return null;
151
+ return JSON.stringify(JSON.parse(text));
152
+ } catch (error) {
153
+ status = "error";
154
+ const message = error instanceof Error && error.name === "AbortError" ? "Mimetic MCP request timed out" : "Mimetic MCP request failed";
155
+ return jsonRpcError(requestId(payload), -32e3, message);
156
+ } finally {
157
+ if (tool || payload && typeof payload === "object" && !Array.isArray(payload)) {
158
+ await trackMimUsageEvent(
159
+ { apiBaseUrl: options.apiBaseUrl, token: options.token, traceId: options.traceId },
160
+ {
161
+ event: "mcp_request",
162
+ client: "mim-mcp",
163
+ project: options.project || void 0,
164
+ tool: tool || void 0,
165
+ status,
166
+ duration_ms: Date.now() - started,
167
+ metadata: {
168
+ method: !Array.isArray(payload) && payload && typeof payload === "object" ? payload.method : "batch",
169
+ http_status: httpStatus
170
+ }
171
+ },
172
+ fetchImpl
173
+ );
174
+ }
175
+ }
176
+ }
177
+ function runMimMcpStdio(options = parseMimMcpOptions()) {
178
+ process.stdin.setEncoding("utf8");
179
+ let buffer = "";
180
+ let chain = Promise.resolve();
181
+ const handleLine = (line) => {
182
+ chain = chain.then(async () => {
183
+ const response = await proxyMimMcpMessage(line, options);
184
+ if (response) process.stdout.write(`${response}
185
+ `);
186
+ }).catch((error) => {
187
+ process.stderr.write(`mim-mcp: ${error instanceof Error ? error.message : "request failed"}
188
+ `);
189
+ });
190
+ };
191
+ process.stdin.on("data", (chunk) => {
192
+ buffer += chunk;
193
+ let newline = buffer.indexOf("\n");
194
+ while (newline !== -1) {
195
+ const line = buffer.slice(0, newline).replace(/\r$/, "");
196
+ buffer = buffer.slice(newline + 1);
197
+ handleLine(line);
198
+ newline = buffer.indexOf("\n");
199
+ }
200
+ });
201
+ process.stdin.on("end", () => {
202
+ if (buffer.trim()) handleLine(buffer);
203
+ });
204
+ }
205
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
206
+ try {
207
+ runMimMcpStdio();
208
+ } catch (error) {
209
+ process.stderr.write(`mim-mcp: ${error instanceof Error ? error.message : "startup failed"}
210
+ `);
211
+ process.exit(1);
212
+ }
213
+ }
214
+
215
+ export {
216
+ mimMcpUsage,
217
+ parseMimMcpOptions,
218
+ proxyMimMcpMessage,
219
+ runMimMcpStdio
220
+ };
@@ -999,13 +999,13 @@ function claudeMcpInstallCommand(project) {
999
999
  "npx",
1000
1000
  "-y",
1001
1001
  "--package",
1002
- "@mimeticinc/rerun",
1002
+ "@mimeticinc/mim-cli",
1003
1003
  "mim-mcp",
1004
1004
  ...project ? ["--project", project] : []
1005
1005
  ];
1006
1006
  }
1007
1007
  function codexMcpConfig(project) {
1008
- const args = ["-y", "--package", "@mimeticinc/rerun", "mim-mcp", ...project ? ["--project", project] : []];
1008
+ const args = ["-y", "--package", "@mimeticinc/mim-cli", "mim-mcp", ...project ? ["--project", project] : []];
1009
1009
  return `[mcp_servers.mim]
1010
1010
  command = "npx"
1011
1011
  args = ${JSON.stringify(args)}
package/dist/mim-bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  mimMain
4
- } from "./chunk-BE3RRPTQ.js";
4
+ } from "./chunk-RXBIMVUG.js";
5
5
 
6
6
  // src/mim-bin.ts
7
7
  mimMain().catch((error) => {
package/dist/mim-cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  saveMimConfig,
22
22
  shouldSendMimTelemetry,
23
23
  trackMimUsageEvent
24
- } from "./chunk-BE3RRPTQ.js";
24
+ } from "./chunk-RXBIMVUG.js";
25
25
  export {
26
26
  buildMimUsageEvent,
27
27
  claudeMcpInstallCommand,
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runMimMcpStdio
4
+ } from "./chunk-CQR3GJV6.js";
5
+ import "./chunk-RXBIMVUG.js";
6
+
7
+ // src/mim-mcp-bin.ts
8
+ try {
9
+ runMimMcpStdio();
10
+ } catch (error) {
11
+ process.stderr.write(`mim-mcp: ${error instanceof Error ? error.message : "startup failed"}
12
+ `);
13
+ process.exit(1);
14
+ }
@@ -1,217 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- defaultMimProject,
4
- loadMimConfig,
5
- mimApiBaseUrl,
6
- mimAuthToken,
7
- normalizeMimApiBaseUrl,
8
- trackMimUsageEvent
9
- } from "./chunk-BE3RRPTQ.js";
10
-
11
- // src/mim-mcp-stdio.ts
12
- import { randomUUID } from "crypto";
13
- import { pathToFileURL } from "url";
14
- function mimMcpUsage() {
15
- return `mim-mcp
16
-
17
- Proxies MCP stdio requests to TryMimetic growth context.
18
-
19
- Usage:
20
- mim-mcp --project my-site
21
- mim-mcp --url https://trymimetic.com/api/mim/mcp --project my-site
22
-
23
- Environment:
24
- MIM_API_TOKEN Mimetic API token. Defaults to credentials from \`mim auth login\`.
25
- MIM_API_BASE_URL TryMimetic API origin. Default: https://trymimetic.com.
26
- MIM_MCP_URL Full MCP endpoint. Default: MIM_API_BASE_URL + /api/mim/mcp.
27
- MIM_PROJECT Default project/site key.
28
- MIM_MCP_TIMEOUT_MS Request timeout. Default: 30000.
29
- `;
30
- }
31
- function readValue(args, index, flag) {
32
- const value = args[index + 1];
33
- if (!value || value.startsWith("-")) throw new Error(`${flag} requires a value`);
34
- return [value, index + 1];
35
- }
36
- function normalizeMcpUrl(value, source) {
37
- return normalizeMimApiBaseUrl(value, source);
38
- }
39
- function parseMimMcpOptions(args = process.argv.slice(2), env = process.env) {
40
- const config = loadMimConfig(env);
41
- let apiBaseUrl = mimApiBaseUrl(config, env);
42
- let mcpUrl = env.MIM_MCP_URL?.trim() || "";
43
- let project = defaultMimProject(config, env);
44
- let token = mimAuthToken(config, env);
45
- let timeoutMs = Number(env.MIM_MCP_TIMEOUT_MS || "30000");
46
- for (let i = 0; i < args.length; i += 1) {
47
- const arg = args[i];
48
- if (arg === "--url" || arg === "--mcp-url") {
49
- const [value, next] = readValue(args, i, arg);
50
- mcpUrl = value;
51
- i = next;
52
- } else if (arg === "--api-base-url") {
53
- const [value, next] = readValue(args, i, arg);
54
- apiBaseUrl = normalizeMimApiBaseUrl(value, arg);
55
- i = next;
56
- } else if (arg === "--project") {
57
- const [value, next] = readValue(args, i, arg);
58
- project = value;
59
- i = next;
60
- } else if (arg === "--token") {
61
- const [value, next] = readValue(args, i, arg);
62
- token = value;
63
- i = next;
64
- } else if (arg === "--timeout-ms") {
65
- const [value, next] = readValue(args, i, arg);
66
- timeoutMs = Number(value);
67
- i = next;
68
- } else if (arg === "-h" || arg === "--help") {
69
- process.stdout.write(mimMcpUsage());
70
- process.exit(0);
71
- } else {
72
- throw new Error(`unknown mim-mcp option: ${arg}`);
73
- }
74
- }
75
- if (!token) throw new Error("Mimetic auth is required; run `mim auth login` or set MIM_API_TOKEN");
76
- if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) throw new Error("--timeout-ms must be a positive integer");
77
- return {
78
- apiBaseUrl,
79
- mcpUrl: mcpUrl ? normalizeMcpUrl(mcpUrl, "MIM_MCP_URL") : `${apiBaseUrl}/api/mim/mcp`,
80
- token,
81
- project,
82
- timeoutMs,
83
- traceId: randomUUID()
84
- };
85
- }
86
- function jsonRpcError(id, code, message) {
87
- return JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
88
- }
89
- function requestId(payload) {
90
- if (Array.isArray(payload)) return null;
91
- if (payload && typeof payload === "object" && "id" in payload) {
92
- return payload.id ?? null;
93
- }
94
- return null;
95
- }
96
- function toolName(payload) {
97
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) return "";
98
- const request = payload;
99
- if (request.method !== "tools/call" || !request.params || typeof request.params !== "object") return "";
100
- const name = request.params.name;
101
- return typeof name === "string" ? name : "";
102
- }
103
- async function fetchWithTimeout(fetchImpl, url, init, timeoutMs) {
104
- const controller = new AbortController();
105
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
106
- try {
107
- return await fetchImpl(url, { ...init, signal: controller.signal });
108
- } finally {
109
- clearTimeout(timeout);
110
- }
111
- }
112
- async function proxyMimMcpMessage(raw, options, fetchImpl = fetch) {
113
- const line = raw.trim();
114
- if (!line) return null;
115
- let payload;
116
- try {
117
- payload = JSON.parse(line);
118
- } catch {
119
- return jsonRpcError(null, -32700, "parse error");
120
- }
121
- const started = Date.now();
122
- const tool = toolName(payload);
123
- let status = "success";
124
- let httpStatus = 200;
125
- try {
126
- const response = await fetchWithTimeout(
127
- fetchImpl,
128
- options.mcpUrl,
129
- {
130
- method: "POST",
131
- headers: {
132
- accept: "application/json",
133
- authorization: `Bearer ${options.token}`,
134
- "content-type": "application/json",
135
- "x-mim-client": "mim-mcp",
136
- "x-mim-client-version": "0.1.0",
137
- "x-mim-trace-id": options.traceId,
138
- ...options.project ? { "x-mim-project": options.project } : {}
139
- },
140
- body: JSON.stringify(payload)
141
- },
142
- options.timeoutMs
143
- );
144
- httpStatus = response.status;
145
- const text = await response.text();
146
- if (!response.ok) {
147
- status = "error";
148
- const message = response.status === 401 || response.status === 403 ? "Mimetic MCP authentication failed" : `Mimetic MCP HTTP request failed with ${response.status}`;
149
- return jsonRpcError(requestId(payload), -32e3, message);
150
- }
151
- if (!text.trim()) return null;
152
- return JSON.stringify(JSON.parse(text));
153
- } catch (error) {
154
- status = "error";
155
- const message = error instanceof Error && error.name === "AbortError" ? "Mimetic MCP request timed out" : "Mimetic MCP request failed";
156
- return jsonRpcError(requestId(payload), -32e3, message);
157
- } finally {
158
- if (tool || payload && typeof payload === "object" && !Array.isArray(payload)) {
159
- await trackMimUsageEvent(
160
- { apiBaseUrl: options.apiBaseUrl, token: options.token, traceId: options.traceId },
161
- {
162
- event: "mcp_request",
163
- client: "mim-mcp",
164
- project: options.project || void 0,
165
- tool: tool || void 0,
166
- status,
167
- duration_ms: Date.now() - started,
168
- metadata: {
169
- method: !Array.isArray(payload) && payload && typeof payload === "object" ? payload.method : "batch",
170
- http_status: httpStatus
171
- }
172
- },
173
- fetchImpl
174
- );
175
- }
176
- }
177
- }
178
- function runMimMcpStdio(options = parseMimMcpOptions()) {
179
- process.stdin.setEncoding("utf8");
180
- let buffer = "";
181
- let chain = Promise.resolve();
182
- const handleLine = (line) => {
183
- chain = chain.then(async () => {
184
- const response = await proxyMimMcpMessage(line, options);
185
- if (response) process.stdout.write(`${response}
186
- `);
187
- }).catch((error) => {
188
- process.stderr.write(`mim-mcp: ${error instanceof Error ? error.message : "request failed"}
189
- `);
190
- });
191
- };
192
- process.stdin.on("data", (chunk) => {
193
- buffer += chunk;
194
- let newline = buffer.indexOf("\n");
195
- while (newline !== -1) {
196
- const line = buffer.slice(0, newline).replace(/\r$/, "");
197
- buffer = buffer.slice(newline + 1);
198
- handleLine(line);
199
- newline = buffer.indexOf("\n");
200
- }
201
- });
202
- process.stdin.on("end", () => {
203
- if (buffer.trim()) handleLine(buffer);
204
- });
205
- }
206
- if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
207
- try {
208
- runMimMcpStdio();
209
- } catch (error) {
210
- process.stderr.write(`mim-mcp: ${error instanceof Error ? error.message : "startup failed"}
211
- `);
212
- process.exit(1);
213
- }
214
- }
3
+ mimMcpUsage,
4
+ parseMimMcpOptions,
5
+ proxyMimMcpMessage,
6
+ runMimMcpStdio
7
+ } from "./chunk-CQR3GJV6.js";
8
+ import "./chunk-RXBIMVUG.js";
215
9
  export {
216
10
  mimMcpUsage,
217
11
  parseMimMcpOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mimeticinc/mim-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Mimetic CLI — growth context for Claude Code, Codex, and shell workflows",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "bin": {
25
25
  "mim": "dist/mim-bin.js",
26
- "mim-mcp": "dist/mim-mcp-stdio.js"
26
+ "mim-mcp": "dist/mim-mcp-bin.js"
27
27
  },
28
28
  "engines": {
29
29
  "node": ">=20"