replicas-mcp 0.2.9 → 0.2.10
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/index.js +143 -40
- package/package.json +1 -1
- package/src/index.ts +6 -2
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ The CLI is the canonical surface. Chat transcripts that show \`DISPLAY=:99 xdoto
|
|
|
61
61
|
\`\`\`bash
|
|
62
62
|
# DO
|
|
63
63
|
replicas computer key Return
|
|
64
|
-
replicas computer
|
|
64
|
+
replicas computer observe /tmp/state.png
|
|
65
65
|
|
|
66
66
|
# DON'T
|
|
67
67
|
DISPLAY=:99 xdotool key Return
|
|
@@ -79,9 +79,9 @@ replicas computer info
|
|
|
79
79
|
# 2) Launch a browser on the workspace display.
|
|
80
80
|
replicas computer launch chrome https://news.ycombinator.com
|
|
81
81
|
|
|
82
|
-
# 3)
|
|
83
|
-
replicas computer
|
|
84
|
-
|
|
82
|
+
# 3) Observe the settled screen and browser tab state before clicking.
|
|
83
|
+
replicas computer observe /tmp/state.png
|
|
84
|
+
replicas computer browser --snapshot
|
|
85
85
|
|
|
86
86
|
# 4) Drive the UI.
|
|
87
87
|
replicas computer click 521 700 # click coordinates from the screenshot
|
|
@@ -102,16 +102,39 @@ Prints the live noVNC viewer URL (\`https://6080-<hash>.tryreplicas.com/\`) for
|
|
|
102
102
|
If invoked very early in the workspace lifecycle, \`info\` will poll briefly while the engine finishes registering the preview, then error if it's still not available.
|
|
103
103
|
|
|
104
104
|
### \`replicas computer status\`
|
|
105
|
-
|
|
105
|
+
Checks and repairs the desktop bridge, then prints which desktop services are running and the active preview URL (if any). Useful for debugging when a tool call seems to be doing nothing.
|
|
106
106
|
|
|
107
|
-
### \`replicas computer screenshot <path
|
|
108
|
-
Captures the current desktop to a PNG at the given path.
|
|
107
|
+
### \`replicas computer screenshot <path> [--raw] [--grid [px]]\`
|
|
108
|
+
Captures the current desktop to a PNG at the given path.
|
|
109
|
+
|
|
110
|
+
Use \`--raw\` for a 1:1 desktop capture with no branding, padding, or rounded corners. Use \`--grid\` for the same 1:1 capture plus a coordinate grid; the optional value sets grid spacing in pixels and defaults to 100. Use the default branded screenshot only when you plan to share the image with \`replicas media upload\`.
|
|
111
|
+
|
|
112
|
+
### \`replicas computer observe <path> [--raw] [--grid [px]] [--timeout MS] [--stable-ms MS] [--poll-ms MS]\`
|
|
113
|
+
Waits briefly for the screen to stop changing, saves a 1:1 screenshot, and prints JSON with screen dimensions, whether the screen stabilized, frame/change counts, mouse location, active window title, and visible window titles.
|
|
114
|
+
|
|
115
|
+
Use this instead of hand-written \`sleep && screenshot\` loops after clicks, navigation, typing, or page loads. By default it saves a 100px coordinate-grid screenshot and waits up to 3s for 600ms of visual stability. Pass \`--raw\` if you need an unannotated 1:1 screenshot.
|
|
116
|
+
|
|
117
|
+
### \`replicas computer browser\`
|
|
118
|
+
Prints JSON for Chrome tabs launched through Replicas, including page titles and URLs. Pass \`--snapshot\` to include visible page text and interactive controls with DOM viewport bounding boxes.
|
|
119
|
+
|
|
120
|
+
Use this alongside \`observe\` when testing web apps so you do not infer navigation, page state, or click targets from pixels alone. Snapshot coordinates are DOM viewport coordinates, not desktop click coordinates.
|
|
121
|
+
|
|
122
|
+
### \`replicas computer browser-click <text> [--exact] [--index N]\`
|
|
123
|
+
Clicks the first visible Chrome control whose text, label, placeholder, or href matches \`<text>\`. Use this for web buttons and links found via \`browser --snapshot\`; it is faster and less error-prone than converting DOM coordinates to desktop pixels.
|
|
124
|
+
|
|
125
|
+
### \`replicas computer browser-fill <field> <value> [--exact] [--index N]\`
|
|
126
|
+
Fills the first visible Chrome field whose label, placeholder, name, or text matches \`<field>\`, then dispatches input/change events. Use this for web forms instead of clicking a field and typing through the desktop.
|
|
127
|
+
|
|
128
|
+
### \`replicas computer browser-wait <text> [--mode any|text|title|url|control] [--exact] [--timeout MS]\`
|
|
129
|
+
Waits until the active Chrome page matches text in the title, URL, body text, or visible controls. Use this after \`browser-click\` / \`browser-fill\` when you need web app state to settle without screenshot polling.
|
|
130
|
+
|
|
131
|
+
For \`browser-click\`, \`browser-fill\`, and \`browser-wait\`, pass \`--id <id>\`, \`--title <text>\`, \`--url <text>\`, or \`--page <n>\` when multiple Chrome tabs are open. Run \`replicas computer browser\` first to list tabs. Prefer \`--id\` when a click may change the page title or URL.
|
|
109
132
|
|
|
110
133
|
### \`replicas computer click <x> <y> [--button N] [--double] [--modifiers ctrl+shift]\`
|
|
111
|
-
Move to (x, y) and click. Default is left-click (button 1); pass \`--button 3\` for right-click. \`--modifiers\` holds keys during the click (e.g. ctrl-click a link to open in a new tab).
|
|
134
|
+
Move to (x, y) and click. Coordinates can be absolute pixels or percentages such as \`50%\` \`50%\`. Default is left-click (button 1); pass \`--button 3\` for right-click. \`--modifiers\` holds keys during the click (e.g. ctrl-click a link to open in a new tab).
|
|
112
135
|
|
|
113
136
|
### \`replicas computer move <x> <y>\`
|
|
114
|
-
Move the mouse without clicking. Useful for hovering tooltips.
|
|
137
|
+
Move the mouse without clicking. Coordinates can be absolute pixels or percentages. Useful for hovering tooltips.
|
|
115
138
|
|
|
116
139
|
### \`replicas computer type <text> [--delay MS]\`
|
|
117
140
|
Type a literal string into the focused field. Default per-character delay is 12ms (~80 wpm) - feels human and avoids breaking apps that debounce input. Bump \`--delay 30\` for stricter apps.
|
|
@@ -122,10 +145,10 @@ For key combos (not literal text), use \`key\`. \`type "ctrl+l"\` will literally
|
|
|
122
145
|
Press a single key or combo. Examples: \`Return\`, \`Escape\`, \`Tab\`, \`ctrl+l\`, \`ctrl+shift+t\`, \`alt+Left\`, \`Page_Down\`, \`Home\`. Syntax matches \`xdotool key\`.
|
|
123
146
|
|
|
124
147
|
### \`replicas computer scroll <up|down|left|right> [--amount N] [--x X --y Y]\`
|
|
125
|
-
Scroll the wheel. Pass \`--x\` / \`--y\` to hover before scrolling (otherwise scrolls wherever the cursor currently is). Default amount is 3 wheel ticks.
|
|
148
|
+
Scroll the wheel. Pass \`--x\` / \`--y\` to hover before scrolling (otherwise scrolls wherever the cursor currently is). Hover coordinates can be absolute pixels or percentages. Default amount is 3 wheel ticks.
|
|
126
149
|
|
|
127
150
|
### \`replicas computer drag <fromX> <fromY> <toX> <toY>\`
|
|
128
|
-
Press left mouse at (fromX, fromY), drag to (toX, toY), release. For things like dragging a file onto an upload zone.
|
|
151
|
+
Press left mouse at (fromX, fromY), drag to (toX, toY), release. Coordinates can be absolute pixels or percentages. For things like dragging a file onto an upload zone.
|
|
129
152
|
|
|
130
153
|
### \`replicas computer launch <app> [args...]\`
|
|
131
154
|
Spawns an app on the workspace display. Built-in aliases:
|
|
@@ -148,31 +171,37 @@ SIGINTs ffmpeg, waits for it to finalize the MP4, prints the output path. Upload
|
|
|
148
171
|
|
|
149
172
|
## Patterns
|
|
150
173
|
|
|
151
|
-
### Action /
|
|
152
|
-
You are blind between tool calls. After any action that changes the screen,
|
|
174
|
+
### Action / observe loop
|
|
175
|
+
You are blind between tool calls. After any action that changes the screen, observe before deciding the next coordinate:
|
|
153
176
|
|
|
154
177
|
\`\`\`bash
|
|
155
178
|
replicas computer click 521 700
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
# read /tmp/after-click.png, decide next click
|
|
179
|
+
replicas computer observe /tmp/after-click.png
|
|
180
|
+
# read /tmp/after-click.png and the JSON output, decide next click
|
|
159
181
|
\`\`\`
|
|
160
182
|
|
|
161
|
-
\`
|
|
183
|
+
The JSON \`stable\`, \`frames\`, and \`changes\` fields tell you whether something changed while you were waiting. If \`stable\` is false, observe again or increase \`--timeout\` before acting on coordinates.
|
|
162
184
|
|
|
163
185
|
### Typing into an address bar
|
|
164
186
|
\`\`\`bash
|
|
165
187
|
replicas computer launch chrome
|
|
166
|
-
|
|
167
|
-
replicas computer key ctrl+l
|
|
188
|
+
replicas computer observe /tmp/browser-open.png
|
|
189
|
+
replicas computer key ctrl+l
|
|
168
190
|
replicas computer type "https://example.com"
|
|
169
191
|
replicas computer key Return
|
|
170
|
-
|
|
171
|
-
replicas computer
|
|
192
|
+
replicas computer observe /tmp/loaded.png
|
|
193
|
+
replicas computer browser --snapshot
|
|
194
|
+
replicas computer browser-fill "Search" "replicas"
|
|
195
|
+
replicas computer browser-click "More information" --title "Example"
|
|
196
|
+
replicas computer browser-wait "Example Domain" --mode title --title "Example"
|
|
172
197
|
\`\`\`
|
|
173
198
|
|
|
174
199
|
### Coordinates from screenshots
|
|
175
|
-
The display is 1920\xD71080 by default.
|
|
200
|
+
The display is 1920\xD71080 by default. For click planning, use \`observe\`, \`screenshot --raw\`, or \`screenshot --grid\`; those pixels map 1:1 to click coordinates. If the grid/raw screenshot shows a button at pixel (520, 700), click \`replicas computer click 520 700\`. The default screenshot is branded for sharing and has padding around the desktop, so do not use it for coordinates.
|
|
201
|
+
|
|
202
|
+
Use percentages for broad, layout-relative targets when exact pixels are unnecessary: \`replicas computer click 50% 50%\` clicks the center of the screen, and \`replicas computer move 95% 5%\` moves near the top-right.
|
|
203
|
+
|
|
204
|
+
Modern image-reading models often imagine the screenshot is at a different resolution. Trust the dimensions printed by \`observe\`, \`replicas computer screenshot ... --raw\` / \`--grid\`, and the \`xdpyinfo\` value shown by \`replicas computer status\`.
|
|
176
205
|
|
|
177
206
|
### Letting the user watch
|
|
178
207
|
The Desktop tab is already live in the dashboard - the user can open it any time. If you're communicating with the user somewhere else (Slack, PR comment, etc.), grab the URL with \`replicas computer info\` and share it inline so they can watch you work.
|
|
@@ -190,8 +219,8 @@ Then embed the printed \`\` line in your chat reply. See \`MEDI
|
|
|
190
219
|
## Failure modes
|
|
191
220
|
|
|
192
221
|
- **"Desktop services script missing"**: workspace image is older than this skill. Tell the user - nothing you can do from the CLI side.
|
|
193
|
-
- **\`xdotool ... failed: Can't open display\`**: Xvfb didn't come up. \`replicas computer status\` will show which service is dead
|
|
194
|
-
- **Browser doesn't appear after \`launch chrome\`**:
|
|
222
|
+
- **\`xdotool ... failed: Can't open display\`**: Xvfb didn't come up. \`replicas computer status\` will show which service is dead and auto-repair the desktop bridge.
|
|
223
|
+
- **Browser doesn't appear after \`launch chrome\`**: run \`replicas computer observe /tmp/state.png\`. Chrome cold-start on the virtual display takes ~500ms but bigger pages take longer.
|
|
195
224
|
- **Live preview shows static / black screen**: the browser may have crashed. \`replicas computer status\` should show no Chrome process - re-launch.
|
|
196
225
|
- **\`replicas computer info\` errors with "not registered"**: engine couldn't register the preview at startup (transient monolith error, or warming mode). Re-running the engine usually fixes it. Until it's registered, the Desktop tab will show a placeholder.
|
|
197
226
|
|
|
@@ -1355,6 +1384,7 @@ replicas automation create ... --disabled
|
|
|
1355
1384
|
|
|
1356
1385
|
# Workspace lifecycle
|
|
1357
1386
|
replicas automation create ... --lifecycle delete_when_done
|
|
1387
|
+
replicas automation create ... --lifecycle sleep_when_done
|
|
1358
1388
|
replicas automation create ... --lifecycle delete_after_inactivity --auto-stop-minutes 30
|
|
1359
1389
|
\`\`\`
|
|
1360
1390
|
|
|
@@ -2377,6 +2407,11 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
2377
2407
|
const toolCallMap = /* @__PURE__ */ new Map();
|
|
2378
2408
|
const taskMessageMap = /* @__PURE__ */ new Map();
|
|
2379
2409
|
const partialIndexes = /* @__PURE__ */ new Map();
|
|
2410
|
+
const completedStreamIds = /* @__PURE__ */ new Set();
|
|
2411
|
+
const supersededStreamIds = /* @__PURE__ */ new Set();
|
|
2412
|
+
let liveStreamId = null;
|
|
2413
|
+
const assistantThinking = /* @__PURE__ */ new Map();
|
|
2414
|
+
const assistantTextCounts = /* @__PURE__ */ new Map();
|
|
2380
2415
|
const taskAccumulator = new TaskAccumulator();
|
|
2381
2416
|
const taskSnapshot = () => taskAccumulator.getTasks().map((task) => ({
|
|
2382
2417
|
text: task.subject,
|
|
@@ -2387,6 +2422,10 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
2387
2422
|
if (event.type === CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE) {
|
|
2388
2423
|
const payload = coerceClaudePartialMessagePayload(event.payload);
|
|
2389
2424
|
if (!payload) return;
|
|
2425
|
+
if (liveStreamId !== null && liveStreamId !== payload.streamId) {
|
|
2426
|
+
supersededStreamIds.add(liveStreamId);
|
|
2427
|
+
}
|
|
2428
|
+
liveStreamId = payload.streamId;
|
|
2390
2429
|
const existing = partialIndexes.get(payload.streamId) ?? {};
|
|
2391
2430
|
if (payload.thinking) {
|
|
2392
2431
|
const reasoningMessage = {
|
|
@@ -2449,23 +2488,51 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
2449
2488
|
if (event.type === "claude-assistant") {
|
|
2450
2489
|
const messageId = event.payload.message?.id;
|
|
2451
2490
|
const contentBlocks = normalizeContentBlocks(event.payload.message?.content);
|
|
2452
|
-
|
|
2491
|
+
const messageKey = messageId || event.timestamp;
|
|
2492
|
+
const streamRefs = messageId ? partialIndexes.get(messageId) : void 0;
|
|
2493
|
+
if (messageId) {
|
|
2494
|
+
completedStreamIds.add(messageId);
|
|
2495
|
+
if (liveStreamId !== null && liveStreamId !== messageId) {
|
|
2496
|
+
supersededStreamIds.add(liveStreamId);
|
|
2497
|
+
}
|
|
2498
|
+
liveStreamId = null;
|
|
2499
|
+
}
|
|
2500
|
+
const thinkingBlocks = contentBlocks.flatMap(
|
|
2501
|
+
(block) => block.type === "thinking" && typeof block.thinking === "string" ? [block.thinking] : []
|
|
2502
|
+
);
|
|
2503
|
+
if (thinkingBlocks.length > 0) {
|
|
2504
|
+
const allThinking = [...assistantThinking.get(messageKey) ?? [], ...thinkingBlocks];
|
|
2505
|
+
assistantThinking.set(messageKey, allThinking);
|
|
2506
|
+
const reasoningMessage = {
|
|
2507
|
+
id: `reasoning-${messageKey}-thinking`,
|
|
2508
|
+
type: "reasoning",
|
|
2509
|
+
content: allThinking.join("\n\n"),
|
|
2510
|
+
status: "completed",
|
|
2511
|
+
timestamp: event.timestamp
|
|
2512
|
+
};
|
|
2513
|
+
if (streamRefs?.reasoning !== void 0) {
|
|
2514
|
+
messages[streamRefs.reasoning] = reasoningMessage;
|
|
2515
|
+
streamRefs.reasoning = void 0;
|
|
2516
|
+
} else {
|
|
2517
|
+
upsertDisplayMessage(messages, reasoningMessage);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
contentBlocks.forEach((block) => {
|
|
2453
2521
|
if (block.type === "text" && block.text) {
|
|
2454
|
-
|
|
2455
|
-
|
|
2522
|
+
const textIndex = assistantTextCounts.get(messageKey) ?? 0;
|
|
2523
|
+
assistantTextCounts.set(messageKey, textIndex + 1);
|
|
2524
|
+
const agentMessage = {
|
|
2525
|
+
id: `agent-${messageKey}-${textIndex}`,
|
|
2456
2526
|
type: "agent",
|
|
2457
2527
|
content: block.text,
|
|
2458
2528
|
timestamp: event.timestamp
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
status: "completed",
|
|
2467
|
-
timestamp: event.timestamp
|
|
2468
|
-
});
|
|
2529
|
+
};
|
|
2530
|
+
if (streamRefs?.agent !== void 0) {
|
|
2531
|
+
messages[streamRefs.agent] = agentMessage;
|
|
2532
|
+
streamRefs.agent = void 0;
|
|
2533
|
+
} else {
|
|
2534
|
+
upsertDisplayMessage(messages, agentMessage);
|
|
2535
|
+
}
|
|
2469
2536
|
}
|
|
2470
2537
|
if (block.type === "tool_use" && block.id) {
|
|
2471
2538
|
const toolName = block.name || "unknown";
|
|
@@ -2737,7 +2804,14 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
2737
2804
|
}
|
|
2738
2805
|
}
|
|
2739
2806
|
});
|
|
2740
|
-
|
|
2807
|
+
const staleIndexes = /* @__PURE__ */ new Set();
|
|
2808
|
+
for (const streamId of [...completedStreamIds, ...supersededStreamIds]) {
|
|
2809
|
+
const refs = partialIndexes.get(streamId);
|
|
2810
|
+
if (refs?.reasoning !== void 0) staleIndexes.add(refs.reasoning);
|
|
2811
|
+
if (refs?.agent !== void 0) staleIndexes.add(refs.agent);
|
|
2812
|
+
}
|
|
2813
|
+
if (staleIndexes.size === 0) return messages;
|
|
2814
|
+
return messages.filter((_, index) => !staleIndexes.has(index));
|
|
2741
2815
|
}
|
|
2742
2816
|
|
|
2743
2817
|
// ../shared/src/display-message/parsers/codex-asp-parser.ts
|
|
@@ -2757,6 +2831,34 @@ function parseAgentEvents(events, agentType) {
|
|
|
2757
2831
|
return parseClaudeEvents(events);
|
|
2758
2832
|
}
|
|
2759
2833
|
|
|
2834
|
+
// ../shared/src/routes/workspaces.ts
|
|
2835
|
+
var WORKSPACE_STATUSES = ["active", "sleeping", "archived", "preparing", "error"];
|
|
2836
|
+
var VALID_LIFECYCLE_POLICIES = ["default", "delete_when_done", "sleep_when_done", "delete_after_inactivity"];
|
|
2837
|
+
var WORKSPACE_FILE_UPLOAD_MAX_SIZE_BYTES = 20 * 1024 * 1024;
|
|
2838
|
+
var WORKSPACE_FILE_CONTENT_MAX_SIZE_BYTES = 1 * 1024 * 1024;
|
|
2839
|
+
var WORKSPACE_STATUS_FILTERS = WORKSPACE_STATUSES.map((status) => status === "error" ? "failed" : status);
|
|
2840
|
+
var WORKSPACE_SORT_CHOICES = [
|
|
2841
|
+
["activity", "Last activity"],
|
|
2842
|
+
["created", "Created date"],
|
|
2843
|
+
["status", "Status"]
|
|
2844
|
+
];
|
|
2845
|
+
var WORKSPACE_SORT_OPTIONS = WORKSPACE_SORT_CHOICES.map(([option]) => option);
|
|
2846
|
+
var WORKSPACE_SORT_LABELS = Object.fromEntries(WORKSPACE_SORT_CHOICES);
|
|
2847
|
+
var WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES = [
|
|
2848
|
+
["chronological", "Chronological"],
|
|
2849
|
+
["environments", "Environments"],
|
|
2850
|
+
["recent", "Recent environments"]
|
|
2851
|
+
];
|
|
2852
|
+
var WORKSPACE_SIDEBAR_ORGANIZATIONS = WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES.map(([organization]) => organization);
|
|
2853
|
+
var WORKSPACE_SIDEBAR_ORGANIZATION_LABELS = Object.fromEntries(WORKSPACE_SIDEBAR_ORGANIZATION_CHOICES);
|
|
2854
|
+
var DEFAULT_STATUS_FILTERS = [...WORKSPACE_STATUS_FILTERS];
|
|
2855
|
+
var DEFAULT_WORKSPACE_FILTERS = {
|
|
2856
|
+
statuses: [...DEFAULT_STATUS_FILTERS],
|
|
2857
|
+
ownerIds: [],
|
|
2858
|
+
activity: "any"
|
|
2859
|
+
};
|
|
2860
|
+
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2861
|
+
|
|
2760
2862
|
// src/index.ts
|
|
2761
2863
|
var API_URL = process.env.REPLICAS_API_URL || "https://api.tryreplicas.com";
|
|
2762
2864
|
var API_KEY = process.env.REPLICAS_API_KEY;
|
|
@@ -2790,12 +2892,13 @@ function result(data, isError = false) {
|
|
|
2790
2892
|
}
|
|
2791
2893
|
var server = new McpServer({
|
|
2792
2894
|
name: "replicas-mcp",
|
|
2793
|
-
version: "0.2.
|
|
2895
|
+
version: "0.2.10"
|
|
2794
2896
|
});
|
|
2795
2897
|
var registerTool = server.registerTool.bind(server);
|
|
2796
2898
|
var codingAgentSchema = z.string().refine(isValidCodingAgentProvider, {
|
|
2797
2899
|
message: `Coding agent must be ${getCodingAgentDisplayNames()}`
|
|
2798
2900
|
});
|
|
2901
|
+
var lifecyclePolicySchema = z.enum(VALID_LIFECYCLE_POLICIES);
|
|
2799
2902
|
registerTool(
|
|
2800
2903
|
"create_replica",
|
|
2801
2904
|
{
|
|
@@ -2807,7 +2910,7 @@ registerTool(
|
|
|
2807
2910
|
repository_set_id: z.string().optional().describe("Repository set ID to use. Mutually exclusive with repository_ids."),
|
|
2808
2911
|
coding_agent: codingAgentSchema.optional().describe("Coding agent to use (default: claude)"),
|
|
2809
2912
|
model: z.string().optional().describe("Model to use for the coding agent"),
|
|
2810
|
-
lifecycle_policy:
|
|
2913
|
+
lifecycle_policy: lifecyclePolicySchema.optional().describe("Lifecycle policy for the workspace")
|
|
2811
2914
|
}
|
|
2812
2915
|
},
|
|
2813
2916
|
async (args) => {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -14,6 +14,9 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
type ReadReplicaHistoryResponse,
|
|
16
16
|
} from '../../shared/src/routes/replica';
|
|
17
|
+
import {
|
|
18
|
+
VALID_LIFECYCLE_POLICIES,
|
|
19
|
+
} from '../../shared/src/routes/workspaces';
|
|
17
20
|
|
|
18
21
|
const API_URL = process.env.REPLICAS_API_URL || 'https://api.tryreplicas.com';
|
|
19
22
|
const API_KEY = process.env.REPLICAS_API_KEY;
|
|
@@ -68,13 +71,14 @@ type RegisterToolFn = (
|
|
|
68
71
|
|
|
69
72
|
const server = new McpServer({
|
|
70
73
|
name: 'replicas-mcp',
|
|
71
|
-
version: '0.2.
|
|
74
|
+
version: '0.2.10',
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
const registerTool = server.registerTool.bind(server) as RegisterToolFn;
|
|
75
78
|
const codingAgentSchema = z.string().refine(isValidCodingAgentProvider, {
|
|
76
79
|
message: `Coding agent must be ${getCodingAgentDisplayNames()}`,
|
|
77
80
|
});
|
|
81
|
+
const lifecyclePolicySchema = z.enum(VALID_LIFECYCLE_POLICIES);
|
|
78
82
|
|
|
79
83
|
// ---------------------------------------------------------------------------
|
|
80
84
|
// Replica CRUD
|
|
@@ -91,7 +95,7 @@ registerTool(
|
|
|
91
95
|
repository_set_id: z.string().optional().describe('Repository set ID to use. Mutually exclusive with repository_ids.'),
|
|
92
96
|
coding_agent: codingAgentSchema.optional().describe('Coding agent to use (default: claude)'),
|
|
93
97
|
model: z.string().optional().describe('Model to use for the coding agent'),
|
|
94
|
-
lifecycle_policy:
|
|
98
|
+
lifecycle_policy: lifecyclePolicySchema.optional().describe('Lifecycle policy for the workspace'),
|
|
95
99
|
},
|
|
96
100
|
},
|
|
97
101
|
async (args) => {
|