Ruby and Rails glossary

MCP vs API

A REST API is a set of HTTP endpoints that a program calls because a developer wrote code to call them. MCP (Model Context Protocol) is an open protocol that lets an AI application discover a server's tools at runtime and call them for the person using it.

A REST API is a set of HTTP endpoints, each a URL plus a verb, that a program calls because a developer wrote code to call it. MCP (Model Context Protocol) is an open protocol that lets an AI application such as Claude, Cursor or ChatGPT connect to a server, ask it which tools it offers, and call those tools while helping a person. Both can reach the same data in the same app. The difference is who is on the other end: a REST API is read by a developer at build time, an MCP server is read by a model at run time.

MCP does not replace REST. You need it when the caller is an AI assistant that has to work out which call to make from a plain-language request, with no one writing integration code first. In most apps the MCP server sits next to the API and calls the same code underneath.

The same task, two shapes

Take one task: list an account's recent orders, optionally filtered by status.

As a REST endpoint in Rails, it is a route and a controller action.

# config/routes.rb
namespace :api do
  namespace :v1 do
    resources :orders, only: [:index]
  end
end
# app/controllers/api/v1/orders_controller.rb
class Api::V1::OrdersController < ApplicationController
  before_action :authenticate_api_token! # your app's own check

  def index
    orders = current_account.orders.order(created_at: :desc).limit(50)
    orders = orders.where(status: params[:status]) if params[:status].present?

    render json: orders.as_json(only: [:id, :number, :status, :total_cents, :created_at])
  end
end

A developer reads your docs, learns that status exists and what values it takes, and writes the call.

curl "https://app.example.com/api/v1/orders?status=refunded" \
  -H "Authorization: Bearer $API_TOKEN"

As an MCP tool, the same task is described in JSON. The client fetches this description by sending a tools/list request, and the model reads it to decide when to call the tool and with what arguments.

{
  "name": "list_orders",
  "title": "List orders",
  "description": "List the 50 most recent orders for the signed-in account, newest first. Use status to narrow the list, for example to find refunded orders.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "status": {
        "type": "string",
        "enum": ["pending", "paid", "shipped", "refunded"],
        "description": "Only return orders in this status"
      }
    },
    "additionalProperties": false
  }
}

When someone asks their assistant "which orders were refunded this week?", the client sends a JSON-RPC request to the server's single endpoint. This is the shape from the spec, with the _meta block left out, as the spec's own examples do.

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "list_orders",
    "arguments": { "status": "refunded" }
  }
}

Nobody wrote code for that call. The model chose the tool and filled in the argument from the description.

The differences that matter

These points are based on MCP specification revision 2026-07-28, the current revision (checked in November 2026).

  • Who the consumer is. A REST API is consumed by code. MCP is consumed by a host application that puts the tool list in front of a model. The spec calls tools "model-controlled" and says a human should always be able to deny a tool call.
  • Discovery. With REST, discovery happens before any request: a person reads the docs or an OpenAPI file. With MCP the client sends tools/list at run time. The spec lets that list vary by the authorization on the request, so a read-only caller can be shown only read tools.
  • How operations are described. REST docs live outside the API. An MCP tool carries its own description and JSON Schema inputSchema, optionally an outputSchema. The description is part of the interface: a vague one gets the wrong tool picked.
  • Errors. REST returns status codes for a program to branch on. MCP returns tool failures as a normal result with isError: true and text the model can read, so it can fix its arguments and retry.
  • Transport. MCP defines two standard transports: stdio, for a server the client starts as a local subprocess, and Streamable HTTP, where every message is a POST to one endpoint and the reply is JSON or a short SSE stream.
  • Auth. Your REST API uses whatever scheme you chose. MCP authorization is optional, but an HTTP server that has it acts as an OAuth 2.1 resource server, publishes Protected Resource Metadata so the client can find the authorization server, and accepts only tokens issued for its own address. A stdio server reads credentials from the environment. In practice a person pastes a server URL into their client and signs in, with no token in a config file.
  • State. REST requests are meant to stand alone. MCP revisions up to 2025-11-25 opened a session with an initialize handshake. Revision 2026-07-28 removed it: each request carries its own protocol version and client capabilities, and there is no protocol-level session. A tool that needs state across calls returns an ID and takes it back as an argument, as a REST API would.

On the current revision, then, an MCP server is a stateless HTTP endpoint with bearer tokens, which a Rails team already knows how to run.

Is MCP just a wrapper around an API?

Often, in its plumbing. Many MCP servers call an existing API or the same service objects its controllers use. The work is in the layer on top: which operations to expose, how to name and describe them, and what each caller may do. Wrapping every endpoint one to one hands a model a long list of similar tools. A few tools shaped around tasks ("search orders", "issue refund") usually work better than a mirror of your routes.

Permissions work as for any API, with one difference: the caller acts on what it reads, and text inside a record can steer it. Give each connection the narrowest access the task needs. Least privilege for AI agents covers how to set that up.

When a REST API is enough

  • The caller is a program you or a partner write: a mobile app, a front end, a sync job, a webhook consumer.
  • The calls are known in advance and do not change with each request.
  • A developer will read the docs and handle errors in code.
  • The AI caller is a coding agent you run yourself. With a terminal, it can call curl against a documented API under the same auth as any client.

When an MCP server earns its place

  • People outside engineering (support, ops, finance) want to ask their assistant about your data in plain words and get answers from real records.
  • You want several AI clients to connect without writing an integration for each one. One server works with any client that speaks the protocol.
  • You want each connection tied to a person, approved through a sign-in screen, and revocable, rather than a shared API key.

If none of these apply, ship the API and add MCP later.

Running both on the same rules

The risk with two surfaces is two permission systems that drift apart. Teams on Avo can serve both from the resources they already defined. The API add-on turns each Avo resource into REST endpoints under /api/resources/v1/<resource>, and the MCP add-on serves those resources and your Avo actions as ten tools over HTTPS with OAuth. With the Authorization add-on, each request on either surface runs through the same Pundit policies as your Avo app, so a role that cannot see a record in the UI cannot read it over the API or MCP either. For the setup steps and how it compares with a hand-rolled server, see Add an MCP server to your Rails app.

Frequently asked questions

What is the difference between MCP and an API?

A REST API is a set of HTTP endpoints that code calls because a developer wrote that code from the docs. MCP is a protocol for AI applications: the client asks the server which tools it has, each with a description and a JSON Schema, and the model picks one from a person's request.

Does MCP replace REST APIs?

No. Mobile apps, front ends, partner integrations and background jobs still call REST APIs. MCP adds a second way in for AI assistants, and in most apps the MCP server calls the same code the API does.

When is a REST API enough without an MCP server?

When every caller is a program someone writes against your docs, including scripts and coding agents you run yourself. Add an MCP server when people want to reach your data from an AI assistant without anyone writing an integration, or when each connection needs its own approval and revoke.

Is MCP stateful?

Not in the current specification. Revision 2026-07-28 removed the session and initialize handshake that earlier revisions used, so every request carries its own protocol version and capabilities. A tool that needs state across calls returns an ID and takes it back as an argument.

Try Avo for free