@prmichaelsen/mcp-auth 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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/auth/base-provider.js +173 -0
  4. package/dist/auth/base-provider.js.map +7 -0
  5. package/dist/auth/index.js +11 -0
  6. package/dist/auth/index.js.map +7 -0
  7. package/dist/auth/providers/env-provider.js +71 -0
  8. package/dist/auth/providers/env-provider.js.map +7 -0
  9. package/dist/auth/providers/index.js +11 -0
  10. package/dist/auth/providers/index.js.map +7 -0
  11. package/dist/auth/providers/simple-resolver.js +185 -0
  12. package/dist/auth/providers/simple-resolver.js.map +7 -0
  13. package/dist/auth/types.js +1 -0
  14. package/dist/auth/types.js.map +7 -0
  15. package/dist/index.js +111 -0
  16. package/dist/index.js.map +7 -0
  17. package/dist/server/config.js +1 -0
  18. package/dist/server/config.js.map +7 -0
  19. package/dist/server/decorators.js +149 -0
  20. package/dist/server/decorators.js.map +7 -0
  21. package/dist/server/index.js +25 -0
  22. package/dist/server/index.js.map +7 -0
  23. package/dist/server/mcp-server.js +269 -0
  24. package/dist/server/mcp-server.js.map +7 -0
  25. package/dist/server/tool.js +66 -0
  26. package/dist/server/tool.js.map +7 -0
  27. package/dist/types.js +1 -0
  28. package/dist/types.js.map +7 -0
  29. package/dist/utils/errors.js +143 -0
  30. package/dist/utils/errors.js.map +7 -0
  31. package/dist/utils/index.js +81 -0
  32. package/dist/utils/index.js.map +7 -0
  33. package/dist/utils/logger.js +200 -0
  34. package/dist/utils/logger.js.map +7 -0
  35. package/dist/utils/validation.js +172 -0
  36. package/dist/utils/validation.js.map +7 -0
  37. package/dist/wrapper/config.js +1 -0
  38. package/dist/wrapper/config.js.map +7 -0
  39. package/dist/wrapper/index.js +10 -0
  40. package/dist/wrapper/index.js.map +7 -0
  41. package/dist/wrapper/server-wrapper.js +427 -0
  42. package/dist/wrapper/server-wrapper.js.map +7 -0
  43. package/package.json +93 -0
@@ -0,0 +1,269 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import {
4
+ ListToolsRequestSchema,
5
+ CallToolRequestSchema
6
+ } from "@modelcontextprotocol/sdk/types.js";
7
+ import { AuthenticatedTool } from "./tool.js";
8
+ import { ConfigurationError, TransportError } from "../utils/errors.js";
9
+ import { createLogger } from "../utils/logger.js";
10
+ import { validateResourceType } from "../utils/validation.js";
11
+ class AuthenticatedMCPServer {
12
+ config;
13
+ mcpServer;
14
+ logger;
15
+ tools;
16
+ isRunning = false;
17
+ constructor(config) {
18
+ this.validateConfig(config);
19
+ this.config = this.normalizeConfig(config);
20
+ this.logger = createLogger(this.config.middleware.logging);
21
+ this.tools = /* @__PURE__ */ new Map();
22
+ this.mcpServer = new Server(
23
+ {
24
+ name: this.config.name,
25
+ version: this.config.version
26
+ },
27
+ {
28
+ capabilities: {
29
+ tools: {}
30
+ }
31
+ }
32
+ );
33
+ this.registerMCPHandlers();
34
+ this.logger.info("AuthenticatedMCPServer created", {
35
+ name: this.config.name,
36
+ version: this.config.version,
37
+ resourceType: this.config.resourceType,
38
+ transport: this.config.transport.type
39
+ });
40
+ }
41
+ /**
42
+ * Validate server configuration
43
+ */
44
+ validateConfig(config) {
45
+ if (!config.authProvider) {
46
+ throw new ConfigurationError("authProvider is required");
47
+ }
48
+ if (!config.tokenResolver) {
49
+ throw new ConfigurationError("tokenResolver is required");
50
+ }
51
+ if (!config.resourceType) {
52
+ throw new ConfigurationError("resourceType is required");
53
+ }
54
+ if (!config.transport) {
55
+ throw new ConfigurationError("transport is required");
56
+ }
57
+ validateResourceType(config.resourceType);
58
+ }
59
+ /**
60
+ * Normalize configuration with defaults
61
+ */
62
+ normalizeConfig(config) {
63
+ return {
64
+ name: config.name ?? "mcp-server",
65
+ version: config.version ?? "1.0.0",
66
+ authProvider: config.authProvider,
67
+ tokenResolver: config.tokenResolver,
68
+ resourceType: config.resourceType,
69
+ transport: config.transport,
70
+ middleware: {
71
+ rateLimit: config.middleware?.rateLimit,
72
+ logging: config.middleware?.logging ?? { enabled: true, level: "info" }
73
+ },
74
+ requestTimeoutMs: config.requestTimeoutMs ?? 3e4,
75
+ enableTracing: config.enableTracing ?? false,
76
+ errorHandler: config.errorHandler
77
+ };
78
+ }
79
+ /**
80
+ * Register MCP protocol handlers
81
+ */
82
+ registerMCPHandlers() {
83
+ this.mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
84
+ const tools = Array.from(this.tools.values()).map((tool) => ({
85
+ name: tool.name,
86
+ description: tool.description,
87
+ inputSchema: tool.inputSchema
88
+ }));
89
+ this.logger.debug("Listing tools", { count: tools.length });
90
+ return { tools };
91
+ });
92
+ this.mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
93
+ const { name, arguments: args } = request.params;
94
+ this.logger.info("Tool called", { toolName: name });
95
+ const tool = this.tools.get(name);
96
+ if (!tool) {
97
+ throw new Error(`Unknown tool: ${name}`);
98
+ }
99
+ const context = {
100
+ transport: this.config.transport.type,
101
+ timestamp: /* @__PURE__ */ new Date(),
102
+ metadata: { toolName: name }
103
+ };
104
+ const result = await tool.handler(
105
+ args,
106
+ context,
107
+ this.config.authProvider,
108
+ this.config.tokenResolver,
109
+ this.config.resourceType
110
+ );
111
+ return {
112
+ content: [
113
+ {
114
+ type: "text",
115
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
116
+ }
117
+ ]
118
+ };
119
+ });
120
+ }
121
+ /**
122
+ * Register a tool with authentication
123
+ *
124
+ * @param name - Tool name
125
+ * @param handler - Authenticated tool handler
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {
130
+ * return getData(args, accessToken);
131
+ * }));
132
+ * ```
133
+ */
134
+ registerTool(name, handler, options) {
135
+ if (this.tools.has(name)) {
136
+ throw new ConfigurationError(`Tool '${name}' is already registered`);
137
+ }
138
+ this.tools.set(name, {
139
+ name,
140
+ description: options?.description,
141
+ inputSchema: options?.inputSchema,
142
+ handler
143
+ });
144
+ this.logger.debug("Tool registered", { name });
145
+ }
146
+ /**
147
+ * Register a Tool class instance
148
+ *
149
+ * @param tool - Tool or AuthenticatedTool instance
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * server.registerToolClass(new AuthenticatedTool(new GetProfileTool()));
154
+ * ```
155
+ */
156
+ registerToolClass(tool) {
157
+ const authenticatedTool = tool instanceof AuthenticatedTool ? tool : new AuthenticatedTool(tool);
158
+ const handler = async (args, context, authProvider, tokenResolver, resourceType) => {
159
+ return authenticatedTool.execute(args, context, authProvider, tokenResolver, resourceType);
160
+ };
161
+ this.registerTool(authenticatedTool.name, handler, {
162
+ description: authenticatedTool.description,
163
+ inputSchema: authenticatedTool.inputSchema
164
+ });
165
+ }
166
+ /**
167
+ * Register multiple tools at once
168
+ *
169
+ * @param tools - Array of Tool or AuthenticatedTool instances
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * server.registerTools([
174
+ * new AuthenticatedTool(new GetProfileTool()),
175
+ * new AuthenticatedTool(new GetMediaTool())
176
+ * ]);
177
+ * ```
178
+ */
179
+ registerTools(tools) {
180
+ for (const tool of tools) {
181
+ this.registerToolClass(tool);
182
+ }
183
+ }
184
+ /**
185
+ * Start the server
186
+ */
187
+ async start() {
188
+ if (this.isRunning) {
189
+ throw new ConfigurationError("Server is already running");
190
+ }
191
+ this.logger.info("Starting authenticated MCP server");
192
+ if (this.config.authProvider.initialize) {
193
+ await this.config.authProvider.initialize();
194
+ this.logger.debug("Auth provider initialized");
195
+ }
196
+ if (this.config.tokenResolver.initialize) {
197
+ await this.config.tokenResolver.initialize();
198
+ this.logger.debug("Token resolver initialized");
199
+ }
200
+ switch (this.config.transport.type) {
201
+ case "stdio":
202
+ await this.startStdioTransport();
203
+ break;
204
+ case "sse":
205
+ case "http":
206
+ throw new TransportError(
207
+ "SSE/HTTP transports not yet implemented for tool-level auth. Use server wrapping pattern for remote transports."
208
+ );
209
+ default:
210
+ throw new TransportError(`Unsupported transport: ${this.config.transport.type}`);
211
+ }
212
+ this.isRunning = true;
213
+ this.logger.info("Server started successfully", {
214
+ name: this.config.name,
215
+ transport: this.config.transport.type,
216
+ toolCount: this.tools.size
217
+ });
218
+ }
219
+ /**
220
+ * Stop the server
221
+ */
222
+ async stop() {
223
+ if (!this.isRunning) {
224
+ return;
225
+ }
226
+ this.logger.info("Stopping server");
227
+ await this.mcpServer.close();
228
+ if (this.config.authProvider.cleanup) {
229
+ await this.config.authProvider.cleanup();
230
+ }
231
+ if (this.config.tokenResolver.cleanup) {
232
+ await this.config.tokenResolver.cleanup();
233
+ }
234
+ this.isRunning = false;
235
+ this.logger.info("Server stopped");
236
+ }
237
+ /**
238
+ * Start stdio transport
239
+ */
240
+ async startStdioTransport() {
241
+ this.logger.info("Starting stdio transport");
242
+ const transport = new StdioServerTransport();
243
+ await this.mcpServer.connect(transport);
244
+ this.logger.info("Stdio transport connected");
245
+ }
246
+ /**
247
+ * Get server statistics
248
+ */
249
+ getStats() {
250
+ return {
251
+ name: this.config.name,
252
+ version: this.config.version,
253
+ resourceType: this.config.resourceType,
254
+ transport: this.config.transport.type,
255
+ toolCount: this.tools.size,
256
+ isRunning: this.isRunning
257
+ };
258
+ }
259
+ /**
260
+ * Get list of registered tool names
261
+ */
262
+ getToolNames() {
263
+ return Array.from(this.tools.keys());
264
+ }
265
+ }
266
+ export {
267
+ AuthenticatedMCPServer
268
+ };
269
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/server/mcp-server.ts"],
4
+ "sourcesContent": ["/**\n * Authenticated MCP Server implementation\n * \n * MCP server with integrated authentication for tool-level auth pattern.\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n type CallToolRequest\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { ServerConfig, NormalizedServerConfig } from './config.js';\nimport type { RequestContext, ToolHandler } from '../types.js';\nimport type { AuthenticatedToolHandler } from './decorators.js';\nimport { AuthenticatedTool, type Tool } from './tool.js';\nimport { ConfigurationError, TransportError } from '../utils/errors.js';\nimport { createLogger, type Logger } from '../utils/logger.js';\nimport { validateResourceType } from '../utils/validation.js';\n\n/**\n * Tool registration entry\n */\ninterface ToolRegistration {\n name: string;\n description?: string;\n inputSchema?: object;\n handler: AuthenticatedToolHandler;\n}\n\n/**\n * Authenticated MCP Server\n * \n * MCP server with integrated authentication support.\n * Use this for building new MCP servers with tool-level authentication.\n * \n * @example\n * ```typescript\n * const server = new AuthenticatedMCPServer({\n * name: 'my-server',\n * authProvider: new EnvAuthProvider(),\n * tokenResolver: new SimpleTokenResolver({ tokenEnvVar: 'API_TOKEN' }),\n * resourceType: 'myapi',\n * transport: { type: 'stdio' }\n * });\n * \n * server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {\n * const client = new APIClient(accessToken);\n * return client.getData(args);\n * }));\n * \n * await server.start();\n * ```\n */\nexport class AuthenticatedMCPServer {\n private config: NormalizedServerConfig;\n private mcpServer: Server;\n private logger: Logger;\n private tools: Map<string, ToolRegistration>;\n private isRunning: boolean = false;\n \n constructor(config: ServerConfig) {\n // Validate configuration\n this.validateConfig(config);\n \n // Normalize configuration\n this.config = this.normalizeConfig(config);\n \n // Initialize logger\n this.logger = createLogger(this.config.middleware.logging);\n \n // Initialize tools map\n this.tools = new Map();\n \n // Create MCP server\n this.mcpServer = new Server(\n {\n name: this.config.name,\n version: this.config.version\n },\n {\n capabilities: {\n tools: {}\n }\n }\n );\n \n // Register MCP handlers\n this.registerMCPHandlers();\n \n this.logger.info('AuthenticatedMCPServer created', {\n name: this.config.name,\n version: this.config.version,\n resourceType: this.config.resourceType,\n transport: this.config.transport.type\n });\n }\n \n /**\n * Validate server configuration\n */\n private validateConfig(config: ServerConfig): void {\n if (!config.authProvider) {\n throw new ConfigurationError('authProvider is required');\n }\n if (!config.tokenResolver) {\n throw new ConfigurationError('tokenResolver is required');\n }\n if (!config.resourceType) {\n throw new ConfigurationError('resourceType is required');\n }\n if (!config.transport) {\n throw new ConfigurationError('transport is required');\n }\n \n validateResourceType(config.resourceType);\n }\n \n /**\n * Normalize configuration with defaults\n */\n private normalizeConfig(config: ServerConfig): NormalizedServerConfig {\n return {\n name: config.name ?? 'mcp-server',\n version: config.version ?? '1.0.0',\n authProvider: config.authProvider,\n tokenResolver: config.tokenResolver,\n resourceType: config.resourceType,\n transport: config.transport,\n middleware: {\n rateLimit: config.middleware?.rateLimit,\n logging: config.middleware?.logging ?? { enabled: true, level: 'info' }\n },\n requestTimeoutMs: config.requestTimeoutMs ?? 30000,\n enableTracing: config.enableTracing ?? false,\n errorHandler: config.errorHandler\n };\n }\n \n /**\n * Register MCP protocol handlers\n */\n private registerMCPHandlers(): void {\n // List tools handler\n this.mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {\n const tools = Array.from(this.tools.values()).map(tool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema\n }));\n \n this.logger.debug('Listing tools', { count: tools.length });\n \n return { tools };\n });\n \n // Call tool handler\n this.mcpServer.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => {\n const { name, arguments: args } = request.params;\n \n this.logger.info('Tool called', { toolName: name });\n \n const tool = this.tools.get(name);\n \n if (!tool) {\n throw new Error(`Unknown tool: ${name}`);\n }\n \n // Create request context\n // Note: For stdio, we don't have headers, so context is minimal\n const context: RequestContext = {\n transport: this.config.transport.type,\n timestamp: new Date(),\n metadata: { toolName: name }\n };\n \n // Execute tool with authentication\n const result = await tool.handler(\n args,\n context,\n this.config.authProvider,\n this.config.tokenResolver,\n this.config.resourceType\n );\n \n // Return MCP-formatted response\n return {\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)\n }\n ]\n };\n });\n }\n \n /**\n * Register a tool with authentication\n * \n * @param name - Tool name\n * @param handler - Authenticated tool handler\n * \n * @example\n * ```typescript\n * server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {\n * return getData(args, accessToken);\n * }));\n * ```\n */\n registerTool<TArgs = any, TResult = any>(\n name: string,\n handler: AuthenticatedToolHandler<TArgs, TResult>,\n options?: {\n description?: string;\n inputSchema?: object;\n }\n ): void {\n if (this.tools.has(name)) {\n throw new ConfigurationError(`Tool '${name}' is already registered`);\n }\n \n this.tools.set(name, {\n name,\n description: options?.description,\n inputSchema: options?.inputSchema,\n handler\n });\n \n this.logger.debug('Tool registered', { name });\n }\n \n /**\n * Register a Tool class instance\n * \n * @param tool - Tool or AuthenticatedTool instance\n * \n * @example\n * ```typescript\n * server.registerToolClass(new AuthenticatedTool(new GetProfileTool()));\n * ```\n */\n registerToolClass(tool: Tool | AuthenticatedTool): void {\n const authenticatedTool = tool instanceof AuthenticatedTool \n ? tool \n : new AuthenticatedTool(tool);\n \n const handler: AuthenticatedToolHandler = async (args, context, authProvider, tokenResolver, resourceType) => {\n return authenticatedTool.execute(args, context, authProvider, tokenResolver, resourceType);\n };\n \n this.registerTool(authenticatedTool.name, handler, {\n description: authenticatedTool.description,\n inputSchema: authenticatedTool.inputSchema\n });\n }\n \n /**\n * Register multiple tools at once\n * \n * @param tools - Array of Tool or AuthenticatedTool instances\n * \n * @example\n * ```typescript\n * server.registerTools([\n * new AuthenticatedTool(new GetProfileTool()),\n * new AuthenticatedTool(new GetMediaTool())\n * ]);\n * ```\n */\n registerTools(tools: Array<Tool | AuthenticatedTool>): void {\n for (const tool of tools) {\n this.registerToolClass(tool);\n }\n }\n \n /**\n * Start the server\n */\n async start(): Promise<void> {\n if (this.isRunning) {\n throw new ConfigurationError('Server is already running');\n }\n \n this.logger.info('Starting authenticated MCP server');\n \n // Initialize auth provider\n if (this.config.authProvider.initialize) {\n await this.config.authProvider.initialize();\n this.logger.debug('Auth provider initialized');\n }\n \n // Initialize token resolver\n if (this.config.tokenResolver.initialize) {\n await this.config.tokenResolver.initialize();\n this.logger.debug('Token resolver initialized');\n }\n \n // Start transport\n switch (this.config.transport.type) {\n case 'stdio':\n await this.startStdioTransport();\n break;\n case 'sse':\n case 'http':\n throw new TransportError(\n 'SSE/HTTP transports not yet implemented for tool-level auth. ' +\n 'Use server wrapping pattern for remote transports.'\n );\n default:\n throw new TransportError(`Unsupported transport: ${this.config.transport.type}`);\n }\n \n this.isRunning = true;\n \n this.logger.info('Server started successfully', {\n name: this.config.name,\n transport: this.config.transport.type,\n toolCount: this.tools.size\n });\n }\n \n /**\n * Stop the server\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n \n this.logger.info('Stopping server');\n \n // Close MCP server\n await this.mcpServer.close();\n \n // Cleanup auth provider\n if (this.config.authProvider.cleanup) {\n await this.config.authProvider.cleanup();\n }\n \n // Cleanup token resolver\n if (this.config.tokenResolver.cleanup) {\n await this.config.tokenResolver.cleanup();\n }\n \n this.isRunning = false;\n \n this.logger.info('Server stopped');\n }\n \n /**\n * Start stdio transport\n */\n private async startStdioTransport(): Promise<void> {\n this.logger.info('Starting stdio transport');\n \n const transport = new StdioServerTransport();\n await this.mcpServer.connect(transport);\n \n this.logger.info('Stdio transport connected');\n }\n \n /**\n * Get server statistics\n */\n getStats(): {\n name: string;\n version: string;\n resourceType: string;\n transport: string;\n toolCount: number;\n isRunning: boolean;\n } {\n return {\n name: this.config.name,\n version: this.config.version,\n resourceType: this.config.resourceType,\n transport: this.config.transport.type,\n toolCount: this.tools.size,\n isRunning: this.isRunning\n };\n }\n \n /**\n * Get list of registered tool names\n */\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,66 @@
1
+ import { AuthenticationError, TokenResolutionError } from "../utils/errors.js";
2
+ import { validateUserId, validateAccessToken } from "../utils/validation.js";
3
+ class AuthenticatedTool {
4
+ constructor(tool, options) {
5
+ this.tool = tool;
6
+ this.options = options;
7
+ }
8
+ /**
9
+ * Get tool name
10
+ */
11
+ get name() {
12
+ return this.tool.name;
13
+ }
14
+ /**
15
+ * Get tool description
16
+ */
17
+ get description() {
18
+ return this.tool.description;
19
+ }
20
+ /**
21
+ * Get tool input schema
22
+ */
23
+ get inputSchema() {
24
+ return this.tool.inputSchema;
25
+ }
26
+ /**
27
+ * Execute tool with authentication
28
+ *
29
+ * @param args - Tool arguments
30
+ * @param context - Request context
31
+ * @param authProvider - Authentication provider
32
+ * @param tokenResolver - Token resolver
33
+ * @param resourceType - Resource type
34
+ * @returns Tool result
35
+ */
36
+ async execute(args, context, authProvider, tokenResolver, resourceType) {
37
+ const requiresAuth = this.options?.requiresAuth ?? true;
38
+ if (!requiresAuth) {
39
+ return this.tool.execute(args, "", "");
40
+ }
41
+ const authResult = await authProvider.authenticate(context);
42
+ if (!authResult.authenticated || !authResult.userId) {
43
+ throw new AuthenticationError(
44
+ authResult.error || "Authentication failed",
45
+ { tool: this.tool.name }
46
+ );
47
+ }
48
+ const userId = validateUserId(authResult.userId);
49
+ const accessToken = await tokenResolver.resolveToken(userId, resourceType);
50
+ if (!accessToken) {
51
+ throw new TokenResolutionError(userId, resourceType, {
52
+ tool: this.tool.name
53
+ });
54
+ }
55
+ validateAccessToken(accessToken);
56
+ return this.tool.execute(args, accessToken, userId);
57
+ }
58
+ }
59
+ function createAuthenticatedTool(tool, options) {
60
+ return new AuthenticatedTool(tool, options);
61
+ }
62
+ export {
63
+ AuthenticatedTool,
64
+ createAuthenticatedTool
65
+ };
66
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/server/tool.ts"],
4
+ "sourcesContent": ["/**\n * Tool interface and wrapper for tool-level authentication\n * \n * Provides class-based tool definitions with authentication support.\n */\n\nimport type { RequestContext } from '../types.js';\nimport type { AuthProvider, ResourceTokenResolver } from '../auth/types.js';\nimport { AuthenticationError, TokenResolutionError } from '../utils/errors.js';\nimport { validateUserId, validateAccessToken } from '../utils/validation.js';\n\n/**\n * Tool interface for class-based tools\n * \n * Implement this interface to create structured, reusable tools.\n * \n * @example\n * ```typescript\n * class GetProfileTool implements Tool {\n * name = 'get_profile';\n * description = 'Get user profile';\n * \n * inputSchema = {\n * type: 'object',\n * properties: {\n * userId: { type: 'string' }\n * }\n * };\n * \n * async execute(args: { userId: string }, accessToken: string, userId: string) {\n * const client = new APIClient(accessToken);\n * return client.getProfile(args.userId);\n * }\n * }\n * ```\n */\nexport interface Tool<TArgs = any, TResult = any> {\n /**\n * Tool name (must be unique within server)\n */\n name: string;\n \n /**\n * Tool description for clients\n */\n description?: string;\n \n /**\n * JSON Schema for tool input validation\n */\n inputSchema?: object;\n \n /**\n * Execute the tool with authenticated context\n * \n * @param args - Tool arguments\n * @param accessToken - Resource-specific access token\n * @param userId - Authenticated user ID\n * @returns Tool result\n */\n execute(args: TArgs, accessToken: string, userId: string): Promise<TResult>;\n}\n\n/**\n * Authenticated tool wrapper\n * \n * Wraps a Tool implementation with automatic authentication.\n * Handles auth provider and token resolver calls before executing the tool.\n * \n * @example\n * ```typescript\n * const tool = new AuthenticatedTool(new GetProfileTool());\n * server.registerTool(tool);\n * ```\n */\nexport class AuthenticatedTool<TArgs = any, TResult = any> {\n constructor(\n private tool: Tool<TArgs, TResult>,\n private options?: {\n /**\n * Whether authentication is required\n * @default true\n */\n requiresAuth?: boolean;\n }\n ) {}\n \n /**\n * Get tool name\n */\n get name(): string {\n return this.tool.name;\n }\n \n /**\n * Get tool description\n */\n get description(): string | undefined {\n return this.tool.description;\n }\n \n /**\n * Get tool input schema\n */\n get inputSchema(): object | undefined {\n return this.tool.inputSchema;\n }\n \n /**\n * Execute tool with authentication\n * \n * @param args - Tool arguments\n * @param context - Request context\n * @param authProvider - Authentication provider\n * @param tokenResolver - Token resolver\n * @param resourceType - Resource type\n * @returns Tool result\n */\n async execute(\n args: TArgs,\n context: RequestContext,\n authProvider: AuthProvider,\n tokenResolver: ResourceTokenResolver,\n resourceType: string\n ): Promise<TResult> {\n // Check if auth is required\n const requiresAuth = this.options?.requiresAuth ?? true;\n \n if (!requiresAuth) {\n // Execute without auth (use empty values)\n return this.tool.execute(args, '', '');\n }\n \n // 1. Authenticate request\n const authResult = await authProvider.authenticate(context);\n \n if (!authResult.authenticated || !authResult.userId) {\n throw new AuthenticationError(\n authResult.error || 'Authentication failed',\n { tool: this.tool.name }\n );\n }\n \n const userId = validateUserId(authResult.userId);\n \n // 2. Resolve resource token\n const accessToken = await tokenResolver.resolveToken(userId, resourceType);\n \n if (!accessToken) {\n throw new TokenResolutionError(userId, resourceType, {\n tool: this.tool.name\n });\n }\n \n validateAccessToken(accessToken);\n \n // 3. Execute tool\n return this.tool.execute(args, accessToken, userId);\n }\n}\n\n/**\n * Create an authenticated tool from a Tool implementation\n * \n * Helper function for creating authenticated tools.\n * \n * @param tool - Tool implementation\n * @param options - Authentication options\n * @returns Authenticated tool wrapper\n * \n * @example\n * ```typescript\n * const tool = createAuthenticatedTool(new GetProfileTool());\n * server.registerTool(tool);\n * ```\n */\nexport function createAuthenticatedTool<TArgs = any, TResult = any>(\n tool: Tool<TArgs, TResult>,\n options?: { requiresAuth?: boolean }\n): AuthenticatedTool<TArgs, TResult> {\n return new AuthenticatedTool(tool, options);\n}\n"],
5
+ "mappings": "AAQA,SAAS,qBAAqB,4BAA4B;AAC1D,SAAS,gBAAgB,2BAA2B;AAkE7C,MAAM,kBAA8C;AAAA,EACzD,YACU,MACA,SAOR;AARQ;AACA;AAAA,EAOP;AAAA;AAAA;AAAA;AAAA,EAKH,IAAI,OAAe;AACjB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAkC;AACpC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAkC;AACpC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,MACA,SACA,cACA,eACA,cACkB;AAElB,UAAM,eAAe,KAAK,SAAS,gBAAgB;AAEnD,QAAI,CAAC,cAAc;AAEjB,aAAO,KAAK,KAAK,QAAQ,MAAM,IAAI,EAAE;AAAA,IACvC;AAGA,UAAM,aAAa,MAAM,aAAa,aAAa,OAAO;AAE1D,QAAI,CAAC,WAAW,iBAAiB,CAAC,WAAW,QAAQ;AACnD,YAAM,IAAI;AAAA,QACR,WAAW,SAAS;AAAA,QACpB,EAAE,MAAM,KAAK,KAAK,KAAK;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,SAAS,eAAe,WAAW,MAAM;AAG/C,UAAM,cAAc,MAAM,cAAc,aAAa,QAAQ,YAAY;AAEzE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,qBAAqB,QAAQ,cAAc;AAAA,QACnD,MAAM,KAAK,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAEA,wBAAoB,WAAW;AAG/B,WAAO,KAAK,KAAK,QAAQ,MAAM,aAAa,MAAM;AAAA,EACpD;AACF;AAiBO,SAAS,wBACd,MACA,SACmC;AACnC,SAAO,IAAI,kBAAkB,MAAM,OAAO;AAC5C;",
6
+ "names": []
7
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,143 @@
1
+ class MCPAuthError extends Error {
2
+ /**
3
+ * Error code for programmatic handling
4
+ */
5
+ code;
6
+ /**
7
+ * HTTP status code (for HTTP/SSE transports)
8
+ */
9
+ statusCode;
10
+ /**
11
+ * Additional error details
12
+ */
13
+ details;
14
+ constructor(message, code = "MCP_AUTH_ERROR", statusCode = 500, details) {
15
+ super(message);
16
+ this.name = this.constructor.name;
17
+ this.code = code;
18
+ this.statusCode = statusCode;
19
+ this.details = details;
20
+ if (typeof Error.captureStackTrace === "function") {
21
+ Error.captureStackTrace(this, this.constructor);
22
+ }
23
+ }
24
+ /**
25
+ * Convert error to JSON for logging/transmission
26
+ */
27
+ toJSON() {
28
+ return {
29
+ name: this.name,
30
+ message: this.message,
31
+ code: this.code,
32
+ statusCode: this.statusCode,
33
+ details: this.details,
34
+ stack: this.stack
35
+ };
36
+ }
37
+ }
38
+ class AuthenticationError extends MCPAuthError {
39
+ constructor(message = "Authentication failed", details) {
40
+ super(message, "AUTHENTICATION_FAILED", 401, details);
41
+ }
42
+ }
43
+ class TokenResolutionError extends MCPAuthError {
44
+ constructor(userId, resourceType, details) {
45
+ super(
46
+ `Failed to resolve ${resourceType} token for user ${userId}`,
47
+ "TOKEN_RESOLUTION_FAILED",
48
+ 401,
49
+ { userId, resourceType, ...details }
50
+ );
51
+ }
52
+ }
53
+ class InvalidTokenError extends MCPAuthError {
54
+ constructor(message = "Invalid or expired token", details) {
55
+ super(message, "INVALID_TOKEN", 401, details);
56
+ }
57
+ }
58
+ class MissingCredentialsError extends MCPAuthError {
59
+ constructor(message = "Missing authentication credentials", details) {
60
+ super(message, "MISSING_CREDENTIALS", 401, details);
61
+ }
62
+ }
63
+ class ConfigurationError extends MCPAuthError {
64
+ constructor(message, details) {
65
+ super(message, "CONFIGURATION_ERROR", 500, details);
66
+ }
67
+ }
68
+ class RateLimitError extends MCPAuthError {
69
+ constructor(message = "Rate limit exceeded", retryAfter, details) {
70
+ super(
71
+ message,
72
+ "RATE_LIMIT_EXCEEDED",
73
+ 429,
74
+ { retryAfter, ...details }
75
+ );
76
+ }
77
+ }
78
+ class ServerPoolError extends MCPAuthError {
79
+ constructor(message, details) {
80
+ super(message, "SERVER_POOL_ERROR", 500, details);
81
+ }
82
+ }
83
+ class TransportError extends MCPAuthError {
84
+ constructor(message, details) {
85
+ super(message, "TRANSPORT_ERROR", 500, details);
86
+ }
87
+ }
88
+ class ValidationError extends MCPAuthError {
89
+ constructor(message, details) {
90
+ super(message, "VALIDATION_ERROR", 400, details);
91
+ }
92
+ }
93
+ function isMCPAuthError(error) {
94
+ return error instanceof MCPAuthError;
95
+ }
96
+ function isAuthenticationError(error) {
97
+ return error instanceof AuthenticationError;
98
+ }
99
+ function isTokenResolutionError(error) {
100
+ return error instanceof TokenResolutionError;
101
+ }
102
+ function isRateLimitError(error) {
103
+ return error instanceof RateLimitError;
104
+ }
105
+ function formatErrorForClient(error) {
106
+ if (isMCPAuthError(error)) {
107
+ return {
108
+ error: error.message,
109
+ code: error.code,
110
+ statusCode: error.statusCode
111
+ };
112
+ }
113
+ if (error instanceof Error) {
114
+ return {
115
+ error: error.message,
116
+ code: "INTERNAL_ERROR",
117
+ statusCode: 500
118
+ };
119
+ }
120
+ return {
121
+ error: "An unknown error occurred",
122
+ code: "UNKNOWN_ERROR",
123
+ statusCode: 500
124
+ };
125
+ }
126
+ export {
127
+ AuthenticationError,
128
+ ConfigurationError,
129
+ InvalidTokenError,
130
+ MCPAuthError,
131
+ MissingCredentialsError,
132
+ RateLimitError,
133
+ ServerPoolError,
134
+ TokenResolutionError,
135
+ TransportError,
136
+ ValidationError,
137
+ formatErrorForClient,
138
+ isAuthenticationError,
139
+ isMCPAuthError,
140
+ isRateLimitError,
141
+ isTokenResolutionError
142
+ };
143
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/errors.ts"],
4
+ "sourcesContent": ["/**\n * Custom error classes for @prmichaelsen/mcp-auth\n * \n * Provides specific error types for different failure scenarios.\n */\n\n/**\n * Base error class for all mcp-auth errors\n */\nexport class MCPAuthError extends Error {\n /**\n * Error code for programmatic handling\n */\n public readonly code: string;\n \n /**\n * HTTP status code (for HTTP/SSE transports)\n */\n public readonly statusCode: number;\n \n /**\n * Additional error details\n */\n public readonly details?: Record<string, unknown>;\n \n constructor(\n message: string,\n code: string = 'MCP_AUTH_ERROR',\n statusCode: number = 500,\n details?: Record<string, unknown>\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.statusCode = statusCode;\n this.details = details;\n \n // Maintains proper stack trace for where error was thrown (V8 only)\n if (typeof (Error as any).captureStackTrace === 'function') {\n (Error as any).captureStackTrace(this, this.constructor);\n }\n }\n \n /**\n * Convert error to JSON for logging/transmission\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n stack: this.stack\n };\n }\n}\n\n/**\n * Authentication failed error\n * Thrown when request authentication fails\n */\nexport class AuthenticationError extends MCPAuthError {\n constructor(message: string = 'Authentication failed', details?: Record<string, unknown>) {\n super(message, 'AUTHENTICATION_FAILED', 401, details);\n }\n}\n\n/**\n * Token resolution failed error\n * Thrown when resource token cannot be resolved for a user\n */\nexport class TokenResolutionError extends MCPAuthError {\n constructor(\n userId: string,\n resourceType: string,\n details?: Record<string, unknown>\n ) {\n super(\n `Failed to resolve ${resourceType} token for user ${userId}`,\n 'TOKEN_RESOLUTION_FAILED',\n 401,\n { userId, resourceType, ...details }\n );\n }\n}\n\n/**\n * Invalid token error\n * Thrown when a token is invalid or expired\n */\nexport class InvalidTokenError extends MCPAuthError {\n constructor(message: string = 'Invalid or expired token', details?: Record<string, unknown>) {\n super(message, 'INVALID_TOKEN', 401, details);\n }\n}\n\n/**\n * Missing credentials error\n * Thrown when required authentication credentials are missing\n */\nexport class MissingCredentialsError extends MCPAuthError {\n constructor(message: string = 'Missing authentication credentials', details?: Record<string, unknown>) {\n super(message, 'MISSING_CREDENTIALS', 401, details);\n }\n}\n\n/**\n * Configuration error\n * Thrown when the server or provider is misconfigured\n */\nexport class ConfigurationError extends MCPAuthError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'CONFIGURATION_ERROR', 500, details);\n }\n}\n\n/**\n * Rate limit exceeded error\n * Thrown when rate limit is exceeded\n */\nexport class RateLimitError extends MCPAuthError {\n constructor(\n message: string = 'Rate limit exceeded',\n retryAfter?: number,\n details?: Record<string, unknown>\n ) {\n super(\n message,\n 'RATE_LIMIT_EXCEEDED',\n 429,\n { retryAfter, ...details }\n );\n }\n}\n\n/**\n * Server pooling error\n * Thrown when server pool operations fail\n */\nexport class ServerPoolError extends MCPAuthError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'SERVER_POOL_ERROR', 500, details);\n }\n}\n\n/**\n * Transport error\n * Thrown when transport-related operations fail\n */\nexport class TransportError extends MCPAuthError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'TRANSPORT_ERROR', 500, details);\n }\n}\n\n/**\n * Validation error\n * Thrown when input validation fails\n */\nexport class ValidationError extends MCPAuthError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'VALIDATION_ERROR', 400, details);\n }\n}\n\n/**\n * Type guard to check if an error is an MCPAuthError\n */\nexport function isMCPAuthError(error: unknown): error is MCPAuthError {\n return error instanceof MCPAuthError;\n}\n\n/**\n * Type guard to check if an error is an authentication error\n */\nexport function isAuthenticationError(error: unknown): error is AuthenticationError {\n return error instanceof AuthenticationError;\n}\n\n/**\n * Type guard to check if an error is a token resolution error\n */\nexport function isTokenResolutionError(error: unknown): error is TokenResolutionError {\n return error instanceof TokenResolutionError;\n}\n\n/**\n * Type guard to check if an error is a rate limit error\n */\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return error instanceof RateLimitError;\n}\n\n/**\n * Format error for client response\n * Sanitizes sensitive information from error details\n */\nexport function formatErrorForClient(error: unknown): {\n error: string;\n code: string;\n statusCode: number;\n} {\n if (isMCPAuthError(error)) {\n return {\n error: error.message,\n code: error.code,\n statusCode: error.statusCode\n };\n }\n \n if (error instanceof Error) {\n return {\n error: error.message,\n code: 'INTERNAL_ERROR',\n statusCode: 500\n };\n }\n \n return {\n error: 'An unknown error occurred',\n code: 'UNKNOWN_ERROR',\n statusCode: 500\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,81 @@
1
+ import {
2
+ MCPAuthError,
3
+ AuthenticationError,
4
+ TokenResolutionError,
5
+ InvalidTokenError,
6
+ MissingCredentialsError,
7
+ ConfigurationError,
8
+ RateLimitError,
9
+ ServerPoolError,
10
+ TransportError,
11
+ ValidationError,
12
+ isMCPAuthError,
13
+ isAuthenticationError,
14
+ isTokenResolutionError,
15
+ isRateLimitError,
16
+ formatErrorForClient
17
+ } from "./errors.js";
18
+ import {
19
+ Logger,
20
+ LogLevel,
21
+ defaultLogger,
22
+ createLogger,
23
+ sanitizeForLogging
24
+ } from "./logger.js";
25
+ import {
26
+ validateNonEmptyString,
27
+ validateUrl,
28
+ validatePositiveNumber,
29
+ validatePort,
30
+ validateEnum,
31
+ validateObject,
32
+ validateFunction,
33
+ validateRequiredFields,
34
+ validateTransportConfig,
35
+ validateRateLimitConfig,
36
+ validateLoggingConfig,
37
+ validatePoolingConfig,
38
+ sanitizeString,
39
+ validateUserId,
40
+ validateResourceType,
41
+ validateAccessToken
42
+ } from "./validation.js";
43
+ export {
44
+ AuthenticationError,
45
+ ConfigurationError,
46
+ InvalidTokenError,
47
+ LogLevel,
48
+ Logger,
49
+ MCPAuthError,
50
+ MissingCredentialsError,
51
+ RateLimitError,
52
+ ServerPoolError,
53
+ TokenResolutionError,
54
+ TransportError,
55
+ ValidationError,
56
+ createLogger,
57
+ defaultLogger,
58
+ formatErrorForClient,
59
+ isAuthenticationError,
60
+ isMCPAuthError,
61
+ isRateLimitError,
62
+ isTokenResolutionError,
63
+ sanitizeForLogging,
64
+ sanitizeString,
65
+ validateAccessToken,
66
+ validateEnum,
67
+ validateFunction,
68
+ validateLoggingConfig,
69
+ validateNonEmptyString,
70
+ validateObject,
71
+ validatePoolingConfig,
72
+ validatePort,
73
+ validatePositiveNumber,
74
+ validateRateLimitConfig,
75
+ validateRequiredFields,
76
+ validateResourceType,
77
+ validateTransportConfig,
78
+ validateUrl,
79
+ validateUserId
80
+ };
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/index.ts"],
4
+ "sourcesContent": ["/**\n * Utilities module exports\n */\n\n// Errors\nexport {\n MCPAuthError,\n AuthenticationError,\n TokenResolutionError,\n InvalidTokenError,\n MissingCredentialsError,\n ConfigurationError,\n RateLimitError,\n ServerPoolError,\n TransportError,\n ValidationError,\n isMCPAuthError,\n isAuthenticationError,\n isTokenResolutionError,\n isRateLimitError,\n formatErrorForClient\n} from './errors.js';\n\n// Logger\nexport {\n Logger,\n LogLevel,\n defaultLogger,\n createLogger,\n sanitizeForLogging,\n type LogEntry\n} from './logger.js';\n\n// Validation\nexport {\n validateNonEmptyString,\n validateUrl,\n validatePositiveNumber,\n validatePort,\n validateEnum,\n validateObject,\n validateFunction,\n validateRequiredFields,\n validateTransportConfig,\n validateRateLimitConfig,\n validateLoggingConfig,\n validatePoolingConfig,\n sanitizeString,\n validateUserId,\n validateResourceType,\n validateAccessToken\n} from './validation.js';\n"],
5
+ "mappings": "AAKA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;",
6
+ "names": []
7
+ }