Skip to main content

MCP Integration

Model Context Protocol (MCP) is an open standard for exposing tools to AI clients. Mellea integrates with MCP via FastMCP: wrap any Mellea function as an MCP tool and call it from Claude Desktop, Cursor, or any MCP-compatible client.

Looking to call tools from an MCP server? See MCP tools in Tools and Agents.

Prerequisites: pip install mellea, pip install "mcp[cli]", Ollama running locally.

Creating an MCP server

Decorate any function with @mcp.tool(). The docstring becomes the tool description visible to the AI client.

# Requires: mcp[cli], mellea[ollama]
# Returns: str
from mcp.server.fastmcp import FastMCP
from mellea import MelleaSession
from mellea.backends import ModelOption, model_ids
from mellea.backends.ollama import OllamaModelBackend
from mellea.core import Requirement
from mellea.stdlib.requirements import simple_validate
from mellea.stdlib.sampling import RejectionSamplingStrategy

mcp = FastMCP("mellea-demo")

@mcp.tool()
def write_a_poem(word_limit: int) -> str:
"""Write a poem with a specified word limit."""
m = MelleaSession(
OllamaModelBackend(
model_ids.IBM_GRANITE_4_HYBRID_MICRO,
model_options={ModelOption.MAX_NEW_TOKENS: word_limit + 10},
)
)
word_limit_req = Requirement(
f"Use only {word_limit} words.",
validation_fn=simple_validate(lambda x: len(x.split()) < word_limit),
)
result = m.instruct(
"Write a poem.",
requirements=[word_limit_req],
strategy=RejectionSamplingStrategy(loop_budget=2),
)
return str(result.value)

@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting."""
return f"Hello, {name}!"

Each @mcp.tool() function becomes a callable tool. Mellea's requirements and sampling strategies work exactly as they do in regular code — the MCP layer just wraps the result.

Multiple tools in one server

A single FastMCP server can expose multiple tools, resources, and prompts:

# Requires: mcp[cli], mellea[ollama]
# Returns: str
from mcp.server.fastmcp import FastMCP
from mellea import MelleaSession, generative, start_session
from mellea.backends.ollama import OllamaModelBackend
from typing import Literal

mcp = FastMCP("mellea-tools")

@mcp.tool()
def summarize(text: str, max_words: int = 100) -> str:
"""Summarize the provided text."""
m = MelleaSession(OllamaModelBackend())
result = m.instruct(
"Summarize the following text in {{max_words}} words or fewer: {{text}}",
user_variables={"text": text, "max_words": str(max_words)},
)
return str(result)

@mcp.tool()
def classify_sentiment(text: str) -> str:
"""Classify the sentiment of the text as positive, negative, or neutral."""
@generative
def _classify(text: str) -> Literal["positive", "negative", "neutral"]:
"""Classify sentiment."""
...

m = start_session()
return _classify(m, text=text)

Note: Each tool invocation creates a new MelleaSession. For high-throughput servers, consider initializing sessions at module level and reusing them across calls.

Running the server

Start the MCP dev UI to test interactively:

uv run mcp dev your_server.py

This opens a browser-based inspector at http://localhost:5173 where you can call tools, inspect arguments, and see outputs.

To run the server directly:

uv run your_server.py

Full example: docs/examples/notebooks/mcp_example.ipynb


See also: Backends and Configuration