mcp-use 2.0.0-beta.7 → 2.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/branding.d.ts +85 -0
  3. package/dist/branding.d.ts.map +1 -0
  4. package/dist/{chunk-FCGJJVL2.js → chunk-GTOOHAI2.js} +2 -1
  5. package/dist/chunk-GTOOHAI2.js.map +1 -0
  6. package/dist/chunk-KIZ72TIK.js +38 -0
  7. package/dist/chunk-KIZ72TIK.js.map +1 -0
  8. package/dist/{public-route-26FUVRO5.js → chunk-SMN75YED.js} +12 -8
  9. package/dist/chunk-SMN75YED.js.map +1 -0
  10. package/dist/cli/build.d.ts.map +1 -1
  11. package/dist/commands/build.js +8 -4
  12. package/dist/commands/build.js.map +1 -1
  13. package/dist/completable.d.ts +9 -0
  14. package/dist/completable.d.ts.map +1 -1
  15. package/dist/config.d.ts +69 -1
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/index.d.ts +4 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +347 -39
  20. package/dist/index.js.map +1 -1
  21. package/dist/inspector-shell.d.ts +3 -0
  22. package/dist/inspector-shell.d.ts.map +1 -1
  23. package/dist/internal/resource-completion.js +7 -0
  24. package/dist/internal/resource-completion.js.map +1 -0
  25. package/dist/{landing-handler-VQRYCQOV.js → landing-handler-3VN4BMR2.js} +6 -3
  26. package/dist/landing-handler-3VN4BMR2.js.map +1 -0
  27. package/dist/landing-handler.d.ts +3 -1
  28. package/dist/landing-handler.d.ts.map +1 -1
  29. package/dist/landing.d.ts.map +1 -1
  30. package/dist/landing.js +1 -1
  31. package/dist/public-route-5JEGFEIN.js +9 -0
  32. package/dist/public-route-5JEGFEIN.js.map +1 -0
  33. package/dist/resource-completion.d.ts +12 -0
  34. package/dist/resource-completion.d.ts.map +1 -0
  35. package/dist/resources.d.ts +38 -4
  36. package/dist/resources.d.ts.map +1 -1
  37. package/dist/server.d.ts +20 -1
  38. package/dist/server.d.ts.map +1 -1
  39. package/dist/views/public-route.d.ts +3 -1
  40. package/dist/views/public-route.d.ts.map +1 -1
  41. package/dist/views/routes.d.ts +3 -1
  42. package/dist/views/routes.d.ts.map +1 -1
  43. package/package.json +2 -2
  44. package/dist/chunk-FCGJJVL2.js.map +0 -1
  45. package/dist/landing-handler-VQRYCQOV.js.map +0 -1
  46. package/dist/public-route-26FUVRO5.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -42,6 +42,9 @@ export type { CompletionCallback, CompletionContext } from "./completable.js";
42
42
  */
43
43
  export type { StandardSchemaV1, StandardSchemaWithJSON, } from "@modelcontextprotocol/server";
44
44
  export type { InspectorOptions, ServerConfig, CorsOptions } from "./config.js";
45
+ export type { ServerBranding } from "./branding.js";
46
+ /** Official MCP icon shape used by {@link ServerConfig.icons}. */
47
+ export type { Icon } from "@modelcontextprotocol/server";
45
48
  export type { MiddlewareContext, McpCompleteEventListenerFn, McpEventListenerFn, McpMiddlewareFn, McpMiddlewareFnFor, McpMiddlewarePatternMap, PromptsGetMiddlewareContext, ResourcesReadMiddlewareContext, ToolsCallMiddlewareContext, } from "./middleware/mcp-middleware.js";
46
49
  export { composeMiddleware, matchesPattern, } from "./middleware/mcp-middleware.js";
47
50
  export type { NodeRequestHandler } from "./node-bridge.js";
@@ -49,6 +52,6 @@ export type { FromOpenAPIOptions, OpenAPIAuth, OpenAPIDocument, OpenAPIExcludeRu
49
52
  export type { Elicit, ElicitationResult, OAuthAuth, RequestClientContext, RequestContext, } from "./context.js";
50
53
  export type { InferToolInput, InferToolName, InferToolOutput, ToolCallback, ToolDefinition, ToolRef, ToolResult, ToolViewConfig, } from "./tools.js";
51
54
  export type { ExternalViewManifestEntry, InlineViewManifestEntry, UiPermissions, ViewManifestEntry, ViewsManifest, } from "./views/index.js";
52
- export type { InferTemplateParams, ResourceCallback, ResourceDefinition, ResourceTemplateCallback, ResourceTemplateDefinition, TemplateVariableValue, } from "./resources.js";
55
+ export type { InferTemplateParams, ResourceCallback, ResourceDefinition, ResourceTemplateCallback, ResourceTemplateCompleter, ResourceTemplateCompletions, ResourceTemplateDefinition, TemplateVariableValue, } from "./resources.js";
53
56
  export type { InferPromptInput, PromptCallback, PromptDefinition, } from "./prompts.js";
54
57
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,0BAA0B,EAC1B,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,YAAY,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC;;;;;GAKG;AACH,YAAY,EACV,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC;;;GAGG;AACH,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE9E;;;;;GAKG;AACH,YAAY,EACV,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,oBAAoB,EACpB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,OAAO,EACP,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,0BAA0B,EAC1B,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,YAAY,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC;;;;;GAKG;AACH,YAAY,EACV,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC;;;GAGG;AACH,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE9E;;;;;GAKG;AACH,YAAY,EACV,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,kEAAkE;AAClE,YAAY,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,oBAAoB,EACpB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,OAAO,EACP,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,14 @@
1
+ import {
2
+ resolvePublicFilePath,
3
+ servePublicFile
4
+ } from "./chunk-SMN75YED.js";
1
5
  import {
2
6
  registerOpenAPITools
3
7
  } from "./chunk-AATFAERC.js";
8
+ import {
9
+ completable,
10
+ normalizeCompletions
11
+ } from "./chunk-KIZ72TIK.js";
4
12
  import {
5
13
  synthesizeViewDocument
6
14
  } from "./chunk-STCR3P5O.js";
@@ -46,6 +54,266 @@ import {
46
54
  isInputRequiredResult
47
55
  } from "@modelcontextprotocol/server";
48
56
 
57
+ // src/branding.ts
58
+ var FAVICON_CACHE_CONTROL = "public, max-age=31536000, immutable";
59
+ var FAVICON_REDIRECT_CACHE_CONTROL = "public, max-age=300";
60
+ function protocolOf(value) {
61
+ const match = /^([a-z][a-z\d+.-]*):/i.exec(value);
62
+ return match?.[1]?.toLowerCase();
63
+ }
64
+ function publicAssetPath(basePath, source) {
65
+ const prefix = basePath === "/" ? "" : basePath;
66
+ return `${prefix}/_mcp-use/public/${source.split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
67
+ }
68
+ function isLocalPublicSource(source) {
69
+ return protocolOf(source) === void 0;
70
+ }
71
+ function extensionPath(source) {
72
+ const protocol = protocolOf(source);
73
+ if (protocol === "data") {
74
+ return "";
75
+ }
76
+ if (protocol === "http" || protocol === "https") {
77
+ return new URL(source).pathname.toLowerCase();
78
+ }
79
+ return source.toLowerCase();
80
+ }
81
+ function dataUrlMimeType(source) {
82
+ if (protocolOf(source) !== "data") {
83
+ return void 0;
84
+ }
85
+ const comma = source.indexOf(",");
86
+ if (comma < 0) {
87
+ return void 0;
88
+ }
89
+ const mimeType = source.slice(5, comma).split(";", 1)[0]?.toLowerCase();
90
+ return mimeType === "" ? void 0 : mimeType;
91
+ }
92
+ function iconMimeType(icon) {
93
+ return icon.mimeType?.toLowerCase() ?? dataUrlMimeType(icon.src);
94
+ }
95
+ function isIco(icon) {
96
+ const mimeType = iconMimeType(icon);
97
+ return mimeType === "image/x-icon" || mimeType === "image/vnd.microsoft.icon" || extensionPath(icon.src).endsWith(".ico");
98
+ }
99
+ function isPng(icon) {
100
+ return iconMimeType(icon) === "image/png" || extensionPath(icon.src).endsWith(".png");
101
+ }
102
+ function selectFaviconFromIcons(icons) {
103
+ return icons.find(isIco) ?? icons.find(
104
+ (icon) => isPng(icon) && icon.sizes?.some((size) => size === "16x16" || size === "32x32")
105
+ ) ?? icons.find(isPng) ?? icons[0];
106
+ }
107
+ function assertLocalPublicSource(source, field) {
108
+ if (source.startsWith("/") || source.includes("\\") || source.includes("?") || source.includes("#") || source.split("/").some((segment) => segment === "" || segment === "..")) {
109
+ throw new TypeError(
110
+ `${field} must be an http(s) URL, image data URL, or safe path relative to public/`
111
+ );
112
+ }
113
+ }
114
+ function parseDataImage(source, field) {
115
+ const comma = source.indexOf(",");
116
+ if (comma < 0) {
117
+ throw new TypeError(`${field} must be a valid image data URL`);
118
+ }
119
+ const metadata = source.slice(5, comma);
120
+ const payload = source.slice(comma + 1);
121
+ const parts = metadata.split(";");
122
+ const mimeType = parts[0]?.toLowerCase() ?? "";
123
+ if (!mimeType.startsWith("image/")) {
124
+ throw new TypeError(`${field} data URL must use an image MIME type`);
125
+ }
126
+ try {
127
+ if (parts.includes("base64")) {
128
+ const binary = atob(payload);
129
+ return {
130
+ mimeType,
131
+ bytes: Uint8Array.from(binary, (character) => character.charCodeAt(0))
132
+ };
133
+ }
134
+ return {
135
+ mimeType,
136
+ bytes: new TextEncoder().encode(decodeURIComponent(payload))
137
+ };
138
+ } catch {
139
+ throw new TypeError(`${field} must be a valid image data URL`);
140
+ }
141
+ }
142
+ function assertBrandingSource(source, field) {
143
+ if (typeof source !== "string" || source.length === 0) {
144
+ throw new TypeError(`${field} must be a non-empty string`);
145
+ }
146
+ const protocol = protocolOf(source);
147
+ if (protocol === void 0) {
148
+ assertLocalPublicSource(source, field);
149
+ return source;
150
+ }
151
+ if (protocol === "data") {
152
+ parseDataImage(source, field);
153
+ return source;
154
+ }
155
+ if (protocol !== "http" && protocol !== "https") {
156
+ throw new TypeError(
157
+ `${field} must be an http(s) URL, image data URL, or safe path relative to public/`
158
+ );
159
+ }
160
+ try {
161
+ new URL(source);
162
+ } catch {
163
+ throw new TypeError(`${field} must be a valid absolute http(s) URL`);
164
+ }
165
+ return source;
166
+ }
167
+ function normalizeServerBranding(config) {
168
+ let websiteUrl;
169
+ if (config.websiteUrl !== void 0) {
170
+ if (typeof config.websiteUrl !== "string" || config.websiteUrl.length === 0) {
171
+ throw new TypeError(
172
+ "websiteUrl must be a non-empty absolute http(s) URL"
173
+ );
174
+ }
175
+ let parsed;
176
+ try {
177
+ parsed = new URL(config.websiteUrl);
178
+ } catch {
179
+ throw new TypeError(
180
+ "websiteUrl must be a non-empty absolute http(s) URL"
181
+ );
182
+ }
183
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
184
+ throw new TypeError(
185
+ "websiteUrl must be a non-empty absolute http(s) URL"
186
+ );
187
+ }
188
+ websiteUrl = config.websiteUrl;
189
+ }
190
+ let icons;
191
+ if (config.icons !== void 0) {
192
+ if (!Array.isArray(config.icons)) {
193
+ throw new TypeError("icons must be an array of MCP Icon objects");
194
+ }
195
+ icons = Object.freeze(
196
+ config.icons.map((value, index) => {
197
+ if (typeof value !== "object" || value === null) {
198
+ throw new TypeError(`icons[${index}] must be an MCP Icon object`);
199
+ }
200
+ const icon = value;
201
+ const src = assertBrandingSource(icon["src"], `icons[${index}].src`);
202
+ const mimeType = icon["mimeType"];
203
+ if (mimeType !== void 0 && (typeof mimeType !== "string" || !mimeType.toLowerCase().startsWith("image/"))) {
204
+ throw new TypeError(
205
+ `icons[${index}].mimeType must be an image MIME type when provided`
206
+ );
207
+ }
208
+ const sizes = icon["sizes"];
209
+ if (sizes !== void 0 && (!Array.isArray(sizes) || sizes.some((size) => typeof size !== "string" || size.length === 0))) {
210
+ throw new TypeError(
211
+ `icons[${index}].sizes must be an array of non-empty strings when provided`
212
+ );
213
+ }
214
+ const normalizedSizes = sizes === void 0 ? void 0 : sizes.map((size) => size);
215
+ const theme = icon["theme"];
216
+ if (theme !== void 0 && theme !== "light" && theme !== "dark") {
217
+ throw new TypeError(
218
+ `icons[${index}].theme must be "light" or "dark" when provided`
219
+ );
220
+ }
221
+ return Object.freeze({
222
+ src,
223
+ ...mimeType !== void 0 && { mimeType },
224
+ ...normalizedSizes !== void 0 && {
225
+ sizes: Object.freeze(normalizedSizes)
226
+ },
227
+ ...theme !== void 0 && { theme }
228
+ });
229
+ })
230
+ );
231
+ }
232
+ const explicitFavicon = config.favicon === void 0 ? void 0 : assertBrandingSource(config.favicon, "favicon");
233
+ const inferred = explicitFavicon === void 0 ? selectFaviconFromIcons(icons ?? []) : void 0;
234
+ const favicon = explicitFavicon ?? inferred?.src;
235
+ const faviconMimeType = inferred?.mimeType ?? icons?.find((icon) => icon.src === explicitFavicon)?.mimeType;
236
+ return Object.freeze({
237
+ ...favicon !== void 0 && { favicon },
238
+ ...faviconMimeType !== void 0 && { faviconMimeType },
239
+ ...icons !== void 0 && { icons },
240
+ ...websiteUrl !== void 0 && { websiteUrl }
241
+ });
242
+ }
243
+ function resolveImplementationIcons(icons, request, basePath) {
244
+ if (icons === void 0) {
245
+ return void 0;
246
+ }
247
+ return icons.map((icon) => ({
248
+ ...icon,
249
+ src: request !== void 0 && isLocalPublicSource(icon.src) ? `${resolveAssetsBase(request)}${publicAssetPath(basePath, icon.src)}` : icon.src,
250
+ ...icon.sizes !== void 0 && { sizes: [...icon.sizes] }
251
+ }));
252
+ }
253
+ function hasLocalBrandingAsset(branding) {
254
+ return branding.favicon !== void 0 && isLocalPublicSource(branding.favicon) || branding.icons?.some((icon) => isLocalPublicSource(icon.src)) === true;
255
+ }
256
+ function createFaviconHandler(branding, options) {
257
+ const source = branding.favicon;
258
+ if (source === void 0) {
259
+ return void 0;
260
+ }
261
+ return async (request) => {
262
+ if (request.method !== "GET" && request.method !== "HEAD") {
263
+ return new Response("Method Not Allowed", {
264
+ status: 405,
265
+ headers: { Allow: "GET, HEAD" }
266
+ });
267
+ }
268
+ if (new URL(request.url).pathname !== "/favicon.ico") {
269
+ return new Response("Not Found", { status: 404 });
270
+ }
271
+ const protocol = protocolOf(source);
272
+ if (protocol === "http" || protocol === "https") {
273
+ return new Response(null, {
274
+ status: 307,
275
+ headers: {
276
+ Location: source,
277
+ "Cache-Control": FAVICON_REDIRECT_CACHE_CONTROL
278
+ }
279
+ });
280
+ }
281
+ if (protocol === "data") {
282
+ const data = parseDataImage(source, "favicon");
283
+ return new Response(
284
+ request.method === "HEAD" ? null : data.bytes.buffer,
285
+ {
286
+ status: 200,
287
+ headers: {
288
+ "Content-Type": branding.faviconMimeType ?? data.mimeType,
289
+ "Cache-Control": FAVICON_CACHE_CONTROL,
290
+ "X-Content-Type-Options": "nosniff"
291
+ }
292
+ }
293
+ );
294
+ }
295
+ const { join } = await import("path");
296
+ const publicRoot = options.dev ? join(options.projectRoot, "public") : join(options.projectRoot, ".mcp-use/build/views/public");
297
+ const diskPath = await resolvePublicFilePath(publicRoot, source);
298
+ if (diskPath === null) {
299
+ return new Response("Not Found", {
300
+ status: 404,
301
+ headers: { "Cache-Control": "no-store" }
302
+ });
303
+ }
304
+ const response = await servePublicFile(diskPath, {
305
+ ...options.deferCors === true && { deferCors: true },
306
+ ...request.method === "HEAD" && { head: true }
307
+ });
308
+ response.headers.set("Cache-Control", FAVICON_CACHE_CONTROL);
309
+ response.headers.set("X-Content-Type-Options", "nosniff");
310
+ if (branding.faviconMimeType !== void 0) {
311
+ response.headers.set("Content-Type", branding.faviconMimeType);
312
+ }
313
+ return response;
314
+ };
315
+ }
316
+
49
317
  // src/config.ts
50
318
  function assertServerConfig(config) {
51
319
  if (config.basePath !== void 0) {
@@ -435,7 +703,7 @@ function serializeForInlineScript(value) {
435
703
  return JSON.stringify(value).replaceAll("<", "\\u003c");
436
704
  }
437
705
  function renderInspectorShell(options) {
438
- const { serverName, basePath, assetsUrl, manufactChatUrl } = options;
706
+ const { serverName, basePath, faviconHref, assetsUrl, manufactChatUrl } = options;
439
707
  const serializedBasePath = serializeForInlineScript(basePath);
440
708
  const serializedManufactChatUrl = manufactChatUrl ? serializeForInlineScript(manufactChatUrl) : null;
441
709
  const rawUrl = assetsUrl ?? DEFAULT_INSPECTOR_ASSETS_URL;
@@ -448,6 +716,7 @@ function renderInspectorShell(options) {
448
716
  <meta charset="utf-8" />
449
717
  <meta name="viewport" content="width=device-width, initial-scale=1" />
450
718
  <title>${escapeHtml(serverName)} \u2014 MCP Inspector</title>
719
+ ${faviconHref !== void 0 ? `<link rel="icon" href="${escapeHtml(faviconHref)}" />` : ""}
451
720
  <link rel="preconnect" href="https://fonts.googleapis.com" />
452
721
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
453
722
  <link
@@ -508,6 +777,9 @@ function createInspectorHandler(inspector, options) {
508
777
  const shellOptions = {
509
778
  serverName: options.serverName,
510
779
  basePath: options.basePath,
780
+ ...options.faviconHref !== void 0 && {
781
+ faviconHref: options.faviconHref
782
+ },
511
783
  assetsUrl,
512
784
  manufactChatUrl
513
785
  };
@@ -1043,20 +1315,20 @@ function createViewAssetsHandler(basePath, views, options) {
1043
1315
  if (entry === void 0 || entry.kind !== "external") {
1044
1316
  return new Response("Not Found", { status: 404 });
1045
1317
  }
1046
- const [{ join }, { resolvePublicFilePath, servePublicFile }] = await Promise.all([import("path"), import("./public-route-26FUVRO5.js")]);
1318
+ const [{ join }, { resolvePublicFilePath: resolvePublicFilePath2, servePublicFile: servePublicFile2 }] = await Promise.all([import("path"), import("./public-route-5JEGFEIN.js")]);
1047
1319
  const viewRoot = join(projectRoot, VIEW_ASSETS_BUILD_ROOT, viewName);
1048
- const diskPath = await resolvePublicFilePath(viewRoot, subpath);
1320
+ const diskPath = await resolvePublicFilePath2(viewRoot, subpath);
1049
1321
  if (diskPath === null) {
1050
1322
  return new Response("Not Found", { status: 404 });
1051
1323
  }
1052
- return await servePublicFile(
1053
- diskPath,
1054
- options?.deferCors === true ? { deferCors: true } : {}
1055
- );
1324
+ return await servePublicFile2(diskPath, {
1325
+ ...options?.deferCors === true && { deferCors: true },
1326
+ ...request.method === "HEAD" && { head: true }
1327
+ });
1056
1328
  };
1057
1329
  }
1058
1330
  function createViewPublicHandler(basePath, views, options) {
1059
- if (views.size === 0) {
1331
+ if (views.size === 0 && options?.enabled !== true) {
1060
1332
  return void 0;
1061
1333
  }
1062
1334
  const publicPrefix = pathUnderBase(basePath, "_mcp-use/public");
@@ -1070,20 +1342,26 @@ function createViewPublicHandler(basePath, views, options) {
1070
1342
  return new Response("Not Found", { status: 404 });
1071
1343
  }
1072
1344
  const pathname = pathnameOf(request);
1073
- const subpath = pathname.slice(publicPrefix.length + 1);
1345
+ const encodedSubpath = pathname.slice(publicPrefix.length + 1);
1346
+ let subpath;
1347
+ try {
1348
+ subpath = decodeURIComponent(encodedSubpath);
1349
+ } catch {
1350
+ return new Response("Not Found", { status: 404 });
1351
+ }
1074
1352
  if (subpath.length === 0) {
1075
1353
  return new Response("Not Found", { status: 404 });
1076
1354
  }
1077
- const [{ join }, { resolvePublicFilePath, servePublicFile }] = await Promise.all([import("path"), import("./public-route-26FUVRO5.js")]);
1355
+ const [{ join }, { resolvePublicFilePath: resolvePublicFilePath2, servePublicFile: servePublicFile2 }] = await Promise.all([import("path"), import("./public-route-5JEGFEIN.js")]);
1078
1356
  const publicRoot = join(projectRoot, subdir);
1079
- const diskPath = await resolvePublicFilePath(publicRoot, subpath);
1357
+ const diskPath = await resolvePublicFilePath2(publicRoot, subpath);
1080
1358
  if (diskPath === null) {
1081
1359
  return new Response("Not Found", { status: 404 });
1082
1360
  }
1083
- return await servePublicFile(
1084
- diskPath,
1085
- options?.deferCors === true ? { deferCors: true } : {}
1086
- );
1361
+ return await servePublicFile2(diskPath, {
1362
+ ...options?.deferCors === true && { deferCors: true },
1363
+ ...request.method === "HEAD" && { head: true }
1364
+ });
1087
1365
  };
1088
1366
  }
1089
1367
 
@@ -1159,6 +1437,7 @@ function viewResourceConfig(_viewName, _entry, authorFacts, options) {
1159
1437
  // src/server.ts
1160
1438
  var MCPServer = class _MCPServer {
1161
1439
  #config;
1440
+ #branding;
1162
1441
  #tools = /* @__PURE__ */ new Map();
1163
1442
  #resources = /* @__PURE__ */ new Map();
1164
1443
  #resourceTemplates = /* @__PURE__ */ new Map();
@@ -1224,6 +1503,7 @@ var MCPServer = class _MCPServer {
1224
1503
  constructor(config) {
1225
1504
  assertServerConfig(config);
1226
1505
  this.#config = config;
1506
+ this.#branding = normalizeServerBranding(config);
1227
1507
  if (config.oauth !== void 0) {
1228
1508
  const mcpUrl = typeof process === "undefined" ? void 0 : process.env["MCP_URL"];
1229
1509
  const resource = resolveConfiguredOAuthResource({
@@ -1246,6 +1526,24 @@ var MCPServer = class _MCPServer {
1246
1526
  get basePath() {
1247
1527
  return this.#basePath();
1248
1528
  }
1529
+ /**
1530
+ * Immutable normalized branding shared by MCP identity and browser pages.
1531
+ *
1532
+ * `favicon` is the final source after explicit-favicon and icon-selection
1533
+ * precedence. Landing-page integrations can use this accessor and link to
1534
+ * the server's root-level `/favicon.ico` route without reading private
1535
+ * configuration or depending on the inspector/view layers.
1536
+ *
1537
+ * @example
1538
+ * ```ts
1539
+ * if (server.branding.favicon) {
1540
+ * console.log("Browser favicon: /favicon.ico");
1541
+ * }
1542
+ * ```
1543
+ */
1544
+ get branding() {
1545
+ return this.#branding;
1546
+ }
1249
1547
  /**
1250
1548
  * Register a tool. Input is validated against `inputSchema` before the callback
1251
1549
  * runs; results carrying `structuredContent` are type-checked against
@@ -1325,8 +1623,10 @@ var MCPServer = class _MCPServer {
1325
1623
  */
1326
1624
  resourceTemplate(definition, callback) {
1327
1625
  this.#assertNotStarted("resourceTemplate", definition.name);
1626
+ const complete = definition.complete === void 0 ? void 0 : normalizeCompletions(definition.complete);
1328
1627
  this.#resourceTemplates.set(definition.name, {
1329
1628
  definition,
1629
+ ...complete !== void 0 && { complete },
1330
1630
  callback
1331
1631
  });
1332
1632
  return this;
@@ -1714,11 +2014,12 @@ var MCPServer = class _MCPServer {
1714
2014
  return mcpRouteHandler(request);
1715
2015
  }
1716
2016
  const respond = async () => {
1717
- const { createLandingPageResponse } = await import("./landing-handler-VQRYCQOV.js");
2017
+ const { createLandingPageResponse } = await import("./landing-handler-3VN4BMR2.js");
1718
2018
  return createLandingPageResponse(
1719
2019
  request,
1720
2020
  basePath,
1721
2021
  this.#config,
2022
+ this.#branding,
1722
2023
  this.#tools.values(),
1723
2024
  this.#prompts.values(),
1724
2025
  this.#resources.values()
@@ -1730,9 +2031,22 @@ var MCPServer = class _MCPServer {
1730
2031
  return respond();
1731
2032
  };
1732
2033
  const routes = [];
2034
+ const brandingDevMode = this.#viewsPrimed ? this.#viewsDevMode : process.env["NODE_ENV"] !== "production";
2035
+ const faviconHandler = createFaviconHandler(this.#branding, {
2036
+ dev: brandingDevMode,
2037
+ projectRoot: this.#viewsProjectRoot,
2038
+ deferCors: deferViewCors
2039
+ });
2040
+ if (faviconHandler !== void 0) {
2041
+ routes.push({
2042
+ match: (request) => new URL(request.url).pathname === "/favicon.ico",
2043
+ handler: faviconHandler
2044
+ });
2045
+ }
1733
2046
  const viewHandler = createViewPublicHandler(basePath, this.#views, {
1734
- dev: this.#viewsDevMode,
2047
+ dev: this.#viewsPrimed ? this.#viewsDevMode : brandingDevMode,
1735
2048
  projectRoot: this.#viewsProjectRoot,
2049
+ enabled: hasLocalBrandingAsset(this.#branding),
1736
2050
  deferCors: deferViewCors
1737
2051
  });
1738
2052
  if (viewHandler !== void 0) {
@@ -1760,7 +2074,8 @@ var MCPServer = class _MCPServer {
1760
2074
  }
1761
2075
  const inspectorHandler = createInspectorHandler(this.#config.inspector, {
1762
2076
  serverName: this.#config.name,
1763
- basePath
2077
+ basePath,
2078
+ ...faviconHandler !== void 0 && { faviconHref: "/favicon.ico" }
1764
2079
  });
1765
2080
  if (inspectorHandler !== void 0) {
1766
2081
  routes.push({
@@ -1849,7 +2164,17 @@ var MCPServer = class _MCPServer {
1849
2164
  name,
1850
2165
  version,
1851
2166
  ...title !== void 0 && { title },
1852
- ...description !== void 0 && { description }
2167
+ ...description !== void 0 && { description },
2168
+ ...this.#branding.websiteUrl !== void 0 && {
2169
+ websiteUrl: this.#branding.websiteUrl
2170
+ },
2171
+ ...this.#branding.icons !== void 0 && {
2172
+ icons: resolveImplementationIcons(
2173
+ this.#branding.icons,
2174
+ ctx.requestInfo,
2175
+ this.#basePath()
2176
+ )
2177
+ }
1853
2178
  },
1854
2179
  {
1855
2180
  capabilities: {
@@ -2086,9 +2411,10 @@ var MCPServer = class _MCPServer {
2086
2411
  }
2087
2412
  );
2088
2413
  }
2089
- #registerResourceTemplate(server, { definition, callback }) {
2414
+ #registerResourceTemplate(server, { definition, callback, complete }) {
2090
2415
  const template = new ResourceTemplate(definition.uriTemplate, {
2091
- list: void 0
2416
+ list: void 0,
2417
+ ...complete !== void 0 && { complete }
2092
2418
  });
2093
2419
  server.registerResource(
2094
2420
  definition.name,
@@ -2195,24 +2521,6 @@ import {
2195
2521
  inputResponse as inputResponse2,
2196
2522
  isInputRequiredResult as isInputRequiredResult2
2197
2523
  } from "@modelcontextprotocol/server";
2198
-
2199
- // src/completable.ts
2200
- import {
2201
- completable as sdkCompletable
2202
- } from "@modelcontextprotocol/server";
2203
- function completable(schema, complete) {
2204
- if (typeof complete === "function") {
2205
- return sdkCompletable(
2206
- schema,
2207
- (value, context) => complete(String(value ?? ""), context)
2208
- );
2209
- }
2210
- const values = complete.map(String);
2211
- return sdkCompletable(schema, (value) => {
2212
- const prefix = String(value ?? "").toLowerCase();
2213
- return values.filter((v) => v.toLowerCase().startsWith(prefix));
2214
- });
2215
- }
2216
2524
  export {
2217
2525
  MCPServer,
2218
2526
  acceptedContent,