@topline-build/harness-mcp 0.5.1 → 0.5.3

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Generated from `src/index.ts#BUILD_MCP_TOOLS`. Do not edit this file by hand.
4
4
 
5
- Package: `@topline-build/harness-mcp@0.5.1`
5
+ Package: `@topline-build/harness-mcp@0.5.3`
6
6
  Transport: `stdio`
7
7
  Default protocol: `2025-11-25`
8
8
  Canonical guide: https://topline.build/docs/build-mcp-guide
@@ -32,6 +32,7 @@ The first authenticated tool call normally opens browser approval. Set `TOPLINE_
32
32
 
33
33
  Tool failures set `isError: true` and return `structuredContent.error` with `code`, `message`, `retryable`, and `recoveryAction`.
34
34
 
35
+ - `authorization_required` (not automatically retryable): Clear only this connection's cached OAuth credentials, then reconnect the Build MCP through browser sign-in. If using a manual bearer token, replace the expired or revoked token. Recover existing artifact/deployment progress before retrying a write.
35
36
  - `platform_harness_timeout` (retryable): Retry the call. For a deployment, use platform_list_artifact_drafts to recover the artifact and platform_wait_artifact_deploy to resume progress.
36
37
  - `platform_mcp_tool_error` (not automatically retryable): Read the returned error code, correct the request or OAuth scopes, then retry.
37
38
  - `artifact_deploy_wait_timeout` (retryable): Call platform_wait_artifact_deploy again with the same artifactId and operationId.
@@ -1604,6 +1605,591 @@ Output schema:
1604
1605
  }
1605
1606
  ```
1606
1607
 
1608
+ ### `platform_get_design_system_state`
1609
+
1610
+ Get the tenant Storyboard's published and draft commits, run status, and preview URL before editing or publishing. May reconcile a completed managed draft.
1611
+
1612
+ Safety: read-only=false, destructive=false, idempotent=false, open-world=false.
1613
+
1614
+ Example request:
1615
+
1616
+ ```json
1617
+ {}
1618
+ ```
1619
+
1620
+ Example success:
1621
+
1622
+ ```json
1623
+ {}
1624
+ ```
1625
+
1626
+ Input schema:
1627
+
1628
+ ```json
1629
+ {
1630
+ "type": "object",
1631
+ "properties": {},
1632
+ "additionalProperties": false
1633
+ }
1634
+ ```
1635
+
1636
+ Output schema:
1637
+
1638
+ ```json
1639
+ {
1640
+ "type": "object",
1641
+ "oneOf": [
1642
+ {
1643
+ "type": "object"
1644
+ },
1645
+ {
1646
+ "type": "object",
1647
+ "properties": {
1648
+ "ok": {
1649
+ "const": false
1650
+ },
1651
+ "error": {
1652
+ "type": "object",
1653
+ "properties": {
1654
+ "code": {
1655
+ "type": "string"
1656
+ },
1657
+ "message": {
1658
+ "type": "string"
1659
+ },
1660
+ "retryable": {
1661
+ "type": "boolean"
1662
+ },
1663
+ "recoveryAction": {
1664
+ "type": "string"
1665
+ }
1666
+ },
1667
+ "required": [
1668
+ "code",
1669
+ "message",
1670
+ "retryable",
1671
+ "recoveryAction"
1672
+ ],
1673
+ "additionalProperties": false
1674
+ }
1675
+ },
1676
+ "required": [
1677
+ "ok",
1678
+ "error"
1679
+ ],
1680
+ "additionalProperties": false
1681
+ }
1682
+ ]
1683
+ }
1684
+ ```
1685
+
1686
+ ### `platform_checkout_design_system`
1687
+
1688
+ Download the exact published tenant Storyboard source into a new local directory for Codex or Claude Code to edit and run with npm ci and npm run storybook. Never overwrites an existing directory.
1689
+
1690
+ Safety: read-only=false, destructive=false, idempotent=false, open-world=true.
1691
+
1692
+ Example request:
1693
+
1694
+ ```json
1695
+ {
1696
+ "targetDir": "<targetDir>"
1697
+ }
1698
+ ```
1699
+
1700
+ Example success:
1701
+
1702
+ ```json
1703
+ {
1704
+ "ok": true,
1705
+ "directory": "<directory>",
1706
+ "currentCommit": "<currentCommit>",
1707
+ "localCommands": []
1708
+ }
1709
+ ```
1710
+
1711
+ Input schema:
1712
+
1713
+ ```json
1714
+ {
1715
+ "type": "object",
1716
+ "properties": {
1717
+ "targetDir": {
1718
+ "type": "string",
1719
+ "minLength": 1
1720
+ }
1721
+ },
1722
+ "required": [
1723
+ "targetDir"
1724
+ ],
1725
+ "additionalProperties": false
1726
+ }
1727
+ ```
1728
+
1729
+ Output schema:
1730
+
1731
+ ```json
1732
+ {
1733
+ "type": "object",
1734
+ "oneOf": [
1735
+ {
1736
+ "type": "object",
1737
+ "properties": {
1738
+ "ok": {
1739
+ "type": "boolean"
1740
+ },
1741
+ "directory": {
1742
+ "type": "string"
1743
+ },
1744
+ "currentCommit": {
1745
+ "type": "string"
1746
+ },
1747
+ "localCommands": {
1748
+ "type": "array",
1749
+ "items": {
1750
+ "type": "string"
1751
+ }
1752
+ }
1753
+ },
1754
+ "required": [
1755
+ "ok",
1756
+ "directory",
1757
+ "currentCommit",
1758
+ "localCommands"
1759
+ ]
1760
+ },
1761
+ {
1762
+ "type": "object",
1763
+ "properties": {
1764
+ "ok": {
1765
+ "const": false
1766
+ },
1767
+ "error": {
1768
+ "type": "object",
1769
+ "properties": {
1770
+ "code": {
1771
+ "type": "string"
1772
+ },
1773
+ "message": {
1774
+ "type": "string"
1775
+ },
1776
+ "retryable": {
1777
+ "type": "boolean"
1778
+ },
1779
+ "recoveryAction": {
1780
+ "type": "string"
1781
+ }
1782
+ },
1783
+ "required": [
1784
+ "code",
1785
+ "message",
1786
+ "retryable",
1787
+ "recoveryAction"
1788
+ ],
1789
+ "additionalProperties": false
1790
+ }
1791
+ },
1792
+ "required": [
1793
+ "ok",
1794
+ "error"
1795
+ ],
1796
+ "additionalProperties": false
1797
+ }
1798
+ ]
1799
+ }
1800
+ ```
1801
+
1802
+ ### `platform_submit_design_system_draft`
1803
+
1804
+ Package a locally edited Storyboard source directory and submit it as a private draft against exact published and draft revisions. The server validates and builds it before it can be published.
1805
+
1806
+ Safety: read-only=false, destructive=false, idempotent=false, open-world=true.
1807
+
1808
+ Example request:
1809
+
1810
+ ```json
1811
+ {
1812
+ "localDir": "<localDir>",
1813
+ "expectedCurrentCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1814
+ "expectedDraftRunId": "00000000-0000-4000-8000-000000000001"
1815
+ }
1816
+ ```
1817
+
1818
+ Example success:
1819
+
1820
+ ```json
1821
+ {
1822
+ "ok": true,
1823
+ "runId": "<runId>",
1824
+ "draftCommit": "<draftCommit>",
1825
+ "draftState": "<draftState>",
1826
+ "previewUrl": "<previewUrl>",
1827
+ "requestId": "<requestId>",
1828
+ "bundleSha256": "<bundleSha256>"
1829
+ }
1830
+ ```
1831
+
1832
+ Input schema:
1833
+
1834
+ ```json
1835
+ {
1836
+ "type": "object",
1837
+ "properties": {
1838
+ "localDir": {
1839
+ "type": "string",
1840
+ "minLength": 1
1841
+ },
1842
+ "expectedCurrentCommit": {
1843
+ "type": "string",
1844
+ "pattern": "^[a-f0-9]{40}$"
1845
+ },
1846
+ "expectedDraftRunId": {
1847
+ "anyOf": [
1848
+ {
1849
+ "type": "string",
1850
+ "format": "uuid"
1851
+ },
1852
+ {
1853
+ "type": "null"
1854
+ }
1855
+ ]
1856
+ }
1857
+ },
1858
+ "required": [
1859
+ "localDir",
1860
+ "expectedCurrentCommit",
1861
+ "expectedDraftRunId"
1862
+ ],
1863
+ "additionalProperties": false
1864
+ }
1865
+ ```
1866
+
1867
+ Output schema:
1868
+
1869
+ ```json
1870
+ {
1871
+ "type": "object",
1872
+ "oneOf": [
1873
+ {
1874
+ "type": "object",
1875
+ "properties": {
1876
+ "ok": {
1877
+ "type": "boolean"
1878
+ },
1879
+ "runId": {
1880
+ "type": "string"
1881
+ },
1882
+ "draftCommit": {
1883
+ "type": "string"
1884
+ },
1885
+ "draftState": {
1886
+ "type": "string"
1887
+ },
1888
+ "previewUrl": {
1889
+ "type": "string"
1890
+ },
1891
+ "requestId": {
1892
+ "type": "string"
1893
+ },
1894
+ "bundleSha256": {
1895
+ "type": "string"
1896
+ }
1897
+ },
1898
+ "required": [
1899
+ "ok",
1900
+ "runId",
1901
+ "draftCommit",
1902
+ "draftState",
1903
+ "previewUrl",
1904
+ "requestId",
1905
+ "bundleSha256"
1906
+ ]
1907
+ },
1908
+ {
1909
+ "type": "object",
1910
+ "properties": {
1911
+ "ok": {
1912
+ "const": false
1913
+ },
1914
+ "error": {
1915
+ "type": "object",
1916
+ "properties": {
1917
+ "code": {
1918
+ "type": "string"
1919
+ },
1920
+ "message": {
1921
+ "type": "string"
1922
+ },
1923
+ "retryable": {
1924
+ "type": "boolean"
1925
+ },
1926
+ "recoveryAction": {
1927
+ "type": "string"
1928
+ }
1929
+ },
1930
+ "required": [
1931
+ "code",
1932
+ "message",
1933
+ "retryable",
1934
+ "recoveryAction"
1935
+ ],
1936
+ "additionalProperties": false
1937
+ }
1938
+ },
1939
+ "required": [
1940
+ "ok",
1941
+ "error"
1942
+ ],
1943
+ "additionalProperties": false
1944
+ }
1945
+ ]
1946
+ }
1947
+ ```
1948
+
1949
+ ### `platform_edit_design_system`
1950
+
1951
+ Start an asynchronous Storyboard draft edit in an existing writable Topline Storyboard conversation. Pass expectedDraftRunId from the last state read (null for no draft); stale or concurrent retries are rejected.
1952
+
1953
+ Safety: read-only=false, destructive=false, idempotent=false, open-world=true.
1954
+
1955
+ Example request:
1956
+
1957
+ ```json
1958
+ {
1959
+ "conversationId": "00000000-0000-4000-8000-000000000001",
1960
+ "instruction": "<instruction>",
1961
+ "expectedDraftRunId": "00000000-0000-4000-8000-000000000001"
1962
+ }
1963
+ ```
1964
+
1965
+ Example success:
1966
+
1967
+ ```json
1968
+ {
1969
+ "runId": "<runId>",
1970
+ "previewUrl": "<previewUrl>"
1971
+ }
1972
+ ```
1973
+
1974
+ Input schema:
1975
+
1976
+ ```json
1977
+ {
1978
+ "type": "object",
1979
+ "properties": {
1980
+ "conversationId": {
1981
+ "type": "string",
1982
+ "format": "uuid"
1983
+ },
1984
+ "instruction": {
1985
+ "type": "string",
1986
+ "minLength": 1,
1987
+ "maxLength": 10000
1988
+ },
1989
+ "expectedDraftRunId": {
1990
+ "anyOf": [
1991
+ {
1992
+ "type": "string",
1993
+ "format": "uuid"
1994
+ },
1995
+ {
1996
+ "type": "null"
1997
+ }
1998
+ ]
1999
+ }
2000
+ },
2001
+ "required": [
2002
+ "conversationId",
2003
+ "instruction",
2004
+ "expectedDraftRunId"
2005
+ ],
2006
+ "additionalProperties": false
2007
+ }
2008
+ ```
2009
+
2010
+ Output schema:
2011
+
2012
+ ```json
2013
+ {
2014
+ "type": "object",
2015
+ "oneOf": [
2016
+ {
2017
+ "type": "object",
2018
+ "properties": {
2019
+ "runId": {
2020
+ "type": "string"
2021
+ },
2022
+ "previewUrl": {
2023
+ "type": "string"
2024
+ }
2025
+ },
2026
+ "required": [
2027
+ "runId",
2028
+ "previewUrl"
2029
+ ]
2030
+ },
2031
+ {
2032
+ "type": "object",
2033
+ "properties": {
2034
+ "ok": {
2035
+ "const": false
2036
+ },
2037
+ "error": {
2038
+ "type": "object",
2039
+ "properties": {
2040
+ "code": {
2041
+ "type": "string"
2042
+ },
2043
+ "message": {
2044
+ "type": "string"
2045
+ },
2046
+ "retryable": {
2047
+ "type": "boolean"
2048
+ },
2049
+ "recoveryAction": {
2050
+ "type": "string"
2051
+ }
2052
+ },
2053
+ "required": [
2054
+ "code",
2055
+ "message",
2056
+ "retryable",
2057
+ "recoveryAction"
2058
+ ],
2059
+ "additionalProperties": false
2060
+ }
2061
+ },
2062
+ "required": [
2063
+ "ok",
2064
+ "error"
2065
+ ],
2066
+ "additionalProperties": false
2067
+ }
2068
+ ]
2069
+ }
2070
+ ```
2071
+
2072
+ ### `platform_publish_design_system`
2073
+
2074
+ Publish the exact reviewed Storyboard draft after its build passes. Managed edits require their writable Storyboard conversation; local submissions require the submitting actor. Always pass state-bound run, draft, and current commits.
2075
+
2076
+ Safety: read-only=false, destructive=true, idempotent=false, open-world=true.
2077
+
2078
+ Example request:
2079
+
2080
+ ```json
2081
+ {
2082
+ "expectedDraftRunId": "00000000-0000-4000-8000-000000000001",
2083
+ "expectedDraftCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
2084
+ "expectedCurrentCommit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
2085
+ }
2086
+ ```
2087
+
2088
+ Example success:
2089
+
2090
+ ```json
2091
+ {
2092
+ "publishedCommit": "<publishedCommit>"
2093
+ }
2094
+ ```
2095
+
2096
+ Input schema:
2097
+
2098
+ ```json
2099
+ {
2100
+ "type": "object",
2101
+ "properties": {
2102
+ "conversationId": {
2103
+ "type": "string",
2104
+ "format": "uuid"
2105
+ },
2106
+ "expectedDraftRunId": {
2107
+ "type": "string",
2108
+ "format": "uuid"
2109
+ },
2110
+ "expectedDraftCommit": {
2111
+ "type": "string",
2112
+ "pattern": "^[a-f0-9]{40}$"
2113
+ },
2114
+ "expectedCurrentCommit": {
2115
+ "anyOf": [
2116
+ {
2117
+ "type": "string",
2118
+ "pattern": "^[a-f0-9]{40}$"
2119
+ },
2120
+ {
2121
+ "type": "null"
2122
+ }
2123
+ ]
2124
+ }
2125
+ },
2126
+ "required": [
2127
+ "expectedDraftRunId",
2128
+ "expectedDraftCommit",
2129
+ "expectedCurrentCommit"
2130
+ ],
2131
+ "additionalProperties": false
2132
+ }
2133
+ ```
2134
+
2135
+ Output schema:
2136
+
2137
+ ```json
2138
+ {
2139
+ "type": "object",
2140
+ "oneOf": [
2141
+ {
2142
+ "type": "object",
2143
+ "properties": {
2144
+ "publishedCommit": {
2145
+ "type": "string"
2146
+ }
2147
+ },
2148
+ "required": [
2149
+ "publishedCommit"
2150
+ ]
2151
+ },
2152
+ {
2153
+ "type": "object",
2154
+ "properties": {
2155
+ "ok": {
2156
+ "const": false
2157
+ },
2158
+ "error": {
2159
+ "type": "object",
2160
+ "properties": {
2161
+ "code": {
2162
+ "type": "string"
2163
+ },
2164
+ "message": {
2165
+ "type": "string"
2166
+ },
2167
+ "retryable": {
2168
+ "type": "boolean"
2169
+ },
2170
+ "recoveryAction": {
2171
+ "type": "string"
2172
+ }
2173
+ },
2174
+ "required": [
2175
+ "code",
2176
+ "message",
2177
+ "retryable",
2178
+ "recoveryAction"
2179
+ ],
2180
+ "additionalProperties": false
2181
+ }
2182
+ },
2183
+ "required": [
2184
+ "ok",
2185
+ "error"
2186
+ ],
2187
+ "additionalProperties": false
2188
+ }
2189
+ ]
2190
+ }
2191
+ ```
2192
+
1607
2193
  ### `platform_validate_artifact`
1608
2194
 
1609
2195
  Read trusted smoke and health evidence for a private artifact draft without requiring a browser session.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topline-build/harness-mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Topline Build MCP for creating and deploying artifact app drafts.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -218,9 +218,7 @@ async function agentMediatedRead(name, command, scratch, apiUrl, appDir, workspa
218
218
  "-p", "--verbose", "--output-format", "stream-json", prompt
219
219
  ], scratch, 180000, strictAgentEnvironment(process.env));
220
220
  if (!result.ok) {
221
- return authUnavailable(result.output)
222
- ? skipped("provider_credentials_or_client_session_unavailable")
223
- : failed("client_mediated_read_failed", result.exitCode);
221
+ return clientMediatedFailure(result);
224
222
  }
225
223
  const usedTool = hasToolCallEvidence(result.output, "platform_inspect_artifact_app");
226
224
  const certified = hasAssistantCertificationEvidence(result.output);
@@ -344,6 +342,12 @@ async function certifyProtocol({ apiUrl, token, appDir, workspaceRoot }) {
344
342
  }
345
343
 
346
344
  function selfTestReport() {
345
+ const timedOutProbe = run({ executable: process.execPath, prefix: [] }, ["-e", "console.log('api key authentication required'); setInterval(() => {}, 1000)"], process.cwd(), 1000);
346
+ const timedOutFailure = clientMediatedFailure(timedOutProbe);
347
+ if (!timedOutProbe.timedOut || !authUnavailable(timedOutProbe.output) || timedOutFailure.status !== "failed" || timedOutFailure.reason !== "client_mediated_read_timed_out"
348
+ || clientMediatedFailure({ timedOut: false, output: "not logged in", exitCode: 1 }).status !== "skipped") {
349
+ throw new Error("client_timeout_classification_self_test_failed");
350
+ }
347
351
  const toolName = "platform_inspect_artifact_app";
348
352
  const promptOnly = JSON.stringify({ type: "user", content: `Call ${toolName} and print TOPLINE_CLIENT_READ_CERTIFIED.` });
349
353
  const toolEvent = JSON.stringify({ type: "item.completed", item: { type: "mcp_tool_call", tool: toolName } });
@@ -477,12 +481,20 @@ function run(command, commandArgs, cwd, timeout = 30000, env = clientProbeEnviro
477
481
  return {
478
482
  ok: result.status === 0,
479
483
  missing: result.error?.code === "ENOENT",
484
+ timedOut: result.error?.code === "ETIMEDOUT",
480
485
  exitCode: result.status,
481
486
  stdout: result.stdout || "",
482
487
  output: `${result.stdout || ""}\n${result.stderr || ""}`
483
488
  };
484
489
  }
485
490
 
491
+ function clientMediatedFailure(result) {
492
+ if (result.timedOut) return failed("client_mediated_read_timed_out", result.exitCode);
493
+ return authUnavailable(result.output)
494
+ ? skipped("provider_credentials_or_client_session_unavailable")
495
+ : failed("client_mediated_read_failed", result.exitCode);
496
+ }
497
+
486
498
  function authUnavailable(output) {
487
499
  return /not logged in|not authenticated|authentication required|api key|login required|please login|sign in|unable to locate credentials|security token|AccessDeniedException|UnrecognizedClientException/i.test(output);
488
500
  }