mcp-auth-core 0.1.0
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/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/mcp-auth.d.ts +19 -0
- package/dist/mcp-auth.d.ts.map +1 -0
- package/dist/mcp-auth.js +140 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +28 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/package.json +55 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 milisp
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# MCP Auth Core
|
2
|
+
|
3
|
+
Universal Authentication for MCP Servers - The standard that everyone should follow.
|
4
|
+
|
5
|
+
A lightweight, modular authentication library that provides OAuth2 support for popular providers like Google, GitHub, Slack, and Microsoft.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```bash
|
10
|
+
npm install mcp-auth-core
|
11
|
+
```
|
12
|
+
|
13
|
+
## Quick Start
|
14
|
+
|
15
|
+
```typescript
|
16
|
+
import { MCPAuth, PROVIDERS } from 'mcp-auth-core';
|
17
|
+
|
18
|
+
// Create auth instance
|
19
|
+
const auth = new MCPAuth();
|
20
|
+
|
21
|
+
// Register a service with Google OAuth
|
22
|
+
auth.registerService('my-app', {
|
23
|
+
clientId: 'your-google-client-id',
|
24
|
+
clientSecret: 'your-google-client-secret',
|
25
|
+
redirectUri: 'http://localhost:3000/callback',
|
26
|
+
scopes: ['profile', 'email'],
|
27
|
+
provider: PROVIDERS.google
|
28
|
+
});
|
29
|
+
|
30
|
+
// Get authorization URL
|
31
|
+
const authUrl = auth.getAuthUrl('my-app');
|
32
|
+
console.log('Visit this URL to authorize:', authUrl);
|
33
|
+
|
34
|
+
// Handle callback (in your server)
|
35
|
+
const token = await auth.handleCallback('my-app', authorizationCode);
|
36
|
+
|
37
|
+
// Make authenticated requests
|
38
|
+
const response = await auth.makeRequest('my-app', userId, 'https://api.example.com/data');
|
39
|
+
```
|
40
|
+
|
41
|
+
## Supported Providers
|
42
|
+
|
43
|
+
- **Google** - Full OAuth2 support with user info
|
44
|
+
- **GitHub** - OAuth2 with user profile
|
45
|
+
- **Slack** - OAuth2 for Slack apps
|
46
|
+
- **Microsoft** - Azure AD OAuth2
|
47
|
+
|
48
|
+
## Highlights
|
49
|
+
|
50
|
+
🎯 **MCP-Auth: The Universal Standard**
|
51
|
+
|
52
|
+
✅ No more custom OAuth for each service
|
53
|
+
✅ Automatic token refresh
|
54
|
+
✅ Secure storage
|
55
|
+
✅ Easy service integration
|
56
|
+
✅ One API to rule them all
|
57
|
+
|
58
|
+
## Features
|
59
|
+
|
60
|
+
- 🔐 **OAuth2 Support** - Complete OAuth2 flow implementation
|
61
|
+
- 🔄 **Token Refresh** - Automatic token refresh when expired
|
62
|
+
- 💾 **Flexible Storage** - Customizable token storage
|
63
|
+
- 🏗️ **Modular Design** - Easy to extend with custom providers
|
64
|
+
- 📦 **TypeScript** - Full TypeScript support with types
|
65
|
+
- 🌐 **Universal** - Works in Node.js and browser environments
|
66
|
+
|
67
|
+
## API Reference
|
68
|
+
|
69
|
+
### MCPAuth Class
|
70
|
+
|
71
|
+
The main authentication class that handles OAuth flows.
|
72
|
+
|
73
|
+
#### Constructor
|
74
|
+
```typescript
|
75
|
+
new MCPAuth(storage?: AuthStorage)
|
76
|
+
```
|
77
|
+
|
78
|
+
#### Methods
|
79
|
+
|
80
|
+
- `registerService(serviceId: string, config: MCPAuthConfig)` - Register a service configuration
|
81
|
+
- `getAuthUrl(serviceId: string, state?: string)` - Get authorization URL
|
82
|
+
- `handleCallback(serviceId: string, code: string)` - Handle OAuth callback
|
83
|
+
- `getToken(serviceId: string, userId: string)` - Get valid access token
|
84
|
+
- `makeRequest(serviceId: string, userId: string, url: string, options?)` - Make authenticated request
|
85
|
+
|
86
|
+
### Types
|
87
|
+
|
88
|
+
- `MCPAuthConfig` - Service configuration
|
89
|
+
- `AuthToken` - Token information
|
90
|
+
- `AuthProvider` - OAuth provider configuration
|
91
|
+
- `AuthStorage` - Storage interface for tokens
|
92
|
+
|
93
|
+
## Examples
|
94
|
+
|
95
|
+
See the `examples/` directory for complete usage examples.
|
96
|
+
|
97
|
+
## License
|
98
|
+
|
99
|
+
MIT
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,YAAY,EACV,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
// MCP-Auth: Universal Authentication for MCP Servers
|
2
|
+
// The standard that everyone should follow
|
3
|
+
// Export main class
|
4
|
+
export { MCPAuth } from './mcp-auth';
|
5
|
+
// Export built-in providers
|
6
|
+
export { PROVIDERS } from './providers';
|
7
|
+
// Re-export providers for convenience
|
8
|
+
export { PROVIDERS as providers } from './providers';
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { MCPAuthConfig, AuthToken, AuthStorage } from './types';
|
2
|
+
export declare class MCPAuth {
|
3
|
+
private storage?;
|
4
|
+
private tokens;
|
5
|
+
private configs;
|
6
|
+
constructor(storage?: AuthStorage | undefined);
|
7
|
+
registerService(serviceId: string, config: MCPAuthConfig): void;
|
8
|
+
getAuthUrl(serviceId: string, state?: string): string;
|
9
|
+
handleCallback(serviceId: string, code: string): Promise<AuthToken>;
|
10
|
+
getToken(serviceId: string, userId: string): Promise<string>;
|
11
|
+
makeRequest(serviceId: string, userId: string, url: string, options?: RequestInit): Promise<Response>;
|
12
|
+
private refreshToken;
|
13
|
+
private exchangeCodeForToken;
|
14
|
+
private getUserId;
|
15
|
+
private generateState;
|
16
|
+
private loadTokens;
|
17
|
+
private saveTokens;
|
18
|
+
}
|
19
|
+
//# sourceMappingURL=mcp-auth.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mcp-auth.d.ts","sourceRoot":"","sources":["../src/mcp-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAErE,qBAAa,OAAO;IAIN,OAAO,CAAC,OAAO,CAAC;IAH5B,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,OAAO,CAAyC;gBAEpC,OAAO,CAAC,EAAE,WAAW,YAAA;IAKzC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa;IAKxD,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAgB/C,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAqBnE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB5D,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YAYN,YAAY;YA+BZ,oBAAoB;YAqBpB,SAAS;IAcvB,OAAO,CAAC,aAAa;YAIP,UAAU;YAcV,UAAU;CAMzB"}
|
package/dist/mcp-auth.js
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
export class MCPAuth {
|
2
|
+
constructor(storage) {
|
3
|
+
this.storage = storage;
|
4
|
+
this.tokens = new Map();
|
5
|
+
this.configs = new Map();
|
6
|
+
this.loadTokens();
|
7
|
+
}
|
8
|
+
// Register a service configuration
|
9
|
+
registerService(serviceId, config) {
|
10
|
+
this.configs.set(serviceId, config);
|
11
|
+
}
|
12
|
+
// Get authorization URL - this is what the user clicks
|
13
|
+
getAuthUrl(serviceId, state) {
|
14
|
+
const config = this.configs.get(serviceId);
|
15
|
+
if (!config)
|
16
|
+
throw new Error(`Service ${serviceId} not configured`);
|
17
|
+
const params = new URLSearchParams({
|
18
|
+
client_id: config.clientId,
|
19
|
+
redirect_uri: config.redirectUri,
|
20
|
+
scope: config.scopes.join(" "),
|
21
|
+
response_type: "code",
|
22
|
+
state: state || this.generateState(),
|
23
|
+
});
|
24
|
+
return `${config.provider.authUrl}?${params.toString()}`;
|
25
|
+
}
|
26
|
+
// Handle the callback after user authorizes
|
27
|
+
async handleCallback(serviceId, code) {
|
28
|
+
const config = this.configs.get(serviceId);
|
29
|
+
if (!config)
|
30
|
+
throw new Error(`Service ${serviceId} not configured`);
|
31
|
+
const tokenData = await this.exchangeCodeForToken(config, code);
|
32
|
+
const token = {
|
33
|
+
accessToken: tokenData.access_token,
|
34
|
+
refreshToken: tokenData.refresh_token,
|
35
|
+
expiresAt: new Date(Date.now() + tokenData.expires_in * 1000),
|
36
|
+
scopes: config.scopes,
|
37
|
+
userId: await this.getUserId(config, tokenData.access_token),
|
38
|
+
};
|
39
|
+
const tokenKey = `${serviceId}:${token.userId}`;
|
40
|
+
this.tokens.set(tokenKey, token);
|
41
|
+
await this.saveTokens();
|
42
|
+
return token;
|
43
|
+
}
|
44
|
+
// Get valid token for a user and service
|
45
|
+
async getToken(serviceId, userId) {
|
46
|
+
const tokenKey = `${serviceId}:${userId}`;
|
47
|
+
let token = this.tokens.get(tokenKey);
|
48
|
+
if (!token) {
|
49
|
+
throw new Error(`No token found for ${serviceId}:${userId}`);
|
50
|
+
}
|
51
|
+
// Check if token is expired and refresh if needed
|
52
|
+
if (token.expiresAt < new Date() && token.refreshToken) {
|
53
|
+
token = await this.refreshToken(serviceId, token);
|
54
|
+
this.tokens.set(tokenKey, token);
|
55
|
+
await this.saveTokens();
|
56
|
+
}
|
57
|
+
return token.accessToken;
|
58
|
+
}
|
59
|
+
// Make authenticated request - this is the magic
|
60
|
+
async makeRequest(serviceId, userId, url, options = {}) {
|
61
|
+
const token = await this.getToken(serviceId, userId);
|
62
|
+
const headers = {
|
63
|
+
...options.headers,
|
64
|
+
Authorization: `Bearer ${token}`,
|
65
|
+
};
|
66
|
+
return fetch(url, { ...options, headers });
|
67
|
+
}
|
68
|
+
// Refresh expired token
|
69
|
+
async refreshToken(serviceId, token) {
|
70
|
+
const config = this.configs.get(serviceId);
|
71
|
+
if (!config || !token.refreshToken) {
|
72
|
+
throw new Error("Cannot refresh token");
|
73
|
+
}
|
74
|
+
const response = await fetch(config.provider.tokenUrl, {
|
75
|
+
method: "POST",
|
76
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
77
|
+
body: new URLSearchParams({
|
78
|
+
grant_type: "refresh_token",
|
79
|
+
refresh_token: token.refreshToken,
|
80
|
+
client_id: config.clientId,
|
81
|
+
client_secret: config.clientSecret || "",
|
82
|
+
}),
|
83
|
+
});
|
84
|
+
const tokenData = await response.json();
|
85
|
+
return {
|
86
|
+
...token,
|
87
|
+
accessToken: tokenData.access_token,
|
88
|
+
refreshToken: tokenData.refresh_token || token.refreshToken,
|
89
|
+
expiresAt: new Date(Date.now() + tokenData.expires_in * 1000),
|
90
|
+
};
|
91
|
+
}
|
92
|
+
// Exchange authorization code for token
|
93
|
+
async exchangeCodeForToken(config, code) {
|
94
|
+
const response = await fetch(config.provider.tokenUrl, {
|
95
|
+
method: "POST",
|
96
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
97
|
+
body: new URLSearchParams({
|
98
|
+
grant_type: "authorization_code",
|
99
|
+
code,
|
100
|
+
redirect_uri: config.redirectUri,
|
101
|
+
client_id: config.clientId,
|
102
|
+
client_secret: config.clientSecret || "",
|
103
|
+
}),
|
104
|
+
});
|
105
|
+
if (!response.ok) {
|
106
|
+
throw new Error(`Token exchange failed: ${response.statusText}`);
|
107
|
+
}
|
108
|
+
return response.json();
|
109
|
+
}
|
110
|
+
// Get user ID from provider
|
111
|
+
async getUserId(config, accessToken) {
|
112
|
+
if (!config.provider.userInfoUrl)
|
113
|
+
return "default";
|
114
|
+
const response = await fetch(config.provider.userInfoUrl, {
|
115
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
116
|
+
});
|
117
|
+
const userInfo = await response.json();
|
118
|
+
return userInfo.id || userInfo.login || userInfo.email || "default";
|
119
|
+
}
|
120
|
+
generateState() {
|
121
|
+
return Math.random().toString(36).substring(2, 15);
|
122
|
+
}
|
123
|
+
async loadTokens() {
|
124
|
+
if (this.storage) {
|
125
|
+
const saved = await this.storage.load();
|
126
|
+
if (saved) {
|
127
|
+
this.tokens = new Map(Object.entries(saved).map(([k, v]) => [
|
128
|
+
k,
|
129
|
+
{ ...v, expiresAt: new Date(v.expiresAt) },
|
130
|
+
]));
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
async saveTokens() {
|
135
|
+
if (this.storage) {
|
136
|
+
const toSave = Object.fromEntries(this.tokens.entries());
|
137
|
+
await this.storage.save(toSave);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA0BlD,CAAC"}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
// Built-in providers - the ones everyone actually uses
|
2
|
+
export const PROVIDERS = {
|
3
|
+
google: {
|
4
|
+
name: "Google",
|
5
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
6
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
7
|
+
userInfoUrl: "https://www.googleapis.com/oauth2/v2/userinfo",
|
8
|
+
revokeUrl: "https://oauth2.googleapis.com/revoke",
|
9
|
+
},
|
10
|
+
github: {
|
11
|
+
name: "GitHub",
|
12
|
+
authUrl: "https://github.com/login/oauth/authorize",
|
13
|
+
tokenUrl: "https://github.com/login/oauth/access_token",
|
14
|
+
userInfoUrl: "https://api.github.com/user",
|
15
|
+
},
|
16
|
+
slack: {
|
17
|
+
name: "Slack",
|
18
|
+
authUrl: "https://slack.com/oauth/v2/authorize",
|
19
|
+
tokenUrl: "https://slack.com/api/oauth.v2.access",
|
20
|
+
userInfoUrl: "https://slack.com/api/auth.test",
|
21
|
+
},
|
22
|
+
microsoft: {
|
23
|
+
name: "Microsoft",
|
24
|
+
authUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
25
|
+
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
26
|
+
userInfoUrl: "https://graph.microsoft.com/v1.0/me",
|
27
|
+
},
|
28
|
+
};
|
package/dist/types.d.ts
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
export interface MCPAuthConfig {
|
2
|
+
clientId: string;
|
3
|
+
clientSecret?: string;
|
4
|
+
redirectUri: string;
|
5
|
+
scopes: string[];
|
6
|
+
provider: AuthProvider;
|
7
|
+
}
|
8
|
+
export interface AuthToken {
|
9
|
+
accessToken: string;
|
10
|
+
refreshToken?: string;
|
11
|
+
expiresAt: Date;
|
12
|
+
scopes: string[];
|
13
|
+
userId: string;
|
14
|
+
}
|
15
|
+
export interface AuthProvider {
|
16
|
+
name: string;
|
17
|
+
authUrl: string;
|
18
|
+
tokenUrl: string;
|
19
|
+
userInfoUrl?: string;
|
20
|
+
revokeUrl?: string;
|
21
|
+
}
|
22
|
+
export interface AuthStorage {
|
23
|
+
save(tokens: Record<string, any>): Promise<void>;
|
24
|
+
load(): Promise<Record<string, any> | null>;
|
25
|
+
}
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;CAC7C"}
|
package/dist/types.js
ADDED
package/package.json
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
{
|
2
|
+
"name": "mcp-auth-core",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"description": "Universal Authentication for MCP Servers - The standard that everyone should follow",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"types": "dist/index.d.ts",
|
7
|
+
"module": "dist/index.js",
|
8
|
+
"exports": {
|
9
|
+
".": {
|
10
|
+
"import": "./dist/index.js",
|
11
|
+
"require": "./dist/index.js",
|
12
|
+
"types": "./dist/index.d.ts"
|
13
|
+
}
|
14
|
+
},
|
15
|
+
"files": [
|
16
|
+
"dist",
|
17
|
+
"README.md",
|
18
|
+
"LICENSE"
|
19
|
+
],
|
20
|
+
"type": "module",
|
21
|
+
"scripts": {
|
22
|
+
"build": "tsc",
|
23
|
+
"dev": "tsc --watch",
|
24
|
+
"clean": "rm -rf dist",
|
25
|
+
"prepublishOnly": "npm run clean && npm run build",
|
26
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
27
|
+
},
|
28
|
+
"keywords": [
|
29
|
+
"mcp",
|
30
|
+
"authentication",
|
31
|
+
"oauth",
|
32
|
+
"oauth2",
|
33
|
+
"auth",
|
34
|
+
"google",
|
35
|
+
"github",
|
36
|
+
"slack",
|
37
|
+
"microsoft"
|
38
|
+
],
|
39
|
+
"author": "milisp",
|
40
|
+
"license": "MIT",
|
41
|
+
"repository": {
|
42
|
+
"type": "git",
|
43
|
+
"url": "git+https://github.com/milisp/mcp-auth-core.git"
|
44
|
+
},
|
45
|
+
"bugs": {
|
46
|
+
"url": "https://github.com/milisp/mcp-auth-core/issues"
|
47
|
+
},
|
48
|
+
"homepage": "https://github.com/milisp/mcp-auth-core#readme",
|
49
|
+
"devDependencies": {
|
50
|
+
"typescript": "^5.0.0"
|
51
|
+
},
|
52
|
+
"engines": {
|
53
|
+
"node": ">=18.0.0"
|
54
|
+
}
|
55
|
+
}
|