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
1.0.70
to
1.0.71
+8
-0
CHANGELOG.md
# @ai-sdk/mcp
## 1.0.71
### Patch Changes
- b0e77c0: Select MCP OAuth authorization scopes from `WWW-Authenticate` challenges or Protected Resource Metadata.
- Updated dependencies [31205a4]
- @ai-sdk/provider-utils@4.0.46
## 1.0.70

@@ -4,0 +12,0 @@

+2
-2
{
"name": "@ai-sdk/mcp",
"version": "1.0.70",
"version": "1.0.71",
"license": "Apache-2.0",

@@ -37,3 +37,3 @@ "sideEffects": false,

"@ai-sdk/provider": "3.0.15",
"@ai-sdk/provider-utils": "4.0.45"
"@ai-sdk/provider-utils": "4.0.46"
},

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

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

import {
extractResourceMetadataUrl,
extractWWWAuthenticateParams,
UnauthorizedError,

@@ -117,3 +117,6 @@ auth,

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

@@ -127,2 +130,3 @@ return Promise.resolve('REDIRECT');

resourceMetadataUrl,
scope,
fetchFn: this.fetchFn,

@@ -207,5 +211,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') {

@@ -419,5 +428,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') {

@@ -424,0 +438,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 @@ });

@@ -274,9 +274,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 =

@@ -286,22 +283,53 @@ response.headers.get('www-authenticate') ??

if (!header) {
return undefined;
return {};
}
const [type, scheme] = header.split(' ');
if (type.toLowerCase() !== 'bearer' || !scheme) {
return undefined;
if (type.replace(/,$/, '').toLowerCase() !== 'bearer' || !scheme) {
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

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

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