@topline-build/harness-mcp 0.2.0 → 0.5.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 ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ All notable customer-visible Build MCP changes are recorded here. A source change is not a published package or customer release.
4
+
5
+ ## Unreleased
6
+
7
+ - Generate a versioned runtime reference and machine-readable documentation manifest from the registry used by MCP `tools/list`.
8
+ - Enforce documentation freshness in tests, continuous integration, and release validation.
9
+ - Define documentation ownership, pull request impact review, release synchronization, and recurring maintenance.
10
+ - Notify the website of an exact npm release immediately, with daily recovery and a review-only pull request boundary.
11
+ - Add machine-readable Codex, Claude Code, and Cursor certification with distinct CLI, protocol, client-mediated read, structured failure, and reviewed apply evidence.
12
+
13
+ ## 0.5.0
14
+
15
+ - Add local artifact initialization and package inspection.
16
+ - Add workspace and draft discovery, durable deployment progress, trusted smoke validation, and plan-bound draft cleanup.
17
+ - Add strict tool schemas, safety annotations, structured recovery guidance, OAuth hardening, and package-boundary protections.
package/README.md CHANGED
@@ -1,75 +1,102 @@
1
1
  # Topline Build MCP
2
2
 
3
- Local stdio MCP connector for deploying Topline artifact app drafts from Codex,
4
- Claude Code, or another local MCP host.
3
+ Local stdio MCP connector for creating, inspecting, and deploying private Topline artifact app drafts from Codex, Claude Code, or another MCP host.
5
4
 
6
- The normal auth path is OAuth with browser approval. The helper stores OAuth
7
- refresh tokens in the user's local Topline config directory, outside the project
8
- repo.
5
+ The canonical customer guide is [Topline Build MCP documentation](https://topline.build/docs/build-mcp-guide). The package also ships a generated [runtime reference](docs/generated/build-mcp-reference.md) and [machine-readable manifest](docs/generated/build-mcp-manifest.json) for the exact package version.
9
6
 
10
- Required environment:
7
+ ## Quick start
11
8
 
12
- - `TOPLINE_API_URL` or `--url https://your-topline-host`
13
-
14
- Optional environment:
15
-
16
- - `TOPLINE_MCP_SURFACE` (`build` by default; `harness` for legacy compatibility)
17
- - `TOPLINE_MCP_PROTOCOL_VERSION`
18
- - `TOPLINE_WORKSPACE_ROOT`
19
- - `TOPLINE_MCP_AUTH_FILE`
20
- - `TOPLINE_MCP_SCOPES`
21
- - `TOPLINE_MCP_TIMEOUT_MS`
22
- - `TOPLINE_MCP_TOKEN` for advanced manual-token fallback
23
-
24
- Compatibility aliases are still accepted for older local setups:
9
+ ```bash
10
+ npx -y @topline-build/harness-mcp --url https://YOUR-TOPLINE-HOST
11
+ ```
25
12
 
26
- - `PLATFORM_API_URL`
27
- - `PLATFORM_MCP_TOKEN`
28
- - `PLATFORM_WORKSPACE_ROOT`
29
- - `PLATFORM_MCP_PROTOCOL_VERSION`
13
+ The first authenticated tool call normally opens Topline in a browser for OAuth approval. Refresh credentials are cached in the user's local Topline config directory, outside the project repository. Developer Access in Topline provides ready-to-use Codex and Claude Code configuration snippets without embedding a raw token.
30
14
 
31
- ## Usage
15
+ Set `TOPLINE_WORKSPACE_ROOT` when the MCP host starts outside the repository containing the artifact app:
32
16
 
33
17
  ```bash
18
+ TOPLINE_API_URL=https://YOUR-TOPLINE-HOST \
19
+ TOPLINE_WORKSPACE_ROOT=/path/to/workspace \
34
20
  npx -y @topline-build/harness-mcp
35
21
  ```
36
22
 
37
- For local checks:
23
+ Run `npx -y @topline-build/harness-mcp --help` for every supported flag and environment variable. `TOPLINE_MCP_TOKEN` is an advanced manual-token fallback; browser-approved OAuth is preferred.
38
24
 
39
- ```bash
40
- npx -y @topline-build/harness-mcp --help
41
- npx -y @topline-build/harness-mcp --url https://hawx.topline.build
42
- ```
25
+ ## Typical workflow
43
26
 
44
- Set `TOPLINE_WORKSPACE_ROOT` when your MCP host starts outside the repo that
45
- contains the artifact app.
27
+ 1. Use `platform_init_artifact_app` to create a starter, or point at an existing artifact app.
28
+ 2. Use `platform_inspect_artifact_app` to check local package boundaries and record its bundle SHA-256.
29
+ 3. Use `platform_deploy_artifact_app` with that SHA-256 to create or update a private draft.
30
+ 4. Use `platform_wait_artifact_deploy`, `platform_run_artifact_smoke`, and `platform_validate_artifact` for durable deployment and render evidence.
31
+ 5. Use the plan-then-delete tools for reviewed cleanup.
46
32
 
47
- Topline Developer Access provides Build MCP snippets for Codex and Claude Code.
48
- Those snippets contain no raw token; the first tool call opens a browser
49
- approval flow scoped to artifact building.
33
+ The generated reference is authoritative for tool names, input/output schemas, safety annotations, configuration, structured errors, and recovery guidance. Runtime `tools/list` and the reference are generated from the same registry.
50
34
 
51
- ## Storybook
35
+ ## Maintainers
52
36
 
53
- Use the `platform_storybook_access` tool to get the tenant Storybook preview URL
54
- and the HTTP MCP client config. For clients with HTTP MCP OAuth support, use
55
- the returned `cursorMcpJson`:
37
+ See [Documentation maintenance](docs/DOCUMENTATION_MAINTENANCE.md) before changing tools, flags, authentication, errors, packaging, or releases. Validate with:
56
38
 
57
- ```json
58
- {
59
- "mcpServers": {
60
- "storybook": {
61
- "url": "https://your-topline-host/api/design-systems/storybook/mcp",
62
- "type": "http"
63
- }
64
- }
65
- }
39
+ ```bash
40
+ npm ci
41
+ npm run docs:check
42
+ npm run typecheck
43
+ npm test
44
+ npm run build
45
+ npm pack --dry-run
66
46
  ```
67
47
 
68
- Storybook MCP access uses the harness bearer/OAuth credentials with
69
- `harness:artifact:read`; OAuth discovery is available at
70
- `/.well-known/oauth-protected-resource/mcp/build`.
48
+ Client certification has two explicit phases and writes a machine-readable JSON
49
+ report. First run the read-only plan:
50
+
51
+ ```bash
52
+ TOPLINE_API_URL=https://YOUR-TOPLINE-HOST \
53
+ TOPLINE_WORKSPACE_ROOT=/path/to/workspace \
54
+ TOPLINE_CERTIFICATION_APP_DIR=artifact-apps/example \
55
+ npm run certify:clients -- --agent-mediated --output certification-plan.json
56
+ ```
57
+
58
+ Review the reported bundle SHA-256. An authorized operator can then supply a
59
+ short-lived manual token and apply that exact reviewed bundle:
60
+
61
+ ```bash
62
+ TOPLINE_MCP_TOKEN=... npm run certify:clients -- \
63
+ --phase apply \
64
+ --expected-bundle-sha256 <reviewed-sha256> \
65
+ --require-all \
66
+ --output certification-apply.json
67
+ ```
71
68
 
72
- If your MCP client does not support HTTP MCP OAuth, use the returned
73
- `manualBearerMcpJson` template with a read-scoped `TOPLINE_MCP_TOKEN` in the
74
- client's secret mechanism. Opening the visual preview URL in a browser still
75
- requires a signed-in Topline session.
69
+ Normal customer setup should use browser-approved OAuth. The manual token is a
70
+ noninteractive certification boundary only; never put it in CLI arguments,
71
+ configuration files, reports, or logs. The report keeps actual CLI
72
+ configuration health, SDK-level `protocolToolDiscovery`, and the optional
73
+ provider-backed `clientMediatedRead` as separate evidence. `--agent-mediated`
74
+ can consume provider model quota and runs only for clients whose CLI can reject
75
+ user/global MCP configuration and disable every built-in tool. Claude Code is
76
+ currently the supported mediated client; Codex and Cursor report
77
+ `strict_client_tool_isolation_unavailable` instead of starting an agent with
78
+ broader access. The Claude process uses strict MCP configuration, safe mode,
79
+ no built-in tools, an allowlisted environment, an isolated OAuth cache, and a
80
+ server exposing only `platform_inspect_artifact_app`. The write credential is
81
+ available only to the direct exact-SHA apply path. Missing client CLIs, provider
82
+ login, URL/app inputs, or credentials produce explicit `skipped` results and
83
+ exit successfully by default; `--require-all` exits 2 for any skip. A failed
84
+ check exits 1. Cursor may report that project MCP approval is required; approve
85
+ it through Cursor, then rerun rather than changing global state from the
86
+ script. Cleanup is separate and runs only with
87
+ `TOPLINE_CERTIFICATION_CLEANUP=1`.
88
+
89
+ CI's no-network self-test sets top-level `evidenceMode` to `simulated`; it is a
90
+ schema/control-flow gate and must never be presented as live client evidence.
91
+
92
+ A weekly and manually dispatchable GitHub canary runs one real Claude Code
93
+ read-only call against the inert `fixtures/certification-app` package. It pins
94
+ the client version, caps provider spend at USD 0.25, exposes only
95
+ `platform_inspect_artifact_app`, passes an allowlisted process environment, and
96
+ uploads the redacted JSON report for seven days. It requires the dedicated
97
+ `TOPLINE_CERTIFICATION_ANTHROPIC_API_KEY` repository secret and fails closed
98
+ when that credential is absent. It performs no Topline API write or customer
99
+ deployment.
100
+
101
+ Local validation and certification do not publish npm, deploy Topline, merge a
102
+ documentation pull request, or release to customers.
package/dist/index.d.ts CHANGED
@@ -29,17 +29,35 @@ export interface PackedArtifactAppBundle {
29
29
  sha256: string;
30
30
  excluded: string[];
31
31
  }
32
- export declare const HARNESS_MCP_VERSION = "0.2.0";
32
+ type ToolProgressReporter = (progress: number, message: string) => void | Promise<void>;
33
+ export declare const DEFAULT_MCP_PROTOCOL_VERSION = "2025-11-25";
34
+ export declare const BUILD_MCP_SERVER_NAME = "topline-build-stdio";
35
+ export declare const HARNESS_MCP_VERSION = "0.5.0";
36
+ export declare const DEFAULT_OAUTH_SCOPES: readonly string[];
37
+ export interface BuildMcpSetupOption {
38
+ readonly flag: string;
39
+ readonly env: string;
40
+ readonly aliases?: readonly string[];
41
+ readonly required?: boolean;
42
+ readonly default?: string | number;
43
+ readonly allowed?: readonly string[];
44
+ readonly description: string;
45
+ }
46
+ export declare const BUILD_MCP_SETUP_OPTIONS: readonly BuildMcpSetupOption[];
33
47
  export declare function parseHarnessOptions(argv: string[], env?: Record<string, string | undefined>): HarnessMcpStdioOptions;
34
48
  export declare function runHarnessMcpStdioCli(): Promise<void>;
35
49
  export declare function cliInfo(argv: string[]): string | null;
36
- export declare function createHarnessMcpStdioServer(opts: HarnessMcpStdioOptions): McpServer;
37
- export declare function callHarnessTool(opts: HarnessMcpStdioOptions, name: string, args: unknown): Promise<CallToolResult>;
38
- export declare function deployArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
50
+ export declare function createHarnessMcpStdioServer(opts: HarnessMcpStdioOptions, toolAllowlist?: readonly string[]): McpServer;
51
+ export declare function callHarnessTool(opts: HarnessMcpStdioOptions, name: string, args: unknown, hooks?: {
52
+ onProgress?: ToolProgressReporter;
53
+ }): Promise<CallToolResult>;
54
+ export declare function deployArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>, onProgress?: ToolProgressReporter): Promise<{
39
55
  ok: boolean;
40
56
  artifactId: string;
41
57
  artifactVersionId: string;
42
58
  manifestId: string | null;
59
+ clientRequestId: string;
60
+ operationId: string | null;
43
61
  bundle: {
44
62
  fileCount: number;
45
63
  byteCount: number;
@@ -49,6 +67,35 @@ export declare function deployArtifactApp(opts: HarnessMcpStdioOptions, input: R
49
67
  create: unknown;
50
68
  deploy: unknown;
51
69
  }>;
70
+ export declare function inspectArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
71
+ ok: boolean;
72
+ packageReady: boolean;
73
+ serverManifestValidationRequired: boolean;
74
+ appDir: string;
75
+ platformAppDir: string;
76
+ manifest: {
77
+ id: string | null;
78
+ manifestVersion: number | null;
79
+ title: string | null;
80
+ kind: string | null;
81
+ };
82
+ bundle: {
83
+ fileCount: number;
84
+ byteCount: number;
85
+ sha256: string;
86
+ excluded: string[];
87
+ };
88
+ nextAction: string;
89
+ }>;
90
+ export declare function waitForArtifactDeploy(opts: HarnessMcpStdioOptions, input: Record<string, unknown>, onProgress?: ToolProgressReporter): Promise<Record<string, unknown>>;
91
+ export declare function initArtifactApp(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<{
92
+ ok: boolean;
93
+ appDir: string;
94
+ manifestId: string;
95
+ title: string;
96
+ files: string[];
97
+ nextAction: string;
98
+ }>;
52
99
  export declare function getArtifactStatus(opts: HarnessMcpStdioOptions, artifactId: string, limit?: number): Promise<unknown>;
53
100
  export declare function readArtifactLogs(opts: HarnessMcpStdioOptions, input: Record<string, unknown>): Promise<unknown>;
54
101
  export declare function openArtifact(opts: HarnessMcpStdioOptions, artifactId: string): Promise<{
@@ -115,8 +162,14 @@ export declare function storybookAccess(opts: HarnessMcpStdioOptions): {
115
162
  };
116
163
  export declare function packArtifactAppDirectory(appDir: string, archivePrefix?: string): Promise<PackedArtifactAppBundle>;
117
164
  export declare function listTools(): ListToolsResult;
165
+ export interface BuildMcpRecoveryGuidance {
166
+ readonly retryable: boolean;
167
+ readonly recoveryAction: string;
168
+ }
169
+ export declare const BUILD_MCP_RECOVERY_ERRORS: Readonly<Record<string, BuildMcpRecoveryGuidance>>;
118
170
  export declare function getBearerToken(opts: HarnessMcpStdioOptions): Promise<string>;
119
171
  export declare function browserOpenCommand(url: string, platform?: string): {
120
172
  command: string;
121
173
  args: string[];
122
174
  };
175
+ export {};