110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
import { generateMcpConfig } from '../src/services/mcp-config-generator.js';
|
||
|
|
import type { ProfileWithServer } from '../src/services/mcp-config-generator.js';
|
||
|
|
|
||
|
|
function makeProfile(overrides: Partial<ProfileWithServer['profile']> = {}): ProfileWithServer['profile'] {
|
||
|
|
return {
|
||
|
|
id: 'p1',
|
||
|
|
name: 'default',
|
||
|
|
serverId: 's1',
|
||
|
|
permissions: [],
|
||
|
|
envOverrides: {},
|
||
|
|
version: 1,
|
||
|
|
createdAt: new Date(),
|
||
|
|
updatedAt: new Date(),
|
||
|
|
...overrides,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeServer(overrides: Partial<ProfileWithServer['server']> = {}): ProfileWithServer['server'] {
|
||
|
|
return {
|
||
|
|
id: 's1',
|
||
|
|
name: 'slack',
|
||
|
|
description: 'Slack MCP',
|
||
|
|
packageName: '@anthropic/slack-mcp',
|
||
|
|
dockerImage: null,
|
||
|
|
transport: 'STDIO',
|
||
|
|
repositoryUrl: null,
|
||
|
|
envTemplate: [],
|
||
|
|
version: 1,
|
||
|
|
createdAt: new Date(),
|
||
|
|
updatedAt: new Date(),
|
||
|
|
...overrides,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('generateMcpConfig', () => {
|
||
|
|
it('returns empty mcpServers for empty profiles', () => {
|
||
|
|
const result = generateMcpConfig([]);
|
||
|
|
expect(result).toEqual({ mcpServers: {} });
|
||
|
|
});
|
||
|
|
|
||
|
|
it('generates config for a single profile', () => {
|
||
|
|
const result = generateMcpConfig([
|
||
|
|
{ profile: makeProfile(), server: makeServer() },
|
||
|
|
]);
|
||
|
|
expect(result.mcpServers['slack--default']).toBeDefined();
|
||
|
|
expect(result.mcpServers['slack--default']?.command).toBe('npx');
|
||
|
|
expect(result.mcpServers['slack--default']?.args).toEqual(['-y', '@anthropic/slack-mcp']);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('excludes secret env vars from output', () => {
|
||
|
|
const server = makeServer({
|
||
|
|
envTemplate: [
|
||
|
|
{ name: 'SLACK_BOT_TOKEN', description: 'Token', isSecret: true },
|
||
|
|
{ name: 'SLACK_TEAM_ID', description: 'Team', isSecret: false, defaultValue: 'T123' },
|
||
|
|
] as never,
|
||
|
|
});
|
||
|
|
const result = generateMcpConfig([
|
||
|
|
{ profile: makeProfile(), server },
|
||
|
|
]);
|
||
|
|
const config = result.mcpServers['slack--default'];
|
||
|
|
expect(config?.env).toBeDefined();
|
||
|
|
expect(config?.env?.['SLACK_TEAM_ID']).toBe('T123');
|
||
|
|
expect(config?.env?.['SLACK_BOT_TOKEN']).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies env overrides from profile (non-secret only)', () => {
|
||
|
|
const server = makeServer({
|
||
|
|
envTemplate: [
|
||
|
|
{ name: 'API_URL', description: 'URL', isSecret: false },
|
||
|
|
] as never,
|
||
|
|
});
|
||
|
|
const profile = makeProfile({
|
||
|
|
envOverrides: { API_URL: 'https://staging.example.com' } as never,
|
||
|
|
});
|
||
|
|
const result = generateMcpConfig([{ profile, server }]);
|
||
|
|
expect(result.mcpServers['slack--default']?.env?.['API_URL']).toBe('https://staging.example.com');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('generates multiple server configs', () => {
|
||
|
|
const result = generateMcpConfig([
|
||
|
|
{ profile: makeProfile({ name: 'readonly' }), server: makeServer({ name: 'slack' }) },
|
||
|
|
{ profile: makeProfile({ name: 'default', id: 'p2' }), server: makeServer({ name: 'github', id: 's2', packageName: '@anthropic/github-mcp' }) },
|
||
|
|
]);
|
||
|
|
expect(Object.keys(result.mcpServers)).toHaveLength(2);
|
||
|
|
expect(result.mcpServers['slack--readonly']).toBeDefined();
|
||
|
|
expect(result.mcpServers['github--default']).toBeDefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('omits env when no non-secret vars have values', () => {
|
||
|
|
const server = makeServer({
|
||
|
|
envTemplate: [
|
||
|
|
{ name: 'TOKEN', description: 'Secret', isSecret: true },
|
||
|
|
] as never,
|
||
|
|
});
|
||
|
|
const result = generateMcpConfig([
|
||
|
|
{ profile: makeProfile(), server },
|
||
|
|
]);
|
||
|
|
expect(result.mcpServers['slack--default']?.env).toBeUndefined();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses server name as fallback when packageName is null', () => {
|
||
|
|
const server = makeServer({ packageName: null });
|
||
|
|
const result = generateMcpConfig([
|
||
|
|
{ profile: makeProfile(), server },
|
||
|
|
]);
|
||
|
|
expect(result.mcpServers['slack--default']?.args).toEqual(['-y', 'slack']);
|
||
|
|
});
|
||
|
|
});
|