Skip to content

Commit 08f1f17

Browse files
author
Jurij Skornik
committed
[improvement] Clarify Publisher async MCP semantics and canonicalize publishOptions input
Align Publisher vs Essentials tool descriptions to reduce sync/async ambiguity. Expand knowledge-asset-publish controls via publishOptions (privacy/priority/epochs/maxAttempts) without retrieval-tool behavior changes.
1 parent 431a1d3 commit 08f1f17

3 files changed

Lines changed: 106 additions & 19 deletions

File tree

packages/plugin-dkg-essentials/src/plugins/dkg-tools.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ export default defineDkgPlugin((ctx, mcp, api) => {
179179
{
180180
title: "DKG Knowledge Asset create tool",
181181
description:
182-
"A tool for creating and publishing Knowledge Assets on OriginTrail Decentralized Knowledge Graph (DKG), " +
183-
"taking either a single JSON-LD string or a single file id as input. " +
182+
"A synchronous direct-publish tool for creating and publishing Knowledge Assets on OriginTrail Decentralized Knowledge Graph (DKG). " +
183+
"Use this when you want immediate publish execution and direct UAL output. " +
184+
"Takes either a single JSON-LD string or a single file id as input. " +
184185
"Optionally, you can specify privacy as 'private' or 'public' (default: 'private').",
185186
inputSchema: {
186187
jsonld: z

packages/plugin-dkg-publisher/src/mcp/tools.ts

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ export function registerMcpTools(
2121
{
2222
title: "Publish Knowledge Asset",
2323
description:
24-
"Register a JSON-LD asset for publishing to the DKG. " +
25-
"You can provide the content directly as a JSON object, or provide a blobId to load content from a previously uploaded file. " +
26-
"Use blobId for large files. Use the MCP query tools to check status and view recent published assets.",
24+
"Register a JSON-LD asset for publishing to the DKG through the DKG Publisher plugin async queue. " +
25+
"This tool queues publishing and returns a tracking record, not an immediate final UAL result. " +
26+
"For direct synchronous publishing with immediate UAL output, use the Essentials `dkg-create` tool. " +
27+
"You can provide content directly as a JSON object, or provide a blobId to load content from a previously uploaded file.",
2728
inputSchema: {
2829
content: z
2930
.object({})
@@ -44,7 +45,15 @@ export function registerMcpTools(
4445
sourceId: z.string().optional(),
4546
})
4647
.optional(),
47-
privacy: z.enum(["private", "public"]).optional(),
48+
publishOptions: z
49+
.object({
50+
privacy: z.enum(["private", "public"]).optional(),
51+
priority: z.number().min(1).max(100).optional(),
52+
epochs: z.number().optional(),
53+
maxAttempts: z.number().optional(),
54+
})
55+
.optional()
56+
.describe("Optional async publishing controls."),
4857
},
4958
},
5059
async (input: any, req: any) => {
@@ -91,12 +100,25 @@ export function registerMcpTools(
91100
}
92101

93102
const assetService = serviceContainer.get<AssetService>("assetService");
103+
const resolvedPrivacy = input.publishOptions?.privacy ?? "private";
104+
const resolvedPriority = input.publishOptions?.priority;
105+
const resolvedEpochs = input.publishOptions?.epochs;
106+
const resolvedMaxAttempts = input.publishOptions?.maxAttempts;
94107

95108
const assetInput = {
96109
content,
97110
metadata: input.metadata,
98111
publishOptions: {
99-
privacy: input.privacy || "private",
112+
privacy: resolvedPrivacy,
113+
...(typeof resolvedPriority === "number"
114+
? { priority: resolvedPriority }
115+
: {}),
116+
...(typeof resolvedEpochs === "number"
117+
? { epochs: resolvedEpochs }
118+
: {}),
119+
...(typeof resolvedMaxAttempts === "number"
120+
? { maxAttempts: resolvedMaxAttempts }
121+
: {}),
100122
},
101123
};
102124

@@ -141,9 +163,15 @@ export function registerMcpTools(
141163
"knowledge-asset-status-by-content-id",
142164
{
143165
title: "Get Knowledge Asset Information by Content ID",
144-
description: "Check, lookup, show, or query a knowledge asset by its JSON-LD @id (URN). Use this when the user provides a URN like 'urn:test:asset:...' or asks about a specific asset ID. Returns status, UAL, transaction hash, and publishing details.",
166+
description:
167+
"Check async publishing status for a specific JSON-LD @id (URN) that was submitted through the DKG Publisher plugin queue. " +
168+
"Returns tracked Publisher status details (status, UAL if published, transaction hash, attempts, and errors).",
145169
inputSchema: {
146-
contentId: z.string().describe("The @id from the JSON-LD content (e.g., 'urn:test:asset:manual-test-1')"),
170+
contentId: z
171+
.string()
172+
.describe(
173+
"The @id from the JSON-LD content (e.g., 'urn:test:asset:manual-test-1')",
174+
),
147175
},
148176
},
149177
async (input: any, req: any) => {
@@ -189,11 +217,26 @@ export function registerMcpTools(
189217
"knowledge-asset-list-recent",
190218
{
191219
title: "List Recent Knowledge Assets",
192-
description: "Show, list, or display recent knowledge assets. Use when user asks 'show me recent assets', 'what was published', 'last X assets', 'publishes 200-500', etc. Can filter by status (published, failed, publishing, queued). Supports pagination with offset for large queries.",
220+
description:
221+
"List recent async publishing records tracked by the DKG Publisher plugin. " +
222+
"Use this for queue/history views (optionally filtered by status) with pagination support.",
193223
inputSchema: {
194-
limit: z.number().min(1).default(20).optional().describe("Number of assets to return (default: 20)"),
195-
offset: z.number().min(0).default(0).optional().describe("Number of assets to skip (for pagination, default: 0)"),
196-
status: z.enum(["published", "failed", "publishing", "queued"]).optional().describe("Filter by status (optional)"),
224+
limit: z
225+
.number()
226+
.min(1)
227+
.default(20)
228+
.optional()
229+
.describe("Number of assets to return (default: 20)"),
230+
offset: z
231+
.number()
232+
.min(0)
233+
.default(0)
234+
.optional()
235+
.describe("Number of assets to skip (for pagination, default: 0)"),
236+
status: z
237+
.enum(["published", "failed", "publishing", "queued"])
238+
.optional()
239+
.describe("Filter by status (optional)"),
197240
},
198241
},
199242
async (input: any, req: any) => {
@@ -282,11 +325,25 @@ export function registerMcpTools(
282325
"knowledge-asset-query-by-status",
283326
{
284327
title: "Find Knowledge Assets by Status",
285-
description: "Find, show, list, or query knowledge assets by publishing status. Use when user asks 'show me all published', 'failed assets', 'what's publishing', 'publishes 100-200', etc. Supports statuses: published (successfully published), failed (publishing failed), publishing (currently being published), queued (waiting to publish). Supports pagination with offset for large queries.",
328+
description:
329+
"Query async publishing records in the DKG Publisher plugin by a required status. " +
330+
"Use this for focused queue/operations views (published, failed, publishing, queued) with pagination.",
286331
inputSchema: {
287-
status: z.enum(["published", "failed", "publishing", "queued"]).describe("The status to filter by"),
288-
limit: z.number().min(1).default(20).optional().describe("Maximum number of results (default: 20)"),
289-
offset: z.number().min(0).default(0).optional().describe("Number of assets to skip (for pagination, default: 0)"),
332+
status: z
333+
.enum(["published", "failed", "publishing", "queued"])
334+
.describe("The status to filter by"),
335+
limit: z
336+
.number()
337+
.min(1)
338+
.default(20)
339+
.optional()
340+
.describe("Maximum number of results (default: 20)"),
341+
offset: z
342+
.number()
343+
.min(0)
344+
.default(0)
345+
.optional()
346+
.describe("Number of assets to skip (for pagination, default: 0)"),
290347
},
291348
},
292349
async (input: any, req: any) => {

packages/plugin-dkg-publisher/tests/dkg-publisher.spec.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,18 @@ describe("@dkg/plugin-dkg-publisher checks", () => {
8383
const publishTool = tools.find((tool) => tool.name === "knowledge-asset-publish");
8484
expect(publishTool).to.not.equal(undefined);
8585
expect(publishTool!.title).to.equal("Publish Knowledge Asset");
86-
expect(publishTool!.description).to.equal("Register a JSON-LD asset for publishing to the DKG");
86+
expect(publishTool!.description).to.include(
87+
"Register a JSON-LD asset for publishing to the DKG",
88+
);
89+
expect(publishTool!.description).to.include("async queue");
8790
expect(publishTool!.inputSchema).to.not.equal(undefined);
91+
expect((publishTool!.inputSchema as any).publishOptions).to.not.equal(
92+
undefined,
93+
);
94+
expect((publishTool!.inputSchema as any).privacy).to.equal(undefined);
95+
expect((publishTool!.inputSchema as any).priority).to.equal(undefined);
96+
expect((publishTool!.inputSchema as any).epochs).to.equal(undefined);
97+
expect((publishTool!.inputSchema as any).maxAttempts).to.equal(undefined);
8898
});
8999

90100
it("should register API routes correctly", async () => {
@@ -159,6 +169,25 @@ describe("@dkg/plugin-dkg-publisher checks", () => {
159169
});
160170

161171
describe("Data Structure Processing", () => {
172+
it("should accept optional async publish controls", async () => {
173+
const withPublishControls = createTestAsset({
174+
publishOptions: {
175+
privacy: "public",
176+
priority: 25,
177+
epochs: 4,
178+
maxAttempts: 5,
179+
},
180+
});
181+
182+
const result = await mockMcpClient.callTool({
183+
name: "knowledge-asset-publish",
184+
arguments: withPublishControls,
185+
});
186+
187+
expect(result.content).to.be.an("array");
188+
expect(result.content).to.have.length.greaterThan(0);
189+
});
190+
162191
it("should process different content types correctly", async () => {
163192
const stringContent = createTestAsset({
164193
content: {
@@ -362,4 +391,4 @@ describe("@dkg/plugin-dkg-publisher checks", () => {
362391
}
363392
});
364393
});
365-
});
394+
});

0 commit comments

Comments
 (0)