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 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.
Explore the server in a browser
MCP servers typically mount their protocol endpoint under a subpath such as /mcp and do not serve a page at their root. When a Python MCP server does not handle a request to its root path, Connect shows a console for the server in its place. The console reports the server’s name and description and shows the Streamable HTTP endpoint with example connection settings for several AI applications. It also lists every tool along with its inputs and outputs. You can fill in a tool’s inputs and run it to see the response, which is a convenient way to confirm the server works before connecting an AI application.
If your tools declare annotations, the console shows them. When a tool declares a title, the console lists it under that title and shows the underlying tool name beside it. The behavior hints a tool declares appear as badges next to its name, and in full when you expand the tool. These hints describe:
- Whether the tool only reads data, or might modify it.
- Whether a modification might be destructive rather than additive.
- Whether repeating a call with the same arguments has further effect.
- Whether the tool reaches systems outside the server.
The console reports only the hints a tool declares, and it does not assume anything about tools that declare none. The server supplies its own annotations, so treat them as a statement of intent rather than a guarantee. Connect does not verify or enforce them.
The console applies to Python MCP servers that use the Streamable HTTP transport and mount their endpoint at the conventional /mcp path. The console is available for Python MCP servers only.
If you would rather present your own page at the content root, serve a route at / from your MCP server. Connect only shows the console when your server returns a “not found” response at its root, so a landing page you build yourself takes precedence.
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.
Using integrations with MCP servers
Service account integrations work seamlessly in MCP servers because they use centrally managed credentials rather than per-user authorization.
If your MCP server uses viewer integrations to access third-party services, such as Google, Databricks, or Snowflake, each user must also authenticate with those services. How that happens depends on how you connect to the MCP server:
OAuth: When you authenticate to the MCP server with OAuth, Connect checks whether you have completed the viewer integration logins the content requires. If any are outstanding, Connect prompts you to authorize them as part of the same sign-in flow, before completing the connection, so no separate step is needed.
API keys, or clients that do not implement the full MCP specification: You must authorize the viewer integrations separately before connecting:
- Visit the MCP server content in the Connect web interface.
- Complete any required OAuth authorization flows for the third-party services.
- 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.
Because a user can connect to an MCP server without having authenticated with every third-party service it needs, design the tools in MCP servers that use integrations to handle missing authorizations gracefully. If a user has not completed the authorization flow for a required integration, the tool should return a clear message explaining:
- Which authorization is missing
- Where to complete the authorization (include the URL to your MCP server content on Connect)
This helps users understand why a tool call failed and how to resolve it, and signals to agents that the authorization must be completed on Connect rather than by retrying authentication in the agent.
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.
Choose a language
Connect supports deploying MCP servers in Python and Node.js. Python is available on all Connect license tiers and is recommended for most deployments. Node.js is available for Advanced tier licenses only.
In Python, 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}!"Choose a transport mode
When running on Connect, configure your MCP server to use Streamable HTTP, rather than the legacy Server-Sent Events (SSE) transport, which has been deprecated in the MCP standard.
Connect supports both stateless and stateful Streamable HTTP modes:
Stateless mode (recommended for most deployments): Each request is independent and does not rely on session state stored on the server. This simplifies deployment and scaling, and requires no special load balancer configuration in HA environments.
Stateful mode: The server maintains session state across requests using the
Mcp-Session-Idheader. Connect provides session affinity to route requests with the same session ID to the same worker process. If you are running Connect in a high-availability configuration, your load balancer must be configured to route requests by theMcp-Session-Idheader so that they reach the same Connect node.
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.hostname or (parsed.netloc or parsed.path).rstrip("/").split(":")[0]
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.
Pass a host name without a port to allowed_hosts, as the example does. TrustedHostMiddleware removes the port from the Host header before it compares the two. An entry that includes a port never matches, so the server rejects every request with Invalid host header.
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.
Auto-detection
On first deploy, Connect automatically recognizes MCP servers by scanning the bundle for common MCP packages:
- Python:
fastmcp,mcpinrequirements.txt - R:
plumber2mcpin the package manifest - Node.js:
@modelcontextprotocol/sdkinpackage.json
When detected, Connect sets the content category to mcp, which gives the content a dedicated icon and makes it appear in the MCP tab of the content list. Connect also automatically sets the minimum number of processes to 1, ensuring the MCP server is always available for clients to connect without cold start delays. This automatic default applies only when the minimum processes setting has not been explicitly configured at either the content or server level. On subsequent deploys, the content category and minimum processes settings are preserved unless explicitly changed via the API.
If auto-detection doesn’t apply to your deployment, you can toggle the MCP category in the Information section of the General tab of the content settings panel, or set it using the Update Content API with content_category set to "mcp". In this case, also set the minimum number of processes to 1 or higher on the Runtime tab to keep the server always available.
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.