feat: add MCP timeout configuration for long-running operations (#1112)
This commit is contained in:
13
.changeset/mcp-timeout-configuration.md
Normal file
13
.changeset/mcp-timeout-configuration.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Enhanced Roo Code profile with MCP timeout configuration for improved reliability during long-running AI operations. The Roo profile now automatically configures a 300-second timeout for MCP server operations, preventing timeouts during complex tasks like `parse-prd`, `expand-all`, `analyze-complexity`, and `research` operations. This change also replaces static MCP configuration files with programmatic generation for better maintainability.
|
||||
|
||||
**What's New:**
|
||||
- 300-second timeout for MCP operations (up from default 60 seconds)
|
||||
- Programmatic MCP configuration generation (replaces static asset files)
|
||||
- Enhanced reliability for AI-powered operations
|
||||
- Consistent with other AI coding assistant profiles
|
||||
|
||||
**Migration:** No user action required - existing Roo Code installations will automatically receive the enhanced MCP configuration on next initialization.
|
||||
@@ -235,6 +235,60 @@ node scripts/init.js
|
||||
- "MCP provider requires session context" → Ensure running in MCP environment
|
||||
- See the [MCP Provider Guide](./mcp-provider-guide.md) for detailed troubleshooting
|
||||
|
||||
### MCP Timeout Configuration
|
||||
|
||||
Long-running AI operations in taskmaster-ai can exceed the default 60-second MCP timeout. Operations like `parse_prd`, `expand_task`, `research`, and `analyze_project_complexity` may take 2-5 minutes to complete.
|
||||
|
||||
#### Adding Timeout Configuration
|
||||
|
||||
Add a `timeout` parameter to your MCP configuration to extend the timeout limit. The timeout configuration works identically across MCP clients including Cursor, Windsurf, and RooCode:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"task-master-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"timeout": 300,
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "your-anthropic-api-key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Configuration Details:**
|
||||
- **`timeout: 300`** - Sets timeout to 300 seconds (5 minutes)
|
||||
- **Value range**: 1-3600 seconds (1 second to 1 hour)
|
||||
- **Recommended**: 300 seconds provides sufficient time for most AI operations
|
||||
- **Format**: Integer value in seconds (not milliseconds)
|
||||
|
||||
#### Automatic Setup
|
||||
|
||||
When adding taskmaster rules for supported editors, the timeout configuration is automatically included:
|
||||
|
||||
```bash
|
||||
# Automatically includes timeout configuration
|
||||
task-master rules add cursor
|
||||
task-master rules add roo
|
||||
task-master rules add windsurf
|
||||
task-master rules add vscode
|
||||
```
|
||||
|
||||
#### Troubleshooting Timeouts
|
||||
|
||||
If you're still experiencing timeout errors:
|
||||
|
||||
1. **Verify configuration**: Check that `timeout: 300` is present in your MCP config
|
||||
2. **Restart editor**: Restart your editor after making configuration changes
|
||||
3. **Increase timeout**: For very complex operations, try `timeout: 600` (10 minutes)
|
||||
4. **Check API keys**: Ensure required API keys are properly configured
|
||||
|
||||
**Expected behavior:**
|
||||
- **Before fix**: Operations fail after 60 seconds with `MCP request timed out after 60000ms`
|
||||
- **After fix**: Operations complete successfully within the configured timeout limit
|
||||
|
||||
### Google Vertex AI Configuration
|
||||
|
||||
Google Vertex AI is Google Cloud's enterprise AI platform and requires specific configuration:
|
||||
|
||||
@@ -5,6 +5,37 @@ import { isSilentMode, log } from '../../scripts/modules/utils.js';
|
||||
import { createProfile, COMMON_TOOL_MAPPINGS } from './base-profile.js';
|
||||
import { ROO_MODES } from '../constants/profiles.js';
|
||||
|
||||
// Import the shared MCP configuration helper
|
||||
import { formatJSONWithTabs } from '../utils/create-mcp-config.js';
|
||||
|
||||
// Roo-specific MCP configuration enhancements
|
||||
function enhanceRooMCPConfiguration(mcpPath) {
|
||||
if (!fs.existsSync(mcpPath)) {
|
||||
log('warn', `[Roo] MCP configuration file not found at ${mcpPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Read the existing configuration
|
||||
const mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
||||
|
||||
if (mcpConfig.mcpServers && mcpConfig.mcpServers['task-master-ai']) {
|
||||
const server = mcpConfig.mcpServers['task-master-ai'];
|
||||
|
||||
// Add Roo-specific timeout enhancement for long-running AI operations
|
||||
server.timeout = 300;
|
||||
|
||||
// Write the enhanced configuration back
|
||||
fs.writeFileSync(mcpPath, formatJSONWithTabs(mcpConfig) + '\n');
|
||||
log('debug', `[Roo] Enhanced MCP configuration with timeout at ${mcpPath}`);
|
||||
} else {
|
||||
log('warn', `[Roo] task-master-ai server not found in MCP configuration`);
|
||||
}
|
||||
} catch (error) {
|
||||
log('error', `[Roo] Failed to enhance MCP configuration: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Lifecycle functions for Roo profile
|
||||
function onAddRulesProfile(targetDir, assetsDir) {
|
||||
// Use the provided assets directory to find the roocode directory
|
||||
@@ -32,6 +63,9 @@ function onAddRulesProfile(targetDir, assetsDir) {
|
||||
}
|
||||
}
|
||||
|
||||
// Note: MCP configuration is now handled by the base profile system
|
||||
// The base profile will call setupMCPConfiguration, and we enhance it in onPostConvert
|
||||
|
||||
for (const mode of ROO_MODES) {
|
||||
const src = path.join(rooModesDir, `rules-${mode}`, `${mode}-rules`);
|
||||
const dest = path.join(targetDir, '.roo', `rules-${mode}`, `${mode}-rules`);
|
||||
@@ -78,6 +112,15 @@ function onRemoveRulesProfile(targetDir) {
|
||||
|
||||
const rooDir = path.join(targetDir, '.roo');
|
||||
if (fs.existsSync(rooDir)) {
|
||||
// Remove MCP configuration
|
||||
const mcpPath = path.join(rooDir, 'mcp.json');
|
||||
try {
|
||||
fs.rmSync(mcpPath, { force: true });
|
||||
log('debug', `[Roo] Removed MCP configuration from ${mcpPath}`);
|
||||
} catch (err) {
|
||||
log('error', `[Roo] Failed to remove MCP configuration: ${err.message}`);
|
||||
}
|
||||
|
||||
fs.readdirSync(rooDir).forEach((entry) => {
|
||||
if (entry.startsWith('rules-')) {
|
||||
const modeDir = path.join(rooDir, entry);
|
||||
@@ -101,7 +144,13 @@ function onRemoveRulesProfile(targetDir) {
|
||||
}
|
||||
|
||||
function onPostConvertRulesProfile(targetDir, assetsDir) {
|
||||
onAddRulesProfile(targetDir, assetsDir);
|
||||
// Enhance the MCP configuration with Roo-specific features after base setup
|
||||
const mcpPath = path.join(targetDir, '.roo', 'mcp.json');
|
||||
try {
|
||||
enhanceRooMCPConfiguration(mcpPath);
|
||||
} catch (err) {
|
||||
log('error', `[Roo] Failed to enhance MCP configuration: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export roo profile using the base factory
|
||||
@@ -111,6 +160,7 @@ export const rooProfile = createProfile({
|
||||
url: 'roocode.com',
|
||||
docsUrl: 'docs.roocode.com',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.ROO_STYLE,
|
||||
mcpConfig: true, // Enable MCP config - we enhance it with Roo-specific features
|
||||
onAdd: onAddRulesProfile,
|
||||
onRemove: onRemoveRulesProfile,
|
||||
onPostConvert: onPostConvertRulesProfile
|
||||
|
||||
@@ -262,3 +262,6 @@ export function removeTaskMasterMCPConfiguration(projectRoot, mcpConfigPath) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Export the formatting function for use by other modules
|
||||
export { formatJSONWithTabs };
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('Roo Profile Initialization Functionality', () => {
|
||||
expect(rooProfile.displayName).toBe('Roo Code');
|
||||
expect(rooProfile.profileDir).toBe('.roo'); // default
|
||||
expect(rooProfile.rulesDir).toBe('.roo/rules'); // default
|
||||
expect(rooProfile.mcpConfig).toBe(true); // default
|
||||
expect(rooProfile.mcpConfig).toBe(true); // now uses standard MCP configuration with Roo enhancements
|
||||
});
|
||||
|
||||
test('roo.js uses custom ROO_STYLE tool mappings', () => {
|
||||
|
||||
@@ -266,10 +266,10 @@ describe('MCP Configuration Validation', () => {
|
||||
expect(mcpEnabledProfiles).toContain('cursor');
|
||||
expect(mcpEnabledProfiles).toContain('gemini');
|
||||
expect(mcpEnabledProfiles).toContain('opencode');
|
||||
expect(mcpEnabledProfiles).toContain('roo');
|
||||
expect(mcpEnabledProfiles).toContain('vscode');
|
||||
expect(mcpEnabledProfiles).toContain('windsurf');
|
||||
expect(mcpEnabledProfiles).toContain('zed');
|
||||
expect(mcpEnabledProfiles).toContain('roo');
|
||||
expect(mcpEnabledProfiles).not.toContain('cline');
|
||||
expect(mcpEnabledProfiles).not.toContain('codex');
|
||||
expect(mcpEnabledProfiles).not.toContain('trae');
|
||||
@@ -384,6 +384,7 @@ describe('MCP Configuration Validation', () => {
|
||||
'claude',
|
||||
'cursor',
|
||||
'gemini',
|
||||
'kiro',
|
||||
'opencode',
|
||||
'roo',
|
||||
'windsurf',
|
||||
|
||||
Reference in New Issue
Block a user