@hyperstar/mcp 0.1.16 → 0.1.17
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/README.md +8 -3
- package/dist/config.d.ts +8 -1
- package/dist/config.js +25 -2
- package/dist/http.js +4 -1
- package/dist/index.js +4 -3
- package/dist/server.js +7 -3
- package/dist/workspaces.d.ts +2 -1
- package/dist/workspaces.js +15 -1
- package/package.json +1 -1
- package/scripts/npm-clean-room-smoke.mjs +126 -1
package/README.md
CHANGED
|
@@ -104,8 +104,11 @@ when `HYPERSTAR_API_KEY` is used. For non-production login, set matching
|
|
|
104
104
|
## Tools
|
|
105
105
|
|
|
106
106
|
Agents should start by reading `get_hyperstar_workflow_guide` or the MCP
|
|
107
|
-
resources/prompts listed below.
|
|
108
|
-
|
|
107
|
+
resources/prompts listed below. The MCP server starts without auth so clients
|
|
108
|
+
can discover tools and guides first; Product API workflow calls still require
|
|
109
|
+
local browser login or `HYPERSTAR_API_KEY`. Tool responses include
|
|
110
|
+
`agent_guidance` and, where the next step is deterministic, `next_tool` and
|
|
111
|
+
`next_arguments`.
|
|
109
112
|
|
|
110
113
|
- `hyperstar_whoami`
|
|
111
114
|
- `list_workspaces`
|
|
@@ -353,7 +356,9 @@ npm exec --yes --package @hyperstar/mcp -- hyperstar-mcp --help
|
|
|
353
356
|
```
|
|
354
357
|
|
|
355
358
|
These checks do not authenticate and do not call Hyperstar workflow APIs. They
|
|
356
|
-
|
|
359
|
+
prove that npm can resolve the package and both binaries can start. The package
|
|
360
|
+
smoke script also verifies unauthenticated MCP `tools/list`, `resources/list`,
|
|
361
|
+
and `prompts/list` discovery.
|
|
357
362
|
|
|
358
363
|
## Troubleshooting
|
|
359
364
|
|
package/dist/config.d.ts
CHANGED
|
@@ -12,7 +12,11 @@ export type CliConfig = {
|
|
|
12
12
|
readonly accessTokenProvider: CliAccessTokenProvider;
|
|
13
13
|
readonly workspaceSelection: CliWorkspaceSelection;
|
|
14
14
|
};
|
|
15
|
-
export type
|
|
15
|
+
export type UnauthenticatedConfig = {
|
|
16
|
+
readonly authMode: "unauthenticated";
|
|
17
|
+
readonly apiBaseUrl: string;
|
|
18
|
+
};
|
|
19
|
+
export type HyperstarMcpConfig = ServiceAccountConfig | CliConfig | UnauthenticatedConfig;
|
|
16
20
|
export type Env = Readonly<Record<string, string | undefined>>;
|
|
17
21
|
export type CliWorkspaceSelection = {
|
|
18
22
|
readonly getSelectedOrganizationId: () => Promise<string | undefined>;
|
|
@@ -20,6 +24,7 @@ export type CliWorkspaceSelection = {
|
|
|
20
24
|
};
|
|
21
25
|
export declare const DEFAULT_API_BASE_URL = "https://autopilot.hyper-star.org";
|
|
22
26
|
export declare const DEFAULT_APP_BASE_URL = "https://app.hyper-star.org";
|
|
27
|
+
export declare const AUTH_CONFIGURATION_MESSAGE = "Run `hyperstar login` or set HYPERSTAR_API_KEY";
|
|
23
28
|
export type LoadConfigOptions = {
|
|
24
29
|
readonly env?: Env;
|
|
25
30
|
readonly fetcher?: Fetcher | undefined;
|
|
@@ -27,6 +32,8 @@ export type LoadConfigOptions = {
|
|
|
27
32
|
};
|
|
28
33
|
/** Load MCP configuration from env or persisted CLI auth state. */
|
|
29
34
|
export declare function loadConfig(options?: Env | LoadConfigOptions): HyperstarMcpConfig;
|
|
35
|
+
/** Load config for MCP server startup, allowing unauthenticated discovery. */
|
|
36
|
+
export declare function loadServerConfig(options?: Env | LoadConfigOptions): HyperstarMcpConfig;
|
|
30
37
|
/** Create the local CLI workspace-selection port backed by auth state. */
|
|
31
38
|
export declare function createCliWorkspaceSelection(store: CliAuthStateStore): CliWorkspaceSelection;
|
|
32
39
|
/** Redact an API key or bearer token for error messages. */
|
package/dist/config.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createCliAuthClient, createStoredCliAccessTokenProvider, } from "./auth
|
|
|
2
2
|
import { createFileCliAuthStateStore, } from "./auth/cli-auth-state.js";
|
|
3
3
|
export const DEFAULT_API_BASE_URL = "https://autopilot.hyper-star.org";
|
|
4
4
|
export const DEFAULT_APP_BASE_URL = "https://app.hyper-star.org";
|
|
5
|
+
export const AUTH_CONFIGURATION_MESSAGE = "Run `hyperstar login` or set HYPERSTAR_API_KEY";
|
|
5
6
|
/** Load MCP configuration from env or persisted CLI auth state. */
|
|
6
7
|
export function loadConfig(options = process.env) {
|
|
7
8
|
const loadOptions = isLoadConfigOptions(options) ? options : { env: options };
|
|
@@ -24,7 +25,7 @@ export function loadConfig(options = process.env) {
|
|
|
24
25
|
const store = createFileCliAuthStateStore({ env });
|
|
25
26
|
const state = store.readSync();
|
|
26
27
|
if (state === null) {
|
|
27
|
-
throw new Error(
|
|
28
|
+
throw new Error(AUTH_CONFIGURATION_MESSAGE);
|
|
28
29
|
}
|
|
29
30
|
const stateApiBaseUrl = normalizeBaseUrl(state.apiBaseUrl, "stored Hyperstar auth API base URL");
|
|
30
31
|
const rawCliApiBaseUrl = env.HYPERSTAR_API_BASE_URL?.trim();
|
|
@@ -52,6 +53,28 @@ export function loadConfig(options = process.env) {
|
|
|
52
53
|
workspaceSelection: createCliWorkspaceSelection(store),
|
|
53
54
|
};
|
|
54
55
|
}
|
|
56
|
+
/** Load config for MCP server startup, allowing unauthenticated discovery. */
|
|
57
|
+
export function loadServerConfig(options = process.env) {
|
|
58
|
+
try {
|
|
59
|
+
return loadConfig(options);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (!(error instanceof Error) ||
|
|
63
|
+
error.message !== AUTH_CONFIGURATION_MESSAGE) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
const loadOptions = isLoadConfigOptions(options)
|
|
67
|
+
? options
|
|
68
|
+
: { env: options };
|
|
69
|
+
const env = loadOptions.env ?? process.env;
|
|
70
|
+
const rawBaseUrl = env.HYPERSTAR_API_BASE_URL?.trim() ?? DEFAULT_API_BASE_URL;
|
|
71
|
+
const apiBaseUrl = normalizeBaseUrl(rawBaseUrl.length === 0 ? DEFAULT_API_BASE_URL : rawBaseUrl, "HYPERSTAR_API_BASE_URL");
|
|
72
|
+
return {
|
|
73
|
+
authMode: "unauthenticated",
|
|
74
|
+
apiBaseUrl,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
55
78
|
/** Create the local CLI workspace-selection port backed by auth state. */
|
|
56
79
|
export function createCliWorkspaceSelection(store) {
|
|
57
80
|
return {
|
|
@@ -60,7 +83,7 @@ export function createCliWorkspaceSelection(store) {
|
|
|
60
83
|
await store.withExclusiveLock(async () => {
|
|
61
84
|
const state = await store.read();
|
|
62
85
|
if (state === null) {
|
|
63
|
-
throw new Error(
|
|
86
|
+
throw new Error(AUTH_CONFIGURATION_MESSAGE);
|
|
64
87
|
}
|
|
65
88
|
await store.write({
|
|
66
89
|
...state,
|
package/dist/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { redactSecret } from "./config.js";
|
|
1
|
+
import { AUTH_CONFIGURATION_MESSAGE, redactSecret, } from "./config.js";
|
|
2
2
|
export class HyperstarApiError extends Error {
|
|
3
3
|
status;
|
|
4
4
|
detail;
|
|
@@ -24,6 +24,9 @@ export function createHyperstarClient(options) {
|
|
|
24
24
|
};
|
|
25
25
|
const secretsToRedact = [];
|
|
26
26
|
let retryCliAccessToken;
|
|
27
|
+
if (options.config.authMode === "unauthenticated") {
|
|
28
|
+
throw new Error(AUTH_CONFIGURATION_MESSAGE);
|
|
29
|
+
}
|
|
27
30
|
if (options.config.authMode === "service_account") {
|
|
28
31
|
baseHeaders["x-hyperstar-api-key"] = options.config.apiKey;
|
|
29
32
|
secretsToRedact.push(options.config.apiKey);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import {
|
|
3
|
+
import { loadServerConfig } from "./config.js";
|
|
4
4
|
import { createHyperstarMcpServer } from "./server.js";
|
|
5
5
|
const MCP_SERVER_USAGE = [
|
|
6
6
|
"Usage: hyperstar-mcp [--help]",
|
|
@@ -8,7 +8,8 @@ const MCP_SERVER_USAGE = [
|
|
|
8
8
|
"Starts the Hyperstar stdio MCP server.",
|
|
9
9
|
"",
|
|
10
10
|
"Authentication:",
|
|
11
|
-
"
|
|
11
|
+
" Tools and guides are discoverable before auth.",
|
|
12
|
+
" Product API calls require `hyperstar login` or HYPERSTAR_API_KEY.",
|
|
12
13
|
].join("\n");
|
|
13
14
|
/** Start the stdio MCP server process. */
|
|
14
15
|
async function main() {
|
|
@@ -16,7 +17,7 @@ async function main() {
|
|
|
16
17
|
process.stdout.write(`${MCP_SERVER_USAGE}\n`);
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
|
-
const config =
|
|
20
|
+
const config = loadServerConfig();
|
|
20
21
|
const server = createHyperstarMcpServer(config);
|
|
21
22
|
await server.connect(new StdioServerTransport());
|
|
22
23
|
}
|
package/dist/server.js
CHANGED
|
@@ -10,8 +10,12 @@ export function createHyperstarMcpServer(config) {
|
|
|
10
10
|
version: packageVersion(),
|
|
11
11
|
});
|
|
12
12
|
registerHyperstarDiscovery(server, { apiBaseUrl: config.apiBaseUrl });
|
|
13
|
-
|
|
14
|
-
? {
|
|
15
|
-
|
|
13
|
+
const toolOptions = config.authMode === "cli"
|
|
14
|
+
? {
|
|
15
|
+
authMode: config.authMode,
|
|
16
|
+
workspaceSelection: config.workspaceSelection,
|
|
17
|
+
}
|
|
18
|
+
: { authMode: config.authMode };
|
|
19
|
+
registerHyperstarTools(server, createHyperstarClient({ config }), toolOptions);
|
|
16
20
|
return server;
|
|
17
21
|
}
|
package/dist/workspaces.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { CliWorkspaceSelection } from "./config.js";
|
|
1
|
+
import type { CliWorkspaceSelection, HyperstarMcpConfig } from "./config.js";
|
|
2
2
|
import type { HyperstarClient, JsonObject } from "./http.js";
|
|
3
3
|
export type WorkspaceToolOptions = {
|
|
4
|
+
readonly authMode?: HyperstarMcpConfig["authMode"];
|
|
4
5
|
readonly workspaceSelection?: CliWorkspaceSelection;
|
|
5
6
|
};
|
|
6
7
|
/** List workspaces through the Product API workspace route. */
|
package/dist/workspaces.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkspaceListResponseSchema } from "./schemas.js";
|
|
2
|
-
import { workflowGuideJson } from "./workflow-content.js";
|
|
2
|
+
import { CLI_SAFETY_NOTES, CLI_WORKFLOW_SEQUENCE, WORKFLOW_DATA_FLOW_NOTES, workflowGuideJson, workflowGuideResourceDefinitions, } from "./workflow-content.js";
|
|
3
3
|
/** List workspaces through the Product API workspace route. */
|
|
4
4
|
export async function listAvailableWorkspaces(client, options = {}) {
|
|
5
5
|
const payload = WorkspaceListResponseSchema.parse(await client.get("/v1/workspaces"));
|
|
@@ -33,6 +33,20 @@ export async function selectAvailableWorkspace(client, organizationId, options =
|
|
|
33
33
|
}
|
|
34
34
|
/** Return the recommended Hyperstar agent workflow and send-safety notes. */
|
|
35
35
|
export function getHyperstarWorkflowGuide(options = {}) {
|
|
36
|
+
if (options.authMode === "unauthenticated") {
|
|
37
|
+
return {
|
|
38
|
+
sequence: [
|
|
39
|
+
"Configure auth first: run `hyperstar login` and select a workspace, or set HYPERSTAR_API_KEY.",
|
|
40
|
+
...CLI_WORKFLOW_SEQUENCE,
|
|
41
|
+
],
|
|
42
|
+
safety_notes: [
|
|
43
|
+
"MCP tools and guides are discoverable before auth, but Product API workflow calls require local browser login or HYPERSTAR_API_KEY.",
|
|
44
|
+
...CLI_SAFETY_NOTES,
|
|
45
|
+
],
|
|
46
|
+
data_flow_notes: [...WORKFLOW_DATA_FLOW_NOTES],
|
|
47
|
+
resources: workflowGuideResourceDefinitions.map((resource) => resource.uri),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
36
50
|
if (options.workspaceSelection === undefined) {
|
|
37
51
|
return workflowGuideJson("service_account");
|
|
38
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
4
5
|
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
5
6
|
import { tmpdir } from "node:os";
|
|
6
7
|
import { dirname, isAbsolute, resolve } from "node:path";
|
|
@@ -39,11 +40,25 @@ function logLocalPackageSpec(value) {
|
|
|
39
40
|
);
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
function smokeEnv() {
|
|
44
|
+
const env = {
|
|
45
|
+
...process.env,
|
|
46
|
+
HOME: scratchDir,
|
|
47
|
+
XDG_CONFIG_HOME: resolve(scratchDir, "config"),
|
|
48
|
+
npm_config_cache: resolve(scratchDir, "npm-cache"),
|
|
49
|
+
npm_config_update_notifier: "false",
|
|
50
|
+
};
|
|
51
|
+
delete env.HYPERSTAR_API_KEY;
|
|
52
|
+
delete env.HYPERSTAR_API_BASE_URL;
|
|
53
|
+
delete env.HYPERSTAR_APP_BASE_URL;
|
|
54
|
+
return env;
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
function runStep(step, command, args) {
|
|
43
58
|
const result = spawnSync(command, args, {
|
|
44
59
|
cwd: scratchDir,
|
|
45
60
|
encoding: "utf8",
|
|
46
|
-
env:
|
|
61
|
+
env: smokeEnv(),
|
|
47
62
|
shell: false,
|
|
48
63
|
});
|
|
49
64
|
const stdout = result.stdout.trim();
|
|
@@ -79,6 +94,115 @@ function runStep(step, command, args) {
|
|
|
79
94
|
);
|
|
80
95
|
}
|
|
81
96
|
|
|
97
|
+
async function runMcpDiscoveryStep() {
|
|
98
|
+
const child = spawn(
|
|
99
|
+
"npm",
|
|
100
|
+
["exec", "--yes", "--package", packageSpec, "--", "hyperstar-mcp"],
|
|
101
|
+
{
|
|
102
|
+
cwd: scratchDir,
|
|
103
|
+
env: smokeEnv(),
|
|
104
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
const responses = [];
|
|
108
|
+
let stdout = "";
|
|
109
|
+
let stderr = "";
|
|
110
|
+
child.stdout.setEncoding("utf8");
|
|
111
|
+
child.stderr.setEncoding("utf8");
|
|
112
|
+
child.stdout.on("data", (chunk) => {
|
|
113
|
+
stdout += chunk;
|
|
114
|
+
for (;;) {
|
|
115
|
+
const lineEnd = stdout.indexOf("\n");
|
|
116
|
+
if (lineEnd === -1) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
const line = stdout.slice(0, lineEnd).trim();
|
|
120
|
+
stdout = stdout.slice(lineEnd + 1);
|
|
121
|
+
if (line.length === 0) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
responses.push(JSON.parse(line));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
child.stderr.on("data", (chunk) => {
|
|
128
|
+
stderr += chunk;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const send = (message) => {
|
|
132
|
+
child.stdin.write(`${JSON.stringify(message)}\n`);
|
|
133
|
+
};
|
|
134
|
+
const waitFor = (id) =>
|
|
135
|
+
new Promise((resolveResponse, rejectResponse) => {
|
|
136
|
+
const started = Date.now();
|
|
137
|
+
const interval = setInterval(() => {
|
|
138
|
+
const response = responses.find((item) => item.id === id);
|
|
139
|
+
if (response !== undefined) {
|
|
140
|
+
clearInterval(interval);
|
|
141
|
+
resolveResponse(response);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (Date.now() - started > 15_000) {
|
|
145
|
+
clearInterval(interval);
|
|
146
|
+
rejectResponse(
|
|
147
|
+
new Error(`Timed out waiting for MCP response ${id}: ${stderr}`),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}, 50);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
send({
|
|
155
|
+
jsonrpc: "2.0",
|
|
156
|
+
id: 1,
|
|
157
|
+
method: "initialize",
|
|
158
|
+
params: {
|
|
159
|
+
protocolVersion: "2024-11-05",
|
|
160
|
+
capabilities: {},
|
|
161
|
+
clientInfo: { name: "hyperstar-npm-smoke", version: "0.0.0" },
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
await waitFor(1);
|
|
165
|
+
send({ jsonrpc: "2.0", method: "notifications/initialized", params: {} });
|
|
166
|
+
send({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} });
|
|
167
|
+
send({ jsonrpc: "2.0", id: 3, method: "resources/list", params: {} });
|
|
168
|
+
send({ jsonrpc: "2.0", id: 4, method: "prompts/list", params: {} });
|
|
169
|
+
const [tools, resources, prompts] = await Promise.all([
|
|
170
|
+
waitFor(2),
|
|
171
|
+
waitFor(3),
|
|
172
|
+
waitFor(4),
|
|
173
|
+
]);
|
|
174
|
+
console.log(
|
|
175
|
+
JSON.stringify(
|
|
176
|
+
{
|
|
177
|
+
step: "hyperstar-mcp-discovery",
|
|
178
|
+
ok: true,
|
|
179
|
+
tools: tools.result.tools.map((tool) => tool.name).slice(0, 8),
|
|
180
|
+
resources: resources.result.resources.map((resource) => resource.uri),
|
|
181
|
+
prompts: prompts.result.prompts.map((prompt) => prompt.name),
|
|
182
|
+
},
|
|
183
|
+
null,
|
|
184
|
+
2,
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error(
|
|
189
|
+
JSON.stringify(
|
|
190
|
+
{
|
|
191
|
+
step: "hyperstar-mcp-discovery",
|
|
192
|
+
ok: false,
|
|
193
|
+
error: error instanceof Error ? error.message : String(error),
|
|
194
|
+
stderr: stderr.trim(),
|
|
195
|
+
},
|
|
196
|
+
null,
|
|
197
|
+
2,
|
|
198
|
+
),
|
|
199
|
+
);
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
} finally {
|
|
202
|
+
child.kill("SIGTERM");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
82
206
|
try {
|
|
83
207
|
if (isLocalPackageSpec(packageSpec)) {
|
|
84
208
|
logLocalPackageSpec(packageSpec);
|
|
@@ -108,6 +232,7 @@ try {
|
|
|
108
232
|
"hyperstar-mcp",
|
|
109
233
|
"--help",
|
|
110
234
|
]);
|
|
235
|
+
await runMcpDiscoveryStep();
|
|
111
236
|
} finally {
|
|
112
237
|
rmSync(scratchDir, { recursive: true, force: true });
|
|
113
238
|
}
|