Skip to content

Commit 4b7fcb0

Browse files
committed
PoC: remove sse, remove server auth, use better-auth for server auth examples, update faq
1 parent aaeff28 commit 4b7fcb0

54 files changed

Lines changed: 1262 additions & 5194 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@ dist/
133133

134134
# IDE
135135
.idea/
136+
.cursor/

docs/faq.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ For production use, you can either:
6565

6666
The SDK ships several runnable server examples under `examples/server/src`. Start from the server examples index in [`examples/server/README.md`](../examples/server/README.md) and the entry-point quick start in the root [`README.md`](../README.md).
6767

68+
### Why did we remove `server` auth exports?
69+
70+
Server authentication & authorization is outside of the scope of the SDK, and the recommendation is to use packages that focus on this area specifically (or a full-fledged Authorization Server for those who use such). Example packages provide an example with `better-auth`.
71+
72+
### Why did we remove `server` SSE transport?
73+
74+
The SSE transport has been deprecated for a long time, and `v2` will not support it on the server side any more. Client side will keep supporting it in order to be able to connect to legacy SSE servers via the `v2` SDK, but serving SSE from `v2` will not be possible. Servers wanting to switch to `v2` and using SSE should migrate to Streamable HTTP.
75+
6876
## v1 (legacy)
6977

7078
### Where do v1 documentation and v1-specific fixes live?

examples/server/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@
3535
},
3636
"dependencies": {
3737
"@hono/node-server": "catalog:runtimeServerOnly",
38-
"hono": "catalog:runtimeServerOnly",
3938
"@modelcontextprotocol/examples-shared": "workspace:^",
4039
"@modelcontextprotocol/server": "workspace:^",
4140
"@modelcontextprotocol/server-express": "workspace:^",
4241
"@modelcontextprotocol/server-hono": "workspace:^",
42+
"better-auth": "^1.4.7",
4343
"cors": "catalog:runtimeServerOnly",
4444
"express": "catalog:runtimeServerOnly",
45+
"hono": "catalog:runtimeServerOnly",
4546
"zod": "catalog:runtimeShared"
4647
},
4748
"devDependencies": {

examples/server/src/elicitationUrlExample.ts

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@
99

1010
import { randomUUID } from 'node:crypto';
1111

12-
import { setupAuthServer } from '@modelcontextprotocol/examples-shared';
13-
import type { CallToolResult, ElicitRequestURLParams, ElicitResult, OAuthMetadata } from '@modelcontextprotocol/server';
1412
import {
15-
checkResourceAllowed,
1613
getOAuthProtectedResourceMetadataUrl,
14+
mcpAuthMetadataRouter,
15+
requireBearerAuth,
16+
setupAuthServer
17+
} from '@modelcontextprotocol/examples-shared';
18+
import type { CallToolResult, ElicitRequestURLParams, ElicitResult, OAuthMetadata } from '@modelcontextprotocol/server';
19+
import {
1720
isInitializeRequest,
1821
McpServer,
1922
NodeStreamableHTTPServerTransport,
2023
UrlElicitationRequiredError
2124
} from '@modelcontextprotocol/server';
22-
import { createMcpExpressApp, mcpAuthMetadataRouter, requireBearerAuth } from '@modelcontextprotocol/server-express';
25+
import { createMcpExpressApp } from '@modelcontextprotocol/server-express';
2326
import cors from 'cors';
2427
import type { Request, Response } from 'express';
2528
import express from 'express';
@@ -238,47 +241,6 @@ const authServerUrl = new URL(`http://localhost:${AUTH_PORT}`);
238241

239242
const oauthMetadata: OAuthMetadata = setupAuthServer({ authServerUrl, mcpServerUrl, strictResource: true });
240243

241-
const tokenVerifier = {
242-
verifyAccessToken: async (token: string) => {
243-
const endpoint = oauthMetadata.introspection_endpoint;
244-
245-
if (!endpoint) {
246-
throw new Error('No token verification endpoint available in metadata');
247-
}
248-
249-
const response = await fetch(endpoint, {
250-
method: 'POST',
251-
headers: {
252-
'Content-Type': 'application/x-www-form-urlencoded'
253-
},
254-
body: new URLSearchParams({
255-
token: token
256-
}).toString()
257-
});
258-
259-
if (!response.ok) {
260-
const text = await response.text().catch(() => null);
261-
throw new Error(`Invalid or expired token: ${text}`);
262-
}
263-
264-
const data = (await response.json()) as { aud: string; client_id: string; scope: string; exp: number };
265-
266-
if (!data.aud) {
267-
throw new Error(`Resource Indicator (RFC8707) missing`);
268-
}
269-
if (!checkResourceAllowed({ requestedResource: data.aud, configuredResource: mcpServerUrl })) {
270-
throw new Error(`Expected resource indicator ${mcpServerUrl}, got: ${data.aud}`);
271-
}
272-
273-
// Convert the response to AuthInfo format
274-
return {
275-
token,
276-
clientId: data.client_id,
277-
scopes: data.scope ? data.scope.split(' ') : [],
278-
expiresAt: data.exp
279-
};
280-
}
281-
};
282244
// Add metadata routes to the main MCP server
283245
app.use(
284246
mcpAuthMetadataRouter({
@@ -290,9 +252,10 @@ app.use(
290252
);
291253

292254
authMiddleware = requireBearerAuth({
293-
verifier: tokenVerifier,
294255
requiredScopes: [],
295-
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(mcpServerUrl)
256+
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(mcpServerUrl),
257+
strictResource: true,
258+
expectedResource: mcpServerUrl
296259
});
297260

298261
/**

examples/server/src/honoWebStandardStreamableHttp.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import { serve } from '@hono/node-server';
1111
import type { CallToolResult } from '@modelcontextprotocol/server';
1212
import { McpServer, WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';
13-
import { mcpStreamableHttpHandler } from '@modelcontextprotocol/server-hono';
1413
import { Hono } from 'hono';
1514
import { cors } from 'hono/cors';
1615
import * as z from 'zod/v4';
@@ -57,7 +56,7 @@ app.use(
5756
app.get('/health', c => c.json({ status: 'ok' }));
5857

5958
// MCP endpoint
60-
app.all('/mcp', mcpStreamableHttpHandler(transport));
59+
app.all('/mcp', c => transport.handleRequest(c.req.raw));
6160

6261
// Start the server
6362
const PORT = process.env.MCP_PORT ? parseInt(process.env.MCP_PORT, 10) : 3000;

examples/server/src/simpleSseServer.ts

Lines changed: 0 additions & 175 deletions
This file was deleted.

0 commit comments

Comments
 (0)