@topline-build/harness-mcp 0.5.2 → 0.6.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/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ All notable customer-visible Build MCP changes are recorded here. A source chang
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.6.0 - pending publication
8
+
9
+ - Add server-owned external build sessions, guarded artifact-private SQL, and full acceptance/reviewer forwarding.
10
+ - Check out exact artifact source and materialize selected assets through authenticated same-account transfers with hash, revision, archive and local-path checks.
11
+ - Bind local draft create/deploy to the existing session identity, checked-out version, inspected source hash and stable operation keys. Additional asset, secret-metadata and data-verification scopes require explicit consent.
12
+
13
+ ## 0.5.3 - pending publication
14
+
15
+ - Add tenant-scoped Storyboard state, guarded edit, and exact-draft publication tools to Build MCP.
16
+ - Check out the published Storyboard source for local Storybook iteration and submit source-only edits as a private, server-validated draft.
17
+
7
18
  ## 0.5.2 - 2026-09-26
8
19
 
9
20
  - Report rejected bearer credentials as `authorization_required`, with scoped cache-clearing and browser reconnect guidance instead of input-correction advice.
package/README.md CHANGED
@@ -24,8 +24,16 @@ Run `npx -y @topline-build/harness-mcp --help` for every supported flag and envi
24
24
 
25
25
  If a tool returns `authorization_required`, clear only that connection's OAuth cache and reconnect through browser sign-in. Replace an expired or revoked manual token if using the fallback. Inspect existing artifact/deployment progress before retrying a write; the helper does not silently replay the rejected request.
26
26
 
27
+ Storyboard authoring uses separate `storyboard:read` and `storyboard:write` OAuth scopes. Request them explicitly with `--scopes` (or `TOPLINE_MCP_SCOPES`) and reconnect so Topline can approve the expanded grant; they are not part of the default artifact scopes. `platform_get_design_system_state` shows the published commit and current draft. `platform_checkout_design_system` creates a local checkout of that published source; run `npm ci` and `npm run storybook` there to iterate, then call `platform_submit_design_system_draft` with the exact published commit and draft ID from the state read. Wait for a successful server build, inspect the private preview, and call `platform_publish_design_system` with the reviewed run and commit values. Alternatively, `platform_edit_design_system` asks Topline's guarded coding agent to edit a draft in an existing writable Storyboard conversation. A timed-out write should be recovered by reading state before another submission. The separate Storybook reference MCP endpoint does not accept source writes.
28
+
27
29
  ## Typical workflow
28
30
 
31
+ The 0.6.0 source adds session authoring; npm publication and a compatible customer API rollout are separate prerequisites. Start `platform_start_build_session` with an existing artifact's exact version or a new app manifest, a stable idempotency key and a Topline operation budget. External client model charges stay separate. For existing apps, `platform_checkout_artifact_app` writes exact saved source into a new local directory and returns its version, commit and source hash. Never reconstruct missing source from its manifest.
32
+
33
+ Keep Build and Workspace as separate same-account connections. Workspace supplies catalog, SQL and trusted calculations through `data:read`. Reusable assets, approved secret metadata, private table writes, validation and finite artifact data verification each require their separately consented Build scopes: `harness:assets:read`, `harness:secrets:metadata:read`, `harness:artifact:tables:write`, `harness:artifact:validate`, and `harness:artifact:data:verify`. The defaults remain the existing artifact scopes; request an expanded set explicitly and reconnect. Secret discovery returns approved references only, never values.
34
+
35
+ In session mode, `platform_deploy_artifact_app` requires the session ID, its exact current artifact version, a stable idempotency key, the session/checkout `inspectedSourceHash` and a fresh local `expectedBundleSha256`. The former pins the previously inspected remote source; the latter pins the local upload. Recover pending deployment and reviewer operations with their original IDs. Unknown work is never resubmitted by a status read. Add and run acceptance checks, prepare validation and request the independent review for the exact deployed revision. Approved output stays a private draft for an operator to publish.
36
+
29
37
  1. Use `platform_init_artifact_app` to create a starter, or point at an existing artifact app.
30
38
  2. Use `platform_inspect_artifact_app` to check local package boundaries and record its bundle SHA-256.
31
39
  3. Use `platform_deploy_artifact_app` with that SHA-256 to create or update a private draft.
@@ -0,0 +1,9 @@
1
+ import type { ListToolsResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
2
+ type Annotate = (name: string, policy: {
3
+ readOnly: boolean;
4
+ idempotent?: boolean;
5
+ openWorld?: boolean;
6
+ }) => ToolAnnotations;
7
+ export declare function externalBuildHelperTools(annotate: Annotate): ListToolsResult["tools"];
8
+ export declare const EXTERNAL_BUILD_FORWARD_TOOLS: Set<string>;
9
+ export {};
@@ -0,0 +1,63 @@
1
+ const id = { type: "string", format: "uuid" };
2
+ const requestKey = { type: "string", minLength: 1, maxLength: 128, pattern: "^[A-Za-z0-9._:-]+$" };
3
+ const session = { sessionId: id };
4
+ const mutation = { ...session, artifactVersionId: id, idempotencyKey: requestKey };
5
+ const deployed = { ...mutation, deploymentRecordId: id };
6
+ export function externalBuildHelperTools(annotate) {
7
+ const tool = (name, description, properties, required, readOnly = false) => ({
8
+ name, description, annotations: annotate(name, { readOnly, idempotent: true, openWorld: true }),
9
+ inputSchema: { type: "object", additionalProperties: false, properties, required },
10
+ // Recovery adds a oneOf branch for {ok:false,error:...}; successful objects
11
+ // may omit ok, but must never match that branch too.
12
+ outputSchema: { type: "object", properties: { ok: { const: true } } }
13
+ });
14
+ return [
15
+ tool("platform_capability_status", "Read the connected Build product's current available, denied, unsupported and unconfigured tool families, contract version and helper requirement. Reconnect explicitly for newly consented scopes.", {}, [], true),
16
+ tool("platform_start_build_session", "Start external authoring with a private artifact identity, current version and platform-operation budget. Launches no internal coder. Existing artifact starts require its current version; new app starts require a manifest. Optional own conversation selects exact operator-approved secret references.", {
17
+ idempotencyKey: requestKey, artifactId: id, artifactVersionId: id, manifest: { type: "object" }, projectId: id, owningConversationId: id,
18
+ budgetCents: { type: "integer", minimum: 0, maximum: 100000 }, brief: { type: "string", minLength: 3, maxLength: 4000 }
19
+ }, ["idempotencyKey", "budgetCents", "brief"]),
20
+ tool("platform_read_build_session", "Read the owned build session and original pending operations. Does not start another coder or deployment.", session, ["sessionId"], true),
21
+ tool("platform_close_build_session", "Stop new authoring and request pending-operation cancellation. Unknown effects retain their reservation; cancellation does not undo committed writes.", session, ["sessionId"]),
22
+ tool("platform_run_artifact_workspace_sql", "Run guarded private artifact SQL using the exact session namespace, version and retry key. CREATE TABLE/ADD COLUMN require documentation. Enforced non-admin writes remain denied; unknown writes are never replayed.", {
23
+ ...mutation, sql: { type: "string", minLength: 1, maxLength: 20000 }, purpose: { type: "string", minLength: 3, maxLength: 500 },
24
+ params: { type: "object", additionalProperties: true }, maxRows: { type: "integer", minimum: 1, maximum: 5000 }, documentation: { type: "object" }, columnDocumentation: { type: "object" }
25
+ }, [...Object.keys(mutation), "sql", "purpose"]),
26
+ tool("platform_checkout_artifact_app", "Download exact saved app source through the owned session, verify archive hash/version/commit and extract regular source files into a new local directory. Missing source is never reconstructed.", {
27
+ ...session, targetDir: { type: "string", minLength: 1 }
28
+ }, ["sessionId", "targetDir"]),
29
+ tool("platform_list_asset_folders", "List the session's permitted reusable asset folders.", session, ["sessionId"], true),
30
+ tool("platform_list_assets", "List permitted reusable asset metadata with bounded pagination; excluded/deleted attachments are omitted.", {
31
+ ...session, query: { type: "string", maxLength: 200 }, folderId: id, limit: { type: "integer", minimum: 1, maximum: 500 }, offset: { type: "integer", minimum: 0 }
32
+ }, ["sessionId"], true),
33
+ tool("platform_materialize_assets", "Download exactly selected approved files into a new local directory. Verify each authenticated transfer's hash and size; source and attachment budgets remain separate.", {
34
+ ...session, assetIds: { type: "array", minItems: 1, maxItems: 50, uniqueItems: true, items: id }, targetDir: { type: "string", minLength: 1 }
35
+ }, ["sessionId", "assetIds", "targetDir"]),
36
+ tool("platform_list_build_secrets", "Read only exact operator-approved binding references for this session. Values are never retrieved. Authoring detach does not prove deployed runtime revocation.", session, ["sessionId"], true),
37
+ tool("platform_add_acceptance_check", "Add a required acceptance check bound to this build session and deployed revision. A semantic control query requires separate Build data-verification consent.", {
38
+ ...mutation, description: { type: "string", minLength: 3, maxLength: 1000 }
39
+ }, [...Object.keys(mutation), "description"]),
40
+ tool("platform_run_acceptance_checks", "Run required acceptance checks for the exact current draft revision through the shared service.", mutation, Object.keys(mutation)),
41
+ tool("platform_record_acceptance_review", "Record the builder's acceptance review without impersonating the independent validator or removing required checks.", {
42
+ ...mutation, checkId: id, status: { type: "string", enum: ["passed", "failed"] }, summary: { type: "string", minLength: 3, maxLength: 2000 }
43
+ }, [...Object.keys(mutation), "checkId", "status", "summary"]),
44
+ tool("platform_prepare_artifact_validation", "Prepare validation evidence for the exact private draft revision; missing required checks block readiness.", { ...session, artifactVersionId: id, deploymentRecordId: id }, ["sessionId", "artifactVersionId", "deploymentRecordId"], true),
45
+ tool("platform_request_artifact_validation", "Request the independent reviewer for the exact deployment and bounded evidence. Returns durable operation status; unavailable infrastructure leaves operator review required, never approval.", {
46
+ ...deployed, summary: { type: "string", minLength: 3, maxLength: 4000 }, waitMs: { type: "integer", minimum: 0, maximum: 1000 },
47
+ buildOk: { type: "boolean" }, typecheckOk: { type: "boolean" }, docImpact: { type: "string", enum: ["material", "none"] },
48
+ docImpactNotes: { type: "string", minLength: 12, maxLength: 2000 }, visualReview: { type: "object", additionalProperties: true }, dataValidation: { type: "object", additionalProperties: true }
49
+ }, [...Object.keys(deployed), "summary", "docImpact", "docImpactNotes", "visualReview"]),
50
+ tool("platform_artifact_validation_status", "Read the original validation result and pending prompts without starting another reviewer or deploy. Current authorization is rechecked before evidence delivery.", {
51
+ ...session, operationId: id
52
+ }, ["sessionId", "operationId"], true),
53
+ tool("platform_answer_operator_prompt", "Answer the exact saved operator prompt on the original review operation. Appends guidance and reopens the same eligible session; cannot approve validation or widen the saved grant.", {
54
+ ...session, operationId: id, promptId: id, idempotencyKey: requestKey, message: { type: "string", minLength: 3, maxLength: 4000 }
55
+ }, ["sessionId", "operationId", "promptId", "idempotencyKey", "message"])
56
+ ];
57
+ }
58
+ export const EXTERNAL_BUILD_FORWARD_TOOLS = new Set([
59
+ "platform_capability_status",
60
+ "platform_start_build_session", "platform_read_build_session", "platform_close_build_session", "platform_run_artifact_workspace_sql",
61
+ "platform_list_asset_folders", "platform_list_assets", "platform_list_build_secrets", "platform_add_acceptance_check", "platform_run_acceptance_checks",
62
+ "platform_record_acceptance_review", "platform_prepare_artifact_validation", "platform_request_artifact_validation", "platform_artifact_validation_status", "platform_answer_operator_prompt"
63
+ ]);
package/dist/index.d.ts CHANGED
@@ -32,7 +32,7 @@ export interface PackedArtifactAppBundle {
32
32
  type ToolProgressReporter = (progress: number, message: string) => void | Promise<void>;
33
33
  export declare const DEFAULT_MCP_PROTOCOL_VERSION = "2025-11-25";
34
34
  export declare const BUILD_MCP_SERVER_NAME = "topline-build-stdio";
35
- export declare const HARNESS_MCP_VERSION = "0.5.2";
35
+ export declare const HARNESS_MCP_VERSION = "0.6.0";
36
36
  export declare const DEFAULT_OAUTH_SCOPES: readonly string[];
37
37
  export interface BuildMcpSetupOption {
38
38
  readonly flag: string;
@@ -52,11 +52,6 @@ export declare function callHarnessTool(opts: HarnessMcpStdioOptions, name: stri
52
52
  onProgress?: ToolProgressReporter;
53
53
  }): Promise<CallToolResult>;
54
54
  export declare function deployArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>, onProgress?: ToolProgressReporter): Promise<{
55
- ok: boolean;
56
- artifactId: string;
57
- artifactVersionId: string;
58
- manifestId: string | null;
59
- clientRequestId: string;
60
55
  operationId: string | null;
61
56
  bundle: {
62
57
  fileCount: number;
@@ -66,6 +61,37 @@ export declare function deployArtifactApp(opts: HarnessMcpStdioOptions, input: R
66
61
  };
67
62
  create: unknown;
68
63
  deploy: unknown;
64
+ sessionId?: string | undefined;
65
+ ok: boolean;
66
+ artifactId: string;
67
+ artifactVersionId: string;
68
+ manifestId: string | null;
69
+ clientRequestId: string;
70
+ }>;
71
+ export declare function checkoutArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
72
+ ok: boolean;
73
+ sessionId: string;
74
+ artifactId: unknown;
75
+ artifactVersionId: string;
76
+ commitSha: string;
77
+ sourceHash: string;
78
+ appDir: string;
79
+ platformAppDir: unknown;
80
+ fileCount: number;
81
+ byteCount: number;
82
+ }>;
83
+ export declare function materializeBuildAssets(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
84
+ ok: boolean;
85
+ sessionId: string;
86
+ directory: string;
87
+ byteCount: number;
88
+ files: {
89
+ id: string;
90
+ file: string;
91
+ size: number;
92
+ sha256: unknown;
93
+ mime: unknown;
94
+ }[];
69
95
  }>;
70
96
  export declare function inspectArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
71
97
  ok: boolean;
@@ -161,6 +187,7 @@ export declare function storybookAccess(opts: HarnessMcpStdioOptions): {
161
187
  operatorAction: string;
162
188
  };
163
189
  export declare function packArtifactAppDirectory(appDir: string, archivePrefix?: string): Promise<PackedArtifactAppBundle>;
190
+ export declare function packStoryboardSourceDirectory(appDir: string): Promise<PackedArtifactAppBundle>;
164
191
  export declare function listTools(): ListToolsResult;
165
192
  export interface BuildMcpRecoveryGuidance {
166
193
  readonly retryable: boolean;