Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 154 additions & 2 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion docs/build-agent-skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ The user asks something like:
```bash
stitch tool get_screen_code -d '{
"projectId": "PROJECT_ID",
"screenId": "SCREEN_ID"
"screenId": "SCREEN_ID",
# Optional : to get inline CSS instead of Tailwind classes
"inlineCss": true
}'
```

Expand Down
2 changes: 2 additions & 0 deletions docs/build-virtual-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ execute: async (client: StitchMCPClient, args: any) => {
const screen = await client.callTool('get_screen', {
projectId,
screenId,
// Optional : to get inline CSS instead of Tailwind classes
inlineCss: true
}) as any;

// 2. Download the HTML content from the returned URL
Expand Down
4 changes: 3 additions & 1 deletion docs/tool-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ Retrieves a screen and downloads its HTML code content.
```json
{
"projectId": "string (required)",
"screenId": "string (required)"
"screenId": "string (required)",
// Optional : to get inline CSS instead of Tailwind classes
"inlineCss": true
}
```

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"ora": "^8.1.1",
"p-limit": "^7.3.0",
"react": "^19.2.4",
"tailwind-to-inline": "^1.1.5",
"vite": "^7.3.1",
"zod": "^3.24.1"
},
Expand Down
12 changes: 11 additions & 1 deletion src/commands/tool/virtual-tools/get-screen-code.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { StitchToolClient, Stitch } from '@google/stitch-sdk';
import { makeStylesInlineFromString } from 'tailwind-to-inline'
import { downloadText } from '../../../ui/copy-behaviors/clipboard.js';
import type { VirtualTool } from '../spec.js';

Expand All @@ -16,12 +17,16 @@ export const getScreenCodeTool: VirtualTool = {
type: 'string',
description: 'Required. The name of screen to retrieve.',
},
inlineCss: {
type: 'boolean',
description: 'Optional. Whether to transform Tailwind classes by inline CSS style attributes.',
}
},
required: ['projectId', 'screenId'],
},
execute: async (client: StitchToolClient, args: any, stitch?: Stitch) => {
if (!stitch) throw new Error('get_screen_code requires a Stitch instance');
const { projectId, screenId } = args;
const { projectId, screenId, inlineCss } = args;

// 1. Get the screen details using the injected SDK instance
const screen = await stitch.project(projectId).getScreen(screenId);
Expand All @@ -37,6 +42,11 @@ export const getScreenCodeTool: VirtualTool = {
console.error(`Error downloading HTML code: ${e}`);
}

// 3. (Optional) Tailwind to inline CSS
if (inlineCss) {
htmlContent = await makeStylesInlineFromString(htmlContent ?? '');
}

// 3. Return screen with code content
return {
screenId: screen.screenId,
Expand Down
11 changes: 9 additions & 2 deletions tests/commands/tool/virtual-tools/get-screen-code.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,26 @@ describe('get_screen_code virtual tool (SDK)', () => {

beforeEach(() => {
mockClient = { callTool: mock() };
global.fetch = mock(() => Promise.resolve(new Response('<html>hello</html>', { status: 200 }))) as any;
global.fetch = mock(() => Promise.resolve(new Response('<html><span class="text-2xl text-center m-auto">hello</span></html>', { status: 200 }))) as any;
});

it('fetches HTML text via SDK screen.getHtml()', async () => {
const result = await getScreenCodeTool.execute(mockClient, { projectId: 'proj-1', screenId: 'home' }, mockStitch as any);

expect(result.screenId).toBe('home');
expect(result.htmlContent).toBe('<html>hello</html>');
expect(result.htmlContent).toBe('<html><span class="text-2xl text-center m-auto">hello</span></html>');
});

it('returns null htmlContent when getHtml() returns null', async () => {
const result = await getScreenCodeTool.execute(mockClient, { projectId: 'proj-1', screenId: 'no-code' }, mockStitch as any);

expect(result.htmlContent).toBeNull();
});

it('returns inline CSS when inlineCss is true', async () => {
const result = await getScreenCodeTool.execute(mockClient, { projectId: 'proj-1', screenId: 'home', inlineCss: true }, mockStitch as any);

expect(result.screenId).toBe('home');
expect(result.htmlContent).toBe('<html><span style="margin: auto; text-align: center; font-size: 1.5rem; line-height: 2rem;">hello</span></html>');
});
});
Loading