Sign In

@ai-sdk/mcp

Package Overview
Dependencies
Maintainers
3
Versions
260
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ai-sdk/mcp - npm Package Compare versions

Comparing version
2.0.31
to
2.0.32
+6
-0
CHANGELOG.md
# @ai-sdk/mcp
## 2.0.32
### Patch Changes
- 1011e33: Select MCP OAuth authorization scopes from `WWW-Authenticate` challenges or Protected Resource Metadata.
## 2.0.31

@@ -4,0 +10,0 @@

+3
-3
{
"name": "@ai-sdk/mcp",
"version": "2.0.31",
"version": "2.0.32",
"type": "module",

@@ -35,4 +35,4 @@ "license": "Apache-2.0",

"pkce-challenge": "^5.0.1",
"@ai-sdk/provider": "4.0.7",
"@ai-sdk/provider-utils": "5.0.27"
"@ai-sdk/provider-utils": "5.0.27",
"@ai-sdk/provider": "4.0.7"
},

@@ -39,0 +39,0 @@ "devDependencies": {

@@ -16,3 +16,3 @@ import {

import {
extractResourceMetadataUrl,
extractWWWAuthenticateParams,
UnauthorizedError,

@@ -163,3 +163,6 @@ auth,

*/
private authorizeOnce(resourceMetadataUrl?: URL): Promise<AuthResult> {
private authorizeOnce(
resourceMetadataUrl?: URL,
scope?: string,
): Promise<AuthResult> {
if (!this.authProvider) {

@@ -173,2 +176,3 @@ return Promise.resolve('REDIRECT');

resourceMetadataUrl,
scope,
fetchFn: this.fetchFn,

@@ -262,5 +266,10 @@ }).finally(() => {

if (response.status === 401 && this.authProvider && !triedAuth) {
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
const { resourceMetadataUrl, scope } =
extractWWWAuthenticateParams(response);
this.resourceMetadataUrl = resourceMetadataUrl;
try {
const result = await this.authorizeOnce(this.resourceMetadataUrl);
const result = await this.authorizeOnce(
this.resourceMetadataUrl,
scope,
);
if (result !== 'AUTHORIZED') {

@@ -480,5 +489,10 @@ const error = new UnauthorizedError();

if (response.status === 401 && this.authProvider && !triedAuth) {
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
const { resourceMetadataUrl, scope } =
extractWWWAuthenticateParams(response);
this.resourceMetadataUrl = resourceMetadataUrl;
try {
const result = await this.authorizeOnce(this.resourceMetadataUrl);
const result = await this.authorizeOnce(
this.resourceMetadataUrl,
scope,
);
if (result !== 'AUTHORIZED') {

@@ -485,0 +499,0 @@ const error = new UnauthorizedError();

@@ -12,3 +12,3 @@ import {

import {
extractResourceMetadataUrl,
extractWWWAuthenticateParams,
UnauthorizedError,

@@ -110,3 +110,5 @@ auth,

if (response.status === 401 && this.authProvider && !triedAuth) {
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
const { resourceMetadataUrl, scope } =
extractWWWAuthenticateParams(response);
this.resourceMetadataUrl = resourceMetadataUrl;
try {

@@ -116,2 +118,3 @@ const result = await auth(this.authProvider, {

resourceMetadataUrl: this.resourceMetadataUrl,
scope,
fetchFn: this.fetchFn,

@@ -279,3 +282,5 @@ });

if (response.status === 401 && this.authProvider && !triedAuth) {
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
const { resourceMetadataUrl, scope } =
extractWWWAuthenticateParams(response);
this.resourceMetadataUrl = resourceMetadataUrl;
try {

@@ -285,2 +290,3 @@ const result = await auth(this.authProvider, {

resourceMetadataUrl: this.resourceMetadataUrl,
scope,
fetchFn: this.fetchFn,

@@ -287,0 +293,0 @@ });

@@ -273,9 +273,6 @@ import pkceChallenge from 'pkce-challenge';

/**
* Extracts the OAuth 2.0 Protected Resource Metadata URL from a WWW-Authenticate header (RFC9728).
* Looks for a resource="..." parameter.
*/
export function extractResourceMetadataUrl(
response: Response,
): URL | undefined {
export function extractWWWAuthenticateParams(response: Response): {
resourceMetadataUrl?: URL;
scope?: string;
} {
const header =

@@ -285,3 +282,3 @@ response.headers.get('www-authenticate') ??

if (!header) {
return undefined;
return {};
}

@@ -291,17 +288,48 @@

if (type.toLowerCase() !== 'bearer' || !scheme) {
return undefined;
return {};
}
// regex taken from MCP spec
const regex = /resource_metadata="([^"]*)"/;
const match = header.match(regex);
if (!match) {
return undefined;
}
const resourceMetadataMatch = header.match(
/(?:^|[,\s])resource_metadata="([^"]*)"/i,
);
const scope = header.match(/(?:^|[,\s])scope="([^"]*)"/i)?.[1];
let resourceMetadataUrl: URL | undefined;
try {
return new URL(match[1]);
} catch {
return undefined;
resourceMetadataUrl = resourceMetadataMatch
? new URL(resourceMetadataMatch[1])
: undefined;
} catch {}
return { resourceMetadataUrl, scope };
}
/**
* Extracts the OAuth 2.0 Protected Resource Metadata URL from a WWW-Authenticate header (RFC9728).
*/
export function extractResourceMetadataUrl(
response: Response,
): URL | undefined {
return extractWWWAuthenticateParams(response).resourceMetadataUrl;
}
function selectScope({
scope,
resourceMetadata,
clientMetadata,
}: {
scope?: string;
resourceMetadata?: OAuthProtectedResourceMetadata;
clientMetadata: OAuthClientMetadata;
}): string | undefined {
if (scope) {
return scope;
}
const resourceScopes = resourceMetadata?.scopes_supported?.join(' ');
if (resourceScopes) {
return resourceScopes;
}
return clientMetadata.scope;
}

@@ -1314,3 +1342,7 @@

redirectUrl: provider.redirectUrl,
scope: scope || provider.clientMetadata.scope,
scope: selectScope({
scope,
resourceMetadata,
clientMetadata: provider.clientMetadata,
}),
resource,

@@ -1317,0 +1349,0 @@ },

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display