{count, plural, one {Corso} other {Corsi}}
Nel mondo dell’AI, il Model Context Protocol (MCP) è rapidamente diventato un tema caldo. MCP è uno standard aperto che offre a modelli come Claude 4 un modo coerente per connettersi a strumenti esterni, servizi e fonti di dati in tempo reale. Questa connettività cambia le regole del gioco perché consente ai large language model (LLM) di fornire risposte più pertinenti, aggiornate e azionabili, colmando il divario tra l’AI e i sistemi.
In questo tutorial esploreremo FastMCP 2.0, un potente framework che semplifica la creazione di un server MCP con poche righe di codice. Vedremo i componenti core di FastMCP, come costruire sia un server MCP sia un client e come integrarli senza attriti nel tuo flusso di lavoro. Se sei alle prime armi con MCP, consulta la nostra Guida al Model Context Protocol con progetto demo per saperne di più.
Che cos’è FastMCP 2.0?
FastMCP 2.0 è un framework Python open-source progettato per rendere semplice ed efficiente la costruzione di server e client Model Context Protocol (MCP). Con poche righe di codice, gli sviluppatori possono creare server MCP personalizzati e collegarli alle proprie applicazioni AI, come editor di codice o assistenti chatbot.
FastMCP 2.0 è il successore di FastMCP 1.0, ora noto come MCP Python SDK, e offre un toolkit completo per lavorare nell’ecosistema MCP.
Ciò che distingue FastMCP 2.0 è il set di funzionalità completo che va ben oltre la specifica MCP di base. Semplifica il deployment, l’autenticazione, il proxying di client e server e permette persino di generare server a partire da API REST.
Componenti principali di FastMCP 2.0
FastMCP 2.0 ruota attorno a tre componenti essenziali: Tools, Resources e Prompts.
1. Tools
I Tools sono funzioni Python esposte agli LLM tramite il protocollo MCP. Decorando una funzione con @mcp.tool, consenti al modello AI di chiamarla durante una conversazione. Questo abilita gli LLM a eseguire azioni nel mondo reale, come interrogare database, chiamare API o effettuare calcoli.
from fastmcp import FastMCPmcp = FastMCP(name="UtilityServer")@mcp.tooldef convert_usd_to_eur(amount: float, rate: float = 0.91) -> float: """Converts a given amount in USD to EUR using the provided rate.""" return round(amount * rate, 2)
2. Resources
Le Resources offrono agli LLM o alle applicazioni client accesso in sola lettura a dati come file, record di database, configurazioni o contenuti generati dinamicamente. Per esempio:
from fastmcp import FastMCPmcp = FastMCP(name="WeatherResourceServer")@mcp.resource("config://weather-settings")def get_weather_settings() -> dict: """Provides weather configuration.""" return { "default_units": "metric", "default_location": "Berlin", "features_enabled": ["forecast", "alerts"] }@mcp.resource("resource://welcome-message")def welcome_message() -> str: """Returns a dynamic greeting for users based on time of day.""" from datetime import datetime hour = datetime.now().hour if hour < 12: return "Good morning! Here's your weather update." elif hour < 18: return "Good afternoon! Need a forecast?" else: return "Good evening! Let's check the weather."
3. Prompts
I Prompts sono modelli di messaggio riutilizzabili e parametrizzati che guidano le risposte degli LLM. Definendoli come funzioni, garantisci istruzioni coerenti e ricche di contesto invocabili dai client.
Sono necessari per eseguire più tool in sequenza e guidare l’LLM a svolgere determinati compiti usando i tool e le risorse disponibili.
from fastmcp import FastMCPfrom fastmcp.prompts.prompt import PromptMessage, TextContentmcp = FastMCP(name="TutorPromptServer")@mcp.promptdef explain_math_concept(concept: str) -> PromptMessage: """Creates a message asking an AI tutor to explain a math concept simply.""" text = f"Can you explain the math concept of '{concept}' in a way that's easy for a 12-year-old to understand?" return PromptMessage(role="user", content=TextContent(type="text", text=text))
Creare un ArXiv Explorer AI con FastMCP 2.0 e Tavily
In questa sezione costruiremo un server MCP "ArXiv Explorer". Il server includerà due tool: uno per estrarre link e titoli degli articoli di ricerca e un secondo per riassumerli. Oltre a questi tool, il server includerà anche resources e prompts per creare un report completo sull’argomento scelto.
1. Configurazione iniziale
Prima di iniziare, ti servirà la chiave API di Tavily. Puoi ottenere una chiave gratuita con 1.000 richieste mensili su tavily.com. Poi, installa le librerie Python necessarie:
pip install fastmcp tavily-python
2. Creare il server "ArxivExplorer"
Innanzitutto creeremo il file Python del server. Il file è composto da:
- Inizializzazione: crea un’istanza di FastMCP assegnando al server il nome "ArxivExplorer".
- Resource: il decorator
@mcp.resourceespone la nostra funzionearxiv_topicscome sorgente dati in sola lettura. Un client AI può recuperare questi topic per avere idee su cosa ricercare, se l’utente non è sicuro. - Tools: il decorator
@mcp.toolrende le normali funzioni Python azioni eseguibili da un LLM. - search_arxiv: questo tool usa l’API di Tavily per limitare la ricerca a un dominio specifico (arxiv.org), assicurando di ottenere solo articoli scientifici pertinenti da arxiv.org.
- summarize_paper: questo tool usa il
qna_searchdi Tavily, ottimizzato per fornire risposte dirette e concise, perfetto per generare un riassunto. - Prompt: il decorator
@mcp.promptcrea un template riutilizzabile. Non è un semplice prompt: è un piano strategico che istruisce un LLM su come usare in sequenza i tool del server per svolgere un compito complesso. - HTTP Transport:
mcp.run(transport="http")è una riga fondamentale. Invece di usare “stdio” per processi locali, avvia un server web. Questo consente a qualsiasi client sulla rete (o sulla stessa macchina) di connettersi al nostro server via URL, rendendolo davvero remoto e condivisibile.
server.py:
import osfrom typing import Dict, Listfrom fastmcp import FastMCPfrom tavily import TavilyClient# --- Configuration ---TAVILY_API_KEY = os.environ.get("TAVILY_API_KEY")if not TAVILY_API_KEY: raise ValueError("Please set the TAVILY_API_KEY environment variable.")tavily = TavilyClient(api_key=TAVILY_API_KEY)mcp = FastMCP(name="ArxivExplorer")print("✅ ArxivExplorer server initialized.")# --- Dynamic Resource: Suggested AI research topics ---@mcp.resource("resource://ai/arxiv_topics")def arxiv_topics() -> List[str]: return [ "Transformer interpretability", "Efficient large-scale model training", "Federated learning privacy", "Neural network pruning", ]print("✅ Resource 'resource://ai/arxiv_topics' registered.")# --- Tool: Search ArXiv for recent papers ---@mcp.tool(annotations={"title": "Search Arxiv"})def search_arxiv(query: str, max_results: int = 5) -> List[Dict]: """ Queries ArXiv via Tavily, returning title + link for each paper, and *only* ArXiv results. """ resp = tavily.search( query=f"site:arxiv.org {query}", max_results=max_results ) return [ {"title": r["title"].strip(), "url": r["url"]} for r in resp.get("results", []) ]# --- Tool: Summarize an ArXiv paper ---@mcp.tool(annotations={"title": "Summarize Paper"})def summarize_paper(paper_url: str) -> str: """ Returns a one-paragraph summary of the paper at the given URL. """ prompt = f"Summarize the key contributions of this ArXiv paper: {paper_url}" return tavily.qna_search(query=prompt)print("✅ Tools 'Search Arxiv' and 'Summarize Paper' registered.")# --- Prompt Template: Explore a topic thoroughly ---@mcp.promptdef explore_topic_prompt(topic: str) -> str: return ( f"I want to explore recent work on '{topic}'.\n" f"1. Call the 'Search Arxiv' tool to find the 5 most recent papers.\n" f"2. For each paper URL, call 'Summarize Paper' to extract its key contributions.\n" f"3. Combine all summaries into an overview report." )print("✅ Prompt 'explore_topic_prompt' registered.")if __name__ == "__main__": print("\n🚀 Starting ArxivExplorer Server...") mcp.run(transport="http")
3. Creare il client interattivo
Dobbiamo testare le funzionalità e gli endpoint del server MCP prima di integrarlo nell’applicazione AI. A questo scopo, FastMCP fornisce una semplice API per connettere il server MCP e testarne tutte le funzioni.
Il file client è composto da:
- HTTP Transport:
StreamableHttpTransportè progettato specificamente per connettersi a un server FastMCP in modalità HTTP. - Helper unwrap_tool_result: è un’utility cruciale. Il client FastMCP non restituisce dati grezzi; restituisce oggetti strutturati. Questa funzione ispeziona in modo sicuro l’oggetto di risposta ed estrae i dati Python che ti servono davvero.
- Workflow: la funzione principale esegue un test completo.
- Esegue un ping al server per assicurarsi che sia online.
- Elenca tutti i tool, le risorse e i prompt disponibili.
- Legge la resource
arxiv_topicse analizza correttamente il risultato. - Chiama il tool
search_arxive usa la funzione helper per “spacchettare” la lista di articoli. - Concatena i tool prendendo l’URL dal primo risultato della ricerca e passandolo al tool
summarize_paper. - Infine, ottiene il
explore_topic_prompt, mostrando le istruzioni finali, pronte per essere inviate a un LLM.
client.py:
import astimport asyncioimport pprintfrom fastmcp import Clientfrom fastmcp.client.transports import StreamableHttpTransport# --- Configuration ---SERVER_URL = "http://localhost:8000/mcp" # adjust if hosted elsewherepp = pprint.PrettyPrinter(indent=2, width=100)def unwrap_tool_result(resp): """ Safely unwraps the content from a FastMCP tool call result object. """ if hasattr(resp, "content") and resp.content: # The content is a list containing a single content object content_object = resp.content[0] # It could be JSON or plain text if hasattr(content_object, "json"): return content_object.json if hasattr(content_object, "text"): try: # Use ast.literal_eval for safely evaluating a string containing a Python literal return ast.literal_eval(content_object.text) except (ValueError, SyntaxError): # If it's not a literal, return the raw text return content_object.text return respasync def main(): transport = StreamableHttpTransport(url=SERVER_URL) client = Client(transport) print("\n🚀 Connecting to FastMCP server at:", SERVER_URL) async with client: # 1. Ping to test connectivity print("\n🔗 Testing server connectivity...") await client.ping() print("✅ Server is reachable!\n") # 2. Discover server capabilities print("🛠️ Available tools:") pp.pprint(await client.list_tools()) print("\n📚 Available resources:") pp.pprint(await client.list_resources()) print("\n💬 Available prompts:") pp.pprint(await client.list_prompts()) # 3. Fetch the topics resource print("\n\n📖 Fetching resource: resource://ai/arxiv_topics") res = await client.read_resource("resource://ai/arxiv_topics") topics = ast.literal_eval(res[0].text) print("Today's AI topics:") for i, t in enumerate(topics, 1): print(f" {i}. {t}") # 4. Test the search tool print("\n\n🔍 Testing tool: search_arxiv") raw_search = await client.call_tool( "search_arxiv", {"query": "Transformer interpretability", "max_results": 3}, ) search_results = unwrap_tool_result(raw_search) for i, paper in enumerate(search_results, 1): print(f" {i}. {paper['title']}\n {paper['url']}") # 5. Test the summarize tool on the first result if search_results: first_url = search_results[0]["url"] print("\n\n📝 Testing tool: summarize_paper") raw_summary = await client.call_tool( "summarize_paper", {"paper_url": first_url} ) summary = unwrap_tool_result(raw_summary) print("\nSummary of first paper:\n", summary) # 6. Test the prompt generator print("\n\n🚀 Testing prompt: explore_topic_prompt") prompt_resp = await client.get_prompt( "explore_topic_prompt", {"topic": "Transformer interpretability"} ) print("\nGenerated prompt for an LLM:") for msg in prompt_resp.messages: print(f"{msg.role.upper()}: {msg.content.text}\n")if __name__ == "__main__": asyncio.run(main())
Tutti i file e le configurazioni sono disponibili nel repository GitHub kingabzpro/FastMCP-Project. Puoi usarlo se riscontri problemi. Ho incluso anche la guida per l’installazione in locale.
4. Esecuzione dell’applicazione
Ora eseguiremo sia il server MCP sia il client.
Per prima cosa, imposta la chiave API di Tavily come variabile d’ambiente sul tuo sistema locale:
export TAVILY_API_KEY='your_tavily_api_key'
Poi, avvia il server:
python server.py
In pochi secondi vedrai che il server FastMCP è in esecuzione su http://localhost:8000/mcp.

Apri un nuovo terminale ed esegui lo script client per verificare che tutto funzioni correttamente:
python client.py
Come possiamo vedere, tutte le funzioni, le risorse, i tool e i prompt funzionano perfettamente. Il nostro server MCP si comporta bene anche con più richieste all’API di Tavily.
🚀 Connecting to FastMCP server at: http://localhost:8000/mcp🔗 Testing server connectivity...✅ Server is reachable!🛠️ Available tools:[ Tool(name='search_arxiv', title='Search Arxiv', description='Queries ArXiv via Tavily, returning title + link for each paper,\nand *only* ArXiv results.', inputSchema={'properties': {'query': {'title': 'Query', 'type': 'string'}, 'max_results': {'default': 5, 'title': 'Max Results', 'type': 'integer'}}, 'required': ['query'], 'type': 'object'}, outputSchema={'properties': {'result': {'items': {'additionalProperties': True, 'type': 'object'}, 'title': 'Result', 'type': 'array'}}, 'required': ['result'], 'title': '_WrappedResult', 'type': 'object', 'x-fastmcp-wrap-result': True}, annotations=ToolAnnotations(title='Search Arxiv', readOnlyHint=None, destructiveHint=None, idempotentHint=None, openWorldHint=None), meta=None), Tool(name='summarize_paper', title='Summarize Paper', description='Returns a one-paragraph summary of the paper at the given URL.', inputSchema={'properties': {'paper_url': {'title': 'Paper Url', 'type': 'string'}}, 'required': ['paper_url'], 'type': 'object'}, outputSchema={'properties': {'result': {'title': 'Result', 'type': 'string'}}, 'required': ['result'], 'title': '_WrappedResult', 'type': 'object', 'x-fastmcp-wrap-result': True}, annotations=ToolAnnotations(title='Summarize Paper', readOnlyHint=None, destructiveHint=None, idempotentHint=None, openWorldHint=None), meta=None)]📚 Available resources:[ Resource(name='arxiv_topics', title=None, uri=AnyUrl('resource://ai/arxiv_topics'), description=None, mimeType='text/plain', size=None, annotations=None, meta=None)]💬 Available prompts:[ Prompt(name='explore_topic_prompt', title=None, description=None, arguments=[PromptArgument(name='topic', description=None, required=True)], meta=None)]📖 Fetching resource: resource://ai/arxiv_topicsToday's AI topics: 1. Transformer interpretability 2. Efficient large-scale model training 3. Federated learning privacy 4. Neural network pruning🔍 Testing tool: search_arxiv 1. Transformer Interpretability Beyond Attention Visualization https://arxiv.org/abs/2012.09838 2. A Practical Review of Mechanistic Interpretability for ... https://arxiv.org/abs/2407.02646 3. Mechanistic Interpretability of Fine-Tuned Vision ... https://arxiv.org/abs/2503.18762📝 Testing tool: summarize_paperSummary of first paper: The paper proposes a novel method for interpreting Transformer networks beyond attention visualization, introducing a new way to compute relevancy. It aims to enhance interpretability in vision tasks. The method is shown to provide more accurate insights into model decisions.🚀 Testing prompt: explore_topic_promptGenerated prompt:USER: type='text' text="I want to explore recent work on 'Transformer interpretability'.\n1. Call the 'Search Arxiv' tool to find the 5 most recent papers.\n2. For each paper URL, call 'Summarize Paper' to extract its key contributions.\n3. Combine all summaries into an overview report." annotations=None meta=None
Integrare il server MCP in Cursor AI
Lascia il server MCP in esecuzione, perché stiamo per integrarlo nell’editor di codice Cursor AI.
- Vai su “Settings”.
- Clicca sulla scheda “Tools & Integrations”.
- Clicca sul pulsante “New MCP Server”.
- Aggiungi la seguente configurazione:
{ "mcpServers": { "ArxivExplorer": { "url": "http://127.0.0.1:8000/mcp/" } }}
Una volta salvato il file mcp.json con la configurazione sopra, vedrai il nuovo server MCP elencato nella sezione “Tools & Integrations”, che mostrerà due tool come nell’immagine seguente.

Testare il server MCP in Cursor AI
Ora arriva la parte divertente. Vediamo come il nostro server MCP si comporta con l’editor di codice Cursor AI. Impareremo a usare i prompt per richiamare tool, accedere a risorse ed eseguire prompt personalizzati, tutto all’interno dell’editor.
1. Test delle risorse
Inizia verificando se il tuo server MCP può fornire dati utili tramite le sue risorse.
Prompt: “what are the some popular arxiv topics”

Se tutto è configurato correttamente, il modello AI capirà la richiesta e recupererà automaticamente l’elenco dei topic dall’endpoint resource del tuo server MCP.
2. Test dei singoli tool
Ora proviamo i tool esposti tramite MCP. Testeremo prima il tool search_arxiv chiedendo al modello AI di elencare i dieci principali articoli di ricerca sui large language model.
Prompt: “Please search for the top 10 research papers on large language models.”

L’AI chiamerà il tool search_arxiv e dovresti vedere un elenco rapido e accurato di articoli pertinenti, estratti direttamente da arXiv.
Poi testeremo il tool di sintesi che prende l’URL dell’articolo e restituisce un riassunto del lavoro.
Prompt: “Please summarize the following paper for me: https://arxiv.org/abs/2402.06196”

Il tool di sintesi recupererà l’articolo e restituirà un riassunto conciso.
3. Test del prompt
Ora invocheremo un prompt personalizzato dall’MCP che ci aiuterà a generare un report.
Prompt: “Create a report on Quantum computing using the latest work.”

Se osservi il codice del server, vedrai che il modello AI comprende il compito e usa la funzione explore_topic_prompt.
@mcp.promptdef explore_topic_prompt(topic: str) -> str: return ( f"I want to explore recent work on '{topic}'.\n" f"1. Call the 'Search Arxiv' tool to find the 5 most recent papers.\n" f"2. For each paper URL, call 'Summarize Paper' to extract its key contributions.\n" f"3. Combine all summaries into an overview report." )
Per prima cosa chiamerà il tool "Search Arxiv" per trovare i link agli articoli.

Poi passerà i link al tool "Summarize Paper" uno alla volta per generare i riassunti. Infine, creerà il report.

Conclusione
FastMCP 2.0 offre molto più di un modo semplice per creare server MCP. Fornisce un framework robusto per costruire integrazioni AI sicure, modulari e scalabili. Con funzionalità come autenticazione, proxying avanzato (che consente a un server FastMCP di fungere da frontend per un altro) e la possibilità di combinare più server FastMCP in un’unica applicazione tramite mounting e importing, puoi progettare sistemi complessi e manutenibili con facilità.
Il supporto middleware ti permette di aggiungere funzionalità trasversali, come logging o modifica delle richieste, a tutte le richieste e risposte MCP. Puoi anche inviare messaggi di log e aggiornamenti di avanzamento ai client tramite il contesto MCP, facilitando il monitoraggio e la gestione di operazioni di lunga durata.
In questo tutorial abbiamo visto come costruire un server MCP pienamente funzionante e testarne le funzionalità. Questi strumenti e il protocollo MCP stanno diventando componenti essenziali delle moderne applicazioni AI, abilitando gli LLM a svolgere compiti più avanzati e ad automatizzare i workflow in modo più efficace.
Per continuare a imparare sui server MCP, dai un’occhiata anche a queste risorse:
- Model Context Protocol (MCP): Guida con progetto demo
- I 10 migliori server e client MCP per l’automazione dei workflow AI nel 2025
- Guida al server MCP con Gradio: build, test, deploy e integrazione
- Creare un agente AI con LangGraph e Model Context Protocol
- Chrome DevTools MCP: automazione e debugging del browser con l’AI
In quanto data scientist certificato, sono appassionato di sfruttare tecnologie all’avanguardia per creare applicazioni di machine learning innovative. Con una solida esperienza in riconoscimento vocale, analisi e reportistica dei dati, MLOps, AI conversazionale e NLP, ho affinato le mie competenze nello sviluppo di sistemi intelligenti in grado di avere un impatto concreto. Oltre alla mia expertise tecnica, sono anche un comunicatore efficace, con il talento di rendere chiari e sintetici concetti complessi. Di conseguenza, sono diventato un blogger molto seguito in ambito data science, condividendo idee ed esperienze con una community in crescita di professionisti dei dati. Attualmente mi concentro sulla creazione e sull’editing di contenuti, lavorando con large language model per sviluppare contenuti potenti e coinvolgenti che possano aiutare aziende e singoli a valorizzare al meglio i propri dati.


