# PassFast

> Remote HTTPS MCP for Apple + Google Wallet passes. Paste sk_live_ once.

- name: st.passfa/passfast
- version: 1.0.0
- connection class: R1 (autonomous)
- trust: 96/100
- quality: 82/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/st.passfa%2Fpassfast
- tools: https://api.protogrid.dev/v1/servers/st.passfa%2Fpassfast/tools

**An agent can connect on its own if it already holds `PASSFAST_TOKEN`.** Remote endpoint behind a static API key or header. The registry never sees the value; the agent fills the placeholder.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "passfast": {
      "type": "http",
      "url": "https://passfa.st/mcp",
      "headers": {
        "Authorization": "Bearer ${PASSFAST_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${PASSFAST_TOKEN}`.

## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 85
- drivers: +repository +dns-namespace +website +reachable +uptime-100% +updated-30d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 82/100 (good)

### protocol: 75 (weight 25)

- warn `protocol.modern`: newest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
- n/a `protocol.stateless`: only applies to 2026-07-28 servers
- pass `protocol.transport`: streamable HTTP
- n/a `protocol.list_ttl`: only applies to 2026-07-28 servers

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 1 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 47 of 47 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- fail `tools.token_cost`: about 25,347 tokens to load every tool, a large share of an agent's context
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 100 (weight 15)

- pass `stability.changes`: no tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 47, about 25,347 tokens to load them all
- tool set hash: 3f9aae02d5c432bb18515627a575ae64
- badge: [![protogrid quality](https://protogrid.dev/badge/st.passfa/passfast.svg)](https://protogrid.dev/servers/st.passfa/passfast)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

_No tool definition changes recorded._

## Remotes

- https://passfa.st/mcp (streamable-http, auth api_key ${PASSFAST_TOKEN}, reachable true, uptime30d 1)

## Packages

_none_

## Tools (47)

- `batchGeneratePasses`: Batch generate wallet passes

Generate up to 100 wallet passes in one **synchronous** request.
Each accepted row is one `POST /generate-pass` (same free-100 and
card-on-file gates as a single generate). Optional
`POST /share-pass/create` per successful row when `create_share_links`
is true (default).

**Host:** `https://passfa.st/api/passes/batch` (site / Vercel preview).
This is not an `api.passfa.st` Edge Function. MCP tool:
`batchGeneratePasses` (secret key `sk_live_` only) — same path and
body as this operation.

**Auth:** `Authorization: Bearer sk_live_…` or `pk_live_…` (scope
`passes:create`). A Supabase user JWT is also accepted (dashboard
session). Send `X-App-Id` for multi-app orgs and `X-Org-Id` as
elsewhere.

**Body:** mapped `rows` (same shape the dashboard posts) **or** raw
`csv` plus optional `column_map`. Do not send both.

**Limits:** more than 100 rows → `400 row_limit_exceeded` **before**
any generate. Empty body / empty CSV → `400 empty_batch` or
`invalid_csv`. Bad template → `400 invalid_template`. Missing or
invalid Bearer → `401 unauthorized`.

**Billing:** a row that hits the free-100 / card gate returns the same
`402` codes as generate-pass (`free_limit_reached`,
`subscription_canceled`, `payment_past_due`). Remaining rows stop.
Already-created rows stay. HTTP `402` is returned only when **zero**
rows succeeded; a later-row 402 after some successes is HTTP `200`
with `stopped_reason` and per-row results.

**Partial failures:** other per-row errors (validation, duplicate
serial, share-link warning) continue. The response lists every
processed row.

**Scope:** `passes:create`

Maps to OpenAPI operationId `batchGeneratePasses` — POST /passes/batch.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `createApiKey`: Create an API key

Creates a new API key. The response contains `id`, `name`, `key_type`,
`key_prefix`, `raw_key`, and `message`. The full raw key is shown only
once and cannot be retrieved again.

**Scope:** `org:manage`

Maps to OpenAPI operationId `createApiKey` — POST /manage-keys.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `createApp`: Create a new app

Creates a new app within the organization.

**Scope:** `org:manage`

Maps to OpenAPI operationId `createApp` — POST /manage-org/app.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `createShareToken`: Create a share token

Creates a public share token for a pass, enabling distribution via URL,
QR code, or messaging. The share URL points to a public page where
recipients can add the pass to Apple or Google Wallet without logging in.

Idempotent — if the pass already has a share token, the existing token
is returned (200) instead of creating a new one (201).

For dual-wallet passes (same serial number with both Apple and Google),
the share token is automatically applied to all sibling passes.

**Scope:** `passes:manage`

Maps to OpenAPI operationId `createShareToken` — POST /share-pass/create.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `createTemplate`: Create a template

Creates a new pass template in draft status.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `createTemplate` — POST /manage-templates.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deactivateGoogleCredential`: Deactivate Google credential

Deactivates a Google Wallet credential.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `deactivateGoogleCredential` — DELETE /manage-certs/google/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deleteApiKey`: Delete an API key

Permanently deletes an API key. The key **must be revoked first**
(via PATCH) before it can be deleted. Attempting to delete an active
key returns 400.

**Scope:** `org:manage`

Maps to OpenAPI operationId `deleteApiKey` — DELETE /manage-keys/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deleteApp`: Deactivate an app

Deactivates the current app. This does not permanently delete data.

**Scope:** `org:manage`

Maps to OpenAPI operationId `deleteApp` — DELETE /manage-org/app.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deleteCertificate`: Delete a certificate

Deletes a certificate.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `deleteCertificate` — DELETE /manage-certs/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deleteImage`: Delete an image

Deletes an image (storage file + DB row). Always succeeds when the image exists.

Any template column pointing at this image is silently cleared (the template
falls back to no image in that slot — re-attach a new one if needed).
Any pass with `strip_image_id` pointing at this image has its override nullified
and reverts to the template's strip on next render.

Use `GET /manage-images/{id}/usage` first if you need to know the blast radius
before deleting.

**Scope:** `images:manage`

Maps to OpenAPI operationId `deleteImage` — DELETE /manage-images/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `deleteTemplate`: Delete a template

Soft-deletes a template by marking it as archived. Use `permanent=true`
to permanently delete the template and its associated data.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `deleteTemplate` — DELETE /manage-templates/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `downloadPass`: Download a .pkpass file

Downloads the `.pkpass` binary for an active pass.

**Scope:** `passes:download`

Maps to OpenAPI operationId `downloadPass` — GET /manage-passes/{id}/download.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `downloadPassBySerial`: Download a .pkpass file by serial number

Downloads the `.pkpass` binary for an active pass looked up by serial number.
When a serial has both Apple and Google passes, use `?wallet_type=` to select which one (defaults to `apple`).

**Scope:** `passes:download`

Maps to OpenAPI operationId `downloadPassBySerial` — GET /manage-passes/serial/{serial_number}/download.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `downloadSharedPass`: Download shared Apple .pkpass

Downloads the Apple `.pkpass` file for a shared pass. No authentication
required. Only works for active Apple passes.

Maps to OpenAPI operationId `downloadSharedPass` — GET /share-pass/{token}/download. Public endpoint — no API key required.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `generatePass`: Generate a wallet pass

Generates a wallet pass from a published template. For Apple passes (default),
returns a signed `.pkpass` binary file directly. For Google passes
(`wallet_type: "google"`), returns a JSON object containing a `save_url`
that the user can open to add the pass to Google Wallet.

When `wallet_type: "both"`, generates both Apple and Google passes in a single
call. The response is always JSON with `apple` and `google` keys. Partial success
is allowed — if one wallet fails, the other is still returned with a warning.
Returns 201 if at least one succeeds.

The pass ID is returned in the `X-Pass-Id` response header (for single-wallet).

If the app has a validation webhook configured, the webhook is called once
before generation (not per wallet type). A webhook rejection returns 403;
a webhook error returns 502 (fail-closed).

**Scope:** `passes:create`

Maps to OpenAPI operationId `generatePass` — POST /generate-pass.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getApp`: Get current app details

Returns the current app's settings.

**Scope:** `org:read`

Maps to OpenAPI operationId `getApp` — GET /manage-org/app.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getBatchGenerateLimits`: Batch generate limits

Public metadata for `POST /passes/batch`. No authentication.

Returns the hard row cap (100), sync mode, auth summary, and stable
error codes. This path is on the site host (`https://passfa.st/api`),
not `https://api.passfa.st/functions/v1`. MCP tool:
`getBatchGenerateLimits`.

Maps to OpenAPI operationId `getBatchGenerateLimits` — GET /passes/batch. Public endpoint — no API key required.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getImageUsage`: Get image usage / reference counts

Report how an image is referenced across templates and passes. Useful before
DELETE to confirm an image is unused, or to find which templates a shared
asset is attached to.

- `template_refs` lists every template column (e.g. `strip_image_id`,
  `icon_image_id`, `google_logo_image_id`) that references this image.
- `pass_refs_count` is the number of passes whose per-pass `strip_image_id`
  points at this image.
- `safe_to_delete` is `true` when `total_refs` is 0.

**Scope:** `images:manage`

Maps to OpenAPI operationId `getImageUsage` — GET /manage-images/{id}/usage.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getManagedSigningStatus`: Check managed signing availability

Returns whether managed (platform) signing credentials are available
for Apple and Google wallets. When `apple_ready` or `google_ready` is
`true`, apps can use `signing_mode: "managed"` or
`google_signing_mode: "managed"` without uploading their own credentials.

**Scope:** `org:read`

Maps to OpenAPI operationId `getManagedSigningStatus` — GET /manage-org/managed-signing-status.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getOrganization`: Get organization details

Returns the current organization's settings.

**Scope:** `org:read`

Maps to OpenAPI operationId `getOrganization` — GET /manage-org.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getPass`: Get a pass

Returns the full details of a single pass.

**Scope:** `passes:read`

Maps to OpenAPI operationId `getPass` — GET /manage-passes/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getPassBySerial`: Get a pass by serial number

Returns the full details of a single pass looked up by serial number.
When a serial has both Apple and Google passes, use `?wallet_type=` to select which one (defaults to `apple`).

**Scope:** `passes:read`

Maps to OpenAPI operationId `getPassBySerial` — GET /manage-passes/serial/{serial_number}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getSharePassMetadata`: Get shared pass metadata

Returns public metadata for a shared pass. No authentication required.
Used by the public share page to display wallet buttons and pass info.

Maps to OpenAPI operationId `getSharePassMetadata` — GET /share-pass/{token}. Public endpoint — no API key required.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `getTemplate`: Get a template

Returns the full details of a single template.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `getTemplate` — GET /manage-templates/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listApiKeys`: List API keys

Returns all API keys for the current organization.

**Scope:** `org:manage`

Maps to OpenAPI operationId `listApiKeys` — GET /manage-keys.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listCertificates`: List certificates

Returns all certificates for the current app.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `listCertificates` — GET /manage-certs.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listGoogleCredentials`: List Google credentials

Returns all active Google Wallet credentials for the current app.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `listGoogleCredentials` — GET /manage-certs/google.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listImages`: List images

Returns all images for the current app, including signed preview URLs.

**Scope:** `images:manage`

Maps to OpenAPI operationId `listImages` — GET /manage-images.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listPasses`: List passes

Returns a paginated list of passes for the current app.

**Scope:** `passes:read`

Maps to OpenAPI operationId `listPasses` — GET /manage-passes.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listTemplates`: List templates

Returns all templates for the current app. By default returns non-archived
templates. Set `archived=true` to return only archived templates.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `listTemplates` — GET /manage-templates.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `listWebhookEvents`: List webhook events

Returns a paginated list of webhook event delivery records for the current app.

**Scope:** `org:read`

Maps to OpenAPI operationId `listWebhookEvents` — GET /manage-org/webhook-events.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `publishTemplate`: Publish a template

Publishes a draft template, making it available for pass generation.
Published templates cannot be modified.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `publishTemplate` — POST /manage-templates/{id}/publish.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `revokeApiKey`: Revoke an API key

Revokes an API key, making it inactive. Revoked keys cannot authenticate.

**Scope:** `org:manage`

Maps to OpenAPI operationId `revokeApiKey` — PATCH /manage-keys/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `testAppleCertificates`: Test Apple certificates

Generates an ephemeral test `.pkpass` file to verify that the uploaded
Apple signing certificates are valid and complete. The test pass is
not stored — it is returned directly as a binary download.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `testAppleCertificates` — POST /manage-certs/test.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `testGoogleConnection`: Test Google connection

Tests the configured Google Wallet credentials by attempting to
authenticate with the Google Wallet API.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `testGoogleConnection` — POST /manage-certs/google/test.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `testWebhook`: Test the validation webhook

Sends a sample validation webhook payload to the configured URL
and returns the result.

**Scope:** `org:manage`

Maps to OpenAPI operationId `testWebhook` — POST /manage-org/app/test-webhook.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `updateApp`: Update app settings

Updates the current app's settings, including webhook configuration.
Set `regenerate_webhook_secret` to `true` to generate a new webhook
signing secret; the new secret is returned in `webhook_secret_raw`
(shown only once).

**Scope:** `org:manage`

Maps to OpenAPI operationId `updateApp` — PATCH /manage-org/app.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `updateOrganization`: Update organization settings

Updates the current organization's settings, including APNs credentials.

**Scope:** `org:manage`

Maps to OpenAPI operationId `updateOrganization` — PATCH /manage-org.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `updatePass`: Update a pass

Updates the dynamic data of an active pass. Optionally sends a push
notification to registered devices so they fetch the updated pass.
At least one of `data`, `expires_at`, `locations`, `relevant_date`,
or `max_distance` is required.

**Scope:** `passes:manage`

Maps to OpenAPI operationId `updatePass` — PATCH /manage-passes/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `updatePassBySerial`: Update a pass by serial number

Updates the dynamic data of an active pass looked up by serial number.
Optionally sends a push notification to registered devices.
At least one of `data`, `expires_at`, `locations`, `relevant_date`,
or `max_distance` is required.
When a serial has both Apple and Google passes, use `?wallet_type=` to select which one (defaults to `apple`).

**Scope:** `passes:manage`

Maps to OpenAPI operationId `updatePassBySerial` — PATCH /manage-passes/serial/{serial_number}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `updateTemplate`: Update a template

Updates a draft template. Published templates cannot be modified.

**Scope:** `templates:manage`

Maps to OpenAPI operationId `updateTemplate` — PATCH /manage-templates/{id}.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `uploadCertificate`: Upload a single certificate

Uploads a single PEM-encoded certificate or key.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `uploadCertificate` — POST /manage-certs.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `uploadGoogleCredentials`: Upload Google credentials

Uploads Google service account credentials for Google Wallet pass signing.
The service account JSON and issuer ID are stored securely.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `uploadGoogleCredentials` — POST /manage-certs/google.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `uploadImage`: Upload an image

Uploads an image for use in pass templates or per-pass strip overrides.
Send as multipart form data with a `purpose` field and a `file` field
containing the PNG image.

**Upload behaviour by purpose:**
- `strip` — **accumulates**. Each upload creates a new image; the returned
  `id` can be passed as `strip_image_id` on `POST /v1/passes` or
  `PATCH /v1/passes/{id}` to give individual passes their own banner.
  Previous `strip` images are NOT deleted — manage them via
  `DELETE /v1/images/{id}` when no longer referenced.
- All other purposes (`icon`, `logo`, `thumbnail`, `background`, `footer`,
  and all `_2x`/`_3x` variants) — **replace-on-upload**. Uploading a new
  image of the same purpose deletes the previous one from storage and DB.
  These are app-wide template assets, not per-pass.

**Scope:** `images:manage`

Maps to OpenAPI operationId `uploadImage` — POST /manage-images.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `uploadP12Certificate`: Upload a .p12 certificate bundle

Uploads a PKCS#12 (.p12) bundle containing signer certificate and private key.
The bundle is decrypted with the provided password, and individual certificates
are extracted and stored with AES-256-GCM encryption.

**Scope:** `certs:manage`

Maps to OpenAPI operationId `uploadP12Certificate` — POST /manage-certs/p12.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `voidPass`: Void a pass

Marks a pass as invalidated and rebuilds the `.pkpass` file with Apple's `voided: true` flag.
Registered devices are sent push notifications so the pass appears voided immediately in Apple Wallet.
Rebuild failure is non-fatal — the pass is still invalidated at the DB level.

**Scope:** `passes:manage`

Maps to OpenAPI operationId `voidPass` — POST /manage-passes/{id}/void.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
- `voidPassBySerial`: Void a pass by serial number

Marks a pass (looked up by serial number) as invalidated and rebuilds the `.pkpass`
file with Apple's `voided: true` flag. Registered devices are sent push notifications
so the pass appears voided immediately in Apple Wallet.
When a serial has both Apple and Google passes, use `?wallet_type=` to select which one (defaults to `apple`).

**Scope:** `passes:manage`

Maps to OpenAPI operationId `voidPassBySerial` — POST /manage-passes/serial/{serial_number}/void.

Same PassFast HTTP API, billing, and rate limits. Do not invent other paths.
