Skip to main content

Model Context Protocol

·7 mins

In the last couple of years AI models have seen remarkable advances in their capabilities, yet they face a fundamental challenge: connecting effectively with external data and systems. While these models excel at processing information within their training, their ability to interact with real-world data and systems remains limited. This limitation affects everything from accessing up-to-date information to integrating with enterprise systems.

Two key approaches have emerged to address this challenge: Retrieval-Augmented Generation (RAG) enables models to incorporate external documents and data into their responses, while function calling (’tools’) allows models to interact with external systems through defined interfaces. However, implementing these approaches often requires significant custom development work, making it challenging to maintain and scale these integrations across different applications and AI models.

Frameworks like LangChain4j and Spring AI have made significant strides in simplifying these integrations. They provide powerful abstractions for working with AI models and offer built-in capabilities for data integration through document loaders, retrievers, and other components. Yet organisations still face challenges when implementing these solutions at scale, particularly in enterprise environments with diverse data sources and complex system requirements. What’s really needed is a standardised way to connect AI models with external systems and data sources.

Enter Model Context Protocol (MCP) by Anthropic, the company behind the Claude AI model. MCP proposes a universal standard for connecting AI systems with the data and functionality they need in real-world applications.

Architecture #

MCP defines a client-server architecture and a protocol for communication between them.

  • Host - LLM applications like Claude for Desktop or an IDE like IntelliJ IDEA where AI-driven tasks need to interact with external data and systems — for example, a weather API or a database schema.
  • Client - MCP implementation inside a host that handles 1:1 communication with an MCP server
  • Server - MCP implementation inside an application that exposes resources, prompts, and Tools to clients.
flowchart LR subgraph "Your Computer" Host["**Host** with MCP **Client**"] S1["MCP **Server** A"] S2["MCP **Server** B"] S3["MCP **Server** C"] Host <-->|"MCP"| S1 Host <-->|"MCP"| S2 Host <-->|"MCP"| S3 S1 <--> D1[("Data Source A")] S2 <--> D2[("Data Source B")] end subgraph "Internet" S3 <-->|"Web APIs"| D3[("Remote Service C")] end

The MCP spec defines a set of JSON-RPC 2.0 message primitives for clients and servers to communicate.

Concepts #

Resources #

Resources represent any kind of data that an MCP server might want to expose to clients to use as context by LLMs. Examples include file contents, database records, API responses, screenshot and images, log files. Binary data is encoded as Base64 strings.

Clients discover available resources through the resources/list endpoint, and read them by making a resources/read request.

Interestingly, servers can also notify clients when their list of available resources changes, and clients can subscribe to receive updates when specific resources change.

Prompts #

Prompts are reusable templates that clients can easily surface to users and LLMs with the intention of the user being able to explicitly select them for use. They provide a way to standardise and share common LLM interactions.

They can:

  • Accept dynamic arguments
  • Include context from resources
  • Chain multiple interactions
  • Guide specific workflows

Clients discover available prompts through the prompts/list endpoint, and use them by making a prompts/get request.

Tools #

Tools are a way for servers to expose functionality to that clients can call as needed. Tools can, for example, be used to wrap existing APIs (e.g. a weather service) or transform or analyse data.

Clients discover available tools through the tools/list endpoint, and use them by making a tools/call request.

Sampling #

Sampling provides a mechanism for servers to send LLM completion requests through the client. This enables more advanced agentic behavior - for example, a Git server might need to generate commit messages by asking the LLM to analyse code changes, or a documentation server might want to summarise API changes by having the LLM process modified endpoints. Rather than maintaining their own LLM connections, servers can leverage the client’s existing LLM integration through a standardised sampling interface. This keeps the architecture clean while enabling servers to build more sophisticated AI-powered features.

Roots #

Roots allow clients to limit the scope of what a server should focus on when carrying out operations on their behalf. For example, in an IDE context, a root might be the current project directory or a specific subdirectory. This helps ensure that servers only operate on relevant data and respect access boundaries.

Developing with MCP #

At the moment there are three official SDKs: one for TypeScript, one for Python, and one for Kotlin. In addition, there are a bunch of other unofficial SDKs (Go, Rust).

These SDKs really accelerate client and server development. Here’s an example server written in Kotlin that serves a single resource.

import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransport
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities

val server = Server(
    serverInfo = Implementation(
        name = "example-server",
        version = "1.0.0"
    ),
    options = ServerOptions(
        capabilities = ServerCapabilities(
            resources = ServerCapabilities.Resources(
                subscribe = true,
                listChanged = true
            )
        )
    )
)

// Add a resource
server.addResource(
    uri = "file:///example.txt",
    name = "Example Resource",
    description = "An example text file",
    mimeType = "text/plain"
) { request ->
    ReadResourceResult(
        contents = listOf(
            TextResourceContents(
                text = "This is the content of the example resource.",
                uri = request.uri,
                mimeType = "text/plain"
            )
        )
    )
}

// Start server with stdio transport
val transport = StdioServerTransport()
server.connect(transport)

Anthropic also provides some developer tools to aid debugging:

  • MCP Inspector - an interactive debugging interface to interact with MCP server APIs
  • Claude Desktop Developer Tools - communicate with MCP servers from Claude Desktop, and view message payloads and logs via Chrome DevTools integration

Looking ahead #

Imagine an AI-powered coding assistant in an IDE that needs to understand your project’s database schema, read configuration files, and interact with your version control system. With MCP, the IDE (acting as a host) could connect to multiple MCP servers: one exposing the database schema as a resource, another providing Git operations as tools, and a third serving configuration files. The AI assistant could then seamlessly access this information and functionality through standardised interfaces, without needing custom integration code for each data source or system. This standardisation makes it easier for developers to add new capabilities to their AI-powered tools while maintaining clean architectural boundaries.

Model Context Protocol represents a postive step in standardising how AI models interact with external systems and data. By providing a common framework for these interactions, MCP reduces development complexity and enables more sophisticated AI applications.

It’s important to note that MCP is still in its early stages, and there are still some challenges to overcome, the biggest of which is that MCP is only supported locally, meaning servers must run on the same machine as the client. In addition, Claude Desktop requests permission to use MCP every time you want to use it. Also, the spec is, in places vague, but it’s a work in progress and a good starting point.

As the AI landscape continues to evolve, standards like MCP will become increasingly important for building scalable, maintainable AI systems. Organisations looking to integrate AI capabilities across their applications should definitely consider MCP playing a part.

While MCP is still emerging, several teams are already putting it to use. IntelliJ IDEA’s AI Assistant is one of the first major implementations, using MCP to give their AI features access to project structure, code context, and IDE functionality. The Docker MCP servers project has seen contributions from developers building servers for various use cases, from database schema exploration to API integration. In the open source community, projects like the OpenAPI MCP Server are extending MCP’s capabilities into new domains.

These early implementations demonstrate MCP’s potential, though widespread adoption will likely depend on how the protocol evolves to address current limitations like local-only support. As more organisations look to standardise their AI integrations, MCP’s adoption trajectory through 2025 will be worth watching.