import { describe, it, expect, vi } from 'vitest';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
// Create mock server
function createMockServer() {
return {
registerTool: vi.fn(),
registerPrompt: vi.fn(),
registerResource: vi.fn(),
server: {
getClientCapabilities: vi.fn(() => ({})),
setRequestHandler: vi.fn(),
},
sendLoggingMessage: vi.fn(),
sendResourceUpdated: vi.fn(),
} as unknown as McpServer;
}
describe('Registration Index Files', () => {
describe('tools/index.ts', () => {
it('should register all standard tools', async () => {
const { registerTools } = await import('../tools/index.js');
const mockServer = createMockServer();
registerTools(mockServer);
// Should register 12 standard tools (non-conditional)
expect(mockServer.registerTool).toHaveBeenCalledTimes(12);
// Verify specific tools are registered
const registeredTools = (mockServer.registerTool as any).mock.calls.map(
(call: any[]) => call[0]
);
expect(registeredTools).toContain('echo');
expect(registeredTools).toContain('get-sum');
expect(registeredTools).toContain('get-env');
expect(registeredTools).toContain('get-tiny-image');
expect(registeredTools).toContain('get-structured-content');
expect(registeredTools).toContain('get-annotated-message');
expect(registeredTools).toContain('trigger-long-running-operation');
expect(registeredTools).toContain('get-resource-links');
expect(registeredTools).toContain('get-resource-reference');
expect(registeredTools).toContain('gzip-file-as-resource');
expect(registeredTools).toContain('toggle-simulated-logging');
expect(registeredTools).toContain('toggle-subscriber-updates');
});
it('should register conditional tools based on capabilities', async () => {
const { registerConditionalTools } = await import('../tools/index.js');
// Server with all capabilities including experimental tasks API
const mockServerWithCapabilities = {
registerTool: vi.fn(),
server: {
getClientCapabilities: vi.fn(() => ({
roots: {},
elicitation: {},
sampling: {},
})),
},
experimental: {
tasks: {
registerToolTask: vi.fn(),
},
},
} as unknown as McpServer;
registerConditionalTools(mockServerWithCapabilities);
// Should register 3 conditional tools + 3 task-based tools when all capabilities present
expect(mockServerWithCapabilities.registerTool).toHaveBeenCalledTimes(3);
const registeredTools = (
mockServerWithCapabilities.registerTool as any
).mock.calls.map((call: any[]) => call[0]);
expect(registeredTools).toContain('get-roots-list');
expect(registeredTools).toContain('trigger-elicitation-request');
expect(registeredTools).toContain('trigger-sampling-request');
// Task-based tools are registered via experimental.tasks.registerToolTask
expect(mockServerWithCapabilities.experimental.tasks.registerToolTask).toHaveBeenCalled();
});
it('should not register conditional tools when capabilities missing', async () => {
const { registerConditionalTools } = await import('../tools/index.js');
const mockServerNoCapabilities = {
registerTool: vi.fn(),
server: {
getClientCapabilities: vi.fn(() => ({})),
},
experimental: {
tasks: {
registerToolTask: vi.fn(),
},
},
} as unknown as McpServer;
registerConditionalTools(mockServerNoCapabilities);
// Should not register any capability-gated tools when capabilities are missing
expect(mockServerNoCapabilities.registerTool).not.toHaveBeenCalled();
});
});
describe('prompts/index.ts', () => {
it('should register all prompts', async () => {
const { registerPrompts } = await import('../prompts/index.js');
const mockServer = createMockServer();
registerPrompts(mockServer);
// Should register 4 prompts
expect(mockServer.registerPrompt).toHaveBeenCalledTimes(4);
const registeredPrompts = (mockServer.registerPrompt as any).mock.calls.map(
(call: any[]) => call[0]
);
expect(registeredPrompts).toContain('simple-prompt');
expect(registeredPrompts).toContain('args-prompt');
expect(registeredPrompts).toContain('completable-prompt');
expect(registeredPrompts).toContain('resource-prompt');
});
});
describe('resources/index.ts', () => {
it('should register resource templates', async () => {
const { registerResources } = await import('../resources/index.js');
const mockServer = createMockServer();
registerResources(mockServer);
// Should register at least the 2 resource templates (text and blob) plus file resources
expect(mockServer.registerResource).toHaveBeenCalled();
const registeredResources = (mockServer.registerResource as any).mock.calls.map(
(call: any[]) => call[0]
);
expect(registeredResources).toContain('Dynamic Text Resource');
expect(registeredResources).toContain('Dynamic Blob Resource');
});
it('should read instructions from file', async () => {
const { readInstructions } = await import('../resources/index.js');
const instructions = readInstructions();
// Should return a string (either content or error message)
expect(typeof instructions).toBe('string');
expect(instructions.length).toBeGreaterThan(0);
});
});
});