@ian-pascoe/pi-mcp 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/mcp-presentation.ts +16 -15
- package/src/mcp-tool-catalog.ts +87 -3
package/package.json
CHANGED
package/src/mcp-presentation.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* oxlint-disable anti-slop/no-conditional-empty-object-spread, anti-slop/no-known-value-widening, anti-slop/no-runtime-typeof, anti-slop/no-unknown-parameters, anti-slop/no-unknown-returns, anti-slop/no-unsafe-dictionary-type -- MCP Transcript Presentation owns Pi's untyped historical result, tool-argument, and custom-message rendering boundaries. */
|
|
2
|
+
import type { JSONValue } from "@modelcontextprotocol/client";
|
|
2
3
|
import {
|
|
3
4
|
DEFAULT_MAX_BYTES,
|
|
4
5
|
DEFAULT_MAX_LINES,
|
|
@@ -32,24 +33,23 @@ const MCP_PRESENTATION_TEXT_STYLE_RESET = "\u001b[22;39m";
|
|
|
32
33
|
const MCP_PRESENTATION_METADATA_LIMIT = 20;
|
|
33
34
|
const MCP_PRESENTATION_RESERVED_BYTES = 8 * 1024;
|
|
34
35
|
const MCP_PRESENTATION_RESERVED_LINES = 64;
|
|
35
|
-
|
|
36
|
+
/** MCP result marker schema shared by persisted-result parsing and tool output metadata. */
|
|
37
|
+
export const McpResultMarkerSchema = Type.Object(
|
|
36
38
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
serverId: Type.Optional(Type.String()),
|
|
45
|
-
toolName: Type.Optional(Type.String()),
|
|
46
|
-
},
|
|
47
|
-
{ additionalProperties: true },
|
|
48
|
-
),
|
|
49
|
-
result: Type.Any(),
|
|
39
|
+
isError: Type.Boolean(),
|
|
40
|
+
operation: Type.Optional(Type.String()),
|
|
41
|
+
outputSchemaError: Type.Optional(Type.String()),
|
|
42
|
+
outputSchemaValid: Type.Optional(Type.Boolean()),
|
|
43
|
+
owner: Type.Literal(MCP_DETAILS_OWNER),
|
|
44
|
+
serverId: Type.Optional(Type.String()),
|
|
45
|
+
toolName: Type.Optional(Type.String()),
|
|
50
46
|
},
|
|
51
47
|
{ additionalProperties: true },
|
|
52
48
|
);
|
|
49
|
+
const McpResultDetailsMarkerSchema = Type.Object(
|
|
50
|
+
{ mcp: McpResultMarkerSchema, result: Type.Any() },
|
|
51
|
+
{ additionalProperties: true },
|
|
52
|
+
);
|
|
53
53
|
|
|
54
54
|
/** Theme operations used by MCP Transcript Presentation and custom-message renderers. */
|
|
55
55
|
export type McpRenderTheme = Pick<Theme, "bg" | "bold" | "fg">;
|
|
@@ -68,10 +68,11 @@ export interface McpResultMarker {
|
|
|
68
68
|
readonly toolName?: string;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
/**
|
|
71
|
+
/** MCP tool details containing host metadata, mapped result details, and optional structured output. */
|
|
72
72
|
export interface McpResultDetails {
|
|
73
73
|
readonly mcp: McpResultMarker;
|
|
74
74
|
readonly result: unknown;
|
|
75
|
+
readonly structuredContent?: JSONValue;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
/** One role-faithful Prompt message persisted for context replay and TUI presentation. */
|
package/src/mcp-tool-catalog.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
} from "@earendil-works/pi-coding-agent";
|
|
16
16
|
import type { TSchema } from "typebox";
|
|
17
17
|
import {
|
|
18
|
+
McpResultMarkerSchema,
|
|
18
19
|
parseMcpResultDetails,
|
|
19
20
|
renderMcpResourceToolCall,
|
|
20
21
|
renderMcpServerToolCall,
|
|
@@ -45,6 +46,69 @@ const ReadResourceSchema = {
|
|
|
45
46
|
additionalProperties: false,
|
|
46
47
|
} as const;
|
|
47
48
|
|
|
49
|
+
type McpOutputSchemaToolDefinition<TParameters extends TSchema = TSchema> = ToolDefinition<
|
|
50
|
+
TParameters,
|
|
51
|
+
unknown
|
|
52
|
+
> & {
|
|
53
|
+
readonly outputSchema: JsonSchemaType;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function mcpResultDetailsOutputSchema(structuredContentSchema?: JsonSchemaType): JsonSchemaType {
|
|
57
|
+
return {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
mcp: McpResultMarkerSchema,
|
|
61
|
+
result: {},
|
|
62
|
+
...(structuredContentSchema === undefined
|
|
63
|
+
? {}
|
|
64
|
+
: { structuredContent: structuredContentSchema }),
|
|
65
|
+
},
|
|
66
|
+
required: ["mcp", "result"],
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function validatedMcpResultDetailsOutputSchema(
|
|
72
|
+
structuredContentSchema: JsonSchemaType,
|
|
73
|
+
): JsonSchemaType {
|
|
74
|
+
const validationMarker = (valid: boolean): JsonSchemaType => ({
|
|
75
|
+
allOf: [
|
|
76
|
+
McpResultMarkerSchema,
|
|
77
|
+
{
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: { outputSchemaValid: { const: valid } },
|
|
80
|
+
required: ["outputSchemaValid"],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
anyOf: [
|
|
86
|
+
{
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
mcp: validationMarker(true),
|
|
90
|
+
result: {},
|
|
91
|
+
structuredContent: structuredContentSchema,
|
|
92
|
+
},
|
|
93
|
+
required: ["mcp", "result"],
|
|
94
|
+
additionalProperties: false,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
mcp: validationMarker(false),
|
|
100
|
+
result: {},
|
|
101
|
+
structuredContent: {},
|
|
102
|
+
},
|
|
103
|
+
required: ["mcp", "result"],
|
|
104
|
+
additionalProperties: false,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const RESOURCE_RESULT_DETAILS_OUTPUT_SCHEMA = mcpResultDetailsOutputSchema();
|
|
111
|
+
|
|
48
112
|
/** Minimal public Pi surface required to register and activate MCP tools. */
|
|
49
113
|
export interface McpToolCatalogPi {
|
|
50
114
|
/** Register or replace one Pi tool by name. */
|
|
@@ -298,9 +362,16 @@ export class McpToolCatalog {
|
|
|
298
362
|
this.syncActiveTools(activeNames);
|
|
299
363
|
}
|
|
300
364
|
|
|
301
|
-
private serverToolDefinition(
|
|
365
|
+
private serverToolDefinition(
|
|
366
|
+
compiled: CompiledServerTool,
|
|
367
|
+
piToolName: string,
|
|
368
|
+
): McpOutputSchemaToolDefinition {
|
|
302
369
|
// SAFETY: MCP's parsed Tool contract requires inputSchema to be JSON Schema; fromJsonSchema compiled this exact object above. Pi accepts the same structural schema without TypeBox metadata.
|
|
303
370
|
const parameters = compiled.definition.inputSchema as TSchema;
|
|
371
|
+
const outputSchema =
|
|
372
|
+
compiled.outputValidator !== undefined && compiled.definition.outputSchema !== undefined
|
|
373
|
+
? validatedMcpResultDetailsOutputSchema(compiled.definition.outputSchema)
|
|
374
|
+
: mcpResultDetailsOutputSchema({});
|
|
304
375
|
return {
|
|
305
376
|
name: piToolName,
|
|
306
377
|
label:
|
|
@@ -310,6 +381,7 @@ export class McpToolCatalog {
|
|
|
310
381
|
description:
|
|
311
382
|
compiled.definition.description ?? `Call MCP Server Tool ${compiled.definition.name}.`,
|
|
312
383
|
parameters,
|
|
384
|
+
outputSchema,
|
|
313
385
|
renderCall: (arguments_, theme, context) =>
|
|
314
386
|
renderMcpServerToolCall(
|
|
315
387
|
compiled.serverId,
|
|
@@ -378,7 +450,16 @@ export class McpToolCatalog {
|
|
|
378
450
|
? {}
|
|
379
451
|
: { serverId: compiled.serverId, toolName: compiled.definition.name }),
|
|
380
452
|
};
|
|
381
|
-
return {
|
|
453
|
+
return {
|
|
454
|
+
content,
|
|
455
|
+
details: {
|
|
456
|
+
mcp,
|
|
457
|
+
result: result.details,
|
|
458
|
+
...(result.structuredContent === undefined
|
|
459
|
+
? {}
|
|
460
|
+
: { structuredContent: result.structuredContent }),
|
|
461
|
+
},
|
|
462
|
+
};
|
|
382
463
|
}
|
|
383
464
|
|
|
384
465
|
private registerResourceTools(): void {
|
|
@@ -387,6 +468,7 @@ export class McpToolCatalog {
|
|
|
387
468
|
label: "List MCP Resources",
|
|
388
469
|
description: "List Resources advertised by connected MCP Servers.",
|
|
389
470
|
parameters: ListResourcesSchema,
|
|
471
|
+
outputSchema: RESOURCE_RESULT_DETAILS_OUTPUT_SCHEMA,
|
|
390
472
|
renderCall: (parameters, theme, context) =>
|
|
391
473
|
renderMcpResourceToolCall(
|
|
392
474
|
"list_resources",
|
|
@@ -411,6 +493,7 @@ export class McpToolCatalog {
|
|
|
411
493
|
label: "List MCP Resource Templates",
|
|
412
494
|
description: "List Resource Templates advertised by connected MCP Servers.",
|
|
413
495
|
parameters: ListResourcesSchema,
|
|
496
|
+
outputSchema: RESOURCE_RESULT_DETAILS_OUTPUT_SCHEMA,
|
|
414
497
|
renderCall: (parameters, theme, context) =>
|
|
415
498
|
renderMcpResourceToolCall(
|
|
416
499
|
"list_resource_templates",
|
|
@@ -435,6 +518,7 @@ export class McpToolCatalog {
|
|
|
435
518
|
label: "Read MCP Resource",
|
|
436
519
|
description: "Read one Resource from a connected MCP Server.",
|
|
437
520
|
parameters: ReadResourceSchema,
|
|
521
|
+
outputSchema: RESOURCE_RESULT_DETAILS_OUTPUT_SCHEMA,
|
|
438
522
|
renderCall: (parameters, theme, context) =>
|
|
439
523
|
renderMcpResourceToolCall(
|
|
440
524
|
"read_resource",
|
|
@@ -457,7 +541,7 @@ export class McpToolCatalog {
|
|
|
457
541
|
}
|
|
458
542
|
|
|
459
543
|
private registerResourceTool<TParameters extends TSchema>(
|
|
460
|
-
tool:
|
|
544
|
+
tool: McpOutputSchemaToolDefinition<TParameters>,
|
|
461
545
|
): void {
|
|
462
546
|
this.ownedToolNames.add(tool.name);
|
|
463
547
|
this.pi.registerTool(tool);
|