skybridge 0.0.0-dev.d26cb78 → 0.0.0-dev.d338619
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 +153 -0
- package/bin/run.js +0 -4
- package/dist/cli/detect-port.d.ts +18 -0
- package/dist/cli/detect-port.js +61 -0
- package/dist/cli/detect-port.js.map +1 -0
- package/dist/cli/header.js +1 -1
- package/dist/cli/header.js.map +1 -1
- package/dist/cli/telemetry.d.ts +7 -0
- package/dist/cli/telemetry.js +123 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/types.d.ts +5 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/use-execute-steps.d.ts +3 -2
- package/dist/cli/use-execute-steps.js +6 -1
- package/dist/cli/use-execute-steps.js.map +1 -1
- package/dist/cli/use-messages.d.ts +3 -0
- package/dist/cli/use-messages.js +11 -0
- package/dist/cli/use-messages.js.map +1 -0
- package/dist/cli/use-nodemon.d.ts +2 -0
- package/dist/cli/use-nodemon.js +64 -0
- package/dist/cli/use-nodemon.js.map +1 -0
- package/dist/cli/use-tunnel.d.ts +14 -0
- package/dist/cli/use-tunnel.js +97 -0
- package/dist/cli/use-tunnel.js.map +1 -0
- package/dist/cli/use-typescript-check.d.ts +8 -0
- package/dist/cli/use-typescript-check.js +59 -0
- package/dist/cli/use-typescript-check.js.map +1 -0
- package/dist/commands/build.js +29 -6
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +5 -1
- package/dist/commands/dev.js +38 -9
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.d.ts +3 -1
- package/dist/commands/start.js +31 -15
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/telemetry/disable.d.ts +5 -0
- package/dist/commands/telemetry/disable.js +14 -0
- package/dist/commands/telemetry/disable.js.map +1 -0
- package/dist/commands/telemetry/enable.d.ts +5 -0
- package/dist/commands/telemetry/enable.js +14 -0
- package/dist/commands/telemetry/enable.js.map +1 -0
- package/dist/commands/telemetry/status.d.ts +5 -0
- package/dist/commands/telemetry/status.js +14 -0
- package/dist/commands/telemetry/status.js.map +1 -0
- package/dist/server/asset-base-url-transform-plugin.d.ts +10 -0
- package/dist/server/asset-base-url-transform-plugin.js +33 -0
- package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
- package/dist/server/asset-base-url-transform-plugin.test.js +55 -0
- package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
- package/dist/server/content-helpers.d.ts +27 -0
- package/dist/server/content-helpers.js +46 -0
- package/dist/server/content-helpers.js.map +1 -0
- package/dist/server/content-helpers.test.d.ts +1 -0
- package/dist/server/content-helpers.test.js +70 -0
- package/dist/server/content-helpers.test.js.map +1 -0
- package/dist/server/express.d.ts +15 -0
- package/dist/server/express.js +77 -0
- package/dist/server/express.js.map +1 -0
- package/dist/server/express.test.d.ts +1 -0
- package/dist/server/express.test.js +252 -0
- package/dist/server/express.test.js.map +1 -0
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.js +3 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/metric.d.ts +14 -0
- package/dist/server/metric.js +62 -0
- package/dist/server/metric.js.map +1 -0
- package/dist/server/middleware.d.ts +124 -0
- package/dist/server/middleware.js +93 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/middleware.test-d.d.ts +1 -0
- package/dist/server/middleware.test-d.js +75 -0
- package/dist/server/middleware.test-d.js.map +1 -0
- package/dist/server/middleware.test.d.ts +1 -0
- package/dist/server/middleware.test.js +493 -0
- package/dist/server/middleware.test.js.map +1 -0
- package/dist/server/server.d.ts +121 -63
- package/dist/server/server.js +299 -64
- package/dist/server/server.js.map +1 -1
- package/dist/server/templateHelper.d.ts +5 -5
- package/dist/server/templates/development.hbs +3 -57
- package/dist/server/templates/production.hbs +2 -3
- package/dist/server/viewsDevServer.d.ts +14 -0
- package/dist/server/viewsDevServer.js +45 -0
- package/dist/server/viewsDevServer.js.map +1 -0
- package/dist/test/utils.d.ts +13 -21
- package/dist/test/utils.js +42 -37
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.d.ts +1 -0
- package/dist/test/view.test.js +454 -0
- package/dist/test/view.test.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +14 -4
- package/dist/web/bridges/apps-sdk/adaptor.js +53 -5
- package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -1
- package/dist/web/bridges/apps-sdk/bridge.d.ts +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +1 -1
- package/dist/web/bridges/apps-sdk/types.d.ts +30 -25
- package/dist/web/bridges/apps-sdk/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +33 -4
- package/dist/web/bridges/mcp-app/adaptor.js +161 -38
- package/dist/web/bridges/mcp-app/adaptor.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.d.ts +13 -30
- package/dist/web/bridges/mcp-app/bridge.js +43 -196
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +5 -3
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +2 -2
- 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 +1 -41
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +40 -5
- package/dist/web/components/modal-provider.d.ts +4 -0
- package/dist/web/components/modal-provider.js +45 -0
- package/dist/web/components/modal-provider.js.map +1 -0
- package/dist/web/create-store.js +15 -1
- package/dist/web/create-store.js.map +1 -1
- package/dist/web/create-store.test.js +9 -4
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.test.js +11 -8
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +20 -18
- package/dist/web/generate-helpers.js +20 -18
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +20 -20
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/hooks/index.d.ts +2 -1
- package/dist/web/hooks/index.js +1 -0
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.js +4 -0
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +3 -3
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
- package/dist/web/hooks/use-display-mode.test-d.js +8 -0
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
- package/dist/web/hooks/use-files.d.ts +3 -6
- package/dist/web/hooks/use-files.js +5 -2
- package/dist/web/hooks/use-files.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +28 -3
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-layout.test.js +3 -3
- package/dist/web/hooks/use-layout.test.js.map +1 -1
- package/dist/web/hooks/use-open-external.d.ts +3 -1
- package/dist/web/hooks/use-open-external.js +1 -1
- package/dist/web/hooks/use-open-external.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js +26 -11
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-request-modal.d.ts +2 -2
- package/dist/web/hooks/use-request-modal.js +9 -7
- package/dist/web/hooks/use-request-modal.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +5 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.d.ts +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.js +8 -0
- package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
- package/dist/web/hooks/use-tool-info.test.js +1 -1
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.js +18 -2
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +29 -1
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-widget-state.test.js +123 -7
- package/dist/web/hooks/use-widget-state.test.js.map +1 -1
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js.map +1 -1
- package/dist/web/mount-widget.js +9 -1
- package/dist/web/mount-widget.js.map +1 -1
- package/dist/web/plugin/plugin.d.ts +4 -1
- package/dist/web/plugin/plugin.js +120 -18
- package/dist/web/plugin/plugin.js.map +1 -1
- package/dist/web/plugin/scan-views.d.ts +8 -0
- package/dist/web/plugin/scan-views.js +70 -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 +67 -0
- package/dist/web/plugin/scan-views.test.js.map +1 -0
- package/dist/web/plugin/transform-data-llm.js +1 -1
- package/dist/web/plugin/transform-data-llm.js.map +1 -1
- package/dist/web/plugin/validate-view.d.ts +1 -0
- package/dist/web/plugin/validate-view.js +9 -0
- 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-view.test.js +24 -0
- package/dist/web/plugin/validate-view.test.js.map +1 -0
- package/dist/web/proxy.js +0 -1
- package/dist/web/proxy.js.map +1 -1
- package/package.json +40 -25
- package/tsconfig.base.json +33 -0
- package/dist/server/widgetsDevServer.d.ts +0 -12
- package/dist/server/widgetsDevServer.js +0 -47
- package/dist/server/widgetsDevServer.js.map +0 -1
- package/dist/test/widget.test.js +0 -255
- package/dist/test/widget.test.js.map +0 -1
- /package/dist/{test/widget.test.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
package/dist/server/server.d.ts
CHANGED
|
@@ -1,43 +1,67 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { McpServer as McpServerBase, type RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1
|
+
import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
2
|
import type { AnySchema, SchemaOutput, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
4
3
|
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
5
|
-
import type {
|
|
4
|
+
import type { ContentBlock, ServerNotification, ServerRequest, ServerResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import type { ErrorRequestHandler, RequestHandler } from "express";
|
|
6
|
+
import type { McpExtra, McpExtraFor, McpMethodString, McpMiddlewareFilter, McpMiddlewareFn, McpResultFor, McpTypedMiddlewareFn, McpWildcard } from "./middleware.js";
|
|
6
7
|
export type ToolDef<TInput = unknown, TOutput = unknown, TResponseMetadata = unknown> = {
|
|
7
8
|
input: TInput;
|
|
8
9
|
output: TOutput;
|
|
9
10
|
responseMetadata: TResponseMetadata;
|
|
10
11
|
};
|
|
12
|
+
export type ViewHostType = "apps-sdk" | "mcp-app";
|
|
13
|
+
export interface ViewCsp {
|
|
14
|
+
/** Origins for static assets (images, fonts, scripts, styles). */
|
|
15
|
+
resourceDomains?: string[];
|
|
16
|
+
/** Origins the view may contact via fetch/XHR. */
|
|
17
|
+
connectDomains?: string[];
|
|
18
|
+
/** Origins allowed for iframe embeds (opts into stricter app review). */
|
|
19
|
+
frameDomains?: string[];
|
|
20
|
+
/** Origins that can receive openExternal redirects without the safe-link modal. */
|
|
21
|
+
redirectDomains?: string[];
|
|
22
|
+
/** Origins allowed in `<base href>` tags (mcp-apps only). */
|
|
23
|
+
baseUriDomains?: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface ViewNameRegistry {
|
|
26
|
+
}
|
|
27
|
+
export type ViewName = keyof ViewNameRegistry extends never ? string : keyof ViewNameRegistry & string;
|
|
28
|
+
export interface ViewConfig {
|
|
29
|
+
component: ViewName;
|
|
30
|
+
description?: string;
|
|
31
|
+
hosts?: ViewHostType[];
|
|
32
|
+
prefersBorder?: boolean;
|
|
33
|
+
domain?: string;
|
|
34
|
+
csp?: ViewCsp;
|
|
35
|
+
_meta?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export interface KnownToolMeta {
|
|
38
|
+
"openai/widgetAccessible"?: boolean;
|
|
39
|
+
"openai/toolInvocation/invoking"?: string;
|
|
40
|
+
"openai/toolInvocation/invoked"?: string;
|
|
41
|
+
}
|
|
42
|
+
export type ToolMeta = KnownToolMeta & Record<string, unknown>;
|
|
43
|
+
export type HandlerContent = string | ContentBlock | ContentBlock[];
|
|
11
44
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
45
|
+
* Type-level marker interface for cross-package type inference.
|
|
46
|
+
*
|
|
47
|
+
* Consumers infer tool types via the structural `$types` property rather than
|
|
48
|
+
* the `McpServer` class generic, because class-generic inference breaks when
|
|
49
|
+
* `McpServer` comes from different package installations (e.g. a consumer
|
|
50
|
+
* with its own `skybridge` dep vs. the in-tree workspace version).
|
|
51
|
+
*
|
|
52
|
+
* Inspired by tRPC's `_def` pattern and Hono's type markers.
|
|
15
53
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* @see https://developers.openai.com/apps-sdk/reference#component-resource-_meta-fields
|
|
20
|
-
*/
|
|
21
|
-
redirectDomains?: string[];
|
|
22
|
-
};
|
|
23
|
-
/** Extended MCP Apps resource metadata with upcoming CSP fields */
|
|
24
|
-
type ExtendedMcpUiResourceMeta = Omit<McpUiResourceMeta, "csp"> & {
|
|
25
|
-
csp?: ExtendedMcpUiResourceCsp;
|
|
26
|
-
};
|
|
27
|
-
/** User-provided resource configuration with optional CSP override */
|
|
28
|
-
export type WidgetResourceMeta = {
|
|
29
|
-
ui?: ExtendedMcpUiResourceMeta;
|
|
30
|
-
} & Resource["_meta"];
|
|
31
|
-
export type WidgetHostType = "apps-sdk" | "mcp-app";
|
|
32
|
-
type McpServerOriginalResourceConfig = Omit<Resource, "uri" | "name" | "mimeType" | "_meta"> & {
|
|
33
|
-
_meta?: WidgetResourceMeta;
|
|
34
|
-
/** Restrict host types to a specific subset */
|
|
35
|
-
hosts?: WidgetHostType[];
|
|
36
|
-
};
|
|
37
|
-
type McpServerOriginalToolConfig = Omit<Parameters<typeof McpServerBase.prototype.registerTool<ZodRawShapeCompat, ZodRawShapeCompat>>[1], "inputSchema" | "outputSchema">;
|
|
54
|
+
export interface McpServerTypes<TTools extends Record<string, ToolDef>> {
|
|
55
|
+
readonly tools: TTools;
|
|
56
|
+
}
|
|
38
57
|
type Simplify<T> = {
|
|
39
58
|
[K in keyof T]: T[K];
|
|
40
59
|
};
|
|
60
|
+
type ShapeOutput<Shape extends ZodRawShapeCompat> = Simplify<{
|
|
61
|
+
[K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? never : K]: SchemaOutput<Shape[K]>;
|
|
62
|
+
} & {
|
|
63
|
+
[K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? K : never]?: SchemaOutput<Shape[K]>;
|
|
64
|
+
}>;
|
|
41
65
|
type ExtractStructuredContent<T> = T extends {
|
|
42
66
|
structuredContent: infer SC;
|
|
43
67
|
} ? Simplify<SC> : never;
|
|
@@ -48,52 +72,86 @@ type ExtractMeta<T> = [Extract<T, {
|
|
|
48
72
|
}> extends {
|
|
49
73
|
_meta: infer M;
|
|
50
74
|
} ? Simplify<M> : unknown;
|
|
51
|
-
/**
|
|
52
|
-
* Type-level marker interface for cross-package type inference.
|
|
53
|
-
* This enables TypeScript to infer tool types across package boundaries
|
|
54
|
-
* using structural typing on the $types property, rather than relying on
|
|
55
|
-
* class generic inference which fails when McpServer comes from different
|
|
56
|
-
* package installations.
|
|
57
|
-
*
|
|
58
|
-
* Inspired by tRPC's _def pattern and Hono's type markers.
|
|
59
|
-
*/
|
|
60
|
-
export interface McpServerTypes<TTools extends Record<string, ToolDef>> {
|
|
61
|
-
readonly tools: TTools;
|
|
62
|
-
}
|
|
63
|
-
type ShapeOutput<Shape extends ZodRawShapeCompat> = Simplify<{
|
|
64
|
-
[K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? never : K]: SchemaOutput<Shape[K]>;
|
|
65
|
-
} & {
|
|
66
|
-
[K in keyof Shape as undefined extends SchemaOutput<Shape[K]> ? K : never]?: SchemaOutput<Shape[K]>;
|
|
67
|
-
}>;
|
|
68
75
|
type AddTool<TTools, TName extends string, TInput extends ZodRawShapeCompat, TOutput, TResponseMetadata = unknown> = McpServer<TTools & {
|
|
69
76
|
[K in TName]: ToolDef<ShapeOutput<TInput>, TOutput, TResponseMetadata>;
|
|
70
77
|
}>;
|
|
71
|
-
|
|
78
|
+
interface UnifiedToolConfig<TInput extends ZodRawShapeCompat | AnySchema> {
|
|
79
|
+
name: string;
|
|
72
80
|
title?: string;
|
|
73
81
|
description?: string;
|
|
74
82
|
inputSchema?: TInput;
|
|
75
83
|
outputSchema?: ZodRawShapeCompat | AnySchema;
|
|
76
84
|
annotations?: ToolAnnotations;
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
view?: ViewConfig;
|
|
86
|
+
_meta?: ToolMeta;
|
|
87
|
+
}
|
|
79
88
|
type ToolHandler<TInput extends ZodRawShapeCompat, TReturn extends {
|
|
80
|
-
content
|
|
81
|
-
} =
|
|
82
|
-
|
|
89
|
+
content?: HandlerContent;
|
|
90
|
+
} = {
|
|
91
|
+
content?: HandlerContent;
|
|
92
|
+
}> = (args: ShapeOutput<TInput>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => TReturn | Promise<TReturn>;
|
|
93
|
+
export declare function normalizeContent(content: HandlerContent | undefined): ContentBlock[];
|
|
94
|
+
interface McpServerBaseOmitted extends Omit<McpServerBase, "registerTool" | "connect"> {
|
|
95
|
+
}
|
|
96
|
+
declare const McpServerBaseOmitted: new (...args: ConstructorParameters<typeof McpServerBase>) => McpServerBaseOmitted;
|
|
97
|
+
export declare class McpServer<TTools extends Record<string, ToolDef> = Record<never, ToolDef>> extends McpServerBaseOmitted {
|
|
83
98
|
readonly $types: McpServerTypes<TTools>;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
private express?;
|
|
100
|
+
private customMiddleware;
|
|
101
|
+
private customErrorMiddleware;
|
|
102
|
+
private mcpMiddlewareEntries;
|
|
103
|
+
private mcpMiddlewareApplied;
|
|
104
|
+
private claimedViews;
|
|
105
|
+
use(...handlers: RequestHandler[]): this;
|
|
106
|
+
use(path: string, ...handlers: RequestHandler[]): this;
|
|
107
|
+
useOnError(...handlers: ErrorRequestHandler[]): this;
|
|
108
|
+
useOnError(path: string, ...handlers: ErrorRequestHandler[]): this;
|
|
109
|
+
/** Register MCP protocol-level middleware (catch-all). */
|
|
110
|
+
mcpMiddleware(handler: McpMiddlewareFn): this;
|
|
111
|
+
/** Register MCP protocol-level middleware for all requests (`extra` is `McpExtra`). */
|
|
112
|
+
mcpMiddleware(filter: "request", handler: (request: {
|
|
113
|
+
method: string;
|
|
114
|
+
params: Record<string, unknown>;
|
|
115
|
+
}, extra: McpExtra, next: () => Promise<ServerResult>) => Promise<unknown> | unknown): this;
|
|
116
|
+
/** Register MCP protocol-level middleware for all notifications (`extra` is `undefined`). */
|
|
117
|
+
mcpMiddleware(filter: "notification", handler: (request: {
|
|
118
|
+
method: string;
|
|
119
|
+
params: Record<string, unknown>;
|
|
120
|
+
}, extra: undefined, next: () => Promise<undefined>) => Promise<unknown> | unknown): this;
|
|
121
|
+
/**
|
|
122
|
+
* Register MCP protocol-level middleware for an exact method.
|
|
123
|
+
* Narrows `params`, `extra`, and `next()` result based on the method string.
|
|
124
|
+
*/
|
|
125
|
+
mcpMiddleware<M extends McpMethodString>(filter: M, handler: McpTypedMiddlewareFn<M>): this;
|
|
126
|
+
/**
|
|
127
|
+
* Register MCP protocol-level middleware for a wildcard pattern (e.g. `"tools/*"`).
|
|
128
|
+
* `next()` returns the union of result types for matching methods.
|
|
129
|
+
*/
|
|
130
|
+
mcpMiddleware<W extends McpWildcard>(filter: W, handler: (request: {
|
|
131
|
+
method: string;
|
|
132
|
+
params: Record<string, unknown>;
|
|
133
|
+
}, extra: McpExtraFor<W>, next: () => Promise<McpResultFor<W>>) => Promise<unknown> | unknown): this;
|
|
134
|
+
/**
|
|
135
|
+
* Register MCP protocol-level middleware with a method filter.
|
|
136
|
+
* Filter can be an exact method (`"tools/call"`), wildcard (`"tools/*"`),
|
|
137
|
+
* category (`"request"` | `"notification"`), or an array of those.
|
|
138
|
+
*/
|
|
139
|
+
mcpMiddleware(filter: McpMiddlewareFilter, handler: McpMiddlewareFn): this;
|
|
140
|
+
private applyMcpMiddleware;
|
|
141
|
+
connect(transport: Parameters<typeof McpServerBase.prototype.connect>[0]): Promise<void>;
|
|
142
|
+
run(): Promise<void>;
|
|
143
|
+
private enforceOneToolPerView;
|
|
144
|
+
private registerViewResources;
|
|
145
|
+
private registerViewResource;
|
|
146
|
+
private wrapHandler;
|
|
147
|
+
private lookupViewFile;
|
|
95
148
|
private lookupDistFile;
|
|
96
|
-
private lookupDistFileWithIndexFallback;
|
|
97
149
|
private readManifest;
|
|
150
|
+
registerTool<TName extends string, InputArgs extends ZodRawShapeCompat, TReturn extends {
|
|
151
|
+
content?: HandlerContent;
|
|
152
|
+
}>(config: UnifiedToolConfig<InputArgs> & {
|
|
153
|
+
name: TName;
|
|
154
|
+
}, cb: ToolHandler<InputArgs, TReturn>): AddTool<TTools, TName, InputArgs, ExtractStructuredContent<TReturn>, ExtractMeta<TReturn>>;
|
|
155
|
+
registerTool<InputArgs extends ZodRawShapeCompat>(config: UnifiedToolConfig<InputArgs>, cb: ToolHandler<InputArgs>): this;
|
|
98
156
|
}
|
|
99
157
|
export {};
|
package/dist/server/server.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
1
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import http from "node:http";
|
|
2
4
|
import path from "node:path";
|
|
3
|
-
import { McpServer as McpServerBase
|
|
5
|
+
import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
6
|
import { mergeWith, union } from "es-toolkit";
|
|
7
|
+
import { createApp } from "./express.js";
|
|
8
|
+
import { createMiddlewareEntry } from "./metric.js";
|
|
9
|
+
import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
|
|
5
10
|
import { templateHelper } from "./templateHelper.js";
|
|
6
11
|
const mergeWithUnion = (target, source) => {
|
|
7
12
|
return mergeWith(target, source, (targetVal, sourceVal) => {
|
|
@@ -10,110 +15,304 @@ const mergeWithUnion = (target, source) => {
|
|
|
10
15
|
}
|
|
11
16
|
});
|
|
12
17
|
};
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
export function normalizeContent(content) {
|
|
19
|
+
if (content === undefined) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
if (typeof content === "string") {
|
|
23
|
+
return [{ type: "text", text: content }];
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(content)) {
|
|
26
|
+
return content;
|
|
27
|
+
}
|
|
28
|
+
return [content];
|
|
29
|
+
}
|
|
30
|
+
const McpServerBaseOmitted = McpServerBase;
|
|
31
|
+
export class McpServer extends McpServerBaseOmitted {
|
|
32
|
+
express;
|
|
33
|
+
customMiddleware = [];
|
|
34
|
+
customErrorMiddleware = [];
|
|
35
|
+
mcpMiddlewareEntries = [];
|
|
36
|
+
mcpMiddlewareApplied = false;
|
|
37
|
+
claimedViews = new Map();
|
|
38
|
+
use(pathOrHandler, ...handlers) {
|
|
39
|
+
if (typeof pathOrHandler === "string") {
|
|
40
|
+
this.customMiddleware.push({
|
|
41
|
+
path: pathOrHandler,
|
|
42
|
+
handlers,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.customMiddleware.push({
|
|
47
|
+
handlers: [pathOrHandler, ...handlers],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
useOnError(pathOrHandler, ...handlers) {
|
|
53
|
+
if (typeof pathOrHandler === "string") {
|
|
54
|
+
this.customErrorMiddleware.push({ path: pathOrHandler, handlers });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.customErrorMiddleware.push({
|
|
58
|
+
handlers: [pathOrHandler, ...handlers],
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
mcpMiddleware(filterOrHandler,
|
|
64
|
+
// biome-ignore lint/suspicious/noExplicitAny: overloads narrow the handler type at call sites; implementation must accept all variants
|
|
65
|
+
maybeHandler) {
|
|
66
|
+
if (this.mcpMiddlewareApplied) {
|
|
67
|
+
throw new Error("Cannot register MCP middleware after run() or connect() has been called");
|
|
68
|
+
}
|
|
69
|
+
const handler = maybeHandler;
|
|
70
|
+
if (typeof filterOrHandler === "function") {
|
|
71
|
+
this.mcpMiddlewareEntries.push({
|
|
72
|
+
filter: null,
|
|
73
|
+
handler: filterOrHandler,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else if (handler) {
|
|
77
|
+
this.mcpMiddlewareEntries.push({
|
|
78
|
+
filter: filterOrHandler,
|
|
79
|
+
handler,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new Error("mcpMiddleware requires a handler function when a filter is provided");
|
|
84
|
+
}
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
applyMcpMiddleware() {
|
|
88
|
+
if (this.mcpMiddlewareApplied) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.mcpMiddlewareApplied = true;
|
|
92
|
+
const monitoringEntry = createMiddlewareEntry();
|
|
93
|
+
const entries = monitoringEntry
|
|
94
|
+
? [monitoringEntry, ...this.mcpMiddlewareEntries]
|
|
95
|
+
: this.mcpMiddlewareEntries;
|
|
96
|
+
if (entries.length === 0) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const { requestHandlers, notificationHandlers } = getHandlerMaps(this.server);
|
|
100
|
+
const instrumentMap = (map, isNotification) => {
|
|
101
|
+
for (const [method, handler] of map) {
|
|
102
|
+
map.set(method, buildMiddlewareChain(method, isNotification, handler, entries));
|
|
103
|
+
}
|
|
104
|
+
const originalSet = map.set.bind(map);
|
|
105
|
+
map.set = (method, handler) => originalSet(method, buildMiddlewareChain(method, isNotification, handler, entries));
|
|
18
106
|
};
|
|
19
|
-
|
|
20
|
-
|
|
107
|
+
instrumentMap(requestHandlers, false);
|
|
108
|
+
instrumentMap(notificationHandlers, true);
|
|
109
|
+
}
|
|
110
|
+
async connect(transport) {
|
|
111
|
+
this.applyMcpMiddleware();
|
|
112
|
+
return McpServerBase.prototype.connect.call(this, transport);
|
|
113
|
+
}
|
|
114
|
+
async run() {
|
|
115
|
+
this.applyMcpMiddleware();
|
|
116
|
+
const httpServer = http.createServer();
|
|
117
|
+
if (!this.express) {
|
|
118
|
+
this.express = await createApp({
|
|
119
|
+
mcpServer: this,
|
|
120
|
+
httpServer,
|
|
121
|
+
customMiddleware: this.customMiddleware,
|
|
122
|
+
errorMiddleware: this.customErrorMiddleware,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
httpServer.on("request", this.express);
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
httpServer.on("error", (error) => {
|
|
128
|
+
console.error("Failed to start server:", error);
|
|
129
|
+
reject(error);
|
|
130
|
+
});
|
|
131
|
+
const port = parseInt(process.env.__PORT ?? "3000", 10);
|
|
132
|
+
httpServer.listen(port, () => {
|
|
133
|
+
resolve();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
enforceOneToolPerView(component, toolName) {
|
|
138
|
+
const existingTool = this.claimedViews.get(component);
|
|
139
|
+
if (existingTool) {
|
|
140
|
+
throw new Error(`skybridge: view "${component}" is already used by tool "${existingTool}". Tool "${toolName}" cannot also reference it — each view backs exactly one tool.`);
|
|
141
|
+
}
|
|
142
|
+
this.claimedViews.set(component, toolName);
|
|
143
|
+
}
|
|
144
|
+
registerViewResources(toolName, view, toolMeta) {
|
|
145
|
+
const hosts = view.hosts ?? ["apps-sdk", "mcp-app"];
|
|
146
|
+
if (hosts.includes("apps-sdk")) {
|
|
147
|
+
const viewResource = {
|
|
21
148
|
hostType: "apps-sdk",
|
|
22
|
-
uri: `ui://widgets/apps-sdk/${
|
|
149
|
+
uri: `ui://widgets/apps-sdk/${view.component}.html`,
|
|
23
150
|
mimeType: "text/html+skybridge",
|
|
24
|
-
buildContentMeta: ({ resourceDomains, connectDomains, domain }) => {
|
|
25
|
-
const userUi = userMeta?.ui;
|
|
26
|
-
const userCsp = userUi?.csp;
|
|
151
|
+
buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
|
|
27
152
|
const defaults = {
|
|
28
153
|
"openai/widgetCSP": {
|
|
29
154
|
resource_domains: resourceDomains,
|
|
30
155
|
connect_domains: connectDomains,
|
|
31
156
|
},
|
|
32
157
|
"openai/widgetDomain": domain,
|
|
33
|
-
"openai/widgetDescription":
|
|
158
|
+
"openai/widgetDescription": view.description,
|
|
34
159
|
};
|
|
35
|
-
const
|
|
160
|
+
const fromView = {
|
|
36
161
|
"openai/widgetCSP": {
|
|
37
|
-
resource_domains:
|
|
38
|
-
connect_domains:
|
|
39
|
-
frame_domains:
|
|
40
|
-
redirect_domains:
|
|
162
|
+
resource_domains: view.csp?.resourceDomains,
|
|
163
|
+
connect_domains: view.csp?.connectDomains,
|
|
164
|
+
frame_domains: view.csp?.frameDomains,
|
|
165
|
+
redirect_domains: view.csp?.redirectDomains,
|
|
41
166
|
},
|
|
42
|
-
"openai/widgetDomain":
|
|
43
|
-
"openai/widgetPrefersBorder":
|
|
167
|
+
"openai/widgetDomain": view.domain,
|
|
168
|
+
"openai/widgetPrefersBorder": view.prefersBorder,
|
|
44
169
|
};
|
|
45
|
-
const
|
|
46
|
-
|
|
170
|
+
const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
|
|
171
|
+
"openai/widgetDomain": overrides.domain,
|
|
172
|
+
});
|
|
173
|
+
if (view._meta) {
|
|
174
|
+
return { ...base, ...view._meta };
|
|
175
|
+
}
|
|
176
|
+
return base;
|
|
47
177
|
},
|
|
48
178
|
};
|
|
49
|
-
this.
|
|
50
|
-
name,
|
|
51
|
-
|
|
52
|
-
|
|
179
|
+
this.registerViewResource({
|
|
180
|
+
name: toolName,
|
|
181
|
+
viewResource,
|
|
182
|
+
view,
|
|
53
183
|
});
|
|
54
|
-
toolMeta["openai/outputTemplate"] =
|
|
184
|
+
toolMeta["openai/outputTemplate"] = viewResource.uri;
|
|
55
185
|
}
|
|
56
|
-
if (
|
|
57
|
-
const
|
|
186
|
+
if (hosts.includes("mcp-app")) {
|
|
187
|
+
const viewResource = {
|
|
58
188
|
hostType: "mcp-app",
|
|
59
|
-
uri: `ui://widgets/ext-apps/${
|
|
189
|
+
uri: `ui://widgets/ext-apps/${view.component}.html`,
|
|
60
190
|
mimeType: "text/html;profile=mcp-app",
|
|
61
|
-
buildContentMeta: ({ resourceDomains, connectDomains, domain }) => {
|
|
191
|
+
buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
|
|
62
192
|
const defaults = {
|
|
63
193
|
ui: {
|
|
64
194
|
csp: {
|
|
65
195
|
resourceDomains,
|
|
66
196
|
connectDomains,
|
|
197
|
+
baseUriDomains,
|
|
67
198
|
},
|
|
68
199
|
domain,
|
|
69
200
|
},
|
|
70
201
|
};
|
|
71
|
-
|
|
202
|
+
const fromView = {
|
|
203
|
+
ui: {
|
|
204
|
+
...(view.description && { description: view.description }),
|
|
205
|
+
...(view.prefersBorder !== undefined && {
|
|
206
|
+
prefersBorder: view.prefersBorder,
|
|
207
|
+
}),
|
|
208
|
+
...(view.domain && { domain: view.domain }),
|
|
209
|
+
csp: {
|
|
210
|
+
...(view.csp?.resourceDomains && {
|
|
211
|
+
resourceDomains: view.csp.resourceDomains,
|
|
212
|
+
}),
|
|
213
|
+
...(view.csp?.connectDomains && {
|
|
214
|
+
connectDomains: view.csp.connectDomains,
|
|
215
|
+
}),
|
|
216
|
+
...(view.csp?.frameDomains && {
|
|
217
|
+
frameDomains: view.csp.frameDomains,
|
|
218
|
+
}),
|
|
219
|
+
...(view.csp?.baseUriDomains && {
|
|
220
|
+
baseUriDomains: view.csp.baseUriDomains,
|
|
221
|
+
}),
|
|
222
|
+
...(view.csp?.redirectDomains && {
|
|
223
|
+
redirectDomains: view.csp.redirectDomains,
|
|
224
|
+
}),
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
|
|
229
|
+
ui: overrides,
|
|
230
|
+
});
|
|
231
|
+
if (view._meta) {
|
|
232
|
+
return { ...base, ...view._meta };
|
|
233
|
+
}
|
|
234
|
+
return base;
|
|
72
235
|
},
|
|
73
236
|
};
|
|
74
|
-
this.
|
|
75
|
-
name,
|
|
76
|
-
|
|
77
|
-
|
|
237
|
+
this.registerViewResource({
|
|
238
|
+
name: toolName,
|
|
239
|
+
viewResource,
|
|
240
|
+
view,
|
|
78
241
|
});
|
|
79
|
-
|
|
242
|
+
// @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
|
|
243
|
+
toolMeta["ui/resourceUri"] = viewResource.uri;
|
|
244
|
+
toolMeta.ui = { resourceUri: viewResource.uri };
|
|
80
245
|
}
|
|
81
|
-
this.registerTool(name, {
|
|
82
|
-
...toolConfig,
|
|
83
|
-
_meta: toolMeta,
|
|
84
|
-
}, toolCallback);
|
|
85
|
-
return this;
|
|
86
246
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
registerWidgetResource({ name, widgetConfig, resourceConfig, }) {
|
|
92
|
-
const { hostType, uri: widgetUri, mimeType, buildContentMeta, } = widgetConfig;
|
|
93
|
-
this.registerResource(name, widgetUri, { ...resourceConfig, _meta: resourceConfig._meta }, async (uri, extra) => {
|
|
247
|
+
registerViewResource({ name, viewResource, view, }) {
|
|
248
|
+
const { hostType, uri: viewUri, mimeType, buildContentMeta } = viewResource;
|
|
249
|
+
this.registerResource(name, viewUri, { description: view.description }, async (uri, extra) => {
|
|
94
250
|
const isProduction = process.env.NODE_ENV === "production";
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
251
|
+
const isClaude = extra?.requestInfo?.headers?.["user-agent"] === "Claude-User";
|
|
252
|
+
const headers = extra?.requestInfo?.headers || {};
|
|
253
|
+
const header = (key) => {
|
|
254
|
+
const val = headers[key];
|
|
255
|
+
return Array.isArray(val) ? val[0] : val;
|
|
256
|
+
};
|
|
257
|
+
let serverUrl;
|
|
258
|
+
const forwardedHost = header("x-forwarded-host");
|
|
259
|
+
const origin = header("origin");
|
|
260
|
+
const host = header("host");
|
|
261
|
+
if (forwardedHost) {
|
|
262
|
+
const proto = header("x-forwarded-proto") || "https";
|
|
263
|
+
serverUrl = `${proto}://${forwardedHost}`;
|
|
264
|
+
}
|
|
265
|
+
else if (origin) {
|
|
266
|
+
serverUrl = origin;
|
|
267
|
+
}
|
|
268
|
+
else if (host) {
|
|
269
|
+
const proto = ["127.0.0.1:", "localhost:"].some((p) => host.startsWith(p))
|
|
270
|
+
? "http"
|
|
271
|
+
: "https";
|
|
272
|
+
serverUrl = `${proto}://${host}`;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const devPort = process.env.__PORT || "3000";
|
|
276
|
+
serverUrl = `http://localhost:${devPort}`;
|
|
277
|
+
}
|
|
98
278
|
const html = isProduction
|
|
99
279
|
? templateHelper.renderProduction({
|
|
100
280
|
hostType,
|
|
101
281
|
serverUrl,
|
|
102
|
-
|
|
103
|
-
styleFile: this.lookupDistFile("style.css"),
|
|
282
|
+
viewFile: this.lookupViewFile(view.component),
|
|
283
|
+
styleFile: this.lookupDistFile("style.css") ?? "",
|
|
104
284
|
})
|
|
105
285
|
: templateHelper.renderDevelopment({
|
|
106
286
|
hostType,
|
|
107
287
|
serverUrl,
|
|
108
|
-
|
|
288
|
+
viewName: view.component,
|
|
109
289
|
});
|
|
110
|
-
const
|
|
290
|
+
const connectDomains = [serverUrl];
|
|
291
|
+
if (!isProduction) {
|
|
292
|
+
const wsUrl = new URL(serverUrl);
|
|
293
|
+
wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
294
|
+
connectDomains.push(wsUrl.origin);
|
|
295
|
+
}
|
|
296
|
+
let contentMetaOverrides = {};
|
|
297
|
+
if (isClaude) {
|
|
298
|
+
const pathname = extra?.requestInfo?.url?.pathname ?? "";
|
|
299
|
+
const rawUrl = header("x-alpic-forwarded-url") ?? `${serverUrl}${pathname}`;
|
|
300
|
+
// Strip a lone trailing slash so the hash matches the connector URL
|
|
301
|
+
// as registered with Claude (which has no trailing slash on bare origins).
|
|
302
|
+
const url = rawUrl.endsWith("/") ? rawUrl.slice(0, -1) : rawUrl;
|
|
303
|
+
const hash = crypto
|
|
304
|
+
.createHash("sha256")
|
|
305
|
+
.update(url)
|
|
306
|
+
.digest("hex")
|
|
307
|
+
.slice(0, 32);
|
|
308
|
+
contentMetaOverrides = { domain: `${hash}.claudemcpcontent.com` };
|
|
309
|
+
}
|
|
111
310
|
const contentMeta = buildContentMeta({
|
|
112
311
|
resourceDomains: [serverUrl],
|
|
113
|
-
connectDomains
|
|
312
|
+
connectDomains,
|
|
114
313
|
domain: serverUrl,
|
|
115
314
|
baseUriDomains: [serverUrl],
|
|
116
|
-
});
|
|
315
|
+
}, contentMetaOverrides);
|
|
117
316
|
return {
|
|
118
317
|
contents: [
|
|
119
318
|
{ uri: uri.href, mimeType, text: html, _meta: contentMeta },
|
|
@@ -121,18 +320,54 @@ export class McpServer extends McpServerBase {
|
|
|
121
320
|
};
|
|
122
321
|
});
|
|
123
322
|
}
|
|
124
|
-
|
|
323
|
+
wrapHandler(cb, { attachViewUUID }) {
|
|
324
|
+
return async (args, extra) => {
|
|
325
|
+
const result = await cb(args, extra);
|
|
326
|
+
return {
|
|
327
|
+
...result,
|
|
328
|
+
content: normalizeContent(result.content),
|
|
329
|
+
...(attachViewUUID && {
|
|
330
|
+
_meta: {
|
|
331
|
+
...result._meta,
|
|
332
|
+
viewUUID: crypto.randomUUID(),
|
|
333
|
+
},
|
|
334
|
+
}),
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
lookupViewFile(viewName) {
|
|
125
339
|
const manifest = this.readManifest();
|
|
126
|
-
|
|
340
|
+
for (const entry of Object.values(manifest)) {
|
|
341
|
+
if (entry?.isEntry && entry.name === viewName && entry.file) {
|
|
342
|
+
return entry.file;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
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.`);
|
|
127
346
|
}
|
|
128
|
-
|
|
347
|
+
lookupDistFile(key) {
|
|
129
348
|
const manifest = this.readManifest();
|
|
130
|
-
|
|
131
|
-
const indexFileKey = `${basePath}/index.tsx`;
|
|
132
|
-
return manifest[flatFileKey]?.file ?? manifest[indexFileKey]?.file;
|
|
349
|
+
return manifest[key]?.file;
|
|
133
350
|
}
|
|
134
351
|
readManifest() {
|
|
135
352
|
return JSON.parse(readFileSync(path.join(process.cwd(), "dist", "assets", ".vite", "manifest.json"), "utf-8"));
|
|
136
353
|
}
|
|
354
|
+
registerTool(...args) {
|
|
355
|
+
const baseFn = McpServerBase.prototype.registerTool;
|
|
356
|
+
if (typeof args[0] === "string") {
|
|
357
|
+
baseFn.call(this, args[0], args[1], args[2]);
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
const config = args[0];
|
|
361
|
+
const cb = args[1];
|
|
362
|
+
const { name, view, _meta: userToolMeta, ...toolFields } = config;
|
|
363
|
+
const toolMeta = { ...userToolMeta };
|
|
364
|
+
if (view) {
|
|
365
|
+
this.enforceOneToolPerView(view.component, name);
|
|
366
|
+
this.registerViewResources(name, view, toolMeta);
|
|
367
|
+
}
|
|
368
|
+
const wrappedCb = this.wrapHandler(cb, { attachViewUUID: Boolean(view) });
|
|
369
|
+
baseFn.call(this, name, { ...toolFields, _meta: toolMeta }, wrappedCb);
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
137
372
|
}
|
|
138
373
|
//# sourceMappingURL=server.js.map
|