@schoolai/shipyard-mcp 0.2.1 → 0.2.2-next.483
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/apps/server/dist/index.js +57 -53
- package/package.json +1 -1
|
@@ -4742,7 +4742,7 @@ var BUNDLED_DOCS = `Execute TypeScript code that calls Shipyard APIs. Use this f
|
|
|
4742
4742
|
|
|
4743
4743
|
## Available APIs
|
|
4744
4744
|
|
|
4745
|
-
### createPlan(opts): Promise<{ planId, sessionToken, url, deliverables }>
|
|
4745
|
+
### createPlan(opts): Promise<{ planId, sessionToken, url, deliverables, monitoringScript }>
|
|
4746
4746
|
Create a new plan and open it in browser.
|
|
4747
4747
|
|
|
4748
4748
|
Parameters:
|
|
@@ -4756,6 +4756,7 @@ Returns:
|
|
|
4756
4756
|
- sessionToken: Required for subsequent API calls
|
|
4757
4757
|
- url: Browser URL for the plan
|
|
4758
4758
|
- deliverables: Array of { id, text } for linking artifacts
|
|
4759
|
+
- monitoringScript: Bash script to poll for approval (for non-hook agents)
|
|
4759
4760
|
|
|
4760
4761
|
Example:
|
|
4761
4762
|
\`\`\`typescript
|
|
@@ -4763,7 +4764,10 @@ const plan = await createPlan({
|
|
|
4763
4764
|
title: "Add auth",
|
|
4764
4765
|
content: "- [ ] Screenshot of login {#deliverable}"
|
|
4765
4766
|
});
|
|
4766
|
-
// Returns: { planId: "abc", sessionToken: "xyz", url: "...", deliverables: [
|
|
4767
|
+
// Returns: { planId: "abc", sessionToken: "xyz", url: "...", deliverables: [...], monitoringScript: "#!/bin/bash..." }
|
|
4768
|
+
|
|
4769
|
+
// For non-hook agents: Run the monitoring script in background to wait for approval
|
|
4770
|
+
// bash <(echo "$monitoringScript") &
|
|
4767
4771
|
\`\`\`
|
|
4768
4772
|
|
|
4769
4773
|
---
|
|
@@ -4801,7 +4805,7 @@ data.deliverables.forEach(d => console.log(d.id, d.completed));
|
|
|
4801
4805
|
|
|
4802
4806
|
---
|
|
4803
4807
|
|
|
4804
|
-
### updatePlan(planId, sessionToken, updates): Promise<
|
|
4808
|
+
### updatePlan(planId, sessionToken, updates): Promise<{ success, monitoringScript }>
|
|
4805
4809
|
Update plan metadata.
|
|
4806
4810
|
|
|
4807
4811
|
Parameters:
|
|
@@ -4810,6 +4814,10 @@ Parameters:
|
|
|
4810
4814
|
- updates.title (string, optional): New title
|
|
4811
4815
|
- updates.status (string, optional): 'draft' | 'pending_review' | 'changes_requested' | 'in_progress'
|
|
4812
4816
|
|
|
4817
|
+
Returns:
|
|
4818
|
+
- success: Boolean indicating update succeeded
|
|
4819
|
+
- monitoringScript: Bash script to poll for approval (for non-hook agents)
|
|
4820
|
+
|
|
4813
4821
|
Note: Most status transitions are automatic. Rarely needed.
|
|
4814
4822
|
|
|
4815
4823
|
---
|
|
@@ -4900,46 +4908,6 @@ Parameters:
|
|
|
4900
4908
|
|
|
4901
4909
|
---
|
|
4902
4910
|
|
|
4903
|
-
### setupReviewNotification(planId, pollIntervalSeconds?): Promise<{ script }>
|
|
4904
|
-
Get a bash script to poll for plan approval status changes.
|
|
4905
|
-
|
|
4906
|
-
Parameters:
|
|
4907
|
-
- planId (string): Plan ID to monitor
|
|
4908
|
-
- pollIntervalSeconds (number, optional): Polling interval (default: 30)
|
|
4909
|
-
|
|
4910
|
-
Returns:
|
|
4911
|
-
- script: Bash script that polls registry server and exits when status becomes 'in_progress' (approved) or 'changes_requested' (needs work)
|
|
4912
|
-
|
|
4913
|
-
**IMPORTANT:** This is ONLY for agents WITHOUT hook support (Cursor, Devin, Windsurf, etc).
|
|
4914
|
-
Claude Code users have automatic blocking via the shipyard hook - you don't need this.
|
|
4915
|
-
|
|
4916
|
-
**Complete workflow for non-hook agents (example user code):**
|
|
4917
|
-
\`\`\`typescript
|
|
4918
|
-
// 1. Create plan and get the monitoring script in ONE code block
|
|
4919
|
-
const plan = await createPlan({
|
|
4920
|
-
title: "My Feature Implementation",
|
|
4921
|
-
content: "- [ ] Screenshot of working feature {#deliverable}"
|
|
4922
|
-
});
|
|
4923
|
-
|
|
4924
|
-
// 2. Get the polling script (returns bash script as string)
|
|
4925
|
-
const { script } = await setupReviewNotification(plan.planId, 15);
|
|
4926
|
-
|
|
4927
|
-
// 3. Return both so the agent can run the script
|
|
4928
|
-
return {
|
|
4929
|
-
planId: plan.planId,
|
|
4930
|
-
sessionToken: plan.sessionToken,
|
|
4931
|
-
monitoringScript: script,
|
|
4932
|
-
instructions: "Run the monitoring script in background: bash <script> &"
|
|
4933
|
-
};
|
|
4934
|
-
\`\`\`
|
|
4935
|
-
|
|
4936
|
-
The agent then runs the returned bash script in the background. The script will:
|
|
4937
|
-
- Poll the registry server every N seconds
|
|
4938
|
-
- Print status changes to stdout
|
|
4939
|
-
- Exit with code 0 when the plan is approved/rejected
|
|
4940
|
-
|
|
4941
|
-
---
|
|
4942
|
-
|
|
4943
4911
|
### requestUserInput(opts): Promise<{ success, response?, status, reason? }>
|
|
4944
4912
|
Request input from the user via browser modal.
|
|
4945
4913
|
|
|
@@ -5075,7 +5043,9 @@ const plan = await createPlan({
|
|
|
5075
5043
|
content: "- [ ] Screenshot {#deliverable}\\n- [ ] Video {#deliverable}"
|
|
5076
5044
|
});
|
|
5077
5045
|
|
|
5078
|
-
// plan
|
|
5046
|
+
// plan includes: planId, sessionToken, url, deliverables, monitoringScript
|
|
5047
|
+
// For non-hook agents: Run monitoringScript in background to wait for approval
|
|
5048
|
+
// The script polls and exits when human approves/rejects
|
|
5079
5049
|
|
|
5080
5050
|
// Do work, take screenshots...
|
|
5081
5051
|
|
|
@@ -5105,6 +5075,7 @@ return { planId: plan.planId, snapshotUrl: result.snapshotUrl };
|
|
|
5105
5075
|
var ExecuteCodeInput = z12.object({
|
|
5106
5076
|
code: z12.string().describe("TypeScript code to execute")
|
|
5107
5077
|
});
|
|
5078
|
+
var scriptTracker = [];
|
|
5108
5079
|
async function createPlan(opts) {
|
|
5109
5080
|
const result = await createPlanTool.handler(opts);
|
|
5110
5081
|
const text = result.content[0]?.text || "";
|
|
@@ -5115,11 +5086,16 @@ async function createPlan(opts) {
|
|
|
5115
5086
|
const allDeliverables = getDeliverables(ydoc);
|
|
5116
5087
|
deliverables = allDeliverables.map((d) => ({ id: d.id, text: d.text }));
|
|
5117
5088
|
}
|
|
5089
|
+
const { script: monitoringScript } = await setupReviewNotification(planId, 30);
|
|
5090
|
+
scriptTracker.push(`Plan "${planId}" created.
|
|
5091
|
+
|
|
5092
|
+
${monitoringScript}`);
|
|
5118
5093
|
return {
|
|
5119
5094
|
planId,
|
|
5120
5095
|
sessionToken: text.match(/Session Token: (\S+)/)?.[1] || "",
|
|
5121
5096
|
url: text.match(/URL: (\S+)/)?.[1] || "",
|
|
5122
|
-
deliverables
|
|
5097
|
+
deliverables,
|
|
5098
|
+
monitoringScript
|
|
5123
5099
|
};
|
|
5124
5100
|
}
|
|
5125
5101
|
async function readPlan(planId, sessionToken, opts) {
|
|
@@ -5149,6 +5125,14 @@ async function readPlan(planId, sessionToken, opts) {
|
|
|
5149
5125
|
}
|
|
5150
5126
|
async function updatePlan(planId, sessionToken, updates) {
|
|
5151
5127
|
await updatePlanTool.handler({ planId, sessionToken, ...updates });
|
|
5128
|
+
const { script: monitoringScript } = await setupReviewNotification(planId, 30);
|
|
5129
|
+
scriptTracker.push(`Plan "${planId}" updated.
|
|
5130
|
+
|
|
5131
|
+
${monitoringScript}`);
|
|
5132
|
+
return {
|
|
5133
|
+
success: true,
|
|
5134
|
+
monitoringScript
|
|
5135
|
+
};
|
|
5152
5136
|
}
|
|
5153
5137
|
async function addArtifact2(opts) {
|
|
5154
5138
|
const result = await addArtifactTool.handler(opts);
|
|
@@ -5335,6 +5319,7 @@ var executeCodeTool = {
|
|
|
5335
5319
|
handler: async (args) => {
|
|
5336
5320
|
const { code } = ExecuteCodeInput.parse(args);
|
|
5337
5321
|
logger.info({ codeLength: code.length }, "Executing code");
|
|
5322
|
+
scriptTracker.length = 0;
|
|
5338
5323
|
try {
|
|
5339
5324
|
async function encodeVideo(opts) {
|
|
5340
5325
|
const fps = opts.fps || 6;
|
|
@@ -5399,14 +5384,33 @@ var executeCodeTool = {
|
|
|
5399
5384
|
const script = new vm.Script(wrappedCode);
|
|
5400
5385
|
const result = await script.runInContext(context, { timeout: 12e4 });
|
|
5401
5386
|
logger.info({ result }, "Code execution complete");
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5387
|
+
const content = [
|
|
5388
|
+
{
|
|
5389
|
+
type: "text",
|
|
5390
|
+
text: typeof result === "object" ? JSON.stringify(result, null, 2) : String(result ?? "Done")
|
|
5391
|
+
}
|
|
5392
|
+
];
|
|
5393
|
+
const latestScript = scriptTracker[scriptTracker.length - 1];
|
|
5394
|
+
if (latestScript) {
|
|
5395
|
+
const [planAction, ...scriptParts] = latestScript.split("\n\n");
|
|
5396
|
+
content.push({
|
|
5397
|
+
type: "text",
|
|
5398
|
+
text: `
|
|
5399
|
+
|
|
5400
|
+
---
|
|
5401
|
+
**\u26A0\uFE0F IMPORTANT FOR NON-HOOK AGENTS (Cursor, Devin, Windsurf, etc.):**
|
|
5402
|
+
|
|
5403
|
+
${planAction} To wait for human approval before proceeding, run this monitoring script in background:
|
|
5404
|
+
|
|
5405
|
+
\`\`\`bash
|
|
5406
|
+
${scriptParts.join("\n\n")}
|
|
5407
|
+
\`\`\`
|
|
5408
|
+
|
|
5409
|
+
Save the script to a file and run: \`bash script.sh &\`
|
|
5410
|
+
The script will exit when the human approves or requests changes.`
|
|
5411
|
+
});
|
|
5412
|
+
}
|
|
5413
|
+
return { content };
|
|
5410
5414
|
} catch (error) {
|
|
5411
5415
|
logger.error({ error, code }, "Code execution failed");
|
|
5412
5416
|
const message = error instanceof Error ? error.message : "Unknown error";
|