Skip to content

Commit b885089

Browse files
committed
fix(ams): use the contract's named schema exports, not the ToolContract.input accessor
Registering with minerXTool.input.shape/output.shape compiled fine standalone but broke once each handler declared an explicit z.infer parameter type: ToolContract.input is typed as the general z.ZodObject class (the type every contract entry shares), so z.infer<typeof minerXTool.input> collapses to a generic/incorrect shape instead of the tool's real fields -- and passing that same widened .shape to registerTool's inputSchema, while the handler declares the SPECIFIC narrower type, is a real contravariant mismatch the MCP SDK's overload correctly rejected (planId missing in type ShapeOutput<...>). Every registration and handler now references the tool's own named MinerXInput/MinerXOutput export from @loopover/contract/tools instead of the ToolContract.input/.output accessor -- the schema passed to registerTool and the type the handler destructures against are now the same concrete object. build:miner and the full repo typecheck are clean; 106 tests green across miner-mcp-scaffold/contract/audit-feed/manage-status/calibration-report/ governor-decisions/tool-docs-parity and contract-registry. Refs #9536
1 parent 43bebf3 commit b885089

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

packages/loopover-miner/bin/loopover-miner-mcp.ts

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
66
// #9536: every tool's schemas come from the shared contract instead of being declared here. The
77
// remote and stdio servers already register from the same package (#9517/#9518) -- this closes the
88
// gap that made AMS the one server with no structured output and no shared source of truth.
9+
import { z } from "zod";
910
import {
1011
minerPingTool,
1112
minerPortfolioDashboardTool,
@@ -19,6 +20,30 @@ import {
1920
minerStatusTool,
2021
minerCalibrationReportTool,
2122
} from "@loopover/contract/tools";
23+
import {
24+
MinerPingInput,
25+
MinerPingOutput,
26+
MinerPortfolioDashboardInput,
27+
MinerPortfolioDashboardOutput,
28+
MinerManageStatusInput,
29+
MinerManageStatusOutput,
30+
MinerListClaimsInput,
31+
MinerListClaimsOutput,
32+
MinerAuditFeedInput,
33+
MinerAuditFeedOutput,
34+
MinerGetRunStateInput,
35+
MinerGetRunStateOutput,
36+
MinerListPlansInput,
37+
MinerListPlansOutput,
38+
MinerGetPlanInput,
39+
MinerGetPlanOutput,
40+
MinerGovernorDecisionsInput,
41+
MinerGovernorDecisionsOutput,
42+
MinerStatusInput,
43+
MinerStatusOutput,
44+
MinerCalibrationReportInput,
45+
MinerCalibrationReportOutput,
46+
} from "@loopover/contract/tools";
2247
import { openClaimLedger } from "../lib/claim-ledger.js";
2348
import { type AuditFeedMcpFilterInput, collectEventLedgerAuditFeed, normalizeAuditFeedMcpFilter } from "../lib/event-ledger-cli.js";
2449
import { initEventLedger, type EventLedger } from "../lib/event-ledger.js";
@@ -184,16 +209,16 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
184209

185210
server.registerTool(
186211
minerPingTool.name,
187-
{ description: minerPingTool.description, inputSchema: minerPingTool.input.shape, outputSchema: minerPingTool.output.shape },
212+
{ description: minerPingTool.description, inputSchema: MinerPingInput.shape, outputSchema: MinerPingOutput.shape },
188213
async () => minerToolResult(MINER_PING_STATUS),
189214
);
190215

191216
server.registerTool(
192217
minerPortfolioDashboardTool.name,
193218
{
194219
description: minerPortfolioDashboardTool.description,
195-
inputSchema: minerPortfolioDashboardTool.input.shape,
196-
outputSchema: minerPortfolioDashboardTool.output.shape,
220+
inputSchema: MinerPortfolioDashboardInput.shape,
221+
outputSchema: MinerPortfolioDashboardOutput.shape,
197222
},
198223
() =>
199224
withMinerToolErrorHandling(() => {
@@ -211,8 +236,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
211236
minerManageStatusTool.name,
212237
{
213238
description: minerManageStatusTool.description,
214-
inputSchema: minerManageStatusTool.input.shape,
215-
outputSchema: minerManageStatusTool.output.shape,
239+
inputSchema: MinerManageStatusInput.shape,
240+
outputSchema: MinerManageStatusOutput.shape,
216241
},
217242
() =>
218243
withMinerToolErrorHandling(() => {
@@ -245,8 +270,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
245270

246271
server.registerTool(
247272
minerListClaimsTool.name,
248-
{ description: minerListClaimsTool.description, inputSchema: minerListClaimsTool.input.shape, outputSchema: minerListClaimsTool.output.shape },
249-
({ repoFullName, status }) =>
273+
{ description: minerListClaimsTool.description, inputSchema: MinerListClaimsInput.shape, outputSchema: MinerListClaimsOutput.shape },
274+
({ repoFullName, status }: z.infer<typeof MinerListClaimsInput>) =>
250275
withMinerToolErrorHandling(() => {
251276
const ownsLedger = options.openClaimLedger === undefined;
252277
const ledger = (options.openClaimLedger ?? openClaimLedger)();
@@ -266,8 +291,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
266291

267292
server.registerTool(
268293
minerAuditFeedTool.name,
269-
{ description: minerAuditFeedTool.description, inputSchema: minerAuditFeedTool.input.shape, outputSchema: minerAuditFeedTool.output.shape },
270-
(input) =>
294+
{ description: minerAuditFeedTool.description, inputSchema: MinerAuditFeedInput.shape, outputSchema: MinerAuditFeedOutput.shape },
295+
(input: z.infer<typeof MinerAuditFeedInput>) =>
271296
withMinerToolErrorHandling(() => {
272297
const ownsLedger = options.initEventLedger === undefined;
273298
const eventLedger = (options.initEventLedger ?? initEventLedger)();
@@ -289,10 +314,10 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
289314
minerGetRunStateTool.name,
290315
{
291316
description: minerGetRunStateTool.description,
292-
inputSchema: minerGetRunStateTool.input.shape,
293-
outputSchema: minerGetRunStateTool.output.shape,
317+
inputSchema: MinerGetRunStateInput.shape,
318+
outputSchema: MinerGetRunStateOutput.shape,
294319
},
295-
({ repoFullName }) =>
320+
({ repoFullName }: z.infer<typeof MinerGetRunStateInput>) =>
296321
withMinerToolErrorHandling(() => {
297322
const ownsStore = options.initRunStateStore === undefined;
298323
const store = (options.initRunStateStore ?? initRunStateStore)();
@@ -306,8 +331,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
306331

307332
server.registerTool(
308333
minerListPlansTool.name,
309-
{ description: minerListPlansTool.description, inputSchema: minerListPlansTool.input.shape, outputSchema: minerListPlansTool.output.shape },
310-
({ status }) =>
334+
{ description: minerListPlansTool.description, inputSchema: MinerListPlansInput.shape, outputSchema: MinerListPlansOutput.shape },
335+
({ status }: z.infer<typeof MinerListPlansInput>) =>
311336
withMinerToolErrorHandling(() => {
312337
const ownsStore = options.openPlanStore === undefined;
313338
const store = (options.openPlanStore ?? openPlanStore)();
@@ -324,8 +349,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
324349

325350
server.registerTool(
326351
minerGetPlanTool.name,
327-
{ description: minerGetPlanTool.description, inputSchema: minerGetPlanTool.input.shape, outputSchema: minerGetPlanTool.output.shape },
328-
({ planId }) =>
352+
{ description: minerGetPlanTool.description, inputSchema: MinerGetPlanInput.shape, outputSchema: MinerGetPlanOutput.shape },
353+
({ planId }: z.infer<typeof MinerGetPlanInput>) =>
329354
withMinerToolErrorHandling(() => {
330355
const ownsStore = options.openPlanStore === undefined;
331356
const store = (options.openPlanStore ?? openPlanStore)();
@@ -342,10 +367,10 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
342367
minerGovernorDecisionsTool.name,
343368
{
344369
description: minerGovernorDecisionsTool.description,
345-
inputSchema: minerGovernorDecisionsTool.input.shape,
346-
outputSchema: minerGovernorDecisionsTool.output.shape,
370+
inputSchema: MinerGovernorDecisionsInput.shape,
371+
outputSchema: MinerGovernorDecisionsOutput.shape,
347372
},
348-
({ repoFullName }) =>
373+
({ repoFullName }: z.infer<typeof MinerGovernorDecisionsInput>) =>
349374
withMinerToolErrorHandling(() => {
350375
const ownsLedger = options.initGovernorLedger === undefined;
351376
const ledger = (options.initGovernorLedger ?? initGovernorLedger)();
@@ -362,7 +387,7 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
362387

363388
server.registerTool(
364389
minerStatusTool.name,
365-
{ description: minerStatusTool.description, inputSchema: minerStatusTool.input.shape, outputSchema: minerStatusTool.output.shape },
390+
{ description: minerStatusTool.description, inputSchema: MinerStatusInput.shape, outputSchema: MinerStatusOutput.shape },
366391
() =>
367392
withMinerToolErrorHandling(() => ({
368393
status: (options.collectStatus ?? collectStatus)(),
@@ -374,8 +399,8 @@ export function createMinerMcpServer(options: MinerMcpServerOptions = {}) {
374399
minerCalibrationReportTool.name,
375400
{
376401
description: minerCalibrationReportTool.description,
377-
inputSchema: minerCalibrationReportTool.input.shape,
378-
outputSchema: minerCalibrationReportTool.output.shape,
402+
inputSchema: MinerCalibrationReportInput.shape,
403+
outputSchema: MinerCalibrationReportOutput.shape,
379404
},
380405
() =>
381406
withMinerToolErrorHandling(() => {

0 commit comments

Comments
 (0)