diff --git a/readme.md b/readme.md index 9f4311a..6b15c5c 100644 --- a/readme.md +++ b/readme.md @@ -1,38 +1,163 @@ # Paystack MCP Server -This project implements a server for Paystack's [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server. +A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that enables AI assistants to interact with the full range of [Paystack APIs](https://paystack.com/docs/api/). +## Quick Start + + +```bash +# Via npx (coming soon) +npx paystack-mcp start + +# With environment configuration +PAYSTACK_SECRET_KEY_TEST=sk_test_... npx paystack-mcp start +``` + +For now, clone and build locally: + +```bash +git clone https://github.com/PaystackOSS/paystack-mcp-server.git +cd paystack-mcp-server +npm install +npm run build +``` + +Then configure your MCP client to use the built server (see [Client Integration](#client-integration)). ## Requirements -- Node.js (v14+ recommended) +- Node.js v18+ - npm or yarn +- A Paystack test secret key (starts with `sk_test_`) + +## Configuration Options + +| Environment Variable | Purpose | Default | +| --- | --- | --- | +| `PAYSTACK_SECRET_KEY_TEST` | Your Paystack test secret key **(required)** | — | +| `NODE_ENV` | Environment mode (`development`, `production`, `test`) | `development` | +| `LOG_LEVEL` | Logging verbosity (`debug`, `info`, `warn`, `error`) | `info` | + +> **Security note:** Only test keys (`sk_test_*`) are allowed. The server validates this at startup and will reject live keys. + +## Client Integration + +The Paystack MCP Server works with any MCP-compatible client. Below is the standard configuration schema used by most clients (Claude Desktop, ChatGPT Desktop, Cursor, Windsurf, etc.). + +### Using a local build + +If you've cloned and built the server locally: + +```json +{ + "mcpServers": { + "paystack": { + "command": "node", + "args": ["/path/to/paystack-mcp-server/build/index.js"], + "env": { + "PAYSTACK_SECRET_KEY_TEST": "sk_test_..." + } + } + } +} +``` + +### Using npm (coming soon) + + +```json +{ + "mcpServers": { + "paystack": { + "command": "npx", + "args": ["paystack-mcp", "start"], + "env": { + "PAYSTACK_SECRET_KEY_TEST": "sk_test_..." + } + } + } +} +``` + +### Where to add this configuration + +| Client | Config file location | +| --- | --- | +| Claude Desktop | `claude_desktop_config.json` | +| ChatGPT Desktop | MCP settings in app preferences | +| Cursor | `.cursor/mcp.json` or global MCP settings | +| Windsurf | MCP configuration in settings | +| Claude Code | `~/.claude/mcp.json` or project-level `.mcp.json` | -## Setup +## How It Works -1. Clone the repository: - ``` - git clone https://github.com/yourusername/paystack-mcp-server.git - cd paystack-mcp - ``` +The Paystack MCP Server exposes the **entire Paystack API** to AI assistants by parsing Paystack's OpenAPI specification at runtime. Instead of hardcoding individual endpoints, the server dynamically discovers all available operations and makes them accessible through a small set of tools. -2. Install dependencies: - ``` - npm install - ``` +### Available Tools -3. Configure environment variables: - - Copy `.env.example` to `.env` and update with your Paystack credentials and server settings. +| Tool | Description | +| --- | --- | +| `get_paystack_operation` | Fetch operation details (method, path, parameters) by operation ID | +| `make_paystack_request` | Execute a Paystack API request | -4. Start the server: - ``` - npm start - ``` +### Available Resources + +| Resource | Description | +| --- | --- | +| `openapi://operations/list` | List all available Paystack operation IDs | + +### Example + +When you ask your AI assistant something like *"Get me the last 5 transactions"*, here's what happens behind the scenes: + +1. The assistant calls `get_paystack_operation("transaction_list")` to look up the endpoint details +2. It gets back the method (`GET`), path (`/transaction`), and available query parameters +3. It then calls `make_paystack_request` with `{ method: "GET", path: "/transaction", data: { perPage: 5 } }` +4. You get your transactions + +## Development + +### Run locally (without building) + +For local development and testing, you can run the TypeScript source directly: + +```bash +PAYSTACK_SECRET_KEY_TEST=sk_test_... npm run dev +``` + +### Run with MCP Inspector + +```bash +npm run inspect +``` + +### Build + +```bash +npm run build +``` + +### Run tests + +```bash +npm test +``` + +## Troubleshooting + +| Issue | Solution | +| --- | --- | +| Server exits silently at startup | Check that `PAYSTACK_SECRET_KEY_TEST` is set (not `PAYSTACK_TEST_SECRET_KEY`) | +| "Invalid key" error | Key must start with `sk_test_` — live keys are not allowed | +| Tools not appearing in client | Ensure the server is running and the client config path is correct | +| Request timeouts | Check network connectivity to `api.paystack.co` | ## Contributing Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. +See [contributing.md](contributing.md) for more details. + ## License MIT diff --git a/src/index.ts b/src/index.ts index de22c51..71c2e20 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,7 @@ async function initializeServer() { try { const operation = openapi.getOperationById(operation_id.trim()); - console.log("Operation: ", operation) + console.error("Operation: ", operation) if (!operation) { return { @@ -93,16 +93,16 @@ async function initializeServer() { }, async ({ request }) => { try { - console.log("Request received:", request.method); - console.log("Request received:", request.path); - console.log("Request received:", request.data); + console.error("Request received:", request.method); + console.error("Request received:", request.path); + console.error("Request received:", request.data); const response = await paystackClient.makeRequest( request.method, request.path, request.data ) - console.log("response: ", response) + console.error("response: ", response) return { content: [ diff --git a/src/paystack-client.ts b/src/paystack-client.ts index c1fbe10..807c498 100644 --- a/src/paystack-client.ts +++ b/src/paystack-client.ts @@ -1,10 +1,7 @@ import { PaystackResponse, PaystackError } from "./types"; -import dotenv from 'dotenv'; +import { paystackConfig } from "./config"; -// Load environment variables -dotenv.config(); - -const PAYSTACK_BASE_URL = process.env.PAYSTACK_BASE_URL || 'https://api.paystack.co'; +const PAYSTACK_BASE_URL = paystackConfig.baseURL; const USER_AGENT = process.env.USER_AGENT || 'Paystack-MCP-Client'; class PaystackClient { @@ -87,5 +84,5 @@ class PaystackClient { } } export const paystackClient = new PaystackClient( - process.env.PAYSTACK_TEST_SECRET_KEY! -); \ No newline at end of file + paystackConfig.secretKey +);