@postman/test-mcp-server 1.0.0

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 (127) hide show
  1. package/README.md +478 -0
  2. package/dist/index.d.ts +13 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +50 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/instructions.md +24 -0
  7. package/dist/logger.d.ts +8 -0
  8. package/dist/logger.d.ts.map +1 -0
  9. package/dist/logger.js +27 -0
  10. package/dist/logger.js.map +1 -0
  11. package/dist/oauth/config.d.ts +6 -0
  12. package/dist/oauth/config.d.ts.map +1 -0
  13. package/dist/oauth/config.js +13 -0
  14. package/dist/oauth/config.js.map +1 -0
  15. package/dist/oauth/helpers.d.ts +17 -0
  16. package/dist/oauth/helpers.d.ts.map +1 -0
  17. package/dist/oauth/helpers.js +100 -0
  18. package/dist/oauth/helpers.js.map +1 -0
  19. package/dist/oauth/index.d.ts +17 -0
  20. package/dist/oauth/index.d.ts.map +1 -0
  21. package/dist/oauth/index.js +15 -0
  22. package/dist/oauth/index.js.map +1 -0
  23. package/dist/oauth/middleware.d.ts +15 -0
  24. package/dist/oauth/middleware.d.ts.map +1 -0
  25. package/dist/oauth/middleware.js +46 -0
  26. package/dist/oauth/middleware.js.map +1 -0
  27. package/dist/oauth/routes.d.ts +3 -0
  28. package/dist/oauth/routes.d.ts.map +1 -0
  29. package/dist/oauth/routes.js +476 -0
  30. package/dist/oauth/routes.js.map +1 -0
  31. package/dist/oauth/stores.d.ts +6 -0
  32. package/dist/oauth/stores.d.ts.map +1 -0
  33. package/dist/oauth/stores.js +20 -0
  34. package/dist/oauth/stores.js.map +1 -0
  35. package/dist/oauth/types.d.ts +46 -0
  36. package/dist/oauth/types.d.ts.map +1 -0
  37. package/dist/oauth/types.js +5 -0
  38. package/dist/oauth/types.js.map +1 -0
  39. package/dist/prompts/index.d.ts +99 -0
  40. package/dist/prompts/index.d.ts.map +1 -0
  41. package/dist/prompts/index.js +135 -0
  42. package/dist/prompts/index.js.map +1 -0
  43. package/dist/resources/index.d.ts +70 -0
  44. package/dist/resources/index.d.ts.map +1 -0
  45. package/dist/resources/index.js +79 -0
  46. package/dist/resources/index.js.map +1 -0
  47. package/dist/server/index.d.ts +11 -0
  48. package/dist/server/index.d.ts.map +1 -0
  49. package/dist/server/index.js +234 -0
  50. package/dist/server/index.js.map +1 -0
  51. package/dist/tools/constants.d.ts +5 -0
  52. package/dist/tools/constants.d.ts.map +1 -0
  53. package/dist/tools/constants.js +5 -0
  54. package/dist/tools/constants.js.map +1 -0
  55. package/dist/tools/definitions/add.d.ts +10 -0
  56. package/dist/tools/definitions/add.d.ts.map +1 -0
  57. package/dist/tools/definitions/add.js +24 -0
  58. package/dist/tools/definitions/add.js.map +1 -0
  59. package/dist/tools/definitions/annotatedMessage.d.ts +14 -0
  60. package/dist/tools/definitions/annotatedMessage.d.ts.map +1 -0
  61. package/dist/tools/definitions/annotatedMessage.js +63 -0
  62. package/dist/tools/definitions/annotatedMessage.js.map +1 -0
  63. package/dist/tools/definitions/echo.d.ts +9 -0
  64. package/dist/tools/definitions/echo.d.ts.map +1 -0
  65. package/dist/tools/definitions/echo.js +17 -0
  66. package/dist/tools/definitions/echo.js.map +1 -0
  67. package/dist/tools/definitions/elicitation.d.ts +8 -0
  68. package/dist/tools/definitions/elicitation.d.ts.map +1 -0
  69. package/dist/tools/definitions/elicitation.js +175 -0
  70. package/dist/tools/definitions/elicitation.js.map +1 -0
  71. package/dist/tools/definitions/getResourceLinks.d.ts +9 -0
  72. package/dist/tools/definitions/getResourceLinks.d.ts.map +1 -0
  73. package/dist/tools/definitions/getResourceLinks.js +31 -0
  74. package/dist/tools/definitions/getResourceLinks.js.map +1 -0
  75. package/dist/tools/definitions/getResourceReference.d.ts +9 -0
  76. package/dist/tools/definitions/getResourceReference.d.ts.map +1 -0
  77. package/dist/tools/definitions/getResourceReference.js +36 -0
  78. package/dist/tools/definitions/getResourceReference.js.map +1 -0
  79. package/dist/tools/definitions/getTinyImage.d.ts +7 -0
  80. package/dist/tools/definitions/getTinyImage.d.ts.map +1 -0
  81. package/dist/tools/definitions/getTinyImage.js +30 -0
  82. package/dist/tools/definitions/getTinyImage.js.map +1 -0
  83. package/dist/tools/definitions/listRoots.d.ts +8 -0
  84. package/dist/tools/definitions/listRoots.d.ts.map +1 -0
  85. package/dist/tools/definitions/listRoots.js +54 -0
  86. package/dist/tools/definitions/listRoots.js.map +1 -0
  87. package/dist/tools/definitions/longRunningOperation.d.ts +10 -0
  88. package/dist/tools/definitions/longRunningOperation.d.ts.map +1 -0
  89. package/dist/tools/definitions/longRunningOperation.js +39 -0
  90. package/dist/tools/definitions/longRunningOperation.js.map +1 -0
  91. package/dist/tools/definitions/printEnv.d.ts +7 -0
  92. package/dist/tools/definitions/printEnv.d.ts.map +1 -0
  93. package/dist/tools/definitions/printEnv.js +19 -0
  94. package/dist/tools/definitions/printEnv.js.map +1 -0
  95. package/dist/tools/definitions/sampleLlm.d.ts +10 -0
  96. package/dist/tools/definitions/sampleLlm.d.ts.map +1 -0
  97. package/dist/tools/definitions/sampleLlm.js +48 -0
  98. package/dist/tools/definitions/sampleLlm.js.map +1 -0
  99. package/dist/tools/definitions/structuredContent.d.ts +14 -0
  100. package/dist/tools/definitions/structuredContent.d.ts.map +1 -0
  101. package/dist/tools/definitions/structuredContent.js +29 -0
  102. package/dist/tools/definitions/structuredContent.js.map +1 -0
  103. package/dist/tools/definitions/zipResources.d.ts +9 -0
  104. package/dist/tools/definitions/zipResources.d.ts.map +1 -0
  105. package/dist/tools/definitions/zipResources.js +41 -0
  106. package/dist/tools/definitions/zipResources.js.map +1 -0
  107. package/dist/tools/index.d.ts +19 -0
  108. package/dist/tools/index.d.ts.map +1 -0
  109. package/dist/tools/index.js +71 -0
  110. package/dist/tools/index.js.map +1 -0
  111. package/dist/tools/types.d.ts +28 -0
  112. package/dist/tools/types.d.ts.map +1 -0
  113. package/dist/tools/types.js +2 -0
  114. package/dist/tools/types.js.map +1 -0
  115. package/dist/transports/sse.d.ts +2 -0
  116. package/dist/transports/sse.d.ts.map +1 -0
  117. package/dist/transports/sse.js +56 -0
  118. package/dist/transports/sse.js.map +1 -0
  119. package/dist/transports/stdio.d.ts +3 -0
  120. package/dist/transports/stdio.d.ts.map +1 -0
  121. package/dist/transports/stdio.js +28 -0
  122. package/dist/transports/stdio.js.map +1 -0
  123. package/dist/transports/streamableHttpServer.d.ts +37 -0
  124. package/dist/transports/streamableHttpServer.d.ts.map +1 -0
  125. package/dist/transports/streamableHttpServer.js +242 -0
  126. package/dist/transports/streamableHttpServer.js.map +1 -0
  127. package/package.json +76 -0
package/README.md ADDED
@@ -0,0 +1,478 @@
1
+ # Test MCP Server for MCP E2E Tests
2
+
3
+ A test MCP server used for E2E tests in the MCP Client. This originally was based off of the MCP Everything Server, but has been given new capabilities which the MCP Client handles.
4
+
5
+ ## Building
6
+
7
+ ```bash
8
+ npm install
9
+ npm run build
10
+ ```
11
+
12
+ ## Running
13
+
14
+ ### STDIO Transport (Default)
15
+ ```bash
16
+ npm start
17
+ # or
18
+
19
+ ```node dist/index.js stdio
20
+
21
+ ### SSE Transport
22
+ ```bash
23
+ npm run start:sse
24
+ # or
25
+ node dist/index.js sse
26
+ ```
27
+
28
+ ### Streamable HTTP Transport
29
+ ```bash
30
+ npm run start:streamableHttp
31
+ # or
32
+ node dist/index.js streamableHttp
33
+ ```
34
+
35
+ ### Streamable HTTP with OAuth2 Authentication
36
+ ```bash
37
+ npm run start:streamableHttp:auth
38
+ # or
39
+ node dist/index.js streamableHttp --auth
40
+ ```
41
+
42
+ This transport requires [OAuth2 Bearer token authentication](#oauth2-configuration) for all MCP endpoints.
43
+
44
+ ## Available Tools
45
+
46
+ | Tool | Description |
47
+ |------|-------------|
48
+ | `echo` | Echoes back the input |
49
+ | `add` | Adds two numbers |
50
+ | `longRunningOperation` | Demonstrates progress updates |
51
+ | `printEnv` | Prints environment variables |
52
+ | `sampleLLM` | Samples from an LLM using MCP's sampling feature |
53
+ | `getTinyImage` | Returns a small test image |
54
+ | `annotatedMessage` | Demonstrates content annotations |
55
+ | `getResourceReference` | Returns a resource reference |
56
+ | `getResourceLinks` | Returns multiple resource links |
57
+ | `structuredContent` | Returns structured content with schema |
58
+ | `zip` | Creates a zip file from URLs |
59
+ | `listRoots` | Lists MCP roots (if client supports) |
60
+ | `startElicitation` | Demonstrates user input elicitation (if client supports) |
61
+
62
+ ## Available Prompts
63
+
64
+ | Prompt | Description |
65
+ |--------|-------------|
66
+ | `simple_prompt` | A prompt without arguments |
67
+ | `complex_prompt` | A prompt with temperature and style arguments |
68
+ | `resource_prompt` | A prompt that includes an embedded resource |
69
+
70
+ ## Resources
71
+
72
+ The server provides 100 static resources:
73
+ - Even-numbered resources contain plaintext
74
+ - Odd-numbered resources contain binary data
75
+ - Accessible via URI pattern: `test://static/resource/{id}`
76
+
77
+
78
+
79
+ ## Project Structure
80
+
81
+ ```
82
+ src/
83
+ ├── index.ts # Main entry point with transport selection
84
+ ├── logger.ts # Pino logger configuration
85
+ ├── server/
86
+ │ └── index.ts # Server creation and request handler wiring
87
+ ├── tools/
88
+ │ ├── index.ts # Tool registry, listing, and call routing
89
+ │ ├── types.ts # Tool type definitions
90
+ │ ├── constants.ts # Tool names enum and constants
91
+ │ └── definitions/ # Individual tool definitions
92
+ │ ├── echo.ts
93
+ │ ├── add.ts
94
+ │ └── ... # One file per tool
95
+ ├── prompts/
96
+ │ └── index.ts # Prompt definitions and handlers
97
+ ├── resources/
98
+ │ └── index.ts # Resource definitions and handlers
99
+ ├── oauth/
100
+ │ ├── index.ts # OAuth module exports
101
+ │ ├── config.ts # OAuth configuration
102
+ │ ├── types.ts # OAuth type definitions
103
+ │ ├── stores.ts # In-memory token/client stores
104
+ │ ├── helpers.ts # Token generation utilities
105
+ │ ├── middleware.ts # Auth middleware
106
+ │ └── routes.ts # OAuth endpoints
107
+ └── transports/
108
+ ├── stdio.ts # Standard I/O transport
109
+ ├── sse.ts # Server-Sent Events transport
110
+ └── streamableHttpServer.ts # Streamable HTTP (with optional OAuth2)
111
+ ```
112
+
113
+ ## Scripts
114
+
115
+ | Command | Description |
116
+ |---------|-------------|
117
+ | `npm run build` | Compile TypeScript to JavaScript |
118
+ | `npm run clean` | Remove `dist/` and build artifacts |
119
+ | `npm run clean:all` | Remove `dist/`, `node_modules/`, logs, and all generated files |
120
+ | `npm run lint` | Check for linting errors |
121
+ | `npm run lint:fix` | Fix auto-fixable linting errors |
122
+ | `npm run format` | Format code with Prettier |
123
+ | `npm run format:check` | Check if code is formatted |
124
+ | `npm run watch` | Watch mode for development |
125
+ | `npm start` | Start with STDIO transport |
126
+ | `npm run start:stdio` | Start with STDIO transport |
127
+ | `npm run start:sse` | Start with SSE transport |
128
+ | `npm run start:streamableHttp` | Start with Streamable HTTP transport |
129
+ | `npm run start:streamableHttp:auth` | Start with Streamable HTTP + OAuth2 |
130
+ | `npm test` | Run all tests |
131
+ | `npm run test:watch` | Run tests in watch mode |
132
+ | `npm run test:unit` | Run only unit tests |
133
+ | `npm run test:e2e` | Run only E2E tests |
134
+ | `npm run test:coverage` | Run tests with coverage report |
135
+
136
+ ## Testing
137
+
138
+ This project uses [Vitest](https://vitest.dev/) for testing, with both unit and end-to-end (E2E) tests.
139
+
140
+ ### Test Structure
141
+
142
+ ```
143
+ src/
144
+ ├── tools/
145
+ │ └── __tests__/ # Unit tests for tools
146
+ │ ├── echo.test.ts
147
+ │ ├── add.test.ts
148
+ │ ├── getTinyImage.test.ts
149
+ │ └── index.test.ts
150
+ ├── prompts/
151
+ │ └── __tests__/ # Unit tests for prompts
152
+ │ └── index.test.ts
153
+ ├── resources/
154
+ │ └── __tests__/ # Unit tests for resources
155
+ │ └── index.test.ts
156
+ └── oauth/
157
+ └── __tests__/ # Unit tests for OAuth
158
+ ├── helpers.test.ts
159
+ └── middleware.test.ts
160
+
161
+ e2e/ # End-to-end tests
162
+ ├── helpers/
163
+ │ └── server.ts # Test helpers for server management
164
+ ├── stdio.test.ts # STDIO transport tests
165
+ ├── sse.test.ts # SSE transport tests
166
+ ├── streamableHttp.test.ts # Streamable HTTP transport tests
167
+ └── oauth.test.ts # OAuth2 flow tests
168
+ ```
169
+
170
+ ### Running Tests
171
+
172
+ ```bash
173
+ # Run all tests
174
+ npm test
175
+
176
+ # Run tests in watch mode (during development)
177
+ npm run test:watch
178
+
179
+ # Run only unit tests
180
+ npm run test:unit
181
+
182
+ # Run only E2E tests
183
+ npm run test:e2e
184
+
185
+ # Run tests with coverage report
186
+ npm run test:coverage
187
+ ```
188
+
189
+ ### Unit Tests
190
+
191
+ Unit tests verify individual components in isolation:
192
+
193
+ - **Tools**: Test handler outputs for each tool (echo, add, getTinyImage, etc.)
194
+ - **Prompts**: Test prompt generation and completion handling
195
+ - **Resources**: Test resource creation, listing, pagination, and reading
196
+ - **OAuth**: Test token generation, validation, and middleware
197
+
198
+ Example test:
199
+
200
+ ```typescript
201
+ import { describe, it, expect } from "vitest";
202
+ import { handler } from "../definitions/echo.js";
203
+
204
+ describe("echo tool", () => {
205
+ it("should echo the message back", async () => {
206
+ const result = await handler({ message: "hello" }, mockExtra, mockContext);
207
+ expect(result.content[0].text).toBe("Echo: hello");
208
+ });
209
+ });
210
+ ```
211
+
212
+ ### E2E Tests
213
+
214
+ E2E tests spin up the actual server and test real client-server communication:
215
+
216
+ - **STDIO Transport**: Tests using `StdioClientTransport`
217
+ - **SSE Transport**: Tests using `SSEClientTransport`
218
+ - **Streamable HTTP Transport**: Tests using `StreamableHTTPClientTransport`
219
+ - **OAuth Flow**: Tests full OAuth2 flows (client_credentials, authorization_code with PKCE, refresh_token)
220
+
221
+ E2E tests verify:
222
+ - Server startup and connection
223
+ - Tool listing and execution
224
+ - Prompt listing and retrieval
225
+ - Resource listing, pagination, and reading
226
+ - OAuth token issuance, introspection, and revocation
227
+ - Authenticated MCP requests
228
+
229
+ ### Prerequisites for Testing
230
+
231
+ Before running tests, ensure the project is built:
232
+
233
+ ```bash
234
+ npm run build
235
+ ```
236
+
237
+ E2E tests require the built `dist/` files since they spawn server processes.
238
+
239
+ ### Configuration
240
+
241
+ Configure logging via environment variables:
242
+
243
+ | Variable | Description | Default |
244
+ |----------|-------------|---------|
245
+ | `LOG_LEVEL` | Log level (trace, debug, info, warn, error, fatal) | `debug` |
246
+
247
+ ### Component Loggers
248
+
249
+ The codebase uses child loggers for different components:
250
+ - `server` - Core server operations
251
+ - `transport` - Transport layer (stdio, sse, http)
252
+ - `tools` - Tool execution
253
+ - `oauth` - OAuth2 authentication
254
+
255
+
256
+ ## OAuth2 Configuration
257
+
258
+ Configure via environment variables (optional, defaults provided for testing):
259
+ - `OAUTH_CLIENT_ID` - Client ID (default: `mcp-client`)
260
+ - `OAUTH_CLIENT_SECRET` - Client secret (default: `mcp-secret`)
261
+ - `OAUTH_TOKEN_SECRET` - Secret for signing tokens (change in production!)
262
+ - `PORT` - Server port (default: `3001`)
263
+
264
+ #### Supported Grant Types
265
+
266
+ | Grant Type | Description |
267
+ |------------|-------------|
268
+ | `client_credentials` | Server-to-server authentication |
269
+ | `authorization_code` | User authorization flow (with optional PKCE) |
270
+ | `refresh_token` | Refresh an expired access token |
271
+
272
+ #### Getting a Token (Client Credentials)
273
+
274
+ ```bash
275
+ curl -X POST http://localhost:3001/oauth/token \
276
+ -d "grant_type=client_credentials" \
277
+ -d "client_id=mcp-client" \
278
+ -d "client_secret=mcp-secret"
279
+ ```
280
+
281
+ #### Authorization Code Flow (with PKCE)
282
+
283
+ 1. **Generate PKCE values** (client-side):
284
+ ```bash
285
+ # Generate code_verifier (43-128 chars)
286
+ CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=' | tr '/+' '_-')
287
+
288
+ # Generate code_challenge (S256)
289
+ CODE_CHALLENGE=$(echo -n $CODE_VERIFIER | openssl sha256 -binary | base64 | tr -d '=' | tr '/+' '_-')
290
+ ```
291
+
292
+ 2. **Redirect user to authorization endpoint**:
293
+ ```
294
+ http://localhost:3001/oauth/authorize?
295
+ response_type=code&
296
+ client_id=mcp-client&
297
+ redirect_uri=http://localhost:3000/callback&
298
+ scope=mcp:read%20mcp:write&
299
+ state=random-state&
300
+ code_challenge=$CODE_CHALLENGE&
301
+ code_challenge_method=S256
302
+ ```
303
+
304
+ 3. **Exchange code for tokens**:
305
+ ```bash
306
+ curl -X POST http://localhost:3001/oauth/token \
307
+ -d "grant_type=authorization_code" \
308
+ -d "code=<authorization-code>" \
309
+ -d "redirect_uri=http://localhost:3000/callback" \
310
+ -d "client_id=mcp-client" \
311
+ -d "code_verifier=$CODE_VERIFIER"
312
+ ```
313
+
314
+ #### Refreshing Tokens
315
+
316
+ ```bash
317
+ curl -X POST http://localhost:3001/oauth/token \
318
+ -d "grant_type=refresh_token" \
319
+ -d "refresh_token=<your-refresh-token>" \
320
+ -d "client_id=mcp-client"
321
+ ```
322
+
323
+ Response (for authorization_code and refresh_token grants):
324
+ ```json
325
+ {
326
+ "access_token": "uuid-token.signature",
327
+ "token_type": "Bearer",
328
+ "expires_in": 3600,
329
+ "refresh_token": "rt_uuid...",
330
+ "scope": "mcp:read mcp:write"
331
+ }
332
+ ```
333
+
334
+ #### Using the Token
335
+
336
+ Include the token in all MCP requests:
337
+ ```bash
338
+ curl -X POST http://localhost:3001/mcp \
339
+ -H "Authorization: Bearer <your-access-token>" \
340
+ -H "Content-Type: application/json" \
341
+ -d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}'
342
+ ```
343
+
344
+ #### OAuth2 Endpoints
345
+
346
+ | Endpoint | Method | Description |
347
+ |----------|--------|-------------|
348
+ | `/.well-known/oauth-authorization-server` | GET | Authorization Server Metadata ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)) |
349
+ | `/oauth/register` | POST | Dynamic Client Registration ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)) |
350
+ | `/oauth/authorize` | GET | Authorization endpoint for authorization_code flow |
351
+ | `/oauth/token` | POST | Token endpoint (all grant types) |
352
+ | `/oauth/introspect` | POST | Token introspection ([RFC 7662](https://datatracker.ietf.org/doc/html/rfc7662)) |
353
+ | `/oauth/revoke` | POST | Token revocation ([RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009)) |
354
+ | `/` | GET | Server info and endpoint documentation |
355
+
356
+ #### Authorization Server Metadata
357
+
358
+ Clients can discover OAuth2 configuration automatically:
359
+
360
+ ```bash
361
+ curl http://localhost:3001/.well-known/oauth-authorization-server
362
+ ```
363
+
364
+ Response:
365
+ ```json
366
+ {
367
+ "issuer": "http://localhost:3001",
368
+ "authorization_endpoint": "http://localhost:3001/oauth/authorize",
369
+ "token_endpoint": "http://localhost:3001/oauth/token",
370
+ "registration_endpoint": "http://localhost:3001/oauth/register",
371
+ "introspection_endpoint": "http://localhost:3001/oauth/introspect",
372
+ "revocation_endpoint": "http://localhost:3001/oauth/revoke",
373
+ "grant_types_supported": ["client_credentials", "authorization_code", "refresh_token"],
374
+ "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic", "none"],
375
+ "code_challenge_methods_supported": ["plain", "S256"],
376
+ "scopes_supported": ["mcp:read", "mcp:write"]
377
+ }
378
+ ```
379
+
380
+ #### Dynamic Client Registration
381
+
382
+ Register a new client dynamically:
383
+
384
+ ```bash
385
+ curl -X POST http://localhost:3001/oauth/register \
386
+ -H "Content-Type: application/json" \
387
+ -d '{
388
+ "client_name": "My MCP Client",
389
+ "grant_types": ["authorization_code", "refresh_token"],
390
+ "redirect_uris": ["http://localhost:3000/callback"],
391
+ "scope": "mcp:read mcp:write"
392
+ }'
393
+ ```
394
+
395
+ Response:
396
+ ```json
397
+ {
398
+ "client_id": "client-abc123...",
399
+ "client_secret": "xyz789...",
400
+ "client_id_issued_at": 1234567890,
401
+ "client_secret_expires_at": 0,
402
+ "client_name": "My MCP Client",
403
+ "grant_types": ["authorization_code", "refresh_token"],
404
+ "token_endpoint_auth_method": "client_secret_post",
405
+ "scope": "mcp:read mcp:write"
406
+ }
407
+ ```
408
+
409
+ Use the returned `client_id` and `client_secret` to obtain access tokens.
410
+
411
+ ## Adding New Capabilities
412
+
413
+ ### Adding a New Tool
414
+
415
+ Each tool lives in its own file under `src/tools/definitions/`. To add a new tool:
416
+
417
+ 1. **Create a new file** `src/tools/definitions/myNewTool.ts`:
418
+ ```typescript
419
+ import { z } from "zod";
420
+ import { zodToJsonSchema } from "zod-to-json-schema";
421
+ import type { ToolDefinition, ToolHandler, ToolContext } from "../types.js";
422
+
423
+ // Tool name (exported for use in index.ts)
424
+ export const name = "myNewTool";
425
+
426
+ // Schema for input validation
427
+ const inputSchema = z.object({
428
+ param1: z.string().describe("Description of param1"),
429
+ });
430
+
431
+ // Tool definition with description and JSON schema
432
+ export const definition: ToolDefinition = {
433
+ description: "Description of what the tool does",
434
+ inputSchema: zodToJsonSchema(inputSchema),
435
+ };
436
+
437
+ // Handler implementation
438
+ export const handler: ToolHandler = async (args, extra, context) => {
439
+ const { param1 } = inputSchema.parse(args);
440
+ // Your implementation here
441
+ return {
442
+ content: [{ type: "text", text: `Result: ${param1}` }],
443
+ };
444
+ };
445
+ ```
446
+
447
+ 2. **Register it** in `src/tools/index.ts`:
448
+ ```typescript
449
+ import * as myNewTool from "./definitions/myNewTool.js";
450
+
451
+ // Add to tools array in getTools()
452
+ {
453
+ name: myNewTool.name,
454
+ description: myNewTool.definition.description,
455
+ inputSchema: myNewTool.definition.inputSchema,
456
+ }
457
+
458
+ // Add to handleToolCall()
459
+ if (name === myNewTool.name) {
460
+ return myNewTool.handler(args, extra, context);
461
+ }
462
+ ```
463
+
464
+ ### Adding a New Prompt
465
+
466
+ 1. **Add the prompt name** to `src/prompts/index.ts`:
467
+ ```typescript
468
+ export enum PromptName {
469
+ // ... existing prompts
470
+ MY_PROMPT = "my_prompt",
471
+ }
472
+ ```
473
+
474
+ 2. **Register it** in `getPrompts()` and implement in `getPrompt()`.
475
+
476
+ ### Adding a New Resource
477
+
478
+ Modify `src/resources/index.ts` to add new resource types or extend the resource generation logic.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Everything Server - Entry Point
4
+ *
5
+ * This server demonstrates all MCP protocol capabilities.
6
+ * Run with different transport modes:
7
+ * - stdio (default): node dist/index.js
8
+ * - sse: node dist/index.js sse
9
+ * - streamableHttp: node dist/index.js streamableHttp
10
+ * - streamableHttp with auth: node dist/index.js streamableHttp --auth
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG"}
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Everything Server - Entry Point
4
+ *
5
+ * This server demonstrates all MCP protocol capabilities.
6
+ * Run with different transport modes:
7
+ * - stdio (default): node dist/index.js
8
+ * - sse: node dist/index.js sse
9
+ * - streamableHttp: node dist/index.js streamableHttp
10
+ * - streamableHttp with auth: node dist/index.js streamableHttp --auth
11
+ */
12
+ import { logger } from "./logger.js";
13
+ const log = logger.child({ component: "main" });
14
+ // Parse command line arguments
15
+ const args = process.argv.slice(2);
16
+ const scriptName = args[0] || "stdio";
17
+ const scriptArgs = args.slice(1); // Additional args after the script name
18
+ async function run() {
19
+ try {
20
+ // Dynamically import only the requested module to prevent all modules from initializing
21
+ switch (scriptName) {
22
+ case "stdio":
23
+ // Import and run the default server
24
+ await import("./transports/stdio.js");
25
+ break;
26
+ case "sse":
27
+ // Import and run the SSE server
28
+ await import("./transports/sse.js");
29
+ break;
30
+ case "streamableHttp": {
31
+ // Import and run the streamable HTTP server with optional --auth flag
32
+ const { startStreamableHttpServer, parseStreamableHttpArgs } = await import("./transports/streamableHttpServer.js");
33
+ const options = parseStreamableHttpArgs(scriptArgs);
34
+ await startStreamableHttpServer(options);
35
+ break;
36
+ }
37
+ default:
38
+ log.error({ scriptName }, "Unknown script");
39
+ log.info("Available scripts: stdio, sse, streamableHttp");
40
+ log.info(" streamableHttp options: --auth (enable OAuth2), --port=<port>");
41
+ process.exit(1);
42
+ }
43
+ }
44
+ catch (error) {
45
+ log.error({ err: error }, "Error running script");
46
+ process.exit(1);
47
+ }
48
+ }
49
+ run();
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;AAEhD,+BAA+B;AAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;AACtC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,wCAAwC;AAE1E,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC;QACH,wFAAwF;QACxF,QAAQ,UAAU,EAAE,CAAC;YACnB,KAAK,OAAO;gBACV,oCAAoC;gBACpC,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,KAAK;gBACR,gCAAgC;gBAChC,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;gBACpC,MAAM;YACR,KAAK,gBAAgB,CAAC,CAAC,CAAC;gBACtB,sEAAsE;gBACtE,MAAM,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,GAC1D,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAAC;gBACvD,MAAM,OAAO,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;gBACpD,MAAM,yBAAyB,CAAC,OAAO,CAAC,CAAC;gBACzC,MAAM;YACR,CAAC;YACD;gBACE,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,gBAAgB,CAAC,CAAC;gBAC5C,GAAG,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;gBAC1D,GAAG,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;gBAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,GAAG,EAAE,CAAC"}
@@ -0,0 +1,24 @@
1
+ Testing and demonstration server for MCP protocol features.
2
+
3
+ ## Resources
4
+
5
+ Resources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources are paginated at 10 items per page with cursor-based navigation.
6
+
7
+ ## Key dependencies
8
+
9
+ Progress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds.
10
+
11
+ ## Performance characteristics
12
+
13
+ Server generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time.
14
+
15
+ ## Multi-modal testing
16
+
17
+ `complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution.
18
+
19
+ Argument completion is available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern.
20
+
21
+ ## Easter egg
22
+
23
+ If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action."
24
+
@@ -0,0 +1,8 @@
1
+ import pino from "pino";
2
+ export declare const logger: pino.Logger<never, boolean>;
3
+ export declare const createLogger: (component: string) => pino.Logger<never, boolean>;
4
+ export declare const serverLogger: pino.Logger<never, boolean>;
5
+ export declare const transportLogger: pino.Logger<never, boolean>;
6
+ export declare const toolsLogger: pino.Logger<never, boolean>;
7
+ export declare const oauthLogger: pino.Logger<never, boolean>;
8
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAWxB,eAAO,MAAM,MAAM,6BAUjB,CAAC;AAGH,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,gCAAgC,CAAC;AAG/E,eAAO,MAAM,YAAY,6BAAyB,CAAC;AACnD,eAAO,MAAM,eAAe,6BAA4B,CAAC;AACzD,eAAO,MAAM,WAAW,6BAAwB,CAAC;AACjD,eAAO,MAAM,WAAW,6BAAwB,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,27 @@
1
+ import pino from "pino";
2
+ /**
3
+ * Centralized Pino logger for the MCP server
4
+ *
5
+ * Configure via environment variables:
6
+ * - LOG_LEVEL: trace, debug, info, warn, error, fatal (default: debug)
7
+ */
8
+ const logLevel = process.env.LOG_LEVEL || "debug";
9
+ export const logger = pino({
10
+ level: logLevel,
11
+ transport: {
12
+ target: "pino-pretty",
13
+ options: {
14
+ colorize: true,
15
+ translateTime: "SYS:standard",
16
+ ignore: "pid,hostname",
17
+ },
18
+ },
19
+ });
20
+ // Create child loggers for different components
21
+ export const createLogger = (component) => logger.child({ component });
22
+ // Pre-configured loggers for common components
23
+ export const serverLogger = createLogger("server");
24
+ export const transportLogger = createLogger("transport");
25
+ export const toolsLogger = createLogger("tools");
26
+ export const oauthLogger = createLogger("oauth");
27
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;GAKG;AAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC;AAElD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE;QACT,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI;YACd,aAAa,EAAE,cAAc;YAC7B,MAAM,EAAE,cAAc;SACvB;KACF;CACF,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AAE/E,+CAA+C;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * OAuth2 Configuration
3
+ */
4
+ import type { OAuthConfig } from "./types.js";
5
+ export declare const OAUTH_CONFIG: OAuthConfig;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/oauth/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,eAAO,MAAM,YAAY,EAAE,WAO1B,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OAuth2 Configuration
3
+ */
4
+ const PORT = parseInt(process.env.PORT || "3001", 10);
5
+ export const OAUTH_CONFIG = {
6
+ // In production, use environment variables for these
7
+ clientId: process.env.OAUTH_CLIENT_ID || "mcp-client",
8
+ clientSecret: process.env.OAUTH_CLIENT_SECRET || "mcp-secret",
9
+ tokenSecret: process.env.OAUTH_TOKEN_SECRET || "your-super-secret-key-change-in-production",
10
+ tokenExpiry: 3600, // 1 hour in seconds
11
+ port: PORT,
12
+ };
13
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/oauth/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,YAAY;IACrD,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,YAAY;IAC7D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,4CAA4C;IAC3F,WAAW,EAAE,IAAI,EAAE,oBAAoB;IACvC,IAAI,EAAE,IAAI;CACX,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * OAuth2 Helper Functions
3
+ */
4
+ import type { TokenInfo, RegisteredClient } from "./types.js";
5
+ export declare function generateClientId(): string;
6
+ export declare function generateClientSecret(): string;
7
+ export declare function validateClient(clientId: string, clientSecret: string): RegisteredClient | null;
8
+ export declare function getClient(clientId: string): RegisteredClient | null;
9
+ export declare function generateAuthorizationCode(): string;
10
+ export declare function generateRefreshToken(): string;
11
+ export declare function base64UrlEncode(buffer: Buffer): string;
12
+ export declare function verifyCodeChallenge(codeVerifier: string, codeChallenge: string, method: "plain" | "S256"): boolean;
13
+ export declare function generateAccessToken(): string;
14
+ export declare function validateTokenSignature(token: string): boolean;
15
+ export declare function createToken(clientId: string, scope: string[]): TokenInfo;
16
+ export declare function validateToken(token: string): TokenInfo | null;
17
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/oauth/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQ9D,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAS9F;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAEnE;AAMD,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,OAAO,GAAG,MAAM,GACvB,OAAO,CAST;AAMD,wBAAgB,mBAAmB,IAAI,MAAM,CAO5C;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAW7D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAYxE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAkB7D"}