Skip to content

Concurrent tool calls on same session hang indefinitely (Dynamic GitLab API) #310

@suguanYang

Description

@suguanYang

When using the Dynamic GitLab API, making concurrent tool calls with the same mcp-session-id causes the second (and subsequent) requests to hang indefinitely until timeout.

Expected Behavior

Both tool calls should complete successfully and return file contents.

Actual Behavior

First request completes successfully (returns file content)
Second request hangs indefinitely (no response)
After 60 seconds: McpError: MCP error -32001: Request timed out

script.js

import { MultiServerMCPClient } from '@langchain/mcp-adapters';

/**
 * 
 * Setup:
 * 1. Start MCP server
 * 2. Configure MCP_ENDPOINT below
 * 3. Run: node test.js
 * 
 * Expected: Both files fetched successfully
 * Actual: Second request hangs for 60s then times out
 */

const MCP_ENDPOINT = process.env.MCP_ENDPOINT || 'http://127.0.0.1:3002/mcp';
const PROJECT_ID = process.env.PROJECT_ID || 'xxx';

async function testConcurrentCalls() {
    console.log('🔧 Connecting to MCP server at:', MCP_ENDPOINT);

    const client = new MultiServerMCPClient({
        mcpServers: {
            gitlab: {
                transport: 'http',
                url: MCP_ENDPOINT,
                headers: {
                    Authorization: `Bearer xxx`,
                    'X-GitLab-API-URL': 'http://gitlab.xxx.com',
                },
            },
        },
        beforeToolCall: ({ serverName, name, args }) => {
            // Inject custom headers for this specific call
            return {
                args,
                headers: {
                    Authorization: `Bearer xxx`,
                    'X-GitLab-API-URL': 'http://gitlab.xxx.com',
                },
            }
        },
    });

    // Get tools
    const tools = await client.getTools();
    const getFileContentsTool = tools.find((t) => t.name === 'get_file_contents');

    if (!getFileContentsTool) {
        throw new Error('get_file_contents tool not found');
    }

    console.log('✅ Found get_file_contents tool');

    // Test 1: Sequential calls (should work)
    console.log('\n📝 Test 1: Sequential calls');
    console.time('Sequential');

    await getFileContentsTool.invoke({
        project_id: PROJECT_ID,
        file_path: 'package.json',
        ref: 'test',
    });
    console.log('  ✅ File 1 fetched');

    await getFileContentsTool.invoke({
        project_id: PROJECT_ID,
        file_path: 'README.md',
        ref: 'test',
    });
    console.log('  ✅ File 2 fetched');

    console.timeEnd('Sequential');

    // Test 2: Concurrent calls (BUG - second one will hang)
    console.log('\n⚠️  Test 2: Concurrent calls (THIS WILL HANG)');
    console.time('Concurrent');

    try {
        const [file3, file4] = await Promise.all([
            getFileContentsTool.invoke({
                project_id: PROJECT_ID,
                file_path: 'package.json',
                ref: 'test',
            }),
            getFileContentsTool.invoke({
                project_id: PROJECT_ID,
                file_path: 'README.md',
                ref: 'test',
            }),
        ]);

        console.log('  ✅ File 3 fetched');
        console.log('  ✅ File 4 fetched');
        console.timeEnd('Concurrent');
    } catch (error) {
        console.timeEnd('Concurrent');
        console.error('  ❌ Error:', error.message);
        throw error;
    }
}

testConcurrentCalls()
    .then(() => {
        console.log('\n✅ All tests passed!');
        process.exit(0);
    })
    .catch((error) => {
        console.error('\n❌ Test failed:', error.message);
        process.exit(1);
    });

script.js Output

🔧 Connecting to MCP server at: http://127.0.0.1:3002/mcp
✅ Client created
✅ Found get_file_contents tool

📝 Test 1: Sequential calls
  ✅ File 1 fetched
  ✅ File 2 fetched
Sequential: 354.626ms

⚠️  Test 2: Concurrent calls (THIS WILL HANG)
McpError: MCP error -32001: Request timed out
    at McpError.fromError (file:///home/binqi/github/dependencies-builder/node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.1_@cfworker+json-schema@4.1.1_hono@4.10.6_zod@4.1.12/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js:2035:16)
    at Timeout.timeoutHandler (file:///home/binqi/github/dependencies-builder/node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.1_@cfworker+json-schema@4.1.1_hono@4.10.6_zod@4.1.12/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js:692:58)
    at listOnTimeout (node:internal/timers:594:17)
    at process.processTimers (node:internal/timers:529:7) {
  code: -32001,
  data: { timeout: 60000 }
}
Concurrent: 1:00.039 (m:ss.mmm)
  ❌ Error: Error calling tool get_file_contents: McpError: MCP error -32001: Request timed out

❌ Test failed: Error calling tool get_file_contents: McpError: MCP error -32001: Request timed out

mcp output

INFO [06:35:37.933] (1772223): Remote authorization enabled: tokens will be read from HTTP headers
INFO [06:35:37.933] (1772223): Configuration validation passed
INFO [06:35:37.934] (1772223): Initializing server with transport mode:
WARN [06:35:37.934] (1772223): Starting GitLab MCP Server with Streamable HTTP transport
INFO [06:35:37.941] (1772223): Configured GitLab API URLs: http://gitlab.seeyon.com/api/v4
INFO [06:35:37.941] (1772223): Default GitLab API URL: http://gitlab.seeyon.com/api/v4
INFO [06:35:37.948] (1772223): GitLab MCP Server running with Streamable HTTP transport
INFO [06:35:37.948] (1772223): Endpoint: http://127.0.0.1:3002/mcp
WARN [06:35:47.857] (1772223): Streamable HTTP session initialized: a6b1c09f-90ec-4696-9d08-ce9235758c4f
INFO [06:35:47.857] (1772223): Session a6b1c09f-90ec-4696-9d08-ce9235758c4f: stored Authorization header
DEBUG [06:35:47.892] (1772223): Session a6b1c09f-90ec-4696-9d08-ce9235758c4f: updated Authorization header
DEBUG [06:35:47.905] (1772223): Session a6b1c09f-90ec-4696-9d08-ce9235758c4f: updated Authorization header
WARN [06:35:47.930] (1772223): Streamable HTTP session initialized: 1c822589-3d9c-4812-bd31-dd563b71c5e8
INFO [06:35:47.930] (1772223): Session 1c822589-3d9c-4812-bd31-dd563b71c5e8: stored Authorization header
DEBUG [06:35:47.936] (1772223): Session 1c822589-3d9c-4812-bd31-dd563b71c5e8: updated Authorization header
DEBUG [06:35:47.942] (1772223): Session 1c822589-3d9c-4812-bd31-dd563b71c5e8: updated Authorization header
INFO [06:35:47.947] (1772223): get_file_contents
DEBUG [06:35:47.948] (1772223): buildAuthHeaders: session context
    context: {
      "sessionId": "1c822589-3d9c-4812-bd31-dd563b71c5e8",
      "header": "Authorization",
      "token": "xxx",
      "lastUsed": 1767940547942,
      "apiUrl": "http://gitlab.xxx.com/api/v4"
    }
WARN [06:35:48.127] (1772223): Streamable HTTP session initialized: 0f3700ca-b62a-4275-bf31-ba1e7f6f06a8
INFO [06:35:48.127] (1772223): Session 0f3700ca-b62a-4275-bf31-ba1e7f6f06a8: stored Authorization header
DEBUG [06:35:48.134] (1772223): Session 0f3700ca-b62a-4275-bf31-ba1e7f6f06a8: updated Authorization header
DEBUG [06:35:48.140] (1772223): Session 0f3700ca-b62a-4275-bf31-ba1e7f6f06a8: updated Authorization header
INFO [06:35:48.141] (1772223): get_file_contents
DEBUG [06:35:48.142] (1772223): buildAuthHeaders: session context
    context: {
      "sessionId": "0f3700ca-b62a-4275-bf31-ba1e7f6f06a8",
      "header": "Authorization",
      "token": "xxx",
      "lastUsed": 1767940548139,
      "apiUrl": "http://gitlab.xxx.com/api/v4"
    }
WARN [06:35:48.316] (1772223): Streamable HTTP session initialized: dc5d0098-e2ab-435d-b282-28326b616e5f
INFO [06:35:48.316] (1772223): Session dc5d0098-e2ab-435d-b282-28326b616e5f: stored Authorization header
WARN [06:35:48.320] (1772223): Streamable HTTP session initialized: 149a183a-c743-4db2-affd-1a239a4e8909
INFO [06:35:48.320] (1772223): Session 149a183a-c743-4db2-affd-1a239a4e8909: stored Authorization header
DEBUG [06:35:48.325] (1772223): Session dc5d0098-e2ab-435d-b282-28326b616e5f: updated Authorization header
DEBUG [06:35:48.327] (1772223): Session 149a183a-c743-4db2-affd-1a239a4e8909: updated Authorization header
DEBUG [06:35:48.333] (1772223): Session dc5d0098-e2ab-435d-b282-28326b616e5f: updated Authorization header
INFO [06:35:48.335] (1772223): get_file_contents
DEBUG [06:35:48.335] (1772223): buildAuthHeaders: session context
    context: {
      "sessionId": "dc5d0098-e2ab-435d-b282-28326b616e5f",
      "header": "Authorization",
      "token": "xxx",
      "lastUsed": 1767940548333,
      "apiUrl": "http://gitlab.xxx.com/api/v4"
    }
DEBUG [06:35:48.336] (1772223): Session 149a183a-c743-4db2-affd-1a239a4e8909: updated Authorization header
INFO [06:35:48.338] (1772223): get_file_contents
DEBUG [06:35:48.338] (1772223): buildAuthHeaders: session context
    context: {
      "sessionId": "149a183a-c743-4db2-affd-1a239a4e8909",
      "header": "Authorization",
      "token": "xxx",
      "lastUsed": 1767940548336,
      "apiUrl": "http://gitlab.xxx.com/api/v4"
    }

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions