-
Notifications
You must be signed in to change notification settings - Fork 10
setup npm distribution #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b85b54f
c3ca7ae
cb2c79a
18dea95
038afad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| # Editor Setup | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have README.md, why the additional file? Seems like this should all just go in the existing file instead
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tolu-paystack I figured that as tools keep increasing, people would like to add how to setup theirs. I wanted to keep Setup separate from the ReadMe so that the read-me is clear.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think let's wait till we get to that point to create a separate file. The readme isn't too long as-is. Plus you can just add a table of contents to the top of the file to make for easier navigation |
||
|
|
||
| Configure the Paystack MCP Server in supported editors with secure `.env`-based API key management. | ||
|
|
||
| - [Environment Setup](#environment-setup) | ||
| - [VS Code](#vs-code) | ||
| - [Cursor](#cursor) | ||
| - [Claude Desktop](#claude-desktop) | ||
|
|
||
| --- | ||
|
|
||
| ## Environment Setup | ||
|
|
||
| Create your environment file: | ||
|
|
||
| 1. **Copy the example file:** | ||
|
|
||
| ```bash | ||
| cp .env.example .env | ||
| ``` | ||
|
|
||
| 2. **Add your Paystack test secret key:** | ||
|
|
||
| ```env | ||
| PAYSTACK_TEST_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
| ``` | ||
|
|
||
| > [!IMPORTANT] | ||
| > - Only **test keys** (starting with `sk_test_`) are accepted. The server rejects live keys. | ||
| > - The `.env` file is already in `.gitignore`—never commit it to version control. | ||
|
|
||
| --- | ||
|
|
||
| ## VS Code | ||
|
|
||
| VS Code supports the `envFile` property, allowing you to load environment variables from a file instead of hardcoding them. | ||
|
|
||
| ### Configuration | ||
|
|
||
| Create or update `.vscode/mcp.json` in your project: | ||
|
|
||
| ```json | ||
| { | ||
| "servers": { | ||
| "paystack": { | ||
| "command": "node", | ||
| "args": ["/path/to/paystack-mcp/build/index.js"], | ||
| "envFile": "${workspaceFolder}/.env" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > Replace `/path/to/paystack-mcp` with the actual path to your cloned repository. | ||
|
|
||
| ### Reload the MCP Server | ||
|
|
||
| After saving the configuration, reload VS Code or run the **"MCP: Restart Server"** command from the Command Palette. | ||
|
|
||
| --- | ||
|
|
||
| ## Cursor | ||
|
|
||
| Cursor supports both `envFile` and environment variable interpolation via `${env:VAR_NAME}`. | ||
|
|
||
| ### Configuration Locations | ||
|
|
||
| | Scope | File Path | | ||
| | ------- | ------------------------ | | ||
| | Project | `.cursor/mcp.json` | | ||
| | Global | `~/.cursor/mcp.json` | | ||
|
|
||
| ### Using `envFile` (Recommended) | ||
|
|
||
| Create `.cursor/mcp.json` in your project: | ||
|
|
||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "paystack": { | ||
| "command": "node", | ||
| "args": ["/path/to/paystack-mcp/build/index.js"], | ||
| "envFile": "${workspaceFolder}/.env" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Claude Desktop | ||
|
|
||
| Claude Desktop uses an inline `env` object for environment variables. It does not support `envFile`. | ||
|
|
||
| ### Configuration Location | ||
|
|
||
| | OS | File Path | | ||
| | ------- | ------------------------------------------------------------ | | ||
| | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | | ||
| | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | | ||
|
|
||
| ### Approach A: Inline Environment Variables (Simple) | ||
|
|
||
| Edit your `claude_desktop_config.json`: | ||
|
|
||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "paystack": { | ||
| "command": "node", | ||
| "args": ["/path/to/paystack-mcp/build/index.js"], | ||
| "env": { | ||
| "PAYSTACK_SECRET_KEY": "sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > [!WARNING] | ||
| > This approach stores your API key directly in the config file. Ensure this file is not shared or committed to version control. | ||
|
|
||
| ### Approach B: Using a Wrapper Script (Secure) | ||
|
|
||
| For better security, create a shell script that loads your `.env` file before starting the server. | ||
|
|
||
| 1. **Create a wrapper script** (e.g., `run-paystack-mcp.sh`): | ||
|
|
||
| ```bash | ||
| #!/bin/bash | ||
| set -a | ||
| source /path/to/paystack-mcp/.env | ||
| set +a | ||
| exec node /path/to/paystack-mcp/build/index.js | ||
| ``` | ||
|
|
||
| 2. **Make it executable:** | ||
|
|
||
| ```bash | ||
| chmod +x /path/to/run-paystack-mcp.sh | ||
| ``` | ||
|
|
||
| 3. **Update your Claude Desktop config:** | ||
|
|
||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "paystack": { | ||
| "command": "/path/to/run-paystack-mcp.sh" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Server not starting | ||
|
|
||
| - Verify Node.js v18+ is installed: `node --version` | ||
| - Check the path to `build/index.js` is correct | ||
| - Ensure your `.env` file exists and contains a valid `sk_test_*` key | ||
|
|
||
| ### Environment variables not loading | ||
|
|
||
| - For VS Code/Cursor: Confirm `envFile` path is correct and the file exists | ||
| - For Claude Desktop: Restart the application after config changes | ||
|
|
||
| ### "Invalid API key" errors | ||
|
|
||
| - Ensure your key starts with `sk_test_` (live will be rejected) | ||
| - Check for trailing whitespace in your `.env` file | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,14 @@ | ||
| { | ||
| "name": "paystack-mcp", | ||
| "name": "@paystack/mcp-server", | ||
| "version": "0.0.1", | ||
| "description": "", | ||
| "description": "Model Context Protocol (MCP) server for Paystack API integration", | ||
| "mcpName": "io.github.PaystackOSS/paystack", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/PaystackOSS/paystack-mcp-server.git" | ||
| }, | ||
| "bin": { | ||
| "paystack": "./build/index.js" | ||
| "paystack-mcp": "./build/index.js" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use |
||
| }, | ||
| "scripts": { | ||
| "build": "tsc && cp -r src/data build/", | ||
|
|
@@ -15,14 +20,20 @@ | |
| "files": [ | ||
| "build" | ||
| ], | ||
| "keywords": [], | ||
| "keywords": [ | ||
| "paystack", | ||
| "mcp", | ||
| "model-context-protocol", | ||
| "api", | ||
| "payment", | ||
| "integration" | ||
| ], | ||
| "author": "Andrew-Paystack", | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "@modelcontextprotocol/inspector": "^0.18.0", | ||
| "@modelcontextprotocol/sdk": "^1.26.0", | ||
| "dotenv": "^17.2.3", | ||
| "zod": "^4.3.6" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see zod is still being imported at the beginning of make-paystack-request.ts, won't the build fail if you've removed it as a dependency? |
||
| "dotenv": "^17.2.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@apidevtools/swagger-parser": "^12.1.0", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,41 +1,46 @@ | ||
| import dotenv from 'dotenv'; | ||
| import { z } from 'zod'; | ||
|
|
||
| // Load environment variables from .env file | ||
| dotenv.config(); | ||
| dotenv.config({quiet: true}); | ||
|
|
||
| // Define schema for required environment variables | ||
| const envSchema = z.object({ | ||
| PAYSTACK_TEST_SECRET_KEY: z.string().min(30, 'PAYSTACK_TEST_SECRET_KEY is required').refine(val => val.startsWith('sk_test_'), { | ||
| message: 'PAYSTACK_TEST_SECRET_KEY must begin with "sk_test_. No live keys allowed."', | ||
| }), | ||
| NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), | ||
| LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'), | ||
| }); | ||
|
|
||
| // Validate environment variables | ||
| function validateEnv() { | ||
| try { | ||
| return envSchema.parse({ | ||
| PAYSTACK_TEST_SECRET_KEY: process.env.PAYSTACK_TEST_SECRET_KEY, | ||
| NODE_ENV: process.env.NODE_ENV || 'development', | ||
| LOG_LEVEL: process.env.LOG_LEVEL || 'info', | ||
| }); | ||
| } catch (error) { | ||
| if (error instanceof z.ZodError) { | ||
| // Environment validation failed - exit silently | ||
| process.exit(1); | ||
| } | ||
| throw error; | ||
| // Get configuration with optional CLI API key | ||
| export function getConfig(cliApiKey?: string) { | ||
| const apiKey = cliApiKey || process.env.PAYSTACK_TEST_SECRET_KEY; | ||
|
|
||
| if (!apiKey) { | ||
| console.error('Error: PAYSTACK_TEST_SECRET_KEY is required'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| if (!apiKey.startsWith('sk_test_')) { | ||
| console.error('Error: PAYSTACK_TEST_SECRET_KEY must begin with "sk_test_". No live keys allowed.'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| if (apiKey.length < 30) { | ||
| console.error('Error: PAYSTACK_TEST_SECRET_KEY appears to be too short'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| return { | ||
| PAYSTACK_TEST_SECRET_KEY: apiKey, | ||
| NODE_ENV: (process.env.NODE_ENV as 'development' | 'production' | 'test') || 'development', | ||
| LOG_LEVEL: (process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error') || 'info', | ||
| }; | ||
| } | ||
|
|
||
| // Export validated configuration | ||
| export const config = validateEnv(); | ||
| // Export validated configuration (for backward compatibility, will use env var) | ||
| export const config = getConfig(); | ||
|
|
||
| // Paystack API configuration factory | ||
| export function createPaystackConfig(cliApiKey?: string) { | ||
| const cfg = getConfig(cliApiKey); | ||
| return { | ||
| baseURL: 'https://api.paystack.co', | ||
| secretKey: cfg.PAYSTACK_TEST_SECRET_KEY, | ||
| timeout: 30000, // 30 seconds | ||
| } as const; | ||
| } | ||
|
|
||
| // Paystack API configuration | ||
| export const paystackConfig = { | ||
| baseURL: 'https://api.paystack.co', | ||
| secretKey: config.PAYSTACK_TEST_SECRET_KEY, | ||
| timeout: 30000, // 30 seconds | ||
| } as const; | ||
| // Default paystack config (for backward compatibility) | ||
| export const paystackConfig = createPaystackConfig(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you've got some formatting issues here @Andrew-Paystack, I think you need to remove the newline characters