abhigyanpatwari/GitNexus · error

Tool "${toolName}" is not available in GitNexus MCP read-onl

Error message

Tool "${toolName}" is not available in GitNexus MCP read-only mode.

What it means

Thrown by assertMcpReadOnlyToolCall when the MCP server runs in read-only mode (GITNEXUS_MCP_READ_ONLY=1) and a client invokes a tool that is not on the read-only allowlist. In read-only mode only the safe query tools in MCP_READ_ONLY_TOOLS and the legacy aliases 'search', 'explore', 'overview' are dispatchable; every mutating or non-allowlisted tool is rejected before it reaches the backend.

Source

Thrown at gitnexus/src/mcp/read-only-policy.ts:37

]);

const MCP_READ_ONLY_ALIASES = new Set(['search', 'explore', 'overview']);

export function resolveMcpReadOnlyMode(env: NodeJS.ProcessEnv = process.env): boolean {
  const value = env.GITNEXUS_MCP_READ_ONLY?.trim();
  if (value === undefined || value === '' || value === '0') return false;
  if (value === '1') return true;
  throw new Error('GITNEXUS_MCP_READ_ONLY must be 0 or 1.');
}

export function assertMcpReadOnlyToolCall(
  toolName: string,
  args: Record<string, unknown> | undefined,
  readOnly: boolean,
): void {
  if (!readOnly) return;
  if (!MCP_READ_ONLY_TOOLS.has(toolName) && !MCP_READ_ONLY_ALIASES.has(toolName)) {
    throw new Error(`Tool "${toolName}" is not available in GitNexus MCP read-only mode.`);
  }
  if (typeof args?.repo === 'string' && args.repo.trim().startsWith('@')) {
    throw new Error('Group routing is not available in GitNexus MCP read-only mode.');
  }
  // crossDepth/subgroup only do anything on the @group path rejected above,
  // but rejecting them here keeps the advertised schema and the dispatch
  // contract in agreement.
  for (const groupOnlyArg of ['crossDepth', 'subgroup']) {
    if (args?.[groupOnlyArg] !== undefined) {
      throw new Error(
        `Parameter "${groupOnlyArg}" is not available in GitNexus MCP read-only mode.`,
      );
    }
  }
}

export function readOnlyResourceTemplateAllowed(uriTemplate: string, readOnly: boolean): boolean {
  return !readOnly || !/^gitnexus:\/\/group\//iu.test(uriTemplate);

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Switch the workflow to read-only-safe tools (query, context, impact, explain, and the other allowlisted read tools).
  2. If the mutation is genuinely required, restart the server with GITNEXUS_MCP_READ_ONLY unset or set to 0.
  3. Catch this error client-side and report to the user that the endpoint is read-only instead of retrying — retry cannot succeed.

Example fix

// before
await client.callTool({ name: 'rename', arguments: { target: 'parseArgs', new_name: 'parseCliArgs', repo: '.' } });

// after (read-only mode)
await client.callTool({ name: 'query', arguments: { search_query: 'parseArgs', repo: '.' } });
Defensive patterns

Strategy: validation

Validate before calling

const READ_ONLY_OK = new Set(['query', 'context', 'impact', 'explain', 'search', 'explore', 'overview' /* + the rest of the server's allowlist */]);
function assertToolAllowed(tool: string, readOnly: boolean) {
  if (readOnly && !READ_ONLY_OK.has(tool)) {
    throw new Error(`Tool ${tool} is not available in read-only mode; pick a read-only tool.`);
  }
}

Type guard

const isReadOnlyTool = (tool: string): boolean =>
  MCP_READ_ONLY_TOOLS.has(tool) || ['search', 'explore', 'overview'].includes(tool);

Try / catch

try {
  return await client.callTool({ name, arguments });
} catch (e) {
  if (e instanceof Error && /not available in GitNexus MCP read-only mode/.test(e.message)) {
    return { skipped: true, reason: 'endpoint is read-only' }; // degrade gracefully, never retry
  }
  throw e;
}

Prevention

When it happens

Trigger: With GITNEXUS_MCP_READ_ONLY=1, calling any tool outside the allowlist — e.g. rename, detect_changes, analyze, or any group_* tool — through the MCP client (callTool / tools/call).

Common situations: An operator hardens a shared MCP endpoint with read-only mode, then an agent re-runs its usual workflow that includes rename or detect_changes. A prompt/agent template written for read-write mode is reused against a read-only deployment.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/e8a7a360d1fbd59e. Report an issue: GitHub.