Skip to main content
Continue from Build your first widget. Add a sales widget alongside weather, using the same Vite project and typed bindings. Each HTML file is an independent widget. A host creates an instance of the widget associated with the tool it calls.

1. Add the sales tool

Replace server/tools.ts with the two-tool version:
server/tools.ts
The existing createApp<typeof tools>() now knows both tool names. In the quickstart’s Weather component, select its tool explicitly so TypeScript narrows the result:
If you added the refresh example, it already selects weather by name.

2. Add the sales component and entry

src/Sales.tsx
Create a React entry for that component:
src/sales-main.tsx
Add its HTML entry at the project root:
sales.html

3. Build each entry separately

The Vite configuration from the quickstart selects one HTML input from --mode:
vite.config.ts
Update the build script in package.json:
Run it:
The weather build clears dist/widgets; the sales build preserves it. The result contains both weather.html and sales.html, each with its own inlined JavaScript/CSS. Use one Vite build per HTML input with vite-plugin-singlefile. The plugin is designed for one HTML entry at a time; separate runs give each resource its own bundled dependencies. For a longer list of widgets, the repository’s build script runs the same sequence in a loop.

4. Register the second resource

In server/index.ts, add salesWidgetUri to the import from ./tools.ts. Before createServer, add the second resource:
Register both definitions:
Both widgets reuse the same widgetUi settings here. Give a resource its own metadata configuration when it needs different permissions or network origins. Rebuild, reload the host’s connector, and call weather and sales. Each tool points to its own resource URI and HTML entry.

Assets and development

Import local JavaScript, CSS, and assets from your widget’s source so the bundler can include them. This recipe sets publicDir: false. If you enable Vite’s public folder, its copied files are not automatically inlined by the single-file plugin. External scripts, fonts, images, and APIs need the appropriate CSP origins. npm run dev serves /weather.html and /sales.html during development. A normal browser tab has no MCP host connection. Rebuild the HTML and reload it in the host to test tool results and interactions. The repository example also has a dev:ui watch build for its shared entry. If several tools should intentionally render the same HTML application, use a shared entry with explicit routing instead.