mcp-ts-template 1.7.2 → 1.7.3

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 (74) hide show
  1. package/README.md +38 -59
  2. package/dist/config/index.d.ts +1 -1
  3. package/dist/config/index.js +2 -2
  4. package/dist/mcp-server/server.js +5 -4
  5. package/dist/mcp-server/tools/echoTool/logic.js +1 -2
  6. package/dist/mcp-server/tools/imageTest/logic.js +3 -1
  7. package/dist/mcp-server/transports/auth/authFactory.d.ts +10 -0
  8. package/dist/mcp-server/transports/auth/authFactory.js +31 -0
  9. package/dist/mcp-server/transports/auth/authMiddleware.d.ts +25 -0
  10. package/dist/mcp-server/transports/auth/authMiddleware.js +48 -0
  11. package/dist/mcp-server/transports/auth/index.d.ts +8 -5
  12. package/dist/mcp-server/transports/auth/index.js +6 -4
  13. package/dist/mcp-server/transports/auth/{core → lib}/authTypes.d.ts +0 -5
  14. package/dist/mcp-server/transports/auth/lib/authTypes.js +8 -0
  15. package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts +17 -0
  16. package/dist/mcp-server/transports/auth/strategies/authStrategy.js +1 -0
  17. package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts +7 -0
  18. package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js +78 -0
  19. package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts +7 -0
  20. package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js +65 -0
  21. package/dist/mcp-server/transports/core/mcpTransportManager.d.ts +32 -0
  22. package/dist/mcp-server/transports/core/mcpTransportManager.js +151 -0
  23. package/dist/mcp-server/transports/core/transportTypes.d.ts +71 -0
  24. package/dist/mcp-server/transports/core/transportTypes.js +5 -0
  25. package/dist/mcp-server/transports/{httpErrorHandler.d.ts → http/httpErrorHandler.d.ts} +1 -1
  26. package/dist/mcp-server/transports/{httpErrorHandler.js → http/httpErrorHandler.js} +2 -2
  27. package/dist/mcp-server/transports/http/httpTransport.d.ts +44 -0
  28. package/dist/mcp-server/transports/{httpTransport.js → http/httpTransport.js} +96 -86
  29. package/dist/mcp-server/transports/http/httpTypes.d.ts +14 -0
  30. package/dist/mcp-server/transports/http/httpTypes.js +5 -0
  31. package/dist/mcp-server/transports/http/index.d.ts +7 -0
  32. package/dist/mcp-server/transports/http/index.js +6 -0
  33. package/dist/mcp-server/transports/stdio/index.d.ts +5 -0
  34. package/dist/mcp-server/transports/stdio/index.js +5 -0
  35. package/dist/mcp-server/transports/{stdioTransport.d.ts → stdio/stdioTransport.d.ts} +2 -2
  36. package/dist/mcp-server/transports/{stdioTransport.js → stdio/stdioTransport.js} +2 -2
  37. package/dist/services/llm-providers/openRouterProvider.d.ts +1 -2
  38. package/dist/services/llm-providers/openRouterProvider.js +3 -2
  39. package/dist/utils/internal/logger.d.ts +5 -0
  40. package/dist/utils/internal/logger.js +14 -0
  41. package/dist/utils/security/sanitization.js +32 -13
  42. package/package.json +2 -1
  43. package/dist/agent/agent-core/agent.d.ts +0 -20
  44. package/dist/agent/agent-core/agent.js +0 -380
  45. package/dist/agent/cli/boot.d.ts +0 -7
  46. package/dist/agent/cli/boot.js +0 -32
  47. package/dist/agent/cli/main.d.ts +0 -7
  48. package/dist/agent/cli/main.js +0 -44
  49. package/dist/mcp-client/client-config/configLoader.d.ts +0 -104
  50. package/dist/mcp-client/client-config/configLoader.js +0 -166
  51. package/dist/mcp-client/core/clientConnectionLogic.d.ts +0 -33
  52. package/dist/mcp-client/core/clientConnectionLogic.js +0 -115
  53. package/dist/mcp-client/core/clientManager.d.ts +0 -71
  54. package/dist/mcp-client/core/clientManager.js +0 -213
  55. package/dist/mcp-client/index.d.ts +0 -21
  56. package/dist/mcp-client/index.js +0 -27
  57. package/dist/mcp-client/transports/httpClientTransport.d.ts +0 -26
  58. package/dist/mcp-client/transports/httpClientTransport.js +0 -56
  59. package/dist/mcp-client/transports/index.d.ts +0 -8
  60. package/dist/mcp-client/transports/index.js +0 -8
  61. package/dist/mcp-client/transports/stdioClientTransport.d.ts +0 -32
  62. package/dist/mcp-client/transports/stdioClientTransport.js +0 -67
  63. package/dist/mcp-client/transports/transportFactory.d.ts +0 -23
  64. package/dist/mcp-client/transports/transportFactory.js +0 -63
  65. package/dist/mcp-server/transports/auth/core/authTypes.js +0 -5
  66. package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.d.ts +0 -27
  67. package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.js +0 -149
  68. package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.d.ts +0 -20
  69. package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.js +0 -124
  70. package/dist/mcp-server/transports/httpTransport.d.ts +0 -21
  71. /package/dist/mcp-server/transports/auth/{core → lib}/authContext.d.ts +0 -0
  72. /package/dist/mcp-server/transports/auth/{core → lib}/authContext.js +0 -0
  73. /package/dist/mcp-server/transports/auth/{core → lib}/authUtils.d.ts +0 -0
  74. /package/dist/mcp-server/transports/auth/{core → lib}/authUtils.js +0 -0
package/README.md CHANGED
@@ -1,41 +1,47 @@
1
- # 🚀 MCP TypeScript Template: Agent, Server & Client
2
-
3
- [![TypeScript](https://img.shields.io/badge/TypeScript-^5.8.3-blue.svg)](https://www.typescriptlang.org/)
4
- [![Model Context Protocol SDK](https://img.shields.io/badge/MCP%20SDK-^1.17.0-green.svg)](https://github.com/modelcontextprotocol/typescript-sdk)
5
- [![MCP Spec Version](https://img.shields.io/badge/MCP%20Spec-2025--06--18-lightgrey.svg)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/changelog.mdx)
6
- [![Version](https://img.shields.io/badge/Version-1.7.2-blue.svg)](./CHANGELOG.md)
7
- [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
8
- [![Status](https://img.shields.io/badge/Status-Stable-green.svg)](https://github.com/cyanheads/mcp-ts-template/issues)
1
+ <div align="center">
2
+
3
+ # 🚀 Model Context Protocol (MCP) Server TypeScript Template
4
+
5
+ **Build production-grade MCP servers with a powerful, type-safe, and extensible foundation.**
6
+
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-^5.8.3-blue?style=flat-square)](https://www.typescriptlang.org/)
8
+ [![Model Context Protocol SDK](https://img.shields.io/badge/MCP%20SDK-^1.17.0-green?style=flat-square)](https://github.com/modelcontextprotocol/typescript-sdk)
9
+ [![MCP Spec Version](https://img.shields.io/badge/MCP%20Spec-2025--06--18-lightgrey?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/changelog.mdx)
10
+ [![Version](https://img.shields.io/badge/Version-1.7.3-blue?style=flat-square)](./CHANGELOG.md)
11
+ [![Coverage](https://img.shields.io/badge/Coverage-62.4%25-yellow?style=flat-square)](./vitest.config.ts)
12
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue?style=flat-square)](https://opensource.org/licenses/Apache-2.0)
13
+ [![Status](https://img.shields.io/badge/Status-Stable-green?style=flat-square)](https://github.com/cyanheads/mcp-ts-template/issues)
9
14
  [![GitHub](https://img.shields.io/github/stars/cyanheads/mcp-ts-template?style=social)](https://github.com/cyanheads/mcp-ts-template)
10
15
 
11
- **Jumpstart your [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) development with this comprehensive TypeScript Template for building autonomous agents, servers, and clients.**
16
+ </div>
12
17
 
13
- This template provides a solid, beginner-friendly foundation for building all components of the MCP ecosystem, adhering to the **MCP 2025-06-18 specification**. It includes a powerful agent framework, a fully-featured server, a robust client, production-ready utilities, and clear documentation to get you up and running quickly.
18
+ This template provides a comprehensive foundation for building rich Model Context Protocol servers, adhering to the **MCP 2025-06-18 specification** and modern best practices. It includes a fully-featured server, production-ready utilities, and clear documentation to get you up and running quickly.
14
19
 
15
- ## 🏛️ Three-Part Architecture
20
+ ## 🤔 Why Use This Template?
16
21
 
17
- This template is organized into three primary, interconnected components:
22
+ Building a robust server for AI agents is more than just writing code. It requires a solid architecture, consistent error handling, and secure, type-safe practices from the ground up. This template solves these challenges by providing:
18
23
 
19
- 1. **🤖 Agent (`src/agent/`)**: An autonomous agent framework. The agent can connect to multiple MCP servers, discover their tools, and use them to accomplish complex tasks based on a user's prompt. Use this as a starting point for your agents.
20
- 2. **🔌 MCP Server (`src/mcp-server/`)**: An extensible MCP server that can host custom tools and resources, making them available to agents and other clients.
21
- 3. **💻 MCP Client (`src/mcp-client/`)**: A robust client for connecting to and interacting with any MCP-compliant server. The agent uses this client to communicate with the outside world.
24
+ - **Accelerated Development**: Skip the boilerplate and focus on your tool's core logic.
25
+ - **Production-Ready Foundation**: Built-in logging, error handling, security, and testing.
26
+ - **Best Practices by Default**: Enforces a clean, modular architecture that's easy to maintain and extend.
27
+ - **AI-Ready**: Designed with LLM agents in mind, including detailed schemas and rich LLM developer-friendly resources (e.g. .clinerules).
28
+
29
+ > **Note on src/mcp-client & src/agent:** The MCP client & Agent components have been enhanced and moved to the [**atlas-mcp-agent**](https://github.com/cyanheads/atlas-mcp-agent) repository. This template now focuses exclusively on providing a best-in-class server implementation and framework.
22
30
 
23
31
  ## ✨ Key Features
24
32
 
25
- | Feature Area | Description | Key Components / Location |
26
- | :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------- |
27
- | **🤖 Agent Framework** | Core `Agent` class and CLI for running autonomous agents that connect to MCP servers and use their tools to achieve goals. | `src/agent/` |
28
- | **🔌 MCP Server** | Functional server with example tools (`EchoTool`, `CatFactFetcher`) and an `EchoResource`. Supports `stdio` and **Streamable HTTP** transports. | `src/mcp-server/` |
29
- | **💻 MCP Client** | Working client aligned with **MCP 2025-03-26 spec**. Connects via `mcp-config.json`. Includes detailed comments and isolated connection management. | `src/mcp-client/` |
30
- | **🚀 Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
31
- | **🔒 Type Safety/Security** | Strong type checking via TypeScript & Zod validation. Built-in security utilities (sanitization, auth middleware for HTTP). | Throughout, `src/utils/security/`, `src/mcp-server/transports/auth/` |
32
- | **⚙️ Error Handling** | Consistent error categorization (`BaseErrorCode`), detailed logging, centralized handling (`ErrorHandler`). | `src/utils/internal/errorHandler.ts`, `src/types-global/` |
33
- | **📚 Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references. | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
34
- | **🕵️ Interaction Logging** | Captures raw requests and responses for all external LLM provider interactions to a dedicated `interactions.log` file for full traceability. | `src/utils/internal/logger.ts` |
35
- | **🤖 Agent Ready** | Includes a [.clinerules](.clinerules) developer cheatsheet tailored for LLM coding agents. | `.clinerules` |
36
- | **🛠️ Utility Scripts** | Scripts for cleaning builds, setting executable permissions, generating directory trees, and fetching OpenAPI specs. | `scripts/` |
37
- | **Services** | Reusable modules for LLM (OpenRouter) and data storage (DuckDB) integration, with examples. | `src/services/`, `src/storage/duckdbExample.ts` |
38
- | **🧪 Unit Testing** | Integrated with Vitest for fast and reliable unit testing. Includes example tests for core tool logic and a coverage reporter. | `vitest.config.ts`, `tests/` |
33
+ | Feature Area | Description | Key Components / Location |
34
+ | :-------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------- |
35
+ | **🔌 MCP Server** | Functional server with example tools (`EchoTool`, `CatFactFetcher`) and an `EchoResource`. Supports `stdio` and **Streamable HTTP** transports. | `src/mcp-server/` |
36
+ | **🚀 Production Utilities** | Logging, Error Handling, ID Generation, Rate Limiting, Request Context tracking, Input Sanitization. | `src/utils/` |
37
+ | **🔒 Type Safety/Security** | Strong type checking via TypeScript & Zod validation. Built-in security utilities (sanitization, auth middleware for HTTP). | Throughout, `src/utils/security/`, `src/mcp-server/transports/auth/` |
38
+ | **⚙️ Error Handling** | Consistent error categorization (`BaseErrorCode`), detailed logging, centralized handling (`ErrorHandler`). | `src/utils/internal/errorHandler.ts`, `src/types-global/` |
39
+ | **📚 Documentation** | Comprehensive `README.md`, structured JSDoc comments, API references. | `README.md`, Codebase, `tsdoc.json`, `docs/api-references/` |
40
+ | **🕵️ Interaction Logging** | Captures raw requests and responses for all external LLM provider interactions to a dedicated `interactions.log` file for full traceability. | `src/utils/internal/logger.ts` |
41
+ | **🤖 Agent Ready** | Includes a [.clinerules](.clinerules) developer cheatsheet tailored for LLM coding agents. | `.clinerules` |
42
+ | **🛠️ Utility Scripts** | Scripts for cleaning builds, setting executable permissions, generating directory trees, and fetching OpenAPI specs. | `scripts/` |
43
+ | **🧩 Services** | Reusable modules for LLM (OpenRouter) and data storage (DuckDB) integration, with examples. | `src/services/`, `src/storage/duckdbExample.ts` |
44
+ | **🧪 Unit Testing** | Integrated with Vitest for fast and reliable unit testing. Includes example tests for core tool logic and a coverage reporter. | `vitest.config.ts`, `tests/` |
39
45
 
40
46
  ## 🌟 Projects Using This Template
41
47
 
@@ -74,11 +80,7 @@ npm run build
74
80
  # Or use 'npm run rebuild' for a clean install
75
81
  ```
76
82
 
77
- ### 3. Running the Components
78
-
79
- #### Running the MCP Server
80
-
81
- You can run the included MCP server to make its tools available.
83
+ ### 3. Running the Server
82
84
 
83
85
  - **Via Stdio (Default):**
84
86
  ```bash
@@ -89,17 +91,6 @@ You can run the included MCP server to make its tools available.
89
91
  npm run start:server:http
90
92
  ```
91
93
 
92
- #### Running the Agent
93
-
94
- The agent can be run from the command line to perform tasks. It will automatically connect to the servers defined in `src/mcp-client/client-config/mcp-config.json`. If running the agent, you must have the MCP config set up correctly and your openrouter API key configured in .env.
95
-
96
- ```bash
97
- npm run start:agent "Your prompt here"
98
-
99
- # Example:
100
- npm run start:agent "Use the echo tool to say hello world and then get a cat fact."
101
- ```
102
-
103
94
  ### 4. Running Tests
104
95
 
105
96
  This template uses [Vitest](https://vitest.dev/) for unit testing. Tests are located in the `tests/` directory, mirroring the `src/` structure.
@@ -129,22 +120,14 @@ Configure the MCP server's behavior using these environment variables:
129
120
  | `MCP_HTTP_PORT` | Port for the HTTP server (if `MCP_TRANSPORT_TYPE=http`). | `3010` |
130
121
  | `MCP_HTTP_HOST` | Host address for the HTTP server (if `MCP_TRANSPORT_TYPE=http`). | `127.0.0.1` |
131
122
  | `MCP_ALLOWED_ORIGINS` | Comma-separated allowed origins for CORS (if `MCP_TRANSPORT_TYPE=http`). | (none) |
132
- | `MCP_AUTH_MODE` | Authentication mode for HTTP: `jwt` (default) or `oauth`. | `jwt` |
123
+ | `MCP_AUTH_MODE` | Authentication mode for HTTP: `jwt`, `oauth`, or `none`. | `none` |
133
124
  | `MCP_AUTH_SECRET_KEY` | **Required for `jwt` mode.** Secret key (min 32 chars) for signing/verifying auth tokens. | (none - **MUST be set in production**) |
134
125
  | `OAUTH_ISSUER_URL` | **Required for `oauth` mode.** The issuer URL of your authorization server. | (none) |
135
126
  | `OAUTH_AUDIENCE` | **Required for `oauth` mode.** The audience identifier for this MCP server. | (none) |
136
- | `OPENROUTER_API_KEY` | API key for OpenRouter.ai service. Required for the agent to function. | (none) |
137
-
138
- ### Client & Agent Configuration
139
-
140
- The agent uses the MCP client to connect to servers. This is configured in `src/mcp-client/client-config/mcp-config.json`. You must list all MCP servers the agent should connect to in this file.
141
-
142
- For a detailed guide, see the [Client Configuration README](src/mcp-client/client-config/README.md).
127
+ | `OPENROUTER_API_KEY` | API key for OpenRouter.ai service. | (none) |
143
128
 
144
129
  ## 🏗️ Project Structure
145
130
 
146
- - **`src/agent/`**: Contains the core agent framework, including the `Agent` class and a CLI for running the agent.
147
- - **`src/mcp-client/`**: Implements the MCP client logic for connecting to and interacting with external MCP servers.
148
131
  - **`src/mcp-server/`**: Contains the MCP server implementation, including example tools, resources, and transport handlers.
149
132
  - **`src/config/`**: Handles loading and validation of environment variables and application configuration.
150
133
  - **`src/services/`**: Provides reusable modules for integrating with external services (DuckDB, OpenRouter).
@@ -166,10 +149,6 @@ npm run tree
166
149
 
167
150
  For detailed guidance on how to add your own custom Tools and Resources to the MCP server, please see the [Server Extension Guide](src/mcp-server/README.md).
168
151
 
169
- ### Modifying the Agent
170
-
171
- The agent's core logic is in `src/agent/agent-core/agent.ts`. You can modify its system prompt, the models it uses (`google/gemini-2.5-flash` by default), and its decision-making loop to change its behavior.
172
-
173
152
  ## 🌍 Explore More MCP Resources
174
153
 
175
154
  Looking for more examples, guides, and pre-built MCP servers? Check out the companion repository:
@@ -45,7 +45,7 @@ export declare const config: {
45
45
  /** Auth secret key (JWTs, http transport). From `MCP_AUTH_SECRET_KEY`. CRITICAL. */
46
46
  mcpAuthSecretKey: string | undefined;
47
47
  /** The authentication mode ('jwt' or 'oauth'). From `MCP_AUTH_MODE`. */
48
- mcpAuthMode: "jwt" | "oauth";
48
+ mcpAuthMode: "jwt" | "oauth" | "none";
49
49
  /** OAuth 2.1 Issuer URL. From `OAUTH_ISSUER_URL`. */
50
50
  oauthIssuerUrl: string | undefined;
51
51
  /** OAuth 2.1 JWKS URI. From `OAUTH_JWKS_URI`. */
@@ -96,8 +96,8 @@ const EnvSchema = z.object({
96
96
  .string()
97
97
  .min(32, "MCP_AUTH_SECRET_KEY must be at least 32 characters long for security reasons.")
98
98
  .optional(),
99
- /** The authentication mode to use. 'jwt' for internal simple JWTs, 'oauth' for OAuth 2.1. Default: 'jwt'. */
100
- MCP_AUTH_MODE: z.enum(["jwt", "oauth"]).default("jwt"),
99
+ /** The authentication mode to use. 'jwt' for internal simple JWTs, 'oauth' for OAuth 2.1, or 'none'. Default: 'none'. */
100
+ MCP_AUTH_MODE: z.enum(["jwt", "oauth", "none"]).default("none"),
101
101
  /** The expected issuer URL for OAuth 2.1 access tokens. CRITICAL for validation. */
102
102
  OAUTH_ISSUER_URL: z.string().url().optional(),
103
103
  /** The JWKS (JSON Web Key Set) URI for the OAuth 2.1 provider. If not provided, it's often discoverable from the issuer URL. */
@@ -21,8 +21,8 @@ import { registerEchoResource } from "./resources/echoResource/index.js";
21
21
  import { registerCatFactFetcherTool } from "./tools/catFactFetcher/index.js";
22
22
  import { registerEchoTool } from "./tools/echoTool/index.js";
23
23
  import { registerFetchImageTestTool } from "./tools/imageTest/index.js";
24
- import { startHttpTransport } from "./transports/httpTransport.js";
25
- import { connectStdioTransport } from "./transports/stdioTransport.js";
24
+ import { startHttpTransport } from "./transports/http/index.js";
25
+ import { startStdioTransport } from "./transports/stdio/index.js";
26
26
  /**
27
27
  * Creates and configures a new instance of the `McpServer`.
28
28
  *
@@ -77,11 +77,12 @@ async function startTransport() {
77
77
  });
78
78
  logger.info(`Starting transport: ${transportType}`, context);
79
79
  if (transportType === "http") {
80
- return startHttpTransport(createMcpServerInstance, context);
80
+ const { server } = await startHttpTransport(createMcpServerInstance, context);
81
+ return server;
81
82
  }
82
83
  if (transportType === "stdio") {
83
84
  const server = await createMcpServerInstance();
84
- await connectStdioTransport(server, context);
85
+ await startStdioTransport(server, context);
85
86
  return server;
86
87
  }
87
88
  throw new Error(`Unsupported transport type: ${transportType}. Must be 'stdio' or 'http'.`);
@@ -15,8 +15,7 @@ export const ECHO_MODES = ["standard", "uppercase", "lowercase"];
15
15
  * Zod schema defining the input parameters for the `echo_message` tool.
16
16
  * This schema is used by the MCP SDK to validate the arguments provided when the tool is called.
17
17
  */
18
- export const EchoToolInputSchema = z
19
- .object({
18
+ export const EchoToolInputSchema = z.object({
20
19
  message: z
21
20
  .string()
22
21
  .min(1, "Message cannot be empty.")
@@ -14,7 +14,9 @@ export const FetchImageTestInputSchema = z.object({
14
14
  });
15
15
  export const FetchImageTestResponseSchema = z.object({
16
16
  data: z.string().describe("Base64 encoded image data."),
17
- mimeType: z.string().describe("The MIME type of the image (e.g., 'image/jpeg')."),
17
+ mimeType: z
18
+ .string()
19
+ .describe("The MIME type of the image (e.g., 'image/jpeg')."),
18
20
  });
19
21
  const CAT_API_URL = "https://cataas.com/cat";
20
22
  export async function fetchImageTestLogic(input, parentRequestContext) {
@@ -0,0 +1,10 @@
1
+ import { AuthStrategy } from "./strategies/authStrategy.js";
2
+ /**
3
+ * Creates and returns an authentication strategy instance based on the
4
+ * application's configuration (`config.mcpAuthMode`).
5
+ *
6
+ * @returns An instance of a class that implements the `AuthStrategy` interface,
7
+ * or `null` if authentication is disabled (`none`).
8
+ * @throws {Error} If the auth mode is unknown or misconfigured.
9
+ */
10
+ export declare function createAuthStrategy(): AuthStrategy | null;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @fileoverview Factory for creating an authentication strategy based on configuration.
3
+ * This module centralizes the logic for selecting and instantiating the correct
4
+ * authentication strategy, promoting loose coupling and easy extensibility.
5
+ * @module src/mcp-server/transports/auth/authFactory
6
+ */
7
+ import { config } from "../../../config/index.js";
8
+ import { JwtStrategy } from "./strategies/jwtStrategy.js";
9
+ import { OauthStrategy } from "./strategies/oauthStrategy.js";
10
+ /**
11
+ * Creates and returns an authentication strategy instance based on the
12
+ * application's configuration (`config.mcpAuthMode`).
13
+ *
14
+ * @returns An instance of a class that implements the `AuthStrategy` interface,
15
+ * or `null` if authentication is disabled (`none`).
16
+ * @throws {Error} If the auth mode is unknown or misconfigured.
17
+ */
18
+ export function createAuthStrategy() {
19
+ switch (config.mcpAuthMode) {
20
+ case "jwt":
21
+ return new JwtStrategy();
22
+ case "oauth":
23
+ return new OauthStrategy();
24
+ case "none":
25
+ return null; // No authentication
26
+ default:
27
+ // This ensures that if a new auth mode is added to the config type
28
+ // but not to this factory, we get a compile-time or runtime error.
29
+ throw new Error(`Unknown authentication mode: ${config.mcpAuthMode}`);
30
+ }
31
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @fileoverview Defines a unified Hono middleware for authentication.
3
+ * This middleware is strategy-agnostic. It extracts a Bearer token,
4
+ * delegates verification to the provided authentication strategy, and
5
+ * populates the async-local storage context with the resulting auth info.
6
+ * @module src/mcp-server/transports/auth/authMiddleware
7
+ */
8
+ import type { HttpBindings } from "@hono/node-server";
9
+ import type { Context, Next } from "hono";
10
+ import type { AuthInfo } from "./lib/authTypes.js";
11
+ import type { AuthStrategy } from "./strategies/authStrategy.js";
12
+ declare module "http" {
13
+ interface IncomingMessage {
14
+ auth?: AuthInfo;
15
+ }
16
+ }
17
+ /**
18
+ * Creates a Hono middleware function that enforces authentication using a given strategy.
19
+ *
20
+ * @param strategy - An instance of a class that implements the `AuthStrategy` interface.
21
+ * @returns A Hono middleware function.
22
+ */
23
+ export declare function createAuthMiddleware(strategy: AuthStrategy): (c: Context<{
24
+ Bindings: HttpBindings;
25
+ }>, next: Next) => Promise<void>;
@@ -0,0 +1,48 @@
1
+ import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
2
+ import { logger, requestContextService } from "../../../utils/index.js";
3
+ import { authContext } from "./lib/authContext.js";
4
+ /**
5
+ * Creates a Hono middleware function that enforces authentication using a given strategy.
6
+ *
7
+ * @param strategy - An instance of a class that implements the `AuthStrategy` interface.
8
+ * @returns A Hono middleware function.
9
+ */
10
+ export function createAuthMiddleware(strategy) {
11
+ return async function authMiddleware(c, next) {
12
+ const context = requestContextService.createRequestContext({
13
+ operation: "authMiddleware",
14
+ method: c.req.method,
15
+ path: c.req.path,
16
+ });
17
+ const authHeader = c.req.header("Authorization");
18
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
19
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Missing or invalid Authorization header. Bearer scheme required.", context);
20
+ }
21
+ const token = authHeader.substring(7);
22
+ if (!token) {
23
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Authentication token is missing.", context);
24
+ }
25
+ try {
26
+ const authInfo = await strategy.verify(token);
27
+ // For logging and potential legacy use, attach to the raw request.
28
+ // The primary mechanism for access should be authContext.
29
+ c.env.incoming.auth = authInfo;
30
+ logger.debug("Authentication successful. Auth context populated.", {
31
+ ...context,
32
+ clientId: authInfo.clientId,
33
+ scopes: authInfo.scopes,
34
+ });
35
+ // Run the next middleware in the chain within the populated auth context.
36
+ await authContext.run({ authInfo }, next);
37
+ }
38
+ catch (error) {
39
+ // The strategy is expected to throw an McpError.
40
+ // We re-throw it here to be caught by the global httpErrorHandler.
41
+ logger.warning("Authentication verification failed.", {
42
+ ...context,
43
+ error: error instanceof Error ? error.message : String(error),
44
+ });
45
+ throw error;
46
+ }
47
+ };
48
+ }
@@ -3,8 +3,11 @@
3
3
  * Exports core utilities and middleware strategies for easier imports.
4
4
  * @module src/mcp-server/transports/auth/index
5
5
  */
6
- export { authContext } from "./core/authContext.js";
7
- export { withRequiredScopes } from "./core/authUtils.js";
8
- export type { AuthInfo } from "./core/authTypes.js";
9
- export { mcpAuthMiddleware as jwtAuthMiddleware } from "./strategies/jwt/jwtMiddleware.js";
10
- export { oauthMiddleware } from "./strategies/oauth/oauthMiddleware.js";
6
+ export { authContext } from "./lib/authContext.js";
7
+ export { withRequiredScopes } from "./lib/authUtils.js";
8
+ export type { AuthInfo } from "./lib/authTypes.js";
9
+ export { createAuthStrategy } from "./authFactory.js";
10
+ export { createAuthMiddleware } from "./authMiddleware.js";
11
+ export { AuthStrategy } from "./strategies/authStrategy.js";
12
+ export { JwtStrategy } from "./strategies/jwtStrategy.js";
13
+ export { OauthStrategy } from "./strategies/oauthStrategy.js";
@@ -3,7 +3,9 @@
3
3
  * Exports core utilities and middleware strategies for easier imports.
4
4
  * @module src/mcp-server/transports/auth/index
5
5
  */
6
- export { authContext } from "./core/authContext.js";
7
- export { withRequiredScopes } from "./core/authUtils.js";
8
- export { mcpAuthMiddleware as jwtAuthMiddleware } from "./strategies/jwt/jwtMiddleware.js";
9
- export { oauthMiddleware } from "./strategies/oauth/oauthMiddleware.js";
6
+ export { authContext } from "./lib/authContext.js";
7
+ export { withRequiredScopes } from "./lib/authUtils.js";
8
+ export { createAuthStrategy } from "./authFactory.js";
9
+ export { createAuthMiddleware } from "./authMiddleware.js";
10
+ export { JwtStrategy } from "./strategies/jwtStrategy.js";
11
+ export { OauthStrategy } from "./strategies/oauthStrategy.js";
@@ -10,8 +10,3 @@ import type { AuthInfo as SdkAuthInfo } from "@modelcontextprotocol/sdk/server/a
10
10
  export type AuthInfo = SdkAuthInfo & {
11
11
  subject?: string;
12
12
  };
13
- declare module "http" {
14
- interface IncomingMessage {
15
- auth?: AuthInfo;
16
- }
17
- }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @fileoverview Shared types for authentication middleware.
3
+ * @module src/mcp-server/transports/auth/core/auth.types
4
+ */
5
+ export {};
6
+ // The declaration for `http.IncomingMessage` is no longer needed here,
7
+ // as the new architecture avoids direct mutation where possible and handles
8
+ // the attachment within the Hono context.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @fileoverview Defines the interface for all authentication strategies.
3
+ * This interface establishes a contract for verifying authentication tokens,
4
+ * ensuring that any authentication method (JWT, OAuth, etc.) can be used
5
+ * interchangeably by the core authentication middleware.
6
+ * @module src/mcp-server/transports/auth/strategies/AuthStrategy
7
+ */
8
+ import type { AuthInfo } from "../lib/authTypes.js";
9
+ export interface AuthStrategy {
10
+ /**
11
+ * Verifies an authentication token.
12
+ * @param token The raw token string extracted from the request.
13
+ * @returns A promise that resolves with the AuthInfo on successful verification.
14
+ * @throws {McpError} if the token is invalid, expired, or fails verification for any reason.
15
+ */
16
+ verify(token: string): Promise<AuthInfo>;
17
+ }
@@ -0,0 +1,7 @@
1
+ import type { AuthInfo } from "../lib/authTypes.js";
2
+ import type { AuthStrategy } from "./authStrategy.js";
3
+ export declare class JwtStrategy implements AuthStrategy {
4
+ private readonly secretKey;
5
+ constructor();
6
+ verify(token: string): Promise<AuthInfo>;
7
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @fileoverview Implements the JWT authentication strategy.
3
+ * This module provides a concrete implementation of the AuthStrategy for validating
4
+ * JSON Web Tokens (JWTs). It encapsulates all logic related to JWT verification,
5
+ * including secret key management and payload validation.
6
+ * @module src/mcp-server/transports/auth/strategies/JwtStrategy
7
+ */
8
+ import { jwtVerify } from "jose";
9
+ import { config, environment } from "../../../../config/index.js";
10
+ import { BaseErrorCode, McpError } from "../../../../types-global/errors.js";
11
+ import { logger } from "../../../../utils/index.js";
12
+ export class JwtStrategy {
13
+ constructor() {
14
+ if (config.mcpAuthMode === "jwt") {
15
+ if (environment === "production" && !config.mcpAuthSecretKey) {
16
+ logger.fatal("CRITICAL: MCP_AUTH_SECRET_KEY is not set in production for JWT auth.");
17
+ throw new Error("MCP_AUTH_SECRET_KEY must be set for JWT auth.");
18
+ }
19
+ else if (!config.mcpAuthSecretKey) {
20
+ logger.warning("MCP_AUTH_SECRET_KEY is not set. JWT auth will be bypassed (DEV ONLY).");
21
+ this.secretKey = null;
22
+ }
23
+ else {
24
+ this.secretKey = new TextEncoder().encode(config.mcpAuthSecretKey);
25
+ }
26
+ }
27
+ else {
28
+ this.secretKey = null;
29
+ }
30
+ }
31
+ async verify(token) {
32
+ // Handle development mode bypass
33
+ if (!this.secretKey) {
34
+ if (environment !== "production") {
35
+ logger.warning("Bypassing JWT verification: No secret key (DEV ONLY).");
36
+ return {
37
+ token: "dev-mode-placeholder-token",
38
+ clientId: "dev-client-id",
39
+ scopes: ["dev-scope"],
40
+ };
41
+ }
42
+ throw new McpError(BaseErrorCode.CONFIGURATION_ERROR, "Auth secret key is missing in production.");
43
+ }
44
+ try {
45
+ const { payload: decoded } = await jwtVerify(token, this.secretKey);
46
+ const clientId = typeof decoded.cid === "string"
47
+ ? decoded.cid
48
+ : typeof decoded.client_id === "string"
49
+ ? decoded.client_id
50
+ : undefined;
51
+ if (!clientId) {
52
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Invalid token: missing 'cid' or 'client_id' claim.");
53
+ }
54
+ let scopes = [];
55
+ if (Array.isArray(decoded.scp) &&
56
+ decoded.scp.every((s) => typeof s === "string")) {
57
+ scopes = decoded.scp;
58
+ }
59
+ else if (typeof decoded.scope === "string" && decoded.scope.trim()) {
60
+ scopes = decoded.scope.split(" ").filter(Boolean);
61
+ }
62
+ if (scopes.length === 0) {
63
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Token must contain valid, non-empty scopes.");
64
+ }
65
+ return { token, clientId, scopes };
66
+ }
67
+ catch (error) {
68
+ if (error instanceof McpError)
69
+ throw error;
70
+ const message = error instanceof Error && error.name === "JWTExpired"
71
+ ? "Token has expired."
72
+ : "Token verification failed.";
73
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, message, {
74
+ originalError: error instanceof Error ? error.name : "Unknown",
75
+ });
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,7 @@
1
+ import type { AuthInfo } from "../lib/authTypes.js";
2
+ import type { AuthStrategy } from "./authStrategy.js";
3
+ export declare class OauthStrategy implements AuthStrategy {
4
+ private readonly jwks;
5
+ constructor();
6
+ verify(token: string): Promise<AuthInfo>;
7
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview Implements the OAuth 2.1 authentication strategy.
3
+ * This module provides a concrete implementation of the AuthStrategy for validating
4
+ * JWTs against a remote JSON Web Key Set (JWKS), as is common in OAuth 2.1 flows.
5
+ * @module src/mcp-server/transports/auth/strategies/OauthStrategy
6
+ */
7
+ import { createRemoteJWKSet, jwtVerify } from "jose";
8
+ import { config } from "../../../../config/index.js";
9
+ import { BaseErrorCode, McpError } from "../../../../types-global/errors.js";
10
+ import { logger } from "../../../../utils/index.js";
11
+ export class OauthStrategy {
12
+ constructor() {
13
+ if (config.mcpAuthMode !== "oauth") {
14
+ throw new Error("OauthStrategy instantiated for non-oauth auth mode.");
15
+ }
16
+ if (!config.oauthIssuerUrl || !config.oauthAudience) {
17
+ throw new Error("OAUTH_ISSUER_URL and OAUTH_AUDIENCE must be set for OAuth mode.");
18
+ }
19
+ try {
20
+ const jwksUrl = new URL(config.oauthJwksUri ||
21
+ `${config.oauthIssuerUrl.replace(/\/$/, "")}/.well-known/jwks.json`);
22
+ this.jwks = createRemoteJWKSet(jwksUrl, {
23
+ cooldownDuration: 300000, // 5 minutes
24
+ timeoutDuration: 5000, // 5 seconds
25
+ });
26
+ logger.info(`JWKS client initialized for URL: ${jwksUrl.href}`);
27
+ }
28
+ catch (error) {
29
+ logger.fatal("Failed to initialize JWKS client.", error);
30
+ throw new Error("Could not initialize JWKS client for OAuth strategy.");
31
+ }
32
+ }
33
+ async verify(token) {
34
+ try {
35
+ const { payload } = await jwtVerify(token, this.jwks, {
36
+ issuer: config.oauthIssuerUrl,
37
+ audience: config.oauthAudience,
38
+ });
39
+ const scopes = typeof payload.scope === "string" ? payload.scope.split(" ") : [];
40
+ if (scopes.length === 0) {
41
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Token must contain valid, non-empty scopes.");
42
+ }
43
+ const clientId = typeof payload.client_id === "string" ? payload.client_id : undefined;
44
+ if (!clientId) {
45
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, "Token must contain a 'client_id' claim.");
46
+ }
47
+ return {
48
+ token,
49
+ clientId,
50
+ scopes,
51
+ subject: typeof payload.sub === "string" ? payload.sub : undefined,
52
+ };
53
+ }
54
+ catch (error) {
55
+ if (error instanceof McpError)
56
+ throw error;
57
+ const message = error instanceof Error && error.name === "JWTExpired"
58
+ ? "Token has expired."
59
+ : "OAuth token verification failed.";
60
+ throw new McpError(BaseErrorCode.UNAUTHORIZED, message, {
61
+ originalError: error instanceof Error ? error.name : "Unknown",
62
+ });
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview MCP Transport Manager implementation using the MCP SDK.
3
+ * @module src/mcp-server/transports/core/mcpTransportManager
4
+ */
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import type { IncomingMessage, ServerResponse } from "http";
7
+ import { RequestContext } from "../../../utils/index.js";
8
+ import { TransportManager, TransportResponse, TransportSession } from "./transportTypes.js";
9
+ /**
10
+ * MCP Transport Manager that handles MCP SDK integration and session management.
11
+ */
12
+ export declare class McpTransportManager implements TransportManager {
13
+ private readonly transports;
14
+ private readonly sessions;
15
+ private readonly createServerInstanceFn;
16
+ constructor(createServerInstanceFn: () => Promise<McpServer>);
17
+ initializeSession(body: unknown, context: RequestContext): Promise<TransportResponse>;
18
+ handleRequest(sessionId: string, req: IncomingMessage, res: ServerResponse, context: RequestContext, body?: unknown): Promise<void>;
19
+ handleDeleteRequest(sessionId: string, context: RequestContext): Promise<TransportResponse>;
20
+ getSession(sessionId: string): TransportSession | undefined;
21
+ shutdown(): Promise<void>;
22
+ /**
23
+ * Helper method to close a specific session.
24
+ */
25
+ private closeSession;
26
+ /**
27
+ * Find existing session that should be closed for re-initialization.
28
+ * This is a simplified implementation - in reality you might want more
29
+ * sophisticated session management.
30
+ */
31
+ private findExistingSessionForReinit;
32
+ }