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 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
@@ -0,0 +1,5 @@
1
+ export { MCPAuth } from './mcp-auth';
2
+ export type { MCPAuthConfig, AuthToken, AuthProvider, AuthStorage, } from './types';
3
+ export { PROVIDERS } from './providers';
4
+ export { PROVIDERS as providers } from './providers';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -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"}
@@ -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,3 @@
1
+ import type { AuthProvider } from './types';
2
+ export declare const PROVIDERS: Record<string, AuthProvider>;
3
+ //# sourceMappingURL=providers.d.ts.map
@@ -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
+ };
@@ -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
@@ -0,0 +1,3 @@
1
+ // MCP-Auth: Universal Authentication for MCP Servers
2
+ // Type definitions
3
+ export {};
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
+ }