Secureflows Mcp

io.github.michal-leflerPublished by GitHub account michal-leflerv0.2.0Updated Nov 2, 2026

MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.

VerifiedStreamable HTTPWeb executableKnowledge & MemoryDeveloper ToolsSecurity & Monitoring

Overview

AI-generated overview

Hosted secureFlows MCP server that gives coding agents token-free login/logout URL builders, an integration linter, and wrapped secureFlows session and docs…

What you can do
  • Build correct hosted-login and redirect-logout URLs, and lint generated app source against secureFlows integration rules (no token needed)
  • Create, get, renew, revoke and get-or-create sessions, and read the session identity
  • Read, set and delete keys in the encrypted session payload, and list or revoke the caller's own sessions
  • Search the public secureFlows documentation index
  • Run a read-only security-review prompt over a project's user-account handling
When to use it
Use it while scaffolding a secureFlows integration in an app, where the URL builders and linter catch redirect, token-lifecycle and error-handling mistakes before a session exists. Also useful for scripted or test automation that already holds a Firebase or session token and needs to drive the session API.
Requirements
A remote MCP endpoint at the secureFlows host under the /mcp path; no local install or npm package is needed. Each call supplies connection.host, optional connection.workspaceName and connection.appId, and whichever token the endpoint needs (auth.firebaseToken, auth.sessionToken or auth.userToken). Documentation search needs no token.
Before you install
Session tools take Firebase ID tokens and session tokens as tool inputs, and the server forwards them to the secureFlows backend. Revoke tools permanently destroy a session and everything stored in it, and are not the same as signing out. The linter is heuristic text analysis, not a parser or type checker, so a clean result is not proof of a correct integration.

Installation

In SourceWeft

  1. Open Secureflows Mcp in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.michal-lefler%2Fsecureflows-mcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "secureflows": {
      "type": "http",
      "url": "https://www.secure-flows.com/mcp"
    }
  }
}

README

secureFlows MCP Server

[secureFlows] [CI]

Cloud-deployable MCP server that wraps the secureFlows OpenAPI surface tagged ai-safe and ai-optional.

This repo is a public mirror, published periodically from the private secureFlows monorepo where development actually happens. Issues and PRs are welcome; large changes may take a release cycle to land upstream first.

What is an MCP server?

An MCP server is a small HTTP service that exposes a set of “tools” an AI client can call in a standard way.

In this repo:

  • The secureFlows MCP server exposes tools that are auto-generated from your OpenAPI YAML specs.
  • When a client calls a tool, the MCP server forwards the call to your real secureFlows backend (connection.host) and returns the response in a normalized tool result.

This lets an AI client:

  • discover available secureFlows operations via listTools
  • call them via callTool
  • without hardcoding the API surface or manual auth/header wiring

What it does

Two kinds of tools, registered together in src/server.ts:

Generated tools (src/tools/build-tools.ts) — one per OpenAPI operation:

  • Loads:
    • docs/openapi/session/secure-flows-session-api.yaml
    • docs/openapi/user/secure-flows-user-api.yaml
    • docs/openapi/docs/secure-flows-docs-api.yaml
  • Exposes only operations tagged ai-safe or ai-optional as MCP tools
  • Forwards requests to a caller-provided secureFlows host — a thin, generic HTTP wrapper with no secureFlows-specific judgment. Every one of these requires a live auth.* token, so they're only useful once a session already exists (see Runtime model below).
  • Maps secureFlows auth headers from MCP tool inputs:
    • auth.firebaseToken
    • auth.sessionToken
    • auth.userToken

Static tools (src/tools/static-tools.ts) — hand-written, not generated from the spec:

  • secureflows_build_login_url / secureflows_build_logout_url — build the hosted-login and redirect-logout URLs correctly by construction (always /app/sessions/login, never the legacy /app/login; refuses a post-logout redirect_uri that points at /callback or leaks session_token). No secureFlows token required.

  • secureflows_lint_integration — checks generated app source against the integration rules and reports structured findings instead of leaving them as prose the agent has to self-police. No secureFlows token required. Two kinds of finding:

    • scope: "file" — a forbidden construct is present, at an exact file:line: env-var config constants, token in localStorage, legacy /app/login, fetch/XHR logout, client-side JWT decode, revoke-on-sign-out, empty catch {}, restore setSession(null) on non-auth errors, Continue CTA gated on session === null, …
    • scope: "project" — required handling is absent across every file passed in: detecting 401/410 but never clearing the token, never handling 403, or handling 403 without the BILLING_GRACE_LOCK carve-out.

    The absence checks exist because the pattern rules structurally could not catch the defect class that dominates real generated apps. Measured: on a real trial's app that the eval harness's LLM judge scored 4/10 — citing "stale token never cleared on signed-out", "403 variants unhandled", "no error handling" — the pattern rules alone produced zero findings, because every one of those bugs is an absence, and a regex can only see what is present. With the absence checks it produces 3, including the error-severity token-clearing one. Both check kinds are validated against the canonical templates/web-app-secureflows starter, which must stay at zero findings.

    Still heuristic text analysis, not a parser or type checker: it misses what it has no rule for, a project check can be satisfied by the right keyword in the wrong place, and it cannot cover the checks that need a running app (auth-guard mount races, the fresh-reload check). A fast first pass — not a replacement for the Agent implementation checklist in SKILL.md.

These static tools exist because the generated tools can't help with the part of an integration that happens before a session exists — scaffolding the redirect/callback/token-lifecycle code — which is exactly where most secureFlows integration mistakes happen.

Prompt (src/prompts/security-review.ts) — one MCP prompt, security-review. It asks the agent to review how the current project manages user accounts, list the security gaps, grade each one against secureFlows, and write a migration plan. Read-only, no secureFlows token required. The same text ships as the Claude Code plugin skill skills/security-review (run it with /secureflows:security-review) and as the copy-paste prompt on https://www.secure-flows.com/docs/getting-started/security-review/. The TypeScript constant is the source; test/security-review-prompt.test.ts fails if either copy drifts from it.

Uses a stateless HTTP MCP transport, so the server does not persist tenant config or secrets.

Runtime model

Each tool call receives:

  • connection.host: secureFlows base URL
  • connection.workspaceName: optional default workspace
  • connection.appId: optional default application id
  • auth.*: whichever token the selected endpoint needs

workspaceName and appId are treated as stable app config. The server injects them into known secureFlows request shapes when omitted by the caller.

For agents (the only supported client path)

Point the MCP client at the hosted URL — same host as the product, path /mcp (not a subdomain):

EnvironmentMCP URL
Productionhttps://www.secure-flows.com/mcp
Staginghttps://secure-flows-staging.onrender.com/mcp
Health…/mcp/health → {"ok":true}
json
{  "mcpServers": {    "secureflows": {      "url": "https://www.secure-flows.com/mcp"    }  }}

Do not tell agents to run npx or use localhost — that splits the story and breaks anyone who never starts a local process. Wired in the web Docker image (Node on 127.0.0.1:8787, nginx location = /mcp; see docs/ROUTING.md). The Node process installs uncaughtException / unhandledRejection guards so a single bad request does not exit the process; docker/entrypoint.sh also restarts MCP if the process still exits.

Claude Code plugin

This repo is also a Claude Code plugin. It connects the hosted MCP server above (.mcp.json) and adds two skills: secureflows-integration and security-review. In Claude Code:

/plugin marketplace add michal-lefler/secureflows-mcp/plugin install secureflows@secureflows-marketplace

Then run /secureflows:security-review in any project for a read-only review of its user management.

Local development (maintainers of this package)

bash
cd mcp-servernpm installnpm run buildnpm testnpm run dev

The server starts on http://0.0.0.0:8787 by default (POST /mcp, GET /health). This is for changing the MCP server itself — not the path product agents should configure.

Environment variables

  • PORT: HTTP port, default 8787 (in the web container, entrypoint sets PORT=8787 only for the MCP child so nginx keeps Render’s public $PORT)
  • HOST: bind host, default 0.0.0.0 (web container uses 127.0.0.1)
  • ALLOWED_HOSTS: optional comma-separated host allowlist for MCP host header validation
  • MCP_ALLOWED_HOSTS: entrypoint override for ALLOWED_HOSTS when starting the in-image process

Endpoints

  • POST /mcp: MCP Streamable HTTP endpoint
  • GET /health: health check (publicly exposed as GET /mcp/health via nginx)

Embedding secureFlows in an application

Product apps integrate directly with secureFlows HTTP APIs and hosted login. Start from:

  • docs/integration/quickstart.md — provisioning (workspace + application) and runtime hosted login
  • docs/integration/CONCEPT.md — baseline order: login → create workspace before advanced features
  • docs/openapi/integration-auth.yaml — /app/sessions/login (session apps) vs /app/login (legacy/console)

Product apps still integrate directly with the HTTP APIs above, not through this server. The generated tools here are for agents/automation that already have a token (testing, scripted verification). The static tools (secureflows_build_login_url, secureflows_build_logout_url, secureflows_lint_integration) need no token and are meant to be called by a coding agent while it's still scaffolding the integration — see What it does above.

Testing this MCP server

  1. npm test in mcp-server/ — unit tests plus HTTP smoke (test/http-smoke.test.ts): starts the Express app on an ephemeral port, checks GET /health, GET /mcp → 405, and a real Streamable-HTTP client listTools + callTool(secureflows_build_login_url).
  2. After deploy: Playwright tests/smoke/mcp-health.spec.ts hits public GET /mcp/health and GET /mcp on the target host (production smoke job).
  3. Local maintainer loop: npm run dev, then curl -sS http://127.0.0.1:8787/health.
  4. Optional: MCP client against POST /mcp with connection.host + auth.* for generated tools.

Plugin distribution is covered by npm test too (offline; monorepo-only checks skip themselves in the public mirror):

  • test/plugin-distribution.test.ts — manifests, the hosted .mcp.json destination, the install commands on the docs pages and README, and the sync-public-mirrors CI job (tag-only, waits for the npm publishes, secrets: inherit, token only in the step env).
  • test/mirror-sync.test.ts — runs the real scripts/sync-public-mirrors.mjs --commit --push against a local bare git repo and checks what a stranger would receive: plugin, marketplace, skills, hosted .mcp.json, registry server.json, idempotent re-run, deletions propagate.
  • npm run test:live (opt-in, SECUREFLOWS_LIVE_MCP=1) — connects to the URL in .mcp.json and lists the tools; add SECUREFLOWS_LIVE_MCP_PROMPTS=1 to also require the security-review prompt. Run it after a deploy (or with SECUREFLOWS_LIVE_MCP_URL for staging). Not part of npm test, so CI stays offline.

What none of this can check: the real push with MIRRORS_PUSH_TOKEN (first run of the workflow on GitHub) and a real /plugin marketplace add from a clean Claude Code install.

Deployment

Shipped inside the web Docker image and proxied at /mcp on www.secure-flows.com / staging (see For agents above). No separate subdomain.

The npm package secureflows is how CI publishes a versioned artifact (and how a standalone container can be built from mcp-server/Dockerfile); it is not the agent-facing setup path. Publish on v*.*.* tags via .github/workflows/publish-secureflows-mcp-server.yml.

bash
docker build -f mcp-server/Dockerfile -t secureflows-mcp-server .docker run --rm -p 8787:8787 secureflows-mcp-server

Notes

  • Hosted login / redirect endpoints are exposed only if they are tagged ai-safe or ai-optional in the OpenAPI specs.
  • Documentation search (get_docs_search) is ai-safe, requires no auth.* — only connection.host and query q.
  • Human-only admin console APIs are intentionally excluded.
  • The response payload from each tool includes:
    • status
    • ok
    • url
    • headers
    • data

Source: README.md at commit 4c2185c

Tools

18

get_sessions

Get the current session payload

Returns the decrypted session payload for the authenticated internal session token. Response shape is a **flat JSON object**. Empty payload returns `{}`. Source: GET /api/v1/sessions Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsconnectionrequired

post_sessions

Create a new session

Verifies **Firebase** ID token, creates a session for **`workspaceName`**, stores serialized **`payload`** (defaults to `{}` when omitted), and returns **`sessionToken`** (JWT; subject = internal session id). Default server-side TTL is **1 hour** (implementation detail). If the Firebase token includes **`email`**, the server best-effort persists it on the workspace end-user row (for audit display). Prefer **`POST /sessions/get-or-create`** for hosted-login-style flows that should reuse an active session. Source: POST /api/v1/sessions Requires `auth.firebaseToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyrequiredqueryparamsconnectionrequired

get_sessions_identity

Get signed-in user's stable id and email (app UI, backend correlation)

Returns the workspace end-user's **`userId`** and **email** for the authenticated session token. Does not return Firebase UID or session payload. `userId` is a stable, opaque identifier for this person across sessions and logins — it is **not** derived from Firebase. Use it as the correlation key when your own backend needs to link an external event (e.g. a billing provider webhook you receive and verify yourself) back to this user. Do not use the session token or session id for this — sessions expire and rotate, `userId` does not. Email is best-effort from hosted login (Firebase `email` claim persisted on the user row). When unknown, `email` is `null`. Browser SDK: **`secureflows-js`** **`fetchSessionIdentity(token)`** (≥ 0.1.15 for `userId`). Source: GET /api/v1/sessions/identity Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsconnectionrequired

post_sessions_get_or_create

Reuse active session or create one

Verifies **Firebase** ID token. If an **active** session already exists for **`(workspaceName, Firebase UID, app_id)`**, returns a new **`sessionToken`** JWT for the **most recently created** matching row (touches activity; does not create a duplicate session). The request **`payload` is ignored on reuse** — it is applied only when a new session row is created. Prefer a dedicated `app_id` per integration surface, or revoke old sessions, if you need a fresh payload. Otherwise behaves like **`POST /sessions`** (new row + default **1 hour** TTL). If the Firebase token includes **`email`**, the server best-effort persists or backfills it on the workspace end-user row (including when reusing an existing session). Intended for integrators that mirror hosted login session reuse. Source: POST /api/v1/sessions/get-or-create Requires `auth.firebaseToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyrequiredqueryparamsconnectionrequired

post_sessions_renew_session_token

Renew session JWT (replace expired token)

Verifies **Firebase** ID token. Parses **`sessionToken`** path segment as an internal SESSION JWT **without enforcing JWT expiry** (signature and `tokenType=SESSION` are still validated). Loads the session by id from the token subject; the Firebase UID must match the session owner. Increments **`tokenRevision`** on the server so **previous session JWTs** (same session id, older revision) are no longer accepted for `GET/POST/DELETE /sessions/...`. Returns a **new `sessionToken`** (with the new `tokenRevision` claim) and the current decrypted **payload**; extends server-side session expiry by **1 hour**. If the Firebase token includes **`email`**, the server best-effort backfills it on the session owner when the user row has no email yet (audit display only). Use the path form `POST /api/v1/sessions/renew/{sessionToken}` — **URL-encode** the JWT (e.g. `encodeURIComponent` in JS). Source: POST /api/v1/sessions/renew/{sessionToken} Requires `auth.firebaseToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsrequiredconnectionrequired

post_sessions_set_key

Set a value inside the session payload

Sets a key in the encrypted session payload and returns the updated decrypted payload. If the JSON body is `{ "value": <x> }`, the server unwraps it and stores `<x>` directly. Source: POST /api/v1/sessions/set/{key} Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyrequiredqueryparamsrequiredconnectionrequired

get_sessions_get_key

Get a single value from the session payload

Retrieves the decrypted payload value for `key`. **Important:** `404` means the key was never written (normal first-use case). Do not treat as an error. Source: GET /api/v1/sessions/get/{key} Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsrequiredconnectionrequired

delete_sessions_delete_key

Delete a key from the session payload

Removes `key` from the session payload and returns `true` if the key existed. Source: DELETE /api/v1/sessions/delete/{key} Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsrequiredconnectionrequired

post_sessions_revoke

Revoke the current session and destroy its data (by session token) - not sign-out

Permanently revokes the session referenced by the internal SESSION Bearer token. The session ends and everything stored in it is destroyed and cannot be restored. This is NOT sign-out: to sign a user out and keep their data, use POST /api/v1/auth/logout (or, in a browser, the redirect helper GET /api/v1/auth/logout). Call revoke only when the user or an admin deliberately wants the session and its data deleted, for example on account deletion. Source: POST /api/v1/sessions/revoke Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsconnectionrequired

auth_session_callback

Session login callback (redirect)

**Browser redirect endpoint** used after hosted `/app/sessions/login`. No `Authorization` header. 1. Verifies **`firebaseToken`** (Firebase ID token). 2. Ensures **`client_redirect_uri`** is allowlisted for **`app_id`** (same rules as `validate-redirect`). 3. **Create vs renew:** If **`session_token`** is absent, **reuses the newest active session** for **`(workspace_name, Firebase UID, app_id)`** or **creates** one (`get-or-create`). Optional **`payload`** (URL-encoded JSON **object**, default `{}`) is stored **only on create** — ignored when reusing an existing session. If **`session_token`** is present (previous session JWT, may be expired), **renews** that session; **`payload`** must **not** be sent on the same request. Optional **`ttl_seconds`** applies to both paths (default **0** = unlimited; otherwise **60–604800**). When the Firebase token includes **`email`**, the server best-effort persists or backfills it on the workspace end-user row (audit display only). 4. Responds with **`302 Found`** to `client_redirect_uri` with query params **`sessionToken`** and, if provided, **`state`**. If **`client_redirect_uri`** is not allowed for **`app_id`**, responds **`400`** and does **not** redirect (open-redirect mitigation). Other failures return an HTTP error status with a JSON **`{"status", "error"}`** body and do **not** redirect. Source: GET /api/v1/auth/callback No Authorization header is required. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryrequiredparamsconnectionrequired

get_auth_logout

Log out (browser redirect helper; first-party cookie clearing)

Browser-friendly logout endpoint for **cross-site** clients (e.g. apps running on `localhost`). Use this as a **top-level navigation** (not XHR/fetch) so `Clear-Site-Data` is applied in a **first-party** context on `secure-flows.com`, making cookie/session clearing reliable even when third-party cookies are blocked. **Critical client rules:** - Clear your in-app `sessionToken` state **before** navigating. - **Never** include `session_token` inside `redirect_uri` (that would silently renew and defeat logout). This endpoint (best-effort / idempotent for browser UX): - Invalidates the provided `session_token` by incrementing `tokenRevision` when the token still matches an **active** session (no new token is issued). - If the session is already expired/revoked or the revision was superseded by renew, still completes logout UX (does **not** return 401 solely for that reason). - Revokes Firebase refresh tokens for the session’s stored Firebase UID when known. - Sets `Clear-Site-Data: "cookies"`. - Redirects the browser to `redirect_uri`. Source: GET /api/v1/auth/logout No Authorization header is required. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryrequiredparamsconnectionrequired

post_auth_logout

Log out (invalidate sessionToken + revoke Firebase refresh tokens)

Logs out the current session **without revoking** it. **Browser warning:** calling this endpoint via XHR/fetch from a different origin than `secure-flows.com` is not a reliable way to clear hosted-login cookies. For browser apps (especially localhost), prefer the redirect helper `GET /api/v1/auth/logout?session_token=...&redirect_uri=...`. Behavior: - **Invalidates** the current `sessionToken` by incrementing `tokenRevision` (no new token is issued). - Calls Firebase `revokeRefreshTokens(firebaseUid)` using the session’s stored Firebase UID. - Sets `Clear-Site-Data: "cookies"` to clear browser cookies (including Firebase session cookie). Session payload and session row are **not** deleted or modified (other than `tokenRevision`). Source: POST /api/v1/auth/logout Requires `auth.sessionToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsconnectionrequired

get_sessions_my

List my sessions (paged, sortable, filterable)

Returns a page of sessions for the current user within the current workspace. Self-service dashboard endpoint — requires workspace **`enableSelfService: true`**. Payload is included only for rows whose computed status is active. Sort keys match the admin workspace session list; `pageSize` is clamped to 1–200 (default 20). Source: GET /api/v1/sessions/my Requires `auth.userToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryrequiredparamsconnectionrequired

post_sessions_revoke_session_id

Revoke a session owned by the current user

Self-service dashboard endpoint. Revokes a session owned by the caller in the current workspace. The session ends and its stored data is destroyed permanently; this is not sign-out. Requires workspace **`enableSelfService: true`**. Source: POST /api/v1/sessions/revoke/{sessionId} Requires `auth.userToken` and forwards it as a Bearer token. Prefer connection.workspaceName and connection.appId as stable config instead of generating identity fields dynamically.

Parametersauthbodyqueryparamsrequiredconnectionrequired

secureflows_build_login_url

Build secureFlows hosted login URL

Builds a correct hosted-login redirect URL. Needs no secureFlows token — safe to call at app-scaffolding time, before any user session exists, which is the phase most secureFlows integration mistakes happen in. Always targets /app/sessions/login (session apps). Never builds the legacy /app/login console URL, which returns a firebaseToken your SecureFlowsCallback handler cannot consume and causes an infinite redirect loop. Use this instead of hand-building the URL with URLSearchParams — hand-built login URLs are the #1 source of the login-loop and stale-renewal bugs documented in SKILL.md.

ParametersappIdrequiredintentoriginredirectUrirequiredexpiredTokenworkspaceNamerequired

secureflows_build_logout_url

Build secureFlows redirect-logout URL

Builds a correct redirect-logout URL and refuses to build one that violates the two documented logout anti-patterns: a redirect_uri pointing at /callback (SPA callback handlers treat the tokenless return as a failed login and loop), and a redirect_uri that itself embeds session_token (silently renews the old session instead of signing out). The result always instructs top-level navigation, never fetch/XHR — cross-site fetch() to this endpoint gets a 200 but browsers silently ignore its Clear-Site-Data header on cross-site responses, so the hosted-login cookie survives and the user silently re-authenticates on the next login redirect. This tool never builds a revoke request: revoke permanently destroys the user's data and must only run on an explicit "delete my account" action, never on ordinary sign-out.

ParametersoriginsessionTokenrequiredpostLogoutRedirectUrirequired

secureflows_lint_integration

Static-scan generated code for secureFlows anti-patterns

Checks source you already generated against the secureFlows integration rules. Needs no secureFlows token; safe at scaffolding time. Pass every auth/session-related file in one call — some checks are evaluated across the whole set. Two kinds of findings: • scope "file" — a forbidden construct is present (localStorage token, legacy /app/login, fetch-based logout, client-side JWT decode, empty catch, restore non-auth errors clearing session UI, Continue CTA gated on null session, ...), reported at an exact file:line. • scope "project" — REQUIRED handling is missing everywhere you passed in: detecting 401/410 but never clearing the token, never handling 403, or handling 403 without the BILLING_GRACE_LOCK carve-out. These are the defects that actually dominate real generated apps, and no "forbidden pattern" check can see them, because the bug is an absence. Heuristic text analysis, not a parser or a type checker. It can miss things it has no rule for, and a project check can be satisfied by the right keyword in the wrong place. It is a fast first pass — not a substitute for the Agent implementation checklist in SKILL.md, and specifically not for the checks that need a running app (auth-guard mount races, the fresh-reload check). Fix every "error" before calling an integration done; treat "needs_review" as a lead.

Parametersfilesrequired

Version history

1
  1. v0.2.0LatestSep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts