Hello! It's been a long time since we last continued the series on building an MCP server. Recently, due to a lot of work, I finally managed to set aside some time to continue writing today.
The MCP specification clearly outlines the authentication mechanism to be used for a remote MCP server. Essentially, it is the authentication process as per the Oauth 2.1 specification. In summary, the process involves the following steps:
Step 1: The client discovers the MCP server and asks whether authentication is required before use. The server responds by indicating either no authentication is needed or providing the necessary paths for user authentication if it is required.
Step 2: The client redirects the user to the authentication pages as instructed by the server.
Step 3: The user authenticates.
Step 4: The authentication process is completed, and normal usage begins.
Overall, these four steps are quite straightforward, but behind them lies a complex process that demands significant implementation efforts from both sides. That is, if you implement an MCP server with Oauth 2.1 authentication flow, the client must also support that authentication flow; otherwise, it cannot be used. I spent a lot of time researching and found that there are almost no free clients implementing the Oauth 2.1 authentication flow.
Because it's too complicated, I decided not to delve further into this process. Instead, we should approach two simpler methods described below.
First, for a local MCP server, as mentioned in the previous article. A local MCP server uses npx or node to run a Node.js process on the machine and return results. The configuration looks like this:
{
"mcpServers": {
"mcp-2coffee": {
"command": "node",
"args": [
"/path/to/mcp-2coffee/build/index.js"
]
}
}
}
/path/to/mcp-2coffee/build/index.js can contain API calls to another server requiring authentication via API Key or Authorization in the headers... To achieve this, simply add an env value to the configuration. The processing code can then retrieve this variable from the env specified by the user.
{
"mcpServers": {
"mcp-2coffee": {
"command": "node",
"args": [
"/path/to/mcp-2coffee/build/index.js"
],
"env": {
"X-API-KEY": "xxx..xxx"
}
}
}
}
For a remote MCP server, the method is quite similar, but instead of adding the env attribute, include it in the headers.
"mcp-2coffee-remote": {
"command": "npx",
"args": [
"mcp-remote@0.1.18",
"http://localhost:3000/mcp",
"--header",
"X-API-KEY: xxx..xxx"
]
}
However, this is only a temporary solution to reduce the complexity of implementing authentication for a remote MCP server. Although Anthropic is working hard to improve the MCP specification, it seems to be becoming more complex and fragmented. Hopefully, in the near future, we will have a definitive solution to this issue.
You can refer to the server implementation code on Github. In the next article, we will explore how to create an MCP Client together.