Skip to main content
Glama
xnetcat

Pekao MCP Server

by xnetcat
README.md
# Pekao MCP Server

A Model Context Protocol (MCP) server for the Pekao Polish API (PolishAPI 2.1.1). This server exposes banking operations as MCP tools that can be used by AI assistants like Claude.

## Features

- **Account Information Service (AIS)**: List accounts, view balances, transaction history
- **Payment Initiation Service (PIS)**: Create domestic, SEPA, and international transfers
- **Confirmation of Funds (CAF)**: Check if funds are available
- **OAuth2 Authorization**: Secure authentication flow

## Prerequisites

- Node.js 18+
- Pekao API credentials (client ID, client secret)
- QSEAL certificate and private key for request signing

## Getting API Credentials

Pekao uses the PolishAPI standard with automatic TPP (Third Party Provider) registration. You need PSD2-compliant certificates to register and use the API.

### 1. Obtain PSD2 Certificates

You need **two separate certificates** (using the same certificate for both purposes is not allowed):

| Certificate | Purpose |
|-------------|---------|
| **QWAC** (Qualified Website Authentication Certificate) | Establishing mutual TLS (mTLS) connection |
| **QSealC** (Qualified Electronic Seal Certificate) | Signing API requests (JWS signatures) |

**Where to obtain certificates:**

For **production**, get certificates from a qualified Trust Service Provider (TSP):
- Krajowa Izba Rozliczeniowa (KIR)
- Asseco Data Systems
- Certum (Asseco)
- Other eIDAS-qualified providers listed on the EU Trusted List

The certificates must contain PSD2 roles in the QC_Statement:
- `PSP_AI` - Account Information Service Provider (AISP) - for AIS
- `PSP_PI` - Payment Initiation Service Provider (PISP) - for PIS
- `PSP_IC` - Payment Instrument Issuing Service Provider (PIISP) - for CAF
- `PSP_AS` - Account Servicing Payment Service Provider (ASPSP)

For **sandbox/testing**, contact Pekao for test certificates or use certificates from a test TSP.

### 2. Register Your Application

Registration is done automatically via the `/auth/v2_1_1.1/register` API endpoint. This MCP server includes a registration tool, but you can also register manually.

**Required for registration:**
- QWAC certificate for mTLS connection
- QSealC certificate for signing the request
- A `software_statement` JWT containing your application details

**Software Statement Structure:**

```json
{
  "redirect_uris": ["https://your-app.com/callback"],
  "iss": "PSDES-ABC-ABC123",
  "client_name": "Your App Name",
  "sub_contact_email": "contact@your-company.com",
  "logo_uri": "https://your-app.com/logo.png",
  "jwks_uri": "https://your-app.com/jwks.json",
  "client_desc": "Application description",
  "sub": "PL-PFSA-YOUR-LICENSE-NUMBER",
  "sub_name": "Your Company Sp. z o.o.",
  "scope": "ais ais-accounts pis"
}
```

The `software_statement` must be signed as a JWT using your QSealC certificate.

### 3. Receive Your Credentials

After successful registration, you'll receive:

| Credential | Description |
|------------|-------------|
| `client_id` | Your application's unique identifier |
| `client_secret` | Secret key for authentication |

**Important:** Store these credentials securely. They are only returned once during registration.

### 4. Prepare Certificate Files

Save your certificates in PEM format in the `certs/` directory:

**QSealC Certificate** (`certificate.pem`):
```
-----BEGIN CERTIFICATE-----
MIIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
-----END CERTIFICATE-----
```

**Private Key** (`private-key.pem`):
```
-----BEGIN PRIVATE KEY-----
MIIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
-----END PRIVATE KEY-----
```

### 5. Configure the Key ID

The `PEKAO_KEY_ID` is the `kid` (Key ID) parameter from your QSealC certificate. You can find it:
- In your certificate's metadata
- By checking the certificate with OpenSSL: `openssl x509 -in certificate.pem -text`
- From your TSP's certificate issuance documentation

### Environment Variables Reference

| Variable | Required | Description |
|----------|----------|-------------|
| `PEKAO_CLIENT_ID` | Yes | OAuth2 client identifier from registration |
| `PEKAO_CLIENT_SECRET` | Yes | OAuth2 client secret from registration |
| `PEKAO_ENVIRONMENT` | No | `sandbox` (default) or `production` |
| `PEKAO_CERT_PATH` | Yes | Path to your QSealC certificate (PEM format) |
| `PEKAO_KEY_PATH` | Yes | Path to your private key (PEM format) |
| `PEKAO_KEY_ID` | Yes | Key ID (`kid`) from your QSealC certificate |
| `PEKAO_REDIRECT_URI` | Yes | OAuth2 redirect URI (must match registration) |

### API Endpoints

| Environment | Base URL |
|-------------|----------|
| Sandbox | `https://api.sandbox.pekao.com.pl` |
| Production | `https://api.pekao.com.pl` |

## Installation

```bash
git clone https://github.com/xnetcat/pekao-mcp.git
cd pekao-mcp
npm install
npm run build
```

## Configuration

1. Copy the example environment file:

```bash
cp .env.example .env
```

2. Edit `.env` with your credentials:

```env
PEKAO_CLIENT_ID=your-client-id
PEKAO_CLIENT_SECRET=your-client-secret
PEKAO_ENVIRONMENT=sandbox
PEKAO_CERT_PATH=./certs/certificate.pem
PEKAO_KEY_PATH=./certs/private-key.pem
PEKAO_KEY_ID=your-key-id
PEKAO_REDIRECT_URI=http://localhost:3000/callback
```

3. Place your QSEAL certificate and private key in the `certs/` directory.

## Usage

### Claude Desktop

Add to your Claude Desktop configuration file:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "pekao": {
      "command": "node",
      "args": ["/path/to/pekao-mcp/dist/index.js"],
      "env": {
        "PEKAO_CLIENT_ID": "your-client-id",
        "PEKAO_CLIENT_SECRET": "your-client-secret",
        "PEKAO_ENVIRONMENT": "sandbox",
        "PEKAO_CERT_PATH": "/path/to/pekao-mcp/certs/certificate.pem",
        "PEKAO_KEY_PATH": "/path/to/pekao-mcp/certs/private-key.pem",
        "PEKAO_KEY_ID": "your-key-id",
        "PEKAO_REDIRECT_URI": "http://localhost:3000/callback"
      }
    }
  }
}
```

### Claude Code (CLI)

Add to your Claude Code MCP settings:

```bash
claude mcp add pekao node /path/to/pekao-mcp/dist/index.js
```

Or add to your project's `.mcp.json`:

```json
{
  "mcpServers": {
    "pekao": {
      "command": "node",
      "args": ["/path/to/pekao-mcp/dist/index.js"],
      "env": {
        "PEKAO_CLIENT_ID": "your-client-id",
        "PEKAO_CLIENT_SECRET": "your-client-secret",
        "PEKAO_ENVIRONMENT": "sandbox",
        "PEKAO_CERT_PATH": "/path/to/pekao-mcp/certs/certificate.pem",
        "PEKAO_KEY_PATH": "/path/to/pekao-mcp/certs/private-key.pem",
        "PEKAO_KEY_ID": "your-key-id",
        "PEKAO_REDIRECT_URI": "http://localhost:3000/callback"
      }
    }
  }
}
```

### Cursor

Add to Cursor's MCP configuration in Settings > MCP Servers:

```json
{
  "pekao": {
    "command": "node",
    "args": ["/path/to/pekao-mcp/dist/index.js"],
    "env": {
      "PEKAO_CLIENT_ID": "your-client-id",
      "PEKAO_CLIENT_SECRET": "your-client-secret",
      "PEKAO_ENVIRONMENT": "sandbox",
      "PEKAO_CERT_PATH": "/path/to/pekao-mcp/certs/certificate.pem",
      "PEKAO_KEY_PATH": "/path/to/pekao-mcp/certs/private-key.pem",
      "PEKAO_KEY_ID": "your-key-id",
      "PEKAO_REDIRECT_URI": "http://localhost:3000/callback"
    }
  }
}
```

### Using npx (after publishing to npm)

```json
{
  "mcpServers": {
    "pekao": {
      "command": "npx",
      "args": ["pekao-mcp"],
      "env": {
        "PEKAO_CLIENT_ID": "your-client-id",
        "PEKAO_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

## Available Tools

### Authorization

| Tool | Description |
|------|-------------|
| `pekao-authorize` | Start OAuth2 authorization flow |
| `pekao-exchange-token` | Exchange authorization code for access token |
| `pekao-refresh-token` | Refresh an expired access token |
| `pekao-set-token` | Manually set an access token |

### Account Information

| Tool | Description |
|------|-------------|
| `pekao-get-accounts` | List all accounts |
| `pekao-get-account` | Get details of a specific account |
| `pekao-get-transactions-done` | Get completed transactions |
| `pekao-get-transactions-pending` | Get pending transactions |
| `pekao-get-transactions-rejected` | Get rejected transactions |
| `pekao-get-transactions-cancelled` | Get cancelled transactions |
| `pekao-get-transactions-scheduled` | Get scheduled transactions |
| `pekao-get-holds` | Get account holds |
| `pekao-get-transaction-detail` | Get details of a specific transaction |
| `pekao-delete-consent` | Remove account access consent |

### Payment Initiation

| Tool | Description |
|------|-------------|
| `pekao-initiate-domestic` | Create a domestic transfer |
| `pekao-initiate-eea` | Create a SEPA/EEA transfer |
| `pekao-initiate-non-eea` | Create an international (non-EEA) transfer |
| `pekao-initiate-tax` | Create a tax payment |
| `pekao-initiate-recurring` | Create a recurring payment |
| `pekao-initiate-bundle` | Create multiple transfers as a bundle |
| `pekao-get-payment` | Get payment status |
| `pekao-get-recurring-payment` | Get recurring payment status |
| `pekao-get-bundle` | Get bundle status |
| `pekao-cancel-payment` | Cancel a payment |
| `pekao-cancel-recurring-payment` | Cancel a recurring payment |

### Confirmation of Funds

| Tool | Description |
|------|-------------|
| `pekao-check-funds` | Check if funds are available on an account |

## Example Usage

Once configured, you can ask Claude to:

- "Show me my Pekao bank accounts"
- "What's my account balance?"
- "List my recent transactions"
- "Transfer 100 PLN to account 12345678901234567890123456"
- "Check if I have 500 PLN available"

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Run in development mode
npm run dev

# Test with MCP Inspector
npx @modelcontextprotocol/inspector node dist/index.js
```

## Technical Details

### JWS Signature Format

All API requests require a detached JWS signature in the `X-JWS-SIGNATURE` header. The signature format is:

```
[base64url-encoded-header]..[base64url-encoded-signature]
```

The payload section is empty (detached) to avoid duplicating request data. This MCP server handles JWS signing automatically.

**JWS Header Structure:**
```json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "your-key-id",
  "x5c": ["base64-encoded-certificate"]
}
```

### Required HTTP Headers

All requests include:
- `X-IBM-Client-Id` - Your client ID
- `X-IBM-Client-Secret` - Your client secret
- `X-JWS-SIGNATURE` - Detached JWS signature
- `X-REQUEST-ID` - UUID v4 for request tracking
- `Authorization: Bearer <token>` - For authenticated endpoints
- `Content-Type: application/json`
- `Accept: application/json`
- `Accept-Encoding: gzip`
- `Accept-Language: pl`
- `Accept-Charset: utf-8`

### Rate Limits

For AIS queries without user presence (automatic queries by TPP):
- Maximum 4 requests per 24 hours per consent
- Transaction history limited to 90 days by default
- Exceeding limits returns `429 Too Many Requests`

### Strong Customer Authentication (SCA)

SCA is performed on Pekao's side using:
- SMS codes
- PeoPay mobile authorization

For multiple-use AIS consents, SCA is required every 90 days.

## API Documentation

This server implements the Pekao Polish API (PolishAPI 2.1.1). For full API documentation, see:
- [Pekao API Portal](https://www.pekao.com.pl/developer)
- [PolishAPI Standard](https://polishapi.org/)
- [PolishAPI Swagger Specification](https://app.swaggerhub.com/apis/ZBP/polish-api/)

## Limitations

Based on Pekao's implementation of PolishAPI:

- **No bundle transfers** for retail customers (only corporate via PekaoBiznes24)
- **No SORBNET2, Blue Cash, or TARGET** payment systems for retail
- **No `getMultiplePayments`** - only for corporate customers
- **No `getTransactionsPending`** for retail customers (Pekao24)
- **No decoupled SCA** - only redirect-based authentication
- **No account list consent flow** - accounts must be specified by TPP
- **CAF service** - currently returns unavailable for all accounts

## License

MIT

Maintenance

ActivityInactive
ResponsivenessNo issues