Experiment · Exploratory

MCP as the tool boundary for a multi-tenant agent platform

MCP standardises how tools are described and transported. It does not standardise who is allowed to call them - and in a multi-tenant product that is most of the work.

NEOB Engineering Published Updated 8 min readExploratory
mcpagent-infrastructuretool-useintegrations

Problem

Every customer integration adds a tool: their CRM, their calendar, their ticket system, their stock lookup. Written ad hoc, each one arrives with its own schema conventions, its own auth handling and its own error semantics, and the agent runtime slowly turns into an integration monolith.

The Model Context Protocol offers a standard shape for that boundary. The question was whether adopting it actually removes work in a multi-tenant setting, or just relocates it.

Hypothesis

Expressing integrations as MCP servers reduces per-integration runtime work to configuration. Authorisation, tenancy and rate limiting remain the platform's responsibility and must sit in front of the protocol, not inside it.

Architecture

Agent runtime

  • loop
  • model calls
  • tool selection

Tool broker (ours)

  • tenant scoping
  • authorisation
  • rate limits
  • audit log
  • schema pinning

MCP transport

  • tool discovery
  • JSON schemas
  • invocation
  • errors

MCP servers

  • CRM
  • calendar
  • ticketing
  • internal APIs
Where each concern lives once MCP is the tool boundary.

The broker layer is the part that is ours and cannot be delegated. An agent serving tenant A must not be able to reach tenant B's calendar server, and the protocol does not have an opinion about that - correctly, since it is an application concern.

Implementation

Tools are resolved per session rather than per deployment. When a conversation starts, the broker assembles the tool list from the tenant's enabled integrations, filters it by the agent's configured scope, and pins each tool schema to a version.

broker.ts - per-session tool resolution
// The agent never sees the full catalogue. It sees the intersection of
// what the tenant has connected and what this agent is scoped to use.
async function toolsFor(session: Session): Promise<Tool[]> {
  const connected = await registry.serversFor(session.tenantId)
  const tools: Tool[] = []

  for (const server of connected) {
    for (const t of await server.listTools()) {
      if (!session.agent.scopes.allows(server.id, t.name)) continue

      tools.push({
        // Namespaced: two servers may both offer "search".
        name: `${server.id}.${t.name}`,
        schema: pin(t.inputSchema, server.schemaVersion),
        invoke: (args) => broker.call(session, server, t, args),
      })
    }
  }
  return tools
}

Schema pinning

Discovery is dynamic; behaviour must not be. If a server changes a tool schema between sessions, agent instructions written against the old shape silently stop working. We pin the schema version per tenant and treat an upstream change as a migration with a diff, not as an automatic upgrade.

Error semantics

The distinction that mattered most was between "the tool failed" and "the tool worked and the answer is no". A calendar with no free slot is not an error, but naive wrappers report it as one, and the agent then retries a call that will never succeed. We normalise this at the broker: transport failures are errors, empty results are results.

Result

The hypothesis broadly held. With a broker in place, adding an integration became configuration plus a server, and the runtime stopped growing per customer - which was the actual goal.

What MCP did not remove: authorisation, tenancy, rate limiting, audit logging, schema governance and cost control. That is not a criticism of the protocol - those are application concerns and it is right that they sit outside it. But a plan that assumes adopting MCP replaces an integration layer will be wrong about roughly half the work.

One practical surprise: tool *description* quality dominates tool selection accuracy far more than the model does. Two servers exposing the same capability with differently-worded descriptions produced noticeably different agent behaviour. Descriptions are prompt engineering wearing an API costume.

Limitations

What this experiment does not establish. Listed because an experiment without limitations is an advertisement.

  • Exploratory. This runs in an internal environment against a small number of servers, not as a production integration surface.
  • We have not stress-tested large tool catalogues. Selection accuracy with dozens of similar tools is an open question we expect to be the real scaling limit.
  • Latency was not a focus. Tool discovery per session is fine at our sizes and would need caching well before it is not.
  • The protocol continues to evolve; anything written here is a snapshot of our reading of it in mid-2026 and should be checked against the current specification.

Next steps

  • Test selection accuracy as the catalogue grows, and find where a flat tool list stops working and needs hierarchical routing.
  • Automate schema-drift detection so an upstream change surfaces as a diff before it surfaces as a broken agent.
  • Evaluate whether the broker should expose itself as an MCP server in turn, so the same boundary composes.

References