fix: mcp
This commit is contained in:
+262
-183
@@ -194,14 +194,16 @@ const boardOptionsSchema = issueOptionsSchema.extend({
|
|||||||
.optional(),
|
.optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const stockOrderBaseSchema = z.object({
|
const stockOrderBaseSchema = z
|
||||||
issueCode: issueCodeSchema,
|
.object({
|
||||||
market: marketCodeSchema,
|
issueCode: issueCodeSchema,
|
||||||
side: tradeSideSchema,
|
market: marketCodeSchema,
|
||||||
accountType: accountTypeSchema.optional(),
|
side: tradeSideSchema,
|
||||||
quantity: z.number().positive().describe('Order quantity'),
|
accountType: accountTypeSchema.optional(),
|
||||||
depositType: depositTypeSchema.optional(),
|
quantity: z.number().positive().describe('Order quantity'),
|
||||||
})
|
depositType: depositTypeSchema.optional(),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const cashOrderPriceConditionSchema = z.enum([
|
const cashOrderPriceConditionSchema = z.enum([
|
||||||
'limit',
|
'limit',
|
||||||
@@ -218,9 +220,14 @@ const cashOrderPriceConditionSchema = z.enum([
|
|||||||
const cashOrderSchema = stockOrderBaseSchema.extend({
|
const cashOrderSchema = stockOrderBaseSchema.extend({
|
||||||
preOrderMarket: marketCodeSchema
|
preOrderMarket: marketCodeSchema
|
||||||
.optional()
|
.optional()
|
||||||
.describe('APK pre-order market for S-kabu; live S-kabu orders still send STK'),
|
.describe(
|
||||||
|
'Original listed market for S-kabu checks, such as XTKS. For S-kabu live orders set kind: "s", market: "STK", and preOrderMarket to the listed market.',
|
||||||
|
),
|
||||||
price: z.number().positive().optional().describe('Order price for price-based orders'),
|
price: z.number().positive().optional().describe('Order price for price-based orders'),
|
||||||
kind: z.enum(['market', 'limit', 'stop', 'oco', 'ifd', 'ifdo', 's', 'unknown']).optional(),
|
kind: z
|
||||||
|
.enum(['market', 'limit', 'stop', 'oco', 'ifd', 'ifdo', 's', 'unknown'])
|
||||||
|
.optional()
|
||||||
|
.describe('Use "s" for S-kabu fractional-share cash orders. Do not use sStock.'),
|
||||||
priceCondition: cashOrderPriceConditionSchema
|
priceCondition: cashOrderPriceConditionSchema
|
||||||
.optional()
|
.optional()
|
||||||
.describe('APK/MTS execution condition for cash orders'),
|
.describe('APK/MTS execution condition for cash orders'),
|
||||||
@@ -245,31 +252,42 @@ const cashOrderSchema = stockOrderBaseSchema.extend({
|
|||||||
.describe('Previous market code sent with SOR orders; defaults to login profile'),
|
.describe('Previous market code sent with SOR orders; defaults to login profile'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const cashOrderPreOrderSchema = z.object({
|
const cashOrderPreOrderSchema = z
|
||||||
issueCode: issueCodeSchema,
|
.object({
|
||||||
market: marketCodeSchema,
|
issueCode: issueCodeSchema,
|
||||||
side: tradeSideSchema,
|
market: marketCodeSchema,
|
||||||
accountType: accountTypeSchema.optional(),
|
side: tradeSideSchema,
|
||||||
depositType: depositTypeSchema.optional(),
|
accountType: accountTypeSchema.optional(),
|
||||||
kind: z.enum(['s']).optional().describe('Requests APK S-kabu pre-order constraints'),
|
depositType: depositTypeSchema.optional(),
|
||||||
preOrderMarket: marketCodeSchema.optional().describe('APK pre-order market for S-kabu checks'),
|
kind: z
|
||||||
})
|
.enum(['s'])
|
||||||
|
.optional()
|
||||||
|
.describe('Set to "s" to request APK S-kabu pre-order constraints. Do not use sStock.'),
|
||||||
|
preOrderMarket: marketCodeSchema
|
||||||
|
.optional()
|
||||||
|
.describe('Original listed market for S-kabu preflight, such as XTKS.'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const stockOrderMarginPositionSchema = z.object({
|
const stockOrderMarginPositionSchema = z
|
||||||
openTradeDate: z
|
.object({
|
||||||
.string()
|
openTradeDate: z
|
||||||
.describe('Open trade date from the margin position record, in yyyyMMdd or yyyy-MM-dd format'),
|
.string()
|
||||||
openPrice: z
|
.describe(
|
||||||
.union([z.number().positive(), z.string().min(1)])
|
'Open trade date from the margin position record, in yyyyMMdd or yyyy-MM-dd format',
|
||||||
.describe('Open price from the margin position record'),
|
),
|
||||||
quantity: z
|
openPrice: z
|
||||||
.union([z.number().positive(), z.string().min(1)])
|
.union([z.number().positive(), z.string().min(1)])
|
||||||
.describe('Selected quantity from the margin position record'),
|
.describe('Open price from the margin position record'),
|
||||||
orgNewTradeDate: z.string().describe('Original new-trade date from the margin position record'),
|
quantity: z
|
||||||
bargainMarketCode: marketCodeSchema.describe(
|
.union([z.number().positive(), z.string().min(1)])
|
||||||
'Bargain market code from the margin position record',
|
.describe('Selected quantity from the margin position record'),
|
||||||
),
|
orgNewTradeDate: z.string().describe('Original new-trade date from the margin position record'),
|
||||||
})
|
bargainMarketCode: marketCodeSchema.describe(
|
||||||
|
'Bargain market code from the margin position record',
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const placeCashOrderSchema = cashOrderSchema.extend({
|
const placeCashOrderSchema = cashOrderSchema.extend({
|
||||||
confirmationId: z
|
confirmationId: z
|
||||||
@@ -283,48 +301,50 @@ const placeCashOrderSchema = cashOrderSchema.extend({
|
|||||||
allowTrading: z.literal(true).optional().describe('Explicitly allows sending a live order'),
|
allowTrading: z.literal(true).optional().describe('Explicitly allows sending a live order'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const orderCorrectionSchema = z.object({
|
const orderCorrectionSchema = z
|
||||||
orderNumber: z
|
.object({
|
||||||
.string()
|
orderNumber: z
|
||||||
.min(1)
|
.string()
|
||||||
.optional()
|
.min(1)
|
||||||
.describe('Order number shown in order inquiry; required by the mobile pre-correction route'),
|
.optional()
|
||||||
orderId: orderIdSchema,
|
.describe('Order number shown in order inquiry; required by the mobile pre-correction route'),
|
||||||
issueCode: issueCodeSchema.optional().describe('Issue code from the pre-correction response'),
|
orderId: orderIdSchema,
|
||||||
market: marketCodeSchema.optional().describe('Market code from the pre-correction response'),
|
issueCode: issueCodeSchema.optional().describe('Issue code from the pre-correction response'),
|
||||||
tradeId: z.string().min(1).optional().describe('Original trade id code'),
|
market: marketCodeSchema.optional().describe('Market code from the pre-correction response'),
|
||||||
correctionType: z.string().min(1).optional().describe('Additional correction flag'),
|
tradeId: z.string().min(1).optional().describe('Original trade id code'),
|
||||||
status: z.string().min(1).optional().describe('Original order status code'),
|
correctionType: z.string().min(1).optional().describe('Additional correction flag'),
|
||||||
rbeOrderStatus: z.string().min(1).optional().describe('Original RBE order status code'),
|
status: z.string().min(1).optional().describe('Original order status code'),
|
||||||
depositTypeText: z.string().min(1).optional().describe('Display deposit type text'),
|
rbeOrderStatus: z.string().min(1).optional().describe('Original RBE order status code'),
|
||||||
orderMethod: z.enum(['normal', 'stop', 'oco']).optional().describe('Primary order method'),
|
depositTypeText: z.string().min(1).optional().describe('Display deposit type text'),
|
||||||
priceCondition: cashOrderPriceConditionSchema
|
orderMethod: z.enum(['normal', 'stop', 'oco']).optional().describe('Primary order method'),
|
||||||
.optional()
|
priceCondition: cashOrderPriceConditionSchema
|
||||||
.describe('Corrected primary execution condition'),
|
.optional()
|
||||||
triggerZone: z.enum(['above', 'below']).optional().describe('Stop trigger direction'),
|
.describe('Corrected primary execution condition'),
|
||||||
triggerPrice: z.number().positive().optional().describe('Stop trigger price'),
|
triggerZone: z.enum(['above', 'below']).optional().describe('Stop trigger direction'),
|
||||||
secondaryPriceCondition: cashOrderPriceConditionSchema
|
triggerPrice: z.number().positive().optional().describe('Stop trigger price'),
|
||||||
.optional()
|
secondaryPriceCondition: cashOrderPriceConditionSchema
|
||||||
.describe('Secondary/OCO execution condition'),
|
.optional()
|
||||||
secondaryPrice: z.number().positive().optional().describe('Secondary/OCO price'),
|
.describe('Secondary/OCO execution condition'),
|
||||||
ifdPriceCondition: cashOrderPriceConditionSchema
|
secondaryPrice: z.number().positive().optional().describe('Secondary/OCO price'),
|
||||||
.optional()
|
ifdPriceCondition: cashOrderPriceConditionSchema
|
||||||
.describe('IFD follow-up execution condition for IF/IFDOCO correction'),
|
.optional()
|
||||||
ifdPrice: z.number().positive().optional().describe('IFD follow-up price'),
|
.describe('IFD follow-up execution condition for IF/IFDOCO correction'),
|
||||||
ifdOrderMethod: z
|
ifdPrice: z.number().positive().optional().describe('IFD follow-up price'),
|
||||||
.enum(['normal', 'stop', 'oco'])
|
ifdOrderMethod: z
|
||||||
.optional()
|
.enum(['normal', 'stop', 'oco'])
|
||||||
.describe('IFD follow-up special order method'),
|
.optional()
|
||||||
ifdTriggerZone: z.enum(['above', 'below']).optional().describe('IFD stop trigger direction'),
|
.describe('IFD follow-up special order method'),
|
||||||
ifdTriggerPrice: z.number().positive().optional().describe('IFD stop trigger price'),
|
ifdTriggerZone: z.enum(['above', 'below']).optional().describe('IFD stop trigger direction'),
|
||||||
ifdSecondaryPriceCondition: cashOrderPriceConditionSchema
|
ifdTriggerPrice: z.number().positive().optional().describe('IFD stop trigger price'),
|
||||||
.optional()
|
ifdSecondaryPriceCondition: cashOrderPriceConditionSchema
|
||||||
.describe('IFD secondary/OCO execution condition'),
|
.optional()
|
||||||
ifdSecondaryPrice: z.number().positive().optional().describe('IFD secondary/OCO price'),
|
.describe('IFD secondary/OCO execution condition'),
|
||||||
correctionControlFlag: z.enum(['1', '2']).optional().describe('Mobile correction control flag'),
|
ifdSecondaryPrice: z.number().positive().optional().describe('IFD secondary/OCO price'),
|
||||||
quantity: z.number().positive().optional().describe('Corrected order quantity'),
|
correctionControlFlag: z.enum(['1', '2']).optional().describe('Mobile correction control flag'),
|
||||||
price: z.number().positive().optional().describe('Corrected order price'),
|
quantity: z.number().positive().optional().describe('Corrected order quantity'),
|
||||||
})
|
price: z.number().positive().optional().describe('Corrected order price'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const placeOrderCorrectionSchema = orderCorrectionSchema.extend({
|
const placeOrderCorrectionSchema = orderCorrectionSchema.extend({
|
||||||
allowTrading: z
|
allowTrading: z
|
||||||
@@ -333,14 +353,16 @@ const placeOrderCorrectionSchema = orderCorrectionSchema.extend({
|
|||||||
.describe('Explicitly allows sending a live correction request'),
|
.describe('Explicitly allows sending a live correction request'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const orderCancelSchema = z.object({
|
const orderCancelSchema = z
|
||||||
orderNumber: z.string().min(1).describe('Order number shown in order inquiry'),
|
.object({
|
||||||
orderId: orderIdSchema.optional().describe('Original order id shown in order inquiry'),
|
orderNumber: z.string().min(1).describe('Order number shown in order inquiry'),
|
||||||
issueCode: issueCodeSchema.optional().describe('Original issue code shown in order inquiry'),
|
orderId: orderIdSchema.optional().describe('Original order id shown in order inquiry'),
|
||||||
market: marketCodeSchema.optional().describe('Original market code shown in order inquiry'),
|
issueCode: issueCodeSchema.optional().describe('Original issue code shown in order inquiry'),
|
||||||
tradeId: z.string().min(1).optional().describe('Original trade id code'),
|
market: marketCodeSchema.optional().describe('Original market code shown in order inquiry'),
|
||||||
cancelType: z.string().min(1).optional().describe('Additional cancel flag'),
|
tradeId: z.string().min(1).optional().describe('Original trade id code'),
|
||||||
})
|
cancelType: z.string().min(1).optional().describe('Additional cancel flag'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const placeOrderCancelSchema = orderCancelSchema.extend({
|
const placeOrderCancelSchema = orderCancelSchema.extend({
|
||||||
tradePassword: z.string().optional().describe('Trading password used by SBI'),
|
tradePassword: z.string().optional().describe('Trading password used by SBI'),
|
||||||
@@ -423,24 +445,26 @@ const placeMarginCloseOrderSchema = marginCloseOrderSchema.extend({
|
|||||||
.describe('Explicitly allows sending a live margin close order'),
|
.describe('Explicitly allows sending a live margin close order'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const actualDeliveryOrderSchema = z.object({
|
const actualDeliveryOrderSchema = z
|
||||||
issueCode: issueCodeSchema,
|
.object({
|
||||||
market: marketCodeSchema,
|
issueCode: issueCodeSchema,
|
||||||
accountType: accountTypeSchema.optional(),
|
market: marketCodeSchema,
|
||||||
quantity: z.number().positive().describe('Order quantity'),
|
accountType: accountTypeSchema.optional(),
|
||||||
depositType: depositTypeSchema.optional(),
|
quantity: z.number().positive().describe('Order quantity'),
|
||||||
price: z.number().positive().optional().describe('Order price for price-based requests'),
|
depositType: depositTypeSchema.optional(),
|
||||||
kind: z.enum(['genbiki', 'genwatashi']),
|
price: z.number().positive().optional().describe('Order price for price-based requests'),
|
||||||
positionId: positionIdSchema.optional().describe('Position ID to deliver'),
|
kind: z.enum(['genbiki', 'genwatashi']),
|
||||||
marginPositions: z
|
positionId: positionIdSchema.optional().describe('Position ID to deliver'),
|
||||||
.array(stockOrderMarginPositionSchema)
|
marginPositions: z
|
||||||
.optional()
|
.array(stockOrderMarginPositionSchema)
|
||||||
.describe('Margin position records selected for genbiki/genwatashi delivery'),
|
.optional()
|
||||||
ippanMarginPaymentLimit: z
|
.describe('Margin position records selected for genbiki/genwatashi delivery'),
|
||||||
.string()
|
ippanMarginPaymentLimit: z
|
||||||
.optional()
|
.string()
|
||||||
.describe('APK ippan margin payment-limit code from board/pre-order information'),
|
.optional()
|
||||||
})
|
.describe('APK ippan margin payment-limit code from board/pre-order information'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const actualDeliveryOrderPreOrderSchema = actualDeliveryOrderSchema.omit({
|
const actualDeliveryOrderPreOrderSchema = actualDeliveryOrderSchema.omit({
|
||||||
quantity: true,
|
quantity: true,
|
||||||
@@ -517,50 +541,58 @@ const placeIfdOrderSchema = ifdOrderSchema.extend({
|
|||||||
allowTrading: z.literal(true).optional().describe('Explicitly allows sending a live IFD order'),
|
allowTrading: z.literal(true).optional().describe('Explicitly allows sending a live IFD order'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const themeInvestmentOrderSchema = z.object({
|
const themeInvestmentOrderSchema = z
|
||||||
themeId: z.string().min(1).describe('Theme ID for the theme investment order'),
|
.object({
|
||||||
themeSetYyyymm: z
|
themeId: z.string().min(1).describe('Theme ID for the theme investment order'),
|
||||||
.string()
|
themeSetYyyymm: z
|
||||||
.length(6)
|
.string()
|
||||||
.describe('Theme set year/month (`theme_set_yyyymm`) from the mobile APK handoff'),
|
.length(6)
|
||||||
themeCourse: z
|
.describe('Theme set year/month (`theme_set_yyyymm`) from the mobile APK handoff'),
|
||||||
.union([z.number().int().nonnegative(), z.string().min(1).max(2)])
|
themeCourse: z
|
||||||
.describe('Theme course (`theme_course`) from the mobile APK handoff'),
|
.union([z.number().int().nonnegative(), z.string().min(1).max(2)])
|
||||||
side: tradeSideSchema,
|
.describe('Theme course (`theme_course`) from the mobile APK handoff'),
|
||||||
accountType: accountTypeSchema.optional().describe('Account/deposit type used for the order'),
|
side: tradeSideSchema,
|
||||||
depositType: accountTypeSchema.optional().describe('Deposit type used for the order'),
|
accountType: accountTypeSchema.optional().describe('Account/deposit type used for the order'),
|
||||||
components: z
|
depositType: accountTypeSchema.optional().describe('Deposit type used for the order'),
|
||||||
.array(
|
components: z
|
||||||
z.object({
|
.array(
|
||||||
issueCode: issueCodeSchema,
|
z.object({
|
||||||
quantity: z.union([z.number().positive(), z.string().min(1)]),
|
issueCode: issueCodeSchema,
|
||||||
}),
|
quantity: z.union([z.number().positive(), z.string().min(1)]),
|
||||||
)
|
}),
|
||||||
.min(1)
|
)
|
||||||
.max(10)
|
.min(1)
|
||||||
.describe('Component stock orders selected by the mobile theme investment flow'),
|
.max(10)
|
||||||
amount: z.number().positive().optional().describe('Order amount for the theme investment order'),
|
.describe('Component stock orders selected by the mobile theme investment flow'),
|
||||||
})
|
amount: z
|
||||||
|
.number()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe('Order amount for the theme investment order'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const themeInvestmentPreOrderSchema = z.object({
|
const themeInvestmentPreOrderSchema = z
|
||||||
themeId: z.string().min(1).describe('Theme ID from the mobile theme investment handoff'),
|
.object({
|
||||||
themeName: z
|
themeId: z.string().min(1).describe('Theme ID from the mobile theme investment handoff'),
|
||||||
.string()
|
themeName: z
|
||||||
.min(1)
|
.string()
|
||||||
.optional()
|
.min(1)
|
||||||
.describe('Theme name from the mobile theme investment handoff'),
|
.optional()
|
||||||
exchangeCode: marketCodeSchema.describe('Exchange code used by the mobile pre-order call'),
|
.describe('Theme name from the mobile theme investment handoff'),
|
||||||
components: z
|
exchangeCode: marketCodeSchema.describe('Exchange code used by the mobile pre-order call'),
|
||||||
.array(
|
components: z
|
||||||
z.object({
|
.array(
|
||||||
issueCode: issueCodeSchema,
|
z.object({
|
||||||
quantity: z.union([z.number().positive(), z.string().min(1)]).optional(),
|
issueCode: issueCodeSchema,
|
||||||
}),
|
quantity: z.union([z.number().positive(), z.string().min(1)]).optional(),
|
||||||
)
|
}),
|
||||||
.min(1)
|
)
|
||||||
.max(10)
|
.min(1)
|
||||||
.describe('Component stocks selected by the mobile theme investment flow'),
|
.max(10)
|
||||||
})
|
.describe('Component stocks selected by the mobile theme investment flow'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const placeThemeInvestmentOrderSchema = themeInvestmentOrderSchema.extend({
|
const placeThemeInvestmentOrderSchema = themeInvestmentOrderSchema.extend({
|
||||||
allowTrading: z
|
allowTrading: z
|
||||||
@@ -569,22 +601,24 @@ const placeThemeInvestmentOrderSchema = themeInvestmentOrderSchema.extend({
|
|||||||
.describe('Explicitly allows sending a live theme investment order'),
|
.describe('Explicitly allows sending a live theme investment order'),
|
||||||
})
|
})
|
||||||
|
|
||||||
const exchangeOrderSchema = z.object({
|
const exchangeOrderSchema = z
|
||||||
currencyCode: z.string().min(1).describe('Currency code, such as USD'),
|
.object({
|
||||||
side: z.enum(['buy', 'sell']).describe('Buy or sell the foreign currency'),
|
currencyCode: z.string().min(1).describe('Currency code, such as USD'),
|
||||||
tradeQuantity: z.union([z.number().positive(), z.string().min(1)]).describe('Order quantity'),
|
side: z.enum(['buy', 'sell']).describe('Buy or sell the foreign currency'),
|
||||||
specificMethod: z
|
tradeQuantity: z.union([z.number().positive(), z.string().min(1)]).describe('Order quantity'),
|
||||||
.enum(['foreign', 'domestic'])
|
specificMethod: z
|
||||||
.optional()
|
.enum(['foreign', 'domestic'])
|
||||||
.describe('foreign for foreign-currency quantity, domestic for yen amount'),
|
.optional()
|
||||||
accountKind: z.enum(['GENERAL', 'JR_NISA']).optional().describe('SBI exchange account kind'),
|
.describe('foreign for foreign-currency quantity, domestic for yen amount'),
|
||||||
sellMethod: z.enum(['SELL_PART', 'SELL_ALL']).optional().describe('Required for sell orders'),
|
accountKind: z.enum(['GENERAL', 'JR_NISA']).optional().describe('SBI exchange account kind'),
|
||||||
orderAmount: z
|
sellMethod: z.enum(['SELL_PART', 'SELL_ALL']).optional().describe('Required for sell orders'),
|
||||||
.union([z.number().positive(), z.string().min(1)])
|
orderAmount: z
|
||||||
.optional()
|
.union([z.number().positive(), z.string().min(1)])
|
||||||
.describe('Hidden order amount posted to SBI; required for domestic orders'),
|
.optional()
|
||||||
tradePassword: z.string().optional().describe('Trading password used by SBI'),
|
.describe('Hidden order amount posted to SBI; required for domestic orders'),
|
||||||
})
|
tradePassword: z.string().optional().describe('Trading password used by SBI'),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
const exchangeRateSchema = exchangeOrderSchema.pick({
|
const exchangeRateSchema = exchangeOrderSchema.pick({
|
||||||
currencyCode: true,
|
currencyCode: true,
|
||||||
@@ -732,8 +766,57 @@ const getActions = Object.keys(getActionToMethod) as Array<keyof typeof getActio
|
|||||||
const changeActions = Object.keys(changeActionToEstimateMethod) as Array<
|
const changeActions = Object.keys(changeActionToEstimateMethod) as Array<
|
||||||
keyof typeof changeActionToEstimateMethod
|
keyof typeof changeActionToEstimateMethod
|
||||||
>
|
>
|
||||||
const getActionSchema = z.enum(['capabilities', 'passkeys', ...getActions])
|
const getActionDescription = `Available actions: capabilities, passkeys, ${getActions
|
||||||
const changeActionSchema = z.enum(changeActions)
|
.map((action) => `${action}=${getActionToMethod[action]}`)
|
||||||
|
.join(
|
||||||
|
', ',
|
||||||
|
)}. S-kabu preflight uses cashOrderPreflight with input.kind: "s" and input.preOrderMarket, not sStock.`
|
||||||
|
const changeActionDescription = `Available actions: ${changeActions
|
||||||
|
.map((action) => `${action}=${changeActionToEstimateMethod[action]}`)
|
||||||
|
.join(
|
||||||
|
', ',
|
||||||
|
)}. S-kabu cash orders use cashOrder with input.kind: "s", input.market: "STK", and input.preOrderMarket set to the listed market such as XTKS; do not use sStock, orderType, or sor.`
|
||||||
|
|
||||||
|
const getToolInputSchema = z.discriminatedUnion('action', [
|
||||||
|
z.object({ action: z.literal('capabilities') }).strict(),
|
||||||
|
z.object({ action: z.literal('passkeys') }).strict(),
|
||||||
|
...getActions.map((action) => {
|
||||||
|
const method = getActionToMethod[action]
|
||||||
|
const paramsSchema = methodParamSchemas[method]
|
||||||
|
return z
|
||||||
|
.object({
|
||||||
|
action: z.literal(action),
|
||||||
|
passkeyId: z.string().describe('Saved SBI passkey id'),
|
||||||
|
...(paramsSchema ? { input: paramsSchema.describe(`${method} input`) } : {}),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
}),
|
||||||
|
] as any)
|
||||||
|
|
||||||
|
const changeToolInputSchema = z.discriminatedUnion(
|
||||||
|
'action',
|
||||||
|
changeActions.map((action) => {
|
||||||
|
const method = changeActionToEstimateMethod[action]
|
||||||
|
const paramsSchema = methodParamSchemas[method]
|
||||||
|
if (!paramsSchema) throw new Error(`${method} must have an input schema`)
|
||||||
|
return z
|
||||||
|
.object({
|
||||||
|
action: z.literal(action),
|
||||||
|
passkeyId: z.string().describe('Saved SBI passkey id'),
|
||||||
|
input: paramsSchema.describe(`${method} input`),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
}) as any,
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetToolArgs =
|
||||||
|
| { action: 'capabilities' }
|
||||||
|
| { action: 'passkeys' }
|
||||||
|
| {
|
||||||
|
action: keyof typeof getActionToMethod
|
||||||
|
passkeyId: string
|
||||||
|
input?: unknown
|
||||||
|
}
|
||||||
|
|
||||||
const parseMethodParams = (method: RpcMethod, input: unknown) => {
|
const parseMethodParams = (method: RpcMethod, input: unknown) => {
|
||||||
const schema = methodParamSchemas[method]
|
const schema = methodParamSchemas[method]
|
||||||
@@ -863,18 +946,12 @@ const createMcpServer = (c: Context<AppBindings>) => {
|
|||||||
'csbie-get',
|
'csbie-get',
|
||||||
{
|
{
|
||||||
title: 'Get SBI Data',
|
title: 'Get SBI Data',
|
||||||
description:
|
description: `Read SBI data through a small abstract action API. This tool never places, corrects, cancels, or otherwise changes real orders. ${getActionDescription}`,
|
||||||
'Read SBI data through a small abstract action API. This tool never places, corrects, cancels, or otherwise changes real orders.',
|
inputSchema: getToolInputSchema,
|
||||||
inputSchema: {
|
|
||||||
action: getActionSchema.describe('Read action to perform'),
|
|
||||||
passkeyId: z
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.describe('Saved SBI passkey id. Required for SBI-backed read actions.'),
|
|
||||||
input: z.unknown().optional().describe('Action input object'),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
async ({ action, passkeyId, input }) => {
|
async (args) => {
|
||||||
|
const parsedArgs = getToolInputSchema.parse(args) as GetToolArgs
|
||||||
|
const { action } = parsedArgs
|
||||||
requireAuthenticated(auth)
|
requireAuthenticated(auth)
|
||||||
|
|
||||||
if (action === 'capabilities') {
|
if (action === 'capabilities') {
|
||||||
@@ -890,6 +967,7 @@ const createMcpServer = (c: Context<AppBindings>) => {
|
|||||||
|
|
||||||
const method = getActionToMethod[action]
|
const method = getActionToMethod[action]
|
||||||
if (!method) throw new Error(`unsupported get action: ${String(action)}`)
|
if (!method) throw new Error(`unsupported get action: ${String(action)}`)
|
||||||
|
const { passkeyId, input } = parsedArgs
|
||||||
if (!passkeyId) throw new Error(`${action} requires passkeyId`)
|
if (!passkeyId) throw new Error(`${action} requires passkeyId`)
|
||||||
|
|
||||||
const params = parseMethodParams(method, input)
|
const params = parseMethodParams(method, input)
|
||||||
@@ -901,16 +979,17 @@ const createMcpServer = (c: Context<AppBindings>) => {
|
|||||||
'csbie-request-change',
|
'csbie-request-change',
|
||||||
{
|
{
|
||||||
title: 'Create SBI Change Request',
|
title: 'Create SBI Change Request',
|
||||||
description:
|
description: `Prepare a real SBI change by running the corresponding estimate/preview and returning a UUID. This tool never submits the change; pass the UUID to confirm-request. ${changeActionDescription}`,
|
||||||
'Prepare a real SBI change by running the corresponding estimate/preview and returning a UUID. This tool never submits the change; pass the UUID to confirm-request.',
|
inputSchema: changeToolInputSchema,
|
||||||
inputSchema: {
|
},
|
||||||
action: changeActionSchema.describe('Change action to prepare'),
|
async (args) => {
|
||||||
passkeyId: z.string().describe('Saved SBI passkey id'),
|
const { action, passkeyId, input } = changeToolInputSchema.parse(args) as {
|
||||||
input: z.unknown().describe('Change action input object'),
|
action: keyof typeof changeActionToEstimateMethod
|
||||||
},
|
passkeyId: string
|
||||||
|
input: unknown
|
||||||
|
}
|
||||||
|
return textResult(await createChangeRequest(action, passkeyId, input))
|
||||||
},
|
},
|
||||||
async ({ action, passkeyId, input }) =>
|
|
||||||
textResult(await createChangeRequest(action, passkeyId, input)),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
server.registerTool(
|
server.registerTool(
|
||||||
|
|||||||
Reference in New Issue
Block a user