Skip to content

Commit b85b54f

Browse files
setup npm distribution
1 parent 6774a1a commit b85b54f

9 files changed

Lines changed: 319 additions & 54 deletions

File tree

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that e
77
88
## Quick Start
99

10-
Clone the repo and build locally:
10+
Install and run via npm (recommended):
11+
12+
```bash
13+
npx @paystack/mcp-server --api-key sk_test_your_key_here
14+
```
15+
16+
Or for local development, clone and build:
1117

1218
```bash
1319
git clone https://github.com/PaystackOSS/paystack-mcp-server.git
@@ -16,7 +22,7 @@ npm install
1622
npm run build
1723
```
1824

19-
Then configure your MCP client to use the built server (see [Client Integration](#client-integration)).
25+
Then configure your MCP client to use the server (see [Client Integration](#client-integration)).
2026

2127
## Requirements
2228

@@ -28,15 +34,19 @@ Then configure your MCP client to use the built server (see [Client Integration]
2834

2935
| Environment Variable | Purpose |
3036
| -------------------------- | ------------------------------------------------------ |
31-
| `PAYSTACK_TEST_SECRET_KEY` | Your Paystack test secret key **(required)** |
37+
| `PAYSTACK_TEST_SECRET_KEY` | Your Paystack test secret key (fallback if no CLI arg) |
38+
39+
You can provide your API key in two ways:
40+
1. **CLI argument (recommended):** `--api-key sk_test_...`
41+
2. **Environment variable:** Set `PAYSTACK_TEST_SECRET_KEY`
3242

3343
> **Security note:** Only test keys (`sk_test_*`) are allowed. The server validates this at startup and will reject live keys.
3444
3545
## Client Integration
3646

3747
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.).
3848

39-
### Using a local build
49+
### Using npm (recommended)\n\nFor npm-installed server:\n\n```json\n{\n \"mcpServers\": {\n \"paystack\": {\n \"command\": \"npx\",\n \"args\": [\"@paystack/mcp-server\", \"--api-key\", \"sk_test_...\"]\n }\n }\n}\n```\n\n### Using a local build
4050

4151
If you've cloned and built the server locally:
4252

SETUP.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Editor Setup
2+
3+
Configure the Paystack MCP Server in supported editors with secure `.env`-based API key management.
4+
5+
- [Environment Setup](#environment-setup)
6+
- [VS Code](#vs-code)
7+
- [Cursor](#cursor)
8+
- [Claude Desktop](#claude-desktop)
9+
10+
---
11+
12+
## Environment Setup
13+
14+
Create your environment file:
15+
16+
1. **Copy the example file:**
17+
18+
```bash
19+
cp .env.example .env
20+
```
21+
22+
2. **Add your Paystack test secret key:**
23+
24+
```env
25+
PAYSTACK_TEST_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
26+
```
27+
28+
> [!IMPORTANT]
29+
> - Only **test keys** (starting with `sk_test_`) are accepted. The server rejects live keys.
30+
> - The `.env` file is already in `.gitignore`—never commit it to version control.
31+
32+
---
33+
34+
## VS Code
35+
36+
VS Code supports the `envFile` property, allowing you to load environment variables from a file instead of hardcoding them.
37+
38+
### Configuration
39+
40+
Create or update `.vscode/mcp.json` in your project:
41+
42+
```json
43+
{
44+
"servers": {
45+
"paystack": {
46+
"command": "node",
47+
"args": ["/path/to/paystack-mcp/build/index.js"],
48+
"envFile": "${workspaceFolder}/.env"
49+
}
50+
}
51+
}
52+
```
53+
54+
> [!NOTE]
55+
> Replace `/path/to/paystack-mcp` with the actual path to your cloned repository.
56+
57+
### Reload the MCP Server
58+
59+
After saving the configuration, reload VS Code or run the **"MCP: Restart Server"** command from the Command Palette.
60+
61+
---
62+
63+
## Cursor
64+
65+
Cursor supports both `envFile` and environment variable interpolation via `${env:VAR_NAME}`.
66+
67+
### Configuration Locations
68+
69+
| Scope | File Path |
70+
| ------- | ------------------------ |
71+
| Project | `.cursor/mcp.json` |
72+
| Global | `~/.cursor/mcp.json` |
73+
74+
### Using `envFile` (Recommended)
75+
76+
Create `.cursor/mcp.json` in your project:
77+
78+
```json
79+
{
80+
"mcpServers": {
81+
"paystack": {
82+
"command": "node",
83+
"args": ["/path/to/paystack-mcp/build/index.js"],
84+
"envFile": "${workspaceFolder}/.env"
85+
}
86+
}
87+
}
88+
```
89+
90+
---
91+
92+
## Claude Desktop
93+
94+
Claude Desktop uses an inline `env` object for environment variables. It does not support `envFile`.
95+
96+
### Configuration Location
97+
98+
| OS | File Path |
99+
| ------- | ------------------------------------------------------------ |
100+
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
101+
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
102+
103+
### Approach A: Inline Environment Variables (Simple)
104+
105+
Edit your `claude_desktop_config.json`:
106+
107+
```json
108+
{
109+
"mcpServers": {
110+
"paystack": {
111+
"command": "node",
112+
"args": ["/path/to/paystack-mcp/build/index.js"],
113+
"env": {
114+
"PAYSTACK_SECRET_KEY": "sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
115+
}
116+
}
117+
}
118+
}
119+
```
120+
121+
> [!WARNING]
122+
> This approach stores your API key directly in the config file. Ensure this file is not shared or committed to version control.
123+
124+
### Approach B: Using a Wrapper Script (Secure)
125+
126+
For better security, create a shell script that loads your `.env` file before starting the server.
127+
128+
1. **Create a wrapper script** (e.g., `run-paystack-mcp.sh`):
129+
130+
```bash
131+
#!/bin/bash
132+
set -a
133+
source /path/to/paystack-mcp/.env
134+
set +a
135+
exec node /path/to/paystack-mcp/build/index.js
136+
```
137+
138+
2. **Make it executable:**
139+
140+
```bash
141+
chmod +x /path/to/run-paystack-mcp.sh
142+
```
143+
144+
3. **Update your Claude Desktop config:**
145+
146+
```json
147+
{
148+
"mcpServers": {
149+
"paystack": {
150+
"command": "/path/to/run-paystack-mcp.sh"
151+
}
152+
}
153+
}
154+
```
155+
156+
---
157+
158+
## Troubleshooting
159+
160+
### Server not starting
161+
162+
- Verify Node.js v18+ is installed: `node --version`
163+
- Check the path to `build/index.js` is correct
164+
- Ensure your `.env` file exists and contains a valid `sk_test_*` key
165+
166+
### Environment variables not loading
167+
168+
- For VS Code/Cursor: Confirm `envFile` path is correct and the file exists
169+
- For Claude Desktop: Restart the application after config changes
170+
171+
### "Invalid API key" errors
172+
173+
- Ensure your key starts with `sk_test_` (live will be rejected)
174+
- Check for trailing whitespace in your `.env` file

package.json

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
{
2-
"name": "paystack-mcp",
2+
"name": "@paystack/mcp-server",
33
"version": "0.0.1",
4-
"description": "",
4+
"description": "Model Context Protocol (MCP) server for Paystack API integration",
5+
"mcpName": "io.github.PaystackOSS/paystack",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/PaystackOSS/paystack-mcp-server.git"
9+
},
510
"bin": {
6-
"paystack": "./build/index.js"
11+
"paystack-mcp": "./build/index.js"
712
},
813
"scripts": {
914
"build": "tsc && cp -r src/data build/",
@@ -15,14 +20,20 @@
1520
"files": [
1621
"build"
1722
],
18-
"keywords": [],
23+
"keywords": [
24+
"paystack",
25+
"mcp",
26+
"model-context-protocol",
27+
"api",
28+
"payment",
29+
"integration"
30+
],
1931
"author": "Andrew-Paystack",
2032
"license": "MIT",
2133
"dependencies": {
2234
"@modelcontextprotocol/inspector": "^0.18.0",
2335
"@modelcontextprotocol/sdk": "^1.26.0",
24-
"dotenv": "^17.2.3",
25-
"zod": "^4.3.6"
36+
"dotenv": "^17.2.3"
2637
},
2738
"devDependencies": {
2839
"@apidevtools/swagger-parser": "^12.1.0",

src/config.ts

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,46 @@
11
import dotenv from 'dotenv';
2-
import { z } from 'zod';
32

43
// Load environment variables from .env file
5-
dotenv.config();
4+
dotenv.config({quiet: true});
65

7-
// Define schema for required environment variables
8-
const envSchema = z.object({
9-
PAYSTACK_TEST_SECRET_KEY: z.string().min(30, 'PAYSTACK_TEST_SECRET_KEY is required').refine(val => val.startsWith('sk_test_'), {
10-
message: 'PAYSTACK_TEST_SECRET_KEY must begin with "sk_test_. No live keys allowed."',
11-
}),
12-
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
13-
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
14-
});
15-
16-
// Validate environment variables
17-
function validateEnv() {
18-
try {
19-
return envSchema.parse({
20-
PAYSTACK_TEST_SECRET_KEY: process.env.PAYSTACK_TEST_SECRET_KEY,
21-
NODE_ENV: process.env.NODE_ENV || 'development',
22-
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
23-
});
24-
} catch (error) {
25-
if (error instanceof z.ZodError) {
26-
// Environment validation failed - exit silently
27-
process.exit(1);
28-
}
29-
throw error;
6+
// Get configuration with optional CLI API key
7+
export function getConfig(cliApiKey?: string) {
8+
const apiKey = cliApiKey || process.env.PAYSTACK_TEST_SECRET_KEY;
9+
10+
if (!apiKey) {
11+
console.error('Error: PAYSTACK_TEST_SECRET_KEY is required');
12+
process.exit(1);
13+
}
14+
15+
if (!apiKey.startsWith('sk_test_')) {
16+
console.error('Error: PAYSTACK_TEST_SECRET_KEY must begin with "sk_test_". No live keys allowed.');
17+
process.exit(1);
18+
}
19+
20+
if (apiKey.length < 30) {
21+
console.error('Error: PAYSTACK_TEST_SECRET_KEY appears to be too short');
22+
process.exit(1);
3023
}
24+
25+
return {
26+
PAYSTACK_TEST_SECRET_KEY: apiKey,
27+
NODE_ENV: (process.env.NODE_ENV as 'development' | 'production' | 'test') || 'development',
28+
LOG_LEVEL: (process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error') || 'info',
29+
};
3130
}
3231

33-
// Export validated configuration
34-
export const config = validateEnv();
32+
// Export validated configuration (for backward compatibility, will use env var)
33+
export const config = getConfig();
34+
35+
// Paystack API configuration factory
36+
export function createPaystackConfig(cliApiKey?: string) {
37+
const cfg = getConfig(cliApiKey);
38+
return {
39+
baseURL: 'https://api.paystack.co',
40+
secretKey: cfg.PAYSTACK_TEST_SECRET_KEY,
41+
timeout: 30000, // 30 seconds
42+
} as const;
43+
}
3544

36-
// Paystack API configuration
37-
export const paystackConfig = {
38-
baseURL: 'https://api.paystack.co',
39-
secretKey: config.PAYSTACK_TEST_SECRET_KEY,
40-
timeout: 30000, // 30 seconds
41-
} as const;
45+
// Default paystack config (for backward compatibility)
46+
export const paystackConfig = createPaystackConfig();

0 commit comments

Comments
 (0)