mcp-use 2.0.0-beta.63 → 2.0.0-beta.64
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/dist/bin.js +1 -1
- package/dist/{chunk-VJ4S2BU7.js → chunk-JTOR5V7S.js} +1 -1
- package/dist/context.d.ts +7 -0
- package/dist/index-node.js +14 -12
- package/dist/index.d.ts +10 -7
- package/dist/index.js +1 -1
- package/dist/internal/usage.js +1 -1
- package/dist/landing.d.ts +17 -4
- package/dist/middleware/mcp-middleware.d.ts +18 -0
- package/dist/next/config.d.ts +33 -4
- package/dist/next/handler.d.ts +16 -0
- package/dist/next/index.d.ts +5 -0
- package/dist/node-bridge.d.ts +33 -4
- package/dist/oauth/auth0.d.ts +24 -0
- package/dist/oauth/better-auth.d.ts +23 -0
- package/dist/oauth/clerk.d.ts +26 -0
- package/dist/oauth/keycloak.d.ts +28 -0
- package/dist/oauth/provider.d.ts +17 -1
- package/dist/oauth/supabase.d.ts +36 -1
- package/dist/oauth/workos.d.ts +27 -0
- package/dist/react/components/error-boundary.d.ts +3 -0
- package/dist/react/components/theme-provider.d.ts +4 -3
- package/dist/react/hooks/use-view-tool.d.ts +3 -3
- package/dist/react/index.d.ts +5 -6
- package/dist/react/index.js +2 -0
- package/dist/react/runtime/bootstrap-view.d.ts +3 -3
- package/dist/react/types/file-types.d.ts +2 -0
- package/dist/react/types/host-types.d.ts +2 -0
- package/dist/response-helpers.d.ts +8 -0
- package/dist/server.d.ts +2 -0
- package/dist/views/types.d.ts +3 -3
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Build stateless MCP servers with a Hono application and a Web-standard
|
|
3
|
+
* Fetch serving boundary.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* 2026-07-28 MCP protocol. See specs/SPEC.md for the phase plan and API contract.
|
|
5
|
+
* @packageDocumentation
|
|
7
6
|
*/
|
|
8
7
|
export { MCPServer } from "./server.js";
|
|
9
8
|
export type { ListenOptions } from "./server.js";
|
|
@@ -59,9 +58,13 @@ export type { ExternalViewManifestEntry, InlineViewManifestEntry, UiPermissions,
|
|
|
59
58
|
export type { InferTemplateParams, ResourceCallback, ResourceDefinition, ResourceTemplateCallback, ResourceTemplateCompleter, ResourceTemplateCompletions, ResourceTemplateDefinition, TemplateVariableValue, } from "./resources.js";
|
|
60
59
|
export type { InferPromptInput, PromptCallback, PromptDefinition, } from "./prompts.js";
|
|
61
60
|
/**
|
|
62
|
-
* @deprecated Prefer raw
|
|
63
|
-
*
|
|
64
|
-
*
|
|
61
|
+
* @deprecated Prefer raw
|
|
62
|
+
* [CallToolResult](https://ts.sdk.modelcontextprotocol.io/types/types.CallToolResult.html),
|
|
63
|
+
* [ReadResourceResult](https://ts.sdk.modelcontextprotocol.io/types/types.ReadResourceResult.html),
|
|
64
|
+
* or
|
|
65
|
+
* [GetPromptResult](https://ts.sdk.modelcontextprotocol.io/types/types.GetPromptResult.html)
|
|
66
|
+
* returns. These helpers remain for upgrade compatibility and map to the
|
|
67
|
+
* official wire envelopes.
|
|
65
68
|
*/
|
|
66
69
|
export { array, audio, binary, css, error, html, image, javascript, markdown, mix, object, resource, text, widget, xml, } from "./response-helpers.js";
|
|
67
70
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{resolvePublicFilePath,servePublicFile}from"./chunk-ZMU5USAZ.js";import{hasExplicitAssetsBase,originFromAssetsBase,resolveAssetsBase,resolveServerOrigin}from"./chunk-PSKSL567.js";import{registerOpenAPITools}from"./chunk-Y26DNVWA.js";import{completable,normalizeCompletions}from"./chunk-OJF6B5EU.js";import{isUsageDisabled,recordUsage}from"./chunk-VJ4S2BU7.js";import{inheritBufferedResponse,toNodeHandler,trackBufferedResponse}from"./chunk-XYHHP43G.js";import{authInfoFromRequest,composeFetch,getOAuthProtectedResourceMetadataUrl,getRequestBag,hostValidationMiddleware,isHtmlNavigationRequest,jsonBodyMiddleware,matchesPath,matchesPathPrefix,oauthMetadata,originValidationMiddleware,pathUnderBase,pathnameOf,requireBearerAuth}from"./chunk-MIZQEWZS.js";import{getOAuthProviderOptions,resolveConfiguredOAuthResource,resolveLocalOAuthResource,wrapOAuthTokenVerifier}from"./chunk-IS7FKXFR.js";import{localhostAllowedHostnames,localhostAllowedOrigins,McpServer as SdkMcpServer,ResourceTemplate,CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY3,CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY3,PROTOCOL_VERSION_META_KEY,isJSONRPCRequest as isJSONRPCRequest2,isInputRequiredResult as isInputRequiredResult2}from"@modelcontextprotocol/server";import{createServer as createNodeHttpServer}from"#mcp-use-node-http";import{Hono}from"hono";var FAVICON_CACHE_CONTROL="public, max-age=31536000, immutable",FAVICON_REDIRECT_CACHE_CONTROL="public, max-age=300";function protocolOf(value){return/^([a-z][a-z\d+.-]*):/i.exec(value)?.[1]?.toLowerCase()}function publicAssetPath(basePath,source){return`${basePath==="/"?"":basePath}/_mcp-use/public/${source.split("/").map(segment=>encodeURIComponent(segment)).join("/")}`}function isLocalPublicSource(source){return protocolOf(source)===void 0}function selectFaviconFromIcons(icons){return icons[0]}function assertLocalPublicSource(source,field){if(source.startsWith("/")||source.includes("\\")||source.includes("?")||source.includes("#")||source.split("/").some(segment=>segment===""||segment===".."))throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`)}function parseDataImage(source,field){let comma=source.indexOf(",");if(comma<0)throw new TypeError(`${field} must be a valid image data URL`);let metadata=source.slice(5,comma),payload=source.slice(comma+1),parts=metadata.split(";"),mimeType=parts[0]?.toLowerCase()??"";if(!mimeType.startsWith("image/"))throw new TypeError(`${field} data URL must use an image MIME type`);try{if(parts.includes("base64")){let binary2=atob(payload);return{mimeType,bytes:Uint8Array.from(binary2,character=>character.charCodeAt(0))}}return{mimeType,bytes:new TextEncoder().encode(decodeURIComponent(payload))}}catch{throw new TypeError(`${field} must be a valid image data URL`)}}function assertBrandingSource(source,field){if(typeof source!="string"||source.length===0)throw new TypeError(`${field} must be a non-empty string`);let protocol=protocolOf(source);if(protocol===void 0)return assertLocalPublicSource(source,field),source;if(protocol==="data")return parseDataImage(source,field),source;if(protocol!=="http"&&protocol!=="https")throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`);try{new URL(source)}catch{throw new TypeError(`${field} must be a valid absolute http(s) URL`)}return source}function normalizeServerBranding(config){let websiteUrl;if(config.websiteUrl!==void 0){if(typeof config.websiteUrl!="string"||config.websiteUrl.length===0)throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");let parsed;try{parsed=new URL(config.websiteUrl)}catch{throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:")throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");websiteUrl=config.websiteUrl}let icons;if(config.icons!==void 0){if(!Array.isArray(config.icons))throw new TypeError("icons must be an array of MCP Icon objects");icons=Object.freeze(config.icons.map((value,index)=>{if(typeof value!="object"||value===null)throw new TypeError(`icons[${index}] must be an MCP Icon object`);let icon=value,src=assertBrandingSource(icon.src,`icons[${index}].src`),mimeType=icon.mimeType;if(mimeType!==void 0&&(typeof mimeType!="string"||!mimeType.toLowerCase().startsWith("image/")))throw new TypeError(`icons[${index}].mimeType must be an image MIME type when provided`);let sizes=icon.sizes;if(sizes!==void 0&&(!Array.isArray(sizes)||sizes.some(size=>typeof size!="string"||size.length===0)))throw new TypeError(`icons[${index}].sizes must be an array of non-empty strings when provided`);let normalizedSizes=sizes===void 0?void 0:sizes.map(size=>size),theme=icon.theme;if(theme!==void 0&&theme!=="light"&&theme!=="dark")throw new TypeError(`icons[${index}].theme must be "light" or "dark" when provided`);return Object.freeze({src,...mimeType!==void 0&&{mimeType},...normalizedSizes!==void 0&&{sizes:Object.freeze(normalizedSizes)},...theme!==void 0&&{theme}})}))}let explicitFavicon=config.favicon===void 0?void 0:assertBrandingSource(config.favicon,"favicon"),inferred=explicitFavicon===void 0?selectFaviconFromIcons(icons??[]):void 0,favicon=explicitFavicon??inferred?.src,faviconMimeType=inferred?.mimeType??icons?.find(icon=>icon.src===explicitFavicon)?.mimeType;return Object.freeze({...favicon!==void 0&&{favicon},...faviconMimeType!==void 0&&{faviconMimeType},...icons!==void 0&&{icons},...websiteUrl!==void 0&&{websiteUrl}})}function resolveImplementationIcons(icons,request,basePath){if(icons!==void 0)return icons.map(icon=>({...icon,src:request!==void 0&&isLocalPublicSource(icon.src)?`${resolveAssetsBase(request)}${publicAssetPath(basePath,icon.src)}`:icon.src,...icon.sizes!==void 0&&{sizes:[...icon.sizes]}}))}function hasLocalBrandingAsset(branding){return branding.favicon!==void 0&&isLocalPublicSource(branding.favicon)||branding.icons?.some(icon=>isLocalPublicSource(icon.src))===!0}function createFaviconHandler(branding,options){let source=branding.favicon;if(source!==void 0)return async request=>{if(request.method!=="GET"&&request.method!=="HEAD")return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, HEAD"}});if(new URL(request.url).pathname!=="/favicon.ico")return new Response("Not Found",{status:404});let protocol=protocolOf(source);if(protocol==="http"||protocol==="https")return new Response(null,{status:307,headers:{Location:source,"Cache-Control":FAVICON_REDIRECT_CACHE_CONTROL}});if(protocol==="data"){let data=parseDataImage(source,"favicon");return new Response(request.method==="HEAD"?null:data.bytes.buffer,{status:200,headers:{"Content-Type":branding.faviconMimeType??data.mimeType,"Cache-Control":FAVICON_CACHE_CONTROL,"X-Content-Type-Options":"nosniff"}})}let{join}=await import("path"),publicRoot=options.dev?join(options.projectRoot,"public"):join(options.projectRoot,".mcp-use/build/views/public"),diskPath=await resolvePublicFilePath(publicRoot,source);if(diskPath===null)return new Response("Not Found",{status:404,headers:{"Cache-Control":"no-store"}});let response=await servePublicFile(diskPath,{...options.deferCors===!0&&{deferCors:!0},...request.method==="HEAD"&&{head:!0}});return response.headers.set("Cache-Control",FAVICON_CACHE_CONTROL),response.headers.set("X-Content-Type-Options","nosniff"),branding.faviconMimeType!==void 0&&response.headers.set("Content-Type",branding.faviconMimeType),response}}function assertServerConfig(config){if(config.basePath!==void 0){if(typeof config.basePath!="string")throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace");let{basePath}=config;if(!basePath.startsWith("/")||basePath.includes("?")||basePath.includes("#")||/\s/.test(basePath)||basePath.includes("//")||basePath.length>1&&basePath.endsWith("/"))throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace")}if(config.port!==void 0&&(typeof config.port!="number"||!Number.isInteger(config.port)||config.port<0||config.port>65535))throw new TypeError("port must be an integer between 0 and 65535")}var DEFAULT_LISTEN_HOST="127.0.0.1";function resolveListenHost(explicitHost,configuredHost,env=process.env){if(explicitHost!==void 0)return explicitHost;let envHost=env.HOST?.trim();return envHost!==void 0&&envHost!==""?envHost:configuredHost??DEFAULT_LISTEN_HOST}function resolveListenPort(explicitPort,configuredPort,env=process.env){if(explicitPort!==void 0)return explicitPort;let envPort=parsePort(env.PORT);return envPort!==void 0?envPort:configuredPort??3e3}function parsePort(value){if(value===void 0||value.trim()==="")return;let port=Number(value);return Number.isInteger(port)&&port>=0&&port<=65535?port:void 0}import{CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY2,CLIENT_INFO_META_KEY,inputRequired,inputResponse}from"@modelcontextprotocol/server";import{HonoRequest}from"hono/request";import{CLIENT_CAPABILITIES_META_KEY}from"@modelcontextprotocol/server";var UI_EXTENSION_ID="io.modelcontextprotocol/ui",UI_MIME_TYPE="text/html;profile=mcp-app",UI_RESOURCE_URI_PREFIX="ui://views/";var UI_RESOURCE_URI_META_KEY="ui/resourceUri";function viewResourceUri(viewName){return`${UI_RESOURCE_URI_PREFIX}${viewName}.html`}var clientCapabilitiesByRequest=new WeakMap;function stashClientCapabilities(request,capabilities){clientCapabilitiesByRequest.set(request,capabilities)}function extractClientCapabilitiesFromBody(body){if(typeof body!="object"||body===null)return;let params=body.params;if(typeof params!="object"||params===null)return;let meta=params._meta;if(typeof meta!="object"||meta===null)return;let capabilities=meta[CLIENT_CAPABILITIES_META_KEY];if(!(typeof capabilities!="object"||capabilities===null))return capabilities}function supportsViews(capabilities){let extensions=capabilities?.extensions;if(extensions===void 0)return!1;let uiExtension=extensions[UI_EXTENSION_ID];if(typeof uiExtension!="object"||uiExtension===null)return!1;let mimeTypes=uiExtension.mimeTypes;return Array.isArray(mimeTypes)?mimeTypes.includes(UI_MIME_TYPE):!1}function requireOAuthAuthInfo(authInfo){if(authInfo===void 0||authInfo.extra===void 0||authInfo.expiresAt===void 0)throw new Error("OAuth callback did not receive mapped AuthInfo.extra")}function stringValue(value){return typeof value=="string"?value:void 0}function coordinateValue(value){return typeof value=="string"||typeof value=="number"&&Number.isFinite(value)?value:void 0}function normalizeUserContext(meta){if(meta===void 0)return;let locale=stringValue(meta["openai/locale"])??stringValue(meta["webplus/i18n"]),userAgent=stringValue(meta["openai/userAgent"]),subject=stringValue(meta["openai/subject"]),conversationId=stringValue(meta["openai/session"]),organizationId=stringValue(meta["openai/organization"]),rawLocation=meta["openai/userLocation"],location;if(typeof rawLocation=="object"&&rawLocation!==null&&!Array.isArray(rawLocation)){let values=rawLocation,normalized={city:stringValue(values.city),region:stringValue(values.region),country:stringValue(values.country),timezone:stringValue(values.timezone),latitude:coordinateValue(values.latitude),longitude:coordinateValue(values.longitude)},entries=Object.entries(normalized).filter(entry=>entry[1]!==void 0);entries.length>0&&(location=Object.fromEntries(entries))}if(!(locale===void 0&&userAgent===void 0&&location===void 0&&subject===void 0&&conversationId===void 0&&organizationId===void 0))return{...locale!==void 0&&{locale},...userAgent!==void 0&&{userAgent},...location!==void 0&&{location},...subject!==void 0&&{subject},...conversationId!==void 0&&{conversationId},...organizationId!==void 0&&{organizationId}}}function toClientContext(ctx){let envelope=ctx.mcpReq.envelope,capabilities={...envelope?.[CLIENT_CAPABILITIES_META_KEY2]??{}},info={...envelope?.[CLIENT_INFO_META_KEY]??{}},user=normalizeUserContext(ctx.mcpReq._meta);return{can(capability){return Object.hasOwn(capabilities,capability)},capabilities(){return{...capabilities}},extension(id){let settings=capabilities.extensions?.[id];return settings===void 0?void 0:{...settings}},info(){return{...info}},user(){return user===void 0?void 0:{...user,...user.location!==void 0&&{location:{...user.location}}}},supportsViews(){return supportsViews(capabilities)}}}function createElicit(inputResponses){return async function(key,message,schemaOrUrl){let request,formSchema;if(typeof schemaOrUrl=="string")request=inputRequired.elicitUrl({message,url:schemaOrUrl});else if(schemaOrUrl!==void 0)formSchema=schemaOrUrl,request=inputRequired.elicit({message,requestedSchema:schemaOrUrl});else throw new TypeError("ctx.elicit(key, message, value) requires a form schema or URL string");let response=inputResponse(inputResponses,key);if(response.kind==="elicit"){if(response.action!=="accept")return{status:response.action};if(formSchema===void 0)return{status:"accept"};if(response.content!==void 0){let outcome=await formSchema["~standard"].validate(response.content);if(outcome.issues===void 0)return{status:"accept",data:outcome.value}}}return{status:"required",result:inputRequired({inputRequests:{[key]:request}})}}}function toRequestContext(ctx){let rawRequest=ctx.http?.req,http=rawRequest===void 0?void 0:getRequestBag(rawRequest).honoContext,request=http?.req??(rawRequest===void 0?void 0:new HonoRequest(rawRequest)),additions={signal:ctx.mcpReq.signal,...request!==void 0&&{request},...ctx.mcpReq.inputResponses!==void 0&&{inputResponses:ctx.mcpReq.inputResponses},client:toClientContext(ctx),elicit:createElicit(ctx.mcpReq.inputResponses),requestState:()=>ctx.mcpReq.requestState(),async sendNotification(method,params){await ctx.mcpReq.notify({method,...params!==void 0&&{params}})},async reportProgress(progress,total,message){let progressToken=ctx.mcpReq._meta?.progressToken;return progressToken===void 0?!1:(await ctx.mcpReq.notify({method:"notifications/progress",params:{progressToken,progress,...total!==void 0&&{total},...message!==void 0&&{message}}}),!0)},async sendLog(level,data,logger){await ctx.mcpReq.notify({method:"notifications/message",params:{level,data,...logger!==void 0&&{logger}}})}};return http!==void 0?Object.assign(http,additions):{...additions,...request!==void 0&&{req:request}}}function toAuthenticatedRequestContext(ctx){let authInfo=ctx.http?.authInfo;return requireOAuthAuthInfo(authInfo),Object.assign(toRequestContext(ctx),{auth:{user:authInfo.extra.user,payload:authInfo.extra.payload,accessToken:authInfo.token,scopes:[...authInfo.scopes],permissions:[...authInfo.extra.permissions],...authInfo.clientId.length>0&&{clientId:authInfo.clientId},expiresAt:authInfo.expiresAt,...authInfo.resource!==void 0&&{resource:authInfo.resource}}})}function isReadResourceResult(result){return"contents"in result&&Array.isArray(result.contents)}function isGetPromptResult(result){return"messages"in result&&Array.isArray(result.messages)}function toResourceResult(result,uri){if(isReadResourceResult(result))return result;let mime=result._meta&&typeof result._meta=="object"&&typeof result._meta.mimeType=="string"?result._meta.mimeType:void 0,contents=[];for(let block of result.content??[]){let mapped=contentBlockToResourceContents(block,uri,mime);mapped!==void 0&&contents.push(mapped)}return contents.length===0&&result.structuredContent!==void 0&&contents.push({uri,mimeType:"application/json",text:JSON.stringify(result.structuredContent)}),contents.length===0&&contents.push({uri,mimeType:"text/plain",text:""}),{contents}}function contentBlockToResourceContents(block,uri,mimeHint){if(block.type==="text")return{uri,mimeType:mimeHint??"text/plain",text:block.text};if(block.type==="image"||block.type==="audio")return{uri,mimeType:block.mimeType,blob:block.data};if(block.type==="resource")return{...block.resource}}function toPromptResult(result){if(isGetPromptResult(result))return result;let messages=(result.content??[]).map(content=>({role:"user",content}));return messages.length===0&&result.structuredContent!==void 0&&messages.push({role:"user",content:{type:"text",text:JSON.stringify(result.structuredContent)}}),messages.length===0&&messages.push({role:"user",content:{type:"text",text:""}}),{messages}}var DEFAULT_METHODS=["GET","HEAD","POST","OPTIONS"],DEFAULT_ALLOWED_HEADERS=["Content-Type","Authorization","mcp-protocol-version","mcp-method","mcp-name"];function resolveAllowedOrigin(origin,requestOrigin){return origin===void 0?requestOrigin:typeof origin=="function"?origin(requestOrigin):origin==="*"?"*":Array.isArray(origin)?requestOrigin!==null&&origin.includes(requestOrigin)?requestOrigin:null:origin}function corsHeaders(options,request){if(request.headers.has("Access-Control-Allow-Origin"))return;let requestOrigin=request.headers.get("Origin"),allowedOrigin=resolveAllowedOrigin(options.origin,requestOrigin);if(allowedOrigin===null)return;let headers={"Access-Control-Allow-Origin":allowedOrigin,"Access-Control-Allow-Methods":options.methods.join(", "),"Access-Control-Allow-Headers":options.allowedHeaders.join(", ")};return options.credentials&&(headers["Access-Control-Allow-Credentials"]="true"),allowedOrigin!=="*"&&(headers.Vary="Origin"),headers}function mergeCorsHeaders(response,headers){if(response.headers.has("Access-Control-Allow-Origin"))return response;let merged=new Headers(response.headers);return new Headers(headers).forEach((value,key)=>{merged.set(key,value)}),inheritBufferedResponse(response,new Response(response.body,{status:response.status,statusText:response.statusText,headers:merged}))}function corsFetchMiddleware(options){if(!(options.enabled!==!1))return async(_request,next)=>next();let resolved={...options.origin!==void 0&&{origin:options.origin},methods:options.methods??DEFAULT_METHODS,allowedHeaders:options.allowedHeaders??DEFAULT_ALLOWED_HEADERS,credentials:options.credentials??!1};return async(request,next)=>{let headers=corsHeaders(resolved,request);if(headers===void 0)return next();if(request.method==="OPTIONS")return new Response(null,{status:204,headers});let response=await next();return mergeCorsHeaders(response,headers)}}function isGlobalCorsEnabled(cors){return cors!==void 0&&cors.enabled!==!1}import{CallToolResultSchema,GetPromptResultSchema,ListPromptsResultSchema,ListResourcesResultSchema,ListToolsResultSchema,ReadResourceResultSchema}from"@modelcontextprotocol/core";import{isInputRequiredResult}from"@modelcontextprotocol/server";var MCP_MIDDLEWARE_METHODS=["tools/call","tools/list","resources/read","resources/list","prompts/get","prompts/list"];function withMcpMiddlewareParams(request,params){if(typeof request!="object"||request===null||Array.isArray(request))throw new TypeError("[mcp-use] MCP middleware received an invalid downstream request");return{...request,params}}function createMcpMiddlewareEntry(pattern,handler){let normalizedPattern=normalizeMcpMiddlewarePattern(pattern),invoke=handler;if(normalizedPattern!=="*"&&!isMcpMiddlewareMethod(normalizedPattern))throw new TypeError(`Unsupported MCP middleware pattern "${pattern}". Use an exact MCP method or "mcp:*".`);return normalizedPattern==="*"?{pattern:normalizedPattern,handler:async(ctx,next)=>{let downstreamCalled=!1,downstreamResult;if(await invoke(ctx,async()=>{downstreamResult=await next(),downstreamCalled=!0}),!downstreamCalled)throw new Error(`Wildcard MCP middleware "${normalizedPattern}" must call next()`);return downstreamResult}}:{pattern:normalizedPattern,handler:(ctx,next)=>invoke(ctx,next)}}function createMcpEventListenerEntry(pattern,handler){let{pattern:normalizedPattern,phase}=parseMcpPattern(pattern),invoke=handler;return{pattern:normalizedPattern,phase,handler:(ctx,result)=>invoke(ctx,result)}}function matchesPattern(pattern,method){if(pattern==="*")return!0;if(pattern.endsWith("/*")){let prefix=pattern.slice(0,-1);return method.startsWith(prefix)}return pattern===method}function isMcpMiddlewareMethod(value){return MCP_MIDDLEWARE_METHODS.some(method=>method===value)}function composeMiddleware(entries,method,innerFn){let matching=entries.filter(entry=>matchesPattern(entry.pattern,method));return matching.length===0?_ctx=>innerFn():ctx=>{let index=-1,dispatch=i=>i<=index?Promise.reject(new Error("next() called multiple times")):(index=i,i===matching.length?innerFn():matching[i].handler(ctx,()=>dispatch(i+1)));return dispatch(0)}}function freezeMiddlewareContext(ctx){return Object.freeze({method:ctx.method,params:Object.freeze({...ctx.params}),...ctx.request!==void 0&&{request:ctx.request},...ctx.req!==void 0&&{req:ctx.req},...ctx.session!==void 0&&{session:Object.freeze({...ctx.session})},...ctx.auth!==void 0&&{auth:ctx.auth},state:new Map(ctx.state)})}async function runMcpOperation(middlewares,events,method,ctx,innerFn){dispatchMcpEvents(events,method,"before",ctx);let result=await composeMiddleware(middlewares,method,innerFn)(ctx);return assertValidMiddlewareResult(method,result),dispatchMcpEvents(events,method,"complete",ctx,result),result}function assertValidMiddlewareResult(method,result){if((method==="tools/call"||method==="resources/read"||method==="prompts/get")&&isInputRequiredResult(result))return;let validation=(()=>{switch(method){case"tools/call":return assertArrayProperty(method,result,"content"),CallToolResultSchema.safeParse(result);case"tools/list":return assertArrayResult(method,result),ListToolsResultSchema.safeParse({tools:result});case"resources/read":return assertArrayProperty(method,result,"contents"),ReadResourceResultSchema.safeParse(result);case"resources/list":return assertArrayResult(method,result),ListResourcesResultSchema.safeParse({resources:result});case"prompts/get":return assertArrayProperty(method,result,"messages"),GetPromptResultSchema.safeParse(result);case"prompts/list":return assertArrayResult(method,result),ListPromptsResultSchema.safeParse({prompts:result});default:throw new TypeError(`Unsupported MCP middleware method "${method}"`)}})();if(!validation.success)throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: ${validation.error.message}`)}function assertArrayResult(method,result){if(!Array.isArray(result))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected an array`)}function assertArrayProperty(method,result,property){if(typeof result!="object"||result===null||!Array.isArray(result[property]))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected a ${property} array`)}function dispatchMcpEvents(events,method,phase,ctx,result){let frozen=freezeMiddlewareContext(ctx);for(let entry of events)if(!(entry.phase!==phase||!matchesPattern(entry.pattern,method)))try{entry.handler(frozen,result)}catch(error2){console.error(`[mcp-use] MCP event listener for "${entry.pattern}" (${phase}) threw:`,error2)}}function parseMcpPattern(raw){let pattern=raw.startsWith("mcp:")?raw.slice(4):raw;return pattern.endsWith(":complete")?{pattern:pattern.slice(0,-9),phase:"complete"}:{pattern,phase:"before"}}function normalizeMcpMiddlewarePattern(raw){return raw.startsWith("mcp:")?raw.slice(4):raw}import{CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY2,isJSONRPCRequest}from"@modelcontextprotocol/server";function colorsEnabled(){return typeof process>"u"||process.env?.NO_COLOR!==void 0?!1:process.stdout?.isTTY===!0}function ansi(open,close){return text2=>colorsEnabled()?`\x1B[${open}m${text2}\x1B[${close}m`:text2}var bold=ansi(1,22),dim=ansi(2,22),red=ansi(31,39),green=ansi(32,39),yellow=ansi(33,39),blue=ansi(34,39),magenta=ansi(35,39),cyan=ansi(36,39),gray=ansi(90,39);function resolveLogLevel(configured){let raw=typeof process>"u"?void 0:process.env?.MCP_USE_LOG_LEVEL?.toLowerCase();return raw==="info"||raw==="debug"||raw==="trace"?raw:configured??"info"}function formatClientInfo(info){if(info!==void 0)return typeof info.version=="string"&&info.version!==""?`${info.name}/${info.version}`:info.name}var detailFormatters={initialize:p=>({subject:formatClientInfo(p.clientInfo)}),ping:()=>({}),"server/discover":()=>({}),"completion/complete":p=>({subject:p.ref.type==="ref/prompt"?p.ref.name:p.ref.uri,input:p.argument}),"logging/setLevel":p=>({subject:p.level}),"prompts/get":p=>({subject:p.name,input:p.arguments}),"prompts/list":()=>({}),"resources/list":()=>({}),"resources/templates/list":()=>({}),"resources/read":p=>({subject:p.uri}),"resources/subscribe":p=>({subject:p.uri}),"resources/unsubscribe":p=>({subject:p.uri}),"subscriptions/listen":()=>({}),"tools/call":p=>({subject:p.name,input:p.arguments}),"tools/list":()=>({}),"sampling/createMessage":()=>({}),"elicitation/create":()=>({}),"roots/list":()=>({})};function isKnownMethod(method){return Object.prototype.hasOwnProperty.call(detailFormatters,method)}function formatDetail(message){if(!isKnownMethod(message.method))return{};try{let formatter=detailFormatters[message.method],detail=formatter(message.params);return typeof detail.subject=="string"||detail.subject===void 0?detail:{}}catch{return{}}}var INLINE_JSON_MAX_LENGTH=80;function inlineJson(value){let text2;try{text2=JSON.stringify(value)??String(value)}catch{text2=String(value)}return text2.length>INLINE_JSON_MAX_LENGTH?`${text2.slice(0,INLINE_JSON_MAX_LENGTH)}...`:text2}function formatClientIdentity(message){let meta=message.params?._meta;if(meta===void 0)return;let info=meta[CLIENT_INFO_META_KEY2];if(!(typeof info!="object"||info===null||typeof info.name!="string"))return formatClientInfo(info)}function sanitize(text2){return text2.replace(/[\u0000-\u001F\u007F-\u009F]+/g," ")}function methodStyle(method){return method.startsWith("tools/")?cyan:method.startsWith("resources/")?green:method.startsWith("prompts/")?magenta:method==="initialize"||method==="ping"?gray:blue}var REDACTED_HEADERS=new Set(["authorization","proxy-authorization","cookie","set-cookie","x-api-key"]);function redactHeaders(headers){return Object.fromEntries(Object.entries(headers).map(([name,value])=>[name,REDACTED_HEADERS.has(name.toLowerCase())?"[REDACTED]":value]))}async function extractResponseOutcome(res){if(!res.body)return{errorMessage:null};let text2;try{text2=await res.clone().text()}catch{return{errorMessage:null}}if(!text2)return{errorMessage:null};let isSse=(res.headers.get("content-type")??"").includes("text/event-stream"),payloads=[],tryParse=raw=>{try{payloads.push(JSON.parse(raw))}catch{}};if(isSse){for(let line of text2.split(/\r?\n/))if(line.startsWith("data:")){let data=line.slice(5).trim();data&&tryParse(data)}}else tryParse(text2);let result;for(let payload of payloads){if(payload===null||typeof payload!="object")continue;let message=payload;if(typeof message.error?.message=="string")return{errorMessage:message.error.message};if(message.result?.isError===!0){let textBlock=(Array.isArray(message.result.content)?message.result.content:[]).find(b=>b?.type==="text"&&typeof b.text=="string");return{errorMessage:textBlock?String(textBlock.text):"tool error"}}"result"in message&&(result=message.result)}return{errorMessage:null,result}}function compactToolResult(result){if(result===null||typeof result!="object")return result;let{structuredContent,content}=result;if(structuredContent!==void 0)return structuredContent;if(Array.isArray(content)){let[block]=content;if(content.length===1&&block?.type==="text")return block.text}return content}function formatForDump(value){function truncate(val){return typeof val=="string"&&val.length>100?`${val.slice(0,100)}...`:Array.isArray(val)?val.map(truncate):val!==null&&typeof val=="object"?Object.fromEntries(Object.entries(val).map(([k,v])=>[k,truncate(v)])):val}try{return JSON.stringify(truncate(value),null,2)}catch{return String(value)}}var DUMP_BODY_MAX_LENGTH=1e4;async function printTraceDump(response,requestHeaders,requestBody,readResponseBody){console.log(`
|
|
1
|
+
import{resolvePublicFilePath,servePublicFile}from"./chunk-ZMU5USAZ.js";import{hasExplicitAssetsBase,originFromAssetsBase,resolveAssetsBase,resolveServerOrigin}from"./chunk-PSKSL567.js";import{registerOpenAPITools}from"./chunk-Y26DNVWA.js";import{completable,normalizeCompletions}from"./chunk-OJF6B5EU.js";import{isUsageDisabled,recordUsage}from"./chunk-JTOR5V7S.js";import{inheritBufferedResponse,toNodeHandler,trackBufferedResponse}from"./chunk-XYHHP43G.js";import{authInfoFromRequest,composeFetch,getOAuthProtectedResourceMetadataUrl,getRequestBag,hostValidationMiddleware,isHtmlNavigationRequest,jsonBodyMiddleware,matchesPath,matchesPathPrefix,oauthMetadata,originValidationMiddleware,pathUnderBase,pathnameOf,requireBearerAuth}from"./chunk-MIZQEWZS.js";import{getOAuthProviderOptions,resolveConfiguredOAuthResource,resolveLocalOAuthResource,wrapOAuthTokenVerifier}from"./chunk-IS7FKXFR.js";import{localhostAllowedHostnames,localhostAllowedOrigins,McpServer as SdkMcpServer,ResourceTemplate,CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY3,CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY3,PROTOCOL_VERSION_META_KEY,isJSONRPCRequest as isJSONRPCRequest2,isInputRequiredResult as isInputRequiredResult2}from"@modelcontextprotocol/server";import{createServer as createNodeHttpServer}from"#mcp-use-node-http";import{Hono}from"hono";var FAVICON_CACHE_CONTROL="public, max-age=31536000, immutable",FAVICON_REDIRECT_CACHE_CONTROL="public, max-age=300";function protocolOf(value){return/^([a-z][a-z\d+.-]*):/i.exec(value)?.[1]?.toLowerCase()}function publicAssetPath(basePath,source){return`${basePath==="/"?"":basePath}/_mcp-use/public/${source.split("/").map(segment=>encodeURIComponent(segment)).join("/")}`}function isLocalPublicSource(source){return protocolOf(source)===void 0}function selectFaviconFromIcons(icons){return icons[0]}function assertLocalPublicSource(source,field){if(source.startsWith("/")||source.includes("\\")||source.includes("?")||source.includes("#")||source.split("/").some(segment=>segment===""||segment===".."))throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`)}function parseDataImage(source,field){let comma=source.indexOf(",");if(comma<0)throw new TypeError(`${field} must be a valid image data URL`);let metadata=source.slice(5,comma),payload=source.slice(comma+1),parts=metadata.split(";"),mimeType=parts[0]?.toLowerCase()??"";if(!mimeType.startsWith("image/"))throw new TypeError(`${field} data URL must use an image MIME type`);try{if(parts.includes("base64")){let binary2=atob(payload);return{mimeType,bytes:Uint8Array.from(binary2,character=>character.charCodeAt(0))}}return{mimeType,bytes:new TextEncoder().encode(decodeURIComponent(payload))}}catch{throw new TypeError(`${field} must be a valid image data URL`)}}function assertBrandingSource(source,field){if(typeof source!="string"||source.length===0)throw new TypeError(`${field} must be a non-empty string`);let protocol=protocolOf(source);if(protocol===void 0)return assertLocalPublicSource(source,field),source;if(protocol==="data")return parseDataImage(source,field),source;if(protocol!=="http"&&protocol!=="https")throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`);try{new URL(source)}catch{throw new TypeError(`${field} must be a valid absolute http(s) URL`)}return source}function normalizeServerBranding(config){let websiteUrl;if(config.websiteUrl!==void 0){if(typeof config.websiteUrl!="string"||config.websiteUrl.length===0)throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");let parsed;try{parsed=new URL(config.websiteUrl)}catch{throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:")throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");websiteUrl=config.websiteUrl}let icons;if(config.icons!==void 0){if(!Array.isArray(config.icons))throw new TypeError("icons must be an array of MCP Icon objects");icons=Object.freeze(config.icons.map((value,index)=>{if(typeof value!="object"||value===null)throw new TypeError(`icons[${index}] must be an MCP Icon object`);let icon=value,src=assertBrandingSource(icon.src,`icons[${index}].src`),mimeType=icon.mimeType;if(mimeType!==void 0&&(typeof mimeType!="string"||!mimeType.toLowerCase().startsWith("image/")))throw new TypeError(`icons[${index}].mimeType must be an image MIME type when provided`);let sizes=icon.sizes;if(sizes!==void 0&&(!Array.isArray(sizes)||sizes.some(size=>typeof size!="string"||size.length===0)))throw new TypeError(`icons[${index}].sizes must be an array of non-empty strings when provided`);let normalizedSizes=sizes===void 0?void 0:sizes.map(size=>size),theme=icon.theme;if(theme!==void 0&&theme!=="light"&&theme!=="dark")throw new TypeError(`icons[${index}].theme must be "light" or "dark" when provided`);return Object.freeze({src,...mimeType!==void 0&&{mimeType},...normalizedSizes!==void 0&&{sizes:Object.freeze(normalizedSizes)},...theme!==void 0&&{theme}})}))}let explicitFavicon=config.favicon===void 0?void 0:assertBrandingSource(config.favicon,"favicon"),inferred=explicitFavicon===void 0?selectFaviconFromIcons(icons??[]):void 0,favicon=explicitFavicon??inferred?.src,faviconMimeType=inferred?.mimeType??icons?.find(icon=>icon.src===explicitFavicon)?.mimeType;return Object.freeze({...favicon!==void 0&&{favicon},...faviconMimeType!==void 0&&{faviconMimeType},...icons!==void 0&&{icons},...websiteUrl!==void 0&&{websiteUrl}})}function resolveImplementationIcons(icons,request,basePath){if(icons!==void 0)return icons.map(icon=>({...icon,src:request!==void 0&&isLocalPublicSource(icon.src)?`${resolveAssetsBase(request)}${publicAssetPath(basePath,icon.src)}`:icon.src,...icon.sizes!==void 0&&{sizes:[...icon.sizes]}}))}function hasLocalBrandingAsset(branding){return branding.favicon!==void 0&&isLocalPublicSource(branding.favicon)||branding.icons?.some(icon=>isLocalPublicSource(icon.src))===!0}function createFaviconHandler(branding,options){let source=branding.favicon;if(source!==void 0)return async request=>{if(request.method!=="GET"&&request.method!=="HEAD")return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, HEAD"}});if(new URL(request.url).pathname!=="/favicon.ico")return new Response("Not Found",{status:404});let protocol=protocolOf(source);if(protocol==="http"||protocol==="https")return new Response(null,{status:307,headers:{Location:source,"Cache-Control":FAVICON_REDIRECT_CACHE_CONTROL}});if(protocol==="data"){let data=parseDataImage(source,"favicon");return new Response(request.method==="HEAD"?null:data.bytes.buffer,{status:200,headers:{"Content-Type":branding.faviconMimeType??data.mimeType,"Cache-Control":FAVICON_CACHE_CONTROL,"X-Content-Type-Options":"nosniff"}})}let{join}=await import("path"),publicRoot=options.dev?join(options.projectRoot,"public"):join(options.projectRoot,".mcp-use/build/views/public"),diskPath=await resolvePublicFilePath(publicRoot,source);if(diskPath===null)return new Response("Not Found",{status:404,headers:{"Cache-Control":"no-store"}});let response=await servePublicFile(diskPath,{...options.deferCors===!0&&{deferCors:!0},...request.method==="HEAD"&&{head:!0}});return response.headers.set("Cache-Control",FAVICON_CACHE_CONTROL),response.headers.set("X-Content-Type-Options","nosniff"),branding.faviconMimeType!==void 0&&response.headers.set("Content-Type",branding.faviconMimeType),response}}function assertServerConfig(config){if(config.basePath!==void 0){if(typeof config.basePath!="string")throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace");let{basePath}=config;if(!basePath.startsWith("/")||basePath.includes("?")||basePath.includes("#")||/\s/.test(basePath)||basePath.includes("//")||basePath.length>1&&basePath.endsWith("/"))throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace")}if(config.port!==void 0&&(typeof config.port!="number"||!Number.isInteger(config.port)||config.port<0||config.port>65535))throw new TypeError("port must be an integer between 0 and 65535")}var DEFAULT_LISTEN_HOST="127.0.0.1";function resolveListenHost(explicitHost,configuredHost,env=process.env){if(explicitHost!==void 0)return explicitHost;let envHost=env.HOST?.trim();return envHost!==void 0&&envHost!==""?envHost:configuredHost??DEFAULT_LISTEN_HOST}function resolveListenPort(explicitPort,configuredPort,env=process.env){if(explicitPort!==void 0)return explicitPort;let envPort=parsePort(env.PORT);return envPort!==void 0?envPort:configuredPort??3e3}function parsePort(value){if(value===void 0||value.trim()==="")return;let port=Number(value);return Number.isInteger(port)&&port>=0&&port<=65535?port:void 0}import{CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY2,CLIENT_INFO_META_KEY,inputRequired,inputResponse}from"@modelcontextprotocol/server";import{HonoRequest}from"hono/request";import{CLIENT_CAPABILITIES_META_KEY}from"@modelcontextprotocol/server";var UI_EXTENSION_ID="io.modelcontextprotocol/ui",UI_MIME_TYPE="text/html;profile=mcp-app",UI_RESOURCE_URI_PREFIX="ui://views/";var UI_RESOURCE_URI_META_KEY="ui/resourceUri";function viewResourceUri(viewName){return`${UI_RESOURCE_URI_PREFIX}${viewName}.html`}var clientCapabilitiesByRequest=new WeakMap;function stashClientCapabilities(request,capabilities){clientCapabilitiesByRequest.set(request,capabilities)}function extractClientCapabilitiesFromBody(body){if(typeof body!="object"||body===null)return;let params=body.params;if(typeof params!="object"||params===null)return;let meta=params._meta;if(typeof meta!="object"||meta===null)return;let capabilities=meta[CLIENT_CAPABILITIES_META_KEY];if(!(typeof capabilities!="object"||capabilities===null))return capabilities}function supportsViews(capabilities){let extensions=capabilities?.extensions;if(extensions===void 0)return!1;let uiExtension=extensions[UI_EXTENSION_ID];if(typeof uiExtension!="object"||uiExtension===null)return!1;let mimeTypes=uiExtension.mimeTypes;return Array.isArray(mimeTypes)?mimeTypes.includes(UI_MIME_TYPE):!1}function requireOAuthAuthInfo(authInfo){if(authInfo===void 0||authInfo.extra===void 0||authInfo.expiresAt===void 0)throw new Error("OAuth callback did not receive mapped AuthInfo.extra")}function stringValue(value){return typeof value=="string"?value:void 0}function coordinateValue(value){return typeof value=="string"||typeof value=="number"&&Number.isFinite(value)?value:void 0}function normalizeUserContext(meta){if(meta===void 0)return;let locale=stringValue(meta["openai/locale"])??stringValue(meta["webplus/i18n"]),userAgent=stringValue(meta["openai/userAgent"]),subject=stringValue(meta["openai/subject"]),conversationId=stringValue(meta["openai/session"]),organizationId=stringValue(meta["openai/organization"]),rawLocation=meta["openai/userLocation"],location;if(typeof rawLocation=="object"&&rawLocation!==null&&!Array.isArray(rawLocation)){let values=rawLocation,normalized={city:stringValue(values.city),region:stringValue(values.region),country:stringValue(values.country),timezone:stringValue(values.timezone),latitude:coordinateValue(values.latitude),longitude:coordinateValue(values.longitude)},entries=Object.entries(normalized).filter(entry=>entry[1]!==void 0);entries.length>0&&(location=Object.fromEntries(entries))}if(!(locale===void 0&&userAgent===void 0&&location===void 0&&subject===void 0&&conversationId===void 0&&organizationId===void 0))return{...locale!==void 0&&{locale},...userAgent!==void 0&&{userAgent},...location!==void 0&&{location},...subject!==void 0&&{subject},...conversationId!==void 0&&{conversationId},...organizationId!==void 0&&{organizationId}}}function toClientContext(ctx){let envelope=ctx.mcpReq.envelope,capabilities={...envelope?.[CLIENT_CAPABILITIES_META_KEY2]??{}},info={...envelope?.[CLIENT_INFO_META_KEY]??{}},user=normalizeUserContext(ctx.mcpReq._meta);return{can(capability){return Object.hasOwn(capabilities,capability)},capabilities(){return{...capabilities}},extension(id){let settings=capabilities.extensions?.[id];return settings===void 0?void 0:{...settings}},info(){return{...info}},user(){return user===void 0?void 0:{...user,...user.location!==void 0&&{location:{...user.location}}}},supportsViews(){return supportsViews(capabilities)}}}function createElicit(inputResponses){return async function(key,message,schemaOrUrl){let request,formSchema;if(typeof schemaOrUrl=="string")request=inputRequired.elicitUrl({message,url:schemaOrUrl});else if(schemaOrUrl!==void 0)formSchema=schemaOrUrl,request=inputRequired.elicit({message,requestedSchema:schemaOrUrl});else throw new TypeError("ctx.elicit(key, message, value) requires a form schema or URL string");let response=inputResponse(inputResponses,key);if(response.kind==="elicit"){if(response.action!=="accept")return{status:response.action};if(formSchema===void 0)return{status:"accept"};if(response.content!==void 0){let outcome=await formSchema["~standard"].validate(response.content);if(outcome.issues===void 0)return{status:"accept",data:outcome.value}}}return{status:"required",result:inputRequired({inputRequests:{[key]:request}})}}}function toRequestContext(ctx){let rawRequest=ctx.http?.req,http=rawRequest===void 0?void 0:getRequestBag(rawRequest).honoContext,request=http?.req??(rawRequest===void 0?void 0:new HonoRequest(rawRequest)),additions={signal:ctx.mcpReq.signal,...request!==void 0&&{request},...ctx.mcpReq.inputResponses!==void 0&&{inputResponses:ctx.mcpReq.inputResponses},client:toClientContext(ctx),elicit:createElicit(ctx.mcpReq.inputResponses),requestState:()=>ctx.mcpReq.requestState(),async sendNotification(method,params){await ctx.mcpReq.notify({method,...params!==void 0&&{params}})},async reportProgress(progress,total,message){let progressToken=ctx.mcpReq._meta?.progressToken;return progressToken===void 0?!1:(await ctx.mcpReq.notify({method:"notifications/progress",params:{progressToken,progress,...total!==void 0&&{total},...message!==void 0&&{message}}}),!0)},async sendLog(level,data,logger){await ctx.mcpReq.notify({method:"notifications/message",params:{level,data,...logger!==void 0&&{logger}}})}};return http!==void 0?Object.assign(http,additions):{...additions,...request!==void 0&&{req:request}}}function toAuthenticatedRequestContext(ctx){let authInfo=ctx.http?.authInfo;return requireOAuthAuthInfo(authInfo),Object.assign(toRequestContext(ctx),{auth:{user:authInfo.extra.user,payload:authInfo.extra.payload,accessToken:authInfo.token,scopes:[...authInfo.scopes],permissions:[...authInfo.extra.permissions],...authInfo.clientId.length>0&&{clientId:authInfo.clientId},expiresAt:authInfo.expiresAt,...authInfo.resource!==void 0&&{resource:authInfo.resource}}})}function isReadResourceResult(result){return"contents"in result&&Array.isArray(result.contents)}function isGetPromptResult(result){return"messages"in result&&Array.isArray(result.messages)}function toResourceResult(result,uri){if(isReadResourceResult(result))return result;let mime=result._meta&&typeof result._meta=="object"&&typeof result._meta.mimeType=="string"?result._meta.mimeType:void 0,contents=[];for(let block of result.content??[]){let mapped=contentBlockToResourceContents(block,uri,mime);mapped!==void 0&&contents.push(mapped)}return contents.length===0&&result.structuredContent!==void 0&&contents.push({uri,mimeType:"application/json",text:JSON.stringify(result.structuredContent)}),contents.length===0&&contents.push({uri,mimeType:"text/plain",text:""}),{contents}}function contentBlockToResourceContents(block,uri,mimeHint){if(block.type==="text")return{uri,mimeType:mimeHint??"text/plain",text:block.text};if(block.type==="image"||block.type==="audio")return{uri,mimeType:block.mimeType,blob:block.data};if(block.type==="resource")return{...block.resource}}function toPromptResult(result){if(isGetPromptResult(result))return result;let messages=(result.content??[]).map(content=>({role:"user",content}));return messages.length===0&&result.structuredContent!==void 0&&messages.push({role:"user",content:{type:"text",text:JSON.stringify(result.structuredContent)}}),messages.length===0&&messages.push({role:"user",content:{type:"text",text:""}}),{messages}}var DEFAULT_METHODS=["GET","HEAD","POST","OPTIONS"],DEFAULT_ALLOWED_HEADERS=["Content-Type","Authorization","mcp-protocol-version","mcp-method","mcp-name"];function resolveAllowedOrigin(origin,requestOrigin){return origin===void 0?requestOrigin:typeof origin=="function"?origin(requestOrigin):origin==="*"?"*":Array.isArray(origin)?requestOrigin!==null&&origin.includes(requestOrigin)?requestOrigin:null:origin}function corsHeaders(options,request){if(request.headers.has("Access-Control-Allow-Origin"))return;let requestOrigin=request.headers.get("Origin"),allowedOrigin=resolveAllowedOrigin(options.origin,requestOrigin);if(allowedOrigin===null)return;let headers={"Access-Control-Allow-Origin":allowedOrigin,"Access-Control-Allow-Methods":options.methods.join(", "),"Access-Control-Allow-Headers":options.allowedHeaders.join(", ")};return options.credentials&&(headers["Access-Control-Allow-Credentials"]="true"),allowedOrigin!=="*"&&(headers.Vary="Origin"),headers}function mergeCorsHeaders(response,headers){if(response.headers.has("Access-Control-Allow-Origin"))return response;let merged=new Headers(response.headers);return new Headers(headers).forEach((value,key)=>{merged.set(key,value)}),inheritBufferedResponse(response,new Response(response.body,{status:response.status,statusText:response.statusText,headers:merged}))}function corsFetchMiddleware(options){if(!(options.enabled!==!1))return async(_request,next)=>next();let resolved={...options.origin!==void 0&&{origin:options.origin},methods:options.methods??DEFAULT_METHODS,allowedHeaders:options.allowedHeaders??DEFAULT_ALLOWED_HEADERS,credentials:options.credentials??!1};return async(request,next)=>{let headers=corsHeaders(resolved,request);if(headers===void 0)return next();if(request.method==="OPTIONS")return new Response(null,{status:204,headers});let response=await next();return mergeCorsHeaders(response,headers)}}function isGlobalCorsEnabled(cors){return cors!==void 0&&cors.enabled!==!1}import{CallToolResultSchema,GetPromptResultSchema,ListPromptsResultSchema,ListResourcesResultSchema,ListToolsResultSchema,ReadResourceResultSchema}from"@modelcontextprotocol/core";import{isInputRequiredResult}from"@modelcontextprotocol/server";var MCP_MIDDLEWARE_METHODS=["tools/call","tools/list","resources/read","resources/list","prompts/get","prompts/list"];function withMcpMiddlewareParams(request,params){if(typeof request!="object"||request===null||Array.isArray(request))throw new TypeError("[mcp-use] MCP middleware received an invalid downstream request");return{...request,params}}function createMcpMiddlewareEntry(pattern,handler){let normalizedPattern=normalizeMcpMiddlewarePattern(pattern),invoke=handler;if(normalizedPattern!=="*"&&!isMcpMiddlewareMethod(normalizedPattern))throw new TypeError(`Unsupported MCP middleware pattern "${pattern}". Use an exact MCP method or "mcp:*".`);return normalizedPattern==="*"?{pattern:normalizedPattern,handler:async(ctx,next)=>{let downstreamCalled=!1,downstreamResult;if(await invoke(ctx,async()=>{downstreamResult=await next(),downstreamCalled=!0}),!downstreamCalled)throw new Error(`Wildcard MCP middleware "${normalizedPattern}" must call next()`);return downstreamResult}}:{pattern:normalizedPattern,handler:(ctx,next)=>invoke(ctx,next)}}function createMcpEventListenerEntry(pattern,handler){let{pattern:normalizedPattern,phase}=parseMcpPattern(pattern),invoke=handler;return{pattern:normalizedPattern,phase,handler:(ctx,result)=>invoke(ctx,result)}}function matchesPattern(pattern,method){if(pattern==="*")return!0;if(pattern.endsWith("/*")){let prefix=pattern.slice(0,-1);return method.startsWith(prefix)}return pattern===method}function isMcpMiddlewareMethod(value){return MCP_MIDDLEWARE_METHODS.some(method=>method===value)}function composeMiddleware(entries,method,innerFn){let matching=entries.filter(entry=>matchesPattern(entry.pattern,method));return matching.length===0?_ctx=>innerFn():ctx=>{let index=-1,dispatch=i=>i<=index?Promise.reject(new Error("next() called multiple times")):(index=i,i===matching.length?innerFn():matching[i].handler(ctx,()=>dispatch(i+1)));return dispatch(0)}}function freezeMiddlewareContext(ctx){return Object.freeze({method:ctx.method,params:Object.freeze({...ctx.params}),...ctx.request!==void 0&&{request:ctx.request},...ctx.req!==void 0&&{req:ctx.req},...ctx.session!==void 0&&{session:Object.freeze({...ctx.session})},...ctx.auth!==void 0&&{auth:ctx.auth},state:new Map(ctx.state)})}async function runMcpOperation(middlewares,events,method,ctx,innerFn){dispatchMcpEvents(events,method,"before",ctx);let result=await composeMiddleware(middlewares,method,innerFn)(ctx);return assertValidMiddlewareResult(method,result),dispatchMcpEvents(events,method,"complete",ctx,result),result}function assertValidMiddlewareResult(method,result){if((method==="tools/call"||method==="resources/read"||method==="prompts/get")&&isInputRequiredResult(result))return;let validation=(()=>{switch(method){case"tools/call":return assertArrayProperty(method,result,"content"),CallToolResultSchema.safeParse(result);case"tools/list":return assertArrayResult(method,result),ListToolsResultSchema.safeParse({tools:result});case"resources/read":return assertArrayProperty(method,result,"contents"),ReadResourceResultSchema.safeParse(result);case"resources/list":return assertArrayResult(method,result),ListResourcesResultSchema.safeParse({resources:result});case"prompts/get":return assertArrayProperty(method,result,"messages"),GetPromptResultSchema.safeParse(result);case"prompts/list":return assertArrayResult(method,result),ListPromptsResultSchema.safeParse({prompts:result});default:throw new TypeError(`Unsupported MCP middleware method "${method}"`)}})();if(!validation.success)throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: ${validation.error.message}`)}function assertArrayResult(method,result){if(!Array.isArray(result))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected an array`)}function assertArrayProperty(method,result,property){if(typeof result!="object"||result===null||!Array.isArray(result[property]))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected a ${property} array`)}function dispatchMcpEvents(events,method,phase,ctx,result){let frozen=freezeMiddlewareContext(ctx);for(let entry of events)if(!(entry.phase!==phase||!matchesPattern(entry.pattern,method)))try{entry.handler(frozen,result)}catch(error2){console.error(`[mcp-use] MCP event listener for "${entry.pattern}" (${phase}) threw:`,error2)}}function parseMcpPattern(raw){let pattern=raw.startsWith("mcp:")?raw.slice(4):raw;return pattern.endsWith(":complete")?{pattern:pattern.slice(0,-9),phase:"complete"}:{pattern,phase:"before"}}function normalizeMcpMiddlewarePattern(raw){return raw.startsWith("mcp:")?raw.slice(4):raw}import{CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY2,isJSONRPCRequest}from"@modelcontextprotocol/server";function colorsEnabled(){return typeof process>"u"||process.env?.NO_COLOR!==void 0?!1:process.stdout?.isTTY===!0}function ansi(open,close){return text2=>colorsEnabled()?`\x1B[${open}m${text2}\x1B[${close}m`:text2}var bold=ansi(1,22),dim=ansi(2,22),red=ansi(31,39),green=ansi(32,39),yellow=ansi(33,39),blue=ansi(34,39),magenta=ansi(35,39),cyan=ansi(36,39),gray=ansi(90,39);function resolveLogLevel(configured){let raw=typeof process>"u"?void 0:process.env?.MCP_USE_LOG_LEVEL?.toLowerCase();return raw==="info"||raw==="debug"||raw==="trace"?raw:configured??"info"}function formatClientInfo(info){if(info!==void 0)return typeof info.version=="string"&&info.version!==""?`${info.name}/${info.version}`:info.name}var detailFormatters={initialize:p=>({subject:formatClientInfo(p.clientInfo)}),ping:()=>({}),"server/discover":()=>({}),"completion/complete":p=>({subject:p.ref.type==="ref/prompt"?p.ref.name:p.ref.uri,input:p.argument}),"logging/setLevel":p=>({subject:p.level}),"prompts/get":p=>({subject:p.name,input:p.arguments}),"prompts/list":()=>({}),"resources/list":()=>({}),"resources/templates/list":()=>({}),"resources/read":p=>({subject:p.uri}),"resources/subscribe":p=>({subject:p.uri}),"resources/unsubscribe":p=>({subject:p.uri}),"subscriptions/listen":()=>({}),"tools/call":p=>({subject:p.name,input:p.arguments}),"tools/list":()=>({}),"sampling/createMessage":()=>({}),"elicitation/create":()=>({}),"roots/list":()=>({})};function isKnownMethod(method){return Object.prototype.hasOwnProperty.call(detailFormatters,method)}function formatDetail(message){if(!isKnownMethod(message.method))return{};try{let formatter=detailFormatters[message.method],detail=formatter(message.params);return typeof detail.subject=="string"||detail.subject===void 0?detail:{}}catch{return{}}}var INLINE_JSON_MAX_LENGTH=80;function inlineJson(value){let text2;try{text2=JSON.stringify(value)??String(value)}catch{text2=String(value)}return text2.length>INLINE_JSON_MAX_LENGTH?`${text2.slice(0,INLINE_JSON_MAX_LENGTH)}...`:text2}function formatClientIdentity(message){let meta=message.params?._meta;if(meta===void 0)return;let info=meta[CLIENT_INFO_META_KEY2];if(!(typeof info!="object"||info===null||typeof info.name!="string"))return formatClientInfo(info)}function sanitize(text2){return text2.replace(/[\u0000-\u001F\u007F-\u009F]+/g," ")}function methodStyle(method){return method.startsWith("tools/")?cyan:method.startsWith("resources/")?green:method.startsWith("prompts/")?magenta:method==="initialize"||method==="ping"?gray:blue}var REDACTED_HEADERS=new Set(["authorization","proxy-authorization","cookie","set-cookie","x-api-key"]);function redactHeaders(headers){return Object.fromEntries(Object.entries(headers).map(([name,value])=>[name,REDACTED_HEADERS.has(name.toLowerCase())?"[REDACTED]":value]))}async function extractResponseOutcome(res){if(!res.body)return{errorMessage:null};let text2;try{text2=await res.clone().text()}catch{return{errorMessage:null}}if(!text2)return{errorMessage:null};let isSse=(res.headers.get("content-type")??"").includes("text/event-stream"),payloads=[],tryParse=raw=>{try{payloads.push(JSON.parse(raw))}catch{}};if(isSse){for(let line of text2.split(/\r?\n/))if(line.startsWith("data:")){let data=line.slice(5).trim();data&&tryParse(data)}}else tryParse(text2);let result;for(let payload of payloads){if(payload===null||typeof payload!="object")continue;let message=payload;if(typeof message.error?.message=="string")return{errorMessage:message.error.message};if(message.result?.isError===!0){let textBlock=(Array.isArray(message.result.content)?message.result.content:[]).find(b=>b?.type==="text"&&typeof b.text=="string");return{errorMessage:textBlock?String(textBlock.text):"tool error"}}"result"in message&&(result=message.result)}return{errorMessage:null,result}}function compactToolResult(result){if(result===null||typeof result!="object")return result;let{structuredContent,content}=result;if(structuredContent!==void 0)return structuredContent;if(Array.isArray(content)){let[block]=content;if(content.length===1&&block?.type==="text")return block.text}return content}function formatForDump(value){function truncate(val){return typeof val=="string"&&val.length>100?`${val.slice(0,100)}...`:Array.isArray(val)?val.map(truncate):val!==null&&typeof val=="object"?Object.fromEntries(Object.entries(val).map(([k,v])=>[k,truncate(v)])):val}try{return JSON.stringify(truncate(value),null,2)}catch{return String(value)}}var DUMP_BODY_MAX_LENGTH=1e4;async function printTraceDump(response,requestHeaders,requestBody,readResponseBody){console.log(`
|
|
2
2
|
${cyan("=".repeat(80))}`),console.log(bold(cyan("[TRACE] Request Details"))),console.log(cyan("-".repeat(80))),Object.keys(requestHeaders).length>0&&(console.log(yellow("Request Headers:")),console.log(formatForDump(redactHeaders(requestHeaders)))),requestBody!==void 0&&(console.log(yellow("Request Body:")),console.log(typeof requestBody=="string"?requestBody:formatForDump(requestBody)));let responseHeaders={};if(response.headers.forEach((value,key)=>{responseHeaders[key]=value}),Object.keys(responseHeaders).length>0&&(console.log(yellow("Response Headers:")),console.log(formatForDump(redactHeaders(responseHeaders)))),!readResponseBody)console.log(`${yellow("Response Body:")} (streaming \u2014 not dumped)`);else if(response.body===null)console.log(`${yellow("Response Body:")} (no body)`);else try{let text2=await response.clone().text();if(text2.length===0)console.log(`${yellow("Response Body:")} (empty)`);else{console.log(yellow("Response Body:"));try{console.log(formatForDump(JSON.parse(text2)))}catch{console.log(text2.length>DUMP_BODY_MAX_LENGTH?`${text2.slice(0,DUMP_BODY_MAX_LENGTH)}
|
|
3
3
|
... (truncated, ${text2.length-DUMP_BODY_MAX_LENGTH} more characters)`:text2)}}}catch{console.log(`${yellow("Response Body:")} (unable to read)`)}console.log(`${cyan("=".repeat(80))}
|
|
4
4
|
`)}function styleStatus(status){let text2=String(status);return status>=500?magenta(text2):status>=400?red(text2):status>=300?yellow(text2):green(text2)}function isNoisyRequest(httpMethod,pathname){return httpMethod!=="GET"&&httpMethod!=="HEAD"?!1:pathname.endsWith("/favicon.ico")}function requestLogger(options={}){return options.enabled===!1?(_request,next)=>next():async(request,next)=>{let level=resolveLogLevel(options.level),startedAt=Date.now(),httpMethod=request.method,pathname=new URL(request.url).pathname;if(isNoisyRequest(httpMethod,pathname))return next();let requestHeaders={};level==="trace"&&request.headers.forEach((value,key)=>{requestHeaders[key]=value});let requestBody;if(httpMethod!=="GET"&&httpMethod!=="HEAD"){let parsedBody=getRequestBag(request).parsedBody;if(parsedBody!==void 0)requestBody=parsedBody;else try{requestBody=await request.clone().json()}catch{}}let response=await next(),durationMs=Date.now()-startedAt,timestamp=new Date().toISOString().substring(11,19),mcpRequest=isJSONRPCRequest(requestBody)?requestBody:void 0,isStreamingMethod=mcpRequest?.method==="subscriptions/listen",lines=[[dim(timestamp),bold(httpMethod),pathname,styleStatus(response.status),dim(`in ${durationMs}ms`)].join(" ")];if(mcpRequest!==void 0){let method=sanitize(mcpRequest.method),parts=[` ${methodStyle(method)(method)}`],detail=formatDetail(mcpRequest);detail.subject!==void 0&&parts.push(bold(sanitize(detail.subject)));let echoPayloads=level!=="info";echoPayloads&&detail.input!==void 0&&parts.push(inlineJson(detail.input));let outcome=isStreamingMethod?{errorMessage:null}:await extractResponseOutcome(response);if(echoPayloads&&mcpRequest.method==="tools/call"&&outcome.errorMessage===null&&outcome.result!==void 0&&parts.push(dim("->"),inlineJson(compactToolResult(outcome.result))),mcpRequest.method!=="initialize"){let client=formatClientIdentity(mcpRequest);client!==void 0&&parts.push(dim(sanitize(client)))}outcome.errorMessage!==null?parts.push(red(`ERROR ${sanitize(outcome.errorMessage)}`)):response.status>=400&&parts.push(red(`ERROR (HTTP ${response.status})`)),lines.push(parts.join(" "))}return console.log(lines.join(`
|
package/dist/internal/usage.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{flushUsage,isUsageDisabled,recordUsage}from"../chunk-
|
|
1
|
+
import{flushUsage,isUsageDisabled,recordUsage}from"../chunk-JTOR5V7S.js";export{flushUsage,isUsageDisabled,recordUsage};
|
package/dist/landing.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Generate an HTML landing page for an MCP server endpoint.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* The rendered page includes server metadata and connection instructions for
|
|
5
|
+
* supported MCP clients.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
6
8
|
*/
|
|
7
9
|
/** A tool shown in the landing page's primitives list. */
|
|
8
10
|
export interface LandingPageTool {
|
|
@@ -61,6 +63,17 @@ export interface LandingPageOptions {
|
|
|
61
63
|
* for Claude Code, Cursor, VS Code, ChatGPT, and Manufact Inspector.
|
|
62
64
|
*
|
|
63
65
|
* @param options - Server identity, endpoint, icon, and primitive metadata.
|
|
64
|
-
* @returns HTML landing page with connection instructions
|
|
66
|
+
* @returns HTML landing page with connection instructions.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { generateLandingPage } from "mcp-use/landing";
|
|
71
|
+
*
|
|
72
|
+
* const html = generateLandingPage({
|
|
73
|
+
* name: "weather",
|
|
74
|
+
* version: "1.0.0",
|
|
75
|
+
* url: "https://example.com/mcp",
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
65
78
|
*/
|
|
66
79
|
export declare function generateLandingPage(options: LandingPageOptions): string;
|
|
@@ -15,28 +15,46 @@ export type McpMiddlewareParams<M extends McpMiddlewareMethod> = RequestTypeMap[
|
|
|
15
15
|
* transformed array.
|
|
16
16
|
*/
|
|
17
17
|
export interface McpMiddlewareOperationMap {
|
|
18
|
+
/** Tool invocation parameters and handler result. */
|
|
18
19
|
"tools/call": {
|
|
20
|
+
/** Parameters for the tool invocation. */
|
|
19
21
|
params: McpMiddlewareParams<"tools/call">;
|
|
22
|
+
/** Tool invocation result passed through the middleware chain. */
|
|
20
23
|
result: HandlerResultTypeMap["tools/call"];
|
|
21
24
|
};
|
|
25
|
+
/** Tool-list parameters and list items. */
|
|
22
26
|
"tools/list": {
|
|
27
|
+
/** Parameters for the tool-list request. */
|
|
23
28
|
params: McpMiddlewareParams<"tools/list">;
|
|
29
|
+
/** Tool descriptors returned by the list request. */
|
|
24
30
|
result: ResultTypeMap["tools/list"]["tools"];
|
|
25
31
|
};
|
|
32
|
+
/** Resource-read parameters and handler result. */
|
|
26
33
|
"resources/read": {
|
|
34
|
+
/** Parameters identifying the resource to read. */
|
|
27
35
|
params: McpMiddlewareParams<"resources/read">;
|
|
36
|
+
/** Resource contents returned by the handler. */
|
|
28
37
|
result: HandlerResultTypeMap["resources/read"];
|
|
29
38
|
};
|
|
39
|
+
/** Resource-list parameters and list items. */
|
|
30
40
|
"resources/list": {
|
|
41
|
+
/** Parameters for the resource-list request. */
|
|
31
42
|
params: McpMiddlewareParams<"resources/list">;
|
|
43
|
+
/** Resource descriptors returned by the list request. */
|
|
32
44
|
result: ResultTypeMap["resources/list"]["resources"];
|
|
33
45
|
};
|
|
46
|
+
/** Prompt-read parameters and handler result. */
|
|
34
47
|
"prompts/get": {
|
|
48
|
+
/** Parameters identifying the prompt and its arguments. */
|
|
35
49
|
params: McpMiddlewareParams<"prompts/get">;
|
|
50
|
+
/** Prompt messages returned by the handler. */
|
|
36
51
|
result: HandlerResultTypeMap["prompts/get"];
|
|
37
52
|
};
|
|
53
|
+
/** Prompt-list parameters and list items. */
|
|
38
54
|
"prompts/list": {
|
|
55
|
+
/** Parameters for the prompt-list request. */
|
|
39
56
|
params: McpMiddlewareParams<"prompts/list">;
|
|
57
|
+
/** Prompt descriptors returned by the list request. */
|
|
40
58
|
result: ResultTypeMap["prompts/list"]["prompts"];
|
|
41
59
|
};
|
|
42
60
|
}
|
package/dist/next/config.d.ts
CHANGED
|
@@ -10,20 +10,38 @@ interface NextHeaderRule {
|
|
|
10
10
|
export interface NextConfigLike {
|
|
11
11
|
/** Preserve arbitrary Next.js settings while augmenting the fields we use. */
|
|
12
12
|
[key: string]: unknown;
|
|
13
|
+
/** Next.js response-header callback augmented with MCP CORS headers. */
|
|
13
14
|
headers?: () => NextHeaderRule[] | Promise<NextHeaderRule[]>;
|
|
15
|
+
/** Next.js output tracing globs augmented with compiled MCP view assets. */
|
|
14
16
|
outputFileTracingIncludes?: Record<string, string[]>;
|
|
15
17
|
}
|
|
16
18
|
/** Options for {@link withMcpUse}. */
|
|
17
19
|
export interface WithMcpUseOptions {
|
|
18
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Authored MCP server entry, relative to `projectRoot`.
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue `"mcp/server.ts"`
|
|
24
|
+
*/
|
|
19
25
|
entry?: string;
|
|
20
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Conventional MCP source directory containing the entry and `views/`.
|
|
28
|
+
*
|
|
29
|
+
* @defaultValue `"mcp"`
|
|
30
|
+
*/
|
|
21
31
|
mcpDir?: string;
|
|
22
32
|
/** Explicit views directory, relative to `projectRoot`. */
|
|
23
33
|
viewsDir?: string;
|
|
24
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* MCP route mounted by the application.
|
|
36
|
+
*
|
|
37
|
+
* @defaultValue `"/api/mcp"`
|
|
38
|
+
*/
|
|
25
39
|
basePath?: string;
|
|
26
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Next.js project root.
|
|
42
|
+
*
|
|
43
|
+
* @defaultValue `process.cwd()`
|
|
44
|
+
*/
|
|
27
45
|
projectRoot?: string;
|
|
28
46
|
}
|
|
29
47
|
/** @internal Exported for focused composition tests, not from `mcp-use/next`. */
|
|
@@ -33,6 +51,17 @@ export declare function composeNextConfig<T extends NextConfigLike>(nextConfig:
|
|
|
33
51
|
*
|
|
34
52
|
* The MCP build runs when Next evaluates `next.config`, for both development
|
|
35
53
|
* and production builds. This removes the need for a separate prebuild script.
|
|
54
|
+
*
|
|
55
|
+
* @param nextConfig - Existing Next.js configuration to augment.
|
|
56
|
+
* @param options - MCP source, route, and project-root settings.
|
|
57
|
+
* @returns The augmented configuration after the MCP project is built.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { withMcpUse } from "mcp-use/next";
|
|
62
|
+
*
|
|
63
|
+
* export default withMcpUse();
|
|
64
|
+
* ```
|
|
36
65
|
*/
|
|
37
66
|
export declare function withMcpUse<T extends NextConfigLike = NextConfigLike>(nextConfig?: T, options?: WithMcpUseOptions): Promise<T & NextConfigLike>;
|
|
38
67
|
export {};
|
package/dist/next/handler.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { MCPServer } from "../server.js";
|
|
2
2
|
/** Route Handler exports returned by {@link createNextHandler}. */
|
|
3
3
|
export interface NextMcpHandlers {
|
|
4
|
+
/** Handles MCP GET requests. */
|
|
4
5
|
GET(request: Request): Promise<Response>;
|
|
6
|
+
/** Handles MCP POST requests. */
|
|
5
7
|
POST(request: Request): Promise<Response>;
|
|
8
|
+
/** Handles MCP DELETE requests. */
|
|
6
9
|
DELETE(request: Request): Promise<Response>;
|
|
10
|
+
/** Handles CORS preflight requests. */
|
|
7
11
|
OPTIONS(request: Request): Promise<Response>;
|
|
8
12
|
}
|
|
9
13
|
/**
|
|
@@ -12,5 +16,17 @@ export interface NextMcpHandlers {
|
|
|
12
16
|
* The generated artifact contains only view registration data; application
|
|
13
17
|
* source continues to import its own server module. Initialization is lazy so
|
|
14
18
|
* importing a route during `next build` does not perform filesystem I/O.
|
|
19
|
+
*
|
|
20
|
+
* @typeParam TUser - Authenticated application user type.
|
|
21
|
+
* @param server - MCP server mounted by the route.
|
|
22
|
+
* @returns App Router method exports for the MCP endpoint.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { server } from "@/mcp/server";
|
|
27
|
+
* import { createNextHandler } from "mcp-use/next";
|
|
28
|
+
*
|
|
29
|
+
* export const { GET, POST, DELETE, OPTIONS } = createNextHandler(server);
|
|
30
|
+
* ```
|
|
15
31
|
*/
|
|
16
32
|
export declare function createNextHandler<TUser>(server: MCPServer<TUser>): NextMcpHandlers;
|
package/dist/next/index.d.ts
CHANGED
package/dist/node-bridge.d.ts
CHANGED
|
@@ -1,34 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* ponytail: track upstream SSE/backpressure fixes when bumping `@modelcontextprotocol/server`.
|
|
2
|
+
* Adapt Web-standard MCP handlers to Node.js HTTP request and response objects.
|
|
4
3
|
*
|
|
5
|
-
* @
|
|
6
|
-
* so the generic edge graph can reuse the response adapter safely.
|
|
4
|
+
* @packageDocumentation
|
|
7
5
|
*/
|
|
8
6
|
import type { AuthInfo, McpHandlerRequestOptions } from "@modelcontextprotocol/server";
|
|
9
7
|
/** Minimal duck-typed shape of a Node.js `IncomingMessage`. */
|
|
10
8
|
export interface NodeIncomingMessageLike extends AsyncIterable<Uint8Array | string> {
|
|
9
|
+
/** HTTP method. Defaults to `GET` when omitted. */
|
|
11
10
|
method?: string | undefined;
|
|
11
|
+
/** Request target. Defaults to `/` when omitted. */
|
|
12
12
|
url?: string | undefined;
|
|
13
|
+
/** Incoming HTTP headers, including `host` or `:authority` when available. */
|
|
13
14
|
headers: Record<string, string | string[] | undefined>;
|
|
15
|
+
/** Verified authentication information forwarded to the Fetch handler. */
|
|
14
16
|
auth?: AuthInfo;
|
|
15
17
|
}
|
|
16
18
|
/** Minimal duck-typed shape of a Node.js `ServerResponse`. */
|
|
17
19
|
export interface NodeServerResponseLike {
|
|
20
|
+
/** Writes the HTTP status and response headers. */
|
|
18
21
|
writeHead(statusCode: number, headers?: Record<string, string>): unknown;
|
|
22
|
+
/** Writes a response-body chunk and returns `false` when backpressure applies. */
|
|
19
23
|
write(chunk: string | Uint8Array): unknown;
|
|
24
|
+
/** Completes the response, optionally with a final body chunk. */
|
|
20
25
|
end(chunk?: string | Uint8Array): unknown;
|
|
26
|
+
/** Subscribes to response lifecycle events such as `close` and `drain`. */
|
|
21
27
|
on(event: string, listener: (...args: unknown[]) => void): unknown;
|
|
28
|
+
/** Whether the underlying response stream has already been destroyed. */
|
|
22
29
|
destroyed?: boolean;
|
|
23
30
|
}
|
|
24
31
|
/** Web-standard fetch face accepted by {@link toNodeHandler}. */
|
|
25
32
|
export interface FetchLikeHandler {
|
|
33
|
+
/** Handles a converted Web-standard request. */
|
|
26
34
|
fetch: (request: Request, options?: McpHandlerRequestOptions) => Promise<Response>;
|
|
27
35
|
}
|
|
28
36
|
/** Node `(req, res, parsedBody?)` handler produced by {@link toNodeHandler}. */
|
|
29
37
|
export type NodeRequestHandler = (req: NodeIncomingMessageLike, res: NodeServerResponseLike, parsedBody?: unknown) => Promise<void>;
|
|
30
38
|
/** Options for {@link toNodeHandler}. */
|
|
31
39
|
export interface ToNodeHandlerOptions {
|
|
40
|
+
/** Observes conversion or handler errors before a JSON-RPC error is returned. */
|
|
32
41
|
onerror?: (error: Error) => void;
|
|
33
42
|
}
|
|
34
43
|
/**
|
|
@@ -36,10 +45,22 @@ export interface ToNodeHandlerOptions {
|
|
|
36
45
|
*
|
|
37
46
|
* @param handler - Handler whose `fetch` receives converted `Request` objects.
|
|
38
47
|
* @param opts - Optional adapter error observer.
|
|
48
|
+
* @returns A Node-compatible asynchronous request handler.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { createServer } from "node:http";
|
|
53
|
+
* import { MCPServer } from "mcp-use";
|
|
54
|
+
* import { toNodeHandler } from "mcp-use/node";
|
|
55
|
+
*
|
|
56
|
+
* const server = new MCPServer({ name: "example", version: "1.0.0" });
|
|
57
|
+
* createServer(toNodeHandler(server)).listen(3000);
|
|
58
|
+
* ```
|
|
39
59
|
*/
|
|
40
60
|
export declare function toNodeHandler(handler: FetchLikeHandler, opts?: ToNodeHandlerOptions): NodeRequestHandler;
|
|
41
61
|
/** Options for {@link toWebRequest}. */
|
|
42
62
|
export interface ToWebRequestOptions {
|
|
63
|
+
/** Signal that aborts the constructed request. */
|
|
43
64
|
signal?: AbortSignal;
|
|
44
65
|
}
|
|
45
66
|
/**
|
|
@@ -48,5 +69,13 @@ export interface ToWebRequestOptions {
|
|
|
48
69
|
* @param req - Node `IncomingMessage` (or Express `req`).
|
|
49
70
|
* @param parsedBody - Optional pre-parsed JSON body.
|
|
50
71
|
* @param options - Optional abort signal for the constructed request.
|
|
72
|
+
* @returns A Web-standard request with the Node headers and body.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { toWebRequest } from "mcp-use/node";
|
|
77
|
+
*
|
|
78
|
+
* const request = await toWebRequest(incomingMessage);
|
|
79
|
+
* ```
|
|
51
80
|
*/
|
|
52
81
|
export declare function toWebRequest(req: NodeIncomingMessageLike, parsedBody?: unknown, options?: ToWebRequestOptions): Promise<Request>;
|
package/dist/oauth/auth0.d.ts
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify Auth0 access tokens for an mcp-use resource server.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
1
6
|
import { type OAuthProvider, type OAuthResourceOptions } from "./provider.js";
|
|
2
7
|
/** Verified Auth0 user claims exposed to authenticated MCP callbacks. */
|
|
3
8
|
export interface Auth0OAuthUser {
|
|
9
|
+
/** Auth0 subject identifier. */
|
|
4
10
|
id: string;
|
|
11
|
+
/** Primary email address, when included in the access token. */
|
|
5
12
|
email?: string;
|
|
13
|
+
/** Display name, when included in the access token. */
|
|
6
14
|
name?: string;
|
|
15
|
+
/** Auth0 nickname, when included in the access token. */
|
|
7
16
|
nickname?: string;
|
|
17
|
+
/** Profile image URL, when included in the access token. */
|
|
8
18
|
picture?: string;
|
|
19
|
+
/** Whether Auth0 has verified {@link Auth0OAuthUser.email}. */
|
|
9
20
|
emailVerified?: boolean;
|
|
21
|
+
/** ISO timestamp for the most recent profile update. */
|
|
10
22
|
updatedAt?: string;
|
|
23
|
+
/** Roles from the access token's `roles` claim. */
|
|
11
24
|
roles: string[];
|
|
12
25
|
}
|
|
13
26
|
/** Configures Auth0 JWT verification and protected-resource metadata. */
|
|
14
27
|
export interface Auth0OAuthProviderOptions extends OAuthResourceOptions {
|
|
28
|
+
/** Auth0 tenant domain or issuer URL. */
|
|
15
29
|
domain: URL | string;
|
|
16
30
|
}
|
|
17
31
|
/**
|
|
@@ -19,5 +33,15 @@ export interface Auth0OAuthProviderOptions extends OAuthResourceOptions {
|
|
|
19
33
|
*
|
|
20
34
|
* @param options - Auth0 domain and resource-server settings.
|
|
21
35
|
* @returns A provider that rejects tokens not issued for the resolved MCP resource.
|
|
36
|
+
* @throws A `TypeError` if `domain` is not a valid HTTP or HTTPS URL.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { oauthAuth0Provider } from "mcp-use/oauth/auth0";
|
|
41
|
+
*
|
|
42
|
+
* const oauth = oauthAuth0Provider({
|
|
43
|
+
* domain: "https://example.us.auth0.com",
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
22
46
|
*/
|
|
23
47
|
export declare function oauthAuth0Provider(options: Auth0OAuthProviderOptions): OAuthProvider<Auth0OAuthUser>;
|
|
@@ -1,13 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify access tokens from the Better Auth OAuth 2.1 Provider plugin.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
1
6
|
import { type OAuthProvider, type OAuthResourceOptions } from "./provider.js";
|
|
2
7
|
/** Verified Better Auth claims exposed to authenticated MCP callbacks. */
|
|
3
8
|
export interface BetterAuthOAuthUser {
|
|
9
|
+
/** Better Auth subject identifier. */
|
|
4
10
|
id: string;
|
|
11
|
+
/** Primary email address, when included in the access token. */
|
|
5
12
|
email?: string;
|
|
13
|
+
/** Display name, when included in the access token. */
|
|
6
14
|
name?: string;
|
|
15
|
+
/** Profile image URL, when included in the access token. */
|
|
7
16
|
picture?: string;
|
|
17
|
+
/** Whether Better Auth has verified {@link BetterAuthOAuthUser.email}. */
|
|
8
18
|
emailVerified?: boolean;
|
|
19
|
+
/** Better Auth session identifier. */
|
|
9
20
|
sessionId?: string;
|
|
21
|
+
/** Whether the session belongs to an anonymous user. */
|
|
10
22
|
isAnonymous?: boolean;
|
|
23
|
+
/** Roles from the access token's `roles` claim. */
|
|
11
24
|
roles: string[];
|
|
12
25
|
}
|
|
13
26
|
/** Configures Better Auth JWT verification and protected-resource metadata. */
|
|
@@ -24,5 +37,15 @@ export interface BetterAuthOAuthProviderOptions extends OAuthResourceOptions {
|
|
|
24
37
|
*
|
|
25
38
|
* @param options - Better Auth issuer URL and resource-server settings.
|
|
26
39
|
* @returns A provider that rejects tokens not issued for the resolved MCP resource.
|
|
40
|
+
* @throws A `TypeError` if `authURL` is not a valid HTTP or HTTPS URL.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { oauthBetterAuthProvider } from "mcp-use/oauth/better-auth";
|
|
45
|
+
*
|
|
46
|
+
* const oauth = oauthBetterAuthProvider({
|
|
47
|
+
* authURL: "https://auth.example.com/api/auth",
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
27
50
|
*/
|
|
28
51
|
export declare function oauthBetterAuthProvider(options: BetterAuthOAuthProviderOptions): OAuthProvider<BetterAuthOAuthUser>;
|
package/dist/oauth/clerk.d.ts
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify Clerk access tokens for an mcp-use resource server.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
1
6
|
import { type OAuthProvider, type OAuthResourceOptions } from "./provider.js";
|
|
2
7
|
/** Verified Clerk user and organization claims exposed to authenticated MCP callbacks. */
|
|
3
8
|
export interface ClerkOAuthUser {
|
|
9
|
+
/** Clerk subject identifier. */
|
|
4
10
|
id: string;
|
|
11
|
+
/** Primary email address, when included in the access token. */
|
|
5
12
|
email?: string;
|
|
13
|
+
/** Display name, when included in the access token. */
|
|
6
14
|
name?: string;
|
|
15
|
+
/** Clerk username, when included in the access token. */
|
|
7
16
|
username?: string;
|
|
17
|
+
/** Profile image URL, when included in the access token. */
|
|
8
18
|
picture?: string;
|
|
19
|
+
/** Whether Clerk has verified {@link ClerkOAuthUser.email}. */
|
|
9
20
|
emailVerified?: boolean;
|
|
21
|
+
/** Active Clerk organization identifier. */
|
|
10
22
|
organizationId?: string;
|
|
23
|
+
/** Role in the active Clerk organization. */
|
|
11
24
|
organizationRole?: string;
|
|
25
|
+
/** Slug of the active Clerk organization. */
|
|
12
26
|
organizationSlug?: string;
|
|
27
|
+
/** Active organization role as a normalized list. */
|
|
13
28
|
roles: string[];
|
|
14
29
|
}
|
|
15
30
|
/** Configures Clerk JWT verification and protected-resource metadata. */
|
|
16
31
|
export interface ClerkOAuthProviderOptions extends OAuthResourceOptions {
|
|
32
|
+
/** Clerk Frontend API URL used as the token issuer. */
|
|
17
33
|
frontendApiUrl: URL | string;
|
|
18
34
|
/** Expected Clerk access-token audience, when the application emits one. */
|
|
19
35
|
audience?: string;
|
|
@@ -23,5 +39,15 @@ export interface ClerkOAuthProviderOptions extends OAuthResourceOptions {
|
|
|
23
39
|
*
|
|
24
40
|
* @param options - Clerk frontend API URL, optional token audience, and resource-server settings.
|
|
25
41
|
* @returns A provider that verifies Clerk-issued access tokens and explicit resource claims.
|
|
42
|
+
* @throws A `TypeError` if `frontendApiUrl` is invalid or `audience` is empty.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { oauthClerkProvider } from "mcp-use/oauth/clerk";
|
|
47
|
+
*
|
|
48
|
+
* const oauth = oauthClerkProvider({
|
|
49
|
+
* frontendApiUrl: "https://example.clerk.accounts.dev",
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
26
52
|
*/
|
|
27
53
|
export declare function oauthClerkProvider(options: ClerkOAuthProviderOptions): OAuthProvider<ClerkOAuthUser>;
|