quantix-mcp 1.0.0
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.
Potentially problematic release.
This version of quantix-mcp might be problematic. Click here for more details.
- package/.github/agents/copilot-instructions.md +32 -0
- package/.github/agents/speckit.analyze.agent.md +184 -0
- package/.github/agents/speckit.checklist.agent.md +294 -0
- package/.github/agents/speckit.clarify.agent.md +181 -0
- package/.github/agents/speckit.constitution.agent.md +82 -0
- package/.github/agents/speckit.implement.agent.md +135 -0
- package/.github/agents/speckit.plan.agent.md +89 -0
- package/.github/agents/speckit.specify.agent.md +258 -0
- package/.github/agents/speckit.tasks.agent.md +137 -0
- package/.github/agents/speckit.taskstoissues.agent.md +30 -0
- package/.github/copilot-instructions.md +17 -0
- package/.github/prompts/speckit.analyze.prompt.md +3 -0
- package/.github/prompts/speckit.checklist.prompt.md +3 -0
- package/.github/prompts/speckit.clarify.prompt.md +3 -0
- package/.github/prompts/speckit.constitution.prompt.md +3 -0
- package/.github/prompts/speckit.implement.prompt.md +3 -0
- package/.github/prompts/speckit.plan.prompt.md +3 -0
- package/.github/prompts/speckit.specify.prompt.md +3 -0
- package/.github/prompts/speckit.tasks.prompt.md +3 -0
- package/.github/prompts/speckit.taskstoissues.prompt.md +3 -0
- package/.github/workflows/publish.yaml +28 -0
- package/.opencode/command/speckit.analyze.md +184 -0
- package/.opencode/command/speckit.checklist.md +294 -0
- package/.opencode/command/speckit.clarify.md +181 -0
- package/.opencode/command/speckit.constitution.md +84 -0
- package/.opencode/command/speckit.implement.md +135 -0
- package/.opencode/command/speckit.plan.md +89 -0
- package/.opencode/command/speckit.specify.md +258 -0
- package/.opencode/command/speckit.tasks.md +137 -0
- package/.opencode/command/speckit.taskstoissues.md +30 -0
- package/.specify/memory/constitution.md +58 -0
- package/.specify/scripts/powershell/check-prerequisites.ps1 +148 -0
- package/.specify/scripts/powershell/common.ps1 +137 -0
- package/.specify/scripts/powershell/create-new-feature.ps1 +283 -0
- package/.specify/scripts/powershell/setup-plan.ps1 +61 -0
- package/.specify/scripts/powershell/update-agent-context.ps1 +448 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/constitution-template.md +50 -0
- package/.specify/templates/plan-template.md +104 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +251 -0
- package/.vscode/launch.json +14 -0
- package/.vscode/settings.json +14 -0
- package/.vscode/tasks.json +15 -0
- package/README.md +151 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/services/apiClient.d.ts +14 -0
- package/dist/services/apiClient.d.ts.map +1 -0
- package/dist/services/apiClient.js +41 -0
- package/dist/services/apiClient.js.map +1 -0
- package/dist/tools/accounts.d.ts +3 -0
- package/dist/tools/accounts.d.ts.map +1 -0
- package/dist/tools/accounts.js +77 -0
- package/dist/tools/accounts.js.map +1 -0
- package/dist/tools/categories.d.ts +3 -0
- package/dist/tools/categories.d.ts.map +1 -0
- package/dist/tools/categories.js +57 -0
- package/dist/tools/categories.js.map +1 -0
- package/dist/tools/credit-cards.d.ts +3 -0
- package/dist/tools/credit-cards.d.ts.map +1 -0
- package/dist/tools/credit-cards.js +93 -0
- package/dist/tools/credit-cards.js.map +1 -0
- package/dist/tools/settings.d.ts +3 -0
- package/dist/tools/settings.d.ts.map +1 -0
- package/dist/tools/settings.js +37 -0
- package/dist/tools/settings.js.map +1 -0
- package/dist/tools/summary.d.ts +3 -0
- package/dist/tools/summary.d.ts.map +1 -0
- package/dist/tools/summary.js +16 -0
- package/dist/tools/summary.js.map +1 -0
- package/dist/tools/transactions.d.ts +3 -0
- package/dist/tools/transactions.d.ts.map +1 -0
- package/dist/tools/transactions.js +84 -0
- package/dist/tools/transactions.js.map +1 -0
- package/dist/types/schemas.d.ts +288 -0
- package/dist/types/schemas.d.ts.map +1 -0
- package/dist/types/schemas.js +170 -0
- package/dist/types/schemas.js.map +1 -0
- package/openapi.yaml +1443 -0
- package/package.json +41 -0
- package/specs/001-mcp-api-integration/checklists/requirements.md +34 -0
- package/specs/001-mcp-api-integration/contracts/openapi.yaml +636 -0
- package/specs/001-mcp-api-integration/data-model.md +106 -0
- package/specs/001-mcp-api-integration/plan.md +73 -0
- package/specs/001-mcp-api-integration/quickstart.md +74 -0
- package/specs/001-mcp-api-integration/research.md +58 -0
- package/specs/001-mcp-api-integration/spec.md +119 -0
- package/specs/001-mcp-api-integration/tasks.md +64 -0
- package/src/config.ts +36 -0
- package/src/index.ts +60 -0
- package/src/services/apiClient.ts +49 -0
- package/src/tools/accounts.ts +111 -0
- package/src/tools/categories.ts +81 -0
- package/src/tools/credit-cards.ts +132 -0
- package/src/tools/settings.ts +51 -0
- package/src/tools/summary.ts +20 -0
- package/src/tools/transactions.ts +118 -0
- package/src/types/schemas.ts +193 -0
- package/tests/benchmark.test.d.ts +2 -0
- package/tests/benchmark.test.d.ts.map +1 -0
- package/tests/benchmark.test.js +33 -0
- package/tests/benchmark.test.js.map +1 -0
- package/tests/benchmark.test.ts +38 -0
- package/tests/server.test.d.ts +2 -0
- package/tests/server.test.d.ts.map +1 -0
- package/tests/server.test.js +13 -0
- package/tests/server.test.js.map +1 -0
- package/tests/server.test.ts +14 -0
- package/tests/setup.d.ts +4 -0
- package/tests/setup.d.ts.map +1 -0
- package/tests/setup.js +17 -0
- package/tests/setup.js.map +1 -0
- package/tests/setup.ts +20 -0
- package/tests/tools/accounts.test.ts +118 -0
- package/tests/tools/categories.test.d.ts +2 -0
- package/tests/tools/categories.test.d.ts.map +1 -0
- package/tests/tools/categories.test.js +63 -0
- package/tests/tools/categories.test.js.map +1 -0
- package/tests/tools/categories.test.ts +78 -0
- package/tests/tools/credit-cards.test.d.ts +2 -0
- package/tests/tools/credit-cards.test.d.ts.map +1 -0
- package/tests/tools/credit-cards.test.js +71 -0
- package/tests/tools/credit-cards.test.js.map +1 -0
- package/tests/tools/credit-cards.test.ts +89 -0
- package/tests/tools/summary.test.d.ts +2 -0
- package/tests/tools/summary.test.d.ts.map +1 -0
- package/tests/tools/summary.test.js +36 -0
- package/tests/tools/summary.test.js.map +1 -0
- package/tests/tools/summary.test.ts +42 -0
- package/tests/tools/transactions.test.d.ts +2 -0
- package/tests/tools/transactions.test.d.ts.map +1 -0
- package/tests/tools/transactions.test.js +67 -0
- package/tests/tools/transactions.test.js.map +1 -0
- package/tests/tools/transactions.test.ts +82 -0
- package/tsconfig.json +52 -0
- package/vitest.config.d.ts +3 -0
- package/vitest.config.d.ts.map +1 -0
- package/vitest.config.js +14 -0
- package/vitest.config.js.map +1 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Data Model & Schema Mapping
|
|
2
|
+
|
|
3
|
+
**Feature**: MCP Server for Quantix API Integration
|
|
4
|
+
**Source**: [contracts/openapi.yaml](./contracts/openapi.yaml)
|
|
5
|
+
|
|
6
|
+
## Domain Entities
|
|
7
|
+
|
|
8
|
+
### Category
|
|
9
|
+
- **Fields**:
|
|
10
|
+
- `id`: string (UUID)
|
|
11
|
+
- `name`: string
|
|
12
|
+
- `type`: enum ("INCOME", "EXPENSE")
|
|
13
|
+
- `createdAt`: datetime
|
|
14
|
+
- **Zod Schema**:
|
|
15
|
+
```typescript
|
|
16
|
+
z.object({
|
|
17
|
+
id: z.string(),
|
|
18
|
+
name: z.string(),
|
|
19
|
+
type: z.enum(["INCOME", "EXPENSE"]),
|
|
20
|
+
createdAt: z.string().datetime()
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Transaction
|
|
25
|
+
- **Fields**:
|
|
26
|
+
- `id`: string
|
|
27
|
+
- `type`: enum ("INCOME", "EXPENSE")
|
|
28
|
+
- `name`: string
|
|
29
|
+
- `amount`: number (min 0)
|
|
30
|
+
- `date`: string (YYYY-MM-DD)
|
|
31
|
+
- `categoryId`: string (optional)
|
|
32
|
+
- `paymentMethod`: enum ("CASH", "PIX", "DEBIT", "CREDIT") (optional)
|
|
33
|
+
- `creditCardId`: string (optional, required if CREDIT)
|
|
34
|
+
- `paid`: boolean (default false)
|
|
35
|
+
- **Zod Schema**:
|
|
36
|
+
```typescript
|
|
37
|
+
z.object({
|
|
38
|
+
id: z.string(),
|
|
39
|
+
type: z.enum(["INCOME", "EXPENSE"]),
|
|
40
|
+
name: z.string(),
|
|
41
|
+
amount: z.number().min(0),
|
|
42
|
+
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
43
|
+
categoryId: z.string().optional(),
|
|
44
|
+
paymentMethod: z.enum(["CASH", "PIX", "DEBIT", "CREDIT"]).optional(),
|
|
45
|
+
creditCardId: z.string().optional(),
|
|
46
|
+
paid: z.boolean().default(false)
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### CreditCard
|
|
51
|
+
- **Fields**:
|
|
52
|
+
- `id`: string
|
|
53
|
+
- `name`: string
|
|
54
|
+
- `limitAmount`: number
|
|
55
|
+
- `closingDay`: integer (1-31)
|
|
56
|
+
- `dueDay`: integer (1-31)
|
|
57
|
+
- **Zod Schema**:
|
|
58
|
+
```typescript
|
|
59
|
+
z.object({
|
|
60
|
+
id: z.string(),
|
|
61
|
+
name: z.string(),
|
|
62
|
+
limitAmount: z.number().min(0),
|
|
63
|
+
closingDay: z.number().int().min(1).max(31),
|
|
64
|
+
dueDay: z.number().int().min(1).max(31)
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Tool Input Schemas
|
|
69
|
+
|
|
70
|
+
These schemas define the arguments for the MCP tools.
|
|
71
|
+
|
|
72
|
+
### `create_category`
|
|
73
|
+
```typescript
|
|
74
|
+
z.object({
|
|
75
|
+
name: z.string(),
|
|
76
|
+
type: z.enum(["INCOME", "EXPENSE"])
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `create_transaction`
|
|
81
|
+
```typescript
|
|
82
|
+
z.object({
|
|
83
|
+
type: z.enum(["INCOME", "EXPENSE"]),
|
|
84
|
+
name: z.string(),
|
|
85
|
+
amount: z.number().positive(),
|
|
86
|
+
date: z.string().describe("ISO date string YYYY-MM-DD"),
|
|
87
|
+
categoryId: z.string().optional(),
|
|
88
|
+
paymentMethod: z.enum(["CASH", "PIX", "DEBIT", "CREDIT"]).optional(),
|
|
89
|
+
creditCardId: z.string().optional()
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `get_transactions`
|
|
94
|
+
```typescript
|
|
95
|
+
z.object({
|
|
96
|
+
month: z.string().regex(/^\d{4}-\d{2}$/).describe("Format: YYYY-MM")
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `pay_statement`
|
|
101
|
+
```typescript
|
|
102
|
+
z.object({
|
|
103
|
+
cardId: z.string(),
|
|
104
|
+
month: z.string().regex(/^\d{4}-\d{2}$/)
|
|
105
|
+
})
|
|
106
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Implementation Plan: MCP Server for Quantix API Integration
|
|
2
|
+
|
|
3
|
+
**Branch**: `001-mcp-api-integration` | **Date**: 2026-01-31 | **Spec**: [spec.md](spec.md)
|
|
4
|
+
**Input**: Feature specification from `/specs/001-mcp-api-integration/spec.md`
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Implement 12 MCP tools to expose the Quantix Personal Finance Manager API capabilities (Categories, Credit Cards, Transactions, Summaries).
|
|
9
|
+
The solution will extend the existing Express-based MCP server in `src/index.ts`, adding Zod validation for all inputs and handling API authentication via `QUANTIX_API_KEY`.
|
|
10
|
+
|
|
11
|
+
## Technical Context
|
|
12
|
+
|
|
13
|
+
**Language/Version**: TypeScript 5.9 (Node.js)
|
|
14
|
+
**Primary Dependencies**: `@modelcontextprotocol/sdk`, `express`, `zod`, `fetch` (native Node 18+)
|
|
15
|
+
**Storage**: N/A (Stateless proxy to external API)
|
|
16
|
+
**Testing**: Vitest (Proposed, currently missing in `package.json`)
|
|
17
|
+
**Target Platform**: MCP Clients (e.g., Claude Desktop) connecting via SSE/HTTP
|
|
18
|
+
**Project Type**: Backend / API Proxy
|
|
19
|
+
**Performance Goals**: Low latency proxy (adding <20ms overhead)
|
|
20
|
+
**Constraints**: Must match OpenAPI 3.0 schema strictly for tools.
|
|
21
|
+
**Scale/Scope**: 12 Tools, ~5-6 Service modules.
|
|
22
|
+
|
|
23
|
+
## Constitution Check
|
|
24
|
+
|
|
25
|
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
26
|
+
|
|
27
|
+
* **Principle 1 (Library-First)**: We will organize tools into modules (`src/tools/`) rather than a monolithic `index.ts`.
|
|
28
|
+
* **Principle 3 (Test-First)**: We need to introduce a testing framework (`vitest`) as none exists.
|
|
29
|
+
* **Principle 4 (Integration Testing)**: We will create tests that mock the external API to verify tool behavior.
|
|
30
|
+
|
|
31
|
+
**Governance**: The `constitution.md` appears to be a template. Proceeding with standard best practices.
|
|
32
|
+
|
|
33
|
+
## Project Structure
|
|
34
|
+
|
|
35
|
+
### Documentation (this feature)
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
specs/001-mcp-api-integration/
|
|
39
|
+
├── plan.md # This file
|
|
40
|
+
├── research.md # Phase 0 output
|
|
41
|
+
├── data-model.md # Phase 1 output
|
|
42
|
+
├── quickstart.md # Phase 1 output
|
|
43
|
+
└── contracts/ # Phase 1 output (Copy of openapi.yaml)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Source Code (repository root)
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
src/
|
|
50
|
+
├── index.ts # Entry point (server setup)
|
|
51
|
+
├── config.ts # Env var loading
|
|
52
|
+
├── tools/ # New directory for tool definitions
|
|
53
|
+
│ ├── categories.ts # Category tools
|
|
54
|
+
│ ├── credit-cards.ts # Credit Card tools
|
|
55
|
+
│ ├── transactions.ts # Transaction tools
|
|
56
|
+
│ └── summary.ts # Summary tools
|
|
57
|
+
├── services/ # New directory for API client
|
|
58
|
+
│ └── apiClient.ts # Typed fetch wrapper for Quantix API
|
|
59
|
+
└── types/ # Shared types / Zod schemas
|
|
60
|
+
└── schemas.ts # Zod schemas matching OpenAPI
|
|
61
|
+
|
|
62
|
+
tests/ # New directory
|
|
63
|
+
├── tools/
|
|
64
|
+
│ └── transactions.test.ts
|
|
65
|
+
└── services/
|
|
66
|
+
└── apiClient.test.ts
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Structure Decision**: Modular approach separating Tool Registration (UI layer) from API Logic (Service layer) and Schemas (Model layer).
|
|
70
|
+
|
|
71
|
+
## Complexity Tracking
|
|
72
|
+
|
|
73
|
+
N/A
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Quickstart: Quantix MCP Server
|
|
2
|
+
|
|
3
|
+
This guide explains how to configure and run the Quantix MCP server integration.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js 18+
|
|
8
|
+
- A running instance of the Quantix API (or access to Staging/Prod)
|
|
9
|
+
- An API Key for Quantix
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
1. Install dependencies:
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. Build the project:
|
|
19
|
+
```bash
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Configuration
|
|
24
|
+
|
|
25
|
+
Set the following environment variables. You can add them to a `.env` file or export them in your shell.
|
|
26
|
+
|
|
27
|
+
| Variable | Description | Example |
|
|
28
|
+
|----------|-------------|---------|
|
|
29
|
+
| `QUANTIX_API_URL` | Base URL of the Quantix API | `https://api.quantix.example.com` |
|
|
30
|
+
| `QUANTIX_API_KEY` | Your authentication key | `sk_live_12345` |
|
|
31
|
+
| `MPC_PORT` | Port for the MCP server | `3001` (default) |
|
|
32
|
+
|
|
33
|
+
## Running the Server
|
|
34
|
+
|
|
35
|
+
### Development Mode
|
|
36
|
+
```bash
|
|
37
|
+
# Windows (PowerShell)
|
|
38
|
+
$env:QUANTIX_API_URL="https://api.quantix.example.com"; $env:QUANTIX_API_KEY="test"; npm run dev
|
|
39
|
+
|
|
40
|
+
# Linux/Mac
|
|
41
|
+
QUANTIX_API_URL=https://api.quantix.example.com QUANTIX_API_KEY=test npm run dev
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Production
|
|
45
|
+
```bash
|
|
46
|
+
node dist/index.js
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Using with Claude Desktop
|
|
50
|
+
|
|
51
|
+
Add the server config to your Claude Desktop configuration file:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"quantix": {
|
|
57
|
+
"command": "node",
|
|
58
|
+
"args": ["path/to/morpheus-mcp/dist/index.js"],
|
|
59
|
+
"env": {
|
|
60
|
+
"QUANTIX_API_URL": "...",
|
|
61
|
+
"QUANTIX_API_KEY": "..."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Verification
|
|
69
|
+
|
|
70
|
+
To verify the integration, use the MCP Inspector or curl the running server (since it's HTTP/SSE based):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
curl http://localhost:3001/mcp
|
|
74
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Research & Decisions: MCP API Integration
|
|
2
|
+
|
|
3
|
+
**Feature**: [spec.md](./spec.md)
|
|
4
|
+
**Status**: Complete
|
|
5
|
+
|
|
6
|
+
## Unknowns & Clarifications
|
|
7
|
+
|
|
8
|
+
### 1. Project Structure for Scaling Tools
|
|
9
|
+
**Question**: How to manage 12+ tools without bloating `index.ts`?
|
|
10
|
+
**Context**: Current `index.ts` has tool definition inline.
|
|
11
|
+
**Finding**: The MCP SDK `server.registerTool` can be called from imported modules if we pass the `mcpServer` instance, or better yet, we can export `Tool` definitions (name, description, schema, handler) and register them in a loop.
|
|
12
|
+
**Decision**:
|
|
13
|
+
- Create a `registerTools(server: McpServer)` function in each tool module (e.g., `src/tools/categories.ts`).
|
|
14
|
+
- `src/index.ts` will import these registration functions and call them.
|
|
15
|
+
|
|
16
|
+
### 2. Mocking `fetch` for Tests
|
|
17
|
+
**Question**: Best way to test without hitting real API?
|
|
18
|
+
**Context**: We generally want unit tests to be fast and isolated.
|
|
19
|
+
**Finding**: Since we are using native `fetch` (Node 18+), we can use `vitest` to spy on `global.fetch` or use a library like `msw` (Mock Service Worker). Given the simplicity, basic `vi.spyOn(global, 'fetch')` is sufficient.
|
|
20
|
+
**Decision**: Use `vitest` and spy on `global.fetch`.
|
|
21
|
+
|
|
22
|
+
## Technology Choices
|
|
23
|
+
|
|
24
|
+
| Area | Choice | Rationale |
|
|
25
|
+
|------|--------|-----------|
|
|
26
|
+
| **Validation** | `zod` | Native support in MCP SDK, TypeScript native, easy to derive from OpenAPI. |
|
|
27
|
+
| **HTTP Client** | Native `fetch` | No extra dependency weight, fully supported in modern Node. |
|
|
28
|
+
| **Testing** | `vitest` | Fast, compatible with ESM (Type "module" in package.json), Jest-compatible API. |
|
|
29
|
+
| **Env Vars** | `process.env` | Simple standard. |
|
|
30
|
+
|
|
31
|
+
## Design Patterns
|
|
32
|
+
|
|
33
|
+
### API Client Wrapper
|
|
34
|
+
Instead of calling `fetch` in every tool, we will create `src/services/apiClient.ts`:
|
|
35
|
+
```typescript
|
|
36
|
+
async function apiFetch<T>(endpoint: string, options: RequestInit): Promise<T> {
|
|
37
|
+
const url = `${process.env.QUANTIX_API_URL}${endpoint}`;
|
|
38
|
+
const response = await fetch(url, {
|
|
39
|
+
...options,
|
|
40
|
+
headers: {
|
|
41
|
+
...options.headers,
|
|
42
|
+
'API-KEY': process.env.QUANTIX_API_KEY
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// Error handling logic here
|
|
46
|
+
return response.json();
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Zod Schema Reusability
|
|
51
|
+
We will define Zod schemas in `src/types/schemas.ts` that mirror the OpenAPI `components/schemas`. Use `z.infer` to generate TypeScript types for compile-time safety.
|
|
52
|
+
|
|
53
|
+
## Alternatives Considered
|
|
54
|
+
|
|
55
|
+
- **OpenAPI Code Generator**: Could auto-generate the client.
|
|
56
|
+
- *Rejected*: Too heavy for 12 endpoints, harder to customize for MCP specific return formats.
|
|
57
|
+
- **Axios**:
|
|
58
|
+
- *Rejected*: `fetch` is built-in.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Feature Specification: MCP Server for Quantix API Integration
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `001-mcp-api-integration`
|
|
4
|
+
**Created**: 2026-01-31
|
|
5
|
+
**Status**: Draft
|
|
6
|
+
**Input**: User description: "Vamos criar um servidor MCP para acessar todas essa rotas da nossa api, coloque o endereço da url como padrão vindo de env e api-key necessária também, use o zod para padronizar e especificar os inputs"
|
|
7
|
+
|
|
8
|
+
## User Scenarios & Testing *(mandatory)*
|
|
9
|
+
|
|
10
|
+
### User Story 1 - Configure and Start MCP Server (Priority: P1)
|
|
11
|
+
|
|
12
|
+
As a developer or AI agent, I want to configure the MCP server with the API URL and API Key so that I can securely access the financial data.
|
|
13
|
+
|
|
14
|
+
**Why this priority**: Essential for the server to function and authenticate.
|
|
15
|
+
|
|
16
|
+
**Independent Test**:
|
|
17
|
+
1. Set `QUANTIX_API_URL` and `QUANTIX_API_KEY` environment variables.
|
|
18
|
+
2. Start the server.
|
|
19
|
+
3. Verify that the server starts without errors and is ready to accept requests.
|
|
20
|
+
|
|
21
|
+
**Acceptance Scenarios**:
|
|
22
|
+
|
|
23
|
+
1. **Given** valid environment variables, **When** the server starts, **Then** it initializes successfully.
|
|
24
|
+
2. **Given** missing API Key, **When** the server starts, **Then** it might warn or fail calls (depending on implementation), but tools should be registered.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### User Story 2 - Manage Financial Categories (Priority: P2)
|
|
29
|
+
|
|
30
|
+
As a user, I want to create, list, and delete categories to organize my finances.
|
|
31
|
+
|
|
32
|
+
**Why this priority**: Categories are foundational for transactions.
|
|
33
|
+
|
|
34
|
+
**Independent Test**: Use an MCP client to call category tools.
|
|
35
|
+
|
|
36
|
+
**Acceptance Scenarios**:
|
|
37
|
+
|
|
38
|
+
1. **Given** the MCP server is running, **When** I call `get_categories`, **Then** I receive a list of categories.
|
|
39
|
+
2. **Given** a new category name and type, **When** I call `create_category`, **Then** the category is created via the API.
|
|
40
|
+
3. **Given** a category ID, **When** I call `delete_category`, **Then** the category is removed.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### User Story 3 - Manage Credit Cards and Statements (Priority: P2)
|
|
45
|
+
|
|
46
|
+
As a user, I want to manage credit cards and view/pay statements.
|
|
47
|
+
|
|
48
|
+
**Why this priority**: Credit card management is a core feature of the API.
|
|
49
|
+
|
|
50
|
+
**Independent Test**: Call credit card related tools.
|
|
51
|
+
|
|
52
|
+
**Acceptance Scenarios**:
|
|
53
|
+
|
|
54
|
+
1. **Given** card details, **When** I call `create_credit_card`, **Then** a new card is added.
|
|
55
|
+
2. **Given** a card ID and month, **When** I call `get_statement`, **Then** I see the transactions for that period.
|
|
56
|
+
3. **Given** a card ID and month, **When** I call `pay_statement`, **Then** the transactions are marked as paid.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### User Story 4 - Manage Transactions and Summaries (Priority: P2)
|
|
61
|
+
|
|
62
|
+
As a user, I want to record transactions and view my monthly financial summary.
|
|
63
|
+
|
|
64
|
+
**Why this priority**: Core value of a finance manager.
|
|
65
|
+
|
|
66
|
+
**Independent Test**: Call transaction and summary tools.
|
|
67
|
+
|
|
68
|
+
**Acceptance Scenarios**:
|
|
69
|
+
|
|
70
|
+
1. **Given** transaction details, **When** I call `create_transaction`, **Then** it is recorded.
|
|
71
|
+
2. **Given** a month, **When** I call `get_transactions`, **Then** I see the list of transactions.
|
|
72
|
+
3. **Given** a month, **When** I call `get_summary`, **Then** I see income, expenses, and balance.
|
|
73
|
+
4. **Given** a transaction ID, **When** I call `pay_transaction`, **Then** it is marked as paid.
|
|
74
|
+
|
|
75
|
+
## Functional Requirements
|
|
76
|
+
|
|
77
|
+
1. **Environment Configuration**:
|
|
78
|
+
- Support `QUANTIX_API_URL` (defaulting to `https://api.quantix.example.com` or requiring it).
|
|
79
|
+
- Support `QUANTIX_API_KEY` for authentication header `API-KEY`.
|
|
80
|
+
|
|
81
|
+
2. **Tool Registration**:
|
|
82
|
+
- Register the following tools in the MCP server:
|
|
83
|
+
- `create_category`
|
|
84
|
+
- `get_categories`
|
|
85
|
+
- `delete_category`
|
|
86
|
+
- `create_credit_card`
|
|
87
|
+
- `get_credit_cards`
|
|
88
|
+
- `get_statement`
|
|
89
|
+
- `pay_statement`
|
|
90
|
+
- `create_transaction`
|
|
91
|
+
- `get_transactions`
|
|
92
|
+
- `pay_transaction`
|
|
93
|
+
- `delete_transaction`
|
|
94
|
+
- `get_summary`
|
|
95
|
+
|
|
96
|
+
3. **Input Validation**:
|
|
97
|
+
- Use `zod` to define input schemas for all tools.
|
|
98
|
+
- Schemas must match the OpenApi 3.0 definitions provided in `openapi.yaml`.
|
|
99
|
+
|
|
100
|
+
4. **API Integration**:
|
|
101
|
+
- Make HTTP requests to the configured `QUANTIX_API_URL`.
|
|
102
|
+
- Forward the API Key in headers.
|
|
103
|
+
- Return clear output messages based on API responses.
|
|
104
|
+
|
|
105
|
+
## Success Criteria
|
|
106
|
+
|
|
107
|
+
1. **measurable**: 100% of the 12 identified API endpoints are exposed as MCP tools.
|
|
108
|
+
2. **measurable**: Inputs for all tools are validated using Zod schemas.
|
|
109
|
+
3. **verifiable**: The server connects to the backend using the environment variables.
|
|
110
|
+
4. **verifiable**: Tools return meaningful success/error messages to the model.
|
|
111
|
+
|
|
112
|
+
## Assumptions
|
|
113
|
+
|
|
114
|
+
- The `openapi.yaml` is the source of truth for schemas.
|
|
115
|
+
- The existing project structure with `src/index.ts` determines the server setup (Express + MCP SDK).
|
|
116
|
+
|
|
117
|
+
## Clarifications
|
|
118
|
+
|
|
119
|
+
- None at this stage.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Tasks: MCP Server for Quantix API Integration
|
|
2
|
+
|
|
3
|
+
**Spec**: [spec.md](spec.md)
|
|
4
|
+
**Plan**: [plan.md](plan.md)
|
|
5
|
+
**Status**: In Progress
|
|
6
|
+
|
|
7
|
+
## Phase 1: Setup
|
|
8
|
+
*Goal: Initialize project structure and dependencies*
|
|
9
|
+
|
|
10
|
+
- [x] T001 [P] Install Vitest and testing dependencies in `package.json`
|
|
11
|
+
- [x] T002 [P] Create project directory structure (`src/tools`, `src/services`, `src/types`, `tests`)
|
|
12
|
+
- [x] T003 Implement `src/config.ts` for environment variable management
|
|
13
|
+
- [x] T004 [P] Configure Vitest in `vitest.config.ts` (or script in package.json)
|
|
14
|
+
|
|
15
|
+
## Phase 2: Foundational & Shared Components
|
|
16
|
+
*Goal: Establish core API client and data schemas*
|
|
17
|
+
|
|
18
|
+
- [x] T005 [P] Implement `src/services/apiClient.ts` with authentication and typed `fetch`
|
|
19
|
+
- [x] T006 [P] Implement `src/types/schemas.ts` with Zod definitions for all entities (Category, Transaction, etc.)
|
|
20
|
+
- [x] T007 Create basic test setup/helpers in `tests/setup.ts`
|
|
21
|
+
|
|
22
|
+
## Phase 3: Server Configuration (User Story 1)
|
|
23
|
+
*Goal: Server starts with correct configuration and tool registration architecture*
|
|
24
|
+
|
|
25
|
+
- [x] T008 [US1] Refactor `src/index.ts` to use `src/config.ts` and support modular tool registration
|
|
26
|
+
- [x] T009 [US1] Create integration test `tests/server.test.ts` to verify server startup and env handling
|
|
27
|
+
|
|
28
|
+
## Phase 4: Categories Support (User Story 2)
|
|
29
|
+
*Goal: Enable management of financial categories*
|
|
30
|
+
|
|
31
|
+
- [x] T010 [US2] TDD: Implement `src/tools/categories.ts` (write tests in `tests/tools/categories.test.ts` first)
|
|
32
|
+
- [x] T011 [US2] Register category tools in `src/index.ts`
|
|
33
|
+
|
|
34
|
+
## Phase 5: Credit Cards Support (User Story 3)
|
|
35
|
+
*Goal: Enable management of credit cards and statements*
|
|
36
|
+
|
|
37
|
+
- [x] T012 [US3] TDD: Implement `src/tools/credit-cards.ts` (write tests in `tests/tools/credit-cards.test.ts` first)
|
|
38
|
+
- [x] T013 [US3] Register credit card tools in `src/index.ts`
|
|
39
|
+
|
|
40
|
+
## Phase 6: Transactions & Summary Support (User Story 4)
|
|
41
|
+
*Goal: Enable transaction recording and financial summaries*
|
|
42
|
+
|
|
43
|
+
- [x] T014 [US4] TDD: Implement `src/tools/transactions.ts` (write tests in `tests/tools/transactions.test.ts` first)
|
|
44
|
+
- [x] T015 [US4] TDD: Implement `src/tools/summary.ts` (write tests in `tests/tools/summary.test.ts` first)
|
|
45
|
+
- [x] T016 [US4] Register transaction and summary tools in `src/index.ts`
|
|
46
|
+
|
|
47
|
+
## Phase 7: Polish & Documentation
|
|
48
|
+
*Goal: Final verification and cleanup*
|
|
49
|
+
|
|
50
|
+
- [x] T017 Remove legacy `get_crypto_price` example from `src/index.ts`
|
|
51
|
+
- [x] T018 Verify `quickstart.md` instructions against the running server
|
|
52
|
+
- [x] T019 Run full test suite and ensure all tests pass
|
|
53
|
+
- [x] T020 Benchmark tool overhead to verify <20ms latency goal
|
|
54
|
+
|
|
55
|
+
## Dependencies
|
|
56
|
+
|
|
57
|
+
- Phase 2 depends on Phase 1
|
|
58
|
+
- Phase 3 depends on Phase 2 (config & client)
|
|
59
|
+
- Phase 4, 5, 6 depend on Phase 3 (server setup) and Phase 2 (schemas/client)
|
|
60
|
+
- Phases 4, 5, 6 can be executed in parallel (independent modules), but registered sequentially in T0XX tasks if strictly following order.
|
|
61
|
+
|
|
62
|
+
## Implementation Strategy
|
|
63
|
+
- **MVP**: Complete through Phase 3 + Phase 4 (Categories) to prove the pattern.
|
|
64
|
+
- **Incremental**: Add Credit Cards and Transactions as separate modules.
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import * as z from 'zod';
|
|
3
|
+
|
|
4
|
+
const envSchema = z.object({
|
|
5
|
+
QUANTIX_API_URL: z.string().default('https://api.quantix.example.com'),
|
|
6
|
+
QUANTIX_API_KEY: z.string().min(1, "QUANTIX_API_KEY is required"),
|
|
7
|
+
MCPPORT: z.string().optional().default('3001'),
|
|
8
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const processEnv = {
|
|
12
|
+
QUANTIX_API_URL: process.env.QUANTIX_API_URL,
|
|
13
|
+
QUANTIX_API_KEY: process.env.QUANTIX_API_KEY,
|
|
14
|
+
MCPPORT: process.env.MCPPORT,
|
|
15
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Parse and validate environment variables
|
|
19
|
+
const parsedEnv = envSchema.safeParse(processEnv);
|
|
20
|
+
|
|
21
|
+
if (!parsedEnv.success) {
|
|
22
|
+
console.error("❌ Invalid environment variables:", parsedEnv.error.format());
|
|
23
|
+
|
|
24
|
+
// In a real app, we might want to throw here, but for now we'll just log
|
|
25
|
+
// and let the application fail when it tries to use the missing keys if essential
|
|
26
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
27
|
+
// Allow tests to run without all env vars if they mock config
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const config = parsedEnv.success ? parsedEnv.data : {
|
|
32
|
+
QUANTIX_API_URL: process.env.QUANTIX_API_URL || 'https://api.quantix.example.com',
|
|
33
|
+
QUANTIX_API_KEY: process.env.QUANTIX_API_KEY || 'your_api_key_here',
|
|
34
|
+
MCPPORT: process.env.MCPPORT || '3001',
|
|
35
|
+
NODE_ENV: (process.env.NODE_ENV as 'development' | 'production' | 'test') || 'development'
|
|
36
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
5
|
+
import express, { type Request, type Response } from 'express';
|
|
6
|
+
import { config } from './config.js';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { registerCategoryTools } from './tools/categories.js';
|
|
9
|
+
import { registerCreditCardTools } from './tools/credit-cards.js';
|
|
10
|
+
import { registerTransactionTools } from './tools/transactions.js';
|
|
11
|
+
import { registerSummaryTools } from './tools/summary.js';
|
|
12
|
+
import { registerAccountTools } from './tools/accounts.js';
|
|
13
|
+
import { registerSettingsTools } from './tools/settings.js';
|
|
14
|
+
|
|
15
|
+
export function getServer() {
|
|
16
|
+
const mcpServer = new McpServer({
|
|
17
|
+
name: 'quantix_mcp_server',
|
|
18
|
+
version: '1.0.0'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
console.log('McpServer started');
|
|
22
|
+
|
|
23
|
+
// Register Tools here
|
|
24
|
+
registerCategoryTools(mcpServer);
|
|
25
|
+
registerCreditCardTools(mcpServer);
|
|
26
|
+
registerTransactionTools(mcpServer);
|
|
27
|
+
registerSummaryTools(mcpServer);
|
|
28
|
+
registerAccountTools(mcpServer);
|
|
29
|
+
registerSettingsTools(mcpServer);
|
|
30
|
+
|
|
31
|
+
return mcpServer;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const app = express();
|
|
35
|
+
app.use(express.json());
|
|
36
|
+
|
|
37
|
+
app.post('/mcp', async (req: Request, res: Response) => {
|
|
38
|
+
const mcpServer = getServer();
|
|
39
|
+
|
|
40
|
+
const transport = new StreamableHTTPServerTransport({
|
|
41
|
+
});
|
|
42
|
+
const mcpTransport = transport as unknown as Transport;
|
|
43
|
+
|
|
44
|
+
res.on('close', () => {
|
|
45
|
+
transport.close();
|
|
46
|
+
mcpServer.close();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await mcpServer.connect(mcpTransport);
|
|
50
|
+
await transport.handleRequest(req, res, req.body);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (config.NODE_ENV !== 'test') {
|
|
54
|
+
const MCPPORT = config.MCPPORT;
|
|
55
|
+
app.listen(MCPPORT, () => {
|
|
56
|
+
console.log(`MCP server is running on http://localhost:${MCPPORT}/mcp`);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { app };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
|
|
3
|
+
export class ApiClientError extends Error {
|
|
4
|
+
constructor(public message: string, public status: number, public statusText: string) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'ApiClientError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function apiFetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
|
11
|
+
const url = `${config.QUANTIX_API_URL}${endpoint}`;
|
|
12
|
+
|
|
13
|
+
const headers = {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'x-api-key': config.QUANTIX_API_KEY,
|
|
16
|
+
...options.headers,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const response = await fetch(url, {
|
|
20
|
+
...options,
|
|
21
|
+
headers,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new ApiClientError(
|
|
26
|
+
`API request failed: ${response.status} ${response.statusText}`,
|
|
27
|
+
response.status,
|
|
28
|
+
response.statusText
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Handle 204 No Content
|
|
33
|
+
if (response.status === 204) {
|
|
34
|
+
return {} as T;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return response.json();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const apiClient = {
|
|
41
|
+
get: <T>(endpoint: string) => apiFetch<T>(endpoint, { method: 'GET' }),
|
|
42
|
+
post: <T>(endpoint: string, body: unknown) =>
|
|
43
|
+
apiFetch<T>(endpoint, { method: 'POST', body: JSON.stringify(body) }),
|
|
44
|
+
patch: <T>(endpoint: string, body: unknown = {}) =>
|
|
45
|
+
apiFetch<T>(endpoint, { method: 'PATCH', body: JSON.stringify(body) }),
|
|
46
|
+
put: <T>(endpoint: string, body: unknown) =>
|
|
47
|
+
apiFetch<T>(endpoint, { method: 'PUT', body: JSON.stringify(body) }),
|
|
48
|
+
delete: <T>(endpoint: string) => apiFetch<T>(endpoint, { method: 'DELETE' }),
|
|
49
|
+
};
|