Skip to main content
Glama
doitian
by doitian

google-task-ifttt-webhook-mcp

MCP server running on Cloudflare Workers that exposes a create_google_task tool. Sends tasks to Google Tasks via the IFTTT Maker webhook.

Authentication is handled by Cloudflare Access (Managed OAuth). The worker validates the Cf-Access-Jwt-Assertion JWT against Access JWKS.

How it works

MCP Client                  Cloudflare Access          Cloudflare Worker         IFTTT
    |                             |                          |                     |
    |-- OAuth login ------------>|                          |                     |
    |<-- access granted ---------|                          |                     |
    |                             |                          |                     |
    |-- POST /mcp -------------->|-- Cf-Access-Jwt-Assertion->|                    |
    |                             |                          |-- POST JSON ------->|
    |                             |                          |<-- "Congratulations"|
    |<-- result -----------------|<-------------------------|                     |

Related MCP server: Remote MCP Server (Authless)

Prerequisites

  • Node.js 22.18+ (also runs the TypeScript source in the test suite)

  • Cloudflare account with Workers enabled

  • Cloudflare Access (requires Cloudflare Zero Trust)

  • IFTTT account with the Maker Webhooks service connected

  • A Google Tasks applet on IFTTT triggered by a JSON web request event named task

Setup

1. Install dependencies

npm install

2. Get your IFTTT Maker key

  1. Go to IFTTT Maker Webhooks

  2. Click Documentation

  3. Your key is the last path segment of the URL shown: https://maker.ifttt.com/use/{YOUR_KEY}

  4. Set it as a Worker secret:

npx wrangler secret put IFTTT_MAKER_TASK_KEY

3. Set up the IFTTT applet

Create an applet on IFTTT:

  • If: Maker Webhooks → Receive a web request with a JSON payload, event name task

  • Then: Google Tasks → Create a task

    • Title: {{JsonPayload.title}}

    • Notes: {{JsonPayload.notes}}

    • Due date: {{JsonPayload.due}}

The worker posts to:

https://maker.ifttt.com/trigger/task/json/with/key/{KEY}

with a JSON body like { "title": "...", "notes": "...", "due": "..." }.

4. Configure Cloudflare Access

  1. Go to Cloudflare Zero Trust dashboard

  2. Navigate to AccessApplicationsAdd an applicationSelf-hosted

  3. Configure:

    • Application name: google-task-mcp

    • Application domain: your worker hostname (custom domain or *.workers.dev)

    • Identity providers: Select your preferred IdP (Google, GitHub, email OTP, etc.)

    • Policy: Create an allow policy for the users who should access the MCP server

    • Managed OAuth (Beta): Must be enabled

  4. Note your team domain (e.g. myteam.cloudflareaccess.com) and the Application Audience (AUD) tag

  5. Set them as Worker secrets:

npx wrangler secret put CF_ACCESS_TEAM_DOMAIN
npx wrangler secret put CF_ACCESS_AUD

CF_ACCESS_AUD is optional but recommended (enables audience validation on the JWT).

5. Deploy

npm run deploy

6. Test locally (optional)

npm run dev

The worker is available at http://localhost:8787. When CF_ACCESS_TEAM_DOMAIN is unset, any present Cf-Access-Jwt-Assertion header is accepted (use a dummy value for local calls).

Run the local checks with:

npm run typecheck
npm test

The tests use signed fixture JWTs and mocked JWKS responses to check authentication, routing, and capability discovery. They do not contact Cloudflare or IFTTT.

7. Configure the MCP client

Point the client at the worker URL (prefer /mcp; / and /mcp/ are also accepted without redirects). Auth is Cloudflare Access Managed OAuth — the client completes Access login; Access injects Cf-Access-Jwt-Assertion on requests to the worker.

The worker uses JSON responses over Streamable HTTP with protocol version 2025-06-18. Initialization returns that supported version even if a client requests another version; the client must support it to continue. No session ID is required. There is no legacy SSE endpoint. An authenticated GET returns HTTP 405, which is allowed for servers without a standalone stream by the Streamable HTTP specification.

Cloudflare MCP Portal

Set the upstream HTTP URL to:

https://google-task-ifttt-webhook-mcp.doitian.workers.dev/mcp

After saving, select Sync capabilities. Cloudflare documents that URLs ending in /mcp use Streamable HTTP directly; other URL patterns can trigger SSE fallback. See Cloudflare's transport and troubleshooting documentation.

opencode

{
  "mcp": {
    "google-tasks": {
      "type": "remote",
      "url": "https://google-task-mcp.yourdomain.com/mcp",
      "oauth": {}
    }
  }
}

Claude Desktop / other streamable HTTP clients

Use your client's remote MCP + OAuth settings with:

https://google-task-mcp.yourdomain.com/mcp

Tool: create_google_task

Parameter

Required

Description

title

yes

Single-line task title

notes

no

Optional detailed notes. \n for line breaks

due

no

Optional due date in ISO 8601 UTC (e.g. 2026-07-25T23:59:59Z)

Example MCP call

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_google_task",
    "arguments": {
      "title": "Buy groceries",
      "notes": "Milk, eggs, bread",
      "due": "2026-07-25T23:59:59Z"
    }
  }
}

Secrets / env

Name

Required

Description

IFTTT_MAKER_TASK_KEY

yes

IFTTT Maker Webhooks key

CF_ACCESS_TEAM_DOMAIN

prod

Cloudflare Zero Trust team domain (e.g. myteam.cloudflareaccess.com). Omit locally to skip JWKS verification

CF_ACCESS_AUD

no

Access application audience tag (enables audience validation)

ICON_URL

no

Override the default server icon URL returned on initialize

Set secrets via:

npx wrangler secret put <NAME>

Endpoints

Method

Path

Description

POST

/, /mcp, or /mcp/

MCP JSON-RPC (requires valid Cf-Access-Jwt-Assertion)

GET, DELETE

/, /mcp, or /mcp/

HTTP 405 after authentication; no SSE stream or session deletion

OPTIONS

*

CORS preflight

Supported MCP methods: initialize, notifications/initialized, ping, tools/list, tools/call.

Notifications receive an empty HTTP 202 response. Unsupported RPC methods return JSON-RPC -32601 over HTTP 200; HTTP 404 is reserved for unknown paths.

Troubleshooting

Portal reports Not found: /mcp/sse

Earlier versions rejected /mcp/ before JWT validation. Use the exact /mcp URL above and sync capabilities, or deploy this version to also accept /mcp/. The /mcp/sse error is consistent with the portal exhausting its transport fallbacks, but does not reveal which earlier request failed. This worker does not implement legacy SSE, so /mcp/sse should still return 404.

If syncing still fails, inspect the server status hover or API error_details (status_code, mcp_code, and cause) and correlate with Worker request logs. An unauthenticated HTTP 401 from Cloudflare Access is expected and does not test the authenticated Worker handshake. A successful local test also does not verify the deployed server or the portal's OAuth credentials.

"Unauthorized: Cloudflare Access authentication required"

Missing or invalid Cf-Access-Jwt-Assertion. Ensure Access protects the worker hostname, Managed OAuth is enabled, and the client completed Access login. Locally, send any non-empty Cf-Access-Jwt-Assertion header when CF_ACCESS_TEAM_DOMAIN is unset.

"IFTTT webhook failed (HTTP 404)"

The Maker key is invalid or no applet listens for event task. Verify the key and applet event name.

"IFTTT_MAKER_TASK_KEY is not configured on the server."

npx wrangler secret put IFTTT_MAKER_TASK_KEY

Then redeploy.

JWT verification failures in production

Confirm CF_ACCESS_TEAM_DOMAIN matches your team domain exactly (hostname only, or full https://… URL). If set, CF_ACCESS_AUD must match the Access application AUD tag.

Related MCP Connectors

Related MCP Servers