@extenshi/mcp 0.2.0 → 0.4.0

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,82 @@
1
+ /**
2
+ * Welcome-page goal presets + the AI-agent brief.
3
+ *
4
+ * SELF-CONTAINED ON PURPOSE — no imports, so it can be copied verbatim into the
5
+ * published `@extenshi/mcp` package, which cannot depend on unpublished
6
+ * workspace packages (same constraint and same solution as svg-scrub.ts).
7
+ *
8
+ * SINGLE SOURCE, TWO COPIES, byte-identical:
9
+ * shared-types/welcome-agent-brief.ts (canonical — edit here)
10
+ * tools/extenshi-mcp/src/welcome-agent-brief.ts (synced copy for @extenshi/mcp)
11
+ * after editing, run:
12
+ * cp shared-types/welcome-agent-brief.ts tools/extenshi-mcp/src/welcome-agent-brief.ts
13
+ * A test in tools/extenshi-mcp/src/welcome-workflow.test.ts fails CI on drift.
14
+ *
15
+ * Why the sync is load-bearing rather than tidy: the brief tells an agent what
16
+ * to build AND states the limits the save path enforces. If the MCP copy drifts,
17
+ * an agent produces blocks against one spec and catalog-bff rejects them against
18
+ * another — and the author sees a validation error for work they were told to do.
19
+ */
20
+ export declare const WELCOME_MAX_BLOCKS = 14;
21
+ export declare const WELCOME_MAX_ANNOTATIONS = 8;
22
+ export declare const WELCOME_TEXT_MAX_LEN = 600;
23
+ export declare const WELCOME_TITLE_MAX_LEN = 120;
24
+ export declare const WELCOME_ALT_MAX_LEN = 200;
25
+ /** Inline SVG cap — an instructional diagram, not an embedded illustration set. */
26
+ export declare const WELCOME_SVG_MAX_LEN = 24000;
27
+ export declare const WELCOME_UPLOAD_MAX_BYTES: number;
28
+ export declare const WELCOME_DEFAULT_ACCENT = "#5e5ce6";
29
+ /**
30
+ * A welcome page exists to drive exactly one action. Naming that action is the
31
+ * single highest-leverage input to both the default copy and the agent brief:
32
+ * in ~90% of extensions the valuable action is "find and pin the extension",
33
+ * but a new-tab replacement instead needs the user to accept the override, and
34
+ * a content-script widget needs them to visit the target site and spot it.
35
+ */
36
+ export type WelcomeGoal = 'PIN_EXTENSION' | 'NEW_TAB_OPT_IN' | 'VISIT_SITE' | 'CUSTOM';
37
+ export interface WelcomeGoalPreset {
38
+ goal: WelcomeGoal;
39
+ label: string;
40
+ /** One-line description of the action, shown in the constructor. */
41
+ summary: string;
42
+ defaultHeadline: string;
43
+ defaultMessage: string;
44
+ /** Starting checklist — the author edits these, they are not fixed. */
45
+ defaultSteps: string[];
46
+ /**
47
+ * What an illustration for this goal must actually show. Fed verbatim into
48
+ * the agent brief, so it has to describe pixels, not intent.
49
+ */
50
+ illustrationTargets: string[];
51
+ }
52
+ export declare const WELCOME_GOAL_PRESETS: Record<WelcomeGoal, WelcomeGoalPreset>;
53
+ export declare const WELCOME_GOALS: WelcomeGoal[];
54
+ export declare function isWelcomeGoal(v: unknown): v is WelcomeGoal;
55
+ export interface WelcomeAgentBriefInput {
56
+ extensionName: string;
57
+ goal: WelcomeGoal;
58
+ /** Free-text description of what the extension actually does. */
59
+ whatItDoes?: string | null;
60
+ /** Site the extension acts on — required to make VISIT_SITE illustrations concrete. */
61
+ targetSite?: string | null;
62
+ /** Store screenshot URLs we already host, offered to the agent as raw material. */
63
+ storeScreenshots?: string[];
64
+ /** Steps the author has already written, if any. */
65
+ existingSteps?: string[];
66
+ accentColor?: string;
67
+ /** Where the finished blocks get pasted back. */
68
+ constructorUrl?: string;
69
+ }
70
+ /**
71
+ * Render the brief that tells a coding/design agent what to produce for this
72
+ * welcome page.
73
+ *
74
+ * This is the tool's real job. An author who opens the constructor knows what
75
+ * their extension does but not what a good welcome page contains; an agent can
76
+ * draw and annotate but does not know the goal, the store assets we already
77
+ * hold, or the block JSON it must emit. The brief is the contract between them,
78
+ * so it states all three — and it is a pure function of the config (no network,
79
+ * no key, no credits) so both dojo and the MCP server can render it.
80
+ */
81
+ export declare function buildWelcomeAgentBrief(input: WelcomeAgentBriefInput): string;
82
+ //# sourceMappingURL=welcome-agent-brief.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome-agent-brief.d.ts","sourceRoot":"","sources":["../src/welcome-agent-brief.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AACpC,eAAO,MAAM,uBAAuB,IAAI,CAAA;AACxC,eAAO,MAAM,oBAAoB,MAAM,CAAA;AACvC,eAAO,MAAM,qBAAqB,MAAM,CAAA;AACxC,eAAO,MAAM,mBAAmB,MAAM,CAAA;AACtC,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,QAAS,CAAA;AACzC,eAAO,MAAM,wBAAwB,QAAkB,CAAA;AACvD,eAAO,MAAM,sBAAsB,YAAY,CAAA;AAI/C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,gBAAgB,GAAG,YAAY,GAAG,QAAQ,CAAA;AAEtF,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,uEAAuE;IACvE,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,EAAE,CAAA;CAC7B;AAED,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAoEvE,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EAAgE,CAAA;AAEvG,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAE1D;AAID,MAAM,WAAW,sBAAsB;IACtC,aAAa,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,WAAW,CAAA;IACjB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAkN5E"}
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Welcome-page goal presets + the AI-agent brief.
3
+ *
4
+ * SELF-CONTAINED ON PURPOSE — no imports, so it can be copied verbatim into the
5
+ * published `@extenshi/mcp` package, which cannot depend on unpublished
6
+ * workspace packages (same constraint and same solution as svg-scrub.ts).
7
+ *
8
+ * SINGLE SOURCE, TWO COPIES, byte-identical:
9
+ * shared-types/welcome-agent-brief.ts (canonical — edit here)
10
+ * tools/extenshi-mcp/src/welcome-agent-brief.ts (synced copy for @extenshi/mcp)
11
+ * after editing, run:
12
+ * cp shared-types/welcome-agent-brief.ts tools/extenshi-mcp/src/welcome-agent-brief.ts
13
+ * A test in tools/extenshi-mcp/src/welcome-workflow.test.ts fails CI on drift.
14
+ *
15
+ * Why the sync is load-bearing rather than tidy: the brief tells an agent what
16
+ * to build AND states the limits the save path enforces. If the MCP copy drifts,
17
+ * an agent produces blocks against one spec and catalog-bff rejects them against
18
+ * another — and the author sees a validation error for work they were told to do.
19
+ */
20
+ // ── Caps (mirrored by the zod schemas in catalog-bff/src/lib/welcome-blocks.ts) ──
21
+ export const WELCOME_MAX_BLOCKS = 14;
22
+ export const WELCOME_MAX_ANNOTATIONS = 8;
23
+ export const WELCOME_TEXT_MAX_LEN = 600;
24
+ export const WELCOME_TITLE_MAX_LEN = 120;
25
+ export const WELCOME_ALT_MAX_LEN = 200;
26
+ /** Inline SVG cap — an instructional diagram, not an embedded illustration set. */
27
+ export const WELCOME_SVG_MAX_LEN = 24_000;
28
+ export const WELCOME_UPLOAD_MAX_BYTES = 2 * 1024 * 1024;
29
+ export const WELCOME_DEFAULT_ACCENT = '#5e5ce6';
30
+ export const WELCOME_GOAL_PRESETS = {
31
+ PIN_EXTENSION: {
32
+ goal: 'PIN_EXTENSION',
33
+ label: 'Pin the extension',
34
+ summary: 'Get the user to find the extension in the toolbar puzzle menu and pin it.',
35
+ defaultHeadline: "You're all set — pin it so it's always one click away",
36
+ defaultMessage: 'Chrome hides new extensions behind the puzzle icon. Pinning takes five seconds and means you never have to hunt for it again.',
37
+ defaultSteps: [
38
+ 'Click the puzzle icon in the top-right of the browser toolbar',
39
+ 'Find this extension in the list that opens',
40
+ 'Click the pin icon next to it so it stays in the toolbar',
41
+ 'The icon now sits in your toolbar — click it any time to start',
42
+ ],
43
+ illustrationTargets: [
44
+ 'The browser toolbar with the puzzle (Extensions) icon highlighted in the top-right.',
45
+ "The open extensions dropdown with this extension's row highlighted.",
46
+ 'The same dropdown with the pin toggle beside that row highlighted.',
47
+ 'The toolbar after pinning, with the extension icon now visible next to the address bar.',
48
+ ],
49
+ },
50
+ NEW_TAB_OPT_IN: {
51
+ goal: 'NEW_TAB_OPT_IN',
52
+ label: 'Keep the new-tab change',
53
+ summary: 'Get the user to accept the new-tab override prompt instead of reverting it.',
54
+ defaultHeadline: 'One last step — keep your new tab',
55
+ defaultMessage: 'Your browser will ask whether to keep the new-tab page. Choose "Keep it" and the extension is ready to use.',
56
+ defaultSteps: [
57
+ 'Open a new tab',
58
+ 'Your browser shows a "change back?" prompt in the top-right',
59
+ 'Click "Keep it" to confirm the new-tab page',
60
+ 'Open a new tab again to see it live',
61
+ ],
62
+ illustrationTargets: [
63
+ 'A fresh browser window with the new-tab change confirmation dialog visible.',
64
+ 'The same dialog with the "Keep it" button highlighted.',
65
+ 'The new tab page rendering the extension after confirmation.',
66
+ ],
67
+ },
68
+ VISIT_SITE: {
69
+ goal: 'VISIT_SITE',
70
+ label: 'Use it on a site',
71
+ summary: 'Send the user to the site where the extension injects its widget, and show them the widget.',
72
+ defaultHeadline: "You're installed — here's where to find it",
73
+ defaultMessage: 'This extension works directly on the pages you already use. Open a supported page and the controls appear automatically.',
74
+ defaultSteps: [
75
+ 'Open a supported page in a new tab',
76
+ 'Wait a second for the page to finish loading',
77
+ 'Look for the extension panel added to the page',
78
+ 'Click it to run the extension on that page',
79
+ ],
80
+ illustrationTargets: [
81
+ 'The target website as it normally looks, before the extension acts.',
82
+ 'The same page with the injected extension widget highlighted in place.',
83
+ 'The widget expanded, showing the extension actually doing its job.',
84
+ ],
85
+ },
86
+ CUSTOM: {
87
+ goal: 'CUSTOM',
88
+ label: 'Something else',
89
+ summary: 'Describe your own primary action; nothing is pre-filled.',
90
+ defaultHeadline: '',
91
+ defaultMessage: '',
92
+ defaultSteps: [],
93
+ illustrationTargets: [],
94
+ },
95
+ };
96
+ export const WELCOME_GOALS = ['PIN_EXTENSION', 'NEW_TAB_OPT_IN', 'VISIT_SITE', 'CUSTOM'];
97
+ export function isWelcomeGoal(v) {
98
+ return typeof v === 'string' && WELCOME_GOALS.includes(v);
99
+ }
100
+ /**
101
+ * Render the brief that tells a coding/design agent what to produce for this
102
+ * welcome page.
103
+ *
104
+ * This is the tool's real job. An author who opens the constructor knows what
105
+ * their extension does but not what a good welcome page contains; an agent can
106
+ * draw and annotate but does not know the goal, the store assets we already
107
+ * hold, or the block JSON it must emit. The brief is the contract between them,
108
+ * so it states all three — and it is a pure function of the config (no network,
109
+ * no key, no credits) so both dojo and the MCP server can render it.
110
+ */
111
+ export function buildWelcomeAgentBrief(input) {
112
+ const preset = WELCOME_GOAL_PRESETS[input.goal] ?? WELCOME_GOAL_PRESETS.PIN_EXTENSION;
113
+ const name = input.extensionName.trim() || 'the extension';
114
+ const accent = input.accentColor || WELCOME_DEFAULT_ACCENT;
115
+ const shots = input.storeScreenshots ?? [];
116
+ const steps = (input.existingSteps ?? []).filter((s) => s.trim());
117
+ const out = [];
118
+ out.push(`# Welcome-page illustrations for "${name}"`);
119
+ out.push('');
120
+ out.push('You are producing the visual, step-by-step content for the page a user lands on the', 'moment they install this browser extension. Everything you make here gets pasted back', 'into the Extenshi welcome-page constructor as blocks — so produce the assets AND the', 'block JSON at the end.', '');
121
+ out.push('## The one action this page must drive');
122
+ out.push('');
123
+ out.push(`**${preset.label}** — ${preset.summary}`);
124
+ out.push('');
125
+ out.push('A welcome page that explains everything drives nothing. Every block you write must', 'serve that single action; cut anything that does not.', '');
126
+ if (input.whatItDoes?.trim()) {
127
+ out.push('## What the extension does');
128
+ out.push('');
129
+ out.push(input.whatItDoes.trim());
130
+ out.push('');
131
+ }
132
+ if (input.goal === 'VISIT_SITE') {
133
+ out.push('## Target site');
134
+ out.push('');
135
+ out.push(input.targetSite?.trim()
136
+ ? `The extension acts on: ${input.targetSite.trim()}. Illustrations must show that real site, not a generic page.`
137
+ : 'No target site was supplied. Ask the developer which site the extension injects into before drawing anything — a generic page teaches the user nothing.');
138
+ out.push('');
139
+ }
140
+ out.push('## Illustrations to produce');
141
+ out.push('');
142
+ if (preset.illustrationTargets.length) {
143
+ out.push('One image per step, in this order:');
144
+ out.push('');
145
+ preset.illustrationTargets.forEach((t, i) => {
146
+ out.push(`${i + 1}. ${t}`);
147
+ });
148
+ }
149
+ else {
150
+ out.push('No preset applies to this goal. Decide the shortest sequence of images that takes a', 'brand-new user from "just installed" to having completed the action above, and produce', 'one image per step.');
151
+ }
152
+ out.push('');
153
+ out.push('### How to get each image');
154
+ out.push('');
155
+ out.push('1. **Screenshot the real thing wherever you can.** Load the extension in a clean browser', ' profile, drive it to the exact moment the step describes, and capture the browser', ' window. A real screenshot of the actual UI beats a drawing, because the user is', ' matching what they see on their own screen against your image.', '2. **Crop to the region that matters.** A full 1920px desktop capture renders unreadably', ' small in a page column. Crop to the toolbar, the dropdown, or the widget — enough', ' surrounding context to locate it, nothing more.', '3. **Draw an SVG instead when a screenshot is impossible or ugly** — an OS dialog you', ' cannot reliably reproduce, a state that needs three preconditions, or anything with', ' personal data in it. A clean vector mock of the browser chrome is better than a', ' cluttered real capture.', '');
156
+ if (shots.length) {
157
+ out.push('### Screenshots we already host');
158
+ out.push('');
159
+ out.push(`This extension has ${shots.length} store screenshot${shots.length === 1 ? '' : 's'} already`, 'mirrored on our storage. They are approved store assets and can be dropped straight into', 'a block with `"source": "store"` and the URL as-is — no upload step:', '');
160
+ for (const u of shots.slice(0, 10)) {
161
+ out.push(`- ${u}`);
162
+ }
163
+ out.push('');
164
+ out.push('Use these for "what the extension looks like / what it does" blocks. They are marketing', 'captures, so they usually will NOT show the install steps — draw or capture those yourself.', '');
165
+ }
166
+ out.push('## Annotating: show exactly where to click');
167
+ out.push('');
168
+ out.push('An un-annotated screenshot makes the user hunt. Every image that has a click target must', 'carry a marker on it. Do NOT burn arrows into the image pixels — the constructor draws', 'markers as an overlay, so they stay crisp, stay translatable, and can be moved later.', '', 'Give each marker as a percentage of the image box:', '', '- `kind: "number"` — a numbered badge on the thing to click. Use when the step is one of', ' an ordered sequence, which is the common case.', '- `kind: "arrow"` — a pointer with an `angle` in degrees clockwise from pointing right', ' (0 = →, 90 = ↓, 180 = ←, 270 = ↑). Use when the target is small or near an edge and a', ' badge would cover it.', "- `x` / `y` are 0–100 percentages of the image's own width/height, measured to the CENTRE", ' of the target. Percentages, not pixels: the page is responsive and the author may swap', ' in a re-captured screenshot at a different resolution.', `- At most ${WELCOME_MAX_ANNOTATIONS} markers per image. If you need more, the image is doing`, ' too much — split it into two steps.', '');
169
+ out.push('## Constraints that will be enforced on save');
170
+ out.push('');
171
+ out.push(`- At most ${WELCOME_MAX_BLOCKS} blocks total.`, `- Step titles ≤ ${WELCOME_TITLE_MAX_LEN} chars; body text ≤ ${WELCOME_TEXT_MAX_LEN} chars.`, `- Every image needs \`alt\` text (≤ ${WELCOME_ALT_MAX_LEN} chars) describing what is shown —`, ' it is what a screen-reader user gets instead of your illustration.', `- SVG: a single \`<svg>\` element, ≤ ${WELCOME_SVG_MAX_LEN} chars, flat shapes only. Scripts,`, ' event handlers, `<foreignObject>`, external references and embedded rasters are stripped', ' by the server sanitizer — if you rely on them the image will render broken, so do not', ' use them.', `- Uploads: PNG / JPEG / WebP only, ≤ ${Math.round(WELCOME_UPLOAD_MAX_BYTES / 1024 / 1024)} MB each.`, `- Accent colour for this page is \`${accent}\` — match it in drawn illustrations so the page`, ' reads as one design.', '');
172
+ if (steps.length) {
173
+ out.push('## Steps the author already wrote');
174
+ out.push('');
175
+ out.push('Keep their wording and intent; you are adding the visuals, not rewriting the page:');
176
+ out.push('');
177
+ steps.forEach((s, i) => {
178
+ out.push(`${i + 1}. ${s}`);
179
+ });
180
+ out.push('');
181
+ }
182
+ out.push('## What to hand back');
183
+ out.push('');
184
+ out.push('A JSON array of blocks in this exact shape:');
185
+ out.push('');
186
+ out.push('```json');
187
+ out.push(JSON.stringify([
188
+ {
189
+ kind: 'step',
190
+ id: 'step-1',
191
+ title: preset.defaultSteps[0] ?? 'First thing the user does',
192
+ body: 'Optional one-sentence elaboration.',
193
+ media: {
194
+ source: 'svg',
195
+ svg: '<svg viewBox="0 0 640 200">…</svg>',
196
+ alt: 'Browser toolbar with the extensions puzzle icon at the top right',
197
+ annotations: [{ x: 92.5, y: 18, kind: 'number', n: 1, label: 'Click here' }],
198
+ },
199
+ },
200
+ {
201
+ kind: 'image',
202
+ id: 'shot-1',
203
+ media: {
204
+ source: 'store',
205
+ url: shots[0] ?? 'https://…/screenshot.png',
206
+ alt: 'The extension panel open on a supported page',
207
+ annotations: [],
208
+ },
209
+ caption: 'What it looks like in use.',
210
+ },
211
+ { kind: 'text', id: 'outro', title: 'Need help?', body: 'Short closing paragraph.' },
212
+ ], null, 2));
213
+ out.push('```');
214
+ out.push('');
215
+ out.push('- `source: "svg"` → put the markup in `svg`, leave `url` unset.', '- `source: "store"` → put one of the hosted URLs above in `url`, leave `svg` unset.', '- `source: "upload"` → the author uploads the file in the constructor and the URL is filled', ' in there; emit the block with an empty `url` and say which local file belongs in it.', '- `id` just has to be unique within the page.', '');
216
+ out.push('## Then');
217
+ out.push('');
218
+ out.push('1. Save any images you drew or captured as files next to the project so the author can upload them.', `2. Open the constructor${input.constructorUrl ? ` — ${input.constructorUrl}` : ''}, paste the block JSON,`, ' upload any local images, and check the live preview.', '3. Look at the preview at a narrow width too — annotations that read fine on desktop can', ' collide on a phone.');
219
+ return out.join('\n');
220
+ }
221
+ //# sourceMappingURL=welcome-agent-brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome-agent-brief.js","sourceRoot":"","sources":["../src/welcome-agent-brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Static content for the free `generate_welcome_page_workflow` MCP tool.
3
+ *
4
+ * Like `generate_icon_workflow`, this path deliberately spends ZERO Extenshi
5
+ * credits and touches no Extenshi infrastructure: the brief is a pure function
6
+ * of its arguments, so the tool works offline and can never fail on a docs or
7
+ * BFF outage. An agent connected through the MCP connector gets the exact
8
+ * requirements — what to illustrate, how to annotate, what JSON to emit —
9
+ * instead of guessing them.
10
+ *
11
+ * The brief itself lives in ./welcome-agent-brief.ts, a byte-identical copy of
12
+ * shared-types/welcome-agent-brief.ts. That sync is what guarantees the spec an
13
+ * agent is handed here is the same spec catalog-bff enforces on save.
14
+ *
15
+ * Store screenshots are NOT fetched here: that would need a catalog read (an
16
+ * API key and a credit) and would turn a free tool into a paid one. An agent
17
+ * that wants them calls `get_extension` and passes the URLs back in via
18
+ * `store_screenshots`.
19
+ */
20
+ export declare const CONSTRUCTOR_URL = "https://dojo.extenshi.io/tools/onboarding-page";
21
+ export interface WelcomeWorkflowArgs {
22
+ extensionName?: string;
23
+ goal?: string;
24
+ whatItDoes?: string;
25
+ targetSite?: string;
26
+ storeScreenshots?: string[];
27
+ existingSteps?: string[];
28
+ accentColor?: string;
29
+ }
30
+ export declare function renderWelcomeWorkflow(args: WelcomeWorkflowArgs): string;
31
+ //# sourceMappingURL=welcome-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome-workflow.d.ts","sourceRoot":"","sources":["../src/welcome-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,eAAO,MAAM,eAAe,mDAAmD,CAAA;AAE/E,MAAM,WAAW,mBAAmB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAkCvE"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Static content for the free `generate_welcome_page_workflow` MCP tool.
3
+ *
4
+ * Like `generate_icon_workflow`, this path deliberately spends ZERO Extenshi
5
+ * credits and touches no Extenshi infrastructure: the brief is a pure function
6
+ * of its arguments, so the tool works offline and can never fail on a docs or
7
+ * BFF outage. An agent connected through the MCP connector gets the exact
8
+ * requirements — what to illustrate, how to annotate, what JSON to emit —
9
+ * instead of guessing them.
10
+ *
11
+ * The brief itself lives in ./welcome-agent-brief.ts, a byte-identical copy of
12
+ * shared-types/welcome-agent-brief.ts. That sync is what guarantees the spec an
13
+ * agent is handed here is the same spec catalog-bff enforces on save.
14
+ *
15
+ * Store screenshots are NOT fetched here: that would need a catalog read (an
16
+ * API key and a credit) and would turn a free tool into a paid one. An agent
17
+ * that wants them calls `get_extension` and passes the URLs back in via
18
+ * `store_screenshots`.
19
+ */
20
+ import { buildWelcomeAgentBrief, isWelcomeGoal } from './welcome-agent-brief.js';
21
+ export const CONSTRUCTOR_URL = 'https://dojo.extenshi.io/tools/onboarding-page';
22
+ export function renderWelcomeWorkflow(args) {
23
+ // An unrecognised goal falls back to the ~90% case rather than erroring: a
24
+ // slightly-wrong preset still produces a usable brief, and a hard failure
25
+ // here would strand the agent with nothing.
26
+ const goal = isWelcomeGoal(args.goal) ? args.goal : 'PIN_EXTENSION';
27
+ const brief = buildWelcomeAgentBrief({
28
+ extensionName: args.extensionName ?? '',
29
+ goal,
30
+ whatItDoes: args.whatItDoes,
31
+ targetSite: args.targetSite,
32
+ storeScreenshots: args.storeScreenshots,
33
+ existingSteps: args.existingSteps,
34
+ accentColor: args.accentColor,
35
+ constructorUrl: CONSTRUCTOR_URL,
36
+ });
37
+ return [
38
+ brief,
39
+ '',
40
+ '---',
41
+ '',
42
+ '## How this page gets published',
43
+ '',
44
+ 'The author does not have to host anything. Saving in the constructor publishes the page at',
45
+ '`welcome.extenshi.io/{extensionId}/{slug}` and produces a `chrome.runtime.onInstalled`',
46
+ 'snippet that opens it once on first install (never on update) and counts confirmed installs',
47
+ 'by version and browser.',
48
+ '',
49
+ 'If the author would rather host the page themselves, they can set their own URL in the',
50
+ 'constructor instead — the generated snippet then opens their page and fires a separate',
51
+ 'permission-free beacon, so the install counter keeps working either way. In that case the',
52
+ 'block JSON above is still worth producing: it is the content spec for their own page.',
53
+ ].join('\n');
54
+ }
55
+ //# sourceMappingURL=welcome-workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome-workflow.js","sourceRoot":"","sources":["../src/welcome-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAoB,MAAM,0BAA0B,CAAA;AAElG,MAAM,CAAC,MAAM,eAAe,GAAG,gDAAgD,CAAA;AAY/E,MAAM,UAAU,qBAAqB,CAAC,IAAyB;IAC9D,2EAA2E;IAC3E,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,IAAI,GAAgB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAA;IAEhF,MAAM,KAAK,GAAG,sBAAsB,CAAC;QACpC,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,EAAE;QACvC,IAAI;QACJ,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,cAAc,EAAE,eAAe;KAC/B,CAAC,CAAA;IAEF,OAAO;QACN,KAAK;QACL,EAAE;QACF,KAAK;QACL,EAAE;QACF,iCAAiC;QACjC,EAAE;QACF,4FAA4F;QAC5F,wFAAwF;QACxF,6FAA6F;QAC7F,yBAAyB;QACzB,EAAE;QACF,wFAAwF;QACxF,wFAAwF;QACxF,2FAA2F;QAC3F,uFAAuF;KACvF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extenshi/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Extenshi MCP server — bring the extension catalog (search, security, market research) and pre-publish scanning into your AI tools",
5
5
  "type": "module",
6
6
  "license": "MIT",