How MCP Tools Work: Discovery, Invocation and Access Control
TL;DR
- MCP tools are executable functions an MCP server advertises to a client through
tools/listand runs on request throughtools/call, each described by a JSON Schema the model uses to build arguments. - The protocol defines two error paths: JSON-RPC protocol errors for unknown tools or malformed requests, and
isError: trueresults for failures inside the tool itself. - The MCP specification requires servers to validate inputs and implement access controls, but it leaves per-team authorization to the infrastructure between the agent and the server.
- Bifrost applies a deny-by-default allowlist of MCP tools to every virtual key, enforces it again at execution time, and records each tool call in request logs while a separate audit log tracks administrative changes.
MCP tools are the mechanism by which an AI model reads a file, queries a database, or opens a pull request instead of only producing text. The Model Context Protocol defines how a client discovers those tools, how it invokes them, and how results and errors come back. What the protocol does not define is which team inside a company is allowed to call which tool, and that gap is where most MCP governance problems start. Bifrost, the open-source AI gateway built by Maxim AI, closes it by sitting between agents and MCP servers as an MCP gateway that filters tools per virtual key, logs every call, and applies guardrails at the execution boundary; the sections below walk through the tool primitive end to end, then show how that control layer works.
What Are MCP Tools?
An MCP tool is a function that an MCP server exposes for a language model to invoke, described by a name, a description, and a JSON Schema for its inputs. Tools are one of three server primitives in the Model Context Protocol, alongside resources and prompts, and they are the only primitive designed to perform actions rather than supply context.
The specification frames tools as model-controlled: the server publishes them, the model requests one when its reasoning calls for it, and the client application sits in the middle with the authority to approve, modify, or refuse the call. That design mirrors the broader tool calling mechanisms in AI agents, where a function-calling model emits a structured request and the runtime executes it. MCP standardizes the wire format so that any client can talk to any server without bespoke integration code.
A server that offers tools must declare the tools capability during initialization, optionally with listChanged: true to signal that it will notify clients when its tool list changes. Bifrost consumes that capability as an MCP client for every server it connects to, and republishes the aggregated tool set as an MCP server.
How MCP Tool Discovery Works with tools/list
Tool discovery in MCP happens through a single JSON-RPC request, tools/list, which returns an array of tool definitions and an optional nextCursor for pagination. Clients call it after initialization, cache the result, and refresh it when the server sends a notifications/tools/list_changed message. Every subsequent choice the model makes about which tool to use rests on this list.
Each entry in the response carries a name, an optional human-readable title, a description the model reads to understand when the tool applies, and an inputSchema. A weather server, for example, returns a get_weather tool whose schema declares a required location string. Large servers page the list with nextCursor, so a client must follow the cursor to see every tool.
Discovery is the first place a gateway earns its position. When Bifrost runs as an MCP gateway, it exposes a single /mcp endpoint that answers tools/list with the union of tools from every connected server, already narrowed to what the calling virtual key is permitted to see. A client connecting through Bifrost never learns that a delete_file tool exists if its key is not allowed to call it. That is a stronger guarantee than trusting the model to ignore tools it should not use, and it is the foundation of the MCP server governance practices that larger teams adopt.
How MCP Tool Calling Works with tools/call
An MCP tool call is a tools/call JSON-RPC request carrying the tool name and an arguments object that must conform to the tool's input schema. The server executes the function and returns a content array (text, image, audio, resource links, or embedded resources), an optional structuredContent object, and an isError flag. The client then feeds the result back to the model.
The full sequence for one turn of an agent loop has four steps:
- The application sends the conversation and the available tool definitions to the model.
- The model returns a response containing one or more tool call requests with arguments.
- The client sends
tools/callto the MCP server for each approved request and receives the result. - The application appends the tool result to the conversation and calls the model again.
Bifrost keeps that loop explicit by default. A chat completion routed through Bifrost returns the model's tool calls without running them; the application reviews them and then submits the approved ones to the tool execution endpoint at /v1/mcp/tool/execute. Tool names come back prefixed with the MCP client name, so two servers that both expose a search tool never collide.
Teams that want autonomous execution turn on Agent Mode, which runs only the tools they have marked as auto-executable and returns everything else for approval. At high tool counts the cost of this loop is dominated by tool definitions in the prompt, which is why MCP tool calling at scale is as much a token problem as a latency problem.
MCP Tool Schemas and Annotations
Every MCP tool carries an inputSchema in JSON Schema format, and may carry an outputSchema and a set of annotations that describe its behavior. The input schema is what the model reads to construct arguments; the output schema lets clients validate structuredContent; the annotations tell the client whether a tool is read-only, destructive, idempotent, or interacts with external systems.
The four behavioral annotations defined in the specification are:
| Annotation | Default | What it signals |
|---|---|---|
readOnlyHint |
false |
The tool does not modify its environment |
destructiveHint |
true |
The tool may perform destructive updates (only meaningful when readOnlyHint is false) |
idempotentHint |
false |
Calling the tool repeatedly with the same arguments has no additional effect |
openWorldHint |
true |
The tool interacts with external entities such as the web rather than a closed system |
The specification is explicit that clients must treat annotations as untrusted unless the server itself is trusted. A compromised server can label a destructive tool as read-only, so annotations are a hint for user-interface decisions, not an access-control mechanism. Bifrost therefore bases its allowlists on the tool name and the originating MCP client, both of which Bifrost observes directly when it normalizes tool definitions from every connected server into one aggregated registry, rather than on hints the server self-reports.
How MCP Tools Report Errors
MCP separates errors into two categories: protocol errors, returned as standard JSON-RPC error objects, and tool execution errors, returned inside a successful JSON-RPC result with isError: true. The distinction tells the client whether the request itself was malformed or whether the tool ran and failed, and each category calls for a different response.
| Error type | Where it appears | Typical causes | Correct client behavior |
|---|---|---|---|
| Protocol error | JSON-RPC error object (for example code -32602) |
Unknown tool name, arguments that fail schema validation, server fault | Do not forward to the model as a tool result; fix the request or surface an infrastructure failure |
| Tool execution error | result.isError: true with explanatory content |
Upstream API failure, rate limit, invalid business input | Return the content to the model so it can retry, adjust arguments, or explain the failure to the user |
The second path is deliberate: the model is often the right party to handle a tool failure, because it can reformulate the request. An unknown-tool error, by contrast, usually means the tool list is stale or the client is misconfigured, and a model cannot fix either.
Transport failures sit underneath both. Bifrost handles them at the connection layer with automatic reconnection and exponential backoff for STDIO, HTTP, and SSE servers, so a server restart does not surface as a tool error in the agent loop. Bifrost also enforces a configurable tool execution timeout, which the specification recommends so that a hung tool cannot stall a conversation.
MCP Tools vs Resources vs Prompts
MCP defines three server-side primitives, and only tools perform actions; resources supply data for the model to read, and prompts supply reusable templates the user selects. Confusing the three leads to servers that expose read-only data as tools (wasting context and inviting unnecessary calls) or expose actions as resources (bypassing the approval flow tools are designed for).
| Primitive | Controlled by | Purpose | Discovery method | Side effects |
|---|---|---|---|---|
| Tools | Model | Execute a function and return a result | tools/list |
Yes, unless annotated read-only |
| Resources | Application | Provide file, database, or API content as context | resources/list, resources/read |
None |
| Prompts | User | Provide templated instructions or workflows | prompts/list, prompts/get |
None |
Because only tools carry side effects, tools are where governance effort concentrates. A gateway that centralizes tool access gives a platform team one place to decide what an agent can do; the post on MCP gateway access control and 92% lower token costs covers the resulting cost and control model, and the MCP gateway resource page covers how Bifrost aggregates all three primitives from connected servers.
Popular MCP Server Tools Teams Run
The MCP servers most engineering teams deploy today fall into five groups: source control, developer tooling, data stores, collaboration systems, and browser or filesystem access. The reference implementations live in the modelcontextprotocol/servers repository, and most major SaaS vendors now publish their own.
| Category | Representative servers | Example tools exposed | Governance concern |
|---|---|---|---|
| Source control | GitHub, GitLab | create_pull_request, push_files, search_code |
Write access to production repositories |
| Developer tooling | Playwright, Sentry, Context7 | browser_navigate, get_issue_details |
Browser sessions can reach internal URLs |
| Data stores | PostgreSQL, SQLite, Snowflake, BigQuery | query, execute_sql |
Direct read of customer data |
| Collaboration | Slack, Atlassian (Jira, Confluence), Notion, Linear | send_message, create_issue, create_page |
Outbound messages and ticket creation on a user's behalf |
| Local and filesystem | Filesystem, Fetch, Memory | read_file, write_file, fetch |
Arbitrary file writes on developer machines |
A single coding agent session can connect to a dozen of these. Bifrost connects to each of them once and presents the aggregate through one endpoint, which is the pattern behind connecting Claude Code to 500 MCP tools through one gateway. It is also the practical way to add and govern MCP servers in Claude Code without editing every developer's local configuration file.
Why Ungoverned MCP Tools Are a Security Problem
The MCP specification places tool security on two parties, the server and the client, and neither of them has visibility across an organization. A server validates its own inputs; a client prompts its own user. Nothing in that model stops a contractor's agent from reaching a drop_table tool that only the data platform team should hold, because both the server and the client will do exactly what they were built to do.
The specification's own security best practices describe the failure modes that follow: confused-deputy attacks through proxied authorization, token passthrough that lets a downstream server receive credentials it was never issued, and session hijacking on shared transports. Each is a consequence of tools being reachable without an intermediary that knows who is calling. The security risks of ungoverned MCP server access extend the list to prompt injection through tool results and unmonitored data exfiltration.
The organizational version of the problem is shadow MCP: servers configured by individual developers inside their editors, invisible to security teams, holding long-lived credentials. Solving it requires authentication that ties each tool call to an identity and a policy layer that decides what that identity may call. For regulated deployments, Bifrost Enterprise ships both, with in-VPC and air-gapped deployment options.
How Bifrost Controls Which MCP Tools Each Team Can Call
Bifrost enforces MCP tool access through a per-virtual-key allowlist that is deny-by-default, stacked on top of client-level and request-level filters, and re-checked at execution time. A team gets a virtual key, the key names the MCP clients and tools it may reach, and every other tool is invisible to that team's agents.
The three filtering levels combine so that a tool must pass all of them:
| Level | Configured on | Semantics | Who typically owns it |
|---|---|---|---|
| Client configuration | Each MCP client's tools_to_execute |
Baseline of tools Bifrost will ever expose from that server; [] or omitted means none |
Platform team |
| Virtual key configuration | mcp_configs on the key |
Ceiling for the key; no config means no tools except from clients marked Allow by Default | Platform or security team |
| Request headers | x-bf-mcp-include-clients, x-bf-mcp-include-tools |
Narrows within the key's ceiling for one request; can never widen it | Application developer |
The virtual-key level is where team scoping lives. A support team's key might grant search and get_article from a knowledge-base server and every tool from a ticketing server, while a data team's key grants query but not execute_sql. When the caller sends no include-tools header, Bifrost generates one from the key; when the caller does send one, Bifrost prunes any entry the key does not allow.
Bifrost checks the allowlist again when the tool executes, and rejects inactive or expired keys with a 403. The full semantics are in the MCP tool filtering for virtual keys and tool filtering pages.
For teams that would rather publish a curated bundle than configure each key by hand, Bifrost provides Virtual MCPs: a named set of tools drawn from one or more servers, served at its own /mcp/<slug> endpoint, and reachable only through the virtual keys attached to it. On Bifrost Enterprise, access profiles grant Virtual MCPs to roles synced from an identity provider, so a new hire inherits the right tool set without anyone touching a key.
Allowlists decide whether a tool may be called; MCP guardrails decide whether a specific call, with specific arguments, may proceed. Bifrost Enterprise guardrail rules can target the MCP execution boundary directly, matching on the MCP client, the tool name, and top-level argument values, and can inspect or redact arguments before execution and results after it. A rule that blocks send_message when the channel argument is external, or redacts secrets from a read_file result before the model sees it, runs inside the gateway rather than in each application.
The governance resource page shows how these MCP controls sit alongside budgets and rate limits on the same virtual keys, and the broader set of MCP server governance tools fits around this core.
Auditing MCP Tool Calls with Bifrost Logs
Bifrost records MCP tool calls in its request logs, which capture the tool name, arguments, result, virtual key, and any request headers configured for capture; a separate audit log records administrative activity such as who changed a key's allowlist. The two serve different questions, and both are needed for a complete answer to "what did this agent do and who let it".
The request logging layer writes a log entry for every LLM request and every MCP tool execution that passes through Bifrost. Headers prefixed x-bf-lh- are captured automatically into the entry's metadata, so an application can tag each call with a tenant, environment, or correlation ID and search on it later. Bifrost Enterprise log exports offload request and response payloads to S3 or GCS while keeping searchable metadata in the database, which keeps retention affordable at high tool-call volumes.
The audit log is scoped to operator actions: create, update, delete, authenticate, authorize, export, and import events, each with the initiator, the target resource, and the outcome. Entries can be signed with an HMAC key, retained for a configurable number of days, exported as JSON, JSON Lines, or RFC 5424 syslog for a SIEM, and archived to S3 or GCS for long-term compliance retention. When a reviewer asks why a virtual key could suddenly call push_files, the audit log shows the change and the request log shows every call that followed. The role of MCP audit logs in enterprise compliance is covered in a companion post.
Frequently Asked Questions
What are MCP tools?
MCP tools are executable functions that an MCP server advertises to AI clients through the Model Context Protocol. Each tool has a name, a description, and a JSON Schema describing its inputs. The model requests a tool, the client application approves and sends a tools/call request, and the server runs the function and returns the result. Tools are the MCP primitive designed for actions with side effects, as opposed to resources, which supply read-only context.
Which tools support MCP?
MCP is supported by most current AI clients, including Claude Desktop, Claude Code, Cursor, Visual Studio Code, and the OpenAI Agents SDK, and on the server side by GitHub, Atlassian, Slack, Notion, Figma, Sentry, PostgreSQL, and Playwright, among many others. Bifrost supports MCP in both directions: it connects to any MCP server as a client and exposes the aggregated tools to any MCP client through its MCP server endpoint.
What are some popular MCP tools?
The most widely deployed MCP tools are source-control operations from the GitHub server (create_pull_request, search_code), filesystem operations (read_file, write_file), database queries from the PostgreSQL and SQLite servers, browser automation from Playwright, and collaboration actions from the Slack, Jira, and Linear servers. Teams that route these through Bifrost can connect coding agents such as Claude Code to all of them through one configured endpoint.
Can I use MCP with ChatGPT?
Yes. OpenAI supports MCP through its Agents SDK and Responses API, where a remote MCP server can be attached as a tool source, and ChatGPT supports MCP-based connectors for custom integrations. Because Bifrost exposes an OpenAI-compatible API and an MCP server endpoint, an OpenAI-based agent can call MCP tools through Bifrost with the same per-key allowlists that apply to any other client.
How does an MCP gateway control tool access?
An MCP gateway sits between agents and MCP servers, connects to each server once, and decides per caller which tools to expose and execute. In Bifrost, each virtual key carries an allowlist of MCP clients and tools; a request through that key sees only the permitted tools in tools/list, and any attempt to execute a tool outside the list is rejected. Curated tool bundles served at their own MCP endpoint make one allowlist reusable across keys.
How do MCP tools authenticate to upstream services?
MCP tools authenticate however the server behind them requires, and a gateway manages those credentials centrally. Bifrost supports six MCP authentication modes: none, static headers, OAuth 2.0, per-user OAuth, per-user headers, and token exchange. Per-user modes ensure a tool call runs with the calling user's own identity at the upstream service rather than a shared service account, which is what most compliance reviews ask for.
Does Bifrost execute MCP tool calls automatically?
Not by default. A chat completion through Bifrost returns the model's tool calls without executing them, and the application submits approved calls to the execution API. Agent Mode enables automatic execution, but only for tools explicitly listed as auto-executable, and it applies to non-streaming requests only. Everything else is returned to the application for approval.
Getting Started with Governed MCP Tools
MCP tools give models the ability to act, and the protocol gives every client and server a shared vocabulary for discovery, invocation, and errors. What it does not give an organization is a single point that knows which team may call which tool, records each call, and can block a dangerous argument before it executes. Bifrost provides that point with per-virtual-key allowlists, Virtual MCPs, MCP-targeted guardrails, request logs, and signed audit logs, at 11 microseconds of gateway overhead per request at 5,000 RPS.
To see how Bifrost governs MCP tools for your agents and coding assistants, book a demo with the Bifrost team, or explore the Bifrost resources hub.