shotops-mcp 0.9.0 → 0.9.1
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/dist/local.js +24 -3
- package/package.json +1 -1
package/dist/local.js
CHANGED
|
@@ -10375,7 +10375,7 @@ var init_package = __esm({
|
|
|
10375
10375
|
"package.json"() {
|
|
10376
10376
|
package_default = {
|
|
10377
10377
|
name: "shotops-mcp",
|
|
10378
|
-
version: "0.9.
|
|
10378
|
+
version: "0.9.1",
|
|
10379
10379
|
private: false,
|
|
10380
10380
|
type: "module",
|
|
10381
10381
|
description: "The bundle-emitting MCP server over the @engine/@sync spine. Exposes ShotOps tools to ChatGPT, Claude Code, Cursor, and CI over Streamable HTTP with OAuth or personal API tokens. Hosted and MCP tool paths never accept, store, or forward a store-signing credential; the explicit local release CLI validates the user's existing key directly with Apple and records only its path. Renders via headless Playwright Chromium, the engine's native non-browser habitat (same path as mockup-mcp). Also ships as a free LOCAL stdio server (`npx shotops-mcp`) \u2014 same render, on your own machine, no account needed.",
|
|
@@ -15543,7 +15543,17 @@ var init_controlPlaneContract = __esm({
|
|
|
15543
15543
|
function controlPlaneUrl() {
|
|
15544
15544
|
return (process.env.SHOTOPS_CONTROL_PLANE_URL || DEFAULT_CONTROL_PLANE_URL).replace(/\/+$/, "");
|
|
15545
15545
|
}
|
|
15546
|
-
|
|
15546
|
+
function retryAfterMs(res, attempt) {
|
|
15547
|
+
const header = res.headers.get("retry-after");
|
|
15548
|
+
if (header) {
|
|
15549
|
+
const seconds = Number(header);
|
|
15550
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, 3e4);
|
|
15551
|
+
const at = Date.parse(header);
|
|
15552
|
+
if (Number.isFinite(at)) return Math.min(Math.max(at - Date.now(), 0), 3e4);
|
|
15553
|
+
}
|
|
15554
|
+
return Math.min(1e3 * 2 ** attempt, 8e3);
|
|
15555
|
+
}
|
|
15556
|
+
async function callOp(token, op, args = {}, attempt = 0) {
|
|
15547
15557
|
const res = await fetch(controlPlaneUrl(), {
|
|
15548
15558
|
method: "POST",
|
|
15549
15559
|
headers: {
|
|
@@ -15564,6 +15574,15 @@ async function callOp(token, op, args = {}) {
|
|
|
15564
15574
|
if (res.status === 401) {
|
|
15565
15575
|
throw new Error("control plane rejected the token \u2014 check SHOTOPS_TOKEN, or mint a new one in ShotOps.");
|
|
15566
15576
|
}
|
|
15577
|
+
if (res.status === 429) {
|
|
15578
|
+
if (attempt < RATE_LIMIT_RETRIES) {
|
|
15579
|
+
await sleep(retryAfterMs(res, attempt));
|
|
15580
|
+
return await callOp(token, op, args, attempt + 1);
|
|
15581
|
+
}
|
|
15582
|
+
throw new Error(
|
|
15583
|
+
`ShotOps is refusing new requests right now (429 after ${RATE_LIMIT_RETRIES + 1} attempts). This is upstream load shedding, not your account or your token \u2014 wait a minute and run it again. A long multi-panel render is the usual trigger.`
|
|
15584
|
+
);
|
|
15585
|
+
}
|
|
15567
15586
|
if (res.status === 426) {
|
|
15568
15587
|
const minimum = parsed?.minimumVersion;
|
|
15569
15588
|
const floor = typeof minimum === "string" && minimum.length > 0 ? ` (${minimum} or newer)` : "";
|
|
@@ -15725,7 +15744,7 @@ function connectHostedBridge(token) {
|
|
|
15725
15744
|
}
|
|
15726
15745
|
};
|
|
15727
15746
|
}
|
|
15728
|
-
var DEFAULT_CONTROL_PLANE_URL, MAX_PASS_BODY_BYTES, ControlPlaneOperationError;
|
|
15747
|
+
var DEFAULT_CONTROL_PLANE_URL, MAX_PASS_BODY_BYTES, ControlPlaneOperationError, RATE_LIMIT_RETRIES, sleep;
|
|
15729
15748
|
var init_hostedBridge = __esm({
|
|
15730
15749
|
"src/hostedBridge.ts"() {
|
|
15731
15750
|
"use strict";
|
|
@@ -15750,6 +15769,8 @@ var init_hostedBridge = __esm({
|
|
|
15750
15769
|
this.requiredPlan = typeof body?.requiredPlan === "string" ? body.requiredPlan : null;
|
|
15751
15770
|
}
|
|
15752
15771
|
};
|
|
15772
|
+
RATE_LIMIT_RETRIES = 3;
|
|
15773
|
+
sleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
15753
15774
|
}
|
|
15754
15775
|
});
|
|
15755
15776
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shotops-mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The bundle-emitting MCP server over the @engine/@sync spine. Exposes ShotOps tools to ChatGPT, Claude Code, Cursor, and CI over Streamable HTTP with OAuth or personal API tokens. Hosted and MCP tool paths never accept, store, or forward a store-signing credential; the explicit local release CLI validates the user's existing key directly with Apple and records only its path. Renders via headless Playwright Chromium, the engine's native non-browser habitat (same path as mockup-mcp). Also ships as a free LOCAL stdio server (`npx shotops-mcp`) — same render, on your own machine, no account needed.",
|