Add Pipedream MCP to your app or agent
Add Pipedream’s MCP server to your application or agent to make tool calls on behalf of your users to 2,700+ APIs and 10,000+ tools.
Pipedream Connect includes built-in user authentication for every MCP server, which means you don’t need to build any authorization flows or deal with token storage and refresh in order to make authenticated requests on behalf of your users. Learn more here.
Overview
Pipedream’s MCP server code is publicly available on GitHub, and you have two options for using Pipedream’s MCP server in your app:
Try out Pipedream MCP in our demo app: chat.pipedream.com
Pipedream concepts to understand
The MCP server accepts two route params:
external_user_id
- This is your user’s ID, in your system: whatever you use to uniquely identify them
- Requests made for that user ID are coupled to that end user and their connected accounts (learn more)
app
- The app’s “name slug” (the unique identifier for the app)
- See below for learn how to discover available apps
Getting started
Prerequisites
To use either the remote or self-hosted MCP server, you’ll need:
- A Pipedream account
- A Pipedream project. Accounts connected via MCP will be stored here.
- Pipedream OAuth credentials
Set up your environment
Set the following environment variables:
PIPEDREAM_CLIENT_ID=your_client_id
PIPEDREAM_CLIENT_SECRET=your_client_secret
PIPEDREAM_PROJECT_ID=your_project_id # proj_xxxxxxx
PIPEDREAM_ENVIRONMENT=development # development | production
Learn more about environments in Pipedream Connect.
Authentication
Developer authentication
Your application authenticates with Pipedream using client credential OAuth. See below for details.
User account connections
One of the core features of Pipedream Connect and our MCP product is the ability for your users to easily connect their accounts without having to build any of the authorization flow or handle token storage.
You can handle account connections in one of two ways in your app:
Add a button in your UI
- Use Pipedream’s frontend SDK to let users connect their account directly in your UI
- You can see an example of this when you connect any account in mcp.pipedream.com
Return a link
- Use Connect Link to let your users open a Pipedream hosted page to connect their account
- There’s no implementation required for this option since it’s already handled by Pipedream’s MCP server
- If a user doesn’t have a connected account that’s required for a given tool call, the server will return a URL in the tool call response:
https://pipedream.com/_static/connect.html?token=ctok_xxxxxxx&connectLink=true&app={appSlug}
Discover available MCP servers
Pipedream provides 2,700+ APIs as MCP servers. Each server corresponds to an app integration (like Notion, Gmail, or Slack) and has its own specific set of tools that you can expose to OpenAI.
import { createBackendClient } from "@pipedream/sdk/server";
// Initialize the Pipedream SDK client
const pd = createBackendClient({
environment: PIPEDREAM_ENVIRONMENT,
credentials: {
clientId: PIPEDREAM_CLIENT_ID,
clientSecret: PIPEDREAM_CLIENT_SECRET,
},
projectId: PIPEDREAM_PROJECT_ID
});
// Get all available apps (paginated)
const apps = await pd.getApps();
// Each app has these key properties:
// - name_slug: Used in the MCP server URL (e.g., "notion", "gmail", "slack")
// - name: Display name (e.g., "Notion", "Gmail", "Slack")
Use Pipedream’s remote MCP server
The remote MCP server is in beta, and we’re looking for feedback. During the beta, the API is subject to change.
Supported transport types
The Pipedream MCP server supports both SSE and streamable HTTP transport types dynamically, with no configuration required by the developer or MCP client.
Tool modes
Pipedream MCP supports two methods for interacting with tools:
- Sub-agent (default)
- Tools only
Sub-agent mode
When using Pipedream MCP in sub-agent mode, all tools you expose to your LLM take a single input: instruction
.
The Pipedream MCP server passes the instruction
to an LLM to handle the configuration of the main tool using a set of agents with narrowly scoped sets of instructions and additional tools to aid in the configuration and execution of the top-level tool.
- The benefit with this approach is that sub-agent mode abstracts a lot of the complexity with handling things like remote options and dynamic props, especially for MCP clients that don’t automatically reload tools.
- However, one downside is that you hand over some of the control and observability to Pipedream in this model.
While in Beta, Pipedream eats the costs of the LLM tokens in sub-agent mode. We’ll likely pass these costs on to the developer in the future.
View the schema for the google_sheets-add-single-row
tool in sub-agent mode
{
"name": "GOOGLE_SHEETS-ADD-SINGLE-ROW",
"description": "Add a single row of data to Google Sheets. [See the documentation](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append)",
"inputSchema": {
"type": "object",
"properties": {
"instruction": {
"type": "string"
}
},
"required": [
"instruction"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
}
Tools-only mode
To handle all tool configuration and calling yourself, you should use tools-only
mode.
Configuring dynamic props
- Tools that use dynamic props can’t be configured in one shot, as the full prop definition isn’t known until certain inputs are defined.
- For example, the full set of props for
google_sheets-add-single-row
aren’t known until you configure thehasHeaders
prop. Once we know if there’s a header row, we can retrieve the column names from the header row and make them available as props that can be configured. - As you call each tool, you should reload the available tools for the server, and we’ll expose meta tools for configuration, such as
begin_configuration_google_sheets-add-single-row
, which causes the rest of the tools to be removed and only tools relevant to the configuration are exposed.
View the schema for the google_sheets-add-single-row
tool in tools-only mode
{
"name": "google_sheets-add-single-row",
"description": "Add a single row of data to Google Sheets. [See the documentation](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append)",
"inputSchema": {
"type": "object",
"properties": {
"drive": {
"anyOf": [
{
"anyOf": [
{
"not": {}
},
{
"type": "string"
}
]
},
{
"type": "null"
}
],
"description": "Defaults to `My Drive`. To select a [Shared Drive](https://support.google.com/a/users/answer/9310351) instead, select it from this list.\n\nYou can use the \"CONFIGURE_COMPONENT\" tool using these parameters to get the values. key: google_sheets-add-single-row, propName: drive"
},
"sheetId": {
"type": "string",
"description": "Select a spreadsheet or provide a spreadsheet ID\n\nYou can use the \"CONFIGURE_COMPONENT\" tool using these parameters to get the values. key: google_sheets-add-single-row, propName: sheetId"
},
"worksheetId": {
"type": "string",
"description": "Select a worksheet or enter a custom expression. When referencing a spreadsheet dynamically, you must provide a custom expression for the worksheet.\n\nYou can use the \"CONFIGURE_COMPONENT\" tool using these parameters to get the values. key: google_sheets-add-single-row, propName: worksheetId"
},
"hasHeaders": {
"type": "boolean",
"description": "If the first row of your document has headers, we'll retrieve them to make it easy to enter the value for each column. Note: When using a dynamic reference for the worksheet ID (e.g. `{{steps.foo.$return_value}}`), this setting is ignored."
}
},
"required": [
"sheetId",
"worksheetId",
"hasHeaders"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
}
Base URL
https://remote.mcp.pipedream.net
API Authentication
To authenticate requests to Pipedream’s MCP server, you need to include an access token with every HTTP request. Here’s how to get it:
import { createBackendClient } from "@pipedream/sdk/server";
// Initialize the Pipedream SDK client
const pd = createBackendClient({
environment: PIPEDREAM_ENVIRONMENT,
credentials: {
clientId: PIPEDREAM_CLIENT_ID,
clientSecret: PIPEDREAM_CLIENT_SECRET,
},
projectId: PIPEDREAM_PROJECT_ID
});
// Get access token for MCP server auth
const accessToken = await pd.rawAccessToken();
console.log(accessToken);
Params
- Below are params that you should send with every HTTP request to Pipedream’s MCP server.
- To enable broad support for various MCP clients, you can pass these params via HTTP headers or as query params on the URL.
Header | Query Param | Value | Required? |
---|---|---|---|
x-pd-project-id | projectId | proj_xxxxxxx | Yes |
x-pd-environment | environment | development , production | Yes |
x-pd-external-user-id | externalUserId | <your-users-id> | Yes |
x-pd-app-slug | app | linear , notion , etc | Yes |
x-pd-tool-mode | toolMode | sub-agent , tools-only | No Defaults to sub-agent |
Example request
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { createBackendClient } from "@pipedream/sdk/server";
// Initialize the Pipedream SDK client
const pd = createBackendClient({
environment: PIPEDREAM_ENVIRONMENT,
credentials: {
clientId: PIPEDREAM_CLIENT_ID,
clientSecret: PIPEDREAM_CLIENT_SECRET,
},
projectId: PIPEDREAM_PROJECT_ID
});
// Retrieve your developer access token via the Pipedream SDK
const accessToken = await pd.rawAccessToken();
const serverUrl = MCP_SERVER_URL || `https://remote.mcp.pipedream.net`;
const transport = new StreamableHTTPClientTransport(new URL(serverUrl), {
requestInit: {
headers: {
"Authorization": `Bearer ${accessToken}`,
"x-pd-project-id": PIPEDREAM_PROJECT_ID, // proj_xxxxxxx
"x-pd-environment": PIPEDREAM_ENVIRONMENT, // development | production
"x-pd-external-user-id": EXTERNAL_USER_ID, // the user's ID from your system
"x-pd-app-slug": APP_SLUG, // notion, linear, gmail, etc
}
}
});
Self-host Pipedream’s MCP server
Hosting the MCP server locally or in your app will expose these routes:
GET /:external_user_id/:app
: app-specific connection endpointPOST /:external_user_id/:app/messages
: app-specific message handler
Using the Dockerfile
You can build and run the container from the reference implementation:
> docker build -t pipedream-connect .
> docker run -d --name pd-mcp -p 3010:3010 --env-file .env pipedream-connect:latest
Running the server using npx
npx @pipedream/mcp sse
The current npx package only supports the sse
transport type, http
is coming soon.
Running the server locally
You can also run the server locally and even customize the MCP server for your specific requirements:
# Clone the repo
git clone https://github.com/PipedreamHQ/pipedream
cd pipedream/modelcontextprotocol
# Install dependencies
pnpm install
# Start the server
pnpm dev:http
See the MCP server README for detailed instructions on customization options.
Debugging
You can use the optional env var PD_SDK_DEBUG
to print out all the requests and responses going to the Connect API:
PD_SDK_DEBUG=true pnpm dev:http
Using the MCP inspector
The MCP inspector can be helpful when debugging tool calls.
npx @modelcontextprotocol/inspector
Enter the server URL:
If using Pipedream’s remote server:
https://remote.mcp.pipedream.net/{external_user_id}/{app_slug}
If running locally:
http://localhost:3010/{external_user_id}/{app_slug}