Skip to content

[FEATURE]: deferred tools for providers with tool count limits (xAI 200 max) #20500

Closed as not planned

Description

@JacekZubielik

Problem

xAI's API enforces a hard limit of 200 tools per request. When multiple MCP servers are configured, the total easily exceeds 200 and the API returns:

Bad Request: Maximum tools limit reached. 520 tools have been provided but the maximum is 200.

This is a server-side limit — @ai-sdk/xai and opencode pass all tools through without validation. There is no way to work around this from the user's opencode.json config today.

Other providers may have similar limits (e.g. some OpenAI-compatible endpoints).

Proposed Solution

Implement a hot/cold tool split inspired by Claude Code's deferred tools pattern:

  1. Detect provider tool limit — map known providers to their max (xAI/Grok → 200)
  2. Split tools — built-in tools get priority ("hot", full JSON schema sent to API), remaining MCP tools become "cold"
  3. System prompt injection — cold tool names + descriptions are appended to the system prompt so the LLM knows they exist
  4. Dispatcher tool — a single call_mcp_tool tool is added to the hot set. The LLM calls it with { tool_id, args } to invoke any cold tool at runtime

This keeps the API request under the limit while preserving access to all registered tools.

Implementation

Working proof-of-concept across 3 files:

packages/opencode/src/session/llm.ts — core logic:

const providerToolLimit = getProviderToolLimit(input.model.providerID)
let tools = allTools

if (providerToolLimit !== undefined && Object.keys(allTools).length > providerToolLimit) {
  const entries = Object.entries(allTools)
  const builtin = entries.filter(([k]) => !k.includes(":"))
  const mcp = entries.filter(([k]) => k.includes(":"))
  const hotSlots = providerToolLimit - 1 // reserve 1 for dispatcher
  const hotEntries = [...builtin, ...mcp].slice(0, hotSlots)
  const coldEntries = [...builtin, ...mcp].slice(hotSlots)
  const coldMap = Object.fromEntries(coldEntries)

  // Inject cold tool catalog into system prompt
  messages.push({ role: "system", content: coldSection })

  // Add dispatcher tool
  tools = { ...Object.fromEntries(hotEntries), call_mcp_tool: dispatcher }
}

packages/opencode/src/session/llm.ts — provider limit map:

function getProviderToolLimit(providerID: string): number | undefined {
  const id = providerID.toLowerCase()
  if (id.includes("xai") || id.includes("grok")) return 200
  return undefined
}

packages/opencode/src/config/config.ts — optional per-server tool whitelist (McpLocal + McpRemote):

tools: z
  .array(z.string())
  .optional()
  .describe("Whitelist of tool names to expose from this MCP server. If omitted, all tools are exposed.")

packages/opencode/src/mcp/index.ts — filter tools by whitelist before registration:

const filtered = mcp.tools?.length
  ? listed.filter((t) => mcp.tools.includes(t.name))
  : listed

Future Improvements

  • Make the limit configurable per provider in opencode.json (e.g. "toolLimit": 200)
  • Support ToolSearch-style lazy schema loading — LLM requests a tool's full schema before calling it, instead of getting all schemas upfront
  • Allow user to prioritize which MCP tools should be "hot" vs "cold"

Environment

  • opencode 1.3.9
  • xAI provider (Grok models)
  • Tested with 520+ tools, confirmed working after patch

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 1, 2026
  2. github-actions commented on Apr 1, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • Feature request titles must start with [FEATURE]: (current title uses feat:)
    • The feature request template requires checking the verification checkbox confirming the feature hasn't been suggested before

    Please edit this issue to address the above within 2 hours, or it will be automatically closed.


    This issue might be a duplicate of existing issues. Please check:

    If you believe this was flagged incorrectly, please let a maintainer know.

  3. changed the title [-]feat: deferred tools for providers with tool count limits (xAI 200 max)[/-] [+][FEATURE]: deferred tools for providers with tool count limits (xAI 200 max)[/+] on Apr 1, 2026
  4. github-actions commented on Apr 1, 2026

    @github-actions
    Contributor

    Thanks for updating the issue! It now meets our contributing guidelines. The [FEATURE]: title prefix is in place and the description clearly explains the problem, proposed solution, and environment. The needs:compliance label has been removed.

  5. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  6. github-actions commented on Jul 4, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions