skybridge 0.0.0-dev.f1722d8 → 0.0.0-dev.f22c21a

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.
Files changed (82) hide show
  1. package/README.md +67 -315
  2. package/dist/src/server/index.d.ts +2 -2
  3. package/dist/src/server/index.js.map +1 -1
  4. package/dist/src/server/inferUtilityTypes.d.ts +10 -0
  5. package/dist/src/server/server.d.ts +30 -15
  6. package/dist/src/server/server.js +4 -4
  7. package/dist/src/server/server.js.map +1 -1
  8. package/dist/src/server/templateHelper.js +2 -2
  9. package/dist/src/server/templateHelper.js.map +1 -1
  10. package/dist/src/server/widgetsDevServer.js +3 -3
  11. package/dist/src/server/widgetsDevServer.js.map +1 -1
  12. package/dist/src/test/utils.d.ts +42 -7
  13. package/dist/src/test/utils.js +66 -8
  14. package/dist/src/test/utils.js.map +1 -1
  15. package/dist/src/test/widget.test.js +19 -20
  16. package/dist/src/test/widget.test.js.map +1 -1
  17. package/dist/src/web/create-store.d.ts +1 -1
  18. package/dist/src/web/create-store.js +3 -81
  19. package/dist/src/web/create-store.js.map +1 -1
  20. package/dist/src/web/create-store.test.d.ts +1 -0
  21. package/dist/src/web/create-store.test.js +70 -0
  22. package/dist/src/web/create-store.test.js.map +1 -0
  23. package/dist/src/web/data-llm.d.ts +1 -0
  24. package/dist/src/web/data-llm.js +4 -3
  25. package/dist/src/web/data-llm.js.map +1 -1
  26. package/dist/src/web/data-llm.test.js.map +1 -1
  27. package/dist/src/web/generate-helpers.d.ts +9 -7
  28. package/dist/src/web/generate-helpers.js +4 -2
  29. package/dist/src/web/generate-helpers.js.map +1 -1
  30. package/dist/src/web/generate-helpers.test-d.js +29 -2
  31. package/dist/src/web/generate-helpers.test-d.js.map +1 -1
  32. package/dist/src/web/generate-helpers.test.js +1 -1
  33. package/dist/src/web/generate-helpers.test.js.map +1 -1
  34. package/dist/src/web/helpers/state.d.ts +7 -0
  35. package/dist/src/web/helpers/state.js +40 -0
  36. package/dist/src/web/helpers/state.js.map +1 -0
  37. package/dist/src/web/helpers/state.test.d.ts +1 -0
  38. package/dist/src/web/helpers/state.test.js +53 -0
  39. package/dist/src/web/helpers/state.test.js.map +1 -0
  40. package/dist/src/web/hooks/index.d.ts +2 -2
  41. package/dist/src/web/hooks/index.js +1 -1
  42. package/dist/src/web/hooks/index.js.map +1 -1
  43. package/dist/src/web/hooks/use-call-tool.js.map +1 -1
  44. package/dist/src/web/hooks/use-call-tool.test-d.js +1 -1
  45. package/dist/src/web/hooks/use-call-tool.test-d.js.map +1 -1
  46. package/dist/src/web/hooks/use-call-tool.test.js +1 -1
  47. package/dist/src/web/hooks/use-call-tool.test.js.map +1 -1
  48. package/dist/src/web/hooks/use-display-mode.js.map +1 -1
  49. package/dist/src/web/hooks/use-display-mode.test.js +2 -2
  50. package/dist/src/web/hooks/use-display-mode.test.js.map +1 -1
  51. package/dist/src/web/hooks/use-files.test.js +1 -1
  52. package/dist/src/web/hooks/use-files.test.js.map +1 -1
  53. package/dist/src/web/hooks/use-locale.test.js +2 -2
  54. package/dist/src/web/hooks/use-locale.test.js.map +1 -1
  55. package/dist/src/web/hooks/use-open-external.test.js +2 -2
  56. package/dist/src/web/hooks/use-open-external.test.js.map +1 -1
  57. package/dist/src/web/hooks/use-openai-global.d.ts +2 -2
  58. package/dist/src/web/hooks/use-openai-global.js +1 -1
  59. package/dist/src/web/hooks/use-openai-global.js.map +1 -1
  60. package/dist/src/web/hooks/use-request-modal.test.js +2 -2
  61. package/dist/src/web/hooks/use-request-modal.test.js.map +1 -1
  62. package/dist/src/web/hooks/use-theme.test.js +2 -2
  63. package/dist/src/web/hooks/use-theme.test.js.map +1 -1
  64. package/dist/src/web/hooks/use-tool-info.js +1 -1
  65. package/dist/src/web/hooks/use-tool-info.js.map +1 -1
  66. package/dist/src/web/hooks/use-tool-info.test-d.js +0 -1
  67. package/dist/src/web/hooks/use-tool-info.test-d.js.map +1 -1
  68. package/dist/src/web/hooks/use-tool-info.test.js +2 -2
  69. package/dist/src/web/hooks/use-tool-info.test.js.map +1 -1
  70. package/dist/src/web/hooks/use-user-agent.test.js +2 -2
  71. package/dist/src/web/hooks/use-user-agent.test.js.map +1 -1
  72. package/dist/src/web/hooks/use-widget-state.js +3 -25
  73. package/dist/src/web/hooks/use-widget-state.js.map +1 -1
  74. package/dist/src/web/hooks/use-widget-state.test.js +2 -2
  75. package/dist/src/web/hooks/use-widget-state.test.js.map +1 -1
  76. package/dist/src/web/index.d.ts +4 -4
  77. package/dist/src/web/index.js +4 -4
  78. package/dist/src/web/index.js.map +1 -1
  79. package/dist/src/web/proxy.js +1 -1
  80. package/dist/src/web/proxy.js.map +1 -1
  81. package/dist/src/web/types.d.ts +5 -5
  82. package/package.json +10 -5
package/README.md CHANGED
@@ -1,371 +1,123 @@
1
1
  <div align="center">
2
2
 
3
- # Skybridge
4
-
5
- **Skybridge is the TypeScript framework for building ChatGPT apps**
6
-
7
- [![By Alpic](https://img.shields.io/badge/Made%20by%20Alpic-f6ffed?logo=alpic)](https://alpic.ai)
8
-
9
- ![NPM Downloads](https://img.shields.io/npm/dm/skybridge?color=e90060)
10
- ![NPM Version](https://img.shields.io/npm/v/skybridge?color=e90060)
11
- ![GitHub License](https://img.shields.io/github/license/alpic-ai/skybridge?color=e90060)
12
-
13
- </div>
14
-
15
- Skybridge comes with 2 packages:
3
+ <img alt="Skybridge" src="docs/static/img/logo.png" width="220">
16
4
 
17
- - `skybridge/server`: A drop-in replacement of the `@modelcontextprotocol/sdk` official `McpServer` class with extra features for widget development.
18
- - `skybridge/web`: A react library with hooks and components to build widgets on the underlying _OpenAI iFrame skybridge_ runtime.
19
-
20
- ## Quick start
21
-
22
- To get started in less than a minute, you can [create a new repository](https://github.com/new?template_name=apps-sdk-template&template_owner=alpic-ai) using our [ChatGPT SDK template](https://github.com/alpic-ai/apps-sdk-template). This template includes a basic setup for both the server and the widgets.
5
+ # Skybridge
23
6
 
24
- ## Installation
7
+ **Build ChatGPT Apps. The Modern TypeScript Way.**
25
8
 
26
- ```bash
27
- pnpm add skybridge
28
- ```
9
+ The fullstack TypeScript framework for ChatGPT Apps.<br />
10
+ **Type-safe. React-powered. Zero config.**
29
11
 
30
- ## Concepts
12
+ <br />
31
13
 
32
- ### Widgets
14
+ [![NPM Version](https://img.shields.io/npm/v/skybridge?color=e90060&style=for-the-badge)](https://www.npmjs.com/package/skybridge)
15
+ [![NPM Downloads](https://img.shields.io/npm/dm/skybridge?color=e90060&style=for-the-badge)](https://www.npmjs.com/package/skybridge)
16
+ [![GitHub License](https://img.shields.io/github/license/alpic-ai/skybridge?color=e90060&style=for-the-badge)](https://github.com/alpic-ai/skybridge/blob/main/LICENSE)
33
17
 
34
- > A widget is a UI component that turns structured tool results into a human-friendly UI. Those are built using React components. They are rendered inside an iframe inline with the conversation on ChatGPT.
18
+ <br />
35
19
 
36
- Each widget in your app must have a unique name. The name is used to bridge the tool invocation result with the widget React component.
20
+ [Documentation](https://skybridge.tech) · [Quick Start](https://github.com/new?template_name=apps-sdk-template&template_owner=alpic-ai) · [Examples](https://github.com/alpic-ai/apps-sdk-template)
37
21
 
38
- For example, in order to register a new widget named `pokemon` on your ChatGPT app. You should have the following file structure and file contents:
39
-
40
- _Project structure_
22
+ </div>
41
23
 
42
- ```
43
- server/
44
- └── src/
45
- └── index.ts // Register the widget with McpServer.widget()
46
- web/
47
- └── src/
48
- └── widgets/
49
- └── pokemon.tsx // Use the same widget name as the file name
50
- ```
24
+ <br />
51
25
 
52
- _server/src/index.ts_
26
+ ## ✨ Why Skybridge?
53
27
 
54
- ```ts
55
- import { McpServer } from "skybridge/server";
28
+ ChatGPT Apps let you embed **rich, interactive UIs** directly in conversations. But the raw SDK is low-level—no hooks, no type safety, no dev tools, and no HMR.
56
29
 
57
- const server = new McpServer();
30
+ **Skybridge fixes that.**
58
31
 
59
- server.widget(
60
- "pokemon"
61
- // Remaining arguments...
62
- );
63
- ```
32
+ | | |
33
+ |:--|:--|
34
+ | 👨‍💻 **Full Dev Environment** — HMR, debug traces, and local emulator. No more refresh loops. | ✅ **End-to-End Type Safety** — tRPC-style inference from server to widget. Autocomplete everywhere. |
35
+ | 🔄 **Widget-to-Model Sync** — Keep the model aware of UI state with `data-llm`. Dual surfaces, one source of truth. | ⚒️ **React Query-style Hooks** — `isPending`, `isError`, callbacks. State management you already know. |
64
36
 
65
- _web/src/widgets/pokemon.tsx_
37
+ <br />
66
38
 
67
- ```ts
68
- import { mountWidget } from "skybridge/web";
39
+ ## 🚀 Get Started
69
40
 
70
- const Pokemon: React.FunctionComponent = () => {
71
- // Your React component code goes here...
72
- };
41
+ **Create a new ChatGPT app:**
73
42
 
74
- mountWidget(<Pokemon />);
43
+ ```bash
44
+ gh repo create my-app --template alpic-ai/apps-sdk-template --clone
45
+ cd my-app && pnpm install
75
46
  ```
76
47
 
77
- ## Packages
78
-
79
- ### skybridge/server
80
-
81
- The `skybridge/server` package is a drop-in replacement of the `@modelcontextprotocol/sdk` official `McpServer` class with extra features for widget development. If you're already using the `@modelcontextprotocol/sdk`, you can simply replace your `McpServer` import with `skybridge/server` and you're good to go.
82
-
83
- ### skybridge/web
48
+ **Or add to an existing project:**
84
49
 
85
- The `skybridge/web` package is a react library with hooks and components to build widgets on the underlying _OpenAI iFrame skybridge_ runtime.
86
-
87
- **Vite plugin**
88
-
89
- The `skybridge/web` package comes with a Vite plugin that allows you to build your widgets as regular Vite apps.
90
-
91
- ```ts
92
- import { defineConfig } from "vite";
93
- import { skybridge } from "skybridge/web";
94
-
95
- export default defineConfig({
96
- plugins: [skybridge()],
97
- });
50
+ ```bash
51
+ npm i skybridge
52
+ yarn add skybridge
53
+ pnpm add skybridge
54
+ bun add skybridge
55
+ deno add skybridge
98
56
  ```
99
57
 
100
- **Typed Hooks**
58
+ <div align="center">
101
59
 
102
- Skybridge provides fully typed hooks that give you autocomplete for tool names and type inference for inputs/outputs - similar to tRPC. This is opt-in and requires exporting your server type.
60
+ **👉 [Read the Docs](https://skybridge.tech) 👈**
103
61
 
104
- > **Tip:** For the best TypeScript experience, use typed hooks throughout your application. They provide autocomplete, type safety, and better IDE support.
62
+ </div>
105
63
 
106
- > **Important:** For `generateHelpers` to work correctly, your MCP server must be defined using method chaining (e.g., `server.widget(...).widget(...).registerTool(...)`). This ensures TypeScript can properly infer the tool registry type from the chained calls.
64
+ <br />
107
65
 
108
- **Examples:**
66
+ ## 📦 The Stack
109
67
 
110
- **Works** - Using method chaining:
68
+ - **`skybridge/server`** — Drop-in MCP SDK replacement with widget registration and type inference.
69
+ - **`skybridge/web`** — React hooks and components for ChatGPT's runtime.
111
70
 
112
- ```ts
113
- import { McpServer } from "skybridge/server";
114
- import { z } from "zod";
115
-
116
- const server = new McpServer({ name: "my-app", version: "1.0" }, {})
117
- .widget("search-voyage", {}, {
118
- inputSchema: { destination: z.string() },
119
- }, async ({ destination }) => {
120
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
121
- })
122
- .registerTool("calculate-price", {
123
- inputSchema: { tripId: z.string() },
124
- }, async ({ tripId }) => {
125
- return { content: [{ type: "text", text: `Price for ${tripId}` }] };
126
- });
127
-
128
- export type AppType = typeof server; // ✅ Type inference works correctly
129
- ```
130
-
131
- ❌ **Doesn't work** - Without method chaining:
71
+ ### Server
132
72
 
133
73
  ```ts
134
74
  import { McpServer } from "skybridge/server";
135
- import { z } from "zod";
136
-
137
- const server = new McpServer({ name: "my-app", version: "1.0" }, {});
138
75
 
139
- server.widget("search-voyage", {}, {
76
+ server.registerWidget("flights", {}, {
140
77
  inputSchema: { destination: z.string() },
141
78
  }, async ({ destination }) => {
142
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
143
- });
144
-
145
- server.registerTool("calculate-price", {
146
- inputSchema: { tripId: z.string() },
147
- }, async ({ tripId }) => {
148
- return { content: [{ type: "text", text: `Price for ${tripId}` }] };
79
+ const flights = await searchFlights(destination);
80
+ return { structuredContent: { flights } };
149
81
  });
150
-
151
- export type AppType = typeof server; // ❌ Type inference fails - tool registry is empty
152
- ```
153
-
154
- _Server setup (server/src/index.ts)_
155
-
156
- ```ts
157
- import { McpServer } from "skybridge/server";
158
- import { z } from "zod";
159
-
160
- const server = new McpServer({ name: "my-app", version: "1.0" }, {})
161
- .widget("search-voyage", {}, {
162
- description: "Search for trips",
163
- inputSchema: {
164
- destination: z.string(),
165
- departureDate: z.string().optional(),
166
- },
167
- outputSchema: {
168
- results: z.array(z.object({ id: z.string(), name: z.string() })),
169
- totalCount: z.number(),
170
- },
171
- }, async ({ destination }) => {
172
- // Your tool logic here...
173
- return { content: [{ type: "text", text: `Found trips to ${destination}` }] };
174
- })
175
- .widget("get-details", {}, {
176
- inputSchema: { tripId: z.string() },
177
- }, async ({ tripId }) => {
178
- return { content: [{ type: "text", text: `Details for ${tripId}` }] };
179
- });
180
-
181
- // Export the server type for the client
182
- export type AppType = typeof server;
183
- ```
184
-
185
- _One-time setup (web/src/skybridge.ts)_
186
-
187
- Create typed hooks once and export them for use across your app. This file acts as a bridge between your server types and your widgets:
188
-
189
- ```ts
190
- import type { AppType } from "../server"; // type-only import
191
- import { generateHelpers } from "skybridge/web";
192
-
193
- export const { useCallTool, useToolInfo } = generateHelpers<AppType>();
194
82
  ```
195
83
 
196
- _Usage in widgets (web/src/widgets/search.tsx)_
84
+ ### Widget
197
85
 
198
86
  ```tsx
199
- import { useCallTool, useToolInfo } from "../skybridge"; // import typed hooks
200
-
201
- export function SearchWidget() {
202
- const { callTool, data, isPending } = useCallTool("search-voyage");
203
- // ^ autocomplete for tool names
204
- const toolInfo = useToolInfo<"search-voyage">();
205
- // ^ autocomplete for widget names
206
-
207
- const handleSearch = () => {
208
- callTool({ destination: "Spain" });
209
- // ^ autocomplete for input fields
210
- };
211
-
212
- return (
213
- <div>
214
- <button onClick={handleSearch} disabled={isPending}>
215
- Search
216
- </button>
217
- {toolInfo.isSuccess && (
218
- <div>Found {toolInfo.output.structuredContent.totalCount} results</div>
219
- // ^ typed output
220
- )}
221
- </div>
222
- );
223
- }
224
- ```
225
-
226
- **Hooks**
227
-
228
- The `skybridge/web` package comes with a set of hooks to help you build your widgets :
229
-
230
- - `useOpenAiGlobal`: A generic hook to get any global data from the OpenAI iFrame skybridge runtime (in `window.openai`).
231
- - `useToolOutput`: A hook to get the initial tool `structuredContent` returned when rendering the widget for the first time. The data inside this hook is not updated when the tool is called again.
232
- - `useToolResponseMetadata`: A hook to get the initial tool `meta` returned when rendering the widget for the first time. The data inside this hook is not updated when the tool is called again.
233
- - `useToolInfo`: A hook to get the tool input, output, and response metadata with type inference. Provides a discriminated union based on status (pending/success).
234
- - `useCallTool`: A @tanstack/react-query inspired hook to send make additional tool calls inside a widget.
235
- - `generateHelpers`: A factory that creates typed versions of `useCallTool` and `useToolInfo` with full type inference from your server type.
236
-
237
- _useOpenAiGlobal_
238
-
239
- ```ts
240
- import { useOpenAiGlobal } from "skybridge/web";
241
-
242
- const theme = useOpenAiGlobal("theme");
243
- ```
244
-
245
- _useToolOutput_
246
-
247
- ```ts
248
- import { useToolOutput } from "skybridge/web";
249
-
250
- const toolOutput = useToolOutput();
251
- ```
252
-
253
- _useToolResponseMetadata_
254
-
255
- ```ts
256
- import { useToolResponseMetadata } from "skybridge/web";
257
-
258
- const toolResponseMetadata = useToolResponseMetadata();
259
- ```
260
-
261
- _useToolInfo_
262
-
263
- ```ts
264
87
  import { useToolInfo } from "skybridge/web";
265
88
 
266
- const toolInfo = useToolInfo<{
267
- input: { query: string };
268
- output: { results: string[] };
269
- responseMetadata: { id: number };
270
- }>();
271
-
272
- // toolInfo.input is typed based on the input type
273
- // toolInfo.output.structuredContent is typed based on the output type (undefined when pending)
274
- // toolInfo.status narrows correctly: "pending" | "success"
89
+ function FlightsWidget() {
90
+ const { output } = useToolInfo();
275
91
 
276
- if (toolInfo.isPending) {
277
- // toolInfo.output is undefined here (pending state)
278
- console.log(toolInfo.input.query);
279
- }
280
-
281
- if (toolInfo.isSuccess) {
282
- // toolInfo.output.structuredContent is typed here
283
- console.log(toolInfo.output.structuredContent.results);
92
+ return output.structuredContent.flights.map(f =>
93
+ <FlightCard key={f.id} flight={f} />
94
+ );
284
95
  }
285
96
  ```
286
97
 
287
- _useToolInfo_ with typed hooks (recommended)
98
+ <br />
288
99
 
289
- ```tsx
290
- import { useToolInfo } from "../skybridge"; // import typed hooks
291
-
292
- export function SearchWidget() {
293
- const toolInfo = useToolInfo<"search-voyage">();
294
- // ^ autocomplete for widget names
295
- // toolInfo.input is typed as { destination: string; departureDate?: string; ... }
296
- // toolInfo.output.structuredContent is typed as { results: Array<...>; totalCount: number; }
297
-
298
- if (toolInfo.isSuccess) {
299
- return <div>Found {toolInfo.output.structuredContent.totalCount} results</div>;
300
- }
100
+ ## 🎯 Features at a Glance
301
101
 
302
- return <div>Searching for {toolInfo.input.destination}...</div>;
303
- }
304
- ```
102
+ - **Live Reload** — Vite HMR. See changes instantly without reinstalling.
103
+ - **Typed Hooks** — Full autocomplete for tools, inputs, outputs.
104
+ - **Widget → Tool Calls** — Trigger server actions from UI.
105
+ - **Dual Surface Sync** — Keep model aware of what users see with `data-llm`.
106
+ - **React Query-style API** — `isPending`, `isError`, callbacks.
107
+ - **MCP Compatible** — Extends the official SDK. Works with any MCP client.
305
108
 
306
- _useCallTool_ in synchronous mode
109
+ <br />
307
110
 
308
- ```ts
309
- import { useCallTool } from "skybridge/web";
310
-
311
- export const TestTool: React.FunctionComponent = () => {
312
- const { callTool, isPending } = useCallTool("myToolName");
313
-
314
- return (
315
- <div>
316
- <button
317
- disabled={isPending}
318
- onClick={() => {
319
- callTool({ input: "test input" }, {
320
- onSuccess: (data) => {
321
- alert("Tool returned: " + data);
322
- },
323
- });
324
- >
325
- Call Tool inside a widget
326
- </button>
327
- </div>
328
- );
329
- };
330
- ```
331
-
332
- _useCallTool_ in asynchronous mode
333
-
334
- ```ts
335
- import { useCallTool } from "skybridge/web";
336
-
337
- export const TestTool: React.FunctionComponent = () => {
338
- const { callToolAsync, isPending } = useCallTool("myToolName");
339
-
340
- return (
341
- <div>
342
- <button
343
- disabled={isPending}
344
- onClick={async () => {
345
- const data = await callToolAsync({ input: "test input" });
346
- alert("Tool returned: " + data);
347
- }}
348
- >
349
- Call Tool inside a widget
350
- </button>
351
- </div>
352
- );
353
- };
354
- ```
111
+ <div align="center">
355
112
 
356
- ## Migrate your existing MCP server to a ChatGPT app
113
+ [![GitHub Discussions](https://img.shields.io/badge/Discussions-Ask%20Questions-blue?style=flat-square&logo=github)](https://github.com/alpic-ai/skybridge/discussions)
114
+ [![GitHub Issues](https://img.shields.io/badge/Issues-Report%20Bugs-red?style=flat-square&logo=github)](https://github.com/alpic-ai/skybridge/issues)
115
+ [![Discord](https://img.shields.io/badge/Discord-Chat-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.com/invite/gNAazGueab)
357
116
 
358
- If you're already using the `@modelcontextprotocol/sdk` to build a MCP server, you can migrate to a ChatGPT app by following these steps:
117
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions
359
118
 
360
- 1. Replace your `McpServer` import from `@modelcontextprotocol/sdk` with the same import from `skybridge/server`
361
- 2. Create a new vite project in a folder named `web` and install the `skybridge` package
362
- 3. Replace the `vite.config.ts` file with the following:
119
+ <br />
363
120
 
364
- ```ts
365
- import { defineConfig } from "vite";
366
- import { skybridge } from "skybridge/web";
121
+ **[GPL-3.0 License](LICENSE)** · Made with ❤️ by **[Alpic](https://alpic.ai)**
367
122
 
368
- export default defineConfig({
369
- plugins: [skybridge()],
370
- });
371
- ```
123
+ </div>
@@ -1,4 +1,4 @@
1
+ export type { AnyToolRegistry, InferTools, ToolInput, ToolNames, ToolOutput, ToolResponseMetadata, } from "./inferUtilityTypes.js";
2
+ export type { McpServerTypes, ToolDef } from "./server.js";
1
3
  export { McpServer } from "./server.js";
2
4
  export { widgetsDevServer } from "./widgetsDevServer.js";
3
- export type { ToolDef, McpServerTypes } from "./server.js";
4
- export type { InferTools, AnyToolRegistry, ToolNames, ToolInput, ToolOutput, } from "./inferUtilityTypes.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -51,4 +51,14 @@ export type ToolInput<ServerType, ToolName extends ToolNames<ServerType>> = Extr
51
51
  * ```
52
52
  */
53
53
  export type ToolOutput<ServerType, ToolName extends ToolNames<ServerType>> = ExtractTool<ServerType, ToolName>["output"];
54
+ /**
55
+ * Get the responseMetadata type for a specific tool (widget or regular tool).
56
+ * This is inferred from the `_meta` property of the tool callback's return value.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * type SearchMeta = ToolResponseMetadata<MyServer, "search">;
61
+ * ```
62
+ */
63
+ export type ToolResponseMetadata<ServerType, ToolName extends ToolNames<ServerType>> = ExtractTool<ServerType, ToolName>["responseMetadata"];
54
64
  export {};
@@ -1,16 +1,23 @@
1
- import { McpServer as McpServerBase, type RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { Resource, ToolAnnotations, CallToolResult, ServerRequest, ServerNotification } from "@modelcontextprotocol/sdk/types.js";
1
+ import type { RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import type { AnySchema, SchemaOutput, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
3
4
  import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
- import type { ZodRawShape, ZodObject, infer as Infer } from "zod";
5
- export type ToolDef<TInput = unknown, TOutput = unknown> = {
5
+ import type { CallToolResult, Resource, ServerNotification, ServerRequest, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
6
+ export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unknown> = {
6
7
  input: TInput;
7
8
  output: TOutput;
9
+ responseMetadata: TResponseMetadata;
8
10
  };
9
11
  type McpServerOriginalResourceConfig = Omit<Resource, "uri" | "name" | "mimeType">;
10
- type McpServerOriginalToolConfig = Omit<Parameters<McpServerBase["registerTool"]>[1], "inputSchema" | "outputSchema">;
12
+ type McpServerOriginalToolConfig = Omit<Parameters<typeof McpServerBase.prototype.registerTool<ZodRawShapeCompat, ZodRawShapeCompat>>[1], "inputSchema" | "outputSchema">;
11
13
  type ExtractStructuredContent<T> = T extends {
12
14
  structuredContent: infer SC;
13
15
  } ? SC : never;
16
+ type ExtractMeta<T> = Extract<T, {
17
+ _meta: unknown;
18
+ }> extends {
19
+ _meta: infer M;
20
+ } ? M : unknown;
14
21
  /**
15
22
  * Type-level marker interface for cross-package type inference.
16
23
  * This enables TypeScript to infer tool types across package boundaries
@@ -23,26 +30,34 @@ type ExtractStructuredContent<T> = T extends {
23
30
  export interface McpServerTypes<TTools extends Record<string, ToolDef> = {}> {
24
31
  readonly tools: TTools;
25
32
  }
26
- type AddTool<TTools, TName extends string, TInput extends ZodRawShape, TOutput> = McpServer<TTools & {
27
- [K in TName]: ToolDef<Infer<ZodObject<TInput>>, TOutput>;
33
+ type Simplify<T> = {
34
+ [K in keyof T]: T[K];
35
+ };
36
+ type ShapeOutput<Shape extends ZodRawShapeCompat> = Simplify<{
37
+ [K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? never : K]: SchemaOutput<Shape[K]>;
38
+ } & {
39
+ [K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? K : never]?: SchemaOutput<Shape[K]>;
40
+ }>;
41
+ type AddTool<TTools, TName extends string, TInput extends ZodRawShapeCompat, TOutput, TResponseMetadata = unknown> = McpServer<TTools & {
42
+ [K in TName]: ToolDef<ShapeOutput<TInput>, TOutput, TResponseMetadata>;
28
43
  }>;
29
- type ToolConfig<TInput extends ZodRawShape> = {
44
+ type ToolConfig<TInput extends ZodRawShapeCompat | AnySchema> = {
30
45
  title?: string;
31
46
  description?: string;
32
47
  inputSchema?: TInput;
33
- outputSchema?: ZodRawShape;
48
+ outputSchema?: ZodRawShapeCompat | AnySchema;
34
49
  annotations?: ToolAnnotations;
35
50
  _meta?: Record<string, unknown>;
36
51
  };
37
- type ToolHandler<TInput extends ZodRawShape, TReturn extends CallToolResult = CallToolResult> = (args: Infer<ZodObject<TInput>>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
52
+ type ToolHandler<TInput extends ZodRawShapeCompat, TReturn extends CallToolResult = CallToolResult> = (args: ShapeOutput<TInput>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
38
53
  export declare class McpServer<TTools extends Record<string, ToolDef> = {}> extends McpServerBase {
39
54
  readonly $types: McpServerTypes<TTools>;
40
- widget<TName extends string, TInput extends ZodRawShape, TReturn extends CallToolResult>(name: TName, resourceConfig: McpServerOriginalResourceConfig, toolConfig: McpServerOriginalToolConfig & {
55
+ registerWidget<TName extends string, TInput extends ZodRawShapeCompat, TReturn extends CallToolResult>(name: TName, resourceConfig: McpServerOriginalResourceConfig, toolConfig: McpServerOriginalToolConfig & {
41
56
  inputSchema?: TInput;
42
- outputSchema?: ZodRawShape;
43
- }, toolCallback: ToolHandler<TInput, TReturn>): AddTool<TTools, TName, TInput, ExtractStructuredContent<TReturn>>;
44
- registerTool<TName extends string, InputArgs extends ZodRawShape, TReturn extends CallToolResult>(name: TName, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs, TReturn>): AddTool<TTools, TName, InputArgs, ExtractStructuredContent<TReturn>>;
45
- registerTool<InputArgs extends ZodRawShape>(name: string, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs>): RegisteredTool;
57
+ outputSchema?: ZodRawShapeCompat | AnySchema;
58
+ }, toolCallback: ToolHandler<TInput, TReturn>): AddTool<TTools, TName, TInput, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
59
+ registerTool<TName extends string, InputArgs extends ZodRawShapeCompat, TReturn extends CallToolResult>(name: TName, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs, TReturn>): AddTool<TTools, TName, InputArgs, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
60
+ registerTool<InputArgs extends ZodRawShapeCompat>(name: string, config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs>): RegisteredTool;
46
61
  private lookupDistFile;
47
62
  }
48
63
  export {};
@@ -1,9 +1,9 @@
1
- import { McpServer as McpServerBase, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { templateHelper } from "./templateHelper.js";
3
1
  import { readFileSync } from "node:fs";
4
2
  import path from "node:path";
3
+ import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { templateHelper } from "./templateHelper.js";
5
5
  export class McpServer extends McpServerBase {
6
- widget(name, resourceConfig, toolConfig, toolCallback) {
6
+ registerWidget(name, resourceConfig, toolConfig, toolCallback) {
7
7
  const uri = `ui://widgets/${name}.html`;
8
8
  const resourceMetadata = {
9
9
  ...(resourceConfig._meta ?? {}),
@@ -11,7 +11,7 @@ export class McpServer extends McpServerBase {
11
11
  if (toolConfig.description !== undefined) {
12
12
  resourceMetadata["openai/widgetDescription"] = toolConfig.description;
13
13
  }
14
- this.resource(name, uri, {
14
+ this.registerResource(name, uri, {
15
15
  ...resourceConfig,
16
16
  _meta: resourceMetadata,
17
17
  }, async (_uri, extra) => {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,IAAI,aAAa,GAG3B,MAAM,yCAAyC,CAAC;AAUjD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAkG7B,MAAM,OAAO,SAEX,SAAQ,aAAa;IAGrB,MAAM,CAKJ,IAAW,EACX,cAA+C,EAC/C,UAGC,EACD,YAA0C;QAE1C,MAAM,GAAG,GAAG,gBAAgB,IAAI,OAAO,CAAC;QACxC,MAAM,gBAAgB,GAAiB;YACrC,GAAG,CAAC,cAAc,CAAC,KAAK,IAAI,EAAE,CAAC;SAChC,CAAC;QACF,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACzC,gBAAgB,CAAC,0BAA0B,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC;QACxE,CAAC;QAED,IAAI,CAAC,QAAQ,CACX,IAAI,EACJ,GAAG,EACH;YACE,GAAG,cAAc;YACjB,KAAK,EAAE,gBAAgB;SACxB,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YACpB,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnC,CAAC,CAAC,WACE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC;oBACjD,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAC/B,EAAE;gBACJ,CAAC,CAAC,uBAAuB,CAAC;YAE9B,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC;oBAC9B,SAAS;oBACT,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,eAAe,IAAI,MAAM,CAAC;oBAC1D,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;iBAC5C,CAAC;gBACJ,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC;oBAC/B,SAAS;oBACT,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;YAET,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG;wBACH,QAAQ,EAAE,qBAAqB;wBAC/B,IAAI,EAAE,IAAI;qBACX;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,MAAM,QAAQ,GAAa;YACzB,GAAG,UAAU,CAAC,KAAK;YACnB,uBAAuB,EAAE,GAAG;YAC5B,gBAAgB,EAAE,GAAG;SACtB,CAAC;QAEF,IAAI,CAAC,YAAY,CACf,IAAI,EACJ;YACE,GAAG,UAAU;YACb,KAAK,EAAE,QAAQ;SAChB,EACD,YAAY,CACb,CAAC;QAEF,OAAO,IAAyE,CAAC;IACnF,CAAC;IAkBQ,YAAY,CACnB,IAAY,EACZ,MAA6B,EAC7B,EAA2B;QAE3B,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,cAAc,CAAC,GAAW;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,YAAY,CACV,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC,EACpE,OAAO,CACR,CACF,CAAC;QAEF,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAK7B,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAcrF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA2HrD,MAAM,OAAO,SAEX,SAAQ,aAAa;IAGrB,cAAc,CAKZ,IAAW,EACX,cAA+C,EAC/C,UAGC,EACD,YAA0C;QAQ1C,MAAM,GAAG,GAAG,gBAAgB,IAAI,OAAO,CAAC;QACxC,MAAM,gBAAgB,GAAiB;YACrC,GAAG,CAAC,cAAc,CAAC,KAAK,IAAI,EAAE,CAAC;SAChC,CAAC;QACF,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACzC,gBAAgB,CAAC,0BAA0B,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC;QACxE,CAAC;QAED,IAAI,CAAC,gBAAgB,CACnB,IAAI,EACJ,GAAG,EACH;YACE,GAAG,cAAc;YACjB,KAAK,EAAE,gBAAgB;SACxB,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YACpB,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnC,CAAC,CAAC,WACE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC;oBACjD,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAC/B,EAAE;gBACJ,CAAC,CAAC,uBAAuB,CAAC;YAE9B,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;gBACnC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC;oBAC9B,SAAS;oBACT,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,eAAe,IAAI,MAAM,CAAC;oBAC1D,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;iBAC5C,CAAC;gBACJ,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC;oBAC/B,SAAS;oBACT,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;YAET,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG;wBACH,QAAQ,EAAE,qBAAqB;wBAC/B,IAAI,EAAE,IAAI;qBACX;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,MAAM,QAAQ,GAAa;YACzB,GAAG,UAAU,CAAC,KAAK;YACnB,uBAAuB,EAAE,GAAG;YAC5B,gBAAgB,EAAE,GAAG;SACtB,CAAC;QAEF,IAAI,CAAC,YAAY,CACf,IAAI,EACJ;YACE,GAAG,UAAU;YACb,KAAK,EAAE,QAAQ;SAChB,EACD,YAAY,CACb,CAAC;QAEF,OAAO,IAMN,CAAC;IACJ,CAAC;IAwBQ,YAAY,CACnB,IAAY,EACZ,MAA6B,EAC7B,EAA2B;QAE3B,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,cAAc,CAAC,GAAW;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,YAAY,CACV,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC,EACpE,OAAO,CACR,CACF,CAAC;QAEF,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAC7B,CAAC;CACF"}
@@ -1,7 +1,7 @@
1
- import Handlebars from "handlebars";
2
1
  import { readFileSync } from "node:fs";
3
- import { join, dirname } from "node:path";
2
+ import { dirname, join } from "node:path";
4
3
  import { fileURLToPath } from "node:url";
4
+ import Handlebars from "handlebars";
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = dirname(__filename);
7
7
  class TemplateHelper {
@@ -1 +1 @@
1
- {"version":3,"file":"templateHelper.js","sourceRoot":"","sources":["../../../src/server/templateHelper.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAOtC,MAAM,cAAc;IACV,aAAa,GAAG,IAAI,GAAG,EAAsC,CAAC;IAE9D,YAAY,CAAC,YAAoB;QACvC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC;QAC/C,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,YAAY,MAAM,CAAC,CAAC;QACzE,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gBAAgB,CAAC,IAIhB;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,iBAAiB,CAAC,IAA+C;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"templateHelper.js","sourceRoot":"","sources":["../../../src/server/templateHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,cAAc;IACV,aAAa,GAAG,IAAI,GAAG,EAAsC,CAAC;IAE9D,YAAY,CAAC,YAAoB;QACvC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC;QAC/C,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,YAAY,MAAM,CAAC,CAAC;QACzE,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gBAAgB,CAAC,IAIhB;QACC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,iBAAiB,CAAC,IAA+C;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
- import express, {} from "express";
2
- import cors from "cors";
3
1
  import path from "node:path";
2
+ import cors from "cors";
3
+ import express, {} from "express";
4
4
  /**
5
5
  * Install Vite dev server
6
6
  * This router MUST be installed at the application root, like so:
@@ -17,7 +17,7 @@ export const widgetsDevServer = async () => {
17
17
  const workspaceRoot = searchForWorkspaceRoot(process.cwd());
18
18
  const webAppRoot = path.join(workspaceRoot, "web");
19
19
  const configResult = await loadConfigFromFile({ command: "serve", mode: "development" }, path.join(webAppRoot, "vite.config.ts"), webAppRoot);
20
- // Remove build-specific options that don't apply to dev server
20
+ // biome-ignore lint/correctness/noUnusedVariables: Remove build-specific options that don't apply to dev server
21
21
  const { build, preview, ...devConfig } = configResult?.config || {};
22
22
  const vite = await createServer({
23
23
  ...devConfig,
@@ -1 +1 @@
1
- {"version":3,"file":"widgetsDevServer.js","sourceRoot":"","sources":["../../../src/server/widgetsDevServer.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAuB,MAAM,SAAS,CAAC;AACvD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAA6B,EAAE;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhC,MAAM,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAChE,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAEnD,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAC3C,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EACzC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EACvC,UAAU,CACX,CAAC;IAEF,+DAA+D;IAC/D,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,YAAY,EAAE,MAAM,IAAI,EAAE,CAAC;IAEpE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC;QAC9B,GAAG,SAAS;QACZ,UAAU,EAAE,KAAK,EAAE,kFAAkF;QACrG,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE;YACN,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;SACrB;QACD,IAAI,EAAE,UAAU;QAChB,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACvC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
1
+ {"version":3,"file":"widgetsDevServer.js","sourceRoot":"","sources":["../../../src/server/widgetsDevServer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,EAAE,EAAuB,MAAM,SAAS,CAAC;AAEvD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAA6B,EAAE;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEhC,MAAM,EAAE,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAChE,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,aAAa,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAEnD,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAC3C,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,EACzC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EACvC,UAAU,CACX,CAAC;IAEF,gHAAgH;IAChH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,YAAY,EAAE,MAAM,IAAI,EAAE,CAAC;IAEpE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC;QAC9B,GAAG,SAAS;QACZ,UAAU,EAAE,KAAK,EAAE,kFAAkF;QACrG,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE;YACN,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;SACrB;QACD,IAAI,EAAE,UAAU;QAChB,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACvC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}