@modelcontextprotocol/server-everything 2026.1.26 → 2026.7.4

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.
package/README.md CHANGED
@@ -31,9 +31,27 @@ Add to your `claude_desktop_config.json`:
31
31
  }
32
32
  ```
33
33
 
34
+ On Windows, use `cmd /c` to launch `npx`:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "everything": {
40
+ "command": "cmd",
41
+ "args": [
42
+ "/c",
43
+ "npx",
44
+ "-y",
45
+ "@modelcontextprotocol/server-everything"
46
+ ]
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
34
52
  ## Usage with VS Code
35
53
 
36
- For quick installation, use of of the one-click install buttons below...
54
+ For quick installation, use one of the one-click install buttons below...
37
55
 
38
56
  [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-NPM-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=everything&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40modelcontextprotocol%2Fserver-everything%22%5D%7D) [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-NPM-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=everything&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40modelcontextprotocol%2Fserver-everything%22%5D%7D&quality=insiders)
39
57
 
@@ -62,6 +80,19 @@ Alternatively, you can add the configuration to a file called `.vscode/mcp.json`
62
80
  }
63
81
  ```
64
82
 
83
+ On Windows, use:
84
+
85
+ ```json
86
+ {
87
+ "servers": {
88
+ "everything": {
89
+ "command": "cmd",
90
+ "args": ["/c", "npx", "-y", "@modelcontextprotocol/server-everything"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
65
96
  ## Running from source with [HTTP+SSE Transport](https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#http-with-sse) (deprecated as of [2025-03-26](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports))
66
97
 
67
98
  ```shell
@@ -104,3 +135,6 @@ npx @modelcontextprotocol/server-everything sse
104
135
  npx @modelcontextprotocol/server-everything streamableHttp
105
136
  ```
106
137
 
138
+ ## License
139
+
140
+ This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
@@ -0,0 +1,131 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { registerSimplePrompt } from '../prompts/simple.js';
3
+ import { registerArgumentsPrompt } from '../prompts/args.js';
4
+ import { registerPromptWithCompletions } from '../prompts/completions.js';
5
+ import { registerEmbeddedResourcePrompt } from '../prompts/resource.js';
6
+ // Helper to capture registered prompt handlers
7
+ function createMockServer() {
8
+ const handlers = new Map();
9
+ const configs = new Map();
10
+ const mockServer = {
11
+ registerPrompt: vi.fn((name, config, handler) => {
12
+ handlers.set(name, handler);
13
+ configs.set(name, config);
14
+ }),
15
+ };
16
+ return { mockServer, handlers, configs };
17
+ }
18
+ describe('Prompts', () => {
19
+ describe('simple-prompt', () => {
20
+ it('should return fixed message with no arguments', () => {
21
+ const { mockServer, handlers } = createMockServer();
22
+ registerSimplePrompt(mockServer);
23
+ const handler = handlers.get('simple-prompt');
24
+ const result = handler();
25
+ expect(result).toEqual({
26
+ messages: [
27
+ {
28
+ role: 'user',
29
+ content: {
30
+ type: 'text',
31
+ text: 'This is a simple prompt without arguments.',
32
+ },
33
+ },
34
+ ],
35
+ });
36
+ });
37
+ });
38
+ describe('args-prompt', () => {
39
+ it('should include city in message', () => {
40
+ const { mockServer, handlers } = createMockServer();
41
+ registerArgumentsPrompt(mockServer);
42
+ const handler = handlers.get('args-prompt');
43
+ const result = handler({ city: 'San Francisco' });
44
+ expect(result.messages[0].content.text).toBe("What's weather in San Francisco?");
45
+ });
46
+ it('should include city and state in message', () => {
47
+ const { mockServer, handlers } = createMockServer();
48
+ registerArgumentsPrompt(mockServer);
49
+ const handler = handlers.get('args-prompt');
50
+ const result = handler({ city: 'San Francisco', state: 'California' });
51
+ expect(result.messages[0].content.text).toBe("What's weather in San Francisco, California?");
52
+ });
53
+ it('should handle city only (optional state omitted)', () => {
54
+ const { mockServer, handlers } = createMockServer();
55
+ registerArgumentsPrompt(mockServer);
56
+ const handler = handlers.get('args-prompt');
57
+ const result = handler({ city: 'New York' });
58
+ expect(result.messages[0].content.text).toBe("What's weather in New York?");
59
+ expect(result.messages[0].content.text).not.toContain(',');
60
+ expect(result.messages[0].role).toBe('user');
61
+ expect(result.messages[0].content.type).toBe('text');
62
+ });
63
+ });
64
+ describe('completable-prompt', () => {
65
+ it('should generate promotion message with department and name', () => {
66
+ const { mockServer, handlers } = createMockServer();
67
+ registerPromptWithCompletions(mockServer);
68
+ const handler = handlers.get('completable-prompt');
69
+ const result = handler({ department: 'Engineering', name: 'Alice' });
70
+ expect(result.messages[0].content.text).toBe('Please promote Alice to the head of the Engineering team.');
71
+ });
72
+ it('should work with different departments', () => {
73
+ const { mockServer, handlers } = createMockServer();
74
+ registerPromptWithCompletions(mockServer);
75
+ const handler = handlers.get('completable-prompt');
76
+ const salesResult = handler({ department: 'Sales', name: 'David' });
77
+ expect(salesResult.messages[0].content.text).toContain('Sales');
78
+ expect(salesResult.messages[0].content.text).toContain('David');
79
+ expect(salesResult.messages[0].role).toBe('user');
80
+ const marketingResult = handler({ department: 'Marketing', name: 'Grace' });
81
+ expect(marketingResult.messages[0].content.text).toContain('Marketing');
82
+ expect(marketingResult.messages[0].content.text).toContain('Grace');
83
+ });
84
+ });
85
+ describe('resource-prompt', () => {
86
+ it('should return text resource reference', () => {
87
+ const { mockServer, handlers } = createMockServer();
88
+ registerEmbeddedResourcePrompt(mockServer);
89
+ const handler = handlers.get('resource-prompt');
90
+ const result = handler({ resourceType: 'Text', resourceId: '1' });
91
+ expect(result.messages).toHaveLength(2);
92
+ expect(result.messages[0].content.text).toContain('Text');
93
+ expect(result.messages[0].content.text).toContain('1');
94
+ expect(result.messages[1].content.type).toBe('resource');
95
+ expect(result.messages[1].content.resource.uri).toContain('text/1');
96
+ });
97
+ it('should return blob resource reference', () => {
98
+ const { mockServer, handlers } = createMockServer();
99
+ registerEmbeddedResourcePrompt(mockServer);
100
+ const handler = handlers.get('resource-prompt');
101
+ const result = handler({ resourceType: 'Blob', resourceId: '5' });
102
+ expect(result.messages[0].content.text).toContain('Blob');
103
+ expect(result.messages[1].content.resource.uri).toContain('blob/5');
104
+ });
105
+ it('should reject invalid resource type', () => {
106
+ const { mockServer, handlers } = createMockServer();
107
+ registerEmbeddedResourcePrompt(mockServer);
108
+ const handler = handlers.get('resource-prompt');
109
+ expect(() => handler({ resourceType: 'Invalid', resourceId: '1' })).toThrow('Invalid resourceType');
110
+ });
111
+ it('should reject invalid resource ID', () => {
112
+ const { mockServer, handlers } = createMockServer();
113
+ registerEmbeddedResourcePrompt(mockServer);
114
+ const handler = handlers.get('resource-prompt');
115
+ expect(() => handler({ resourceType: 'Text', resourceId: '-1' })).toThrow('Invalid resourceId');
116
+ expect(() => handler({ resourceType: 'Text', resourceId: '0' })).toThrow('Invalid resourceId');
117
+ expect(() => handler({ resourceType: 'Text', resourceId: 'abc' })).toThrow('Invalid resourceId');
118
+ });
119
+ it('should include both intro text and resource messages', () => {
120
+ const { mockServer, handlers } = createMockServer();
121
+ registerEmbeddedResourcePrompt(mockServer);
122
+ const handler = handlers.get('resource-prompt');
123
+ const result = handler({ resourceType: 'Text', resourceId: '3' });
124
+ expect(result.messages).toHaveLength(2);
125
+ expect(result.messages[0].role).toBe('user');
126
+ expect(result.messages[0].content.type).toBe('text');
127
+ expect(result.messages[1].role).toBe('user');
128
+ expect(result.messages[1].content.type).toBe('resource');
129
+ });
130
+ });
131
+ });
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ // Create mock server
3
+ function createMockServer() {
4
+ return {
5
+ registerTool: vi.fn(),
6
+ registerPrompt: vi.fn(),
7
+ registerResource: vi.fn(),
8
+ server: {
9
+ getClientCapabilities: vi.fn(() => ({})),
10
+ setRequestHandler: vi.fn(),
11
+ },
12
+ sendLoggingMessage: vi.fn(),
13
+ sendResourceUpdated: vi.fn(),
14
+ };
15
+ }
16
+ describe('Registration Index Files', () => {
17
+ describe('tools/index.ts', () => {
18
+ it('should register all standard tools', async () => {
19
+ const { registerTools } = await import('../tools/index.js');
20
+ const mockServer = createMockServer();
21
+ registerTools(mockServer);
22
+ // Should register 12 standard tools (non-conditional)
23
+ expect(mockServer.registerTool).toHaveBeenCalledTimes(12);
24
+ // Verify specific tools are registered
25
+ const registeredTools = mockServer.registerTool.mock.calls.map((call) => call[0]);
26
+ expect(registeredTools).toContain('echo');
27
+ expect(registeredTools).toContain('get-sum');
28
+ expect(registeredTools).toContain('get-env');
29
+ expect(registeredTools).toContain('get-tiny-image');
30
+ expect(registeredTools).toContain('get-structured-content');
31
+ expect(registeredTools).toContain('get-annotated-message');
32
+ expect(registeredTools).toContain('trigger-long-running-operation');
33
+ expect(registeredTools).toContain('get-resource-links');
34
+ expect(registeredTools).toContain('get-resource-reference');
35
+ expect(registeredTools).toContain('gzip-file-as-resource');
36
+ expect(registeredTools).toContain('toggle-simulated-logging');
37
+ expect(registeredTools).toContain('toggle-subscriber-updates');
38
+ });
39
+ it('should register conditional tools based on capabilities', async () => {
40
+ const { registerConditionalTools } = await import('../tools/index.js');
41
+ // Server with all capabilities including experimental tasks API
42
+ const mockServerWithCapabilities = {
43
+ registerTool: vi.fn(),
44
+ server: {
45
+ getClientCapabilities: vi.fn(() => ({
46
+ roots: {},
47
+ elicitation: { url: {} },
48
+ sampling: {},
49
+ })),
50
+ },
51
+ experimental: {
52
+ tasks: {
53
+ registerToolTask: vi.fn(),
54
+ },
55
+ },
56
+ };
57
+ registerConditionalTools(mockServerWithCapabilities);
58
+ // Should register 4 conditional tools via registerTool when all capabilities
59
+ // are present. Task-based tools register via registerToolTask (counted separately),
60
+ // so they are not included in this registerTool count.
61
+ expect(mockServerWithCapabilities.registerTool).toHaveBeenCalledTimes(4);
62
+ const registeredTools = mockServerWithCapabilities.registerTool.mock.calls.map((call) => call[0]);
63
+ expect(registeredTools).toContain('get-roots-list');
64
+ expect(registeredTools).toContain('trigger-elicitation-request');
65
+ expect(registeredTools).toContain('trigger-url-elicitation');
66
+ expect(registeredTools).toContain('trigger-sampling-request');
67
+ // Task-based tools are registered via experimental.tasks.registerToolTask
68
+ expect(mockServerWithCapabilities.experimental.tasks.registerToolTask).toHaveBeenCalled();
69
+ });
70
+ it('should not register conditional tools when capabilities missing', async () => {
71
+ const { registerConditionalTools } = await import('../tools/index.js');
72
+ const mockServerNoCapabilities = {
73
+ registerTool: vi.fn(),
74
+ server: {
75
+ getClientCapabilities: vi.fn(() => ({})),
76
+ },
77
+ experimental: {
78
+ tasks: {
79
+ registerToolTask: vi.fn(),
80
+ },
81
+ },
82
+ };
83
+ registerConditionalTools(mockServerNoCapabilities);
84
+ // Should not register any capability-gated tools when capabilities are missing
85
+ expect(mockServerNoCapabilities.registerTool).not.toHaveBeenCalled();
86
+ });
87
+ });
88
+ describe('prompts/index.ts', () => {
89
+ it('should register all prompts', async () => {
90
+ const { registerPrompts } = await import('../prompts/index.js');
91
+ const mockServer = createMockServer();
92
+ registerPrompts(mockServer);
93
+ // Should register 4 prompts
94
+ expect(mockServer.registerPrompt).toHaveBeenCalledTimes(4);
95
+ const registeredPrompts = mockServer.registerPrompt.mock.calls.map((call) => call[0]);
96
+ expect(registeredPrompts).toContain('simple-prompt');
97
+ expect(registeredPrompts).toContain('args-prompt');
98
+ expect(registeredPrompts).toContain('completable-prompt');
99
+ expect(registeredPrompts).toContain('resource-prompt');
100
+ });
101
+ });
102
+ describe('resources/index.ts', () => {
103
+ it('should register resource templates', async () => {
104
+ const { registerResources } = await import('../resources/index.js');
105
+ const mockServer = createMockServer();
106
+ registerResources(mockServer);
107
+ // Should register at least the 2 resource templates (text and blob) plus file resources
108
+ expect(mockServer.registerResource).toHaveBeenCalled();
109
+ const registeredResources = mockServer.registerResource.mock.calls.map((call) => call[0]);
110
+ expect(registeredResources).toContain('Dynamic Text Resource');
111
+ expect(registeredResources).toContain('Dynamic Blob Resource');
112
+ });
113
+ it('should read instructions from file', async () => {
114
+ const { readInstructions } = await import('../resources/index.js');
115
+ const instructions = readInstructions();
116
+ // Should return a string (either content or error message)
117
+ expect(typeof instructions).toBe('string');
118
+ expect(instructions.length).toBeGreaterThan(0);
119
+ });
120
+ });
121
+ });
@@ -0,0 +1,240 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
+ import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { textResource, blobResource, textResourceUri, blobResourceUri, RESOURCE_TYPE_TEXT, RESOURCE_TYPE_BLOB, RESOURCE_TYPES, resourceTypeCompleter, resourceIdForPromptCompleter, resourceIdForResourceTemplateCompleter, registerResourceTemplates, } from '../resources/templates.js';
4
+ import { getSessionResourceURI, registerSessionResource, } from '../resources/session.js';
5
+ import { registerFileResources } from '../resources/files.js';
6
+ import { setSubscriptionHandlers, beginSimulatedResourceUpdates, stopSimulatedResourceUpdates, } from '../resources/subscriptions.js';
7
+ describe('Resource Templates', () => {
8
+ describe('Constants', () => {
9
+ it('should include both types in RESOURCE_TYPES array', () => {
10
+ expect(RESOURCE_TYPES).toContain(RESOURCE_TYPE_TEXT);
11
+ expect(RESOURCE_TYPES).toContain(RESOURCE_TYPE_BLOB);
12
+ expect(RESOURCE_TYPES).toHaveLength(2);
13
+ });
14
+ });
15
+ describe('textResourceUri', () => {
16
+ it('should create URL for text resource', () => {
17
+ const uri = textResourceUri(1);
18
+ expect(uri.toString()).toBe('demo://resource/dynamic/text/1');
19
+ });
20
+ it('should handle different resource IDs', () => {
21
+ expect(textResourceUri(5).toString()).toBe('demo://resource/dynamic/text/5');
22
+ expect(textResourceUri(100).toString()).toBe('demo://resource/dynamic/text/100');
23
+ });
24
+ });
25
+ describe('blobResourceUri', () => {
26
+ it('should create URL for blob resource', () => {
27
+ const uri = blobResourceUri(1);
28
+ expect(uri.toString()).toBe('demo://resource/dynamic/blob/1');
29
+ });
30
+ it('should handle different resource IDs', () => {
31
+ expect(blobResourceUri(5).toString()).toBe('demo://resource/dynamic/blob/5');
32
+ expect(blobResourceUri(100).toString()).toBe('demo://resource/dynamic/blob/100');
33
+ });
34
+ });
35
+ describe('textResource', () => {
36
+ it('should create text resource with correct structure', () => {
37
+ const uri = textResourceUri(1);
38
+ const resource = textResource(uri, 1);
39
+ expect(resource.uri).toBe(uri.toString());
40
+ expect(resource.mimeType).toBe('text/plain');
41
+ expect(resource.text).toContain('Resource 1');
42
+ expect(resource.text).toContain('plaintext');
43
+ });
44
+ it('should include timestamp in content', () => {
45
+ const uri = textResourceUri(2);
46
+ const resource = textResource(uri, 2);
47
+ // Timestamp format varies, just check it contains time-related content
48
+ expect(resource.text).toMatch(/\d/);
49
+ });
50
+ });
51
+ describe('blobResource', () => {
52
+ it('should create blob resource with correct structure', () => {
53
+ const uri = blobResourceUri(1);
54
+ const resource = blobResource(uri, 1);
55
+ expect(resource.uri).toBe(uri.toString());
56
+ expect(resource.mimeType).toBe('text/plain');
57
+ expect(resource.blob).toBeDefined();
58
+ });
59
+ it('should create valid base64 encoded content', () => {
60
+ const uri = blobResourceUri(3);
61
+ const resource = blobResource(uri, 3);
62
+ // Decode and verify content
63
+ const decoded = Buffer.from(resource.blob, 'base64').toString();
64
+ expect(decoded).toContain('Resource 3');
65
+ expect(decoded).toContain('base64 blob');
66
+ });
67
+ });
68
+ describe('resourceTypeCompleter', () => {
69
+ it('should be defined as a completable schema', () => {
70
+ // The completer is a zod schema wrapped with completable
71
+ expect(resourceTypeCompleter).toBeDefined();
72
+ // It should have the zod parse method
73
+ expect(typeof resourceTypeCompleter.parse).toBe('function');
74
+ });
75
+ it('should validate string resource types', () => {
76
+ // Test that valid strings pass validation
77
+ expect(() => resourceTypeCompleter.parse('Text')).not.toThrow();
78
+ expect(() => resourceTypeCompleter.parse('Blob')).not.toThrow();
79
+ });
80
+ });
81
+ describe('resourceIdForPromptCompleter', () => {
82
+ it('should be defined as a completable schema', () => {
83
+ expect(resourceIdForPromptCompleter).toBeDefined();
84
+ expect(typeof resourceIdForPromptCompleter.parse).toBe('function');
85
+ });
86
+ it('should validate string IDs', () => {
87
+ // Test that valid strings pass validation
88
+ expect(() => resourceIdForPromptCompleter.parse('1')).not.toThrow();
89
+ expect(() => resourceIdForPromptCompleter.parse('100')).not.toThrow();
90
+ });
91
+ });
92
+ describe('resourceIdForResourceTemplateCompleter', () => {
93
+ it('should validate positive integer IDs', () => {
94
+ expect(resourceIdForResourceTemplateCompleter('1')).toEqual(['1']);
95
+ expect(resourceIdForResourceTemplateCompleter('50')).toEqual(['50']);
96
+ });
97
+ it('should reject invalid IDs', () => {
98
+ expect(resourceIdForResourceTemplateCompleter('0')).toEqual([]);
99
+ expect(resourceIdForResourceTemplateCompleter('-5')).toEqual([]);
100
+ expect(resourceIdForResourceTemplateCompleter('not-a-number')).toEqual([]);
101
+ });
102
+ });
103
+ describe('registerResourceTemplates', () => {
104
+ it('should register text and blob resource templates', () => {
105
+ const registeredResources = [];
106
+ const mockServer = {
107
+ registerResource: vi.fn((...args) => {
108
+ registeredResources.push(args);
109
+ }),
110
+ };
111
+ registerResourceTemplates(mockServer);
112
+ expect(mockServer.registerResource).toHaveBeenCalledTimes(2);
113
+ // Check text resource registration
114
+ const textRegistration = registeredResources.find((r) => r[0].includes('Text'));
115
+ expect(textRegistration).toBeDefined();
116
+ expect(textRegistration[1]).toBeInstanceOf(ResourceTemplate);
117
+ // Check blob resource registration
118
+ const blobRegistration = registeredResources.find((r) => r[0].includes('Blob'));
119
+ expect(blobRegistration).toBeDefined();
120
+ });
121
+ });
122
+ });
123
+ describe('Session Resources', () => {
124
+ describe('getSessionResourceURI', () => {
125
+ it('should generate correct URI for resource name', () => {
126
+ expect(getSessionResourceURI('test')).toBe('demo://resource/session/test');
127
+ });
128
+ it('should handle various resource names', () => {
129
+ expect(getSessionResourceURI('my-file')).toBe('demo://resource/session/my-file');
130
+ expect(getSessionResourceURI('document_123')).toBe('demo://resource/session/document_123');
131
+ });
132
+ });
133
+ describe('registerSessionResource', () => {
134
+ it('should register text resource and return resource link', () => {
135
+ const registrations = [];
136
+ const mockServer = {
137
+ registerResource: vi.fn((...args) => {
138
+ registrations.push(args);
139
+ }),
140
+ };
141
+ const resource = {
142
+ uri: 'demo://resource/session/test-file',
143
+ name: 'test-file',
144
+ mimeType: 'text/plain',
145
+ description: 'A test file',
146
+ };
147
+ const result = registerSessionResource(mockServer, resource, 'text', 'Hello, World!');
148
+ expect(result.type).toBe('resource_link');
149
+ expect(result.uri).toBe(resource.uri);
150
+ expect(result.name).toBe(resource.name);
151
+ expect(mockServer.registerResource).toHaveBeenCalledWith('test-file', 'demo://resource/session/test-file', expect.objectContaining({
152
+ mimeType: 'text/plain',
153
+ description: 'A test file',
154
+ }), expect.any(Function));
155
+ });
156
+ it('should register blob resource correctly', () => {
157
+ const mockServer = {
158
+ registerResource: vi.fn(),
159
+ };
160
+ const resource = {
161
+ uri: 'demo://resource/session/binary-file',
162
+ name: 'binary-file',
163
+ mimeType: 'application/octet-stream',
164
+ };
165
+ const blobContent = Buffer.from('binary data').toString('base64');
166
+ const result = registerSessionResource(mockServer, resource, 'blob', blobContent);
167
+ expect(result.type).toBe('resource_link');
168
+ expect(mockServer.registerResource).toHaveBeenCalled();
169
+ });
170
+ it('should return resource handler that provides correct content', async () => {
171
+ let capturedHandler = null;
172
+ const mockServer = {
173
+ registerResource: vi.fn((_name, _uri, _config, handler) => {
174
+ capturedHandler = handler;
175
+ }),
176
+ };
177
+ const resource = {
178
+ uri: 'demo://resource/session/content-test',
179
+ name: 'content-test',
180
+ mimeType: 'text/plain',
181
+ };
182
+ registerSessionResource(mockServer, resource, 'text', 'Test content here');
183
+ expect(capturedHandler).not.toBeNull();
184
+ const handlerResult = await capturedHandler(new URL(resource.uri));
185
+ expect(handlerResult.contents).toHaveLength(1);
186
+ expect(handlerResult.contents[0].text).toBe('Test content here');
187
+ expect(handlerResult.contents[0].mimeType).toBe('text/plain');
188
+ });
189
+ });
190
+ });
191
+ describe('File Resources', () => {
192
+ describe('registerFileResources', () => {
193
+ it('should register file resources when docs directory exists', () => {
194
+ const mockServer = {
195
+ registerResource: vi.fn(),
196
+ };
197
+ registerFileResources(mockServer);
198
+ // The docs folder exists in the everything server and contains files
199
+ // so registerResource should have been called
200
+ expect(mockServer.registerResource).toHaveBeenCalled();
201
+ });
202
+ });
203
+ });
204
+ describe('Subscriptions', () => {
205
+ describe('setSubscriptionHandlers', () => {
206
+ it('should set request handlers on server', () => {
207
+ const mockServer = {
208
+ server: {
209
+ setRequestHandler: vi.fn(),
210
+ },
211
+ sendLoggingMessage: vi.fn(),
212
+ };
213
+ setSubscriptionHandlers(mockServer);
214
+ // Should set both subscribe and unsubscribe handlers
215
+ expect(mockServer.server.setRequestHandler).toHaveBeenCalledTimes(2);
216
+ });
217
+ });
218
+ describe('simulated resource updates lifecycle', () => {
219
+ afterEach(() => {
220
+ // Clean up any intervals
221
+ stopSimulatedResourceUpdates('lifecycle-test-session');
222
+ });
223
+ it('should start and stop updates without errors', () => {
224
+ const mockServer = {
225
+ server: {
226
+ notification: vi.fn(),
227
+ },
228
+ };
229
+ // Start updates - should work for both defined and undefined sessionId
230
+ beginSimulatedResourceUpdates(mockServer, 'lifecycle-test-session');
231
+ beginSimulatedResourceUpdates(mockServer, undefined);
232
+ // Stop updates - should handle all cases gracefully
233
+ stopSimulatedResourceUpdates('lifecycle-test-session');
234
+ stopSimulatedResourceUpdates('non-existent-session');
235
+ stopSimulatedResourceUpdates(undefined);
236
+ // If we got here without throwing, the lifecycle works correctly
237
+ expect(true).toBe(true);
238
+ });
239
+ });
240
+ });
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { createServer } from '../server/index.js';
3
+ describe('Server Factory', () => {
4
+ describe('createServer', () => {
5
+ it('should return a ServerFactoryResponse object', () => {
6
+ const result = createServer();
7
+ expect(result).toHaveProperty('server');
8
+ expect(result).toHaveProperty('cleanup');
9
+ });
10
+ it('should return a cleanup function', () => {
11
+ const { cleanup } = createServer();
12
+ expect(typeof cleanup).toBe('function');
13
+ });
14
+ it('should create an McpServer instance', () => {
15
+ const { server } = createServer();
16
+ expect(server).toBeDefined();
17
+ expect(server.server).toBeDefined();
18
+ });
19
+ it('should have an oninitialized handler set', () => {
20
+ const { server } = createServer();
21
+ expect(server.server.oninitialized).toBeDefined();
22
+ });
23
+ it('should allow multiple servers to be created', () => {
24
+ const result1 = createServer();
25
+ const result2 = createServer();
26
+ expect(result1.server).toBeDefined();
27
+ expect(result2.server).toBeDefined();
28
+ expect(result1.server).not.toBe(result2.server);
29
+ });
30
+ });
31
+ });