60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
86 lines
2.0 KiB
Python
86 lines
2.0 KiB
Python
"""Example: Search transforms with BM25 relevance ranking.
|
|
|
|
BM25SearchTransform uses term-frequency/inverse-document-frequency scoring
|
|
to rank tools by relevance to a natural language query. Unlike regex search
|
|
(which requires the user to construct a pattern), BM25 handles queries like
|
|
"work with text" or "do math" and returns the most relevant matches.
|
|
|
|
The index is built lazily and rebuilt automatically when the tool catalog
|
|
changes (e.g. tools added or removed between requests).
|
|
|
|
Run with:
|
|
uv run python examples/search/server_bm25.py
|
|
"""
|
|
|
|
import os
|
|
|
|
from fastmcp import FastMCP
|
|
from fastmcp.server.transforms.search import BM25SearchTransform
|
|
|
|
mcp = FastMCP("BM25 Search Demo")
|
|
|
|
|
|
@mcp.tool
|
|
def add(a: int, b: int) -> int:
|
|
"""Add two numbers together."""
|
|
return a + b
|
|
|
|
|
|
@mcp.tool
|
|
def multiply(x: float, y: float) -> float:
|
|
"""Multiply two numbers."""
|
|
return x * y
|
|
|
|
|
|
@mcp.tool
|
|
def fibonacci(n: int) -> list[int]:
|
|
"""Generate the first n Fibonacci numbers."""
|
|
if n <= 0:
|
|
return []
|
|
seq = [0, 1]
|
|
while len(seq) < n:
|
|
seq.append(seq[-1] + seq[-2])
|
|
return seq[:n]
|
|
|
|
|
|
@mcp.tool
|
|
def reverse_string(text: str) -> str:
|
|
"""Reverse a string."""
|
|
return text[::-1]
|
|
|
|
|
|
@mcp.tool
|
|
def word_count(text: str) -> int:
|
|
"""Count the number of words in a text."""
|
|
return len(text.split())
|
|
|
|
|
|
@mcp.tool
|
|
def to_uppercase(text: str) -> str:
|
|
"""Convert text to uppercase."""
|
|
return text.upper()
|
|
|
|
|
|
@mcp.tool
|
|
def list_files(directory: str) -> list[str]:
|
|
"""List files in a directory."""
|
|
return os.listdir(directory)
|
|
|
|
|
|
@mcp.tool
|
|
def read_file(path: str) -> str:
|
|
"""Read the contents of a file."""
|
|
with open(path) as f:
|
|
return f.read()
|
|
|
|
|
|
# BM25 search with a higher result limit for this larger catalog.
|
|
# The `always_visible` option keeps specific tools in list_tools output
|
|
# alongside the search/call tools — useful for tools the LLM should
|
|
# always know about.
|
|
mcp.add_transform(BM25SearchTransform(max_results=5, always_visible=["list_files"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mcp.run()
|