@harness-control/runner 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +21 -0
  3. package/dist/audit/index.d.ts +18 -0
  4. package/dist/audit/index.js +28 -0
  5. package/dist/config/index.d.ts +179 -0
  6. package/dist/config/index.js +124 -0
  7. package/dist/connection/index.d.ts +2 -0
  8. package/dist/connection/index.js +2 -0
  9. package/dist/connection/runner-connection.d.ts +22 -0
  10. package/dist/connection/runner-connection.js +631 -0
  11. package/dist/harnesses/adapters/providers/claude-runtime.d.ts +5 -0
  12. package/dist/harnesses/adapters/providers/claude-runtime.js +186 -0
  13. package/dist/harnesses/adapters/providers/claude.d.ts +24 -0
  14. package/dist/harnesses/adapters/providers/claude.js +189 -0
  15. package/dist/harnesses/adapters/providers/cli-process.d.ts +44 -0
  16. package/dist/harnesses/adapters/providers/cli-process.js +195 -0
  17. package/dist/harnesses/adapters/providers/codex-models.d.ts +4 -0
  18. package/dist/harnesses/adapters/providers/codex-models.js +62 -0
  19. package/dist/harnesses/adapters/providers/codex-rpc.d.ts +21 -0
  20. package/dist/harnesses/adapters/providers/codex-rpc.js +114 -0
  21. package/dist/harnesses/adapters/providers/codex-runtime.d.ts +3 -0
  22. package/dist/harnesses/adapters/providers/codex-runtime.js +267 -0
  23. package/dist/harnesses/adapters/providers/codex.d.ts +22 -0
  24. package/dist/harnesses/adapters/providers/codex.js +161 -0
  25. package/dist/harnesses/adapters/providers/mock.d.ts +13 -0
  26. package/dist/harnesses/adapters/providers/mock.js +64 -0
  27. package/dist/harnesses/adapters/providers/native-process.d.ts +9 -0
  28. package/dist/harnesses/adapters/providers/native-process.js +41 -0
  29. package/dist/harnesses/adapters/providers/native-turn.d.ts +17 -0
  30. package/dist/harnesses/adapters/providers/native-turn.js +139 -0
  31. package/dist/harnesses/adapters/providers/opencode.d.ts +44 -0
  32. package/dist/harnesses/adapters/providers/opencode.js +416 -0
  33. package/dist/harnesses/adapters/providers/shared.d.ts +9 -0
  34. package/dist/harnesses/adapters/providers/shared.js +97 -0
  35. package/dist/harnesses/adapters/registry.d.ts +12 -0
  36. package/dist/harnesses/adapters/registry.js +47 -0
  37. package/dist/harnesses/adapters/types.d.ts +54 -0
  38. package/dist/harnesses/adapters/types.js +9 -0
  39. package/dist/harnesses/adapters.d.ts +8 -0
  40. package/dist/harnesses/adapters.js +8 -0
  41. package/dist/harnesses/index.d.ts +93 -0
  42. package/dist/harnesses/index.js +620 -0
  43. package/dist/host/provider-registry.d.ts +34 -0
  44. package/dist/host/provider-registry.js +162 -0
  45. package/dist/index.d.ts +3 -0
  46. package/dist/index.js +201 -0
  47. package/dist/local-actions/dispatcher.d.ts +28 -0
  48. package/dist/local-actions/dispatcher.js +407 -0
  49. package/dist/local-actions/executors.d.ts +159 -0
  50. package/dist/local-actions/executors.js +1103 -0
  51. package/dist/local-actions/index.d.ts +74 -0
  52. package/dist/local-actions/index.js +275 -0
  53. package/dist/logs/index.d.ts +6 -0
  54. package/dist/logs/index.js +9 -0
  55. package/dist/mcp/McpAttachmentClient.d.ts +111 -0
  56. package/dist/mcp/McpAttachmentClient.js +345 -0
  57. package/dist/mcp/McpProxyServer.d.ts +18 -0
  58. package/dist/mcp/McpProxyServer.js +188 -0
  59. package/dist/mcp/McpStdioProfileClient.d.ts +19 -0
  60. package/dist/mcp/McpStdioProfileClient.js +91 -0
  61. package/dist/mcp/index.d.ts +5 -0
  62. package/dist/mcp/index.js +5 -0
  63. package/dist/mcp/redaction.d.ts +3 -0
  64. package/dist/mcp/redaction.js +40 -0
  65. package/dist/pairing/index.d.ts +38 -0
  66. package/dist/pairing/index.js +180 -0
  67. package/dist/state/index.d.ts +76 -0
  68. package/dist/state/index.js +242 -0
  69. package/dist/workspaces/index.d.ts +13 -0
  70. package/dist/workspaces/index.js +110 -0
  71. package/package.json +76 -0
@@ -0,0 +1,74 @@
1
+ import type { HcpSessionStartPayload, LocalCapabilityGrant, LocalCapabilityLease } from "@harness-control/protocol";
2
+ import type { ProviderInstanceConfig, RunnerConfig } from "../config/index.js";
3
+ export type LocalCapabilityActionRequest = {
4
+ session_id: string;
5
+ turn_id: string;
6
+ workspace_id: string;
7
+ provider_instance_id: string;
8
+ capability_id: string;
9
+ scope: string;
10
+ action: string;
11
+ };
12
+ export type LocalFilesystemAction = "read" | "list" | "write" | "create" | "delete" | "patch";
13
+ export type LocalFilesystemAuthorizationRequest = {
14
+ session_id: string;
15
+ turn_id: string;
16
+ workspace_id: string;
17
+ provider_instance_id: string;
18
+ action: LocalFilesystemAction;
19
+ };
20
+ export type LocalGitAction = "status" | "diff" | "branch" | "commit_metadata" | "commit" | "checkout" | "push";
21
+ export type LocalGitAuthorizationRequest = {
22
+ session_id: string;
23
+ turn_id: string;
24
+ workspace_id: string;
25
+ provider_instance_id: string;
26
+ action: LocalGitAction;
27
+ };
28
+ export type LocalShellAuthorizationRequest = {
29
+ session_id: string;
30
+ turn_id: string;
31
+ workspace_id: string;
32
+ provider_instance_id: string;
33
+ executable: string;
34
+ argv: string[];
35
+ cwd: string;
36
+ workspace_root: string;
37
+ use_shell: boolean;
38
+ timeout_seconds: number;
39
+ env?: Record<string, string>;
40
+ };
41
+ export type LocalDevServerAuthorizationRequest = {
42
+ session_id: string;
43
+ turn_id: string;
44
+ workspace_id: string;
45
+ provider_instance_id: string;
46
+ action: "start" | "stop" | "inspect";
47
+ executable?: string;
48
+ argv?: string[];
49
+ cwd?: string;
50
+ workspace_root?: string;
51
+ use_shell?: boolean;
52
+ timeout_seconds?: number;
53
+ env?: Record<string, string>;
54
+ };
55
+ export declare class LocalCapabilityPolicyError extends Error {
56
+ readonly code: string;
57
+ constructor(code: string, message: string);
58
+ }
59
+ export declare class LocalCapabilityLeaseManager {
60
+ #private;
61
+ constructor(config: RunnerConfig, hostId: string, now?: () => Date);
62
+ validateSessionLease(payload: HcpSessionStartPayload, provider: ProviderInstanceConfig): LocalCapabilityLease | undefined;
63
+ revokeLease(leaseId: string): void;
64
+ assertActionAllowed(lease: LocalCapabilityLease, request: LocalCapabilityActionRequest): LocalCapabilityGrant;
65
+ }
66
+ export declare class LocalCapabilityEngine {
67
+ readonly leaseManager: LocalCapabilityLeaseManager;
68
+ constructor(leaseManager: LocalCapabilityLeaseManager);
69
+ authorizeFilesystemAction(lease: LocalCapabilityLease, request: LocalFilesystemAuthorizationRequest): LocalCapabilityGrant;
70
+ authorizeGitAction(lease: LocalCapabilityLease, request: LocalGitAuthorizationRequest): LocalCapabilityGrant;
71
+ authorizeShellCommand(lease: LocalCapabilityLease, request: LocalShellAuthorizationRequest): Promise<LocalCapabilityGrant>;
72
+ authorizeDevServerAction(lease: LocalCapabilityLease, request: LocalDevServerAuthorizationRequest): Promise<LocalCapabilityGrant>;
73
+ }
74
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,275 @@
1
+ import { realpath } from "node:fs/promises";
2
+ import { isAbsolute, relative } from "node:path";
3
+ export class LocalCapabilityPolicyError extends Error {
4
+ code;
5
+ constructor(code, message) {
6
+ super(message);
7
+ this.code = code;
8
+ this.name = "LocalCapabilityPolicyError";
9
+ }
10
+ }
11
+ export class LocalCapabilityLeaseManager {
12
+ #config;
13
+ #hostId;
14
+ #now;
15
+ #revokedLeaseIds = new Set();
16
+ #callCounts = new Map();
17
+ constructor(config, hostId, now = () => new Date()) {
18
+ this.#config = config;
19
+ this.#hostId = hostId;
20
+ this.#now = now;
21
+ }
22
+ validateSessionLease(payload, provider) {
23
+ const lease = payload.local_capability_lease;
24
+ if (!lease) {
25
+ return undefined;
26
+ }
27
+ this.#assertLeaseBinding(lease, payload);
28
+ this.#assertLeaseUsable(lease);
29
+ for (const grant of lease.capabilities) {
30
+ const configuredCapability = this.#requireConfiguredCapability(grant.id);
31
+ this.#assertGrantScopesAllowed(configuredCapability, grant);
32
+ this.#assertProviderSupportsCapability(provider, grant.id);
33
+ }
34
+ return lease;
35
+ }
36
+ revokeLease(leaseId) {
37
+ this.#revokedLeaseIds.add(leaseId);
38
+ }
39
+ assertActionAllowed(lease, request) {
40
+ this.#assertLeaseUsable(lease);
41
+ if (request.session_id !== lease.hcp_session_id) {
42
+ throw new LocalCapabilityPolicyError("local_capability_session_mismatch", "Local capability action session does not match the lease.");
43
+ }
44
+ if (request.workspace_id !== lease.workspace_id) {
45
+ throw new LocalCapabilityPolicyError("local_capability_workspace_mismatch", "Local capability action workspace does not match the lease.");
46
+ }
47
+ if (request.provider_instance_id !== lease.provider_instance_id) {
48
+ throw new LocalCapabilityPolicyError("local_capability_provider_mismatch", "Local capability action provider does not match the lease.");
49
+ }
50
+ const grant = lease.capabilities.find((candidate) => candidate.id === request.capability_id);
51
+ if (!grant) {
52
+ throw new LocalCapabilityPolicyError("local_capability_not_granted", `Capability '${request.capability_id}' is not granted by lease '${lease.lease_id}'.`);
53
+ }
54
+ if (!grant.scopes.includes(request.scope)) {
55
+ throw new LocalCapabilityPolicyError("local_capability_scope_not_granted", `Scope '${request.scope}' is not granted for capability '${request.capability_id}'.`);
56
+ }
57
+ const configuredCapability = this.#requireConfiguredCapability(request.capability_id);
58
+ if (!configuredCapability.scopes.includes(request.scope)) {
59
+ throw new LocalCapabilityPolicyError("local_capability_scope_unavailable", `Scope '${request.scope}' is not available for capability '${request.capability_id}' on this runner.`);
60
+ }
61
+ const countKey = `${lease.lease_id}:${grant.id}`;
62
+ const existingCallCount = this.#callCounts.get(countKey) ?? 0;
63
+ if (grant.max_calls !== undefined && existingCallCount >= grant.max_calls) {
64
+ throw new LocalCapabilityPolicyError("local_capability_max_calls_exceeded", `Capability '${request.capability_id}' exceeded its max call count.`);
65
+ }
66
+ this.#callCounts.set(countKey, existingCallCount + 1);
67
+ return grant;
68
+ }
69
+ #assertLeaseBinding(lease, payload) {
70
+ if (lease.hcp_session_id !== payload.session_id) {
71
+ throw new LocalCapabilityPolicyError("local_capability_session_mismatch", "Local capability lease session does not match the HCP session.");
72
+ }
73
+ if (lease.execution_host_id !== this.#hostId) {
74
+ throw new LocalCapabilityPolicyError("local_capability_host_mismatch", "Local capability lease host does not match this runner.");
75
+ }
76
+ if (lease.provider_instance_id !== payload.provider_instance_id) {
77
+ throw new LocalCapabilityPolicyError("local_capability_provider_mismatch", "Local capability lease provider does not match the selected provider.");
78
+ }
79
+ if (lease.workspace_id !== payload.workspace_id) {
80
+ throw new LocalCapabilityPolicyError("local_capability_workspace_mismatch", "Local capability lease workspace does not match the selected workspace.");
81
+ }
82
+ }
83
+ #assertLeaseUsable(lease) {
84
+ if (this.#revokedLeaseIds.has(lease.lease_id)) {
85
+ throw new LocalCapabilityPolicyError("local_capability_lease_revoked", `Local capability lease '${lease.lease_id}' has been revoked.`);
86
+ }
87
+ const expiresAt = Date.parse(lease.expires_at);
88
+ if (Number.isNaN(expiresAt) || expiresAt <= this.#now().getTime()) {
89
+ throw new LocalCapabilityPolicyError("local_capability_lease_expired", `Local capability lease '${lease.lease_id}' has expired.`);
90
+ }
91
+ }
92
+ #requireConfiguredCapability(capabilityId) {
93
+ const capability = this.#config.local_capabilities.find((candidate) => candidate.id === capabilityId);
94
+ if (!capability) {
95
+ throw new LocalCapabilityPolicyError("local_capability_unavailable", `Capability '${capabilityId}' is not configured by this runner.`);
96
+ }
97
+ if (capability.status !== "available") {
98
+ throw new LocalCapabilityPolicyError("local_capability_unavailable", `Capability '${capabilityId}' is ${capability.status}.`);
99
+ }
100
+ return capability;
101
+ }
102
+ #assertProviderSupportsCapability(provider, capabilityId) {
103
+ if (!provider.local_capabilities.includes(capabilityId)) {
104
+ throw new LocalCapabilityPolicyError("local_capability_provider_unsupported", `Provider '${provider.id}' does not support capability '${capabilityId}'.`);
105
+ }
106
+ }
107
+ #assertGrantScopesAllowed(configuredCapability, grant) {
108
+ const unavailableScopes = grant.scopes.filter((scope) => !configuredCapability.scopes.includes(scope));
109
+ if (unavailableScopes.length > 0) {
110
+ throw new LocalCapabilityPolicyError("local_capability_scope_unavailable", `Capability '${grant.id}' requested unavailable scopes: ${unavailableScopes.join(", ")}.`);
111
+ }
112
+ }
113
+ }
114
+ export class LocalCapabilityEngine {
115
+ leaseManager;
116
+ constructor(leaseManager) {
117
+ this.leaseManager = leaseManager;
118
+ }
119
+ authorizeFilesystemAction(lease, request) {
120
+ return this.leaseManager.assertActionAllowed(lease, {
121
+ session_id: request.session_id,
122
+ turn_id: request.turn_id,
123
+ workspace_id: request.workspace_id,
124
+ provider_instance_id: request.provider_instance_id,
125
+ capability_id: "filesystem",
126
+ scope: filesystemScopeForAction(request.action),
127
+ action: request.action,
128
+ });
129
+ }
130
+ authorizeGitAction(lease, request) {
131
+ return this.leaseManager.assertActionAllowed(lease, {
132
+ session_id: request.session_id,
133
+ turn_id: request.turn_id,
134
+ workspace_id: request.workspace_id,
135
+ provider_instance_id: request.provider_instance_id,
136
+ capability_id: "git",
137
+ scope: gitScopeForAction(request.action),
138
+ action: request.action,
139
+ });
140
+ }
141
+ async authorizeShellCommand(lease, request) {
142
+ const grant = this.leaseManager.assertActionAllowed(lease, {
143
+ session_id: request.session_id,
144
+ turn_id: request.turn_id,
145
+ workspace_id: request.workspace_id,
146
+ provider_instance_id: request.provider_instance_id,
147
+ capability_id: "shell",
148
+ scope: "workspace",
149
+ action: "run_command",
150
+ });
151
+ await assertExecutableGrantAllowed(grant, "Shell actions");
152
+ await assertCommandPolicyAllows(grant.command_policy, {
153
+ executable: request.executable,
154
+ argv: request.argv,
155
+ cwd: request.cwd,
156
+ workspace_root: request.workspace_root,
157
+ use_shell: request.use_shell,
158
+ timeout_seconds: request.timeout_seconds,
159
+ env: request.env ?? {},
160
+ });
161
+ return grant;
162
+ }
163
+ async authorizeDevServerAction(lease, request) {
164
+ const grant = this.leaseManager.assertActionAllowed(lease, {
165
+ session_id: request.session_id,
166
+ turn_id: request.turn_id,
167
+ workspace_id: request.workspace_id,
168
+ provider_instance_id: request.provider_instance_id,
169
+ capability_id: "dev_server",
170
+ scope: "workspace",
171
+ action: request.action,
172
+ });
173
+ if (request.action === "start") {
174
+ await assertExecutableGrantAllowed(grant, "Dev server start actions");
175
+ if (!request.executable ||
176
+ !request.argv ||
177
+ !request.cwd ||
178
+ !request.workspace_root ||
179
+ request.use_shell === undefined ||
180
+ request.timeout_seconds === undefined) {
181
+ throw new LocalCapabilityPolicyError("local_capability_command_policy_required", "Dev server start actions require executable, argv, cwd, workspace root, shell mode, and timeout.");
182
+ }
183
+ await assertCommandPolicyAllows(grant.command_policy, {
184
+ executable: request.executable,
185
+ argv: request.argv,
186
+ cwd: request.cwd,
187
+ workspace_root: request.workspace_root,
188
+ use_shell: request.use_shell,
189
+ timeout_seconds: request.timeout_seconds,
190
+ env: request.env ?? {},
191
+ });
192
+ }
193
+ return grant;
194
+ }
195
+ }
196
+ async function assertExecutableGrantAllowed(grant, actionLabel) {
197
+ if (grant.approval_policy !== "full_access") {
198
+ throw new LocalCapabilityPolicyError("local_capability_approval_required", `${actionLabel} require a local capability lease grant with approval_policy 'full_access'.`);
199
+ }
200
+ if (!grant.command_policy) {
201
+ throw new LocalCapabilityPolicyError("local_capability_command_policy_required", `${actionLabel} require a structured command policy.`);
202
+ }
203
+ }
204
+ async function assertCommandPolicyAllows(policy, request) {
205
+ if (!policy) {
206
+ throw new LocalCapabilityPolicyError("local_capability_command_policy_required", "Executable local capability actions require a structured command policy.");
207
+ }
208
+ if (!policy.allow_shell && request.use_shell) {
209
+ throw new LocalCapabilityPolicyError("local_capability_shell_denied", "Shell wrappers are not allowed by policy.");
210
+ }
211
+ if (request.timeout_seconds > policy.timeout_seconds) {
212
+ throw new LocalCapabilityPolicyError("local_capability_timeout_exceeded", `Requested timeout ${request.timeout_seconds}s exceeds policy timeout ${policy.timeout_seconds}s.`);
213
+ }
214
+ if (policy.network_policy !== "inherit") {
215
+ throw new LocalCapabilityPolicyError("local_capability_network_policy_unsupported", `Network policy '${policy.network_policy}' cannot be enforced by this runner.`);
216
+ }
217
+ if (policy.env_policy === "minimal" && Object.keys(request.env).length > 0) {
218
+ throw new LocalCapabilityPolicyError("local_capability_env_denied", "Custom environment variables are not allowed by minimal environment policy.");
219
+ }
220
+ if (policy.denied_executables?.includes(request.executable)) {
221
+ throw new LocalCapabilityPolicyError("local_capability_executable_denied", `Executable '${request.executable}' is denied by policy.`);
222
+ }
223
+ if (policy.allowed_executables && !policy.allowed_executables.includes(request.executable)) {
224
+ throw new LocalCapabilityPolicyError("local_capability_executable_not_allowed", `Executable '${request.executable}' is not allowed by policy.`);
225
+ }
226
+ if (policy.argv_patterns && !argvMatchesPolicy(request.argv, policy.argv_patterns)) {
227
+ throw new LocalCapabilityPolicyError("local_capability_argv_denied", `Command arguments do not match policy.`);
228
+ }
229
+ if (policy.cwd_policy === "selected_workspace_only") {
230
+ await assertPathInsideWorkspace(request.cwd, request.workspace_root);
231
+ }
232
+ }
233
+ function filesystemScopeForAction(action) {
234
+ return action === "read" || action === "list" ? "workspace_read" : "workspace_write";
235
+ }
236
+ function gitScopeForAction(action) {
237
+ return action === "status" || action === "diff" || action === "branch" || action === "commit_metadata"
238
+ ? "workspace_read"
239
+ : "workspace_write";
240
+ }
241
+ function argvMatchesPolicy(argv, patterns) {
242
+ const commandLine = argv.join(" ");
243
+ return patterns.some((pattern) => {
244
+ try {
245
+ return new RegExp(pattern).test(commandLine);
246
+ }
247
+ catch (error) {
248
+ if (error instanceof SyntaxError) {
249
+ throw new LocalCapabilityPolicyError("local_capability_command_policy_invalid", `Command policy argv pattern '${pattern}' is invalid: ${error.message}`);
250
+ }
251
+ throw error;
252
+ }
253
+ });
254
+ }
255
+ async function assertPathInsideWorkspace(path, workspaceRoot) {
256
+ const resolvedPath = await realpathForPolicy(path);
257
+ const resolvedWorkspace = await realpathForPolicy(workspaceRoot);
258
+ const pathFromWorkspace = relative(resolvedWorkspace, resolvedPath);
259
+ if (pathFromWorkspace === "" || (!pathFromWorkspace.startsWith("..") && !isAbsolute(pathFromWorkspace))) {
260
+ return;
261
+ }
262
+ throw new LocalCapabilityPolicyError("local_capability_cwd_denied", `Path '${path}' is outside the selected workspace.`);
263
+ }
264
+ async function realpathForPolicy(path) {
265
+ try {
266
+ return await realpath(path);
267
+ }
268
+ catch (error) {
269
+ if (error instanceof Error) {
270
+ throw new LocalCapabilityPolicyError("local_capability_path_unresolved", `Path '${path}' could not be resolved: ${error.message}`);
271
+ }
272
+ throw error;
273
+ }
274
+ }
275
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,6 @@
1
+ export type RunnerLogger = {
2
+ info(message: string): void;
3
+ error(message: string): void;
4
+ };
5
+ export declare const consoleLogger: RunnerLogger;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ export const consoleLogger = {
2
+ info(message) {
3
+ console.log(message);
4
+ },
5
+ error(message) {
6
+ console.error(message);
7
+ },
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,111 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client";
2
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { HcpEventType, StreamableHttpMcpServerAttachment } from "@harness-control/protocol";
4
+ export type McpAttachmentEvent = {
5
+ event_type: HcpEventType;
6
+ data: Record<string, unknown>;
7
+ };
8
+ export type McpAttachmentEventSink = (event: McpAttachmentEvent) => void | Promise<void>;
9
+ export type McpToolCallArguments = Record<string, unknown>;
10
+ type FetchLike = (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => ReturnType<typeof fetch>;
11
+ export type McpToolDescriptor = {
12
+ name: string;
13
+ description?: string;
14
+ input_schema: Record<string, unknown>;
15
+ output_schema?: Record<string, unknown>;
16
+ };
17
+ export type McpToolCallResult = {
18
+ content?: unknown[];
19
+ structured_content?: Record<string, unknown>;
20
+ is_error: boolean;
21
+ };
22
+ export declare class McpToolPolicyError extends Error {
23
+ readonly attachmentName: string;
24
+ readonly toolName: string;
25
+ constructor(attachmentName: string, toolName: string, message: string);
26
+ }
27
+ export declare class McpAttachmentExpiredError extends Error {
28
+ readonly attachmentName: string;
29
+ constructor(attachmentName: string);
30
+ }
31
+ export declare class McpProofBindingError extends Error {
32
+ readonly attachmentName: string;
33
+ constructor(attachmentName: string, message: string);
34
+ }
35
+ export type McpProofContext = {
36
+ session_id: string;
37
+ host_id: string;
38
+ provider_instance_id: string;
39
+ workspace_id: string;
40
+ server_id?: string;
41
+ turn_id?: string;
42
+ };
43
+ export type McpProofSigningInput = {
44
+ key_id: string;
45
+ method: string;
46
+ url: string;
47
+ body_hash: string;
48
+ lease_id: string;
49
+ session_id: string;
50
+ host_id: string;
51
+ provider_instance_id: string;
52
+ workspace_id: string;
53
+ server_id: string;
54
+ turn_id?: string;
55
+ timestamp: string;
56
+ nonce: string;
57
+ };
58
+ export type McpProofSigner = (input: McpProofSigningInput) => string;
59
+ type SdkToolClient = {
60
+ connect(transport: unknown): Promise<void>;
61
+ listTools(): Promise<{
62
+ tools: Tool[];
63
+ }>;
64
+ callTool(params: {
65
+ name: string;
66
+ arguments?: McpToolCallArguments;
67
+ }): Promise<SdkToolCallResult>;
68
+ close(): Promise<void>;
69
+ };
70
+ type SdkToolCallResult = Awaited<ReturnType<Client["callTool"]>>;
71
+ type McpSdkFactory = {
72
+ createClient(): SdkToolClient;
73
+ createStreamableHttpTransport(attachment: StreamableHttpMcpServerAttachment, options: {
74
+ fetch: FetchLike;
75
+ }): unknown;
76
+ };
77
+ export type McpAttachmentClientOptions = {
78
+ eventSink?: McpAttachmentEventSink;
79
+ sdkFactory?: McpSdkFactory;
80
+ now?: () => Date;
81
+ proofContext?: McpProofContext;
82
+ proofSigner?: McpProofSigner;
83
+ };
84
+ export declare class McpAttachmentClient {
85
+ private readonly attachment;
86
+ private readonly allowedTools;
87
+ private readonly deniedTools;
88
+ private readonly eventSink;
89
+ private readonly sdkFactory;
90
+ private readonly now;
91
+ private readonly proofContext;
92
+ private readonly proofSigner;
93
+ private readonly hasProofSigner;
94
+ private client;
95
+ private connected;
96
+ constructor(attachment: StreamableHttpMcpServerAttachment, options?: McpAttachmentClientOptions);
97
+ connect(): Promise<void>;
98
+ listTools(): Promise<McpToolDescriptor[]>;
99
+ callTool(name: string, arguments_?: McpToolCallArguments): Promise<McpToolCallResult>;
100
+ close(): Promise<void>;
101
+ isToolAllowed(toolName: string): boolean;
102
+ private assertToolAllowed;
103
+ private requireConnectedClient;
104
+ private emitEvent;
105
+ private assertNotExpired;
106
+ private assertProofBindingConfigured;
107
+ private createProofFetch;
108
+ }
109
+ export declare function createDevelopmentHmacProofSigner(secret: string): McpProofSigner;
110
+ export {};
111
+ //# sourceMappingURL=McpAttachmentClient.d.ts.map