{"record":{"id":"19b6671383d8aa1d","repo":"abhigyanpatwari/GitNexus","slug":"group-routing-is-unavailable-when-an-mcp-repositor","errorCode":null,"errorMessage":"Group routing is unavailable when an MCP repository allowlist is set.","messagePattern":"Group routing is unavailable when an MCP repository allowlist is set\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/repository-policy.ts","lineNumber":141,"sourceCode":"        .filter((name) => registryNameCounts.get(name) === 1),\n    );\n  }\n\n  private resolveRuntimeRepo(specifier: string): ResolvedRepository {\n    const result = resolveSpecifier(specifier, this.registry);\n    if (!result.repo || (this.restricted && !this.allowedPathKeys.has(result.repo.pathKey))) {\n      throw unavailableRepositoryError();\n    }\n    return result.repo;\n  }\n\n  private repoForArgs(args: Record<string, unknown> | undefined): ResolvedRepository | undefined {\n    const explicit = args?.repo;\n    if (explicit !== undefined) {\n      if (typeof explicit !== 'string') throw unavailableRepositoryError();\n      if (explicit.trim().startsWith('@')) {\n        if (this.restricted) {\n          throw new Error('Group routing is unavailable when an MCP repository allowlist is set.');\n        }\n        return undefined;\n      }\n      return this.resolveRuntimeRepo(explicit);\n    }\n\n    if (this.defaultRepo) return this.defaultRepo;\n    if (this.restricted && this.allowed.length === 1) return this.allowed[0];\n    if (this.restricted && this.allowed.length > 1) {\n      throw new Error('Specify an explicit repo because multiple repositories are allowed.');\n    }\n    return undefined;\n  }\n\n  private normalizeToolArgs(\n    args: Record<string, unknown> | undefined,\n  ): Record<string, unknown> | undefined {\n    if (!this.configured) return args;","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/52924ef12c2290ceee4612526a828ec4cdf2047f/gitnexus/src/mcp/repository-policy.ts#L123-L159","documentation":"Thrown by McpRepositoryPolicy.repoForArgs when an allowlist is configured (GITNEXUS_MCP_ALLOWED_REPOS set, so restricted=true) and a tool call passes a repo argument starting with '@'. Group routing and repository allowlists are mutually exclusive by design: an allowlist pins the server to specific local repos, so it must not fan a call out across a group.","triggerScenarios":"With GITNEXUS_MCP_ALLOWED_REPOS set, calling any MCP tool with arguments like { repo: '@org' } (leading whitespace trimmed). Note the same call succeeds when no allowlist is configured.","commonSituations":"A server originally deployed for cross-repo group queries later gets an allowlist tightened onto it, and existing client prompts keep sending @group repos. Agents copy the group-routing example from cross-repo docs into an allowlisted deployment.","solutions":["Pass an explicit repo that is on the allowlist, e.g. repo: 'frontend' — the policy resolves it against the allowed entries.","If group routing is required, remove GITNEXUS_MCP_ALLOWED_REPOS from the server environment.","Update shared agent templates to derive the repo argument from the deployment configuration instead of hard-coding '@group'."],"exampleFix":"# server env (before)\nGITNEXUS_MCP_ALLOWED_REPOS=frontend,backend\n# client call (before): repo: '@org'\n\n# client call (after)\nawait client.callTool({ name: 'query', arguments: { search_query: 'auth', repo: 'frontend' } });","handlingStrategy":"validation","validationCode":"function assertRepoCompatibleWithAllowlist(repo: unknown, allowlistConfigured: boolean) {\n  if (allowlistConfigured && typeof repo === 'string' && repo.trim().startsWith('@')) {\n    throw new Error('This endpoint has a repository allowlist; pass an explicit repo instead of @group.');\n  }\n}","typeGuard":"const isAllowedRepoArg = (repo: unknown): repo is string =>\n  typeof repo === 'string' && !repo.trim().startsWith('@');","tryCatchPattern":"try {\n  await client.callTool({ name: 'query', arguments: { search_query: q, repo } });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Group routing is unavailable')) {\n    throw new Error('Group routing disabled by allowlist — ask the operator for the repo list.');\n  }\n  throw e;\n}","preventionTips":["Read the server's capabilities once at session start and choose group vs explicit-repo strategy accordingly.","Never ship '@group' literals in shared prompts; make the repo argument a configured variable.","When tightening a deployment with an allowlist, grep client configs for '@' repos at the same time."],"tags":["mcp","allowlist","group-routing","authorization","configuration"],"backgroundTag":"allowlist-restriction","analyzedSha":"52924ef12c2290ceee4612526a828ec4cdf2047f","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}