@armor/zuora-mcp 0.0.0-development

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.env.example +16 -0
  2. package/README.md +249 -0
  3. package/dist/cli.d.ts +15 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +73 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +26 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +56 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/index.d.ts +22 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +148 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/prompts.d.ts +11 -0
  16. package/dist/prompts.d.ts.map +1 -0
  17. package/dist/prompts.js +236 -0
  18. package/dist/prompts.js.map +1 -0
  19. package/dist/resources.d.ts +11 -0
  20. package/dist/resources.d.ts.map +1 -0
  21. package/dist/resources.js +526 -0
  22. package/dist/resources.js.map +1 -0
  23. package/dist/setup.d.ts +12 -0
  24. package/dist/setup.d.ts.map +1 -0
  25. package/dist/setup.js +188 -0
  26. package/dist/setup.js.map +1 -0
  27. package/dist/token-manager.d.ts +34 -0
  28. package/dist/token-manager.d.ts.map +1 -0
  29. package/dist/token-manager.js +103 -0
  30. package/dist/token-manager.js.map +1 -0
  31. package/dist/tools.d.ts +1096 -0
  32. package/dist/tools.d.ts.map +1 -0
  33. package/dist/tools.js +2841 -0
  34. package/dist/tools.js.map +1 -0
  35. package/dist/types.d.ts +758 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +5 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/zoql-helpers.d.ts +68 -0
  40. package/dist/zoql-helpers.d.ts.map +1 -0
  41. package/dist/zoql-helpers.js +154 -0
  42. package/dist/zoql-helpers.js.map +1 -0
  43. package/dist/zuora-client.d.ts +184 -0
  44. package/dist/zuora-client.d.ts.map +1 -0
  45. package/dist/zuora-client.js +583 -0
  46. package/dist/zuora-client.js.map +1 -0
  47. package/package.json +60 -0
package/.env.example ADDED
@@ -0,0 +1,16 @@
1
+ # Zuora OAuth Configuration
2
+ # Required: OAuth2 Client ID (create at Zuora Admin > Settings > Administration > OAuth Clients)
3
+ ZUORA_CLIENT_ID=your-oauth-client-id
4
+
5
+ # Required: OAuth2 Client Secret
6
+ ZUORA_CLIENT_SECRET=your-oauth-client-secret
7
+
8
+ # Required: Zuora base URL for your environment
9
+ # Production US: https://rest.zuora.com
10
+ # Sandbox US: https://rest.apisandbox.zuora.com
11
+ # Production EU: https://rest.eu.zuora.com
12
+ # Sandbox EU: https://rest.sandbox.eu.zuora.com
13
+ ZUORA_BASE_URL=https://rest.apisandbox.zuora.com
14
+
15
+ # Optional: Enable debug logging (true/false)
16
+ DEBUG=false
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # Zuora MCP Server
2
+
3
+ A Model Context Protocol (MCP) server that enables Claude to interact with Zuora's billing platform. Query accounts, invoices, subscriptions, payments, and execute ZOQL queries directly from Claude Code.
4
+
5
+ ## Quick Start
6
+
7
+ Run one command — no cloning, no building:
8
+
9
+ ```bash
10
+ npx @armor/zuora-mcp setup
11
+ ```
12
+
13
+ The setup wizard will:
14
+ 1. Ask for your Zuora OAuth credentials
15
+ 2. Let you choose your Zuora environment (sandbox, production, EU)
16
+ 3. Auto-configure Claude Code and/or Claude Desktop
17
+
18
+ Then restart Claude Code and the Zuora tools are ready.
19
+
20
+ ### Prerequisites
21
+
22
+ - Node.js 20+
23
+ - Zuora OAuth credentials (create at Zuora Admin > Settings > Administration > OAuth Clients)
24
+
25
+ ### Manual Configuration (Alternative)
26
+
27
+ If you prefer to configure manually, add to `~/.claude/.mcp.json`:
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "zuora": {
33
+ "command": "npx",
34
+ "args": ["-y", "@armor/zuora-mcp"],
35
+ "env": {
36
+ "ZUORA_CLIENT_ID": "your-client-id",
37
+ "ZUORA_CLIENT_SECRET": "your-client-secret",
38
+ "ZUORA_BASE_URL": "https://rest.apisandbox.zuora.com"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### Install from Source
46
+
47
+ ```bash
48
+ git clone git@github.com:armor/zuora-mcp.git
49
+ cd zuora-mcp
50
+ npm install
51
+ npm run build
52
+ ```
53
+
54
+ When installing from source, point to the built file in your MCP config:
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "zuora": {
60
+ "command": "node",
61
+ "args": ["/path/to/zuora-mcp/dist/index.js"],
62
+ "env": {
63
+ "ZUORA_CLIENT_ID": "your-client-id",
64
+ "ZUORA_CLIENT_SECRET": "your-client-secret",
65
+ "ZUORA_BASE_URL": "https://rest.apisandbox.zuora.com"
66
+ }
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### Configuration
73
+
74
+ Required environment variables:
75
+
76
+ | Variable | Description |
77
+ |----------|-------------|
78
+ | `ZUORA_CLIENT_ID` | OAuth2 client ID |
79
+ | `ZUORA_CLIENT_SECRET` | OAuth2 client secret |
80
+ | `ZUORA_BASE_URL` | One of the Zuora base URLs (see below) |
81
+
82
+ Optional variables:
83
+
84
+ | Variable | Description |
85
+ |----------|-------------|
86
+ | `DEBUG` | Set to `true` for verbose logging |
87
+
88
+ #### Zuora Base URLs
89
+
90
+ | Environment | URL |
91
+ |-------------|-----|
92
+ | US Production | `https://rest.zuora.com` |
93
+ | US Sandbox | `https://rest.apisandbox.zuora.com` |
94
+ | EU Production | `https://rest.eu.zuora.com` |
95
+ | EU Sandbox | `https://rest.sandbox.eu.zuora.com` |
96
+
97
+ ### Getting Zuora OAuth Credentials
98
+
99
+ 1. Log into Zuora (production or sandbox)
100
+ 2. Navigate to **Settings > Administration > Manage Users**
101
+ 3. Select your user or create a service account
102
+ 4. Go to **OAuth Clients** tab and create a new client
103
+ 5. Copy the **Client ID** and **Client Secret** (secret is shown only once)
104
+
105
+ ## Available Tools
106
+
107
+ ### Account Tools
108
+
109
+ | Tool | Description |
110
+ |------|-------------|
111
+ | `get_account` | Get account details by key (ID or account number) |
112
+ | `get_account_summary` | Get comprehensive account summary with balances, subscriptions, invoices, and payments |
113
+
114
+ ### Invoice Tools
115
+
116
+ | Tool | Description |
117
+ |------|-------------|
118
+ | `get_invoice` | Get invoice details including line items |
119
+ | `list_invoices` | List invoices for an account with pagination |
120
+
121
+ ### Subscription Tools
122
+
123
+ | Tool | Description |
124
+ |------|-------------|
125
+ | `get_subscription` | Get subscription details with rate plans and charges |
126
+ | `list_subscriptions` | List all subscriptions for an account |
127
+
128
+ ### Payment Tools
129
+
130
+ | Tool | Description |
131
+ |------|-------------|
132
+ | `get_payment` | Get payment details |
133
+ | `list_payments` | List payments with optional account filter and pagination |
134
+
135
+ ### ZOQL Query Tools
136
+
137
+ | Tool | Description |
138
+ |------|-------------|
139
+ | `execute_zoql_query` | Execute a ZOQL query for ad-hoc data retrieval |
140
+ | `continue_zoql_query` | Continue paginated ZOQL results using queryLocator |
141
+
142
+ ### Product Catalog
143
+
144
+ | Tool | Description |
145
+ |------|-------------|
146
+ | `list_products` | List products with rate plans and pricing |
147
+
148
+ ## Upgrading
149
+
150
+ ```bash
151
+ npm update -g @armor/zuora-mcp
152
+ ```
153
+
154
+ ## Development
155
+
156
+ ```bash
157
+ npm run dev # Run with tsx (no build required)
158
+ npm run build # Build TypeScript to dist/
159
+ npm run lint # Run ESLint
160
+ npm run typecheck # Type check without building
161
+ npm test # Build and run tests
162
+ npm run clean # Remove dist/
163
+ ```
164
+
165
+ ### Debug Mode
166
+
167
+ Set `DEBUG=true` to enable verbose logging to stderr:
168
+
169
+ ```bash
170
+ DEBUG=true npm start
171
+ ```
172
+
173
+ Debug output goes to stderr to avoid corrupting the stdio JSON-RPC transport.
174
+
175
+ ### Release Process
176
+
177
+ This project uses semantic-release with branch-based publishing:
178
+
179
+ | Branch | npm Tag | Description |
180
+ |--------|---------|-------------|
181
+ | `dev` | `alpha` | Development pre-releases |
182
+ | `stage` | `beta` | Staging pre-releases |
183
+ | `main` | `latest` | Production releases |
184
+
185
+ Merging to any of these branches triggers the CD pipeline which:
186
+ 1. Runs lint, typecheck, build, and tests
187
+ 2. Determines the next version from commit messages
188
+ 3. Creates a GitHub release with notes
189
+ 4. Publishes to npm with the appropriate tag
190
+
191
+ #### Commit Convention
192
+
193
+ Follow conventional commits for automatic version bumps:
194
+
195
+ | Prefix | Version Bump |
196
+ |--------|--------------|
197
+ | `feat:` | Minor (1.x.0) |
198
+ | `fix:` | Patch (1.0.x) |
199
+ | `breaking:` | Major (x.0.0) |
200
+
201
+ ## Architecture
202
+
203
+ ```
204
+ src/
205
+ ├── cli.ts # CLI entry point (bin): server, setup, --help, --version
206
+ ├── setup.ts # Interactive setup wizard (zero external deps)
207
+ ├── index.ts # MCP server bootstrap (exports startServer)
208
+ ├── config.ts # Zod-validated environment configuration
209
+ ├── token-manager.ts # OAuth2 token lifecycle (refresh, coalescing)
210
+ ├── zuora-client.ts # Zuora REST API client with resilience
211
+ ├── tools.ts # Tool definitions, Zod schemas, handlers
212
+ ├── zoql-helpers.ts # ZOQL query composition utilities
213
+ ├── resources.ts # MCP resources (data model, ZOQL guides)
214
+ ├── prompts.ts # MCP prompts (finance workflow templates)
215
+ └── types.ts # TypeScript interfaces
216
+ ```
217
+
218
+ ### Authentication
219
+
220
+ Uses OAuth 2.0 Client Credentials flow:
221
+ - Tokens are stored in memory only (not persisted)
222
+ - Proactive refresh 60 seconds before expiry
223
+ - Promise coalescing prevents duplicate refresh requests under concurrency
224
+ - Automatic 401 retry with token refresh
225
+
226
+ ### Resilience
227
+
228
+ - Exponential backoff with jitter on 429/502/503/504
229
+ - Idempotent methods (GET, PUT, DELETE) retry on transport failures
230
+ - POST requests are NOT retried on HTTP errors (financial safety)
231
+ - 20-second request timeout with AbortController
232
+
233
+ ### Security
234
+
235
+ - All inputs validated with Zod schemas
236
+ - Sensitive fields (card numbers, bank accounts) redacted from debug logs
237
+ - Bearer tokens scrubbed from error messages
238
+ - OAuth credentials never logged
239
+ - Base URL validated against known Zuora endpoints at startup
240
+
241
+ ## Version History
242
+
243
+ ### v1.0.0
244
+
245
+ - Initial release with 11 read-only tools
246
+ - OAuth 2.0 authentication with token lifecycle management
247
+ - Account, invoice, subscription, payment, and ZOQL query support
248
+ - Product catalog access
249
+ - Resilient HTTP client with retry and backoff
package/dist/cli.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for zuora-mcp.
4
+ *
5
+ * Routes between:
6
+ * zuora-mcp → starts the MCP server (stdio transport)
7
+ * zuora-mcp setup → runs the interactive setup wizard
8
+ * zuora-mcp --help → prints usage
9
+ * zuora-mcp --version → prints version from package.json
10
+ *
11
+ * Dynamic imports keep the server and setup wizard fully isolated —
12
+ * `setup` never loads the MCP SDK, and server code only loads when serving.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
package/dist/cli.js ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for zuora-mcp.
4
+ *
5
+ * Routes between:
6
+ * zuora-mcp → starts the MCP server (stdio transport)
7
+ * zuora-mcp setup → runs the interactive setup wizard
8
+ * zuora-mcp --help → prints usage
9
+ * zuora-mcp --version → prints version from package.json
10
+ *
11
+ * Dynamic imports keep the server and setup wizard fully isolated —
12
+ * `setup` never loads the MCP SDK, and server code only loads when serving.
13
+ */
14
+ import { readFileSync } from "node:fs";
15
+ function getVersion() {
16
+ try {
17
+ const packageJsonPath = new URL("../package.json", import.meta.url);
18
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
19
+ if (typeof pkg.version === "string" && pkg.version.length) {
20
+ return pkg.version;
21
+ }
22
+ }
23
+ catch {
24
+ // Fall through to safe default.
25
+ }
26
+ return "0.0.0";
27
+ }
28
+ function printHelp() {
29
+ const version = getVersion();
30
+ console.log(`zuora-mcp v${version} — Zuora Billing MCP Server
31
+
32
+ Usage:
33
+ zuora-mcp Start the MCP server (stdio transport)
34
+ zuora-mcp setup Interactive setup wizard for Claude Code / Desktop
35
+ zuora-mcp --help Show this help message
36
+ zuora-mcp --version Show version number
37
+
38
+ Environment variables (required for server mode):
39
+ ZUORA_CLIENT_ID OAuth2 client ID from Zuora Admin
40
+ ZUORA_CLIENT_SECRET OAuth2 client secret
41
+ ZUORA_BASE_URL Zuora API base URL
42
+
43
+ More info: https://github.com/armor/zuora-mcp`);
44
+ }
45
+ async function run() {
46
+ const arg = process.argv[2];
47
+ if (arg === "--help" || arg === "-h") {
48
+ printHelp();
49
+ return;
50
+ }
51
+ if (arg === "--version" || arg === "-v") {
52
+ console.log(getVersion());
53
+ return;
54
+ }
55
+ if (arg === "setup") {
56
+ const { runSetup } = await import("./setup.js");
57
+ await runSetup();
58
+ return;
59
+ }
60
+ if (arg !== undefined) {
61
+ console.error(`Unknown command: ${arg}\n`);
62
+ printHelp();
63
+ process.exit(1);
64
+ }
65
+ // Default: start the MCP server
66
+ const { startServer } = await import("./index.js");
67
+ await startServer();
68
+ }
69
+ run().catch((error) => {
70
+ console.error("Fatal error:", error);
71
+ process.exit(1);
72
+ });
73
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAE3D,CAAC;QACF,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1D,OAAO,GAAG,CAAC,OAAO,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO;;;;;;;;;;;;;8CAaW,CAAC,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5B,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACrC,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,QAAQ,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;QAC3C,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gCAAgC;IAChC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACpB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Configuration management for Zuora MCP Server
3
+ * Security-first: No hardcoded values, all from environment
4
+ */
5
+ import { z } from "zod";
6
+ declare const configSchema: z.ZodObject<{
7
+ zuoraClientId: z.ZodString;
8
+ zuoraClientSecret: z.ZodString;
9
+ zuoraBaseUrl: z.ZodEffects<z.ZodString, string, string>;
10
+ debug: z.ZodDefault<z.ZodBoolean>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ zuoraClientId: string;
13
+ zuoraClientSecret: string;
14
+ zuoraBaseUrl: string;
15
+ debug: boolean;
16
+ }, {
17
+ zuoraClientId: string;
18
+ zuoraClientSecret: string;
19
+ zuoraBaseUrl: string;
20
+ debug?: boolean | undefined;
21
+ }>;
22
+ export type Config = z.infer<typeof configSchema>;
23
+ export declare function loadConfig(): Config;
24
+ export declare function validateConfig(): void;
25
+ export {};
26
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;EAoBhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAkBnC;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
package/dist/config.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Configuration management for Zuora MCP Server
3
+ * Security-first: No hardcoded values, all from environment
4
+ */
5
+ import { config as dotenvConfig } from "dotenv";
6
+ import { z } from "zod";
7
+ // Load .env files with quiet mode to prevent stdout corruption of JSON-RPC.
8
+ // Precedence: process env > .env.local > .env
9
+ // Base .env does NOT use override so process-level env vars take precedence.
10
+ // .env.local uses override so it can override both .env and process env for local dev.
11
+ dotenvConfig({ path: ".env", quiet: true });
12
+ dotenvConfig({ path: ".env.local", override: true, quiet: true });
13
+ const VALID_ZUORA_BASE_URLS = new Set([
14
+ "https://rest.zuora.com",
15
+ "https://rest.apisandbox.zuora.com",
16
+ "https://rest.eu.zuora.com",
17
+ "https://rest.sandbox.eu.zuora.com",
18
+ ]);
19
+ const configSchema = z.object({
20
+ zuoraClientId: z
21
+ .string()
22
+ .min(1, "ZUORA_CLIENT_ID is required")
23
+ .describe("OAuth2 client ID from Zuora Admin"),
24
+ zuoraClientSecret: z
25
+ .string()
26
+ .min(1, "ZUORA_CLIENT_SECRET is required")
27
+ .describe("OAuth2 client secret"),
28
+ zuoraBaseUrl: z
29
+ .string()
30
+ .url("ZUORA_BASE_URL must be a valid URL")
31
+ .refine((url) => VALID_ZUORA_BASE_URLS.has(url.replace(/\/$/, "")), {
32
+ message: `ZUORA_BASE_URL must be one of: ${[...VALID_ZUORA_BASE_URLS].join(", ")}`,
33
+ })
34
+ .describe("Zuora REST API base URL"),
35
+ debug: z.boolean().default(false).describe("Enable debug logging"),
36
+ });
37
+ export function loadConfig() {
38
+ const rawConfig = {
39
+ zuoraClientId: process.env.ZUORA_CLIENT_ID,
40
+ zuoraClientSecret: process.env.ZUORA_CLIENT_SECRET,
41
+ zuoraBaseUrl: process.env.ZUORA_BASE_URL?.replace(/\/$/, ""),
42
+ debug: process.env.DEBUG === "true",
43
+ };
44
+ const result = configSchema.safeParse(rawConfig);
45
+ if (!result.success) {
46
+ const errors = result.error.errors
47
+ .map((e) => ` - ${e.path.join(".")}: ${e.message}`)
48
+ .join("\n");
49
+ throw new Error(`Configuration validation failed:\n${errors}`);
50
+ }
51
+ return result.data;
52
+ }
53
+ export function validateConfig() {
54
+ loadConfig();
55
+ }
56
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,4EAA4E;AAC5E,8CAA8C;AAC9C,6EAA6E;AAC7E,uFAAuF;AACvF,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,YAAY,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAElE,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,wBAAwB;IACxB,mCAAmC;IACnC,2BAA2B;IAC3B,mCAAmC;CACpC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,6BAA6B,CAAC;SACrC,QAAQ,CAAC,mCAAmC,CAAC;IAChD,iBAAiB,EAAE,CAAC;SACjB,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC;SACzC,QAAQ,CAAC,sBAAsB,CAAC;IACnC,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,GAAG,CAAC,oCAAoC,CAAC;SACzC,MAAM,CACL,CAAC,GAAG,EAAE,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAC1D;QACE,OAAO,EAAE,kCAAkC,CAAC,GAAG,qBAAqB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KACnF,CACF;SACA,QAAQ,CAAC,yBAAyB,CAAC;IACtC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACnE,CAAC,CAAC;AAIH,MAAM,UAAU,UAAU;IACxB,MAAM,SAAS,GAAG;QAChB,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QAC1C,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAClD,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QAC5D,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM;KACpC,CAAC;IAEF,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEjD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,UAAU,EAAE,CAAC;AACf,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Zuora MCP Server
3
+ *
4
+ * A Model Context Protocol server for Zuora billing operations.
5
+ * Provides account, invoice, subscription, payment, and ZOQL query tools.
6
+ *
7
+ * Features:
8
+ * - OAuth 2.0 authentication with automatic token lifecycle
9
+ * - Account and billing entity read operations
10
+ * - ZOQL query support with pagination
11
+ * - Product catalog access
12
+ * - Resilient HTTP client with retry and backoff
13
+ *
14
+ * Security:
15
+ * - No hardcoded credentials
16
+ * - Input validation with Zod schemas
17
+ * - Sensitive data redaction in logs
18
+ * - OAuth token promise coalescing for concurrency safety
19
+ */
20
+ declare function main(): Promise<void>;
21
+ export { main as startServer };
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA8DH,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+HnC;AAED,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Zuora MCP Server
3
+ *
4
+ * A Model Context Protocol server for Zuora billing operations.
5
+ * Provides account, invoice, subscription, payment, and ZOQL query tools.
6
+ *
7
+ * Features:
8
+ * - OAuth 2.0 authentication with automatic token lifecycle
9
+ * - Account and billing entity read operations
10
+ * - ZOQL query support with pagination
11
+ * - Product catalog access
12
+ * - Resilient HTTP client with retry and backoff
13
+ *
14
+ * Security:
15
+ * - No hardcoded credentials
16
+ * - Input validation with Zod schemas
17
+ * - Sensitive data redaction in logs
18
+ * - OAuth token promise coalescing for concurrency safety
19
+ */
20
+ import { readFileSync } from "node:fs";
21
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
23
+ import { CallToolRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
24
+ import { loadConfig } from "./config.js";
25
+ import { ZuoraClient } from "./zuora-client.js";
26
+ import { toolRegistrations, ToolHandlers } from "./tools.js";
27
+ import { registerResources } from "./resources.js";
28
+ import { registerPrompts } from "./prompts.js";
29
+ const SERVER_NAME = "zuora-mcp";
30
+ function getServerVersion() {
31
+ try {
32
+ const packageJsonPath = new URL("../package.json", import.meta.url);
33
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
34
+ if (typeof packageJson.version === "string" &&
35
+ packageJson.version.length) {
36
+ return packageJson.version;
37
+ }
38
+ }
39
+ catch {
40
+ // Fall through to safe default.
41
+ }
42
+ return "0.0.0";
43
+ }
44
+ function toCallToolResult(result) {
45
+ const structuredContent = {
46
+ success: result.success,
47
+ message: result.message,
48
+ };
49
+ if (result.data !== undefined) {
50
+ structuredContent.data = result.data;
51
+ }
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: JSON.stringify(structuredContent, null, 2),
57
+ },
58
+ ],
59
+ structuredContent,
60
+ isError: !result.success,
61
+ };
62
+ }
63
+ async function main() {
64
+ // Validate configuration before starting
65
+ let config;
66
+ try {
67
+ config = loadConfig();
68
+ }
69
+ catch (error) {
70
+ console.error("Configuration error:", error instanceof Error ? error.message : error);
71
+ console.error("\nRequired environment variables:");
72
+ console.error(" ZUORA_CLIENT_ID - OAuth2 client ID from Zuora Admin");
73
+ console.error(" ZUORA_CLIENT_SECRET - OAuth2 client secret");
74
+ console.error(" ZUORA_BASE_URL - Zuora API base URL (e.g., https://rest.apisandbox.zuora.com)");
75
+ console.error("\nOptional:");
76
+ console.error(" DEBUG=true - Enable debug logging");
77
+ process.exit(1);
78
+ }
79
+ const client = new ZuoraClient(config);
80
+ const handlers = new ToolHandlers(client);
81
+ // Create MCP server
82
+ const server = new McpServer({
83
+ name: SERVER_NAME,
84
+ version: getServerVersion(),
85
+ });
86
+ // Register tools for MCP capability advertisement (tool listing).
87
+ // Dispatch is handled by the setRequestHandler override below.
88
+ for (const registration of toolRegistrations) {
89
+ server.registerTool(registration.name, {
90
+ description: registration.description,
91
+ inputSchema: registration.inputSchema,
92
+ }, async (args) => {
93
+ // Stub: actual dispatch is handled by setRequestHandler below.
94
+ const result = await registration.invoke(handlers, args);
95
+ return toCallToolResult(result);
96
+ });
97
+ }
98
+ // Register MCP resources (Zuora data model, ZOQL guides)
99
+ registerResources(server);
100
+ // Register MCP prompts (finance workflow templates)
101
+ registerPrompts(server);
102
+ // Map-based dispatch with protocol-level error handling.
103
+ // This overrides the SDK's default CallToolRequest handler to provide
104
+ // proper McpError responses for unknown tools and invalid parameters.
105
+ const registrationByName = new Map(toolRegistrations.map((registration) => [
106
+ registration.name,
107
+ registration,
108
+ ]));
109
+ server.server.setRequestHandler(CallToolRequestSchema, async (request) => {
110
+ const { name, arguments: args } = request.params;
111
+ const registration = registrationByName.get(name);
112
+ if (!registration) {
113
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
114
+ }
115
+ if (config.debug) {
116
+ console.error(`[${SERVER_NAME}] Tool called: ${registration.name}`, args);
117
+ }
118
+ let validatedArgs;
119
+ try {
120
+ validatedArgs = registration.inputSchema.parse(args);
121
+ }
122
+ catch (error) {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for ${registration.name}: ${message}`);
125
+ }
126
+ try {
127
+ const result = await registration.invoke(handlers, validatedArgs);
128
+ return toCallToolResult(result);
129
+ }
130
+ catch (error) {
131
+ const message = error instanceof Error ? error.message : String(error);
132
+ return toCallToolResult({
133
+ success: false,
134
+ message: `Unhandled tool error: ${message}`,
135
+ });
136
+ }
137
+ });
138
+ // Connect via stdio transport
139
+ const transport = new StdioServerTransport();
140
+ await server.connect(transport);
141
+ if (config.debug) {
142
+ console.error(`[${SERVER_NAME}] Server started successfully`);
143
+ console.error(`[${SERVER_NAME}] Connected to ${config.zuoraBaseUrl}`);
144
+ console.error(`[${SERVER_NAME}] Tools registered: ${toolRegistrations.length}`);
145
+ }
146
+ }
147
+ export { main as startServer };
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * MCP Prompt Definitions for Zuora Finance Workflows
3
+ *
4
+ * Workflow templates that guide Claude through multi-tool sequences
5
+ * for common finance scenarios. Each prompt provides structured
6
+ * instructions for using composite and base tools in the right order
7
+ * with proper formatting.
8
+ */
9
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ export declare function registerPrompts(server: McpServer): void;
11
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6PvD"}