# MCP Plan

Version: `2.9.8`

This document describes how to expose Ollaid SSO as an MCP-compatible
integration layer for other SaaS products and for AI-enabled clients.

## Goal

Provide a standard integration surface so external SaaS platforms can:

- discover available Ollaid identity capabilities
- authenticate users through a stable contract
- exchange tokens without reimplementing tenant-specific logic
- synchronize sessions and profile data
- receive revocation and update events reliably

## What MCP is useful for here

MCP is a good fit when the consumer is:

- an AI agent
- a tool runner
- a SaaS product that already speaks MCP
- an internal integration service that wants typed discovery

MCP is not a replacement for:

- the existing REST APIs
- webhook delivery
- the SaaS backend session model
- the IAM backend as source of truth

## Recommended architecture

### 1. IAM backend

The IAM backend remains the source of truth for:

- users
- credentials
- password validation
- OTP validation
- access grants
- revocations
- profile sync events

### 2. SaaS backend

The SaaS backend keeps owning:

- local session issuance
- local user mapping
- token refresh policy
- app-level authorization
- tenant-specific business rules

### 3. MCP bridge service

Add a dedicated MCP bridge that:

- exposes stable MCP tools
- calls the IAM and SaaS REST APIs internally
- normalizes errors and response shapes
- hides tenant-specific complexity from the consumer

This bridge can live as:

- a small Node service
- a PHP service if you want to stay in the existing stack
- a sidecar service behind the SaaS backend

## What the MCP bridge should expose

### Identity tools

- `sso.getConfig`
- `sso.encryptNative`
- `sso.initNative`
- `sso.validateNative`
- `sso.verifyTotp`
- `sso.grantAccess`
- `sso.resendOtp`
- `sso.exchange`
- `sso.checkToken`
- `sso.refresh`
- `sso.logout`

### Account tools

- `account.refreshUserInfo`
- `account.linkEmail`
- `account.linkPhone`
- `account.updateAvatar`
- `account.resetAvatar`

### Tenant tools

- `tenant.resolve`
- `tenant.listApplications`
- `tenant.getRuntimeConfig`

### Debug tools

- `debug.traceLastCall`
- `debug.exportLogs`
- `debug.health`

## Tool contract rules

Each MCP tool should have:

- a strict input schema
- a strict output schema
- normalized error codes
- no hidden side effects beyond the documented behavior

Use only opaque transport values for:

- `encrypted_credentials`
- `native_token`
- `process_token`
- `callback_token`
- `refresh_token`

Never expose secret keys in MCP outputs.

## Data flow

### Login flow

1. MCP client requests config
2. MCP bridge fetches SaaS config
3. MCP bridge sends credentials to IAM encrypt/init
4. MCP bridge validates password or OTP
5. IAM returns `callback_token`
6. MCP bridge calls SaaS `/api/sso/exchange`
7. SaaS returns local token and user snapshot
8. MCP client receives final session result

### Needs-access flow

1. IAM returns `needs_access`
2. MCP bridge exposes the access prompt state
3. User confirms grant access
4. MCP bridge calls `grantAccess`
5. IAM returns `callback_token`
6. MCP bridge completes `exchange`

### Refresh flow

1. MCP client requests session refresh
2. MCP bridge validates local refresh policy
3. SaaS backend rotates refresh token if needed
4. MCP bridge returns updated session data

### Revocation flow

1. IAM emits a webhook or a revocation event
2. SaaS backend revokes the local session using `iam_token`
3. MCP bridge reports the event to downstream consumers

## Error normalization

Convert backend-specific failures into a small stable set:

- `invalid_credentials`
- `invalid_password`
- `invalid_otp`
- `invalid_token`
- `invalid_refresh`
- `expired_credentials`
- `needs_access`
- `connection_error`
- `timeout`
- `incomplete_data`
- `server_error`
- `rate_limited`

This is the main reason to add MCP here: one consistent error model across
integrations.

## Security model

### Authentication

The MCP bridge should require one of:

- a per-client API key
- OAuth-style bearer credentials
- a signed tenant bootstrap token

### Authorization

Authorize per:

- tenant
- application
- allowed tool set
- environment (`dev`, `staging`, `prod`)

### Secret handling

- keep `secret_key` server-side only
- do not surface raw decrypted payloads unless the tool explicitly needs them
- log tokens in redacted form only
- sign webhook payloads

### Transport

- enforce HTTPS
- reject plaintext callbacks
- use short timeouts on IAM calls
- retry only safe/idempotent operations

## Webhooks to pair with MCP

MCP should be paired with webhooks for push events:

- `session.revoked`
- `user.updated`
- `user.linked`
- `user.unlinked`
- `access.granted`
- `access.revoked`
- `profile.avatar.updated`

Webhooks are still the best mechanism for asynchronous sync.

## Minimal tool schema examples

### `sso.getConfig`

Input:

```json
{
  "tenant": "iam",
  "app": "default"
}
```

Output:

```json
{
  "success": true,
  "app_key": "oiam_ak_...",
  "encrypted_credentials": "opaque-base64-blob",
  "iam_api_url": "https://identityam.ollaid.com/api",
  "credentials_ttl": 300,
  "debug": false,
  "bypass": false
}
```

### `sso.exchange`

Input:

```json
{
  "callback_token": "ct_...",
  "tenant": "iam"
}
```

Output:

```json
{
  "success": true,
  "token": "sanctum-token-string",
  "expires_at": "2026-07-11T23:48:54+00:00",
  "user": {
    "reference": "iam_user_123",
    "name": "User Name",
    "email": "user@example.com"
  }
}
```

## Implementation phases

### Phase 1: contract stabilization

- freeze the REST payloads
- document every success and error shape
- normalize field names
- ensure `exchange` failure modes are explicit

### Phase 2: SDK layer

- publish a small SDK for SaaS integrators
- wrap the REST calls
- expose typed helpers
- provide consistent retries and error mapping

### Phase 3: MCP bridge

- implement MCP tool discovery
- add the identity tools
- add profile tools
- add tenant and debug tools

### Phase 4: webhook sync

- add webhook handlers
- sign payloads
- deduplicate events
- expose replay support

### Phase 5: partner onboarding

- add sample configs
- add reference flows
- provide a checklist for new SaaS integrations

## What an external SaaS would need

At minimum, a third-party SaaS integrating through this system needs:

- its own tenant credentials
- a registered callback URL
- a way to call the MCP bridge
- a way to verify webhook signatures
- a session strategy for its own app

## Recommended deliverables

If you want this to be easy to adopt, ship these together:

- REST docs
- MCP tool spec
- SDK
- webhook spec
- example integration project

## Practical recommendation

If you only have time to build one thing now, build the REST contract first.
If you want the next layer of developer experience, build the SDK.
If you want AI or agent-based integrations, add the MCP bridge after that.
