MCP servers

Enhanced Advanced

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:

  1. Visit the MCP server content in the Connect web interface first.
  2. Complete any required OAuth authorization flows for the third-party services.
  3. 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.

Designing for missing authorizations

When building MCP servers that use viewer OAuth integrations, design your tool implementations to handle missing authorizations gracefully. If a user has not completed the authorization flow for a required integration, your 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 the issue, and helps agents understand that the authorization needs to be solved on Connect, not 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.

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:

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 has been deprecated in the MCP standard. 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 object. See the documentation on entrypoints for details.

This may not be the same as how the server is started 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.

For a FastMCP server in a file named server.py with the server object named mcp, the entrypoint would be server:mcp.

Configure transport security

When running behind the Connect proxy, your MCP server must allow connections from the Connect server. This requires transport security settings that permit the Connect server hostname.

Here’s a complete configuration example, including both transport security and stateless HTTP mode, and returning the server object named mcp, suitable for referencing as the entrypoint:

server.py
import os
from urllib.parse import urlparse
from fastmcp import FastMCP
from mcp.server.lowlevel.server import TransportSecuritySettings

def get_transport_security():
    """Configure transport security based on environment."""
    connect_server = os.environ.get("CONNECT_SERVER", "")
    if connect_server:
        # Extract host from Connect server URL
        parsed = urlparse(connect_server)
        host = parsed.netloc or parsed.path
        host = host.rstrip("/")
        if host:
            # Include both bare host and port wildcard
            allowed_hosts = [host, f"{host}:*"]
            return TransportSecuritySettings(
                enable_dns_rebinding_protection=True,
                allowed_hosts=allowed_hosts,
            )
    # Default: let FastMCP auto-configure based on host
    return None

mcp = FastMCP(
    "My MCP Server",
    transport_security=get_transport_security(),
    stateless_http=True,
    json_response=True,
)

When running locally, transport_security is None and FastMCP uses its default behavior. When running on Connect, it restricts connections to the Connect server hostname.

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:mcp \
    ./

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.