Skip to content

feat: add authorization middleware to protect endpoints #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
{
"inputs": [
{
"password": true,
"id": "mcp-server-sse-token",
"description": "Enter the token for the SSE server",
"type": "promptString",
}
],
"servers": {
"mcp-server-sse": {
"type": "sse",
"url": "http://localhost:3000/sse"
"url": "http://localhost:3000/sse",
"headers": {
"Authorization": "Bearer ${input:mcp-server-sse-token}"
}
},

"mcp-server-sse-remote": {
"type": "sse",
"url": "https://<container-id>.<location>.azurecontainerapps.io/sse"
"url": "https://mcp-container-ts.kindsand-78aa4194.swedencentral.azurecontainerapps.io/sse",
"headers": {
"Authorization": "Bearer ${input:mcp-server-sse-token}"
}
}
}
}
53 changes: 46 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,48 @@ The quickest way to connect to the MCP server is the use the provided [mcp.json]

```json
{
"inputs": [
{
"password": true,
"id": "mcp-server-sse-token",
"description": "Enter the token for the SSE server",
"type": "promptString",
}
],
"servers": {
"mcp-server-sse": {
"type": "sse",
"url": "http://localhost:3000/sse"
"url": "http://localhost:3000/sse",
"headers": {
"Authorization": "Bearer ${input:mcp-server-sse-token}"
}
}
}
}
```

Once you have this file opened, you can click on the "start" inlined action button that will connect the MCP server and fetch the available tools.

**IMPORTANT:** Because the server is secured with a token, you will be prompted by VS Code to enter the token. The demo token we are using is`abc`.

> [!NOTE]
> In a real world scenario, you would want to validate the token and use a more secure method of authentication. This is just a demo token for testing purposes. Learn more about to secure your server [here](https://learn.microsoft.com/en-us/entra/identity-platform/authentication-vs-authorization).


### Option 2 - Manually Adding MCP Server to VS Code

1. Add MCP Server from command palette and add URL to your running Function app's SSE endpoint:
1. Add MCP Server from command palette and add URL to your running server's SSE endpoint:

For local development, the URL will be:
```bash
http://localhost:3000/sse
```

For Azure Container Apps, the URL will be:
```bash
https://<your-app-name>.<region>.azurecontainerapps.io/sse
```

2. Select HTTP (Server-Sent-Events) for the type of MCP server to add.
3. Enter the URL to your running function app's SSE endpoint
4. Enter the server ID. (This can be any name you want)
Expand All @@ -210,12 +232,15 @@ npm run inspect

2. CTRL click to load the MCP Inspector web app from the URL displayed by the app (e.g. http://0.0.0.0:5173/#resources)
3. Set the transport type to SSE
4. Set the URL to your running Function app's SSE endpoint and Connect:
4. Add authentication header: `Authorization` and Bearer token: `abc`.
4. Set the URL to your running server's SSE endpoint and Connect:
```bash
http://localhost:3000/sse
```
5. List Tools. Click on a tool and Run Tool.

![alt](./docs/mcp-inspector.png)

## Deploy to Azure Container Apps

1. Install the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd) (azd)
Expand All @@ -238,14 +263,25 @@ azd up
https://<env-name>.<container-id>.<region>.azurecontainerapps.io
```

5. You can configure the MCP server in your local VS Code environment by adding the URL to the `mcp.json` file or manually adding it as described in the previous section:
5. You can configure the MCP server in your local VS Code environment by adding the URL to the `mcp.json` file or manually adding it as described in the section below:

```json
{
"inputs": [
{
"password": true,
"id": "mcp-server-sse-token",
"description": "Enter the token for the SSE server",
"type": "promptString"
}
],
"servers": {
"mcp-server-sse-remote": {
"type": "sse",
"url": "https://<your-app-name>.<region>.azurecontainerapps.io/sse"
"url": "https://<your-app-name>.<region>.azurecontainerapps.io/sse",
"headers": {
"Authorization": "Bearer ${input:mcp-server-sse-token}"
}
}
}
}
Expand All @@ -258,9 +294,12 @@ https://<env-name>.<container-id>.<region>.azurecontainerapps.io
6. If you were simply testing the deployment, you can remove and clean up all deployed resources by running the following command to avoid incurring any costs:

```bash
azd down
azd down --purge --force
```

## Next Steps

- Learn more about [related MCP efforts from Microsoft](https://github.com/microsoft/mcp)
- Learn more about [Model Context Protocol](https://modelcontextprotocol.io/)
- Learn more about [related MCP efforts from Microsoft](https://github.com/microsoft/mcp)
- Learn more about [Azure Container Apps](https://learn.microsoft.com/en-us/azure/container-apps/)
- Learn more about [Azure AI Foundry](https://ai.azure.com)
Binary file added docs/mcp-inspector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 16 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { logger } from './helpers/logs.js';
import { SSEPServer } from './server.js';

const log = logger('index');
const FAKE_TOKEN = 'abc';

const server = new SSEPServer(
new Server(
Expand All @@ -24,13 +25,26 @@ app.use(express.json());

const router = express.Router();

// Authorization middleware
function requireAuth(req: Request, res: Response, next: NextFunction) {
const auth = req.headers["Authorization"] || req.headers["authorization"];
if (auth !== `Bearer ${FAKE_TOKEN}`) {
log.error('Client not authorized');
res.status(401).json({ error: "Unauthorized" });
return;
}

log.success('Client authorized');
next();
}

// Legacy message endpoint for older clients
router.post('/messages', async (req: Request, res: Response) => {
router.post('/messages', requireAuth, async (req: Request, res: Response) => {
await server.handlePostRequest(req, res);
});

// Legacy SSE endpoint for older clients
router.get('/sse', async (req: Request, res: Response) => {
router.get('/sse', requireAuth, async (req: Request, res: Response) => {
await server.handleGetRequest(req, res);
});

Expand Down