MCP Streamable HTTP Server
The MCP server is exposed via the /_plugins/_ml/mcp endpoint and implements the Streamable HTTP transport defined by the Model Context Protocol (MCP). It allows agents or clients to connect to Lucenia and discover or invoke available tools.
This server does not open a persistent SSE connection with the client; all communication happens over stateless HTTP calls. If a client sends a GET request (typically, to establish an SSE connection), the server returns a 405 Method Not Allowed response.
Prerequisites
Before connecting to the MCP server, enable the MCP server functionality in your cluster:
PUT /_cluster/settings
{
"persistent": {
"plugins.ml_commons.mcp_server_enabled": "true"
}
}
You can also optionally register custom tools using the Register MCP Tools API.
Endpoint
POST /_plugins/_ml/mcp
Request format
The MCP server uses JSON-RPC 2.0 for communication. All requests should be sent as POST requests with a JSON body:
{
"jsonrpc": "2.0",
"id": "string|number",
"method": "string",
"params": {}
}
Request fields
| Field | Type | Description | Required |
|---|---|---|---|
jsonrpc | String | JSON-RPC version (must be "2.0") | Yes |
id | String/Number | Unique identifier for the request | Yes |
method | String | Method to invoke on the MCP server | Yes |
params | Object | Parameters for the method call | No |
Supported methods
tools/list
List all available tools on the MCP server.
curl -X POST "https://localhost:9200/_plugins/_ml/mcp" \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'username:password' | base64)" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Example response
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "ListIndexTool",
"description": "Lists indices in the cluster",
"inputSchema": {
"type": "object",
"properties": {
"indices": {
"type": "array",
"description": "List of index names to filter"
}
}
}
},
{
"name": "SearchIndexTool",
"description": "Searches documents in an index",
"inputSchema": {
"type": "object",
"properties": {
"index": {
"type": "string",
"description": "Index name to search"
},
"query": {
"type": "object",
"description": "Search query"
}
},
"required": ["index"]
}
}
]
}
}
tools/call
Execute a specific tool with provided parameters.
curl -X POST "https://localhost:9200/_plugins/_ml/mcp" \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'username:password' | base64)" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "ListIndexTool",
"arguments": {
"indices": []
}
}
}'
Example response
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "health status index uuid pri rep docs.count docs.deleted store.size pri.store.size\nyellow open my-index abc123def456 1 1 5 0 10.2kb 10.2kb"
}
]
}
}
initialize
Initialize the MCP connection and get server capabilities.
curl -X POST "https://localhost:9200/_plugins/_ml/mcp" \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'username:password' | base64)" \
-d '{
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}'
Example response
{
"jsonrpc": "2.0",
"id": 0,
"result": {
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "Lucenia MCP Server",
"version": "0.8.0"
},
"capabilities": {
"tools": {}
}
}
}
Built-in tools
The MCP server provides several built-in tools that are available without registration:
Zero-configuration tools
These tools require no additional parameters during registration:
| Tool Name | Description |
|---|---|
ListIndexTool | Lists indices in the cluster |
CatIndexTool | Returns detailed index information |
SearchIndexTool | Searches documents in an index |
GetMappingsTool | Retrieves index mappings |
GetSettingsTool | Retrieves index settings |
Parameterized tools
These tools require parameters to be provided during registration:
| Tool Name | Description | Required Parameters |
|---|---|---|
VectorSearchTool | Performs vector similarity search | model_id, embedding_field |
RAGTool | Retrieval-augmented generation | model_id, index |
Client examples
Python with fastmcp
You can connect to the MCP server using any client that supports the Streamable HTTP transport. The following example uses the fastmcp library:
import asyncio
from fastmcp import Client
async def main():
async with Client("http://localhost:9200/_plugins/_ml/mcp") as client:
# List available tools
tools = await client.list_tools()
for tool in tools:
print(f"Tool: {tool.name}")
# Call a tool
result = await client.call_tool("ListIndexTool", {"indices": []})
print("Result:", result)
asyncio.run(main())
Python with httpx
import httpx
import json
def call_mcp(method: str, params: dict = None):
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": method
}
if params:
payload["params"] = params
response = httpx.post(
"http://localhost:9200/_plugins/_ml/mcp",
json=payload,
auth=("username", "password"),
headers={"Content-Type": "application/json"}
)
return response.json()
# List tools
tools = call_mcp("tools/list")
print("Available tools:", tools)
# Call a tool
result = call_mcp("tools/call", {
"name": "ListIndexTool",
"arguments": {"indices": []}
})
print("Result:", result)
JavaScript/Node.js
async function callMCP(method, params = {}) {
const response = await fetch('http://localhost:9200/_plugins/_ml/mcp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa('username:password')
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: method,
params: params
})
});
return response.json();
}
// List tools
const tools = await callMCP('tools/list');
console.log('Available tools:', tools);
// Call a tool
const result = await callMCP('tools/call', {
name: 'ListIndexTool',
arguments: { indices: [] }
});
console.log('Result:', result);
JSON-RPC error codes
The MCP server uses standard JSON-RPC 2.0 error codes:
| Code | Message | Description |
|---|---|---|
-32700 | Parse error | Invalid JSON in request |
-32600 | Invalid Request | Request is not a valid JSON-RPC object |
-32601 | Method not found | Requested method does not exist |
-32602 | Invalid params | Invalid method parameters |
-32603 | Internal error | Server internal error |
Custom error codes
| Code | Message | Description |
|---|---|---|
-32000 | Tool not found | Requested tool does not exist |
-32001 | Tool execution failed | Tool execution encountered an error |
-32002 | Authentication required | Request requires authentication |
Best practices
- Use unique request IDs: Use descriptive, unique request IDs for easier debugging and correlation
- Handle errors gracefully: Implement comprehensive error handling for all JSON-RPC error codes
- Initialize first: Call the
initializemethod before using other methods to ensure compatibility - Check tool availability: Use
tools/listto verify tools are available before calling them - Provide required arguments: Ensure all required arguments are provided when calling tools