-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Danny/mcp hosted servers #16743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Danny/mcp hosted servers #16743
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,42 +1,190 @@ | ||||||||||||||||||||||||||||||||
| import { Steps } from 'nextra/components' | ||||||||||||||||||||||||||||||||
| import { Callout, Steps, Tabs } from 'nextra/components' | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Deploy Pipedream MCP to your agent | ||||||||||||||||||||||||||||||||
| Deploy Pipedream's MCP servers to your application or agent and make authenticated request on behalf of your customers. Refer to our reference implementation [here](https://github.com/PipedreamHQ/pipedream/blob/master/modelcontextprotocol/README.md). | ||||||||||||||||||||||||||||||||
| # Add Pipedream MCP to your app or agent | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Quickstart | ||||||||||||||||||||||||||||||||
| Add Pipedream's MCP server to your application or agent to make tool calls on behalf of your users to {process.env.PUBLIC_APPS}+ APIs and 10,000+ tools. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| <Steps> | ||||||||||||||||||||||||||||||||
| ## Overview | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Prerequisites | ||||||||||||||||||||||||||||||||
| Pipedream's MCP server code is [publicly available on GitHub](https://github.com/PipedreamHQ/pipedream/blob/master/modelcontextprotocol/README.md), and you have two options for using Pipedream's MCP server in your app: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| To run your own MCP server, you'll need: | ||||||||||||||||||||||||||||||||
| 1. [Use Pipedream's remote MCP server](#use-pipedreams-remote-mcp-server) | ||||||||||||||||||||||||||||||||
| 2. [Self-host Pipedream's MCP server](#self-host-pipedreams-mcp-server) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### 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 | ||||||||||||||||||||||||||||||||
| - Any requests made to that route are coupled to that end user and uses the connected account tied to that user | ||||||||||||||||||||||||||||||||
| - [See here](/connect/api/#external-users) for more detail | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| **`app`** | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - The app's "name slug" (the unique identifier for the app) | ||||||||||||||||||||||||||||||||
| - [See below](#discover-available-mcp-servers) for discovering available apps | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Getting started | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Prerequisites | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| For either option, you'll need: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| 1. A [Pipedream account](https://pipedream.com/auth/signup) | ||||||||||||||||||||||||||||||||
| 2. A [Pipedream project](/projects/#creating-projects). Accounts connected via MCP will be stored here. | ||||||||||||||||||||||||||||||||
| 3. [Pipedream OAuth credentials](/rest-api/auth/#oauth) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Set up environment variables | ||||||||||||||||||||||||||||||||
| #### Set up your environment | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Set the following environment variables: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| PIPEDREAM_CLIENT_ID=your_client_id | ||||||||||||||||||||||||||||||||
| PIPEDREAM_CLIENT_SECRET=your_client_secret | ||||||||||||||||||||||||||||||||
| PIPEDREAM_PROJECT_ID=your_project_id | ||||||||||||||||||||||||||||||||
| PIPEDREAM_ENVIRONMENT=development | ||||||||||||||||||||||||||||||||
| PIPEDREAM_PROJECT_ID=your_project_id # proj_xxxxxxx | ||||||||||||||||||||||||||||||||
| PIPEDREAM_ENVIRONMENT=development # development | production | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Authentication | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Developer authentication | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Your application authenticates with Pipedream using client credential OAuth. [See below](#api-authentication) 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](/connect/managed-auth/quickstart/#use-the-pipedream-sdk-in-your-frontend) 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](https://mcp.pipedream.com) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Return a link | ||||||||||||||||||||||||||||||||
| - Use [Connect Link ](/connect/managed-auth/quickstart/#or-use-connect-link) to let your users open a Pipedream hosted page to connect their account | ||||||||||||||||||||||||||||||||
| - There is no implementation required for this option since it's already handled in Pipedream's MCP server | ||||||||||||||||||||||||||||||||
| - If a user doesn't have a connected account that's required for a given tool call, we'll return a URL in the tool call response. For example: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| https://pipedream.com/_static/connect.html?token=ctok_xxxxxxx&connectLink=true&app={appSlug} | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Discover available MCP servers | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Pipedream provides [{process.env.PUBLIC_APPS}+ APIs as MCP servers](https://mcp.pipedream.com). 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. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| <Tabs items={['List all apps', 'Search for a specific app']}> | ||||||||||||||||||||||||||||||||
| <Tabs.Tab> | ||||||||||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||||||||||
| // 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") | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| </Tabs.Tab> | ||||||||||||||||||||||||||||||||
| <Tabs.Tab> | ||||||||||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||||||||||
| // Search by app name | ||||||||||||||||||||||||||||||||
| const notionApps = await pd.getApps({ q: "notion" }); | ||||||||||||||||||||||||||||||||
| const gmailApps = await pd.getApps({ q: "gmail" }); | ||||||||||||||||||||||||||||||||
| const slackApps = await pd.getApps({ q: "slack" }); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| </Tabs.Tab> | ||||||||||||||||||||||||||||||||
| </Tabs> | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Use Pipedream's remote MCP server | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| <Callout type="info"> | ||||||||||||||||||||||||||||||||
| Pipedream MCP server supports both SSE and streamable HTTP transport types, with no configuration required by the developer or MCP client. | ||||||||||||||||||||||||||||||||
| </Callout> | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Base URL | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| https://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: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Run the MCP server | ||||||||||||||||||||||||||||||||
| <Tabs items={['Node.js', 'cURL']}> | ||||||||||||||||||||||||||||||||
| <Tabs.Tab> | ||||||||||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||||||||||
| import { createBackendClient } from "@pipedream/sdk/server"; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Pipedream's MCP servers can run in two modes: | ||||||||||||||||||||||||||||||||
| // Initialize the Pipedream client with the SDK | ||||||||||||||||||||||||||||||||
| const pd = createBackendClient({ | ||||||||||||||||||||||||||||||||
| environment: PIPEDREAM_ENVIRONMENT, | ||||||||||||||||||||||||||||||||
| credentials: { | ||||||||||||||||||||||||||||||||
| clientId: PIPEDREAM_CLIENT_ID, | ||||||||||||||||||||||||||||||||
| clientSecret: PIPEDREAM_CLIENT_SECRET, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| projectId: PIPEDREAM_PROJECT_ID | ||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### Stdio (for local testing) | ||||||||||||||||||||||||||||||||
| // Get access token for MCP server auth | ||||||||||||||||||||||||||||||||
| const accessToken = await pd.rawAccessToken(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| console.log(accessToken); | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| </Tabs.Tab> | ||||||||||||||||||||||||||||||||
| <Tabs.Tab> | ||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| npx @pipedream/mcp stdio --app slack --external-user-id user123 | ||||||||||||||||||||||||||||||||
| curl -s -X POST https://api.pipedream.com/v1/oauth/token \ | ||||||||||||||||||||||||||||||||
| -H "Content-Type: application/json" \ | ||||||||||||||||||||||||||||||||
| -d '{ | ||||||||||||||||||||||||||||||||
| "grant_type": "client_credentials", | ||||||||||||||||||||||||||||||||
| "client_id": "'$PIPEDREAM_CLIENT_ID'", | ||||||||||||||||||||||||||||||||
| "client_secret": "'$PIPEDREAM_CLIENT_SECRET'" | ||||||||||||||||||||||||||||||||
| }' | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
Comment on lines
+139
to
+146
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct quoting in the cURL -curl -s -X POST https://api.pipedream.com/v1/oauth/token \
- -H "Content-Type: application/json" \
- -d '{
- "grant_type": "client_credentials",
- "client_id": "'$PIPEDREAM_CLIENT_ID'",
- "client_secret": "'$PIPEDREAM_CLIENT_SECRET'"
- }'
+curl -s -X POST https://api.pipedream.com/v1/oauth/token \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"grant_type\": \"client_credentials\",
+ \"client_id\": \"${PIPEDREAM_CLIENT_ID}\",
+ \"client_secret\": \"${PIPEDREAM_CLIENT_SECRET}\"
+ }"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| </Tabs.Tab> | ||||||||||||||||||||||||||||||||
| </Tabs> | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Required headers | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Include these headers in every HTTP request: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| Authorization: `Bearer ${PIPEDREAM_ACCESS_TOKEN}`, | ||||||||||||||||||||||||||||||||
| "x-pd-project-id": PIPEDREAM_PROJECT_ID, // proj_xxxxxxx | ||||||||||||||||||||||||||||||||
| "x-pd-environment": PIPEDREAM_ENVIRONMENT // development | production | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+155
to
+159
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clarify header variable references -{
- Authorization: `Bearer ${PIPEDREAM_ACCESS_TOKEN}`,
- "x-pd-project-id": PIPEDREAM_PROJECT_ID,
- "x-pd-environment": PIPEDREAM_ENVIRONMENT // development | production
-}
+{
+ Authorization: `Bearer ${accessToken}`,
+ "x-pd-project-id": process.env.PIPEDREAM_PROJECT_ID,
+ "x-pd-environment": process.env.PIPEDREAM_ENVIRONMENT, // development | production
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ##### SSE (for hosting) | ||||||||||||||||||||||||||||||||
| ### Self-host Pipedream's MCP server | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Using the `Dockerfile` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| If you have Docker installed locally, you can build and run the container from the [reference implementation](https://github.com/PipedreamHQ/pipedream/blob/master/modelcontextprotocol/Dockerfile): | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```console | ||||||||||||||||||||||||||||||||
| > docker build -t pipedream-connect . | ||||||||||||||||||||||||||||||||
| > docker run -d --name pd-mcp -p 3010:3010 --env-file .env pipedream-connect:latest | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| This exposes a generic MCP server at [http://localhost:3010/:external_user_id/:app](http://localhost:3010/:external_user_id/:app). | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Start the server with Streamable HTTP Transport | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| pnpm dev:http | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| You can use the optional env var `PD_SDK_DEBUG` to print out all the requests and responses going to the Connect API: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| PD_SDK_DEBUG=true pnpm dev:http | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Start the server with SSE | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| npx @pipedream/mcp sse | ||||||||||||||||||||||||||||||||
|
|
@@ -46,13 +194,9 @@ This exposes routes at: | |||||||||||||||||||||||||||||||
| - `GET /:external_user_id/:app` - App-specific SSE connection endpoint | ||||||||||||||||||||||||||||||||
| - `POST /:external_user_id/:app/messages` - App-specific message handler | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Where: | ||||||||||||||||||||||||||||||||
| - `:external_user_id` is your user's unique identifier in your system | ||||||||||||||||||||||||||||||||
| - `:app` is the app slug (e.g., "slack", "github") | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Customize for your needs | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| You can host and customize the MCP server for your specific requirements: | ||||||||||||||||||||||||||||||||
| You can also host and customize the MCP server for your specific requirements: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| # Clone the repo | ||||||||||||||||||||||||||||||||
|
|
@@ -71,4 +215,24 @@ npm run start:sse:prod | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| See the [MCP server README](https://github.com/PipedreamHQ/pipedream/blob/master/modelcontextprotocol/README.md) for detailed instructions on customization options. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| </Steps> | ||||||||||||||||||||||||||||||||
| ### Use the MCP inspector | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| The [MCP inspector](https://modelcontextprotocol.io/docs/tools/inspector) can be helpful when debugging tool calls. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||
| npx @modelcontextprotocol/inspector | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Enter the server URL: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| If using Pipedream's remote server: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| https://mcp.pipedream.net/{external_user_id}/{app_slug} | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| If running locally: | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| http://localhost:3010/{external_user_id}/{app_slug} | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix Node.js snippet to read from
process.envand handleawaitcorrectlyAs written, the snippet references bare identifiers (
PIPEDREAM_*) which will causeReferenceError. Also, top-levelawaitrequires an ES module context. Proposed diff:📝 Committable suggestion
🤖 Prompt for AI Agents