Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
231251a
chore: switch peer deps to @modelcontextprotocol/{client,server}@2 (l…
felixweinberger Apr 9, 2026
b50315b
refactor(types): v2 import paths; capabilities interface->type; sdk-c…
felixweinberger Apr 9, 2026
a9713e3
refactor: standalone EventDispatcher (no SDK coupling); PostMessageTr…
felixweinberger Apr 9, 2026
25da665
refactor(app): App composes Client + ExtensionHandle (SEP-1865 role a…
felixweinberger Apr 9, 2026
a1f1f01
refactor(app-bridge): AppBridge composes Server + ExtensionHandle
felixweinberger Apr 9, 2026
a537873
refactor(react,server): v2 import paths; registerAppTool on v2 McpServer
felixweinberger Apr 9, 2026
ea3f4af
wip(build): exclude examples/tests from tsc pending port; add BREAKIN…
felixweinberger Apr 9, 2026
1347a08
fix: JSDoc */ terminator in app-bridge; schema.test.ts v2 imports
felixweinberger Apr 9, 2026
2c119a5
fix: nested capability interfaces->type for JSONObject; drop Extensio…
felixweinberger Apr 9, 2026
a97206c
fix: schema-inference casts at z.custom boundary; regenerate schemas;…
felixweinberger Apr 9, 2026
953a5d8
build: external Node builtins from with-deps browser bundles (v2 SDK …
felixweinberger Apr 9, 2026
87fee34
fix: re-export EXTENSION_ID/getUiCapability; getHostContext() undefin…
felixweinberger Apr 9, 2026
7e8ae10
test: port app-bridge.test.ts to composition shape (73 pass, 8 skip, …
felixweinberger Apr 9, 2026
f7490c6
fix: alias getters for .toBe() identity; visibility empty-array; getT…
felixweinberger Apr 9, 2026
9998758
docs: port companion *.examples.ts(x) and docs/patterns.tsx to v2 imp…
felixweinberger Apr 9, 2026
570781e
examples: port all workspaces to v2 imports + @modelcontextprotocol/{…
felixweinberger Apr 9, 2026
47f4cdf
fix(app-bridge): v1 parity — setHostContext diffing, hostContext accu…
felixweinberger Apr 9, 2026
be67283
fix(server): bidirectional _meta.ui<->flat resourceUri sync (v1 parity)
felixweinberger Apr 9, 2026
cce8436
test: fix type errors; un-skip implemented tests; delete tests for dr…
felixweinberger Apr 9, 2026
4298d34
examples: drop v1 inputSchema:{} shape; vite external Node builtins; …
felixweinberger Apr 9, 2026
b845fd7
test: scope npm test to SDK + ported example tests; add test:full for…
felixweinberger Apr 9, 2026
4e26407
chore: revert browser-bundle external workaround (fixed upstream by t…
felixweinberger Apr 9, 2026
76b3ba7
examples: import StdioServerTransport from /stdio subpath (typescript…
felixweinberger Apr 9, 2026
c8bc264
refactor: eliminate sdk-compat.ts via isSpecType() (typescript-sdk#1887)
felixweinberger Apr 13, 2026
60e9d69
refactor: pass specTypeSchema() directly to ExtensionHandle (typescri…
felixweinberger Apr 13, 2026
8695d3a
feat: v1↔v2 wire-compat shims + interop docs
felixweinberger Apr 13, 2026
6365821
chore: port .examples.ts companions, fix all example builds, typedoc …
felixweinberger Apr 13, 2026
0464603
fix(pdf-server): port to v2 (raw-shape inputSchema → z.object, .tool→…
felixweinberger Apr 13, 2026
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
104 changes: 104 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# ext-apps v2 — Breaking Changes

This release moves ext-apps from `@modelcontextprotocol/sdk@^1` to
`@modelcontextprotocol/client@^2` + `@modelcontextprotocol/server@^2`. The
public method surface (`app.callServerTool()`, `app.openLink()`,
`bridge.sendToolInput()`, every `on*` handler, `addEventListener`) is preserved.
The breaks below are at the inheritance/import boundary.

## Dependencies

| v1 | v2 |
|---|---|
| `@modelcontextprotocol/sdk` (peer) | `@modelcontextprotocol/client` (peer) + `@modelcontextprotocol/server` (peer, optional unless you use `app-bridge` or `server`) |

## `App` and `AppBridge` no longer extend `Protocol`

v1 subclassed the SDK's `Protocol` class. v2 composes `Client`/`Server`
instances instead. If you were calling inherited `Protocol` members directly:

| Removed inherited member | Replacement |
|---|---|
| `app.request(...)` / `app.notification(...)` | `app.ui.sendRequest(...)` / `app.ui.sendNotification(...)` for `ui/*`; `app.client.callTool(...)` etc. for standard MCP |
| `app.setRequestHandler(...)` | `app.ui.setRequestHandler(...)` (custom) or `app.client.setRequestHandler(...)` (standard) |
| `bridge.setRequestHandler(...)` | `bridge.ui.setRequestHandler(...)` or `bridge.server.setRequestHandler(...)` |
| `instanceof Protocol` | `app.client` is a `Client`, `bridge.server` is a `Server` |
| `assertCapabilityForMethod` etc. | Removed (were no-ops) |

`app.transport` / `app.onerror` / `app.close()` are kept as forwarding shims.

## `RequestHandlerExtra` slimmed

The second argument to `on*` request handlers is now `{ signal: AbortSignal }`
only. v1 passed the full SDK `RequestHandlerExtra` (sessionId, sendNotification,
etc.). If you need the full SDK context, register directly via
`app.ui.setRequestHandler(method, schema, (params, ctx) => …)` — `ctx` is the
SDK's `BaseContext`.

## Wire-protocol method renames

These affect custom hosts/iframes that bypass the SDK and speak raw JSON-RPC:

| v1 method | v2 method | Why |
|---|---|---|
| `notifications/message` (App→Host) | `ui/log` | v1 direction conflicted with core MCP semantics (SEP-1865 erratum candidate) |
| `tools/call` (Host→App) | `ui/call-view-tool` | Non-spec direction; renamed to a `ui/*` custom method |
| `tools/list` (Host→App) | `ui/list-view-tools` | Same |

The TypeScript API names (`app.sendLog`, `bridge.callTool`, `app.oncalltool`)
are **unchanged** — only the wire-level method strings moved.

### v1↔v2 interop

Hosts and iframes upgrade independently. The wire renames are shimmed where the
v2 SDK's direction enforcement allows it; where it doesn't, you get a clear
error instead of silent failure.

| Scenario | What works | What doesn't |
|---|---|---|
| **v2 host (`AppBridge`) + v1 iframe** | ✅ handshake (`ui/initialize`), all `ui/*` requests, **logging** (host dual-listens on both `ui/log` and legacy `notifications/message`), proxied `tools/call`/`resources/*` | ⚠️ `bridge.callTool()`/`bridge.listTools()` throw a descriptive error — host→iframe tool calls require the iframe on v2 |
| **v1 host + v2 iframe** | ✅ handshake (v2 `App` still sends `ui/initialize`), all `ui/*` requests, proxied standard MCP | ❌ `app.sendLog()` (sends `ui/log`; v1 host listens on `notifications/message` only — silently dropped). ❌ host-initiated `tools/call` (v2 iframe handles `ui/call-view-tool` only — MethodNotFound) |

**Recommended upgrade order:** host first, then iframes. A v2 host accepts logs
from either generation; a v2 iframe's logs reach only a v2 host.

## Capability negotiation via SEP-2133

`McpUiAppCapabilities` / `McpUiHostCapabilities` now travel in
`capabilities.extensions["io.modelcontextprotocol/ui"]` during the standard MCP
`initialize` exchange. `app.hostCapabilities` and `bridge.appCapabilities` read
from there. `ui/initialize` is kept (for `hostContext` delivery and v1 wire
compat) but no longer the sole capability source.

`McpUiAppCapabilities` and `McpUiHostCapabilities` are now `type` aliases (were
`interface`) to satisfy `JSONObject`.

## `ProtocolWithEvents` → `EventDispatcher`

`src/events.ts` no longer extends `Protocol`. The class is renamed to
`EventDispatcher`; a `ProtocolWithEvents` alias is kept for one release.
`replaceRequestHandler` and the throw-on-double-set behavior are removed
(handlers are now eagerly registered with field-based delegation).

## Import path changes

| v1 import | v2 |
|---|---|
| `@modelcontextprotocol/sdk/types.js` | `@modelcontextprotocol/client` (types are re-exported there) |
| `@modelcontextprotocol/sdk/client/index.js` | `@modelcontextprotocol/client` |
| `@modelcontextprotocol/sdk/server/mcp.js` | `@modelcontextprotocol/server` |
| `@modelcontextprotocol/sdk/shared/transport.js` | `@modelcontextprotocol/client` |

## `server` entry point

`registerAppTool` / `registerAppResource` now take v2 `McpServer` and
`StandardSchemaWithJSON` (was v1 `ZodRawShapeCompat | AnySchema`). The call
shape is otherwise unchanged. `BaseToolCallback` re-export removed (use
`ToolCallback` from `@modelcontextprotocol/server`).

## Validation depth

Zod schemas for SDK-defined shapes (`CallToolResult`, `ContentBlock`, …) are now
type-preserving pass-throughs (`z.custom<T>`) rather than deep validators (see
`src/sdk-compat.ts`). Validation of those shapes is the SDK's job at the actual
MCP boundary; ext-apps relays them unchanged.
2 changes: 1 addition & 1 deletion build.bun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function buildJs(

// zod is a peerDependency — keep it external so consumers share a single
// zod instance (instanceof ZodError / schema.extend() break with duplicate copies).
const PEER_EXTERNALS = ["@modelcontextprotocol/sdk", "zod"];
const PEER_EXTERNALS = ["@modelcontextprotocol/client", "@modelcontextprotocol/server", "zod"];

await Promise.all([
buildJs("src/app.ts", {
Expand Down
13 changes: 6 additions & 7 deletions docs/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ registerAppTool(
"update-quantity",
{
description: "Update item quantity in cart",
inputSchema: { itemId: z.string(), quantity: z.number() },
inputSchema: z.object({ itemId: z.string(), quantity: z.number() }),
_meta: {
ui: {
resourceUri: "ui://shop/cart.html",
Expand Down Expand Up @@ -127,14 +127,14 @@ registerAppTool(
{
title: "Read Data Bytes",
description: "Load binary data in chunks",
inputSchema: {
inputSchema: z.object({
id: z.string().describe("Resource identifier"),
offset: z.number().min(0).default(0).describe("Byte offset"),
byteCount: z
.number()
.default(MAX_CHUNK_BYTES)
.describe("Bytes to read"),
},
}),
outputSchema: DataChunkSchema,
// Hidden from model - only callable by the App
_meta: { ui: { visibility: ["app"] } },
Expand Down Expand Up @@ -281,10 +281,9 @@ server.registerResource(

<!-- prettier-ignore -->
```ts source="./patterns.tsx#binaryBlobResourceClient"
const result = await app.request(
{ method: "resources/read", params: { uri: `video://${videoId}` } },
ReadResourceResultSchema,
);
const result = await app.readServerResource({
uri: `video://${videoId}`,
});

const content = result.contents[0];
if (!content || !("blob" in content)) {
Expand Down
17 changes: 8 additions & 9 deletions docs/patterns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ import { randomUUID } from "node:crypto";
import type {
CallToolResult,
ReadResourceResult,
} from "@modelcontextprotocol/sdk/types.js";
import { ReadResourceResultSchema } from "@modelcontextprotocol/sdk/types.js";
} from "@modelcontextprotocol/client";

import type { McpUiHostContext } from "../src/types.js";
import { useEffect, useState } from "react";
import { useApp } from "../src/react/index.js";
import { registerAppTool } from "../src/server/index.js";
import {
McpServer,
ResourceTemplate,
} from "@modelcontextprotocol/sdk/server/mcp.js";
} from "@modelcontextprotocol/server";
import { z } from "zod";

/**
Expand Down Expand Up @@ -117,14 +117,14 @@ function chunkedDataServer(server: McpServer) {
{
title: "Read Data Bytes",
description: "Load binary data in chunks",
inputSchema: {
inputSchema: z.object({
id: z.string().describe("Resource identifier"),
offset: z.number().min(0).default(0).describe("Byte offset"),
byteCount: z
.number()
.default(MAX_CHUNK_BYTES)
.describe("Bytes to read"),
},
}),
outputSchema: DataChunkSchema,
// Hidden from model - only callable by the App
_meta: { ui: { visibility: ["app"] } },
Expand Down Expand Up @@ -252,10 +252,9 @@ function binaryBlobResourceServer(
*/
async function binaryBlobResourceClient(app: App, videoId: string) {
//#region binaryBlobResourceClient
const result = await app.request(
{ method: "resources/read", params: { uri: `video://${videoId}` } },
ReadResourceResultSchema,
);
const result = await app.readServerResource({
uri: `video://${videoId}`,
});

const content = result.contents[0];
if (!content || !("blob" in content)) {
Expand Down
12 changes: 6 additions & 6 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ import {
registerAppTool,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { McpServer } from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";

Expand All @@ -205,7 +205,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time.",
inputSchema: {},

_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async () => {
Expand Down Expand Up @@ -240,10 +240,10 @@ export function createServer(): McpServer {

<!-- prettier-ignore -->
```ts source="../examples/quickstart/main.ts"
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { createMcpExpressApp } from "@modelcontextprotocol/express";
import type { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { NodeStreamableHTTPServerTransport as StreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
Expand Down
6 changes: 4 additions & 2 deletions examples/basic-host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "^1.0.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"zod": "^4.1.13"
"zod": "^4.1.13",
"@modelcontextprotocol/server": "file:/tmp/modelcontextprotocol-server-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/express": "file:/tmp/modelcontextprotocol-express-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/node": "file:/tmp/modelcontextprotocol-node-2.0.0-alpha.2.tgz"
},
"devDependencies": {
"@types/express": "^5.0.0",
Expand Down
14 changes: 7 additions & 7 deletions examples/basic-host/src/implementation.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport, type McpUiResourceCsp, type McpUiResourcePermissions, buildAllowAttribute, type McpUiUpdateModelContextRequest, type McpUiMessageRequest } from "@modelcontextprotocol/ext-apps/app-bridge";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import type { CallToolResult, Resource, Tool } from "@modelcontextprotocol/sdk/types.js";
import { Client } from "@modelcontextprotocol/client";
import { SSEClientTransport } from "@modelcontextprotocol/client";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
import type { CallToolResult, Resource, Tool } from "@modelcontextprotocol/server";
import { getTheme, onThemeChange } from "./theme";
import { HOST_STYLE_VARIABLES } from "./host-styles";

Expand Down Expand Up @@ -303,7 +303,7 @@ export function newAppBridge(
// Listen for theme changes (from toggle or system) and notify the app
onThemeChange((newTheme) => {
log.info("Theme changed:", newTheme);
appBridge.sendHostContextChange({ theme: newTheme });
appBridge.sendHostContextChanged({ theme: newTheme });
});

// Per spec, the host SHOULD notify the view when container dimensions
Expand All @@ -315,7 +315,7 @@ export function newAppBridge(
const iframeResizeObserver = new ResizeObserver(([entry]) => {
const width = Math.round(entry.contentRect.width);
if (width > 0) {
appBridge.sendHostContextChange({
appBridge.sendHostContextChanged({
containerDimensions: { width, maxHeight: 6000 },
});
}
Expand Down Expand Up @@ -397,7 +397,7 @@ export function newAppBridge(
log.info("Display mode request from MCP App:", params);
const newMode = params.mode === "fullscreen" ? "fullscreen" : "inline";
// Update host context and notify the app
appBridge.sendHostContextChange({
appBridge.sendHostContextChanged({
displayMode: newMode,
});
// Notify the host UI (via callback)
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-host/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getToolUiResourceUri, McpUiToolMetaSchema } from "@modelcontextprotocol/ext-apps/app-bridge";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
import type { Tool } from "@modelcontextprotocol/server";
import { Component, type ErrorInfo, type ReactNode, StrictMode, Suspense, use, useEffect, useMemo, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import { callTool, connectToServer, hasAppHtml, initializeApp, loadSandboxProxy, log, newAppBridge, type ServerInfo, type ToolCallInfo, type ModelContext, type AppMessage } from "./implementation";
Expand Down
8 changes: 4 additions & 4 deletions examples/basic-server-preact/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { createMcpExpressApp } from "@modelcontextprotocol/express";
import type { McpServer } from "@modelcontextprotocol/server";
import { NodeStreamableHTTPServerTransport as StreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
Expand Down
6 changes: 4 additions & 2 deletions examples/basic-server-preact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "^1.0.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"preact": "^10.0.0",
"zod": "^4.1.13"
"zod": "^4.1.13",
"@modelcontextprotocol/server": "file:/tmp/modelcontextprotocol-server-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/express": "file:/tmp/modelcontextprotocol-express-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/node": "file:/tmp/modelcontextprotocol-node-2.0.0-alpha.2.tgz"
},
"devDependencies": {
"@preact/preset-vite": "^2.0.0",
Expand Down
6 changes: 3 additions & 3 deletions examples/basic-server-preact/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import { McpServer } from "@modelcontextprotocol/server";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
Expand Down Expand Up @@ -28,7 +28,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
inputSchema: {},

_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise<CallToolResult> => {
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-server-preact/src/mcp-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import type { CallToolResult } from "@modelcontextprotocol/server";
import { useCallback, useEffect, useState } from "preact/hooks";
import { render } from "preact";
import styles from "./mcp-app.module.css";
Expand Down
8 changes: 4 additions & 4 deletions examples/basic-server-react/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/

import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { createMcpExpressApp } from "@modelcontextprotocol/express";
import type { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { NodeStreamableHTTPServerTransport as StreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
Expand Down
6 changes: 4 additions & 2 deletions examples/basic-server-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "^1.0.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"zod": "^4.1.13"
"zod": "^4.1.13",
"@modelcontextprotocol/server": "file:/tmp/modelcontextprotocol-server-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/express": "file:/tmp/modelcontextprotocol-express-2.0.0-alpha.2.tgz",
"@modelcontextprotocol/node": "file:/tmp/modelcontextprotocol-node-2.0.0-alpha.2.tgz"
},
"devDependencies": {
"@types/cors": "^2.8.19",
Expand Down
Loading
Loading