skybridge 0.0.0-dev.8eed82d → 0.0.0-dev.8f4a954
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.
- package/README.md +8 -8
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/header.js.map +1 -1
- package/dist/cli/run-command.js.map +1 -1
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/cli/tunnel-control-server.d.ts +9 -0
- package/dist/cli/tunnel-control-server.js +31 -0
- package/dist/cli/tunnel-control-server.js.map +1 -0
- package/dist/cli/tunnel-control-server.test.js +39 -0
- package/dist/cli/tunnel-control-server.test.js.map +1 -0
- package/dist/cli/tunnel-handler.d.ts +3 -0
- package/dist/cli/tunnel-handler.js +48 -0
- package/dist/cli/tunnel-handler.js.map +1 -0
- package/dist/cli/tunnel-handler.test.js +105 -0
- package/dist/cli/tunnel-handler.test.js.map +1 -0
- package/dist/cli/tunnel.d.ts +57 -0
- package/dist/cli/tunnel.js +154 -0
- package/dist/cli/tunnel.js.map +1 -0
- package/dist/cli/tunnel.test.js +190 -0
- package/dist/cli/tunnel.test.js.map +1 -0
- package/dist/cli/types.js.map +1 -1
- package/dist/cli/use-execute-steps.js.map +1 -1
- package/dist/cli/use-messages.js.map +1 -1
- package/dist/cli/use-nodemon.js +11 -2
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-open-browser.d.ts +1 -0
- package/dist/cli/use-open-browser.js +44 -0
- package/dist/cli/use-open-browser.js.map +1 -0
- package/dist/cli/use-tunnel.d.ts +1 -1
- package/dist/cli/use-tunnel.js +102 -68
- package/dist/cli/use-tunnel.js.map +1 -1
- package/dist/cli/use-typescript-check.d.ts +1 -0
- package/dist/cli/use-typescript-check.js +41 -6
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.js +62 -7
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +33 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/status.js.map +1 -1
- package/dist/server/asset-base-url-transform-plugin.js +1 -1
- package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
- package/dist/server/asset-base-url-transform-plugin.test.js +29 -0
- package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/content-helpers.test.js +1 -1
- package/dist/server/content-helpers.test.js.map +1 -1
- package/dist/server/express.d.ts +1 -5
- package/dist/server/express.js +34 -10
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +249 -71
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/inferUtilityTypes.d.ts +6 -6
- package/dist/server/inferUtilityTypes.js.map +1 -1
- package/dist/server/metric.js.map +1 -1
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/server.d.ts +90 -40
- package/dist/server/server.js +150 -77
- package/dist/server/server.js.map +1 -1
- package/dist/server/templateHelper.d.ts +5 -7
- package/dist/server/templateHelper.js +3 -22
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.d.ts +4 -0
- package/dist/server/templates.generated.js +47 -0
- package/dist/server/templates.generated.js.map +1 -0
- package/dist/server/tunnel-proxy-router.d.ts +7 -0
- package/dist/server/tunnel-proxy-router.js +110 -0
- package/dist/server/tunnel-proxy-router.js.map +1 -0
- package/dist/server/tunnel-proxy-router.test.js +229 -0
- package/dist/server/tunnel-proxy-router.test.js.map +1 -0
- package/dist/server/viewsDevServer.d.ts +14 -0
- package/dist/server/{widgetsDevServer.js → viewsDevServer.js} +17 -5
- package/dist/server/viewsDevServer.js.map +1 -0
- package/dist/test/utils.d.ts +7 -7
- package/dist/test/utils.js +21 -21
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.d.ts +1 -0
- package/dist/test/{widget.test.js → view.test.js} +128 -59
- package/dist/test/view.test.js.map +1 -0
- package/dist/version.js +1 -3
- package/dist/version.js.map +1 -1
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +5 -3
- package/dist/web/bridges/apps-sdk/adaptor.js +19 -4
- package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -1
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.js.map +1 -1
- package/dist/web/bridges/apps-sdk/types.d.ts +8 -1
- package/dist/web/bridges/apps-sdk/types.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.js.map +1 -1
- package/dist/web/bridges/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +9 -7
- package/dist/web/bridges/mcp-app/adaptor.js +33 -30
- package/dist/web/bridges/mcp-app/adaptor.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +17 -9
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/bridges/use-host-context.js.map +1 -1
- package/dist/web/components/modal-provider.js +1 -1
- package/dist/web/components/modal-provider.js.map +1 -1
- package/dist/web/create-store.js +9 -9
- package/dist/web/create-store.js.map +1 -1
- package/dist/web/create-store.test.js +14 -16
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +1 -1
- package/dist/web/data-llm.js +3 -3
- package/dist/web/data-llm.js.map +1 -1
- package/dist/web/data-llm.test.js +22 -22
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +14 -14
- package/dist/web/generate-helpers.js +14 -14
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +26 -26
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/generate-helpers.test.js.map +1 -1
- package/dist/web/helpers/state.d.ts +2 -2
- package/dist/web/helpers/state.js +11 -11
- package/dist/web/helpers/state.js.map +1 -1
- package/dist/web/helpers/state.test.js +9 -9
- package/dist/web/helpers/state.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +3 -1
- package/dist/web/hooks/index.js +3 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +0 -4
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-files.js.map +1 -1
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-layout.js.map +1 -1
- package/dist/web/hooks/use-layout.test.js.map +1 -1
- package/dist/web/hooks/use-open-external.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-request-close.d.ts +2 -0
- package/dist/web/hooks/use-request-close.js +8 -0
- package/dist/web/hooks/use-request-close.js.map +1 -0
- package/dist/web/hooks/use-request-close.test.d.ts +1 -0
- package/dist/web/hooks/use-request-close.test.js +52 -0
- package/dist/web/hooks/use-request-close.test.js.map +1 -0
- package/dist/web/hooks/use-request-modal.d.ts +1 -1
- package/dist/web/hooks/use-request-modal.js +4 -4
- package/dist/web/hooks/use-request-modal.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +1 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.d.ts +3 -0
- package/dist/web/hooks/use-request-size.js +8 -0
- package/dist/web/hooks/use-request-size.js.map +1 -0
- package/dist/web/hooks/use-request-size.test.d.ts +1 -0
- package/dist/web/hooks/use-request-size.test.js +65 -0
- package/dist/web/hooks/use-request-size.test.js.map +1 -0
- package/dist/web/hooks/use-send-follow-up-message.d.ts +2 -1
- package/dist/web/hooks/use-send-follow-up-message.js +2 -2
- package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.d.ts +4 -0
- package/dist/web/hooks/use-view-state.js +32 -0
- package/dist/web/hooks/use-view-state.js.map +1 -0
- package/dist/web/hooks/use-view-state.test.d.ts +1 -0
- package/dist/web/hooks/{use-widget-state.test.js → use-view-state.test.js} +17 -17
- package/dist/web/hooks/use-view-state.test.js.map +1 -0
- package/dist/web/index.d.ts +1 -3
- package/dist/web/index.js +1 -2
- package/dist/web/index.js.map +1 -1
- package/dist/web/mount-view.d.ts +1 -0
- package/dist/web/{mount-widget.js → mount-view.js} +2 -2
- package/dist/web/mount-view.js.map +1 -0
- package/dist/web/plugin/data-llm.test.js.map +1 -1
- package/dist/web/plugin/plugin.d.ts +1 -1
- package/dist/web/plugin/plugin.js +87 -41
- package/dist/web/plugin/plugin.js.map +1 -1
- package/dist/web/plugin/scan-views.d.ts +16 -0
- package/dist/web/plugin/scan-views.js +88 -0
- package/dist/web/plugin/scan-views.js.map +1 -0
- package/dist/web/plugin/scan-views.test.d.ts +1 -0
- package/dist/web/plugin/scan-views.test.js +99 -0
- package/dist/web/plugin/scan-views.test.js.map +1 -0
- package/dist/web/plugin/transform-data-llm.js.map +1 -1
- package/dist/web/plugin/transform-data-llm.test.js.map +1 -1
- package/dist/web/plugin/{validate-widget.js → validate-view.js} +1 -1
- package/dist/web/plugin/validate-view.js.map +1 -0
- package/dist/web/plugin/validate-view.test.d.ts +1 -0
- package/dist/web/plugin/{validate-widget.test.js → validate-view.test.js} +6 -6
- package/dist/web/plugin/validate-view.test.js.map +1 -0
- package/dist/web/proxy.js.map +1 -1
- package/dist/web/types.js.map +1 -1
- package/package.json +26 -20
- package/dist/server/templates/development.hbs +0 -12
- package/dist/server/templates/production.hbs +0 -6
- package/dist/server/widgetsDevServer.d.ts +0 -3
- package/dist/server/widgetsDevServer.js.map +0 -1
- package/dist/test/widget.test.js.map +0 -1
- package/dist/web/hooks/use-widget-state.d.ts +0 -4
- package/dist/web/hooks/use-widget-state.js +0 -32
- package/dist/web/hooks/use-widget-state.js.map +0 -1
- package/dist/web/hooks/use-widget-state.test.js.map +0 -1
- package/dist/web/mount-widget.d.ts +0 -1
- package/dist/web/mount-widget.js.map +0 -1
- package/dist/web/plugin/scan-widgets.d.ts +0 -8
- package/dist/web/plugin/scan-widgets.js +0 -68
- package/dist/web/plugin/scan-widgets.js.map +0 -1
- package/dist/web/plugin/scan-widgets.test.js +0 -96
- package/dist/web/plugin/scan-widgets.test.js.map +0 -1
- package/dist/web/plugin/validate-widget.js.map +0 -1
- package/dist/web/plugin/validate-widget.test.js.map +0 -1
- /package/dist/{test/widget.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
- /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
- /package/dist/{web/plugin/scan-widgets.test.d.ts → cli/tunnel.test.d.ts} +0 -0
- /package/dist/{web/plugin/validate-widget.test.d.ts → server/tunnel-proxy-router.test.d.ts} +0 -0
- /package/dist/web/plugin/{validate-widget.d.ts → validate-view.d.ts} +0 -0
package/dist/server/server.d.ts
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
2
|
import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import type { AnySchema, SchemaOutput, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
4
4
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
5
|
-
import type { ContentBlock, ServerNotification, ServerRequest, ServerResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import type
|
|
5
|
+
import type { ContentBlock, Implementation, ServerNotification, ServerRequest, ServerResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { type ErrorRequestHandler, type Express, type RequestHandler } from "express";
|
|
7
7
|
import type { McpExtra, McpExtraFor, McpMethodString, McpMiddlewareFilter, McpMiddlewareFn, McpResultFor, McpTypedMiddlewareFn, McpWildcard } from "./middleware.js";
|
|
8
8
|
export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unknown> = {
|
|
9
9
|
input: TInput;
|
|
10
10
|
output: TOutput;
|
|
11
11
|
responseMetadata: TResponseMetadata;
|
|
12
12
|
};
|
|
13
|
-
export type
|
|
13
|
+
export type ViewHostType = "apps-sdk" | "mcp-app";
|
|
14
14
|
export interface ViewCsp {
|
|
15
|
+
/** Origins for static assets (images, fonts, scripts, styles). */
|
|
15
16
|
resourceDomains?: string[];
|
|
17
|
+
/** Origins the view may contact via fetch/XHR. */
|
|
16
18
|
connectDomains?: string[];
|
|
19
|
+
/** Origins allowed for iframe embeds (opts into stricter app review). */
|
|
17
20
|
frameDomains?: string[];
|
|
21
|
+
/** Origins that can receive openExternal redirects without the safe-link modal. */
|
|
18
22
|
redirectDomains?: string[];
|
|
23
|
+
/** Origins allowed in `<base href>` tags (mcp-apps only). */
|
|
19
24
|
baseUriDomains?: string[];
|
|
20
25
|
}
|
|
21
|
-
export interface
|
|
26
|
+
export interface ViewNameRegistry {
|
|
22
27
|
}
|
|
23
|
-
export type
|
|
28
|
+
export type ViewName = keyof ViewNameRegistry & string;
|
|
24
29
|
export interface ViewConfig {
|
|
25
|
-
component:
|
|
30
|
+
component: ViewName;
|
|
26
31
|
description?: string;
|
|
27
|
-
hosts?:
|
|
32
|
+
hosts?: ViewHostType[];
|
|
28
33
|
prefersBorder?: boolean;
|
|
29
34
|
domain?: string;
|
|
30
35
|
csp?: ViewCsp;
|
|
@@ -37,19 +42,15 @@ export interface KnownToolMeta {
|
|
|
37
42
|
}
|
|
38
43
|
export type ToolMeta = KnownToolMeta & Record<string, unknown>;
|
|
39
44
|
export type HandlerContent = string | ContentBlock | ContentBlock[];
|
|
40
|
-
type OpenaiToolMeta = {
|
|
41
|
-
"openai/outputTemplate": string;
|
|
42
|
-
"openai/widgetAccessible"?: boolean;
|
|
43
|
-
"openai/toolInvocation/invoking"?: string;
|
|
44
|
-
"openai/toolInvocation/invoked"?: string;
|
|
45
|
-
};
|
|
46
|
-
/** @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#resource-discovery */
|
|
47
|
-
type McpAppsToolMeta = {
|
|
48
|
-
ui: McpUiToolMeta;
|
|
49
|
-
};
|
|
50
|
-
type InternalToolMeta = Partial<OpenaiToolMeta & McpAppsToolMeta>;
|
|
51
45
|
/**
|
|
52
46
|
* Type-level marker interface for cross-package type inference.
|
|
47
|
+
*
|
|
48
|
+
* Consumers infer tool types via the structural `$types` property rather than
|
|
49
|
+
* the `McpServer` class generic, because class-generic inference breaks when
|
|
50
|
+
* `McpServer` comes from different package installations (e.g. a consumer
|
|
51
|
+
* with its own `skybridge` dep vs. the in-tree workspace version).
|
|
52
|
+
*
|
|
53
|
+
* Inspired by tRPC's `_def` pattern and Hono's type markers.
|
|
53
54
|
*/
|
|
54
55
|
export interface McpServerTypes<TTools extends Record<string, ToolDef>> {
|
|
55
56
|
readonly tools: TTools;
|
|
@@ -75,7 +76,7 @@ type ExtractMeta<T> = [Extract<T, {
|
|
|
75
76
|
type AddTool<TTools, TName extends string, TInput extends ZodRawShapeCompat, TOutput, TResponseMetadata = unknown> = McpServer<TTools & {
|
|
76
77
|
[K in TName]: ToolDef<ShapeOutput<TInput>, TOutput, TResponseMetadata>;
|
|
77
78
|
}>;
|
|
78
|
-
interface
|
|
79
|
+
interface ToolConfig<TInput extends ZodRawShapeCompat | AnySchema> {
|
|
79
80
|
name: string;
|
|
80
81
|
title?: string;
|
|
81
82
|
description?: string;
|
|
@@ -86,61 +87,110 @@ interface UnifiedToolConfig<TInput extends ZodRawShapeCompat | AnySchema> {
|
|
|
86
87
|
_meta?: ToolMeta;
|
|
87
88
|
}
|
|
88
89
|
type ToolHandler<TInput extends ZodRawShapeCompat, TReturn extends {
|
|
89
|
-
content
|
|
90
|
+
content?: HandlerContent;
|
|
90
91
|
} = {
|
|
91
|
-
content
|
|
92
|
+
content?: HandlerContent;
|
|
92
93
|
}> = (args: ShapeOutput<TInput>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
|
|
93
|
-
export declare function normalizeContent(content: HandlerContent): ContentBlock[];
|
|
94
|
+
export declare function normalizeContent(content: HandlerContent | undefined): ContentBlock[];
|
|
94
95
|
interface McpServerBaseOmitted extends Omit<McpServerBase, "registerTool" | "connect"> {
|
|
95
96
|
}
|
|
96
97
|
declare const McpServerBaseOmitted: new (...args: ConstructorParameters<typeof McpServerBase>) => McpServerBaseOmitted;
|
|
97
98
|
export declare class McpServer<TTools extends Record<string, ToolDef> = Record<never, ToolDef>> extends McpServerBaseOmitted {
|
|
98
99
|
readonly $types: McpServerTypes<TTools>;
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
/**
|
|
101
|
+
* The underlying Express app. Use this to extend the HTTP server with
|
|
102
|
+
* custom routes, middleware, or settings — e.g.
|
|
103
|
+
* `server.express.get("/health", ...)`.
|
|
104
|
+
*
|
|
105
|
+
* `express.json()` is pre-applied. Register your handlers before `run()`;
|
|
106
|
+
* after `run()`, dev-mode middleware, the `/mcp` route, and the default
|
|
107
|
+
* error handler are appended in that order.
|
|
108
|
+
*
|
|
109
|
+
* Note: Alpic Cloud only routes traffic to `/mcp` — custom routes work
|
|
110
|
+
* locally and on self-hosted deployments.
|
|
111
|
+
*/
|
|
112
|
+
readonly express: Express;
|
|
101
113
|
private customErrorMiddleware;
|
|
102
114
|
private mcpMiddlewareEntries;
|
|
103
115
|
private mcpMiddlewareApplied;
|
|
104
|
-
private
|
|
116
|
+
private claimedViews;
|
|
117
|
+
private viteManifest;
|
|
118
|
+
private readonly serverInfo;
|
|
119
|
+
private readonly serverOptions?;
|
|
120
|
+
constructor(serverInfo: Implementation, options?: ServerOptions);
|
|
105
121
|
use(...handlers: RequestHandler[]): this;
|
|
106
122
|
use(path: string, ...handlers: RequestHandler[]): this;
|
|
107
123
|
useOnError(...handlers: ErrorRequestHandler[]): this;
|
|
108
124
|
useOnError(path: string, ...handlers: ErrorRequestHandler[]): this;
|
|
125
|
+
/** Register MCP protocol-level middleware (catch-all). */
|
|
109
126
|
mcpMiddleware(handler: McpMiddlewareFn): this;
|
|
127
|
+
/** Register MCP protocol-level middleware for all requests (`extra` is `McpExtra`). */
|
|
110
128
|
mcpMiddleware(filter: "request", handler: (request: {
|
|
111
129
|
method: string;
|
|
112
130
|
params: Record<string, unknown>;
|
|
113
131
|
}, extra: McpExtra, next: () => Promise<ServerResult>) => Promise<unknown> | unknown): this;
|
|
132
|
+
/** Register MCP protocol-level middleware for all notifications (`extra` is `undefined`). */
|
|
114
133
|
mcpMiddleware(filter: "notification", handler: (request: {
|
|
115
134
|
method: string;
|
|
116
135
|
params: Record<string, unknown>;
|
|
117
136
|
}, extra: undefined, next: () => Promise<undefined>) => Promise<unknown> | unknown): this;
|
|
137
|
+
/**
|
|
138
|
+
* Register MCP protocol-level middleware for an exact method.
|
|
139
|
+
* Narrows `params`, `extra`, and `next()` result based on the method string.
|
|
140
|
+
*/
|
|
118
141
|
mcpMiddleware<M extends McpMethodString>(filter: M, handler: McpTypedMiddlewareFn<M>): this;
|
|
142
|
+
/**
|
|
143
|
+
* Register MCP protocol-level middleware for a wildcard pattern (e.g. `"tools/*"`).
|
|
144
|
+
* `next()` returns the union of result types for matching methods.
|
|
145
|
+
*/
|
|
119
146
|
mcpMiddleware<W extends McpWildcard>(filter: W, handler: (request: {
|
|
120
147
|
method: string;
|
|
121
148
|
params: Record<string, unknown>;
|
|
122
149
|
}, extra: McpExtraFor<W>, next: () => Promise<McpResultFor<W>>) => Promise<unknown> | unknown): this;
|
|
150
|
+
/**
|
|
151
|
+
* Register MCP protocol-level middleware with a method filter.
|
|
152
|
+
* Filter can be an exact method (`"tools/call"`), wildcard (`"tools/*"`),
|
|
153
|
+
* category (`"request"` | `"notification"`), or an array of those.
|
|
154
|
+
*/
|
|
123
155
|
mcpMiddleware(filter: McpMiddlewareFilter, handler: McpMiddlewareFn): this;
|
|
124
156
|
private applyMcpMiddleware;
|
|
125
157
|
connect(transport: Parameters<typeof McpServerBase.prototype.connect>[0]): Promise<void>;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Per-request stateless connect. The SDK's `Protocol` only allows one
|
|
160
|
+
* transport per instance, so we can't reuse this `McpServer` across
|
|
161
|
+
* concurrent requests. The SDK's idiomatic fix is a `() => McpServer`
|
|
162
|
+
* factory, but that would break Skybridge's singleton API — so instead
|
|
163
|
+
* we build a fresh underlying `Server` per request and share the main
|
|
164
|
+
* server's handler maps by reference. The cast is unavoidable: there's
|
|
165
|
+
* no public API to inject handler maps. `getHandlerMaps` validates the
|
|
166
|
+
* read side and fails fast on SDK field renames.
|
|
167
|
+
*/
|
|
168
|
+
connectStatelessTransport(transport: Parameters<typeof McpServerBase.prototype.connect>[0]): Promise<void>;
|
|
169
|
+
run(): Promise<{
|
|
170
|
+
fetch: (...args: unknown[]) => unknown;
|
|
171
|
+
} | undefined>;
|
|
172
|
+
private enforceOneToolPerView;
|
|
173
|
+
private registerViewResources;
|
|
174
|
+
private registerViewResource;
|
|
175
|
+
private wrapHandler;
|
|
176
|
+
private computeViewVersionParam;
|
|
177
|
+
private lookupViewFile;
|
|
137
178
|
private lookupDistFile;
|
|
179
|
+
/**
|
|
180
|
+
* Inject the Vite manifest as a value rather than letting `readManifest()`
|
|
181
|
+
* load it from disk. Required for runtimes without a usable filesystem
|
|
182
|
+
* (Cloudflare Workers, etc.) — the user's `skybridge build` emits the
|
|
183
|
+
* manifest as a JS module which the entry imports and passes here.
|
|
184
|
+
*/
|
|
185
|
+
setViteManifest(manifest: Record<string, {
|
|
186
|
+
file: string;
|
|
187
|
+
}>): this;
|
|
138
188
|
private readManifest;
|
|
139
189
|
registerTool<TName extends string, InputArgs extends ZodRawShapeCompat, TReturn extends {
|
|
140
|
-
content
|
|
141
|
-
}>(config:
|
|
190
|
+
content?: HandlerContent;
|
|
191
|
+
}>(config: ToolConfig<InputArgs> & {
|
|
142
192
|
name: TName;
|
|
143
193
|
}, cb: ToolHandler<InputArgs, TReturn>): AddTool<TTools, TName, InputArgs, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
|
|
144
|
-
registerTool<InputArgs extends ZodRawShapeCompat>(config:
|
|
194
|
+
registerTool<InputArgs extends ZodRawShapeCompat>(config: ToolConfig<InputArgs>, cb: ToolHandler<InputArgs>): this;
|
|
145
195
|
}
|
|
146
196
|
export {};
|
package/dist/server/server.js
CHANGED
|
@@ -2,8 +2,10 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { Server as SdkServer, } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
6
|
import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import { mergeWith, union } from "es-toolkit";
|
|
8
|
+
import express, {} from "express";
|
|
7
9
|
import { createApp } from "./express.js";
|
|
8
10
|
import { createMiddlewareEntry } from "./metric.js";
|
|
9
11
|
import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
|
|
@@ -15,10 +17,10 @@ const mergeWithUnion = (target, source) => {
|
|
|
15
17
|
}
|
|
16
18
|
});
|
|
17
19
|
};
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Content normalization
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
20
|
export function normalizeContent(content) {
|
|
21
|
+
if (content === undefined) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
22
24
|
if (typeof content === "string") {
|
|
23
25
|
return [{ type: "text", text: content }];
|
|
24
26
|
}
|
|
@@ -29,23 +31,41 @@ export function normalizeContent(content) {
|
|
|
29
31
|
}
|
|
30
32
|
const McpServerBaseOmitted = McpServerBase;
|
|
31
33
|
export class McpServer extends McpServerBaseOmitted {
|
|
34
|
+
/**
|
|
35
|
+
* The underlying Express app. Use this to extend the HTTP server with
|
|
36
|
+
* custom routes, middleware, or settings — e.g.
|
|
37
|
+
* `server.express.get("/health", ...)`.
|
|
38
|
+
*
|
|
39
|
+
* `express.json()` is pre-applied. Register your handlers before `run()`;
|
|
40
|
+
* after `run()`, dev-mode middleware, the `/mcp` route, and the default
|
|
41
|
+
* error handler are appended in that order.
|
|
42
|
+
*
|
|
43
|
+
* Note: Alpic Cloud only routes traffic to `/mcp` — custom routes work
|
|
44
|
+
* locally and on self-hosted deployments.
|
|
45
|
+
*/
|
|
32
46
|
express;
|
|
33
|
-
customMiddleware = [];
|
|
34
47
|
customErrorMiddleware = [];
|
|
35
48
|
mcpMiddlewareEntries = [];
|
|
36
49
|
mcpMiddlewareApplied = false;
|
|
37
|
-
|
|
50
|
+
claimedViews = new Map();
|
|
51
|
+
viteManifest = null;
|
|
52
|
+
serverInfo;
|
|
53
|
+
serverOptions;
|
|
54
|
+
constructor(serverInfo, options) {
|
|
55
|
+
super(serverInfo, options);
|
|
56
|
+
this.serverInfo = serverInfo;
|
|
57
|
+
this.serverOptions = options;
|
|
58
|
+
this.express = express();
|
|
59
|
+
this.express.use(express.json());
|
|
60
|
+
}
|
|
38
61
|
use(pathOrHandler, ...handlers) {
|
|
62
|
+
// Branching is load-bearing: Express's `app.use` overloads can't be
|
|
63
|
+
// resolved against a `string | RequestHandler` union, so we narrow.
|
|
39
64
|
if (typeof pathOrHandler === "string") {
|
|
40
|
-
this.
|
|
41
|
-
path: pathOrHandler,
|
|
42
|
-
handlers,
|
|
43
|
-
});
|
|
65
|
+
this.express.use(pathOrHandler, ...handlers);
|
|
44
66
|
}
|
|
45
67
|
else {
|
|
46
|
-
this.
|
|
47
|
-
handlers: [pathOrHandler, ...handlers],
|
|
48
|
-
});
|
|
68
|
+
this.express.use(pathOrHandler, ...handlers);
|
|
49
69
|
}
|
|
50
70
|
return this;
|
|
51
71
|
}
|
|
@@ -111,49 +131,84 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
111
131
|
this.applyMcpMiddleware();
|
|
112
132
|
return McpServerBase.prototype.connect.call(this, transport);
|
|
113
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Per-request stateless connect. The SDK's `Protocol` only allows one
|
|
136
|
+
* transport per instance, so we can't reuse this `McpServer` across
|
|
137
|
+
* concurrent requests. The SDK's idiomatic fix is a `() => McpServer`
|
|
138
|
+
* factory, but that would break Skybridge's singleton API — so instead
|
|
139
|
+
* we build a fresh underlying `Server` per request and share the main
|
|
140
|
+
* server's handler maps by reference. The cast is unavoidable: there's
|
|
141
|
+
* no public API to inject handler maps. `getHandlerMaps` validates the
|
|
142
|
+
* read side and fails fast on SDK field renames.
|
|
143
|
+
*/
|
|
144
|
+
async connectStatelessTransport(transport) {
|
|
145
|
+
this.applyMcpMiddleware();
|
|
146
|
+
const { requestHandlers, notificationHandlers } = getHandlerMaps(this.server);
|
|
147
|
+
const fresh = new SdkServer(this.serverInfo, this.serverOptions);
|
|
148
|
+
const target = fresh;
|
|
149
|
+
target._requestHandlers = requestHandlers;
|
|
150
|
+
target._notificationHandlers = notificationHandlers;
|
|
151
|
+
await fresh.connect(transport);
|
|
152
|
+
}
|
|
114
153
|
async run() {
|
|
115
154
|
this.applyMcpMiddleware();
|
|
116
155
|
const httpServer = http.createServer();
|
|
117
|
-
|
|
118
|
-
this
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
errorMiddleware: this.customErrorMiddleware,
|
|
123
|
-
});
|
|
124
|
-
}
|
|
156
|
+
await createApp({
|
|
157
|
+
mcpServer: this,
|
|
158
|
+
httpServer,
|
|
159
|
+
errorMiddleware: this.customErrorMiddleware,
|
|
160
|
+
});
|
|
125
161
|
httpServer.on("request", this.express);
|
|
126
|
-
|
|
162
|
+
const port = parseInt(process.env.__PORT ?? "3000", 10);
|
|
163
|
+
await new Promise((resolve, reject) => {
|
|
127
164
|
httpServer.on("error", (error) => {
|
|
128
165
|
console.error("Failed to start server:", error);
|
|
129
166
|
reject(error);
|
|
130
167
|
});
|
|
131
|
-
const port = parseInt(process.env.__PORT ?? "3000", 10);
|
|
132
168
|
httpServer.listen(port, () => {
|
|
133
169
|
resolve();
|
|
134
170
|
});
|
|
135
171
|
});
|
|
172
|
+
// On workerd, bridge the Node http server to a Workers fetch handler.
|
|
173
|
+
// The specifier is held in a variable to sidestep tsc's module resolution
|
|
174
|
+
// (`cloudflare:node` only exists under wrangler/workerd).
|
|
175
|
+
if (typeof navigator !== "undefined" &&
|
|
176
|
+
navigator.userAgent === "Cloudflare-Workers") {
|
|
177
|
+
const cloudflareNode = "cloudflare:node";
|
|
178
|
+
const { httpServerHandler } = await import(cloudflareNode);
|
|
179
|
+
return httpServerHandler({ port });
|
|
180
|
+
}
|
|
181
|
+
const shutdown = () => {
|
|
182
|
+
// Drop both handlers so a second signal falls through to Node's default
|
|
183
|
+
// (force-quit on a second Ctrl+C while drain is hanging).
|
|
184
|
+
process.off("SIGTERM", shutdown);
|
|
185
|
+
process.off("SIGINT", shutdown);
|
|
186
|
+
httpServer.close(() => process.exit(0));
|
|
187
|
+
// Force exit if connections don't drain in time so the port is still
|
|
188
|
+
// released promptly (e.g. for nodemon restarts).
|
|
189
|
+
setTimeout(() => process.exit(0), 3000).unref();
|
|
190
|
+
};
|
|
191
|
+
process.on("SIGTERM", shutdown);
|
|
192
|
+
process.on("SIGINT", shutdown);
|
|
193
|
+
return undefined;
|
|
136
194
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// -------------------------------------------------------------------------
|
|
140
|
-
// View (widget) resource registration
|
|
141
|
-
// -------------------------------------------------------------------------
|
|
142
|
-
/** @internal */
|
|
143
|
-
enforceOneToolPerWidget(component, toolName) {
|
|
144
|
-
const existingTool = this.claimedWidgets.get(component);
|
|
195
|
+
enforceOneToolPerView(component, toolName) {
|
|
196
|
+
const existingTool = this.claimedViews.get(component);
|
|
145
197
|
if (existingTool) {
|
|
146
|
-
throw new Error(`skybridge:
|
|
198
|
+
throw new Error(`skybridge: view "${component}" is already used by tool "${existingTool}". Tool "${toolName}" cannot also reference it — each view backs exactly one tool.`);
|
|
147
199
|
}
|
|
148
|
-
this.
|
|
200
|
+
this.claimedViews.set(component, toolName);
|
|
149
201
|
}
|
|
150
|
-
/** @internal */
|
|
151
202
|
registerViewResources(toolName, view, toolMeta) {
|
|
152
203
|
const hosts = view.hosts ?? ["apps-sdk", "mcp-app"];
|
|
204
|
+
// Append a content-derived version param so hosts (e.g. ChatGPT) bust
|
|
205
|
+
// their cache when the bundle changes, but keep the URI stable across
|
|
206
|
+
// `tools/list` calls when the bundle hasn't changed.
|
|
207
|
+
const versionParam = this.computeViewVersionParam(view.component);
|
|
153
208
|
if (hosts.includes("apps-sdk")) {
|
|
154
|
-
const
|
|
209
|
+
const viewResource = {
|
|
155
210
|
hostType: "apps-sdk",
|
|
156
|
-
uri: `ui://
|
|
211
|
+
uri: `ui://views/apps-sdk/${view.component}.html${versionParam}`,
|
|
157
212
|
mimeType: "text/html+skybridge",
|
|
158
213
|
buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
|
|
159
214
|
const defaults = {
|
|
@@ -183,17 +238,17 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
183
238
|
return base;
|
|
184
239
|
},
|
|
185
240
|
};
|
|
186
|
-
this.
|
|
241
|
+
this.registerViewResource({
|
|
187
242
|
name: toolName,
|
|
188
|
-
|
|
243
|
+
viewResource,
|
|
189
244
|
view,
|
|
190
245
|
});
|
|
191
|
-
toolMeta["openai/outputTemplate"] =
|
|
246
|
+
toolMeta["openai/outputTemplate"] = viewResource.uri;
|
|
192
247
|
}
|
|
193
248
|
if (hosts.includes("mcp-app")) {
|
|
194
|
-
const
|
|
249
|
+
const viewResource = {
|
|
195
250
|
hostType: "mcp-app",
|
|
196
|
-
uri: `ui://
|
|
251
|
+
uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
|
|
197
252
|
mimeType: "text/html;profile=mcp-app",
|
|
198
253
|
buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
|
|
199
254
|
const defaults = {
|
|
@@ -241,19 +296,19 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
241
296
|
return base;
|
|
242
297
|
},
|
|
243
298
|
};
|
|
244
|
-
this.
|
|
299
|
+
this.registerViewResource({
|
|
245
300
|
name: toolName,
|
|
246
|
-
|
|
301
|
+
viewResource,
|
|
247
302
|
view,
|
|
248
303
|
});
|
|
249
304
|
// @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
|
|
250
|
-
toolMeta["ui/resourceUri"] =
|
|
251
|
-
toolMeta.ui = { resourceUri:
|
|
305
|
+
toolMeta["ui/resourceUri"] = viewResource.uri;
|
|
306
|
+
toolMeta.ui = { resourceUri: viewResource.uri };
|
|
252
307
|
}
|
|
253
308
|
}
|
|
254
|
-
|
|
255
|
-
const { hostType, uri:
|
|
256
|
-
this.registerResource(name,
|
|
309
|
+
registerViewResource({ name, viewResource, view, }) {
|
|
310
|
+
const { hostType, uri: viewUri, mimeType, buildContentMeta } = viewResource;
|
|
311
|
+
this.registerResource(name, viewUri, { description: view.description }, async (uri, extra) => {
|
|
257
312
|
const isProduction = process.env.NODE_ENV === "production";
|
|
258
313
|
const isClaude = extra?.requestInfo?.headers?.["user-agent"] === "Claude-User";
|
|
259
314
|
const headers = extra?.requestInfo?.headers || {};
|
|
@@ -286,13 +341,13 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
286
341
|
? templateHelper.renderProduction({
|
|
287
342
|
hostType,
|
|
288
343
|
serverUrl,
|
|
289
|
-
|
|
344
|
+
viewFile: this.lookupViewFile(view.component),
|
|
290
345
|
styleFile: this.lookupDistFile("style.css") ?? "",
|
|
291
346
|
})
|
|
292
347
|
: templateHelper.renderDevelopment({
|
|
293
348
|
hostType,
|
|
294
349
|
serverUrl,
|
|
295
|
-
|
|
350
|
+
viewName: view.component,
|
|
296
351
|
});
|
|
297
352
|
const connectDomains = [serverUrl];
|
|
298
353
|
if (!isProduction) {
|
|
@@ -304,6 +359,8 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
304
359
|
if (isClaude) {
|
|
305
360
|
const pathname = extra?.requestInfo?.url?.pathname ?? "";
|
|
306
361
|
const rawUrl = header("x-alpic-forwarded-url") ?? `${serverUrl}${pathname}`;
|
|
362
|
+
// Strip a lone trailing slash so the hash matches the connector URL
|
|
363
|
+
// as registered with Claude (which has no trailing slash on bare origins).
|
|
307
364
|
const url = rawUrl.endsWith("/") ? rawUrl.slice(0, -1) : rawUrl;
|
|
308
365
|
const hash = crypto
|
|
309
366
|
.createHash("sha256")
|
|
@@ -325,50 +382,68 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
325
382
|
};
|
|
326
383
|
});
|
|
327
384
|
}
|
|
328
|
-
|
|
329
|
-
// Handler wrapping
|
|
330
|
-
// -------------------------------------------------------------------------
|
|
331
|
-
/** @internal */
|
|
332
|
-
wrapHandlerWithViewUUID(cb) {
|
|
385
|
+
wrapHandler(cb, { attachViewUUID }) {
|
|
333
386
|
return async (args, extra) => {
|
|
334
387
|
const result = await cb(args, extra);
|
|
335
388
|
return {
|
|
336
389
|
...result,
|
|
337
390
|
content: normalizeContent(result.content),
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
391
|
+
...(attachViewUUID && {
|
|
392
|
+
_meta: {
|
|
393
|
+
...result._meta,
|
|
394
|
+
viewUUID: crypto.randomUUID(),
|
|
395
|
+
},
|
|
396
|
+
}),
|
|
342
397
|
};
|
|
343
398
|
};
|
|
344
399
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
400
|
+
computeViewVersionParam(viewName) {
|
|
401
|
+
if (process.env.NODE_ENV !== "production") {
|
|
402
|
+
return "";
|
|
403
|
+
}
|
|
404
|
+
try {
|
|
405
|
+
const viewFile = this.lookupViewFile(viewName);
|
|
406
|
+
const styleFile = this.lookupDistFile("style.css") ?? "";
|
|
407
|
+
const hash = crypto
|
|
408
|
+
.createHash("sha256")
|
|
409
|
+
.update(viewFile)
|
|
410
|
+
.update("\0")
|
|
411
|
+
.update(styleFile)
|
|
412
|
+
.digest("hex")
|
|
413
|
+
.slice(0, 8);
|
|
414
|
+
return `?v=${hash}`;
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
return "";
|
|
418
|
+
}
|
|
354
419
|
}
|
|
355
|
-
|
|
356
|
-
// Manifest helpers
|
|
357
|
-
// -------------------------------------------------------------------------
|
|
358
|
-
lookupWidgetFile(widgetName) {
|
|
420
|
+
lookupViewFile(viewName) {
|
|
359
421
|
const manifest = this.readManifest();
|
|
360
422
|
for (const entry of Object.values(manifest)) {
|
|
361
|
-
if (entry?.isEntry && entry.name ===
|
|
423
|
+
if (entry?.isEntry && entry.name === viewName && entry.file) {
|
|
362
424
|
return entry.file;
|
|
363
425
|
}
|
|
364
426
|
}
|
|
365
|
-
throw new Error(`
|
|
427
|
+
throw new Error(`View "${viewName}" not found in Vite manifest. Did the build complete successfully? Look for an entry with name "${viewName}" in dist/assets/.vite/manifest.json.`);
|
|
366
428
|
}
|
|
367
429
|
lookupDistFile(key) {
|
|
368
430
|
const manifest = this.readManifest();
|
|
369
431
|
return manifest[key]?.file;
|
|
370
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* Inject the Vite manifest as a value rather than letting `readManifest()`
|
|
435
|
+
* load it from disk. Required for runtimes without a usable filesystem
|
|
436
|
+
* (Cloudflare Workers, etc.) — the user's `skybridge build` emits the
|
|
437
|
+
* manifest as a JS module which the entry imports and passes here.
|
|
438
|
+
*/
|
|
439
|
+
setViteManifest(manifest) {
|
|
440
|
+
this.viteManifest = manifest;
|
|
441
|
+
return this;
|
|
442
|
+
}
|
|
371
443
|
readManifest() {
|
|
444
|
+
if (this.viteManifest) {
|
|
445
|
+
return this.viteManifest;
|
|
446
|
+
}
|
|
372
447
|
return JSON.parse(readFileSync(path.join(process.cwd(), "dist", "assets", ".vite", "manifest.json"), "utf-8"));
|
|
373
448
|
}
|
|
374
449
|
registerTool(...args) {
|
|
@@ -382,12 +457,10 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
382
457
|
const { name, view, _meta: userToolMeta, ...toolFields } = config;
|
|
383
458
|
const toolMeta = { ...userToolMeta };
|
|
384
459
|
if (view) {
|
|
385
|
-
this.
|
|
460
|
+
this.enforceOneToolPerView(view.component, name);
|
|
386
461
|
this.registerViewResources(name, view, toolMeta);
|
|
387
462
|
}
|
|
388
|
-
const wrappedCb = view
|
|
389
|
-
? this.wrapHandlerWithViewUUID(cb)
|
|
390
|
-
: this.wrapHandlerWithContentNormalization(cb);
|
|
463
|
+
const wrappedCb = this.wrapHandler(cb, { attachViewUUID: Boolean(view) });
|
|
391
464
|
baseFn.call(this, name, { ...toolFields, _meta: toolMeta }, wrappedCb);
|
|
392
465
|
return this;
|
|
393
466
|
}
|