iyzico MCP Server
README.md
# iyzico MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) server that gives AI
agents a typed, safe interface to the [iyzico](https://www.iyzico.com) payments
API. Look up card BINs and installment plans, spin up hosted checkout forms,
inspect payments, issue refunds and cancellations, and query recurring
subscriptions — all from Claude Desktop, Claude Code, Cursor, or any MCP client.
iyzico is one of the most widely used payment gateways in Turkey. It exposes a
rich REST API but signs every request with a non-trivial `IYZWSv2` HMAC-SHA256
scheme; this server implements that correctly so you don't have to, and wraps
each operation in a well-described, zod-validated tool.
> **Status:** unofficial, community-built. Not affiliated with or endorsed by
> iyzico. Defaults to the **sandbox** environment so you can't accidentally move
> real money while experimenting.
---
## Features
- **10 well-scoped tools** covering BIN/installment lookups, checkout forms,
payment inspection, refunds/cancellations, and subscription queries.
- **Correct `IYZWSv2` request signing** (HMAC-SHA256), verified by a unit test
against an independent reference implementation.
- **Input validation with [zod](https://zod.dev)** — malformed arguments are
rejected before they ever reach iyzico.
- **Graceful, informative errors.** iyzico reports business failures as HTTP 200
with a `status: "failure"` body; this server surfaces those as real errors
with the iyzico `errorCode`, so agents can react instead of proceeding on a
silent failure.
- **Sandbox-first & safe by default.** Write operations (`cancel_payment`,
`refund_payment`) are annotated as destructive so clients can warn the user.
- **Runs over stdio** — the standard transport for local MCP servers.
---
## Requirements
- Node.js **18+** (uses the built-in global `fetch`).
- iyzico API credentials:
- Sandbox: create a free merchant account at
<https://sandbox-merchant.iyzipay.com> → **Settings → API Keys**.
- Production: <https://merchant.iyzipay.com> → **Settings → API Keys**.
---
## Installation
### From source (current)
```bash
git clone <your-fork-url> iyzico-mcp
cd iyzico-mcp
npm install
npm run build
```
The built entrypoint is `dist/index.js`. You can run it directly:
```bash
IYZICO_API_KEY=sandbox-xxxx \
IYZICO_SECRET_KEY=sandbox-yyyy \
IYZICO_ENVIRONMENT=sandbox \
node dist/index.js
```
### Via npx (once published)
If/after this package is published to npm, it can be launched without a local
checkout:
```bash
npx -y iyzico-mcp
```
The config snippets below show both forms.
---
## Configuration
All configuration is via environment variables:
| Variable | Required | Default | Description |
| -------------------- | -------- | ---------- | --------------------------------------------- |
| `IYZICO_API_KEY` | yes | — | Your iyzico API key. |
| `IYZICO_SECRET_KEY` | yes | — | Your iyzico secret key. |
| `IYZICO_ENVIRONMENT` | no | `sandbox` | `sandbox` (safe) or `production` (live money).|
| `IYZICO_TIMEOUT_MS` | no | `30000` | Per-request timeout in milliseconds. |
Copy `.env.example` to `.env` for local reference. Credentials are read lazily,
so the server will still start and list its tools without them — you'll only get
an error (naming the missing variable) when you actually call a tool.
### Verify your setup
```bash
# List the tools without any credentials (offline):
node dist/index.js --list-tools
# Confirm your credentials authenticate against iyzico:
# then call the `ping` tool from your MCP client.
```
---
## Client setup
### Claude Desktop
Edit the config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
**Using a local build:**
```json
{
"mcpServers": {
"iyzico": {
"command": "node",
"args": ["/absolute/path/to/iyzico-mcp/dist/index.js"],
"env": {
"IYZICO_API_KEY": "sandbox-xxxx",
"IYZICO_SECRET_KEY": "sandbox-yyyy",
"IYZICO_ENVIRONMENT": "sandbox"
}
}
}
}
```
**Using npx (once published):**
```json
{
"mcpServers": {
"iyzico": {
"command": "npx",
"args": ["-y", "iyzico-mcp"],
"env": {
"IYZICO_API_KEY": "sandbox-xxxx",
"IYZICO_SECRET_KEY": "sandbox-yyyy",
"IYZICO_ENVIRONMENT": "sandbox"
}
}
}
}
```
Restart Claude Desktop after editing.
### Claude Code
Add the server with the `claude mcp add` command:
```bash
# Local build:
claude mcp add iyzico \
--env IYZICO_API_KEY=sandbox-xxxx \
--env IYZICO_SECRET_KEY=sandbox-yyyy \
--env IYZICO_ENVIRONMENT=sandbox \
-- node /absolute/path/to/iyzico-mcp/dist/index.js
# npx (once published):
claude mcp add iyzico \
--env IYZICO_API_KEY=sandbox-xxxx \
--env IYZICO_SECRET_KEY=sandbox-yyyy \
--env IYZICO_ENVIRONMENT=sandbox \
-- npx -y iyzico-mcp
```
Or add it to `.mcp.json` in your project root:
```json
{
"mcpServers": {
"iyzico": {
"command": "node",
"args": ["/absolute/path/to/iyzico-mcp/dist/index.js"],
"env": {
"IYZICO_API_KEY": "sandbox-xxxx",
"IYZICO_SECRET_KEY": "sandbox-yyyy",
"IYZICO_ENVIRONMENT": "sandbox"
}
}
}
}
```
### Cursor
Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project) using
the same JSON shape as the Claude Desktop example above.
---
## Tools
| Tool | Type | What it does |
| ------------------------------- | ---------- | ------------------------------------------------------------------- |
| `ping` | read-only | Verify connectivity and that your credentials authenticate. |
| `check_bin` | read-only | Look up bank/scheme/type metadata for a card BIN (first 6-8 digits). |
| `retrieve_installment_info` | read-only | Get installment plans and per-installment pricing for a BIN + amount.|
| `initialize_checkout_form` | **write** | Start a hosted checkout form; returns a payment page URL and token. |
| `retrieve_checkout_form_result` | read-only | Fetch the outcome of a checkout form by its token. |
| `retrieve_payment` | read-only | Get full detail of a payment (status, amounts, item transactions). |
| `cancel_payment` | **write** | Void a payment in full (same-day, before settlement). |
| `refund_payment` | **write** | Refund a payment transaction, in full or in part. |
| `search_subscriptions` | read-only | List/filter recurring subscriptions with paging. |
| `retrieve_subscription` | read-only | Get detail of one subscription by its reference code. |
Write tools are annotated as destructive (`readOnlyHint: false`,
`destructiveHint: true`) so MCP clients can prompt for confirmation.
### Example prompts
Once connected, you can ask your agent things like:
- *"Check the BIN 554960 and tell me which bank issued it and whether it's a
credit or debit card."* → `check_bin`
- *"For a 1,200 TRY purchase on BIN 552879, what installment options are
available and what's the total cost at 6 installments?"* →
`retrieve_installment_info`
- *"Create a checkout form for a 249.90 TRY order for buyer Ada Lovelace, one
virtual item, callback to https://example.com/iyzico/callback."* →
`initialize_checkout_form`
- *"Look up payment 12345678 and refund the first basket item in full."* →
`retrieve_payment` then `refund_payment`
- *"How many ACTIVE subscriptions do we have, and show me the ones for customer
CUST-42."* → `search_subscriptions`
### Example tool call
Arguments passed to `check_bin`:
```json
{
"binNumber": "554960",
"locale": "en"
}
```
Returns iyzico's response as pretty-printed JSON, e.g.:
```json
{
"status": "success",
"binNumber": "554960",
"cardType": "CREDIT_CARD",
"cardAssociation": "MASTER_CARD",
"cardFamily": "Bonus",
"bankName": "Garanti Bankası",
"bankCode": 62,
"commercial": 0
}
```
---
## How authentication works
Every request is signed with iyzico's `IYZWSv2` scheme:
1. Generate a random per-request key (sent in the `x-iyzi-rnd` header).
2. Compute `HMAC-SHA256(randomKey + uriPath + JSON(body), secretKey)` as
lowercase hex. For `GET` endpoints the body is `{}` and parameters travel in
the query string.
3. Build `apiKey:<key>&randomKey:<rnd>&signature:<hex>`, base64-encode it, and
send it as `Authorization: IYZWSv2 <base64>`.
This is implemented in [`src/auth.ts`](src/auth.ts) and covered by
[`test/auth.test.mjs`](test/auth.test.mjs).
---
## Development
```bash
npm install # install dependencies
npm run build # compile TypeScript to dist/
npm test # build, run the auth unit test, and the stdio smoke test
npm run list-tools # print the tool catalog as JSON
```
The smoke test launches the built server over stdio **without** any API key and
verifies the MCP handshake, the full tool catalog, tool annotations, and that a
credential-less call returns a clean, actionable error — so it runs safely in CI
with no secrets.
### Project layout
```
src/
index.ts CLI entrypoint (stdio transport, --list-tools/--help)
server.ts Builds the McpServer and registers all tools
client.ts HTTP client: signing, query strings, timeouts, error mapping
auth.ts IYZWSv2 HMAC-SHA256 request signing
config.ts Env-var configuration + validation
tools/
shared.ts Common request fields, result/error helpers, tool type
index.ts Tool registry
ping.ts, checkBin.ts, installmentInfo.ts, checkoutForm.ts,
retrievePayment.ts, cancelPayment.ts, refundPayment.ts, subscriptions.ts
test/
auth.test.mjs Signature/authorization-header unit test
smoke.mjs End-to-end stdio handshake + tool-catalog test
```
---
## Safety notes
- The server **defaults to sandbox**. Set `IYZICO_ENVIRONMENT=production` only
when you intend to move real money.
- `cancel_payment` and `refund_payment` are irreversible. They are flagged
destructive for MCP clients, but you remain responsible for confirming intent.
- Never pass full card numbers to `check_bin` — only the 6-8 digit BIN.
- Keep your secret key out of source control. Use environment variables or your
MCP client's secret storage.
---
## License
[MIT](LICENSE) © Seyithan Alkan
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues