feat(profiles): Add MCP configuration to Claude Code rules (#980)
* add .mcp.json with claude profile * add changeset * update changeset * update test
This commit is contained in:
committed by
Ralph Khreish
parent
901eec1058
commit
0a70ab6179
5
.changeset/swift-turtles-sit.md
Normal file
5
.changeset/swift-turtles-sit.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add MCP configuration support to Claude Code rules
|
||||||
@@ -46,7 +46,9 @@ export function createProfile(editorConfig) {
|
|||||||
onPostConvert
|
onPostConvert
|
||||||
} = editorConfig;
|
} = editorConfig;
|
||||||
|
|
||||||
const mcpConfigPath = mcpConfigName ? `${profileDir}/${mcpConfigName}` : null;
|
const mcpConfigPath = mcpConfigName
|
||||||
|
? path.join(profileDir, mcpConfigName)
|
||||||
|
: null;
|
||||||
|
|
||||||
// Standard file mapping with custom overrides
|
// Standard file mapping with custom overrides
|
||||||
// Use taskmaster subdirectory only if profile supports it
|
// Use taskmaster subdirectory only if profile supports it
|
||||||
|
|||||||
@@ -197,9 +197,73 @@ function onRemoveRulesProfile(targetDir) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform standard MCP config format to Claude format
|
||||||
|
* @param {Object} mcpConfig - Standard MCP configuration object
|
||||||
|
* @returns {Object} - Transformed Claude configuration object
|
||||||
|
*/
|
||||||
|
function transformToClaudeFormat(mcpConfig) {
|
||||||
|
const claudeConfig = {};
|
||||||
|
|
||||||
|
// Transform mcpServers to servers (keeping the same structure but adding type)
|
||||||
|
if (mcpConfig.mcpServers) {
|
||||||
|
claudeConfig.mcpServers = {};
|
||||||
|
|
||||||
|
for (const [serverName, serverConfig] of Object.entries(
|
||||||
|
mcpConfig.mcpServers
|
||||||
|
)) {
|
||||||
|
// Transform server configuration with type as first key
|
||||||
|
const reorderedServer = {};
|
||||||
|
|
||||||
|
// Add type: "stdio" as the first key
|
||||||
|
reorderedServer.type = 'stdio';
|
||||||
|
|
||||||
|
// Then add the rest of the properties in order
|
||||||
|
if (serverConfig.command) reorderedServer.command = serverConfig.command;
|
||||||
|
if (serverConfig.args) reorderedServer.args = serverConfig.args;
|
||||||
|
if (serverConfig.env) reorderedServer.env = serverConfig.env;
|
||||||
|
|
||||||
|
// Add any other properties that might exist
|
||||||
|
Object.keys(serverConfig).forEach((key) => {
|
||||||
|
if (!['command', 'args', 'env', 'type'].includes(key)) {
|
||||||
|
reorderedServer[key] = serverConfig[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
claudeConfig.mcpServers[serverName] = reorderedServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return claudeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
function onPostConvertRulesProfile(targetDir, assetsDir) {
|
function onPostConvertRulesProfile(targetDir, assetsDir) {
|
||||||
// For Claude, post-convert is the same as add since we don't transform rules
|
// For Claude, post-convert is the same as add since we don't transform rules
|
||||||
onAddRulesProfile(targetDir, assetsDir);
|
onAddRulesProfile(targetDir, assetsDir);
|
||||||
|
|
||||||
|
// Transform MCP configuration to Claude format
|
||||||
|
const mcpConfigPath = path.join(targetDir, '.mcp.json');
|
||||||
|
if (fs.existsSync(mcpConfigPath)) {
|
||||||
|
try {
|
||||||
|
const mcpConfig = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf8'));
|
||||||
|
const claudeConfig = transformToClaudeFormat(mcpConfig);
|
||||||
|
|
||||||
|
// Write back the transformed configuration
|
||||||
|
fs.writeFileSync(
|
||||||
|
mcpConfigPath,
|
||||||
|
JSON.stringify(claudeConfig, null, '\t') + '\n'
|
||||||
|
);
|
||||||
|
log(
|
||||||
|
'debug',
|
||||||
|
`[Claude] Transformed MCP configuration to Claude format at ${mcpConfigPath}`
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
log(
|
||||||
|
'error',
|
||||||
|
`[Claude] Failed to transform MCP configuration: ${err.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and export claude profile using the base factory
|
// Create and export claude profile using the base factory
|
||||||
@@ -210,8 +274,7 @@ export const claudeProfile = createProfile({
|
|||||||
docsUrl: 'docs.anthropic.com/en/docs/claude-code',
|
docsUrl: 'docs.anthropic.com/en/docs/claude-code',
|
||||||
profileDir: '.', // Root directory
|
profileDir: '.', // Root directory
|
||||||
rulesDir: '.', // No specific rules directory needed
|
rulesDir: '.', // No specific rules directory needed
|
||||||
mcpConfig: false,
|
mcpConfigName: '.mcp.json', // Place MCP config in project root
|
||||||
mcpConfigName: null,
|
|
||||||
includeDefaultRules: false,
|
includeDefaultRules: false,
|
||||||
fileMap: {
|
fileMap: {
|
||||||
'AGENTS.md': '.taskmaster/CLAUDE.md'
|
'AGENTS.md': '.taskmaster/CLAUDE.md'
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe('Claude Profile Initialization Functionality', () => {
|
|||||||
expect(claudeProfileContent).toContain("displayName: 'Claude Code'");
|
expect(claudeProfileContent).toContain("displayName: 'Claude Code'");
|
||||||
expect(claudeProfileContent).toContain("profileDir: '.'"); // non-default
|
expect(claudeProfileContent).toContain("profileDir: '.'"); // non-default
|
||||||
expect(claudeProfileContent).toContain("rulesDir: '.'"); // non-default
|
expect(claudeProfileContent).toContain("rulesDir: '.'"); // non-default
|
||||||
expect(claudeProfileContent).toContain('mcpConfig: false'); // non-default
|
expect(claudeProfileContent).toContain("mcpConfigName: '.mcp.json'"); // non-default
|
||||||
expect(claudeProfileContent).toContain('includeDefaultRules: false'); // non-default
|
expect(claudeProfileContent).toContain('includeDefaultRules: false'); // non-default
|
||||||
expect(claudeProfileContent).toContain(
|
expect(claudeProfileContent).toContain(
|
||||||
"'AGENTS.md': '.taskmaster/CLAUDE.md'"
|
"'AGENTS.md': '.taskmaster/CLAUDE.md'"
|
||||||
@@ -32,8 +32,9 @@ describe('Claude Profile Initialization Functionality', () => {
|
|||||||
expect(claudeProfile.displayName).toBe('Claude Code');
|
expect(claudeProfile.displayName).toBe('Claude Code');
|
||||||
expect(claudeProfile.profileDir).toBe('.');
|
expect(claudeProfile.profileDir).toBe('.');
|
||||||
expect(claudeProfile.rulesDir).toBe('.');
|
expect(claudeProfile.rulesDir).toBe('.');
|
||||||
expect(claudeProfile.mcpConfig).toBe(false);
|
expect(claudeProfile.mcpConfig).toBe(true); // default from base profile
|
||||||
expect(claudeProfile.mcpConfigName).toBe(null); // computed
|
expect(claudeProfile.mcpConfigName).toBe('.mcp.json'); // explicitly set
|
||||||
|
expect(claudeProfile.mcpConfigPath).toBe('.mcp.json'); // computed
|
||||||
expect(claudeProfile.includeDefaultRules).toBe(false);
|
expect(claudeProfile.includeDefaultRules).toBe(false);
|
||||||
expect(claudeProfile.fileMap['AGENTS.md']).toBe('.taskmaster/CLAUDE.md');
|
expect(claudeProfile.fileMap['AGENTS.md']).toBe('.taskmaster/CLAUDE.md');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { jest } from '@jest/globals';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import { claudeProfile } from '../../../src/profiles/claude.js';
|
||||||
|
|
||||||
// Mock external modules
|
// Mock external modules
|
||||||
jest.mock('child_process', () => ({
|
jest.mock('child_process', () => ({
|
||||||
@@ -77,11 +78,22 @@ describe('Claude Profile Integration', () => {
|
|||||||
expect(mkdirCalls).toHaveLength(0);
|
expect(mkdirCalls).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('does not create MCP configuration files', () => {
|
test('supports MCP configuration when using rule transformer', () => {
|
||||||
|
// This test verifies that the Claude profile is configured to support MCP
|
||||||
|
// The actual MCP file creation is handled by the rule transformer
|
||||||
|
|
||||||
|
// Assert - Claude profile should now support MCP configuration
|
||||||
|
expect(claudeProfile.mcpConfig).toBe(true);
|
||||||
|
expect(claudeProfile.mcpConfigName).toBe('.mcp.json');
|
||||||
|
expect(claudeProfile.mcpConfigPath).toBe('.mcp.json');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('mock function does not create MCP configuration files', () => {
|
||||||
// Act
|
// Act
|
||||||
mockCreateClaudeStructure();
|
mockCreateClaudeStructure();
|
||||||
|
|
||||||
// Assert - Claude profile should not create any MCP config files
|
// Assert - The mock function should not create MCP config files
|
||||||
|
// (This is expected since the mock doesn't use the rule transformer)
|
||||||
const writeFileCalls = fs.writeFileSync.mock.calls;
|
const writeFileCalls = fs.writeFileSync.mock.calls;
|
||||||
const mcpConfigCalls = writeFileCalls.filter(
|
const mcpConfigCalls = writeFileCalls.filter(
|
||||||
(call) =>
|
(call) =>
|
||||||
|
|||||||
@@ -92,7 +92,12 @@ describe('MCP Configuration Validation', () => {
|
|||||||
RULE_PROFILES.forEach((profileName) => {
|
RULE_PROFILES.forEach((profileName) => {
|
||||||
const profile = getRulesProfile(profileName);
|
const profile = getRulesProfile(profileName);
|
||||||
if (profile.mcpConfig !== false) {
|
if (profile.mcpConfig !== false) {
|
||||||
expect(profile.mcpConfigPath).toMatch(/^\.[\w-]+\/[\w_.]+$/);
|
// Claude profile uses root directory (.), so its path is just '.mcp.json'
|
||||||
|
if (profileName === 'claude') {
|
||||||
|
expect(profile.mcpConfigPath).toBe('.mcp.json');
|
||||||
|
} else {
|
||||||
|
expect(profile.mcpConfigPath).toMatch(/^\.[\w-]+\/[\w_.]+$/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -123,17 +128,13 @@ describe('MCP Configuration Validation', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should have null config name for non-MCP profiles', () => {
|
test('should have null config name for non-MCP profiles', () => {
|
||||||
const clineProfile = getRulesProfile('cline');
|
// Only codex, cline, and trae profiles should have null config names
|
||||||
expect(clineProfile.mcpConfigName).toBe(null);
|
const nonMcpProfiles = ['codex', 'cline', 'trae'];
|
||||||
|
|
||||||
const traeProfile = getRulesProfile('trae');
|
for (const profileName of nonMcpProfiles) {
|
||||||
expect(traeProfile.mcpConfigName).toBe(null);
|
const profile = getRulesProfile(profileName);
|
||||||
|
expect(profile.mcpConfigName).toBe(null);
|
||||||
const claudeProfile = getRulesProfile('claude');
|
}
|
||||||
expect(claudeProfile.mcpConfigName).toBe(null);
|
|
||||||
|
|
||||||
const codexProfile = getRulesProfile('codex');
|
|
||||||
expect(codexProfile.mcpConfigName).toBe(null);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -185,17 +186,19 @@ describe('MCP Configuration Validation', () => {
|
|||||||
|
|
||||||
describe('MCP Configuration Creation Logic', () => {
|
describe('MCP Configuration Creation Logic', () => {
|
||||||
test('should indicate which profiles require MCP configuration creation', () => {
|
test('should indicate which profiles require MCP configuration creation', () => {
|
||||||
|
// Get all profiles that have MCP configuration enabled
|
||||||
const mcpEnabledProfiles = RULE_PROFILES.filter((profileName) => {
|
const mcpEnabledProfiles = RULE_PROFILES.filter((profileName) => {
|
||||||
const profile = getRulesProfile(profileName);
|
const profile = getRulesProfile(profileName);
|
||||||
return profile.mcpConfig !== false;
|
return profile.mcpConfig !== false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Verify expected MCP-enabled profiles
|
||||||
|
expect(mcpEnabledProfiles).toContain('claude');
|
||||||
expect(mcpEnabledProfiles).toContain('cursor');
|
expect(mcpEnabledProfiles).toContain('cursor');
|
||||||
expect(mcpEnabledProfiles).toContain('gemini');
|
expect(mcpEnabledProfiles).toContain('gemini');
|
||||||
expect(mcpEnabledProfiles).toContain('roo');
|
expect(mcpEnabledProfiles).toContain('roo');
|
||||||
expect(mcpEnabledProfiles).toContain('vscode');
|
expect(mcpEnabledProfiles).toContain('vscode');
|
||||||
expect(mcpEnabledProfiles).toContain('windsurf');
|
expect(mcpEnabledProfiles).toContain('windsurf');
|
||||||
expect(mcpEnabledProfiles).not.toContain('claude');
|
|
||||||
expect(mcpEnabledProfiles).not.toContain('cline');
|
expect(mcpEnabledProfiles).not.toContain('cline');
|
||||||
expect(mcpEnabledProfiles).not.toContain('codex');
|
expect(mcpEnabledProfiles).not.toContain('codex');
|
||||||
expect(mcpEnabledProfiles).not.toContain('trae');
|
expect(mcpEnabledProfiles).not.toContain('trae');
|
||||||
@@ -215,18 +218,25 @@ describe('MCP Configuration Validation', () => {
|
|||||||
|
|
||||||
describe('MCP Configuration Path Usage Verification', () => {
|
describe('MCP Configuration Path Usage Verification', () => {
|
||||||
test('should verify that rule transformer functions use mcpConfigPath correctly', () => {
|
test('should verify that rule transformer functions use mcpConfigPath correctly', () => {
|
||||||
// This test verifies that the mcpConfigPath property exists and is properly formatted
|
|
||||||
// for use with the setupMCPConfiguration function
|
|
||||||
RULE_PROFILES.forEach((profileName) => {
|
RULE_PROFILES.forEach((profileName) => {
|
||||||
const profile = getRulesProfile(profileName);
|
const profile = getRulesProfile(profileName);
|
||||||
if (profile.mcpConfig !== false) {
|
if (profile.mcpConfig !== false) {
|
||||||
// Verify the path is properly formatted for path.join usage
|
// Verify the path is properly formatted for path.join usage
|
||||||
expect(profile.mcpConfigPath.startsWith('/')).toBe(false);
|
expect(profile.mcpConfigPath.startsWith('/')).toBe(false);
|
||||||
expect(profile.mcpConfigPath).toContain('/');
|
|
||||||
|
// Claude profile uses root directory (.), so its path is just '.mcp.json'
|
||||||
|
if (profileName === 'claude') {
|
||||||
|
expect(profile.mcpConfigPath).toBe('.mcp.json');
|
||||||
|
} else {
|
||||||
|
expect(profile.mcpConfigPath).toContain('/');
|
||||||
|
}
|
||||||
|
|
||||||
// Verify it matches the expected pattern: profileDir/configName
|
// Verify it matches the expected pattern: profileDir/configName
|
||||||
const expectedPath = `${profile.profileDir}/${profile.mcpConfigName}`;
|
const expectedPath = `${profile.profileDir}/${profile.mcpConfigName}`;
|
||||||
expect(profile.mcpConfigPath).toBe(expectedPath);
|
// For Claude, path.join('.', '.mcp.json') returns '.mcp.json'
|
||||||
|
const normalizedExpected =
|
||||||
|
profileName === 'claude' ? '.mcp.json' : expectedPath;
|
||||||
|
expect(profile.mcpConfigPath).toBe(normalizedExpected);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -250,20 +260,19 @@ describe('MCP Configuration Validation', () => {
|
|||||||
|
|
||||||
describe('MCP Configuration Function Integration', () => {
|
describe('MCP Configuration Function Integration', () => {
|
||||||
test('should verify that setupMCPConfiguration receives the correct mcpConfigPath parameter', () => {
|
test('should verify that setupMCPConfiguration receives the correct mcpConfigPath parameter', () => {
|
||||||
// This test verifies the integration between rule transformer and mcp-utils
|
|
||||||
RULE_PROFILES.forEach((profileName) => {
|
RULE_PROFILES.forEach((profileName) => {
|
||||||
const profile = getRulesProfile(profileName);
|
const profile = getRulesProfile(profileName);
|
||||||
if (profile.mcpConfig !== false) {
|
if (profile.mcpConfig !== false) {
|
||||||
// Verify that the mcpConfigPath can be used directly with setupMCPConfiguration
|
|
||||||
// The function signature is: setupMCPConfiguration(projectDir, mcpConfigPath)
|
|
||||||
expect(profile.mcpConfigPath).toBeDefined();
|
|
||||||
expect(typeof profile.mcpConfigPath).toBe('string');
|
|
||||||
|
|
||||||
// Verify the path structure is correct for the new function signature
|
// Verify the path structure is correct for the new function signature
|
||||||
const parts = profile.mcpConfigPath.split('/');
|
if (profileName === 'claude') {
|
||||||
expect(parts).toHaveLength(2); // Should be profileDir/configName
|
// Claude profile uses root directory, so path is just '.mcp.json'
|
||||||
expect(parts[0]).toBe(profile.profileDir);
|
expect(profile.mcpConfigPath).toBe('.mcp.json');
|
||||||
expect(parts[1]).toBe(profile.mcpConfigName);
|
} else {
|
||||||
|
const parts = profile.mcpConfigPath.split('/');
|
||||||
|
expect(parts).toHaveLength(2); // Should be profileDir/configName
|
||||||
|
expect(parts[0]).toBe(profile.profileDir);
|
||||||
|
expect(parts[1]).toBe(profile.mcpConfigName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -271,7 +280,9 @@ describe('MCP Configuration Validation', () => {
|
|||||||
|
|
||||||
describe('MCP configuration validation', () => {
|
describe('MCP configuration validation', () => {
|
||||||
const mcpProfiles = ['cursor', 'gemini', 'roo', 'windsurf', 'vscode'];
|
const mcpProfiles = ['cursor', 'gemini', 'roo', 'windsurf', 'vscode'];
|
||||||
const nonMcpProfiles = ['claude', 'codex', 'cline', 'trae'];
|
const nonMcpProfiles = ['codex', 'cline', 'trae'];
|
||||||
|
const profilesWithLifecycle = ['claude'];
|
||||||
|
const profilesWithoutLifecycle = ['codex'];
|
||||||
|
|
||||||
test.each(mcpProfiles)(
|
test.each(mcpProfiles)(
|
||||||
'should have valid MCP config for %s profile',
|
'should have valid MCP config for %s profile',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
getRulesProfile
|
getRulesProfile
|
||||||
} from '../../../src/utils/rule-transformer.js';
|
} from '../../../src/utils/rule-transformer.js';
|
||||||
import { RULE_PROFILES } from '../../../src/constants/profiles.js';
|
import { RULE_PROFILES } from '../../../src/constants/profiles.js';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
describe('Rule Transformer - General', () => {
|
describe('Rule Transformer - General', () => {
|
||||||
describe('Profile Configuration Validation', () => {
|
describe('Profile Configuration Validation', () => {
|
||||||
@@ -166,19 +167,13 @@ describe('Rule Transformer - General', () => {
|
|||||||
// Check types based on MCP configuration
|
// Check types based on MCP configuration
|
||||||
expect(typeof profileConfig.mcpConfig).toBe('boolean');
|
expect(typeof profileConfig.mcpConfig).toBe('boolean');
|
||||||
|
|
||||||
if (profileConfig.mcpConfig === false) {
|
if (profileConfig.mcpConfig !== false) {
|
||||||
// Profiles without MCP configuration
|
|
||||||
expect(profileConfig.mcpConfigName).toBe(null);
|
|
||||||
expect(profileConfig.mcpConfigPath).toBe(null);
|
|
||||||
} else {
|
|
||||||
// Profiles with MCP configuration
|
|
||||||
expect(typeof profileConfig.mcpConfigName).toBe('string');
|
|
||||||
expect(typeof profileConfig.mcpConfigPath).toBe('string');
|
|
||||||
|
|
||||||
// Check that mcpConfigPath is properly constructed
|
// Check that mcpConfigPath is properly constructed
|
||||||
expect(profileConfig.mcpConfigPath).toBe(
|
const expectedPath = path.join(
|
||||||
`${profileConfig.profileDir}/${profileConfig.mcpConfigName}`
|
profileConfig.profileDir,
|
||||||
|
profileConfig.mcpConfigName
|
||||||
);
|
);
|
||||||
|
expect(profileConfig.mcpConfigPath).toBe(expectedPath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -186,9 +181,9 @@ describe('Rule Transformer - General', () => {
|
|||||||
it('should have correct MCP configuration for each profile', () => {
|
it('should have correct MCP configuration for each profile', () => {
|
||||||
const expectedConfigs = {
|
const expectedConfigs = {
|
||||||
claude: {
|
claude: {
|
||||||
mcpConfig: false,
|
mcpConfig: true,
|
||||||
mcpConfigName: null,
|
mcpConfigName: '.mcp.json',
|
||||||
expectedPath: null
|
expectedPath: '.mcp.json'
|
||||||
},
|
},
|
||||||
cline: {
|
cline: {
|
||||||
mcpConfig: false,
|
mcpConfig: false,
|
||||||
@@ -245,25 +240,19 @@ describe('Rule Transformer - General', () => {
|
|||||||
it('should have consistent profileDir and mcpConfigPath relationship', () => {
|
it('should have consistent profileDir and mcpConfigPath relationship', () => {
|
||||||
RULE_PROFILES.forEach((profile) => {
|
RULE_PROFILES.forEach((profile) => {
|
||||||
const profileConfig = getRulesProfile(profile);
|
const profileConfig = getRulesProfile(profile);
|
||||||
|
if (profileConfig.mcpConfig !== false) {
|
||||||
if (profileConfig.mcpConfig === false) {
|
|
||||||
// Profiles without MCP configuration have null mcpConfigPath
|
|
||||||
expect(profileConfig.mcpConfigPath).toBe(null);
|
|
||||||
} else {
|
|
||||||
// Profiles with MCP configuration should have valid paths
|
// Profiles with MCP configuration should have valid paths
|
||||||
// The mcpConfigPath should start with the profileDir
|
// The mcpConfigPath should start with the profileDir
|
||||||
expect(profileConfig.mcpConfigPath).toMatch(
|
if (profile === 'claude') {
|
||||||
new RegExp(
|
// Claude uses root directory (.), so path.join('.', '.mcp.json') = '.mcp.json'
|
||||||
`^${profileConfig.profileDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/`
|
expect(profileConfig.mcpConfigPath).toBe('.mcp.json');
|
||||||
)
|
} else {
|
||||||
);
|
expect(profileConfig.mcpConfigPath).toMatch(
|
||||||
|
new RegExp(
|
||||||
// The mcpConfigPath should end with the mcpConfigName
|
`^${profileConfig.profileDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/`
|
||||||
expect(profileConfig.mcpConfigPath).toMatch(
|
)
|
||||||
new RegExp(
|
);
|
||||||
`${profileConfig.mcpConfigName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`
|
}
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user