Skip to content

Commit 99de77f

Browse files
committed
chore: update mcp-express readme file
1 parent 0e76f95 commit 99de77f

File tree

1 file changed

+119
-30
lines changed

1 file changed

+119
-30
lines changed

packages/mcp-express/README.md

Lines changed: 119 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ Express middleware for enforcing Model Context Protocol (MCP) authorization usin
1010
This package provides Express middleware that implements Model Context Protocol (MCP) based authorization for Express.js
1111
applications. It integrates with Asgardeo for authentication and authorization services.
1212

13-
This package is part of the
14-
[Asgardeo MCP Node.js SDKs monorepo](https://github.com/asgardeo/asgardeo-mcp-node#readme). For overall project
15-
information, contribution guidelines, and details on other related packages, please refer to the main repository.
13+
This package is part of the [Asgardeo MCP Node.js SDKs monorepo](https://github.com/asgardeo/asgardeo-mcp-node#readme).
14+
For overall project information, contribution guidelines, and details on other related packages, please refer to the
15+
main repository.
1616

1717
## Installation
1818

@@ -32,30 +32,31 @@ pnpm add @asgardeo/mcp-express
3232
- Built-in CORS support
3333
- Seamless integration with Asgardeo
3434

35-
## Usage
35+
### Basic Setup
3636

3737
```typescript
3838
import express from 'express';
3939
import {McpAuth, protectedRoute} from '@asgardeo/mcp-express';
4040

4141
const app = express();
4242

43-
// Initialize MCP authentication server with baseUrl
43+
// Initialize MCP authentication middleware with baseUrl
4444
app.use(
4545
McpAuth({
4646
baseUrl: process.env.BASE_URL as string,
4747
}),
4848
);
4949

50-
// Public routes
51-
app.get('/api/public', (req, res) => {
52-
res.json({message: 'This is a public endpoint'});
53-
});
54-
55-
// Protected routes
56-
app.use('/api/protected', protectedRoute, (req, res) => {
57-
res.json({message: 'This is a protected endpoint'});
58-
});
50+
// Protect your MCP endpoint
51+
app.post(
52+
'/mcp',
53+
protectedRoute({
54+
baseUrl: process.env.BASE_URL as string,
55+
}),
56+
async (req, res) => {
57+
// Your MCP handling logic here
58+
},
59+
);
5960
```
6061

6162
### API Reference
@@ -96,31 +97,119 @@ interface McpAuthOptions {
9697
Here's a complete example of setting up an Express server with MCP authentication:
9798

9899
```typescript
99-
import express from 'express';
100+
import {randomUUID} from 'node:crypto';
100101
import {McpAuth, protectedRoute} from '@asgardeo/mcp-express';
102+
import {McpServer} from '@modelcontextprotocol/sdk/server/mcp';
103+
import {StreamableHTTPServerTransport} from '@modelcontextprotocol/sdk/server/streamableHttp';
104+
import {isInitializeRequest} from '@modelcontextprotocol/sdk/types';
105+
import {config} from 'dotenv';
106+
import express, {Express, Request, Response} from 'express';
107+
import {z} from 'zod';
101108

102-
const app = express();
103-
const port = process.env.PORT || 3000;
109+
config();
104110

111+
const app: Express = express();
105112
app.use(express.json());
113+
app.use(
114+
McpAuth({
115+
baseUrl: process.env.BASE_URL as string,
116+
}),
117+
);
106118

107-
// Initialize MCP authentication
108-
app.use(McpAuth());
119+
// Session management
120+
interface TransportMap {
121+
[sessionId: string]: {
122+
lastAccess: number;
123+
transport: StreamableHTTPServerTransport;
124+
};
125+
}
109126

110-
// Public routes
111-
app.use('/api', publicRoutes);
127+
const transports: TransportMap = {};
128+
const SESSION_TIMEOUT_MS: number = 30 * 60 * 1000;
112129

113-
// Protected routes with MCP authentication
114-
app.use('/api/protected', protectedRoute, protectedRoutes);
130+
const isSessionExpired = (lastAccessTime: number): boolean => Date.now() - lastAccessTime > SESSION_TIMEOUT_MS;
115131

116-
// Error handling
117-
app.use((err, req, res, next) => {
118-
console.error(err.stack);
119-
res.status(500).json({error: 'Something broke!'});
120-
});
132+
// MCP endpoint with authentication
133+
app.post(
134+
'/mcp',
135+
protectedRoute({
136+
baseUrl: process.env.BASE_URL as string,
137+
}),
138+
async (req: Request, res: Response): Promise<void> => {
139+
try {
140+
const sessionId: string | undefined = req.headers['mcp-session-id'] as string | undefined;
141+
let transport: StreamableHTTPServerTransport;
142+
143+
// Handle existing session or create new one
144+
if (sessionId && transports[sessionId]) {
145+
// Session management code...
146+
transport = transports[sessionId].transport;
147+
transports[sessionId].lastAccess = Date.now();
148+
} else if (!sessionId && isInitializeRequest(req.body)) {
149+
// Extract bearer token if present
150+
let bearerToken: string | undefined;
151+
const authHeader: string | undefined = req.headers.authorization as string | undefined;
152+
if (authHeader && authHeader.toLowerCase().startsWith('bearer ')) {
153+
bearerToken = authHeader.substring(7);
154+
console.log(`Bearer token captured for new session.`);
155+
}
156+
157+
// Create MCP server and configure tools
158+
transport = new StreamableHTTPServerTransport({
159+
// Transport configuration...
160+
});
161+
162+
const server: McpServer = new McpServer({
163+
name: 'example-server',
164+
version: '1.0.0',
165+
});
166+
167+
// Define MCP tools
168+
server.tool(
169+
'get_pet_vaccination_info',
170+
'Retrieves the vaccination history for a specific pet.',
171+
{
172+
petId: z.string().describe('The unique identifier for the pet.'),
173+
},
174+
async ({petId}) => {
175+
// Tool implementation using bearer token
176+
return {
177+
content: [
178+
{
179+
text: `Retrieved vaccination info for pet ID: ${petId}. Token was ${
180+
bearerToken ? 'present' : 'absent'
181+
}.`,
182+
type: 'text',
183+
},
184+
],
185+
};
186+
},
187+
);
188+
189+
await server.connect(transport);
190+
} else {
191+
// Handle invalid requests
192+
res.status(400).json({
193+
error: {
194+
code: -32000,
195+
message: 'Bad Request',
196+
},
197+
id: req.body?.id || null,
198+
jsonrpc: '2.0',
199+
});
200+
return;
201+
}
202+
203+
await transport.handleRequest(req, res, req.body);
204+
} catch (error) {
205+
// Error handling
206+
}
207+
},
208+
);
121209

122-
app.listen(port, () => {
123-
console.log(`Server is running on port ${port}`);
210+
const PORT: string | number = process.env.PORT || 3000;
211+
app.listen(PORT, (): void => {
212+
console.log(`MCP server running on port ${PORT}`);
124213
});
125214
```
126215

0 commit comments

Comments
 (0)