iwantmymtg-mcp 0.0.1
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.
- package/README.md +91 -0
- package/dist/api-client.js +51 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.js +18 -0
- package/dist/config.js.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/alerts.js +39 -0
- package/dist/tools/alerts.js.map +1 -0
- package/dist/tools/get-card.js +34 -0
- package/dist/tools/get-card.js.map +1 -0
- package/dist/tools/index.js +51 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inventory.js +54 -0
- package/dist/tools/inventory.js.map +1 -0
- package/dist/tools/notifications.js +27 -0
- package/dist/tools/notifications.js.map +1 -0
- package/dist/tools/portfolio.js +54 -0
- package/dist/tools/portfolio.js.map +1 -0
- package/dist/tools/search-cards.js +40 -0
- package/dist/tools/search-cards.js.map +1 -0
- package/dist/tools/sets.js +41 -0
- package/dist/tools/sets.js.map +1 -0
- package/dist/tools/transactions.js +84 -0
- package/dist/tools/transactions.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# iwantmymtg-mcp
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server for [I Want My MTG](https://iwantmymtg.net). Exposes IWMM's API as tools so Claude Desktop, Claude Code, Cursor, and other MCP clients can search Magic: The Gathering cards/sets and manage a user's collection conversationally.
|
|
4
|
+
|
|
5
|
+
> Status: v0 scaffold. The set of tools below is the v1 surface; coverage will expand to match the API.
|
|
6
|
+
|
|
7
|
+
## What you can do
|
|
8
|
+
|
|
9
|
+
- **Anonymous (no key):** search cards, look up a card by set+number, get current prices and 30-day price history, list sets and their cards, list sealed products.
|
|
10
|
+
- **Authenticated (with an IWMM API key):** list and update your inventory.
|
|
11
|
+
|
|
12
|
+
More authenticated tools (transactions, portfolio breakdowns, price alerts, notifications) are coming - see the [project roadmap](https://github.com/matthewdtowles/i-want-my-mtg/blob/main/ROADMAP.md#43-mcp-server--agentic-ai-integration).
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
Requires Node 20+.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx iwantmymtg-mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
(Until published to npm, use the local install instructions below.)
|
|
23
|
+
|
|
24
|
+
## Claude Desktop
|
|
25
|
+
|
|
26
|
+
Add to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`; Windows: `%APPDATA%\Claude\claude_desktop_config.json`):
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"iwmm": {
|
|
32
|
+
"command": "npx",
|
|
33
|
+
"args": ["-y", "iwantmymtg-mcp"],
|
|
34
|
+
"env": {
|
|
35
|
+
"IWMM_API_KEY": "iwm_live_..."
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`IWMM_API_KEY` is optional - read-only tools work without it. Create a key at https://iwantmymtg.net/user/api-keys.
|
|
43
|
+
|
|
44
|
+
## Claude Code
|
|
45
|
+
|
|
46
|
+
Add to `.mcp.json` in your project (or `~/.claude/.mcp.json` globally):
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"iwmm": {
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": ["-y", "iwantmymtg-mcp"],
|
|
54
|
+
"env": { "IWMM_API_KEY": "iwm_live_..." }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Example prompts
|
|
61
|
+
|
|
62
|
+
- "Search for Lightning Bolt printings and show me the cheapest one."
|
|
63
|
+
- "What's the price history of Bloodbraid Elf from Modern Horizons 3?"
|
|
64
|
+
- "Add 4 copies of Lightning Bolt LEA to my inventory."
|
|
65
|
+
- "What sealed products are available for MH3?"
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
| Env var | Default | Purpose |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `IWMM_API_KEY` | _(unset)_ | Personal API key. Required only for authenticated tools. |
|
|
72
|
+
| `IWMM_BASE_URL` | `https://iwantmymtg.net` | Override for self-hosted or local-dev IWMM instances. |
|
|
73
|
+
|
|
74
|
+
## Local development
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install
|
|
78
|
+
npm run build
|
|
79
|
+
node dist/index.js
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or with `tsx` for live reload:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install
|
|
86
|
+
npx tsx src/index.ts
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { config } from "./config.js";
|
|
2
|
+
export class ApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
rateLimit;
|
|
6
|
+
constructor(status, body, rateLimit) {
|
|
7
|
+
super(`IWMM API ${status}: ${body}`);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
this.rateLimit = rateLimit;
|
|
11
|
+
this.name = "ApiError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function apiFetch(req) {
|
|
15
|
+
const url = new URL(req.path, config.baseUrl);
|
|
16
|
+
if (req.query) {
|
|
17
|
+
for (const [k, v] of Object.entries(req.query)) {
|
|
18
|
+
if (v !== undefined && v !== null && v !== "") {
|
|
19
|
+
url.searchParams.set(k, String(v));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const headers = {
|
|
24
|
+
Accept: "application/json",
|
|
25
|
+
"User-Agent": "iwantmymtg-mcp/0.0.1",
|
|
26
|
+
};
|
|
27
|
+
if (req.authenticated) {
|
|
28
|
+
const { requireApiKey } = await import("./config.js");
|
|
29
|
+
headers["Authorization"] = `Bearer ${requireApiKey()}`;
|
|
30
|
+
}
|
|
31
|
+
if (req.body !== undefined) {
|
|
32
|
+
headers["Content-Type"] = "application/json";
|
|
33
|
+
}
|
|
34
|
+
const res = await fetch(url, {
|
|
35
|
+
method: req.method ?? "GET",
|
|
36
|
+
headers,
|
|
37
|
+
body: req.body !== undefined ? JSON.stringify(req.body) : undefined,
|
|
38
|
+
});
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
const text = await res.text();
|
|
41
|
+
throw new ApiError(res.status, text, {
|
|
42
|
+
limit: res.headers.get("X-RateLimit-Limit") ?? undefined,
|
|
43
|
+
remaining: res.headers.get("X-RateLimit-Remaining") ?? undefined,
|
|
44
|
+
reset: res.headers.get("X-RateLimit-Reset") ?? undefined,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (res.status === 204)
|
|
48
|
+
return undefined;
|
|
49
|
+
return (await res.json());
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAUrC,MAAM,OAAO,QAAS,SAAQ,KAAK;IAEf;IACA;IACA;IAHlB,YACkB,MAAc,EACd,IAAY,EACZ,SAIf;QAED,KAAK,CAAC,YAAY,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QARrB,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QACZ,cAAS,GAAT,SAAS,CAIxB;QAGD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAc,GAAe;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC9C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,kBAAkB;QAC1B,YAAY,EAAE,sBAAsB;KACrC,CAAC;IAEF,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACtD,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,aAAa,EAAE,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;IAC/C,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,KAAK;QAC3B,OAAO;QACP,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE;YACnC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,SAAS;YACxD,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,SAAS;YAChE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,SAAS;SACzD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,SAAc,CAAC;IAC9C,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;AACjC,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Reads env lazily so callers and tests see live values rather than a snapshot
|
|
2
|
+
// taken at import time.
|
|
3
|
+
export const config = {
|
|
4
|
+
get baseUrl() {
|
|
5
|
+
return process.env.IWMM_BASE_URL ?? "https://iwantmymtg.net";
|
|
6
|
+
},
|
|
7
|
+
get apiKey() {
|
|
8
|
+
return process.env.IWMM_API_KEY;
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export function requireApiKey() {
|
|
12
|
+
if (!config.apiKey) {
|
|
13
|
+
throw new Error("This tool requires an API key. Set IWMM_API_KEY in your MCP client config. " +
|
|
14
|
+
"Create a key at https://iwantmymtg.net/user/api-keys.");
|
|
15
|
+
}
|
|
16
|
+
return config.apiKey;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAwB;AACxB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,OAAO;QACT,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,wBAAwB,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM;QACR,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAClC,CAAC;CACF,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,6EAA6E;YAC3E,uDAAuD,CAC1D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC1B,oDAAoD;IACpD,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
5
|
+
import { tools, toolsByName } from "./tools/index.js";
|
|
6
|
+
import { ApiError } from "./api-client.js";
|
|
7
|
+
export async function startServer() {
|
|
8
|
+
const server = new Server({
|
|
9
|
+
name: "iwantmymtg-mcp",
|
|
10
|
+
version: "0.0.1",
|
|
11
|
+
}, {
|
|
12
|
+
capabilities: {
|
|
13
|
+
tools: {},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
17
|
+
tools: tools.map((t) => ({
|
|
18
|
+
name: t.name,
|
|
19
|
+
description: t.description,
|
|
20
|
+
inputSchema: zodToJsonSchema(t.inputSchema, { target: "openApi3" }),
|
|
21
|
+
})),
|
|
22
|
+
}));
|
|
23
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
24
|
+
const tool = toolsByName[req.params.name];
|
|
25
|
+
if (!tool) {
|
|
26
|
+
return {
|
|
27
|
+
isError: true,
|
|
28
|
+
content: [{ type: "text", text: `Unknown tool: ${req.params.name}` }],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const args = tool.inputSchema.safeParse(req.params.arguments ?? {});
|
|
32
|
+
if (!args.success) {
|
|
33
|
+
return {
|
|
34
|
+
isError: true,
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: `Invalid arguments for ${tool.name}: ${args.error.message}`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const result = await tool.handler(args.data);
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return { isError: true, content: [{ type: "text", text: formatError(err) }] };
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const transport = new StdioServerTransport();
|
|
54
|
+
await server.connect(transport);
|
|
55
|
+
}
|
|
56
|
+
function formatError(err) {
|
|
57
|
+
if (err instanceof ApiError) {
|
|
58
|
+
const rl = err.rateLimit;
|
|
59
|
+
const rateNote = rl?.remaining !== undefined
|
|
60
|
+
? ` (rate limit: ${rl.remaining}/${rl.limit} remaining, resets ${rl.reset ?? "?"})`
|
|
61
|
+
: "";
|
|
62
|
+
return `IWMM API responded ${err.status}${rateNote}: ${err.body}`;
|
|
63
|
+
}
|
|
64
|
+
return err instanceof Error ? err.message : String(err);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
const thresholdRefinement = (v) => v.increasePct != null || v.decreasePct != null;
|
|
4
|
+
export const listAlertsTool = {
|
|
5
|
+
name: "list_price_alerts",
|
|
6
|
+
description: "List the authenticated user's price alerts. Free tier is capped at 5 active alerts and a single threshold direction per alert; Premium removes both limits. Requires IWMM_API_KEY.",
|
|
7
|
+
inputSchema: z.object({}),
|
|
8
|
+
handler: () => apiFetch({ path: "/api/v1/price-alerts", authenticated: true }),
|
|
9
|
+
};
|
|
10
|
+
export const createAlertTool = {
|
|
11
|
+
name: "create_price_alert",
|
|
12
|
+
description: "Create a price alert for a card. Supply increasePct, decreasePct, or both (Premium). At least one threshold is required. Requires IWMM_API_KEY.",
|
|
13
|
+
inputSchema: z
|
|
14
|
+
.object({
|
|
15
|
+
cardId: z.string().uuid().describe("Internal IWMM card UUID."),
|
|
16
|
+
increasePct: z.number().min(0.01).optional().describe("Trigger when price increases by at least this percent."),
|
|
17
|
+
decreasePct: z.number().min(0.01).optional().describe("Trigger when price decreases by at least this percent."),
|
|
18
|
+
})
|
|
19
|
+
.refine(thresholdRefinement, { message: "Provide at least one of increasePct or decreasePct." }),
|
|
20
|
+
handler: (input) => apiFetch({ path: "/api/v1/price-alerts", method: "POST", body: input, authenticated: true }),
|
|
21
|
+
};
|
|
22
|
+
export const updateAlertTool = {
|
|
23
|
+
name: "update_price_alert",
|
|
24
|
+
description: "Update an existing price alert. Pass null for a threshold to clear it (Premium only - free users must keep exactly one direction). isActive toggles enable/disable without deleting. Requires IWMM_API_KEY.",
|
|
25
|
+
inputSchema: z.object({
|
|
26
|
+
id: z.string().describe("Alert ID from list_price_alerts."),
|
|
27
|
+
increasePct: z.number().min(0.01).nullable().optional(),
|
|
28
|
+
decreasePct: z.number().min(0.01).nullable().optional(),
|
|
29
|
+
isActive: z.boolean().optional(),
|
|
30
|
+
}),
|
|
31
|
+
handler: ({ id, ...patch }) => apiFetch({ path: `/api/v1/price-alerts/${encodeURIComponent(id)}`, method: "PATCH", body: patch, authenticated: true }),
|
|
32
|
+
};
|
|
33
|
+
export const deleteAlertTool = {
|
|
34
|
+
name: "delete_price_alert",
|
|
35
|
+
description: "Delete a price alert by ID. Requires IWMM_API_KEY.",
|
|
36
|
+
inputSchema: z.object({ id: z.string() }),
|
|
37
|
+
handler: ({ id }) => apiFetch({ path: `/api/v1/price-alerts/${encodeURIComponent(id)}`, method: "DELETE", authenticated: true }),
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=alerts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/tools/alerts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,mBAAmB,GAAG,CAAC,CAA+D,EAAE,EAAE,CAC9F,CAAC,CAAC,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC;AAEjD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,oLAAoL;IACtL,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC/E,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,iJAAiJ;IACnJ,WAAW,EAAE,CAAC;SACX,MAAM,CAAC;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAC9D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;QAC/G,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;KAChH,CAAC;SACD,MAAM,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAC;IAClG,OAAO,EAAE,CAAC,KAAqE,EAAE,EAAE,CACjF,QAAQ,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC/F,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,6MAA6M;IAC/M,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;QACvD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;QACvD,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACjC,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,KAAK,EAA4C,EAAE,EAAE,CACtE,QAAQ,CAAC,EAAE,IAAI,EAAE,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC1H,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,oDAAoD;IACjE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACzC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAkB,EAAE,EAAE,CAClC,QAAQ,CAAC,EAAE,IAAI,EAAE,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC9G,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
export const getCardInputSchema = {
|
|
4
|
+
setCode: z.string().describe("Set code (e.g. 'lea')."),
|
|
5
|
+
setNumber: z.string().describe("Collector number within the set (e.g. '161'). String, not int - some sets use suffixes like '12a'."),
|
|
6
|
+
};
|
|
7
|
+
export async function getCard(input) {
|
|
8
|
+
return apiFetch({
|
|
9
|
+
path: `/api/v1/cards/${encodeURIComponent(input.setCode)}/${encodeURIComponent(input.setNumber)}`,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
export const getCardTool = {
|
|
13
|
+
name: "get_card",
|
|
14
|
+
description: "Look up a specific card printing by set code and collector number. Returns full card detail including current prices, rarity, type, and flavor name. For broader catalog search use search_cards.",
|
|
15
|
+
inputSchema: z.object(getCardInputSchema),
|
|
16
|
+
handler: getCard,
|
|
17
|
+
};
|
|
18
|
+
export const getCardPricesTool = {
|
|
19
|
+
name: "get_card_prices",
|
|
20
|
+
description: "Get current normal and foil prices for a specific card printing.",
|
|
21
|
+
inputSchema: z.object(getCardInputSchema),
|
|
22
|
+
handler: async (input) => apiFetch({
|
|
23
|
+
path: `/api/v1/cards/${encodeURIComponent(input.setCode)}/${encodeURIComponent(input.setNumber)}/prices`,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
export const getCardPriceHistoryTool = {
|
|
27
|
+
name: "get_card_price_history",
|
|
28
|
+
description: "Get the 30-day price history for a card printing (normal + foil). Older data is retained on a weekly/monthly cadence beyond 30 days.",
|
|
29
|
+
inputSchema: z.object(getCardInputSchema),
|
|
30
|
+
handler: async (input) => apiFetch({
|
|
31
|
+
path: `/api/v1/cards/${encodeURIComponent(input.setCode)}/${encodeURIComponent(input.setNumber)}/price-history`,
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=get-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-card.js","sourceRoot":"","sources":["../../src/tools/get-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IACtD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oGAAoG,CAAC;CACrI,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAA6C;IACzE,OAAO,QAAQ,CAAC;QACd,IAAI,EAAE,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;KAClG,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,UAAU;IAChB,WAAW,EACT,mMAAmM;IACrM,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;IACzC,OAAO,EAAE,OAAO;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,kEAAkE;IAC/E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;IACzC,OAAO,EAAE,KAAK,EAAE,KAA6C,EAAE,EAAE,CAC/D,QAAQ,CAAC;QACP,IAAI,EAAE,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS;KACzG,CAAC;CACL,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,sIAAsI;IACxI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;IACzC,OAAO,EAAE,KAAK,EAAE,KAA6C,EAAE,EAAE,CAC/D,QAAQ,CAAC;QACP,IAAI,EAAE,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,gBAAgB;KAChH,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { searchCardsTool } from "./search-cards.js";
|
|
2
|
+
import { getCardTool, getCardPricesTool, getCardPriceHistoryTool } from "./get-card.js";
|
|
3
|
+
import { searchSetsTool, getSetTool, listSetCardsTool, getSealedProductsTool } from "./sets.js";
|
|
4
|
+
import { listInventoryTool, addInventoryTool, updateInventoryTool, removeInventoryTool, getInventoryQuantitiesTool, } from "./inventory.js";
|
|
5
|
+
import { listTransactionsTool, recordTransactionTool, updateTransactionTool, deleteTransactionTool, getCostBasisTool, } from "./transactions.js";
|
|
6
|
+
import { getPortfolioSummaryTool, getPortfolioHistoryTool, getCardPerformanceTool, getCashFlowTool, getRealizedGainsTool, getPortfolioBreakdownTool, refreshPortfolioTool, } from "./portfolio.js";
|
|
7
|
+
import { listAlertsTool, createAlertTool, updateAlertTool, deleteAlertTool, } from "./alerts.js";
|
|
8
|
+
import { listNotificationsTool, getUnreadCountTool, markNotificationReadTool, markAllNotificationsReadTool, } from "./notifications.js";
|
|
9
|
+
export const tools = [
|
|
10
|
+
// Read-only (no auth)
|
|
11
|
+
searchCardsTool,
|
|
12
|
+
getCardTool,
|
|
13
|
+
getCardPricesTool,
|
|
14
|
+
getCardPriceHistoryTool,
|
|
15
|
+
searchSetsTool,
|
|
16
|
+
getSetTool,
|
|
17
|
+
listSetCardsTool,
|
|
18
|
+
getSealedProductsTool,
|
|
19
|
+
// Inventory (auth)
|
|
20
|
+
listInventoryTool,
|
|
21
|
+
getInventoryQuantitiesTool,
|
|
22
|
+
addInventoryTool,
|
|
23
|
+
updateInventoryTool,
|
|
24
|
+
removeInventoryTool,
|
|
25
|
+
// Transactions (auth)
|
|
26
|
+
listTransactionsTool,
|
|
27
|
+
recordTransactionTool,
|
|
28
|
+
updateTransactionTool,
|
|
29
|
+
deleteTransactionTool,
|
|
30
|
+
getCostBasisTool,
|
|
31
|
+
// Portfolio (auth; most are Premium-gated)
|
|
32
|
+
getPortfolioSummaryTool,
|
|
33
|
+
getPortfolioHistoryTool,
|
|
34
|
+
getCardPerformanceTool,
|
|
35
|
+
getCashFlowTool,
|
|
36
|
+
getRealizedGainsTool,
|
|
37
|
+
getPortfolioBreakdownTool,
|
|
38
|
+
refreshPortfolioTool,
|
|
39
|
+
// Price alerts (auth)
|
|
40
|
+
listAlertsTool,
|
|
41
|
+
createAlertTool,
|
|
42
|
+
updateAlertTool,
|
|
43
|
+
deleteAlertTool,
|
|
44
|
+
// Notifications (auth)
|
|
45
|
+
listNotificationsTool,
|
|
46
|
+
getUnreadCountTool,
|
|
47
|
+
markNotificationReadTool,
|
|
48
|
+
markAllNotificationsReadTool,
|
|
49
|
+
];
|
|
50
|
+
export const toolsByName = Object.fromEntries(tools.map((t) => [t.name, t]));
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAS5B,MAAM,CAAC,MAAM,KAAK,GAAqB;IACrC,sBAAsB;IACtB,eAAe;IACf,WAAW;IACX,iBAAiB;IACjB,uBAAuB;IACvB,cAAc;IACd,UAAU;IACV,gBAAgB;IAChB,qBAAqB;IACrB,mBAAmB;IACnB,iBAAiB;IACjB,0BAA0B;IAC1B,gBAAgB;IAChB,mBAAmB;IACnB,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,gBAAgB;IAChB,2CAA2C;IAC3C,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,eAAe;IACf,oBAAoB;IACpB,yBAAyB;IACzB,oBAAoB;IACpB,sBAAsB;IACtB,cAAc;IACd,eAAe;IACf,eAAe;IACf,eAAe;IACf,uBAAuB;IACvB,qBAAqB;IACrB,kBAAkB;IAClB,wBAAwB;IACxB,4BAA4B;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAmC,MAAM,CAAC,WAAW,CAC3E,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAC9B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
const inventoryItem = z.object({
|
|
4
|
+
cardId: z.string().uuid().describe("Internal IWMM card UUID. Get from search_cards or get_card."),
|
|
5
|
+
quantity: z.number().int().min(0).describe("Total quantity for this card+finish. 0 removes the row."),
|
|
6
|
+
isFoil: z.boolean().describe("Whether this is the foil variant. Foil and non-foil are tracked as separate rows."),
|
|
7
|
+
});
|
|
8
|
+
export const listInventoryTool = {
|
|
9
|
+
name: "list_inventory",
|
|
10
|
+
description: "List the authenticated user's card inventory, paginated. Requires IWMM_API_KEY. Returns cards with quantities, prices, and metadata.",
|
|
11
|
+
inputSchema: z.object({
|
|
12
|
+
page: z.number().int().min(1).optional(),
|
|
13
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
14
|
+
}),
|
|
15
|
+
handler: (input) => apiFetch({
|
|
16
|
+
path: "/api/v1/inventory",
|
|
17
|
+
query: input,
|
|
18
|
+
authenticated: true,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
export const addInventoryTool = {
|
|
22
|
+
name: "add_inventory",
|
|
23
|
+
description: "Add one or more cards to the authenticated user's inventory. Accepts a batch - pass a single-item array for one card. This is a real write. Use update_inventory to change quantities, remove_inventory to delete a row. Requires IWMM_API_KEY.",
|
|
24
|
+
inputSchema: z.object({ items: z.array(inventoryItem).min(1) }),
|
|
25
|
+
handler: (input) => apiFetch({ path: "/api/v1/inventory", method: "POST", body: input.items, authenticated: true }),
|
|
26
|
+
};
|
|
27
|
+
export const updateInventoryTool = {
|
|
28
|
+
name: "update_inventory",
|
|
29
|
+
description: "Update quantities for one or more existing inventory rows. Accepts a batch. Use remove_inventory to delete a row entirely. Requires IWMM_API_KEY.",
|
|
30
|
+
inputSchema: z.object({ items: z.array(inventoryItem).min(1) }),
|
|
31
|
+
handler: (input) => apiFetch({ path: "/api/v1/inventory", method: "PATCH", body: input.items, authenticated: true }),
|
|
32
|
+
};
|
|
33
|
+
export const removeInventoryTool = {
|
|
34
|
+
name: "remove_inventory",
|
|
35
|
+
description: "Remove a card+finish row from the authenticated user's inventory. Requires IWMM_API_KEY.",
|
|
36
|
+
inputSchema: z.object({
|
|
37
|
+
cardId: z.string().uuid(),
|
|
38
|
+
isFoil: z.boolean(),
|
|
39
|
+
}),
|
|
40
|
+
handler: (input) => apiFetch({ path: "/api/v1/inventory", method: "DELETE", body: input, authenticated: true }),
|
|
41
|
+
};
|
|
42
|
+
export const getInventoryQuantitiesTool = {
|
|
43
|
+
name: "get_inventory_quantities",
|
|
44
|
+
description: "Batch lookup: given a list of card UUIDs, return how many of each (normal + foil) the user owns. Useful before recommending adds. Requires IWMM_API_KEY.",
|
|
45
|
+
inputSchema: z.object({
|
|
46
|
+
cardIds: z.array(z.string().uuid()).min(1).max(200),
|
|
47
|
+
}),
|
|
48
|
+
handler: ({ cardIds }) => apiFetch({
|
|
49
|
+
path: "/api/v1/inventory/quantities",
|
|
50
|
+
query: { cardIds: cardIds.join(",") },
|
|
51
|
+
authenticated: true,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../src/tools/inventory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
export const listNotificationsTool = {
|
|
4
|
+
name: "list_notifications",
|
|
5
|
+
description: "List the authenticated user's price alert notifications, newest first. Includes both read and unread. Requires IWMM_API_KEY.",
|
|
6
|
+
inputSchema: z.object({}),
|
|
7
|
+
handler: () => apiFetch({ path: "/api/v1/notifications", authenticated: true }),
|
|
8
|
+
};
|
|
9
|
+
export const getUnreadCountTool = {
|
|
10
|
+
name: "get_unread_notification_count",
|
|
11
|
+
description: "Get the count of unread notifications for the authenticated user. Requires IWMM_API_KEY.",
|
|
12
|
+
inputSchema: z.object({}),
|
|
13
|
+
handler: () => apiFetch({ path: "/api/v1/notifications/unread-count", authenticated: true }),
|
|
14
|
+
};
|
|
15
|
+
export const markNotificationReadTool = {
|
|
16
|
+
name: "mark_notification_read",
|
|
17
|
+
description: "Mark a single notification as read. Requires IWMM_API_KEY.",
|
|
18
|
+
inputSchema: z.object({ id: z.string() }),
|
|
19
|
+
handler: ({ id }) => apiFetch({ path: `/api/v1/notifications/${encodeURIComponent(id)}/read`, method: "PATCH", authenticated: true }),
|
|
20
|
+
};
|
|
21
|
+
export const markAllNotificationsReadTool = {
|
|
22
|
+
name: "mark_all_notifications_read",
|
|
23
|
+
description: "Mark every notification for the authenticated user as read. Requires IWMM_API_KEY.",
|
|
24
|
+
inputSchema: z.object({}),
|
|
25
|
+
handler: () => apiFetch({ path: "/api/v1/notifications/read-all", method: "PATCH", authenticated: true }),
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../src/tools/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,8HAA8H;IAChI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAChF,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,+BAA+B;IACrC,WAAW,EAAE,0FAA0F;IACvG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,oCAAoC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC7F,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,4DAA4D;IACzE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACzC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAkB,EAAE,EAAE,CAClC,QAAQ,CAAC,EAAE,IAAI,EAAE,yBAAyB,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACnH,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,IAAI,EAAE,6BAA6B;IACnC,WAAW,EAAE,oFAAoF;IACjG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,gCAAgC,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC1G,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
export const getPortfolioSummaryTool = {
|
|
4
|
+
name: "get_portfolio_summary",
|
|
5
|
+
description: "Get the authenticated user's portfolio summary - current value, total invested, unrealized P&L, ROI, card/unit counts. Free tier sees current value + total invested only; Premium gets the full P&L set. Requires IWMM_API_KEY.",
|
|
6
|
+
inputSchema: z.object({}),
|
|
7
|
+
handler: () => apiFetch({ path: "/api/v1/portfolio", authenticated: true }),
|
|
8
|
+
};
|
|
9
|
+
export const getPortfolioHistoryTool = {
|
|
10
|
+
name: "get_portfolio_history",
|
|
11
|
+
description: "Get portfolio value history. Premium-gated - free tier receives 403. Requires IWMM_API_KEY.",
|
|
12
|
+
inputSchema: z.object({
|
|
13
|
+
days: z.number().int().min(1).max(3650).optional().describe("How many days of history. Server default applies if omitted."),
|
|
14
|
+
}),
|
|
15
|
+
handler: ({ days }) => apiFetch({ path: "/api/v1/portfolio/history", query: { days }, authenticated: true }),
|
|
16
|
+
};
|
|
17
|
+
export const getCardPerformanceTool = {
|
|
18
|
+
name: "get_card_performance",
|
|
19
|
+
description: "Get the user's best- or worst-performing cards by P&L. Default: best, top 10. Premium-gated. Requires IWMM_API_KEY.",
|
|
20
|
+
inputSchema: z.object({
|
|
21
|
+
type: z.enum(["best", "worst"]).optional(),
|
|
22
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
23
|
+
}),
|
|
24
|
+
handler: (input) => apiFetch({ path: "/api/v1/portfolio/performance", query: input, authenticated: true }),
|
|
25
|
+
};
|
|
26
|
+
export const getCashFlowTool = {
|
|
27
|
+
name: "get_cash_flow",
|
|
28
|
+
description: "Get the user's cash flow (money in vs money out from BUY/SELL transactions). Premium-gated. Requires IWMM_API_KEY.",
|
|
29
|
+
inputSchema: z.object({}),
|
|
30
|
+
handler: () => apiFetch({ path: "/api/v1/portfolio/cash-flow", authenticated: true }),
|
|
31
|
+
};
|
|
32
|
+
export const getRealizedGainsTool = {
|
|
33
|
+
name: "get_realized_gains",
|
|
34
|
+
description: "Get the user's realized gains from SELL transactions using FIFO cost basis. Premium-gated. Requires IWMM_API_KEY.",
|
|
35
|
+
inputSchema: z.object({}),
|
|
36
|
+
handler: () => apiFetch({ path: "/api/v1/portfolio/realized-gains", authenticated: true }),
|
|
37
|
+
};
|
|
38
|
+
export const getPortfolioBreakdownTool = {
|
|
39
|
+
name: "get_portfolio_breakdown",
|
|
40
|
+
description: "Get the user's collection value broken down by a dimension. Premium-gated. Requires IWMM_API_KEY.",
|
|
41
|
+
inputSchema: z.object({
|
|
42
|
+
by: z
|
|
43
|
+
.enum(["set", "rarity", "type", "format", "cost-basis"])
|
|
44
|
+
.describe("Dimension to break down by. 'cost-basis' buckets are gain/loss/at-cost."),
|
|
45
|
+
}),
|
|
46
|
+
handler: ({ by }) => apiFetch({ path: "/api/v1/portfolio/breakdown", query: { by }, authenticated: true }),
|
|
47
|
+
};
|
|
48
|
+
export const refreshPortfolioTool = {
|
|
49
|
+
name: "refresh_portfolio",
|
|
50
|
+
description: "Recalculate the user's portfolio P&L. Use after recording a batch of transactions if you want immediate fresh numbers. Requires IWMM_API_KEY.",
|
|
51
|
+
inputSchema: z.object({}),
|
|
52
|
+
handler: () => apiFetch({ path: "/api/v1/portfolio/refresh", method: "POST", authenticated: true }),
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=portfolio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio.js","sourceRoot":"","sources":["../../src/tools/portfolio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,kOAAkO;IACpO,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC5E,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,6FAA6F;IAC/F,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;KAC5H,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAqB,EAAE,EAAE,CACvC,QAAQ,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACxF,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,qHAAqH;IACvH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;QAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;KACnD,CAAC;IACF,OAAO,EAAE,CAAC,KAAkD,EAAE,EAAE,CAC9D,QAAQ,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACzF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,oHAAoH;IACtH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,6BAA6B,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACtF,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,mHAAmH;IACrH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,kCAAkC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CAC3F,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EACT,mGAAmG;IACrG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,EAAE,EAAE,CAAC;aACF,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;aACvD,QAAQ,CAAC,yEAAyE,CAAC;KACvF,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,EAAE,EAAkB,EAAE,EAAE,CAClC,QAAQ,CAAC,EAAE,IAAI,EAAE,6BAA6B,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACxF,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,+IAA+I;IACjJ,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;CACpG,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
export const searchCardsInputSchema = {
|
|
4
|
+
q: z
|
|
5
|
+
.string()
|
|
6
|
+
.optional()
|
|
7
|
+
.describe("Substring to search card name + flavor name. Optional; omit to filter purely by setCode/rarity/type/format."),
|
|
8
|
+
setCode: z.string().optional().describe("3-5 character set code (e.g. 'lea', 'mh3')."),
|
|
9
|
+
rarity: z
|
|
10
|
+
.enum(["common", "uncommon", "rare", "mythic"])
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Filter by rarity."),
|
|
13
|
+
type: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Substring match against card type line (e.g. 'Goblin', 'Instant')."),
|
|
17
|
+
format: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Filter to cards with a legality entry in this format (e.g. 'modern', 'commander')."),
|
|
21
|
+
legality: z
|
|
22
|
+
.enum(["legal", "banned", "restricted"])
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Used with 'format'. Defaults to 'legal' when format is set."),
|
|
25
|
+
page: z.number().int().min(1).optional().describe("1-based page index."),
|
|
26
|
+
limit: z.number().int().min(1).max(100).optional().describe("Page size (max 100)."),
|
|
27
|
+
};
|
|
28
|
+
export async function searchCards(input) {
|
|
29
|
+
return apiFetch({
|
|
30
|
+
path: "/api/v1/cards",
|
|
31
|
+
query: input,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export const searchCardsTool = {
|
|
35
|
+
name: "search_cards",
|
|
36
|
+
description: "Search Magic: The Gathering cards by name (substring), set code, rarity, type, or format legality. Returns a paginated list with prices and basic metadata. Use this for catalog lookups; for a specific printing prefer get_card with set+number.",
|
|
37
|
+
inputSchema: z.object(searchCardsInputSchema),
|
|
38
|
+
handler: searchCards,
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=search-cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-cards.js","sourceRoot":"","sources":["../../src/tools/search-cards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,CAAC,EAAE,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,6GAA6G,CAAC;IAC1H,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IACtF,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;SAC9C,QAAQ,EAAE;SACV,QAAQ,CAAC,mBAAmB,CAAC;IAChC,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oEAAoE,CAAC;IACjF,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oFAAoF,CAAC;IACjG,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;SACvC,QAAQ,EAAE;SACV,QAAQ,CAAC,6DAA6D,CAAC;IAC1E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACxE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACpF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAA8B;IAC9D,OAAO,QAAQ,CAAC;QACd,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,KAAoD;KAC5D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,oPAAoP;IACtP,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC;IAC7C,OAAO,EAAE,WAAW;CACrB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
export const searchSetsTool = {
|
|
4
|
+
name: "search_sets",
|
|
5
|
+
description: "List Magic: The Gathering sets, optionally paginated. Returns set code, name, release date, type, and aggregate prices.",
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
page: z.number().int().min(1).optional(),
|
|
8
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
9
|
+
}),
|
|
10
|
+
handler: (input) => apiFetch({ path: "/api/v1/sets", query: input }),
|
|
11
|
+
};
|
|
12
|
+
export const getSetTool = {
|
|
13
|
+
name: "get_set",
|
|
14
|
+
description: "Get detail for a single set by code (e.g. 'lea', 'mh3').",
|
|
15
|
+
inputSchema: z.object({ code: z.string() }),
|
|
16
|
+
handler: ({ code }) => apiFetch({ path: `/api/v1/sets/${encodeURIComponent(code)}` }),
|
|
17
|
+
};
|
|
18
|
+
export const listSetCardsTool = {
|
|
19
|
+
name: "list_set_cards",
|
|
20
|
+
description: "List all cards in a set, paginated. Supports the same filters as search_cards (rarity, type, format, legality).",
|
|
21
|
+
inputSchema: z.object({
|
|
22
|
+
code: z.string().describe("Set code."),
|
|
23
|
+
rarity: z.enum(["common", "uncommon", "rare", "mythic"]).optional(),
|
|
24
|
+
type: z.string().optional(),
|
|
25
|
+
format: z.string().optional(),
|
|
26
|
+
legality: z.enum(["legal", "banned", "restricted"]).optional(),
|
|
27
|
+
page: z.number().int().min(1).optional(),
|
|
28
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
29
|
+
}),
|
|
30
|
+
handler: ({ code, ...rest }) => apiFetch({
|
|
31
|
+
path: `/api/v1/sets/${encodeURIComponent(code)}/cards`,
|
|
32
|
+
query: rest,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
export const getSealedProductsTool = {
|
|
36
|
+
name: "get_sealed_products",
|
|
37
|
+
description: "List sealed products (booster boxes, bundles, commander decks, etc.) for a set. Each entry includes a TCGPlayer purchase URL.",
|
|
38
|
+
inputSchema: z.object({ code: z.string() }),
|
|
39
|
+
handler: ({ code }) => apiFetch({ path: `/api/v1/sets/${encodeURIComponent(code)}/sealed-products` }),
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=sets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sets.js","sourceRoot":"","sources":["../../src/tools/sets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,yHAAyH;IAC3H,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;KACnD,CAAC;IACF,OAAO,EAAE,CAAC,KAA8B,EAAE,EAAE,CAC1C,QAAQ,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,KAAoD,EAAE,CAAC;CAClG,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,0DAA0D;IACvE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC3C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAoB,EAAE,EAAE,CACtC,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;CACjE,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,iHAAiH;IACnH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;QACtC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;QACnE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC7B,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE;QAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;KACnD,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAA8C,EAAE,EAAE,CACzE,QAAQ,CAAC;QACP,IAAI,EAAE,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,QAAQ;QACtD,KAAK,EAAE,IAAmD;KAC3D,CAAC;CACL,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,+HAA+H;IACjI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC3C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAoB,EAAE,EAAE,CACtC,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,kBAAkB,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;CACjF,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch } from "../api-client.js";
|
|
3
|
+
const transactionCreate = z.object({
|
|
4
|
+
cardId: z.string().describe("Internal IWMM card UUID."),
|
|
5
|
+
type: z.enum(["BUY", "SELL"]),
|
|
6
|
+
quantity: z.number().int().min(1),
|
|
7
|
+
pricePerUnit: z.number().min(0).describe("Per-unit price in USD."),
|
|
8
|
+
isFoil: z.boolean(),
|
|
9
|
+
date: z.string().describe("ISO 8601 date (YYYY-MM-DD)."),
|
|
10
|
+
source: z.string().optional().describe("Where the transaction happened (e.g. 'TCGPlayer', 'LGS')."),
|
|
11
|
+
fees: z.number().min(0).optional(),
|
|
12
|
+
notes: z.string().optional(),
|
|
13
|
+
skipInventorySync: z
|
|
14
|
+
.boolean()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("If true, record the transaction without adjusting inventory. Default false - transactions normally update inventory."),
|
|
17
|
+
});
|
|
18
|
+
const transactionUpdate = z.object({
|
|
19
|
+
quantity: z.number().int().min(1).optional(),
|
|
20
|
+
pricePerUnit: z.number().min(0).optional(),
|
|
21
|
+
date: z.string().optional(),
|
|
22
|
+
source: z.string().optional(),
|
|
23
|
+
fees: z.number().min(0).optional(),
|
|
24
|
+
notes: z.string().optional(),
|
|
25
|
+
});
|
|
26
|
+
export const listTransactionsTool = {
|
|
27
|
+
name: "list_transactions",
|
|
28
|
+
description: "List the authenticated user's transactions, paginated. Supports sort/filter query params. Free tier sees the last 30 days only; Premium gets full history. Requires IWMM_API_KEY.",
|
|
29
|
+
inputSchema: z.object({
|
|
30
|
+
page: z.number().int().min(1).optional(),
|
|
31
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
32
|
+
sort: z.string().optional().describe("Sort key (e.g. TX_DATE, TX_TYPE, TX_CARD, TX_PRICE)."),
|
|
33
|
+
order: z.enum(["asc", "desc"]).optional(),
|
|
34
|
+
type: z.enum(["BUY", "SELL"]).optional(),
|
|
35
|
+
}),
|
|
36
|
+
handler: (input) => apiFetch({
|
|
37
|
+
path: "/api/v1/transactions",
|
|
38
|
+
query: input,
|
|
39
|
+
authenticated: true,
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
export const recordTransactionTool = {
|
|
43
|
+
name: "record_transaction",
|
|
44
|
+
description: "Record a buy or sell transaction. By default this also adjusts inventory (BUY adds, SELL subtracts). This is a real write. Requires IWMM_API_KEY.",
|
|
45
|
+
inputSchema: transactionCreate,
|
|
46
|
+
handler: (input) => apiFetch({ path: "/api/v1/transactions", method: "POST", body: input, authenticated: true }),
|
|
47
|
+
};
|
|
48
|
+
export const updateTransactionTool = {
|
|
49
|
+
name: "update_transaction",
|
|
50
|
+
description: "Update an existing transaction by ID. Only the fields supplied are changed. Card identity and type (BUY/SELL) cannot be changed via this endpoint - delete and re-create instead. Requires IWMM_API_KEY.",
|
|
51
|
+
inputSchema: z.object({
|
|
52
|
+
id: z.number().int().min(1).describe("Transaction ID from list_transactions."),
|
|
53
|
+
patch: transactionUpdate,
|
|
54
|
+
}),
|
|
55
|
+
handler: ({ id, patch }) => apiFetch({ path: `/api/v1/transactions/${id}`, method: "PATCH", body: patch, authenticated: true }),
|
|
56
|
+
};
|
|
57
|
+
export const deleteTransactionTool = {
|
|
58
|
+
name: "delete_transaction",
|
|
59
|
+
description: "Delete a transaction by ID. Requires IWMM_API_KEY.",
|
|
60
|
+
inputSchema: z.object({ id: z.number().int().min(1) }),
|
|
61
|
+
handler: ({ id }) => apiFetch({ path: `/api/v1/transactions/${id}`, method: "DELETE", authenticated: true }),
|
|
62
|
+
};
|
|
63
|
+
export const getCostBasisTool = {
|
|
64
|
+
name: "get_cost_basis",
|
|
65
|
+
description: "Get FIFO cost basis for a specific card+finish for the authenticated user. Pass either cardId or (setCode, setNumber). Requires IWMM_API_KEY.",
|
|
66
|
+
inputSchema: z
|
|
67
|
+
.object({
|
|
68
|
+
cardId: z.string().optional(),
|
|
69
|
+
setCode: z.string().optional(),
|
|
70
|
+
setNumber: z.string().optional(),
|
|
71
|
+
isFoil: z.boolean().default(false),
|
|
72
|
+
})
|
|
73
|
+
.refine((v) => !!v.cardId || (!!v.setCode && !!v.setNumber), {
|
|
74
|
+
message: "Provide either cardId, or both setCode and setNumber.",
|
|
75
|
+
}),
|
|
76
|
+
handler: (input) => {
|
|
77
|
+
const query = { isFoil: input.isFoil };
|
|
78
|
+
const path = input.cardId
|
|
79
|
+
? `/api/v1/transactions/cost-basis/${encodeURIComponent(input.cardId)}`
|
|
80
|
+
: `/api/v1/transactions/cost-basis/${encodeURIComponent(input.setCode)}/${encodeURIComponent(input.setNumber)}`;
|
|
81
|
+
return apiFetch({ path, query, authenticated: true });
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=transactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/tools/transactions.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iwantmymtg-mcp",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "MCP server for I Want My MTG - query cards/sets and manage your collection from Claude Desktop, Claude Code, Cursor, and other MCP clients.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"iwantmymtg-mcp": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"test": "node --test --import tsx test/*.test.ts",
|
|
18
|
+
"clean": "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"model-context-protocol",
|
|
26
|
+
"magic-the-gathering",
|
|
27
|
+
"mtg",
|
|
28
|
+
"claude"
|
|
29
|
+
],
|
|
30
|
+
"author": "matthewdtowles",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/matthewdtowles/iwantmymtg-mcp.git"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://iwantmymtg.net",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
39
|
+
"zod": "^3.23.0",
|
|
40
|
+
"zod-to-json-schema": "^3.23.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.14.0",
|
|
44
|
+
"tsx": "^4.16.0",
|
|
45
|
+
"typescript": "^5.5.0"
|
|
46
|
+
}
|
|
47
|
+
}
|