This project helps you create your own remote MCP server on Cloudflare with user login and payment options. You don't need to be a technical expert to get it running!
- An MCP server that works with , Cursor, Claude and other AI assistants
- User login with Google or GitHub
- Payment processing with Stripe
- The ability to create both free and paid MCP tools
Before starting, make sure you have:
- Node.js installed (download from nodejs.org)
- A Cloudflare account (sign up at dash.cloudflare.com/sign-up)
- A Google account for setting up login (or GitHub if you prefer)
- A Stripe account for payments (sign up at dashboard.stripe.com/register)
- Clone this repository to your computer:
git clone https://github.com/playbookshq/mcp-boilerplate.git
cd mcp-boilerplate- Install everything needed:
npm install- Install Wrangler (Cloudflare's tool) if you haven't already:
npm install -g wrangler- Create a database for user login:
npx wrangler kv:namespace create "OAUTH_KV"-
After running this command, you'll see some text that includes
idandpreview_idvalues -
Open the
wrangler.jsoncfile in the project folder -
Look for the section with
"kv_namespaces": [ -
Add your database information there:
"kv_namespaces": [
{
"binding": "OAUTH_KV",
"id": "paste-your-id-here",
"preview_id": "paste-your-preview-id-here"
}
]- Create a file for your settings:
cp .dev.vars.example .dev.vars-
Open the
.dev.varsfile in your code editor -
You'll need to add several values here (we'll get them in the next steps)
- Go to the Google Cloud Console
- Create a new project with any name you like
- Go to "APIs & Services" > "Credentials"
- Click "+ CREATE CREDENTIALS" and choose "OAuth client ID"
- If prompted, set up a consent screen:
- Choose "External" for User Type
- Add an App name (like "My AI Tool")
- Add your email address where required
- You can skip the "Scopes" and "Test users" sections
- For the OAuth client:
- Select "Web application" for Application type
- Give it a name
- Under "Authorized redirect URIs" add:
http://localhost:8787/auth/google/callback
- Click "CREATE"
- You'll now see your Client ID and Client Secret - copy these values
- Add them to your
.dev.varsfile:
GOOGLE_CLIENT_ID="paste-your-client-id-here"
GOOGLE_CLIENT_SECRET="paste-your-client-secret-here"Once you've completed this step, you can proceed directly to Step 5 if you don't need GitHub login.
If you prefer to use GitHub for login instead of Google:
- Go to your GitHub account
- Click on your profile picture in the top-right corner, then go to "Settings"
- In the left sidebar, scroll down and click on "Developer settings"
- Click on "OAuth Apps", then click the "New OAuth App" button
- Fill in the form:
- Application name: Give it a name (like "My AI Tool")
- Homepage URL:
http://localhost:8787 - Application description: A brief description of your app (optional)
- Authorization callback URL:
http://localhost:8787/auth/github/callback
- Click "Register application"
- On the next page, you'll see your Client ID
- Click "Generate a new client secret"
- Copy your Client Secret immediately (you won't be able to see it again)
- Add these values to your
.dev.varsfile:
GITHUB_CLIENT_ID="paste-your-client-id-here"
GITHUB_CLIENT_SECRET="paste-your-client-secret-here"- You'll also need to update the default authentication in your code:
- Open
src/index.ts - Find the import for Google handler:
import { GoogleHandler } from "./auth/google-handler"; - Replace it with:
import { GithubHandler } from "./auth/github-handler"; - Find the line with
defaultHandler: GoogleHandler as any, - Change it to:
defaultHandler: GithubHandler as any,
- Open
After completing either Step 4a or 4b, proceed to Step 5.
- Log in to your Stripe Dashboard
- Get your test API key:
- Go to Developers > API keys
- Copy your "Secret key" (it starts with
sk_test_)
- Create a product and price:
- Go to Products > Add Product
- Give it a name and description
- Add a price (this is what users will pay)
- Save the product
- After saving, find and copy the "Price ID" (it starts with
price_)
- Add these values to your
.dev.varsfile:
STRIPE_SECRET_KEY="sk_test_your-key-here"
STRIPE_PRICE_ID="price_your-price-id-here"Make sure your .dev.vars file has all these values:
BASE_URL="http://localhost:8787"
COOKIE_ENCRYPTION_KEY="generate-a-random-string-at-least-32-characters"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
STRIPE_SECRET_KEY="your-stripe-secret-key"
STRIPE_PRICE_ID="your-stripe-price-id"For the COOKIE_ENCRYPTION_KEY, you can generate a random string with this command:
openssl rand -hex 32- Run this command to start your server:
npx wrangler dev-
Your server will start at
http://localhost:8787 -
The main endpoint for AI tools will be at
http://localhost:8787/sse
You can test your server by connecting to it with an AI assistant:
- Go to Cloudflare AI Playground
- Enter your server URL:
http://localhost:8787/sse - You'll be redirected to log in with Google
- After logging in, you can start testing the tools
Or with Claude Desktop:
- Open Claude Desktop
- Go to Settings > Developer > Edit Config
- Add your server:
{
"mcpServers": {
"my_server": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:8787/sse"
]
}
}
}- Restart Claude Desktop
- Your tools should now be available in Claude
Or with MCP Inspector:
- Run MCP Inspector and connect to your server:
npx @modelcontextprotocol/inspector@latest- Enter your server URL:
http://localhost:8787/sse - Use the web interface to test and debug your tools
- You can directly call your tools, see the request/response data, and quickly iterate during development
When you're ready to make your server available online:
- Deploy to Cloudflare:
npx wrangler deploy-
After deployment, you'll get a URL like
https://your-worker-name.your-account.workers.dev -
Update your Google OAuth settings:
- Go back to Google Cloud Console > APIs & Services > Credentials
- Edit your OAuth client
- Add another redirect URI:
https://your-worker-name.your-account.workers.dev/auth/google/callback
-
Add your settings to Cloudflare by running these commands (you'll be prompted to enter each value):
npx wrangler secret put BASE_URL
npx wrangler secret put COOKIE_ENCRYPTION_KEY
npx wrangler secret put GOOGLE_CLIENT_ID
npx wrangler secret put GOOGLE_CLIENT_SECRET
npx wrangler secret put STRIPE_SECRET_KEY
npx wrangler secret put STRIPE_PRICE_IDFor the BASE_URL, use your Cloudflare URL: https://your-worker-name.your-account.workers.dev
You can easily create your own AI tools by adding new files to the src/tools folder. The project comes with examples of both free and paid tools.
To create a free tool (one that users can access without payment):
- Create a new file in the
src/toolsfolder (for example:myTool.ts) - Copy this template from the existing
add.tsexample:
import { z } from "zod";
import { experimental_PaidMcpAgent as PaidMcpAgent } from "@stripe/agent-toolkit/cloudflare";
export function myTool(agent: PaidMcpAgent<Env, any, any>) {
const server = agent.server;
// @ts-ignore
server.tool(
"my_tool_name", // The tool name
"This tool does something cool.", // Description of what your tool does
{ // Input parameters
input1: z.string(), // Parameter definitions using Zod
input2: z.number() // E.g., strings, numbers, booleans
},
async ({ input1, input2 }: { input1: string; input2: number }) => ({
// The function that runs when the tool is called
content: [{ type: "text", text: `You provided: ${input1} and ${input2}` }],
})
);
}-
Modify the code to create your own tool:
- Change the function name (
myTool) - Change the tool name (
my_tool_name) - Update the description
- Define the input parameters your tool needs
- Write the code that runs when the tool is called
- Change the function name (
-
Add your tool to
src/tools/index.ts:
// Add this line with your other exports
export * from './myTool';- Register your tool in
src/index.ts:
// Inside the init() method, add:
tools.myTool(this);To create a tool that requires payment:
- Create a new file in the
src/toolsfolder (for example:myPaidTool.ts) - Copy this template from the existing
bigAdd.tsexample:
import { z } from "zod";
import { experimental_PaidMcpAgent as PaidMcpAgent } from "@stripe/agent-toolkit/cloudflare";
import { REUSABLE_PAYMENT_REASON } from "../helpers/constants";
export function myPaidTool(
agent: PaidMcpAgent<Env, any, any>,
env?: { STRIPE_PRICE_ID: string; BASE_URL: string }
) {
const priceId = env?.STRIPE_PRICE_ID || null;
const baseUrl = env?.BASE_URL || null;
if (!priceId || !baseUrl) {
throw new Error("No env provided");
}
agent.paidTool(
"my_paid_tool_name", // The tool name
{ // Input parameters
input1: z.string(), // Parameter definitions using Zod
input2: z.number() // E.g., strings, numbers, booleans
},
async ({ input1, input2 }: { input1: string; input2: number }) => ({
// The function that runs when the tool is called
content: [{ type: "text", text: `You provided: ${input1} and ${input2}` }],
}),
{
priceId, // Uses the Stripe price ID
successUrl: `${baseUrl}/payment/success`,
paymentReason: REUSABLE_PAYMENT_REASON,
}
);
}-
Modify the code to create your own paid tool:
- Change the function name (
myPaidTool) - Change the tool name (
my_paid_tool_name) - Define the input parameters your tool needs
- Write the code that runs when the tool is called
- Change the function name (
-
Add your tool to
src/tools/index.ts:
// Add this line with your other exports
export * from './myPaidTool';- Register your tool in
src/index.ts:
// Inside the init() method, add:
tools.myPaidTool(this, {
STRIPE_PRICE_ID: this.env.STRIPE_PRICE_ID,
BASE_URL: this.env.BASE_URL
});You can create different paid tools with different Stripe products by creating additional price IDs in your Stripe dashboard and passing them as environment variables.
When a user tries to access a paid tool without having purchased it:
- The server checks if they've already paid
- If not, the AI assistant will automatically prompt them with a checkout link
- After completing payment on Stripe they should be able to use the tool immediately
The basic setup above is all you need to get started. The built-in Stripe integration verifies payments directly when users try to access paid tools - it checks both one-time payments and subscriptions automatically.
Webhooks are completely optional but could be useful for more complex payment scenarios in the future, like:
- Building a customer dashboard to display subscription status
- Implementing usage-based billing with metering
- Creating custom workflows when subscriptions are created or canceled
- Handling refunds and disputes with special logic
If you ever want to add webhook support:
- Go to your Stripe Dashboard > Developers > Webhooks
- Click "Add endpoint"
- For the endpoint URL:
- For local development:
http://localhost:8787/webhooks/stripe - For production:
https://your-worker-name.your-account.workers.dev/webhooks/stripe
- For local development:
- For "Events to send", select events relevant to your needs, such as:
- checkout.session.completed
- invoice.payment_succeeded
- customer.subscription.updated
- After creating the webhook, copy the "Signing secret"
- Add this value to your settings:
- For local development, add to
.dev.vars:
- For local development, add to
STRIPE_WEBHOOK_SECRET="whsec_your-webhook-secret-here"- For production, set it using Wrangler:
npx wrangler secret put STRIPE_WEBHOOK_SECRETIf you get stuck or have questions, check out the more detailed documentation or reach out for support!