MCP servers
Model Context Protocol (MCP) is an open standard that connects AI applications to external tools, data sources, and services. MCP servers expose “tools” that AI clients can discover and invoke.
You can deploy MCP servers to Posit Connect so that AI clients across your organization can access shared tools and resources.
When to deploy MCP servers to Connect
Deploy MCP servers to Connect when you want to:
- Access shared resources: Provide access to resources only available on the Connect server, such as files on a shared filesystem or internal databases.
- Proxy third-party services: Securely proxy access to external APIs and manage credentials centrally. This pairs well with OAuth integrations, which allow your MCP server to obtain short-lived access tokens for third-party services on behalf of users.
- Sandbox execution: Run MCP tools in a controlled, sandboxed environment.
- Enable discoverability: Let team members discover and connect to shared MCP tools through the content management features in Connect.
- Centralize management: Manage MCP server deployments, updates, and scaling from a central location. Some organizations have policies that restrict MCP servers from untrusted sources because they can execute code on users’ machines when run locally. A deployment on Connect allows IT teams to vet and control MCP server deployments.
If your security policies allow it, you might prefer to run MCP servers locally when you want:
- Local file access: Your tools need to read or write files on the user’s local machine.
- Low latency: You need minimal response times for tool invocations.
- Simplicity: You have a simple setup that doesn’t require shared access or centralized management.
Connect to an MCP server
To use an MCP server deployed on Connect, you need the content URL for your deployed MCP server. This is the standalone URL that points to the MCP server, not the URL that views it inside the Connect UI.
It is common for MCP servers to mount their endpoints under a /mcp path. So if your Connect content URL is https://connect.example.com/content/abc123/, the MCP server URL would likely be https://connect.example.com/content/abc123/mcp.
For a more readable URL, you can set a vanity URL for your MCP server content. With a vanity URL, the MCP server URL would look like https://connect.example.com/my-mcp-server/mcp.
Authentication
The MCP standard includes an OAuth-based authentication flow. When you add an MCP server URL to your application, it discovers Connect’s OAuth server and prompts you to authorize the connection in your browser. After you authorize once, the application handles authentication automatically.
Use your application’s standard flow for adding an MCP server, providing the MCP server URL and choosing the HTTP transport option.
API key authentication
If OAuth has been disabled on your Connect server, or if your application does not support the MCP OAuth flow, you can use API key authentication instead.
See the API key user guide for instructions on how to generate API keys.
The exact configuration format varies by application. In general, you need to provide an Authorization header with the value Key YOUR_CONNECT_API_KEY. For example, if your application accepts a JSON configuration, it might look something like this:
{
"url": "https://connect.example.com/content/abc123/mcp",
"headers": {
"Authorization": "Key YOUR_CONNECT_API_KEY"
}
}Consult the documentation for your application for the specific configuration syntax.
OAuth integrations with MCP servers
If your MCP server uses viewer OAuth integrations to access third-party services (like Google, Databricks, or Snowflake), you might need to authorize those integrations separately.
When you connect to an MCP server using OAuth, the authorization only grants the application access to Connect. It does not automatically authorize any third-party OAuth integrations that the MCP server uses.
To use MCP servers with viewer OAuth integrations:
- Visit the MCP server content in the Connect web interface first.
- Complete any required OAuth authorization flows for the third-party services.
- Then connect to the MCP server from your application.
After you complete the authorization flows in the web interface, the MCP server can access those integration credentials when running on your behalf.
Service account OAuth integrations work without this step because they use centrally managed credentials rather than per-user authorization.
Adapting an MCP server for Connect
If you have an MCP server that runs locally, you might need to make adjustments before deploying to Connect.
Use Python instead of JavaScript
Connect supports deploying Python and R applications. If your MCP server is written in JavaScript or TypeScript, consider rewriting it in Python using FastMCP or the MCP Python SDK.
FastMCP provides a high-level interface to build MCP servers. The examples in this guide use FastMCP 3.x (tested with 3.1):
server.py
from fastmcp import FastMCP
mcp = FastMCP("My MCP Server")
@mcp.tool()
def greet(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"Use streamable HTTP in stateless mode
When running on Connect, configure your MCP server to use Streamable HTTP, rather than the legacy Server-Sent Events (SSE) transport, which the MCP standard has deprecated. Additionally, configure your server to use stateless HTTP mode. Without this configuration, Streamable HTTP can still use Server-Sent Events internally for streaming responses.
Stateless HTTP mode ensures that each request is independent and does not rely on session state stored on the server. On high-availability Connect deployments with load balancers, SSE would require additional sticky session configuration beyond what Connect recommends. Not only does stateless mode follow the MCP standard more closely, it also simplifies deployment and scaling.
Specify the entrypoint
To deploy to Connect, you must specify the correct entrypoint so Connect can locate your MCP server. See the documentation on entrypoints for details.
This may differ from how you start the server locally. For example, Python MCP servers often use an if __name__ == "__main__" block to launch the server when run directly. However, Connect needs to import the server object from the module instead of executing code that starts a server. You may need to refactor your code to define the server object outside of the __main__ block.
With FastMCP, call mcp.http_app() to create a Starlette ASGI application with the correct transport settings. The entrypoint should reference this ASGI app, not the FastMCP instance directly.
For example, if your file is named server.py and the ASGI app variable is named app, the entrypoint would be server:app.
Configure for Connect deployment
When deploying to Connect, your server needs two configuration changes beyond the basic FastMCP setup:
- Stateless HTTP mode: Connect may run multiple processes behind a load balancer. Stateless mode ensures each request is independent and doesn’t rely on session state stored on a specific process.
- Trusted host protection: Connect proxies requests to your server and rewrites the
Hostheader to match the public server hostname. Adding Starlette’sTrustedHostMiddlewarevalidates that theHostheader matches the expected Connect server, protecting against DNS rebinding attacks.
Here’s a complete configuration example:
server.py
import os
from urllib.parse import urlparse
from fastmcp import FastMCP
from starlette.middleware import Middleware
from starlette.middleware.trustedhost import TrustedHostMiddleware
mcp = FastMCP("My MCP Server")
@mcp.tool()
def greet(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
# Configure trusted host middleware for DNS rebinding protection.
# On Connect, derive allowed hosts from the CONNECT_SERVER environment variable.
middleware = []
connect_server = os.environ.get("CONNECT_SERVER", "")
if connect_server:
parsed = urlparse(connect_server)
host = (parsed.netloc or parsed.path).rstrip("/")
if host:
middleware.append(
Middleware(TrustedHostMiddleware, allowed_hosts=[host])
)
# Create the ASGI app for deployment.
# stateless_http: each request is independent (required for load-balanced deployments)
# json_response: return JSON instead of SSE streams
app = mcp.http_app(
stateless_http=True,
json_response=True,
middleware=middleware,
)Connect automatically sets the CONNECT_SERVER environment variable, and the middleware restricts requests to those with a matching Host header. When you run the server locally without CONNECT_SERVER set, the server applies no host restriction.
Implement filesystem tools for remote access
MCP servers running on Connect do not have access to the end user’s local file system. If your MCP server needs to work with files, you’ll need to implement tools that provide file access through the server.
Common scenarios where this applies:
- Expose shared storage: Your MCP server provides access to files on the Connect shared filesystem or network storage that users cannot access directly.
- Proxy external files: Your MCP server downloads files from cloud storage, APIs, or other services on behalf of the user.
In these cases, implement tools that mirror standard file operations: reading files, listing directories, searching file contents, and similar operations. These tools let AI clients interact with the remote filesystem through your MCP server, similar to how local MCP servers provide access to the user’s local files.
Deploying
To deploy your MCP server using rsconnect-python, use the fastapi mode, and specify the entrypoint for your MCP server:
Terminal
rsconnect deploy fastapi \
-n <saved server name> \
--entrypoint server:app \
./Or use the Posit Publisher extension for VS Code or Positron to deploy directly from your editor. Use the python-fastapi project type and specify the entrypoint in the TOML file if it is not automatically detected.
Ensure your requirements.txt includes the necessary Python dependencies. If you’re using pyproject.toml or another file for dependency management, you can generate requirements.txt with uv pip compile or similar tools.
After deploying, for best performance you can set the minimum number of processes to 1 or higher in the runtime settings. This ensures the MCP server is always available for clients to connect, avoiding cold start delays when all processes have been shut down due to inactivity.
Wrap existing REST APIs
If you already have REST APIs on Connect and want to expose them via MCP without a dedicated MCP server, you can use tools like the FastMCP OpenAPI integration to automatically generate MCP tools from an OpenAPI specification. You could run such a wrapper as a local MCP server or deploy it to Connect.
However, be aware that automatic REST API wrappers have limitations. Design principles that make for good REST APIs do not always align with those for effective MCP tools. See this discussion for considerations when you decide between native MCP implementations and API wrappers.