@battle-racing/br-common-lib 4.6.0 → 4.6.2
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/.gemini/settings.json +10 -0
- package/dist/domains/ticketing/Ticketing.schema.d.ts +51 -0
- package/dist/domains/ticketing/Ticketing.schema.js +13 -1
- package/dist/domains/ticketing/Ticketing.types.d.ts +3 -1
- package/dist/domains/user/User.schema.d.ts +9 -9
- package/dist/domains/user/User.schema.js +2 -2
- package/dist/mcp-server/index.d.ts +1 -0
- package/dist/mcp-server/index.js +174 -0
- package/package.json +6 -1
- package/src/domains/ticketing/Ticketing.schema.ts +14 -0
- package/src/domains/ticketing/Ticketing.types.ts +4 -0
- package/src/domains/user/User.schema.ts +2 -2
- package/src/mcp-server/index.ts +171 -0
|
@@ -85,6 +85,57 @@ export declare const purchaseSchema: z.ZodObject<{
|
|
|
85
85
|
createdAt: z.ZodDate;
|
|
86
86
|
updatedAt: z.ZodDate;
|
|
87
87
|
}, z.core.$strip>;
|
|
88
|
+
export declare const filterPurchaseSchema: z.ZodObject<{
|
|
89
|
+
purchaseNumber: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
90
|
+
buyerUserId: z.ZodOptional<z.ZodString>;
|
|
91
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
92
|
+
readonly PENDING: "pending";
|
|
93
|
+
readonly PAID: "paid";
|
|
94
|
+
readonly CANCELLED: "cancelled";
|
|
95
|
+
}>>;
|
|
96
|
+
guestName: z.ZodOptional<z.ZodString>;
|
|
97
|
+
guestContact: z.ZodOptional<z.ZodString>;
|
|
98
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
99
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
100
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
101
|
+
}, z.core.$strip>;
|
|
102
|
+
export declare const paginatedPurchaseSchema: z.ZodObject<{
|
|
103
|
+
data: z.ZodArray<z.ZodObject<{
|
|
104
|
+
id: z.ZodUUID;
|
|
105
|
+
purchaseNumber: z.ZodNumber;
|
|
106
|
+
buyerUserId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
107
|
+
guestName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
108
|
+
guestContact: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
109
|
+
items: z.ZodArray<z.ZodObject<{
|
|
110
|
+
ticketType: z.ZodEnum<{
|
|
111
|
+
readonly Race: "Race";
|
|
112
|
+
readonly Battle: "Battle";
|
|
113
|
+
}>;
|
|
114
|
+
quantity: z.ZodNumber;
|
|
115
|
+
priceCents: z.ZodNumber;
|
|
116
|
+
}, z.core.$strip>>;
|
|
117
|
+
totalAmountCents: z.ZodNumber;
|
|
118
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
119
|
+
readonly PENDING: "pending";
|
|
120
|
+
readonly PAID: "paid";
|
|
121
|
+
readonly CANCELLED: "cancelled";
|
|
122
|
+
}>>;
|
|
123
|
+
totalTickets: z.ZodOptional<z.ZodNumber>;
|
|
124
|
+
ticketType: z.ZodOptional<z.ZodEnum<{
|
|
125
|
+
readonly RACE: "race";
|
|
126
|
+
readonly BATTLE: "battle";
|
|
127
|
+
readonly SOCCER: "soccer";
|
|
128
|
+
}>>;
|
|
129
|
+
paymentData: z.ZodOptional<z.ZodAny>;
|
|
130
|
+
createdAt: z.ZodDate;
|
|
131
|
+
updatedAt: z.ZodDate;
|
|
132
|
+
}, z.core.$strip>>;
|
|
133
|
+
meta: z.ZodObject<{
|
|
134
|
+
nextCursor: z.ZodOptional<z.ZodString>;
|
|
135
|
+
hasMore: z.ZodOptional<z.ZodBoolean>;
|
|
136
|
+
limit: z.ZodNumber;
|
|
137
|
+
}, z.core.$strip>;
|
|
138
|
+
}, z.core.$strip>;
|
|
88
139
|
export declare const createPurchaseInputSchema: z.ZodObject<{
|
|
89
140
|
buyerUserId: z.ZodOptional<z.ZodString>;
|
|
90
141
|
guestName: z.ZodOptional<z.ZodString>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.gameTurnQueueItemSchema = exports.gameTurnSchema = exports.gameTurnTaskSchema = exports.gameTurnTaskStatusSchema = exports.gameTurnTaskTypeSchema = exports.gameTurnCheckSchema = exports.gameTurnStatusSchema = exports.createPurchaseInputSchema = exports.purchaseSchema = exports.purchaseItemSchema = exports.purchaseStatusSchema = exports.gameTicketSchema = exports.ticketSummarySchema = exports.ticketTypeSchema = exports.ticketUserTypeSchema = exports.gameTicketStatusSchema = void 0;
|
|
3
|
+
exports.gameTurnQueueItemSchema = exports.gameTurnSchema = exports.gameTurnTaskSchema = exports.gameTurnTaskStatusSchema = exports.gameTurnTaskTypeSchema = exports.gameTurnCheckSchema = exports.gameTurnStatusSchema = exports.createPurchaseInputSchema = exports.paginatedPurchaseSchema = exports.filterPurchaseSchema = exports.purchaseSchema = exports.purchaseItemSchema = exports.purchaseStatusSchema = exports.gameTicketSchema = exports.ticketSummarySchema = exports.ticketTypeSchema = exports.ticketUserTypeSchema = exports.gameTicketStatusSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const pagination_1 = require("../pagination");
|
|
5
6
|
const Ticketing_const_1 = require("./Ticketing.const");
|
|
6
7
|
const game_1 = require("../game");
|
|
7
8
|
exports.gameTicketStatusSchema = zod_1.z.enum(Ticketing_const_1.GAME_TICKET_STATUS);
|
|
@@ -43,6 +44,17 @@ exports.purchaseSchema = zod_1.z.object({
|
|
|
43
44
|
createdAt: zod_1.z.date(),
|
|
44
45
|
updatedAt: zod_1.z.date(),
|
|
45
46
|
});
|
|
47
|
+
exports.filterPurchaseSchema = zod_1.z.object({
|
|
48
|
+
purchaseNumber: zod_1.z.coerce.number().optional(),
|
|
49
|
+
buyerUserId: zod_1.z.string().optional(),
|
|
50
|
+
status: exports.purchaseStatusSchema.optional(),
|
|
51
|
+
guestName: zod_1.z.string().optional(),
|
|
52
|
+
guestContact: zod_1.z.string().optional(),
|
|
53
|
+
page: zod_1.z.coerce.number().min(1).default(1),
|
|
54
|
+
limit: zod_1.z.coerce.number().min(1).max(100).default(10),
|
|
55
|
+
cursor: zod_1.z.string().optional(),
|
|
56
|
+
});
|
|
57
|
+
exports.paginatedPurchaseSchema = (0, pagination_1.paginatedResponseSchema)(exports.purchaseSchema);
|
|
46
58
|
exports.createPurchaseInputSchema = zod_1.z.object({
|
|
47
59
|
buyerUserId: zod_1.z.string().optional(),
|
|
48
60
|
guestName: zod_1.z.string().optional(),
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createPurchaseInputSchema, gameTicketSchema, gameTicketStatusSchema, gameTurnCheckSchema, gameTurnQueueItemSchema, gameTurnSchema, gameTurnStatusSchema, gameTurnTaskSchema, gameTurnTaskStatusSchema, gameTurnTaskTypeSchema, purchaseSchema, ticketSummarySchema, ticketTypeSchema, ticketUserTypeSchema } from './Ticketing.schema';
|
|
2
|
+
import { createPurchaseInputSchema, filterPurchaseSchema, gameTicketSchema, gameTicketStatusSchema, gameTurnCheckSchema, gameTurnQueueItemSchema, gameTurnSchema, gameTurnStatusSchema, gameTurnTaskSchema, gameTurnTaskStatusSchema, gameTurnTaskTypeSchema, paginatedPurchaseSchema, purchaseSchema, ticketSummarySchema, ticketTypeSchema, ticketUserTypeSchema } from './Ticketing.schema';
|
|
3
3
|
export type TicketType = z.infer<typeof ticketTypeSchema>;
|
|
4
4
|
export type GameTicketStatus = z.infer<typeof gameTicketStatusSchema>;
|
|
5
5
|
export type TicketUserType = z.infer<typeof ticketUserTypeSchema>;
|
|
6
6
|
export type TicketSummary = z.infer<typeof ticketSummarySchema>;
|
|
7
7
|
export type Purchase = z.infer<typeof purchaseSchema>;
|
|
8
8
|
export type CreatePurchaseInput = z.infer<typeof createPurchaseInputSchema>;
|
|
9
|
+
export type FilterPurchase = z.infer<typeof filterPurchaseSchema>;
|
|
10
|
+
export type PaginatedPurchase = z.infer<typeof paginatedPurchaseSchema>;
|
|
9
11
|
export type GameTicket = z.infer<typeof gameTicketSchema>;
|
|
10
12
|
export type GameTurnStatus = z.infer<typeof gameTurnStatusSchema>;
|
|
11
13
|
export type GameTurnCheck = z.infer<typeof gameTurnCheckSchema>;
|
|
@@ -7,8 +7,8 @@ export declare const PHONE_REGEX: RegExp;
|
|
|
7
7
|
export declare const emailOrPhoneSchema: z.ZodString;
|
|
8
8
|
export declare const userSchema: z.ZodObject<{
|
|
9
9
|
id: z.ZodUUID;
|
|
10
|
-
name: z.ZodString
|
|
11
|
-
lastName: z.ZodString
|
|
10
|
+
name: z.ZodOptional<z.ZodString>;
|
|
11
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
12
12
|
email: z.ZodNullable<z.ZodOptional<z.ZodEmail>>;
|
|
13
13
|
phoneNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
14
14
|
role: z.ZodEnum<{
|
|
@@ -48,8 +48,8 @@ export declare const initialUserSchema: z.ZodObject<{
|
|
|
48
48
|
*/
|
|
49
49
|
export declare const authUserSchema: z.ZodObject<{
|
|
50
50
|
id: z.ZodUUID;
|
|
51
|
-
name: z.ZodString
|
|
52
|
-
lastName: z.ZodString
|
|
51
|
+
name: z.ZodOptional<z.ZodString>;
|
|
52
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
53
53
|
email: z.ZodNullable<z.ZodOptional<z.ZodEmail>>;
|
|
54
54
|
phoneNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
55
55
|
role: z.ZodEnum<{
|
|
@@ -72,8 +72,8 @@ export declare const authUserSchema: z.ZodObject<{
|
|
|
72
72
|
}, z.core.$strip>;
|
|
73
73
|
export declare const userWithPasswordSchema: z.ZodIntersection<z.ZodObject<{
|
|
74
74
|
id: z.ZodUUID;
|
|
75
|
-
name: z.ZodString
|
|
76
|
-
lastName: z.ZodString
|
|
75
|
+
name: z.ZodOptional<z.ZodString>;
|
|
76
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
77
77
|
email: z.ZodNullable<z.ZodOptional<z.ZodEmail>>;
|
|
78
78
|
phoneNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
79
79
|
role: z.ZodEnum<{
|
|
@@ -104,7 +104,7 @@ export declare const userVerifySchema: z.ZodObject<{
|
|
|
104
104
|
code: z.ZodString;
|
|
105
105
|
}, z.core.$strip>;
|
|
106
106
|
export declare const userCompleteProfileSchema: z.ZodObject<{
|
|
107
|
-
name: z.ZodString
|
|
107
|
+
name: z.ZodOptional<z.ZodString>;
|
|
108
108
|
lastName: z.ZodOptional<z.ZodString>;
|
|
109
109
|
nickname: z.ZodString;
|
|
110
110
|
birthDate: z.ZodCoercedDate<unknown>;
|
|
@@ -112,9 +112,9 @@ export declare const userCompleteProfileSchema: z.ZodObject<{
|
|
|
112
112
|
teamName: z.ZodOptional<z.ZodString>;
|
|
113
113
|
}, z.core.$strip>;
|
|
114
114
|
export declare const userRegistrationInputSchema: z.ZodObject<{
|
|
115
|
-
name: z.ZodString
|
|
115
|
+
name: z.ZodOptional<z.ZodString>;
|
|
116
116
|
email: z.ZodNullable<z.ZodOptional<z.ZodEmail>>;
|
|
117
|
-
lastName: z.ZodString
|
|
117
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
118
118
|
phoneNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
119
119
|
password: z.ZodString;
|
|
120
120
|
nickname: z.ZodString;
|
|
@@ -17,8 +17,8 @@ exports.emailOrPhoneSchema = zod_1.z
|
|
|
17
17
|
}, { message: 'Must be a valid email or phone number' });
|
|
18
18
|
const baseUserObj = zod_1.z.object({
|
|
19
19
|
id: zod_1.z.uuidv4(),
|
|
20
|
-
name: zod_1.z.string(),
|
|
21
|
-
lastName: zod_1.z.string(),
|
|
20
|
+
name: zod_1.z.string().optional(),
|
|
21
|
+
lastName: zod_1.z.string().optional(),
|
|
22
22
|
email: zod_1.z.email().toLowerCase().optional().nullable(),
|
|
23
23
|
phoneNumber: zod_1.z.string().regex(exports.PHONE_REGEX, 'Invalid phone number format').optional().nullable(),
|
|
24
24
|
// --- ACCESS CONTROL ---
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
37
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
38
|
+
const zod_1 = require("zod");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
/**
|
|
42
|
+
* MCP Server for Battle Racing Common Library
|
|
43
|
+
* This server allows other AI agents to query types, schemas and constants
|
|
44
|
+
* from the br-common-lib repository locally.
|
|
45
|
+
*/
|
|
46
|
+
const DOMAINS_DIR = path.resolve(__dirname, "../../src/domains");
|
|
47
|
+
const server = new mcp_js_1.McpServer({
|
|
48
|
+
name: "br-common-lib-mcp",
|
|
49
|
+
version: "1.1.1",
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* List all available domains in src/domains
|
|
53
|
+
*/
|
|
54
|
+
async function listDomains() {
|
|
55
|
+
if (!fs.existsSync(DOMAINS_DIR)) {
|
|
56
|
+
throw new Error(`Domains directory not found at ${DOMAINS_DIR}`);
|
|
57
|
+
}
|
|
58
|
+
const entries = fs.readdirSync(DOMAINS_DIR, { withFileTypes: true });
|
|
59
|
+
return entries
|
|
60
|
+
.filter((entry) => entry.isDirectory())
|
|
61
|
+
.map((entry) => entry.name);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get details for a specific domain (recursive)
|
|
65
|
+
*/
|
|
66
|
+
async function getDomainDetails(domain) {
|
|
67
|
+
const domainPath = path.join(DOMAINS_DIR, domain);
|
|
68
|
+
if (!fs.existsSync(domainPath)) {
|
|
69
|
+
throw new Error(`Domain "${domain}" not found at ${domainPath}`);
|
|
70
|
+
}
|
|
71
|
+
let output = `## Domain: ${domain}\n\n`;
|
|
72
|
+
function readDirRecursive(dir) {
|
|
73
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
const fullPath = path.join(dir, entry.name);
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
readDirRecursive(fullPath);
|
|
78
|
+
}
|
|
79
|
+
else if (entry.name.endsWith(".types.ts") ||
|
|
80
|
+
entry.name.endsWith(".schema.ts") ||
|
|
81
|
+
entry.name.endsWith(".const.ts") ||
|
|
82
|
+
entry.name === "index.ts") {
|
|
83
|
+
const relativePath = path.relative(domainPath, fullPath);
|
|
84
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
85
|
+
output += `### File: ${relativePath}\n\`\`\`typescript\n${content}\n\`\`\`\n\n`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
readDirRecursive(domainPath);
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Search for a symbol (type, constant, etc) across all domains
|
|
94
|
+
*/
|
|
95
|
+
async function searchSymbol(query) {
|
|
96
|
+
const domains = await listDomains();
|
|
97
|
+
let results = [];
|
|
98
|
+
for (const domain of domains) {
|
|
99
|
+
const domainPath = path.join(DOMAINS_DIR, domain);
|
|
100
|
+
function searchInDir(dir) {
|
|
101
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
const fullPath = path.join(dir, entry.name);
|
|
104
|
+
if (entry.isDirectory()) {
|
|
105
|
+
searchInDir(fullPath);
|
|
106
|
+
}
|
|
107
|
+
else if (entry.isFile() && (entry.name.endsWith(".ts"))) {
|
|
108
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
109
|
+
if (content.includes(query)) {
|
|
110
|
+
const lines = content.split("\n");
|
|
111
|
+
const matchLine = lines.find(l => l.includes(query)) || "";
|
|
112
|
+
results.push({
|
|
113
|
+
domain,
|
|
114
|
+
file: path.relative(DOMAINS_DIR, fullPath),
|
|
115
|
+
match: matchLine.trim()
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
searchInDir(domainPath);
|
|
122
|
+
}
|
|
123
|
+
if (results.length === 0)
|
|
124
|
+
return `No results found for "${query}"`;
|
|
125
|
+
return results
|
|
126
|
+
.map(r => `- [${r.domain}] ${r.file}: \`${r.match}\``)
|
|
127
|
+
.join("\n");
|
|
128
|
+
}
|
|
129
|
+
// Register tools using the high-level McpServer API (registerTool)
|
|
130
|
+
server.registerTool("list_domains", {
|
|
131
|
+
description: "List all available domains in br-common-lib (e.g., kart, game, powerUp)",
|
|
132
|
+
}, async () => {
|
|
133
|
+
const domains = await listDomains();
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: "text",
|
|
138
|
+
text: `Available domains: ${domains.join(", ")}`,
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
server.registerTool("get_domain_details", {
|
|
144
|
+
description: "Get all types, schemas, and constants for a specific domain (recursive)",
|
|
145
|
+
inputSchema: zod_1.z.object({
|
|
146
|
+
domain: zod_1.z.string().describe("The name of the domain (e.g., 'kart')"),
|
|
147
|
+
}),
|
|
148
|
+
}, async ({ domain }) => {
|
|
149
|
+
const details = await getDomainDetails(domain);
|
|
150
|
+
return {
|
|
151
|
+
content: [{ type: "text", text: details }],
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
server.registerTool("search_symbol", {
|
|
155
|
+
description: "Search for a specific type, constant or property across all domains",
|
|
156
|
+
inputSchema: zod_1.z.object({
|
|
157
|
+
query: zod_1.z.string().describe("The symbol or string to search for (e.g., 'hardwareState')"),
|
|
158
|
+
}),
|
|
159
|
+
}, async ({ query }) => {
|
|
160
|
+
const results = await searchSymbol(query);
|
|
161
|
+
return {
|
|
162
|
+
content: [{ type: "text", text: results }],
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
// Start the server
|
|
166
|
+
async function main() {
|
|
167
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
168
|
+
await server.connect(transport);
|
|
169
|
+
console.error("Battle Racing Common Lib MCP Server running on stdio");
|
|
170
|
+
}
|
|
171
|
+
main().catch((error) => {
|
|
172
|
+
console.error("Fatal error in main():", error);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@battle-racing/br-common-lib",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.2",
|
|
4
4
|
"description": "Common library for all Battle Racing Repositorios",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -30,10 +30,15 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"private": false,
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
34
|
+
"@types/node": "^25.6.0",
|
|
33
35
|
"typescript": "^5.8.3",
|
|
34
36
|
"zod": "^4.2.1"
|
|
35
37
|
},
|
|
36
38
|
"peerDependencies": {
|
|
37
39
|
"zod": "^4.2.1"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@battle-racing/br-common-lib": "^4.6.1"
|
|
38
43
|
}
|
|
39
44
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { paginatedResponseSchema } from '../pagination';
|
|
2
3
|
import {
|
|
3
4
|
GAME_TICKET_STATUS,
|
|
4
5
|
GAME_TURN_CHECK,
|
|
@@ -59,6 +60,19 @@ export const purchaseSchema = z.object({
|
|
|
59
60
|
updatedAt: z.date(),
|
|
60
61
|
});
|
|
61
62
|
|
|
63
|
+
export const filterPurchaseSchema = z.object({
|
|
64
|
+
purchaseNumber: z.coerce.number().optional(),
|
|
65
|
+
buyerUserId: z.string().optional(),
|
|
66
|
+
status: purchaseStatusSchema.optional(),
|
|
67
|
+
guestName: z.string().optional(),
|
|
68
|
+
guestContact: z.string().optional(),
|
|
69
|
+
page: z.coerce.number().min(1).default(1),
|
|
70
|
+
limit: z.coerce.number().min(1).max(100).default(10),
|
|
71
|
+
cursor: z.string().optional(),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const paginatedPurchaseSchema = paginatedResponseSchema(purchaseSchema);
|
|
75
|
+
|
|
62
76
|
export const createPurchaseInputSchema = z.object({
|
|
63
77
|
buyerUserId: z.string().optional(),
|
|
64
78
|
guestName: z.string().optional(),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import {
|
|
3
3
|
createPurchaseInputSchema,
|
|
4
|
+
filterPurchaseSchema,
|
|
4
5
|
gameTicketSchema,
|
|
5
6
|
gameTicketStatusSchema,
|
|
6
7
|
gameTurnCheckSchema,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
gameTurnTaskSchema,
|
|
11
12
|
gameTurnTaskStatusSchema,
|
|
12
13
|
gameTurnTaskTypeSchema,
|
|
14
|
+
paginatedPurchaseSchema,
|
|
13
15
|
purchaseSchema,
|
|
14
16
|
ticketSummarySchema,
|
|
15
17
|
ticketTypeSchema,
|
|
@@ -23,6 +25,8 @@ export type TicketSummary = z.infer<typeof ticketSummarySchema>;
|
|
|
23
25
|
|
|
24
26
|
export type Purchase = z.infer<typeof purchaseSchema>;
|
|
25
27
|
export type CreatePurchaseInput = z.infer<typeof createPurchaseInputSchema>;
|
|
28
|
+
export type FilterPurchase = z.infer<typeof filterPurchaseSchema>;
|
|
29
|
+
export type PaginatedPurchase = z.infer<typeof paginatedPurchaseSchema>;
|
|
26
30
|
|
|
27
31
|
export type GameTicket = z.infer<typeof gameTicketSchema>;
|
|
28
32
|
|
|
@@ -22,8 +22,8 @@ export const emailOrPhoneSchema = z
|
|
|
22
22
|
const baseUserObj = z.object({
|
|
23
23
|
id: z.uuidv4(),
|
|
24
24
|
|
|
25
|
-
name: z.string(),
|
|
26
|
-
lastName: z.string(),
|
|
25
|
+
name: z.string().optional(),
|
|
26
|
+
lastName: z.string().optional(),
|
|
27
27
|
|
|
28
28
|
email: z.email().toLowerCase().optional().nullable(),
|
|
29
29
|
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* MCP Server for Battle Racing Common Library
|
|
9
|
+
* This server allows other AI agents to query types, schemas and constants
|
|
10
|
+
* from the br-common-lib repository locally.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const DOMAINS_DIR = path.resolve(__dirname, "../../src/domains");
|
|
14
|
+
|
|
15
|
+
const server = new McpServer({
|
|
16
|
+
name: "br-common-lib-mcp",
|
|
17
|
+
version: "1.1.1",
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* List all available domains in src/domains
|
|
22
|
+
*/
|
|
23
|
+
async function listDomains() {
|
|
24
|
+
if (!fs.existsSync(DOMAINS_DIR)) {
|
|
25
|
+
throw new Error(`Domains directory not found at ${DOMAINS_DIR}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const entries = fs.readdirSync(DOMAINS_DIR, { withFileTypes: true });
|
|
29
|
+
return entries
|
|
30
|
+
.filter((entry: fs.Dirent) => entry.isDirectory())
|
|
31
|
+
.map((entry: fs.Dirent) => entry.name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get details for a specific domain (recursive)
|
|
36
|
+
*/
|
|
37
|
+
async function getDomainDetails(domain: string) {
|
|
38
|
+
const domainPath = path.join(DOMAINS_DIR, domain);
|
|
39
|
+
|
|
40
|
+
if (!fs.existsSync(domainPath)) {
|
|
41
|
+
throw new Error(`Domain "${domain}" not found at ${domainPath}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let output = `## Domain: ${domain}\n\n`;
|
|
45
|
+
|
|
46
|
+
function readDirRecursive(dir: string) {
|
|
47
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
48
|
+
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const fullPath = path.join(dir, entry.name);
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
readDirRecursive(fullPath);
|
|
53
|
+
} else if (
|
|
54
|
+
entry.name.endsWith(".types.ts") ||
|
|
55
|
+
entry.name.endsWith(".schema.ts") ||
|
|
56
|
+
entry.name.endsWith(".const.ts") ||
|
|
57
|
+
entry.name === "index.ts"
|
|
58
|
+
) {
|
|
59
|
+
const relativePath = path.relative(domainPath, fullPath);
|
|
60
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
61
|
+
output += `### File: ${relativePath}\n\`\`\`typescript\n${content}\n\`\`\`\n\n`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
readDirRecursive(domainPath);
|
|
67
|
+
return output;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Search for a symbol (type, constant, etc) across all domains
|
|
72
|
+
*/
|
|
73
|
+
async function searchSymbol(query: string) {
|
|
74
|
+
const domains = await listDomains();
|
|
75
|
+
let results: { domain: string; file: string; match: string }[] = [];
|
|
76
|
+
|
|
77
|
+
for (const domain of domains) {
|
|
78
|
+
const domainPath = path.join(DOMAINS_DIR, domain);
|
|
79
|
+
|
|
80
|
+
function searchInDir(dir: string) {
|
|
81
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const fullPath = path.join(dir, entry.name);
|
|
84
|
+
if (entry.isDirectory()) {
|
|
85
|
+
searchInDir(fullPath);
|
|
86
|
+
} else if (entry.isFile() && (entry.name.endsWith(".ts"))) {
|
|
87
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
88
|
+
if (content.includes(query)) {
|
|
89
|
+
const lines = content.split("\n");
|
|
90
|
+
const matchLine = lines.find(l => l.includes(query)) || "";
|
|
91
|
+
results.push({
|
|
92
|
+
domain,
|
|
93
|
+
file: path.relative(DOMAINS_DIR, fullPath),
|
|
94
|
+
match: matchLine.trim()
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
searchInDir(domainPath);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (results.length === 0) return `No results found for "${query}"`;
|
|
104
|
+
|
|
105
|
+
return results
|
|
106
|
+
.map(r => `- [${r.domain}] ${r.file}: \`${r.match}\``)
|
|
107
|
+
.join("\n");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Register tools using the high-level McpServer API (registerTool)
|
|
111
|
+
server.registerTool(
|
|
112
|
+
"list_domains",
|
|
113
|
+
{
|
|
114
|
+
description: "List all available domains in br-common-lib (e.g., kart, game, powerUp)",
|
|
115
|
+
},
|
|
116
|
+
async () => {
|
|
117
|
+
const domains = await listDomains();
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: `Available domains: ${domains.join(", ")}`,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
server.registerTool(
|
|
130
|
+
"get_domain_details",
|
|
131
|
+
{
|
|
132
|
+
description: "Get all types, schemas, and constants for a specific domain (recursive)",
|
|
133
|
+
inputSchema: z.object({
|
|
134
|
+
domain: z.string().describe("The name of the domain (e.g., 'kart')"),
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
async ({ domain }) => {
|
|
138
|
+
const details = await getDomainDetails(domain);
|
|
139
|
+
return {
|
|
140
|
+
content: [{ type: "text", text: details }],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
server.registerTool(
|
|
146
|
+
"search_symbol",
|
|
147
|
+
{
|
|
148
|
+
description: "Search for a specific type, constant or property across all domains",
|
|
149
|
+
inputSchema: z.object({
|
|
150
|
+
query: z.string().describe("The symbol or string to search for (e.g., 'hardwareState')"),
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
async ({ query }) => {
|
|
154
|
+
const results = await searchSymbol(query);
|
|
155
|
+
return {
|
|
156
|
+
content: [{ type: "text", text: results }],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// Start the server
|
|
162
|
+
async function main() {
|
|
163
|
+
const transport = new StdioServerTransport();
|
|
164
|
+
await server.connect(transport);
|
|
165
|
+
console.error("Battle Racing Common Lib MCP Server running on stdio");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
main().catch((error) => {
|
|
169
|
+
console.error("Fatal error in main():", error);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
});
|