fetchsandbox-mcp 0.3.4 → 0.3.6
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 +40 -17
- package/dist/tools/run_workflow.d.ts +8 -0
- package/dist/tools/run_workflow.js +23 -2
- package/dist/tools/run_workflow.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# fetchsandbox-mcp
|
|
2
2
|
|
|
3
|
+
<a href="https://www.producthunt.com/products/fetchsandbox?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-fetchsandbox" target="_blank" rel="noopener noreferrer"><img alt="FetchSandbox - Runnable API integrations for developers and AI agents | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1175731&theme=light"></a>
|
|
4
|
+
|
|
5
|
+
|
|
3
6
|
Turn any OpenAPI spec into a working sandbox your AI agent can use, right from your IDE.
|
|
4
7
|
|
|
5
8
|
This is the Model Context Protocol (MCP) server for [FetchSandbox](https://fetchsandbox.com). It exposes three tools that let any MCP-compatible agent ingest an OpenAPI spec, list its workflows, and run them — with realistic, schema-validated responses for every endpoint.
|
|
@@ -131,39 +134,59 @@ If your agent speaks MCP, it accepts a stdio command. Use:
|
|
|
131
134
|
|
|
132
135
|
## Try it now
|
|
133
136
|
|
|
134
|
-
After restarting your agent, paste any of these prompts.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
After restarting your agent, paste any of these prompts. Every prompt
|
|
138
|
+
starts with the `./fetchsandbox` dispatch prefix — that's the routing
|
|
139
|
+
signal. The brain matches your symptom to a workflow + scenario,
|
|
140
|
+
reproduces it deterministically, and returns a public receipt URL as
|
|
141
|
+
proof. **Variant prefixes also accepted:** `/fetchsandbox`,
|
|
142
|
+
`@fetchsandbox`, `fs:`.
|
|
137
143
|
|
|
138
|
-
|
|
144
|
+
### Stripe — investigate a webhook bug
|
|
139
145
|
|
|
140
|
-
|
|
146
|
+
> `./fetchsandbox stripe webhook bug in prod — payments getting marked paid 2-3 times. fix it with proof.`
|
|
141
147
|
|
|
142
|
-
|
|
148
|
+
The brain matches the `webhook_duplicate_side_effect` pattern. The
|
|
149
|
+
agent reproduces the bug via `accept_payment` + `webhook_retries`
|
|
150
|
+
scenario, applies the fix from the brain's `fix_pattern`, re-runs to
|
|
151
|
+
confirm, and surfaces the brain's `check_for` items as the audit list.
|
|
152
|
+
Receipt URL is the proof artifact.
|
|
143
153
|
|
|
144
|
-
|
|
154
|
+
### Stripe — silent card decline
|
|
145
155
|
|
|
146
|
-
|
|
156
|
+
> `./fetchsandbox stripe checkout fails silently when cards are declined — investigate and fix.`
|
|
147
157
|
|
|
148
|
-
|
|
158
|
+
Brain matches `card_decline_not_handled` → reproduces via
|
|
159
|
+
`payment_declined` scenario → recommends the wrap-in-try/except fix
|
|
160
|
+
pattern with `decline_code` surfacing.
|
|
149
161
|
|
|
150
|
-
|
|
162
|
+
### Stripe — webhook signature security
|
|
151
163
|
|
|
152
|
-
|
|
164
|
+
> `./fetchsandbox stripe webhook security audit failed — anyone can post to the endpoint. fix it.`
|
|
153
165
|
|
|
154
|
-
|
|
166
|
+
Brain matches `webhook_signature_unverified` → reproduces via
|
|
167
|
+
`auth_failure` scenario → recommends the `stripe.Webhook.construct_event`
|
|
168
|
+
fix with `STRIPE_WEBHOOK_SECRET` env sourcing.
|
|
155
169
|
|
|
156
|
-
|
|
170
|
+
### Build a new integration
|
|
157
171
|
|
|
158
|
-
>
|
|
172
|
+
> `./fetchsandbox help me integrate resend for transactional email`
|
|
159
173
|
|
|
160
|
-
|
|
174
|
+
Brain surfaces Resend's discovery questions (SPF/DKIM, bounce
|
|
175
|
+
handling, etc.), routes to the right send-email workflow, and walks
|
|
176
|
+
the implementation against a curated Resend sandbox.
|
|
161
177
|
|
|
162
178
|
### Any other API
|
|
163
179
|
|
|
164
|
-
>
|
|
180
|
+
> `./fetchsandbox <your question or bug report about any API>`
|
|
165
181
|
|
|
166
|
-
For
|
|
182
|
+
For Stripe, Resend, Clerk, Privy, Surge, AgentMail, Twilio, PayPal,
|
|
183
|
+
Paddle, GitHub, OpenAI, Pinecone, Datadog, and 19 others, the brain
|
|
184
|
+
routes via curated knowledge. For specs we don't have curated configs
|
|
185
|
+
for, the engine auto-enumerates `create + verify` workflows for every
|
|
186
|
+
detected resource. Honest about what it shows: UUIDs instead of
|
|
187
|
+
vendor-style IDs, generic enum values instead of API-specific ones —
|
|
188
|
+
but the request/response shape and template substitution between steps
|
|
189
|
+
still work.
|
|
167
190
|
|
|
168
191
|
## Tools
|
|
169
192
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface RunWorkflowInput {
|
|
2
2
|
sandbox_id: string;
|
|
3
3
|
workflow_name: string;
|
|
4
|
+
scenario?: string;
|
|
4
5
|
}
|
|
5
6
|
interface BackendStepResult {
|
|
6
7
|
name?: string;
|
|
@@ -18,6 +19,9 @@ export interface NormalizedRunResult {
|
|
|
18
19
|
steps_passed: number;
|
|
19
20
|
steps_total: number;
|
|
20
21
|
steps: BackendStepResult[];
|
|
22
|
+
share_url?: string;
|
|
23
|
+
flow_run_id?: string;
|
|
24
|
+
sandbox_id?: string;
|
|
21
25
|
}
|
|
22
26
|
export declare const runWorkflowTool: {
|
|
23
27
|
readonly name: "run_workflow";
|
|
@@ -33,6 +37,10 @@ export declare const runWorkflowTool: {
|
|
|
33
37
|
readonly type: "string";
|
|
34
38
|
readonly description: string;
|
|
35
39
|
};
|
|
40
|
+
readonly scenario: {
|
|
41
|
+
readonly type: "string";
|
|
42
|
+
readonly description: string;
|
|
43
|
+
};
|
|
36
44
|
};
|
|
37
45
|
readonly required: readonly ["sandbox_id", "workflow_name"];
|
|
38
46
|
readonly additionalProperties: false;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { postJson, ToolError } from "../client.js";
|
|
2
2
|
export const runWorkflowTool = {
|
|
3
3
|
name: "run_workflow",
|
|
4
|
-
description: "Execute ONE specific workflow by name and return its step-by-step trace
|
|
4
|
+
description: "Execute ONE specific workflow by name and return its step-by-step trace " +
|
|
5
|
+
"PLUS a `share_url` — a public, replayable proof URL that renders the " +
|
|
6
|
+
"full timeline (every request, response, webhook event) for this run. " +
|
|
7
|
+
"The share_url is the canonical 'here's what happened' artifact: surface " +
|
|
8
|
+
"it verbatim in any reply that needs evidence (PR comments, Slack " +
|
|
9
|
+
"threads, blog posts, X replies). Do NOT substitute a docs URL or any " +
|
|
10
|
+
"other link as the proof — the share_url is the only valid receipt. " +
|
|
5
11
|
"Use ONLY when the user explicitly names a single workflow to run (e.g., " +
|
|
6
12
|
"\"run accept_payment\", \"just check the refund workflow\"). For ANY " +
|
|
7
13
|
"validation-style request — \"validate stripe\", \"check coverage\", \"run " +
|
|
@@ -22,6 +28,14 @@ export const runWorkflowTool = {
|
|
|
22
28
|
description: "Workflow id or name from list_workflows. Case-insensitive; dashes and " +
|
|
23
29
|
"underscores are interchangeable.",
|
|
24
30
|
},
|
|
31
|
+
scenario: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "OPTIONAL failure scenario to exercise (e.g. payment_declined, " +
|
|
34
|
+
"insufficient_funds, fraud_hold). Toggles the sandbox engine's " +
|
|
35
|
+
"scenario for the duration of the run, then restores. Use this for " +
|
|
36
|
+
"'test with declined card' / 'simulate failure X' intents. Omit " +
|
|
37
|
+
"for the happy path.",
|
|
38
|
+
},
|
|
25
39
|
},
|
|
26
40
|
required: ["sandbox_id", "workflow_name"],
|
|
27
41
|
additionalProperties: false,
|
|
@@ -33,7 +47,11 @@ export async function runRunWorkflow(input) {
|
|
|
33
47
|
if (!input.workflow_name)
|
|
34
48
|
throw new ToolError("workflow_name is required.");
|
|
35
49
|
const path = `/api/sandboxes/${encodeURIComponent(input.sandbox_id)}/workflows/${encodeURIComponent(input.workflow_name)}/run`;
|
|
36
|
-
const
|
|
50
|
+
const body = {};
|
|
51
|
+
if (input.scenario && input.scenario.trim()) {
|
|
52
|
+
body.scenario = input.scenario.trim();
|
|
53
|
+
}
|
|
54
|
+
const raw = await postJson(path, body);
|
|
37
55
|
const steps = raw.steps ?? [];
|
|
38
56
|
const passedSteps = steps.filter((s) => s.status === "passed").length;
|
|
39
57
|
return {
|
|
@@ -44,6 +62,9 @@ export async function runRunWorkflow(input) {
|
|
|
44
62
|
steps_passed: passedSteps,
|
|
45
63
|
steps_total: steps.length,
|
|
46
64
|
steps,
|
|
65
|
+
share_url: raw.share_url,
|
|
66
|
+
flow_run_id: raw.flow_run_id,
|
|
67
|
+
sandbox_id: raw.sandbox_id ?? input.sandbox_id,
|
|
47
68
|
};
|
|
48
69
|
}
|
|
49
70
|
//# sourceMappingURL=run_workflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run_workflow.js","sourceRoot":"","sources":["../../src/tools/run_workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"run_workflow.js","sourceRoot":"","sources":["../../src/tools/run_workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAiDnD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,0EAA0E;QAC1E,uEAAuE;QACvE,uEAAuE;QACvE,0EAA0E;QAC1E,mEAAmE;QACnE,uEAAuE;QACvE,qEAAqE;QACrE,0EAA0E;QAC1E,uEAAuE;QACvE,4EAA4E;QAC5E,wEAAwE;QACxE,2DAA2D;QAC3D,yEAAyE;QACzE,yEAAyE;QACzE,qBAAqB;IACvB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yCAAyC;aACvD;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,wEAAwE;oBACxE,kCAAkC;aACrC;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,gEAAgE;oBAChE,gEAAgE;oBAChE,oEAAoE;oBACpE,iEAAiE;oBACjE,qBAAqB;aACxB;SACF;QACD,QAAQ,EAAE,CAAC,YAAY,EAAE,eAAe,CAAC;QACzC,oBAAoB,EAAE,KAAK;KAC5B;CACO,CAAC;AAEX,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAuB;IAC1D,IAAI,CAAC,KAAK,CAAC,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,CAAC,aAAa;QAAE,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,kBAAkB,kBAAkB,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,kBAAkB,CACjG,KAAK,CAAC,aAAa,CACpB,MAAM,CAAC;IACR,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAmB,IAAI,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACtE,OAAO;QACL,aAAa,EAAE,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa;QACnD,WAAW,EAAE,GAAG,CAAC,gBAAgB,IAAI,EAAE;QACvC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QACpC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC;QAC7C,YAAY,EAAE,WAAW;QACzB,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,KAAK;QACL,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU;KAC/C,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fetchsandbox-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"mcpName": "io.github.fetchsandbox/mcp",
|
|
5
5
|
"description": "Turn any OpenAPI spec into a working sandbox your AI agent can use. MCP server for Claude Code, Cursor, and any other MCP-compatible LLM IDE.",
|
|
6
6
|
"license": "MIT",
|