Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions examples/custom-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Example - custom MCP server on Databricks Apps

This example shows how to create and launch a custom agent on Databricks Apps.
Please note that this example doesn't use any Databricks SDK, and is independent of the `mcp` package in the root dir of this repo.

## Prerequisites

- Databricks CLI installed and configured
- `uv`

## Local development

- run `uv` sync:

```bash
uv sync
```

- start the server locally. Changes will trigger a reload:

```bash
uvicorn custom-server.app:mcp --reload
```

## Deploying a custom MCP server on Databricks Apps

There are two ways to deploy the server on Databricks Apps: using the `databricks apps` CLI or using the `databricks bundle` CLI. Depending on your preference, you can choose either method.

Both approaches require first configuring Databricks authentication:
```bash
export DATABRICKS_CONFIG_PROFILE=<your-profile-name> # e.g. custom-mcp-server
databricks auth login --profile "$DATABRICKS_CONFIG_PROFILE"
```

### Using `databricks apps` CLI

To deploy the server using the `databricks apps` CLI, follow these steps:

Create a Databricks app to host your MCP server:
```bash
databricks apps create mcp-custom-server
```

Upload the source code to Databricks and deploy the app:

```bash
DATABRICKS_USERNAME=$(databricks current-user me | jq -r .userName)
databricks sync . "/Users/$DATABRICKS_USERNAME/my-mcp-server"
databricks apps deploy mcp-custom-server --source-code-path "/Workspace/Users/$DATABRICKS_USERNAME/my-mcp-server"
```

### Using `databricks bundle` CLI

To deploy the server using the `databricks bundle` CLI, follow these steps

[//]: # (TODO: would be nice to also be able to use the same uv command to auto-install dependencies and run the app)
Update the `app.yaml` file in this directory to use the following command:
```yaml
command: ["uvicorn", "custom_server.app:app"]
```

- In this directory, run the following command to deploy and run the MCP server on Databricks Apps:

```bash
uv build --wheel
databricks bundle deploy
databricks bundle run custom-mcp-server
```

## Connecting to the MCP server

[//]: # (TODO: once official Databricks docs for using MCP servers in agents are live, replace this with a link)
[//]: # (to that section)

To connect to the MCP server, use the `Streamable HTTP` transport with the following URL:

```
https://your-app-url.usually.ends.with.databricksapps.com/mcp/
```

For authentication, you can use the `Bearer` token from your Databricks profile.
You can get the token by running the following command:

```bash
databricks auth token -p <name-of-your-profile>
```

Please note that the URL should end with `/mcp/` (including the trailing slash), as this is required for the server to work correctly.
1 change: 1 addition & 0 deletions examples/custom-server/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
command: ["uv", "run", "custom-server"]
4 changes: 1 addition & 3 deletions examples/custom-server/databricks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ artifacts:
resources:
apps:
custom-mcp-server:
name: "custom-mcp-server"
name: "mcp-custom-server-bundles"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid conflict with the one deployed via apps CLI

description: "Custom MCP Server on Databricks Apps"
source_code_path: ./.build
config:
command: ["uvicorn", "custom_server.app:app"]

targets:
dev:
Expand Down
3 changes: 3 additions & 0 deletions examples/custom-server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ dev = [

[tool.hatch.build.hooks.custom]
path = "hooks/apps_build.py"

[project.scripts]
custom-server = "custom_server.main:main"
2 changes: 2 additions & 0 deletions examples/custom-server/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# We only need `uv` in our requirements if deploying via apps CLI
uv
16 changes: 10 additions & 6 deletions examples/custom-server/src/custom_server/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from pathlib import Path
from fastapi.staticfiles import StaticFiles
from mcp.server.fastmcp import FastMCP
from fastapi import FastAPI
from fastapi.responses import FileResponse

STATIC_DIR = Path(__file__).parent / "static"

# Create an MCP server
mcp = FastMCP("Custom MCP Server on Databricks Apps")
Expand All @@ -22,14 +24,16 @@ def get_greeting(name: str) -> str:


mcp_app = mcp.streamable_http_app()
static = StaticFiles(directory=Path(__file__).parent / "static", html=True)


app = FastAPI(
lifespan=lambda _: mcp.session_manager.run(),
)

# note the order of mounting here,
# and don't change it unless you know what you're doing
app.mount("/api", mcp_app)
Copy link
Contributor Author

@smurching smurching Jun 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some upcoming product features that expect that the MCP server is hosted at /mcp instead of /api/mcp (and /mcp is also the default when using FastMCP), so updating to reflect that

app.mount("/", static)

@app.get("/", include_in_schema=False)
async def serve_index():
return FileResponse(STATIC_DIR / "index.html")


app.mount("/", mcp_app)
10 changes: 10 additions & 0 deletions examples/custom-server/src/custom_server/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import uvicorn


def main():
uvicorn.run(
"custom_server.app:app", # import path to your `app`
host="0.0.0.0",
port=8000,
reload=True, # optional
)
8 changes: 4 additions & 4 deletions examples/custom-server/src/custom_server/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ <h3 class="text-lg leading-6 font-medium text-white">Connection Details</h3>
<pre class="bg-gray-900 p-3 rounded overflow-x-auto">
<code class="language-python">
from databricks.sdk import WorkspaceClient
from databricks_mcp import DatabricksOAuthClientProvider
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using this new API to configure auth. We'll also recommend this in docs

from mcp.client.streamable_http import streamablehttp_client as connect
from mcp import ClientSession

Expand All @@ -96,9 +97,8 @@ <h3 class="text-lg leading-6 font-medium text-white">Connection Details</h3>
async def main():
# Connect to a streamable HTTP server

headers = client.config.authenticate()
app_url = "https://your.app.url.databricksapps.com/api/mcp"
async with connect(app_url, headers=headers) as (
app_url = "https://your.app.url.databricksapps.com/mcp/"
async with connect(app_url, auth=DatabricksOAuthClientProvider(client)) as (
read_stream,
write_stream,
_,
Expand All @@ -118,7 +118,7 @@ <h3 class="text-lg leading-6 font-medium text-white">Connection Details</h3>
Or use your favourite tool
</dt>
<dd class="mt-1 text-sm text-gray-100">
You can also connect using tools like <strong>Cloude</strong>, <strong>MCP
You can also connect using tools like <strong>Claude</strong>, <strong>MCP
Inspector</strong>, or any other compatible client.
</dd>
</div>
Expand Down