Saltar al contenido principal

MCP API Reference

Reference for the FlowPOS MCP server in apps/backend/src/mcp/.

This page documents current behavior from source code (controllers, guards, services, and tool definitions), including:

  • HTTP endpoints
  • Auth and token flows
  • Session lifecycle
  • Runtime tool catalog and visibility rules

Architecture map (hexagonal)

domain/
mcp-principal.interface.ts
mcp-tool.interface.ts
mcp-api-key-repository.domain.ts

application/
mcp-api-key.service.ts
mcp-token.service.ts
mcp-session.service.ts
mcp-tools-initializer.service.ts

infrastructure/
mcp-api-key.repository.ts
mcp-prompts.handler.ts
mcp-resources.handler.ts

interfaces/
mcp.controller.ts
mcp-token.controller.ts
mcp-api-key.controller.ts
mcp-well-known.controller.ts
guards/

Infrastructure handles HTTP, Redis, and DB details; business rules (scope checks, token exchange behavior, tool filtering) live in application/domain.


Authentication modes

V1: API key

  • Key management endpoints: /mcp/keys/*
  • Runtime auth: Authorization: Bearer fp_mcp_<token>
  • Key is validated by SHA-256 hash lookup in mcp_api_key
  • Principal comes from DB key metadata:
    • role
    • businessId -> activeBusinessId
    • scopes
    • createdBy -> userId (nullable)

V2: Firebase -> MCP JWT

  • Exchange endpoint: POST /mcp/token
  • Refresh endpoint: POST /mcp/token/refresh
  • Runtime auth: Authorization: Bearer <jwt>
  • Role is always merchant for V2 tokens
  • Scopes are fixed by token service:
    • pos:read
    • pos:write
    • reports:read
    • psa:read
    • pos:intents

Guard chain on /mcp

McpAuthGuard attempts:

  1. McpApiKeyGuard
  2. McpTokenGuard

If both fail -> 401 Unauthorized.


Endpoint reference

POST /mcp/keys

Create a new MCP API key.

  • Auth: Firebase app auth (global AuthGuard)
  • Controller: McpApiKeyController
  • Raw key is returned once (rawKey) and cannot be recovered
  • platform_operator key creation is rejected by service

Request body:

{
"businessId": "uuid",
"role": "merchant",
"scopes": ["pos:read", "reports:read"],
"label": "My key",
"expiresAt": "2027-01-01T00:00:00.000Z"
}

Notes:

  • businessId is effectively required for this endpoint
  • Allowed roles in DTO include platform_operator, but service forbids it

GET /mcp/keys?businessId=<uuid>

List key metadata for a business.

  • Auth: Firebase app auth
  • Does not return key hash or raw key

PATCH /mcp/keys/:id/revoke

Soft revoke key (isActive = false).

  • Auth: Firebase app auth
  • Effect is immediate for MCP auth

DELETE /mcp/keys/:id

Hard delete key record.

  • Auth: Firebase app auth
  • Response: 204

POST /mcp/token

Exchange Firebase ID token for MCP JWT.

  • Public endpoint (@IsPublic)
  • Validates Firebase token
  • Resolves internal user and active business memberships
  • Returns MCP access token and business metadata

Request:

{ "firebaseIdToken": "<firebase-id-token>" }

Common errors:

  • 401: invalid/expired Firebase token
  • 403: no active business memberships

POST /mcp/token/refresh

Refresh MCP JWT without requiring Firebase token.

  • Public endpoint
  • Accepts valid or expired JWT
  • Expired token is refreshable for up to 7 days
  • Memberships are reloaded from DB during refresh

Request:

{ "token": "<mcp-jwt>" }

Common errors:

  • 401: invalid signature/claims
  • 401: expired beyond 7-day grace window

GET /.well-known/oauth-authorization-server

OAuth Authorization Server Metadata (RFC 8414).


GET /.well-known/oauth-protected-resource

OAuth Protected Resource Metadata (RFC 9728).


POST /mcp

Primary MCP JSON-RPC endpoint.

  • Auth: McpAuthGuard (API key or MCP JWT)
  • First request must be initialize
  • On initialize success, response includes mcp-session-id header
  • Non-initialize requests require mcp-session-id

Error patterns:

  • 400: missing mcp-session-id on non-initialize request
  • 400: unknown session id
  • 401: invalid credential

GET /mcp

Open SSE stream for existing session.

  • Requires both:
    • Authorization
    • mcp-session-id

DELETE /mcp

Close existing session.

  • Requires both:
    • Authorization
    • mcp-session-id

Session lifecycle and state

Source: mcp-session.service.ts

  1. initialize -> creates in-memory session transport
  2. tool requests reuse session via mcp-session-id
  3. DELETE /mcp or transport close -> session removed

For OAuth sessions, principal is additionally stored in Redis key:

mcp:session:{sessionId}

Important constraint:

  • Redis stores principal state, not transport
  • Session transport remains in-memory only
  • Sessions do not survive instance restart

Runtime tool catalog (35 tools)

The runtime tool list is built by McpToolsInitializer.

Platform and context tools (5)

ToolPurposeScopes
list_tenantsList all businesses on the platform (operator only)none
set_active_tenantSet active business for platform operator sessionsnone
set_active_businessSwitch active business for multi-business merchantsnone
get_active_businessFetch current business metadata and location listpos:read
list_locationsList locations for current active businesspos:read

Commerce and reporting tools (15)

ToolPurposeScopes
get_productsPaginated product listing with optional filterspos:read
search_productsFast lookup by name/SKU/barcodepos:read
get_inventoryInventory snapshot per product/locationpos:read
get_low_stock_alertsFlat low-stock list by reorder thresholdpos:read
list_ordersPaginated restaurant order listingpos:read
get_orderRestaurant order detail by IDpos:read
create_orderCreate restaurant orderpos:write
void_transactionVoid retail sale transactionpos:write
list_salesPaginated retail sales listingpos:read
get_saleRetail sale detail by IDpos:read
list_purchasesPaginated purchase listingpos:read
get_purchasePurchase detail by IDpos:read
get_sales_reportRaw date-range totals (revenue, count, AOV)reports:read
get_top_productsTop-selling products by revenuereports:read
get_sales_by_locationRevenue breakdown by locationreports:read

FEL tools (7)

ToolPurposeScopes
get_taxpayer_infoNIT lookup via FEL shared infopos:read
list_credit_notesPaginated credit note listingpos:read
get_credit_noteCredit note detail by IDpos:read
list_debit_notesPaginated debit note listingpos:read
get_debit_noteDebit note detail by IDpos:read
list_cancellationsPaginated cancellation listingpos:read
get_cancellationCancellation detail by IDpos:read

Implementation Portal (PSA) tools (4)

ToolPurposeScopes
list_implementationsList implementation boardspsa:read
get_implementationFull board tree (phases and steps)psa:read
log_hoursLog time entry on hourly stepspsa:read
get_implementation_statusCompletion/status summary for one boardpsa:read

Intent tools (4)

ToolPurposeScopes
summarize_dayDaily business narrative summarypos:intents
summarize_periodMulti-day summary with prior-period comparisonpos:intents
get_inventory_healthPrioritized low-stock/out-of-stock health reportpos:intents
get_client_healthPSA board health summary with hours and blockerspos:intents, psa:read

Tool visibility rules

Visibility is filtered at initialize (ToolRegistry.listFor) and rechecked at dispatch (ToolRegistry.dispatch).

Key rules:

  • operatorOnly tools -> only platform_operator
  • multiBusinessOnly tools -> only when authorizedBusinessIds.length > 1
  • pos:intents tools:
    • require pos:intents scope
    • never visible to tenant_developer
  • non-operator tools require activeBusinessId unless skipTenantCheck = true

Scope reference

  • pos:read: product/inventory/order/sale/purchase/FEL reads
  • pos:write: create_order, void_transaction
  • reports:read: report tools
  • psa:read: PSA tools (list_implementations, log_hours, etc.)
  • pos:intents: intent tools

Note on log_hours: write behavior is intentionally protected by psa:read in current implementation.