MCP Protocol Overview
This page provides an overview of the Model Context Protocol (MCP) and how it works.
What is MCP?
The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide knowledge and capabilities (context) to Large Language Models (LLMs). Created by Anthropic, MCP enables AI assistants like Claude to connect to external data sources and tools in standardized way.
The Problem MCP Solves
Before MCP, integrating external data and tools with LLMs faced several challenges:
-
Each data source required integration code (HTTP client, database connector, etc.)
-
LLMs were often confined to information available at training time
-
No standard way for tools, databases, and services to expose their capabilities to AI
MCP addresses these issues by providing a universal, open protocol for context exchange.
Protocol Specification
quarkus-mcp-server implements the 2025-11-25 version of the MCP specification.
The specification defines:
-
How messages are formatted using a JSON-RPC 2.0-based communication
-
How messages are transmitted using various transport such as STDIO and HTTP (with SSE and Streamable variants)
-
How the client and server negotiate capabilities during connection initialization and how this connection is managed throughout its lifecycle
-
The main primitives: Tools, Resources, and Prompts
-
More advanced features such as: Sampling, Elicitation, and Roots
See the official MCP specification for complete technical details.
Compliance and Testing
The absence of an official "Compliance Test Suite" (similar to Java’s TCK) makes it challenging to verify full specification compliance.
The quarkus-mcp-server implementation is tested against real MCP clients and aims for maximum compatibility.
If you encounter any issues or discrepancies with the specification, please open an issue on https://github.com/quarkiverse/quarkus-mcp-server/issues.
|
Known Limitations
The following MCP features are not currently supported:
-
Streamable HTTP - Resumability and Redelivery (optional feature)
-
Tasks (experimental feature)
If you encounter a problem or discrepancy, please file an issue.
JSON-RPC Layer
MCP uses JSON-RPC 2.0 as its message format, providing a lightweight and language-agnostic communication layer.
Message Types
MCP defines three types of JSON-RPC messages:
- Requests
-
Messages that expect a response from the receiver. Each request has a unique
idthat the response must reference.{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} } - Responses
-
Messages sent in reply to requests, containing either a
resultor anerror.{ "jsonrpc": "2.0", "id": 1, "result": { "tools": [...] } } - Notifications
-
One-way messages that do not expect a response. No
idfield is present.{ "jsonrpc": "2.0", "method": "notifications/progress", "params": { "progressToken": "abc123", "progress": 50, "total": 100 } }
Bidirectional Communication
Unlike traditional REST APIs, MCP is bidirectional:
-
Client-to-Server Requests: Clients invoke server capabilities (e.g., calling tools, reading resources)
-
Server-to-Client Requests: Servers can request services from clients (e.g., LLM sampling, user input via elicitation)
-
Both Directions for Notifications: Progress updates, log messages, and lifecycle events flow in both directions
Capability Negotiation
MCP uses capability negotiation to establish what features are available between client and server.
Initialization Sequence
-
Client sends
initializerequest:{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "{spec-version}", "clientInfo": { "name": "my-mcp-client", "version": "1.0.0" }, "capabilities": { "sampling": {}, "elicitation": {}, "roots": { "listChanged": true } } } } -
Server responds with its capabilities:
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "{spec-version}", "serverInfo": { "name": "quarkus-mcp-server", "version": "1.0.0" }, "capabilities": { "tools": {}, "resources": { "subscribe": true }, "prompts": {}, "logging": {} } } } -
Client sends
initializednotification:{ "jsonrpc": "2.0", "method": "notifications/initialized" }
Capability Checking
After initialization, both parties know what features are available:
-
Client capabilities (what the server can request from the client):
-
sampling: Allows invoking the client-side LLM from the server side -
elicitation: User input collection (e.g., forms, confirmations) -
roots: Access to client’s root directories/contexts
-
-
Server capabilities (what the client can request from the server):
-
tools: Executable functions -
resources: Readable/subscribable data -
prompts: Reusable prompt templates -
logging: Server-to-client log messages
-
The Quarkus MCP server automatically includes capabilities in the initialization response based on what features you’ve implemented (tools, resources, prompts) in your application.
Connection Lifecycle
Understanding the MCP connection lifecycle helps you manage server state and resources effectively.
Lifecycle States
┌─────────────┐
│ Created │ Server process starts
└──────┬──────┘
│
│ Client sends 'initialize'
↓
┌─────────────┐
│ Initialized │ Capabilities negotiated
└──────┬──────┘
│
│ Client sends 'initialized' notification
↓
┌─────────────┐
│ Ready │ Normal operation (tools/call, resources/read, etc.)
└──────┬──────┘
│
│ Connection closed or client sends 'shutdown'
↓
┌─────────────┐
│ Shutdown │ Server cleans up and exits
└─────────────┘
| The exact sequence is not strictly enforced by the protocol, but this is the typical flow for most clients and servers. |
Connection Management
- STDIO Transport
-
-
Connection lifecycle tied to process lifecycle
-
Server exits when STDIN closes
-
No explicit shutdown request needed
-
- HTTP Transports
-
-
Connections are session-based
-
Each session maintains separate state
-
Explicit
shutdownrequest recommended for clean termination -
SSE connections require keep-alive mechanism
-
- WebSocket Transport (custom transport)
-
-
Bidirectional, persistent connection
-
WebSocket close frame triggers shutdown
-
Supports reconnection with new initialization
-
Handling Initialization Events
The Quarkus MCP server provides annotations to hook into lifecycle events:
import io.quarkiverse.mcp.server.Notification;
import io.quarkiverse.mcp.server.Notification.Type;
@Notification(Type.INITIALIZED)
void onInitialized(McpConnection connection) {
// Called when client is ready
// Initialize per-connection state here
}
This allows you to perform setup tasks (e.g., loading user-specific data) after capability negotiation completes.
Core Primitives
MCP defines three primary primitives for exposing functionality to clients.
Tools
Tools are executable functions that the LLM can invoke to perform actions or retrieve computed information.
-
Defined with JSON Schema for input validation
-
Return structured or unstructured results
-
Support both synchronous and asynchronous execution
-
Can report progress and handle cancellation
Example use cases: Database queries, API calls, code execution, file operations
See: Tools Specification
Resources
Resources are data sources that clients can read and optionally subscribe to for updates.
-
Identified by URI (e.g.,
file:///path/to/file,database://table/row) -
Support static URIs and URI templates with variables
-
Can be text or binary content
-
Clients can subscribe to receive update notifications
Example use cases: File contents, database records, API responses, configuration data
Prompts
Prompts are reusable templates for LLM interactions, parameterized with arguments.
-
Define conversation starters or task templates
-
Support multiple message roles (system, user, assistant)
-
Can include embedded resources
-
Completion API for argument suggestions
Example use cases: Code review templates, analysis frameworks, guided workflows
Message Flow Examples
Tool Call Flow
Client Server
│ │
│ 1. initialize │
├─────────────────────────────────────────>│
│ │
│ 2. initialize response (capabilities) │
│<─────────────────────────────────────────┤
│ │
│ 3. initialized notification │
├─────────────────────────────────────────>│
│ │
│ 4. tools/list │
├─────────────────────────────────────────>│
│ │
│ 5. tools/list response │
│<─────────────────────────────────────────┤
│ │
│ 6. tools/call (name: "search") │
├─────────────────────────────────────────>│
│ │ [Tool executes]
│ 7. notifications/progress (optional) │
│<─────────────────────────────────────────┤
│ │
│ 8. tools/call response (result) │
│<─────────────────────────────────────────┤
│ │
Server-to-Client Request (Sampling)
Client Server
│ │
│ tools/call (name: "analyze") │
├─────────────────────────────────────────>│
│ │ [Tool starts]
│ │ [Needs LLM help]
│ sampling/createMessage │
│<─────────────────────────────────────────┤
│ │
│ [Client asks LLM] │
│ │
│ sampling/createMessage response │
├─────────────────────────────────────────>│
│ │ [Tool continues]
│ tools/call response (result) │
│<─────────────────────────────────────────┤
│ │
See Also
-
Architecture - Quarkus MCP Server architecture
-
Transports - Available transport mechanisms