Partager via


Utiliser des serveurs MCP gérés par Databricks

Important

Cette fonctionnalité est en version bêta. Les administrateurs d’espace de travail peuvent contrôler l’accès à cette fonctionnalité à partir de la page Aperçus . Consultez Gérer les préversions d’Azure Databricks.

Les serveurs MCP gérés par Databricks sont des serveurs prêts à l’emploi qui connectent vos agents IA aux données stockées dans unity Catalog, les index Databricks Vector Search, les espaces Génie et les fonctions personnalisées.

Serveurs managés disponibles

Pour afficher vos serveurs MCP et leurs URL de point de terminaison, accédez à l’espace de travail >Agents>Serveurs MCP :

Onglet Agents du serveur MCP

Databricks fournit les serveurs MCP suivants qui sont prêts à l'emploi.

Serveur MCP Description Modèle d’URL
Recherche vectorielle Interroger les index de recherche vectorielle pour trouver des documents pertinents. Seuls les index avec des intégrations gérées par Databricks sont pris en charge. https://<workspace-hostname>/api/2.0/mcp/vector-search/{catalog}/{schema}
Espace Génie Interrogez des espaces Génie pour analyser des données structurées à l’aide du langage naturel. Utilisez le serveur Genie MCP lors de la connexion d’assistants IA externes, tels que Claude ou ChatGPT, à vos données pour les opérations en lecture seule.
Note: Le serveur MCP managé pour Genie appelle Genie en tant qu’outil MCP, ce qui signifie que l’historique n’est pas passé lors de l’appel des API Genie. En guise d’alternative, vous pouvez utiliser Genie dans un système multi-agent.
https://<workspace-hostname>/api/2.0/mcp/genie/{genie_space_id}
Fonctions de Unity Catalog Utilisez les fonctions catalogue Unity pour exécuter des requêtes SQL prédéfinies. https://<workspace-hostname>/api/2.0/mcp/functions/{catalog}/{schema}
DBSQL Exécutez SQL généré par l’IA. Utilisez le serveur DBSQL MCP pour créer des pipelines de données avec des outils de codage IA (Claude Code, Cursor, Codex, etc.). Pour la récupération de données en lecture seule et les intégrations de chatbots, utilisez Génie à la place. https://<workspace-hostname>/api/2.0/mcp/sql

Exemple de scénario

Considérez un agent personnalisé qui aide à prendre en charge le support client. Vous pouvez le connecter à plusieurs serveurs MCP gérés :

  • Recherche vectorielle : https://<workspace-hostname>/api/2.0/mcp/vector-search/prod/customer_support
    • Rechercher des tickets de support et de la documentation
  • Espace Génie : https://<workspace-hostname>/api/2.0/mcp/genie/{billing_space_id}
    • Interroger les données de facturation et les informations client
  • Fonctions UC : https://<workspace-hostname>/api/2.0/mcp/functions/prod/billing
    • Exécuter des fonctions personnalisées pour les recherches et mises à jour de compte

Cela permet à votre agent d’accéder aux données non structurées (tickets de support), aux données structurées (tables de facturation) et à la logique métier personnalisée.

Exemples de notebooks : Créer un agent avec des serveurs Databricks MCP

Les notebooks suivants montrent comment créer des agents LangGraph et OpenAI qui appellent des outils MCP à l’aide de serveurs MCP gérés par Databricks.

Agent d’appel d’outils MCP LangGraph

Obtenir un ordinateur portable

Agent d’appel d’outils OPENAI MCP

Obtenir un ordinateur portable

Créer un agent à partir d’un environnement local

La connexion à un serveur MCP sur Databricks est similaire à la connexion à tout autre serveur MCP distant. Vous pouvez vous connecter au serveur à l’aide de kits SDK standard, tels que le Kit de développement logiciel (SDK) Python MCP. La principale différence est que les serveurs MCP Databricks sont sécurisés par défaut et nécessitent que les clients spécifient l’authentification.

La bibliothèque Python databricks-mcp permet de simplifier l’authentification dans le code d’agent personnalisé.

Le moyen le plus simple de développer du code d’agent consiste à l’exécuter localement et à l’authentifier auprès de votre espace de travail. Suivez ces étapes pour générer un agent IA qui se connecte à un serveur MCP Databricks.

Configurer votre environnement

  1. Utilisez OAuth pour vous authentifier auprès de votre espace de travail. Exécutez la commande suivante dans un terminal local :

    databricks auth login --host https://<your-workspace-hostname>
    
  2. Lorsque vous y êtes invité, créez le nom d'un profil et notez-le pour une utilisation ultérieure. Le nom du profil par défaut est DEFAULT.

  3. Vérifiez que vous disposez d’un environnement local avec Python 3.12 ou version ultérieure, puis installez les dépendances :

    pip install -U "mcp>=1.9" "databricks-sdk[openai]" "mlflow>=3.1.0" "databricks-agents>=1.0.0" "databricks-mcp"
    

Tester votre connexion réseau locale

Le calcul serverless doit être activé dans votre espace de travail pour exécuter cet extrait de code.

Validez votre connexion au serveur MCP en répertoriant vos outils de catalogue Unity et en exécutant l’outil d’interpréteur de code Python intégré.

  1. Exécutez le code suivant pour valider votre connexion au serveur MCP :
from databricks_mcp import DatabricksMCPClient
from databricks.sdk import WorkspaceClient

# TODO: Update to the Databricks CLI profile name you specified when
# configuring authentication to the workspace.
databricks_cli_profile = "YOUR_DATABRICKS_CLI_PROFILE"
assert (
    databricks_cli_profile != "YOUR_DATABRICKS_CLI_PROFILE"
), "Set databricks_cli_profile to the Databricks CLI profile name you specified when configuring authentication to the workspace"
workspace_client = WorkspaceClient(profile=databricks_cli_profile)
workspace_hostname = workspace_client.config.host
mcp_server_url = f"{workspace_hostname}/api/2.0/mcp/functions/system/ai"

# This code uses the Unity Catalog functions MCP server to expose built-in
# AI tools under `system.ai`, like the `system.ai.python_exec` code interpreter tool
def test_connect_to_server():
    mcp_client = DatabricksMCPClient(server_url=mcp_server_url, workspace_client=workspace_client)
    tools = mcp_client.list_tools()

    print(
        f"Discovered tools {[t.name for t in tools]} "
        f"from MCP server {mcp_server_url}"
    )

    result = mcp_client.call_tool(
        "system__ai__python_exec", {"code": "print('Hello, world!')"}
    )
    print(
        f"Called system__ai__python_exec tool and got result "
        f"{result.content}"
    )


if __name__ == "__main__":
    test_connect_to_server()

Créer un agent

  1. S'appuyer sur le code ci-dessus pour définir un agent de base à un seul tour qui utilise des outils. Enregistrez le code de l’agent localement en tant que fichier nommé mcp_agent.py:

     import json
     import uuid
     import asyncio
     from typing import Any, Callable, List
     from pydantic import BaseModel
    
     import mlflow
     from mlflow.pyfunc import ResponsesAgent
     from mlflow.types.responses import ResponsesAgentRequest, ResponsesAgentResponse
    
     from databricks_mcp import DatabricksMCPClient
     from databricks.sdk import WorkspaceClient
    
     # 1) CONFIGURE YOUR ENDPOINTS/PROFILE
     LLM_ENDPOINT_NAME = "databricks-claude-sonnet-4-5"
     SYSTEM_PROMPT = "You are a helpful assistant."
     DATABRICKS_CLI_PROFILE = "YOUR_DATABRICKS_CLI_PROFILE"
     assert (
         DATABRICKS_CLI_PROFILE != "YOUR_DATABRICKS_CLI_PROFILE"
     ), "Set DATABRICKS_CLI_PROFILE to the Databricks CLI profile name you specified when configuring authentication to the workspace"
     workspace_client = WorkspaceClient(profile=DATABRICKS_CLI_PROFILE)
     host = workspace_client.config.host
     # Add more MCP server URLs here if desired, for example:
     # f"{host}/api/2.0/mcp/vector-search/prod/billing"
     # to include vector search indexes under the prod.billing schema, or
     # f"{host}/api/2.0/mcp/genie/<genie_space_id>"
     # to include a Genie space
     MANAGED_MCP_SERVER_URLS = [
         f"{host}/api/2.0/mcp/functions/system/ai",
     ]
     # Add Custom MCP Servers hosted on Databricks Apps
     CUSTOM_MCP_SERVER_URLS = []
    
    
    
     # 2) HELPER: convert between ResponsesAgent “message dict” and ChatCompletions format
     def _to_chat_messages(msg: dict[str, Any]) -> List[dict]:
         """
         Take a single ResponsesAgent‐style dict and turn it into one or more
         ChatCompletions‐compatible dict entries.
         """
         msg_type = msg.get("type")
         if msg_type == "function_call":
             return [
                 {
                     "role": "assistant",
                     "content": None,
                     "tool_calls": [
                         {
                             "id": msg["call_id"],
                             "type": "function",
                             "function": {
                                 "name": msg["name"],
                                 "arguments": msg["arguments"],
                             },
                         }
                     ],
                 }
             ]
         elif msg_type == "message" and isinstance(msg["content"], list):
             return [
                 {
                     "role": "assistant" if msg["role"] == "assistant" else msg["role"],
                     "content": content["text"],
                 }
                 for content in msg["content"]
             ]
         elif msg_type == "function_call_output":
             return [
                 {
                     "role": "tool",
                     "content": msg["output"],
                     "tool_call_id": msg["tool_call_id"],
                 }
             ]
         else:
             # fallback for plain {"role": ..., "content": "..."} or similar
             return [
                 {
                     k: v
                     for k, v in msg.items()
                     if k in ("role", "content", "name", "tool_calls", "tool_call_id")
                 }
             ]
    
    
     # 3) “MCP SESSION” + TOOL‐INVOCATION LOGIC
     def _make_exec_fn(
         server_url: str, tool_name: str, ws: WorkspaceClient
     ) -> Callable[..., str]:
         def exec_fn(**kwargs):
             mcp_client = DatabricksMCPClient(server_url=server_url, workspace_client=ws)
             response = mcp_client.call_tool(tool_name, kwargs)
             return "".join([c.text for c in response.content])
    
         return exec_fn
    
    
     class ToolInfo(BaseModel):
         name: str
         spec: dict
         exec_fn: Callable
    
    
     def _fetch_tool_infos(ws: WorkspaceClient, server_url: str) -> List[ToolInfo]:
         print(f"Listing tools from MCP server {server_url}")
         infos: List[ToolInfo] = []
         mcp_client = DatabricksMCPClient(server_url=server_url, workspace_client=ws)
         mcp_tools = mcp_client.list_tools()
         for t in mcp_tools:
             schema = t.inputSchema.copy()
             if "properties" not in schema:
                 schema["properties"] = {}
             spec = {
                 "type": "function",
                 "function": {
                     "name": t.name,
                     "description": t.description,
                     "parameters": schema,
                 },
             }
             infos.append(
                 ToolInfo(
                     name=t.name, spec=spec, exec_fn=_make_exec_fn(server_url, t.name, ws)
                 )
             )
         return infos
    
    
     # 4) “SINGLE‐TURN” AGENT CLASS
     class SingleTurnMCPAgent(ResponsesAgent):
         def _call_llm(self, history: List[dict], ws: WorkspaceClient, tool_infos):
             """
             Send current history → LLM, returning the raw response dict.
             """
             client = ws.serving_endpoints.get_open_ai_client()
             flat_msgs = []
             for msg in history:
                 flat_msgs.extend(_to_chat_messages(msg))
             return client.chat.completions.create(
                 model=LLM_ENDPOINT_NAME,
                 messages=flat_msgs,
                 tools=[ti.spec for ti in tool_infos],
             )
    
         def predict(self, request: ResponsesAgentRequest) -> ResponsesAgentResponse:
             ws = WorkspaceClient(profile=DATABRICKS_CLI_PROFILE)
    
             # 1) build initial history: system + user
             history: List[dict] = [{"role": "system", "content": SYSTEM_PROMPT}]
             for inp in request.input:
                 history.append(inp.model_dump())
    
             # 2) call LLM once
             tool_infos = [
                 tool_info
                 for mcp_server_url in (MANAGED_MCP_SERVER_URLS + CUSTOM_MCP_SERVER_URLS)
                 for tool_info in _fetch_tool_infos(ws, mcp_server_url)
             ]
             tools_dict = {tool_info.name: tool_info for tool_info in tool_infos}
             llm_resp = self._call_llm(history, ws, tool_infos)
             raw_choice = llm_resp.choices[0].message.to_dict()
             raw_choice["id"] = uuid.uuid4().hex
             history.append(raw_choice)
    
             tool_calls = raw_choice.get("tool_calls") or []
             if tool_calls:
                 # (we only support a single tool in this “single‐turn” example)
                 fc = tool_calls[0]
                 name = fc["function"]["name"]
                 args = json.loads(fc["function"]["arguments"])
                 try:
                     tool_info = tools_dict[name]
                     result = tool_info.exec_fn(**args)
                 except Exception as e:
                     result = f"Error invoking {name}: {e}"
    
                 # 4) append the “tool” output
                 history.append(
                     {
                         "type": "function_call_output",
                         "role": "tool",
                         "id": uuid.uuid4().hex,
                         "tool_call_id": fc["id"],
                         "output": result,
                     }
                 )
    
                 # 5) call LLM a second time and treat that reply as final
                 followup = (
                     self._call_llm(history, ws, tool_infos=[]).choices[0].message.to_dict()
                 )
                 followup["id"] = uuid.uuid4().hex
    
                 assistant_text = followup.get("content", "")
                 return ResponsesAgentResponse(
                     output=[
                         {
                             "id": uuid.uuid4().hex,
                             "type": "message",
                             "role": "assistant",
                             "content": [{"type": "output_text", "text": assistant_text}],
                         }
                     ],
                     custom_outputs=request.custom_inputs,
                 )
    
             # 6) if no tool_calls at all, return the assistant’s original reply
             assistant_text = raw_choice.get("content", "")
             return ResponsesAgentResponse(
                 output=[
                     {
                         "id": uuid.uuid4().hex,
                         "type": "message",
                         "role": "assistant",
                         "content": [{"type": "output_text", "text": assistant_text}],
                     }
                 ],
                 custom_outputs=request.custom_inputs,
             )
    
    
     mlflow.models.set_model(SingleTurnMCPAgent())
    
     if __name__ == "__main__":
         req = ResponsesAgentRequest(
             input=[{"role": "user", "content": "What's the 100th Fibonacci number?"}]
         )
         resp = SingleTurnMCPAgent().predict(req)
         for item in resp.output:
             print(item)
    
    

Déployer votre agent

Lorsque vous êtes prêt à déployer un agent qui se connecte à des serveurs MCP gérés, consultez Déployer un agent pour les applications d’IA génératives.

Spécifiez toutes les ressources dont votre agent a besoin au moment de la journalisation. Voir Authentification pour les ressources Databricks

Par exemple, si votre agent utilise les URL du serveur MCP listées ci-dessous, vous devez spécifier tous les index de recherche vectorielle dans les schémas prod.customer_support et prod.billing. Vous devez également spécifier toutes les fonctions de catalogue Unity dans prod.billing:

  • https://<your-workspace-hostname>/api/2.0/mcp/vector-search/prod/customer_support
  • https://<your-workspace-hostname>/api/2.0/mcp/vector-search/prod/billing
  • https://<your-workspace-hostname>/api/2.0/mcp/functions/prod/billing

Si votre agent se connecte aux serveurs MCP sur Databricks pour découvrir et exécuter des outils, consignez les ressources nécessaires à ces serveurs MCP avec votre agent. Databricks recommande d’installer le databricks-mcp package PyPI pour simplifier ce processus.

En particulier, si vous utilisez des serveurs MCP managés, vous pouvez utiliser databricks_mcp.DatabricksMCPClient().get_databricks_resources(<server_url>) pour récupérer les ressources nécessaires par le serveur MCP géré. Si votre agent interroge un serveur MCP personnalisé hébergé sur une application Databricks, vous pouvez configurer l’autorisation en incluant explicitement le serveur en tant que ressource lors de la journalisation de votre modèle.

Par exemple, pour déployer l’agent défini ci-dessus, exécutez le code suivant, en supposant que vous avez enregistré la définition du code de l’agent dans mcp_agent.py:

import os
from databricks.sdk import WorkspaceClient
from databricks import agents
import mlflow
from mlflow.models.resources import DatabricksFunction, DatabricksServingEndpoint, DatabricksVectorSearchIndex
from mcp_agent import LLM_ENDPOINT_NAME
from databricks_mcp import DatabricksMCPClient

# TODO: Update this to your Databricks CLI profile name
databricks_cli_profile = "YOUR_DATABRICKS_CLI_PROFILE"
assert (
    databricks_cli_profile != "YOUR_DATABRICKS_CLI_PROFILE"
), "Set databricks_cli_profile to the Databricks CLI profile name you specified when configuring authentication to the workspace"
workspace_client = WorkspaceClient(profile=databricks_cli_profile)


# Configure MLflow and the Databricks SDK to use your Databricks CLI profile
current_user = workspace_client.current_user.me().user_name
mlflow.set_tracking_uri(f"databricks://{databricks_cli_profile}")
mlflow.set_registry_uri(f"databricks-uc://{databricks_cli_profile}")
mlflow.set_experiment(f"/Users/{current_user}/databricks_docs_example_mcp_agent")
os.environ["DATABRICKS_CONFIG_PROFILE"] = databricks_cli_profile

MANAGED_MCP_SERVER_URLS = [
    f"{host}/api/2.0/mcp/functions/system/ai",
]
# Log the agent defined in mcp_agent.py
here = os.path.dirname(os.path.abspath(__file__))
agent_script = os.path.join(here, "mcp_agent.py")
resources = [
    DatabricksServingEndpoint(endpoint_name=LLM_ENDPOINT_NAME),
    DatabricksFunction("system.ai.python_exec"),
    # --- Uncomment and edit the following lines to include custom mcp servers hosted on Databricks Apps ---
    # DatabricksApp(app_name="app-name")
]

for mcp_server_url in MANAGED_MCP_SERVER_URLS:
    mcp_client = DatabricksMCPClient(server_url=mcp_server_url, workspace_client=workspace_client)
    resources.extend(mcp_client.get_databricks_resources())

with mlflow.start_run():
    logged_model_info = mlflow.pyfunc.log_model(
        artifact_path="mcp_agent",
        python_model=agent_script,
        resources=resources,
    )

# TODO Specify your UC model name here
UC_MODEL_NAME = "main.default.databricks_docs_mcp_agent"
registered_model = mlflow.register_model(logged_model_info.model_uri, UC_MODEL_NAME)

agents.deploy(
    model_name=UC_MODEL_NAME,
    model_version=registered_model.version,
)

Étapes suivantes