Skip to main content
Glama
README.md
# flowya-mcp

Hosted, multi-tenant [MCP](https://modelcontextprotocol.io) server that exposes each Flowya user's tasks, spaces, and weekly goals to AI clients (Cursor, Claude, Cowork).

It is a thin tool layer over the same Supabase database Flowya's macOS/iOS apps use. Every request is scoped to the calling user, so it is safe to run one shared endpoint for all users.

## How it works

```
AI client (Cursor / Claude / Cowork)
   │  HTTPS POST /mcp  +  Authorization: Bearer fmcp_...
   ▼
flowya-mcp (Vercel)  ──service role + per-user ownership checks──▶  Supabase
```

- **Transport:** Streamable HTTP at `POST /mcp` (stateless: a fresh MCP server per request). A local `stdio` entrypoint exists for development.
- **Auth (v1):** Personal Access Tokens (PAT, prefix `fmcp_`). A user generates one from Flowya ("Connect with AI"); the client sends it as a Bearer token. See [`src/auth.ts`](src/auth.ts).
- **Isolation:** the server uses the Supabase service role but scopes every query by the verified `user_id` and checks resource ownership (spaces/todos/goals) before any read or write. See [`src/api/`](src/api).

## Tools

| Tool | Description |
|---|---|
| `list_spaces` | List the user's spaces (fronts) |
| `get_tasks` | List tasks with filters (space, status, priority, archived, due dates) |
| `create_task` | Create a task in a space |
| `update_task` | Partial update (status changes set started_at/completed_at) |
| `reorder_tasks` | Set task order/positions |
| `archive_task` | Soft-delete a task |
| `get_weekly_goals` | Current week's goals (optionally last week too) |
| `set_weekly_goals` | Replace the current week's goals |
| `link_goal_to_tasks` | Attach tasks to a weekly goal |

The server also declares instructions so agents treat Flowya as the single source of truth for tasks and prioritize by impact on goals.

## Setup

1. Install: `npm install`
2. Create `.env` from [`.env.example`](.env.example):
   - `FLOWYA_SUPABASE_URL`, `FLOWYA_SUPABASE_ANON_KEY` — same values Flowya uses (`VITE_SUPABASE_URL` / `VITE_SUPABASE_ANON_KEY`).
   - `SUPABASE_SERVICE_ROLE` — the project's service role key (server only).
3. Apply the token table migration to the Supabase project:
   `Flowya-MacOS/supabase/migrations/create_mcp_tokens_table.sql`
4. Typecheck/build: `npm run typecheck` / `npm run build`

## Run locally

- HTTP server: `npm run start` (defaults to `:8787`). Health: `GET /health`.
- Stdio (dev, no token — acts as one user): set `FLOWYA_DEV_USER_ID` and run `npm run mcp`.

## Deploy (Vercel)

The repo is Vercel-ready:
- [`vercel.json`](vercel.json) builds `dist/` via `tsc` and routes all traffic to [`api/index.js`](api/index.js), which calls the shared `dispatch` from `dist/http.js`.
- Set env vars in the Vercel project: `FLOWYA_SUPABASE_URL`, `FLOWYA_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE`, `PUBLIC_API_URL` (the deployed URL).
- Deployment protection (Vercel Authentication / SSO) must be OFF so the `/mcp` endpoint is publicly reachable.
- Optional: point a custom domain (e.g. `mcp.flowya.app`) at the deployment.

Currently deployed at **https://flowya-mcp.vercel.app** (MCP endpoint: `https://flowya-mcp.vercel.app/mcp`).

```bash
vercel --prod   # from this directory, after `vercel link`
```

## How a user connects

1. In Flowya, open Settings → **Connect with AI** and generate a token (`fmcp_...`). It is shown once.
2. Add the remote MCP server to their client with the URL `https://flowya-mcp.vercel.app/mcp` and header `Authorization: Bearer fmcp_...`.

Example Cursor `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "flowya": {
      "url": "https://flowya-mcp.vercel.app/mcp",
      "headers": { "Authorization": "Bearer fmcp_YOUR_TOKEN" }
    }
  }
}
```

The Flowya desktop app talks to this server's `/v1/tokens` endpoints (authenticated with the user's Supabase session) to create, list, and revoke tokens. Set `VITE_FLOWYA_MCP_URL` in Flowya-MacOS if the MCP is not at the default `https://flowya-mcp.vercel.app`.

## Roadmap (v2)

OAuth 2.1 (dynamic client registration + PKCE) for a one-click "Connect" experience, replacing manual token paste. The transport, tools, and `api/` layer are reused unchanged; only an OAuth token-issuance layer and a consent page are added.