@aipermission/mcp 0.2.54 → 0.2.56
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 +12 -6
- package/dist/config.js +1 -1
- package/dist/generated-connector-contract.js +27 -0
- package/dist/init.js +25 -14
- package/dist/resources/aipermission-operator/SKILL.md +8 -3
- package/dist/response-contracts.js +81 -33
- package/dist/results.js +13 -2
- package/dist/server.js +9 -9
- package/dist/vault-tools.js +7 -2
- package/package.json +3 -3
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ does this automatically.
|
|
|
86
86
|
## Tools
|
|
87
87
|
|
|
88
88
|
`AIPERMISSION_HTTP_TIMEOUT_MS` sets the gateway request deadline (default:
|
|
89
|
-
|
|
89
|
+
95000 milliseconds; maximum: 600000). The value must be a positive base-10
|
|
90
90
|
integer; invalid configuration stops the bridge instead of silently changing
|
|
91
91
|
the deadline. It covers both response headers and the complete response body,
|
|
92
92
|
including streamed bodies. A timeout does not prove that a submitted
|
|
@@ -228,12 +228,18 @@ disclose secrets. Never automatically retry `submission_unknown`.
|
|
|
228
228
|
|
|
229
229
|
Connector responses can include `approval_pending` or `running`. Poll
|
|
230
230
|
`get_connector_action_request(request_id)` until the request reaches a terminal
|
|
231
|
-
status.
|
|
232
|
-
|
|
231
|
+
status. Failed action calls carry the MCP `isError` flag; reading a recorded
|
|
232
|
+
failed request is a successful read and does not. A `stopped` call response is a
|
|
233
|
+
gateway control result, not a recorded request. `outcome_unknown` is terminal
|
|
234
|
+
and means the gateway could not prove the remote outcome after interruption;
|
|
235
|
+
inspect target state or ask the operator
|
|
233
236
|
before retrying. Gateway API errors with that status retain their request id,
|
|
234
|
-
assistant hint, and bounded retry delay in the MCP error envelope.
|
|
235
|
-
responses
|
|
236
|
-
temporary paths, archive staging paths, or local upload contents.
|
|
237
|
+
assistant hint, and bounded retry delay in the MCP error envelope. File-transfer
|
|
238
|
+
queue and status responses do not include transferred file bytes, gateway
|
|
239
|
+
temporary paths, archive staging paths, or local upload contents. Explicitly
|
|
240
|
+
authorized connector read actions may return bounded content, such as S3
|
|
241
|
+
`download_object` `content_base64` or SSH command output; treat it as sensitive
|
|
242
|
+
target data.
|
|
237
243
|
|
|
238
244
|
## Operator Skill
|
|
239
245
|
|
package/dist/config.js
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Code generated by backend/cmd/openapi. DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
export const connectorActionStatuses = Object.freeze([
|
|
4
|
+
"completed",
|
|
5
|
+
"failed",
|
|
6
|
+
"canceled",
|
|
7
|
+
"running",
|
|
8
|
+
"approval_pending",
|
|
9
|
+
"blocked",
|
|
10
|
+
"stale",
|
|
11
|
+
"declined",
|
|
12
|
+
"error",
|
|
13
|
+
"outcome_unknown",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
export const connectorRetryClasses = Object.freeze(["read_only", "idempotent", "conditional", "non_idempotent"]);
|
|
17
|
+
|
|
18
|
+
export const executionRules = Object.freeze(["always_run", "approval_required", "blocked"]);
|
|
19
|
+
|
|
20
|
+
export const connectorActionResponseRequiredFields = Object.freeze([
|
|
21
|
+
"status",
|
|
22
|
+
"request_id",
|
|
23
|
+
"target_ref",
|
|
24
|
+
"connector_kind",
|
|
25
|
+
"action_name",
|
|
26
|
+
"retry_policy",
|
|
27
|
+
]);
|
package/dist/init.js
CHANGED
|
@@ -609,29 +609,40 @@ function removeTOMLServer(source, name) {
|
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
function scanTOMLHeader(line, state) {
|
|
612
|
-
if (state.multiline) {
|
|
613
|
-
if (hasMultilineDelimiter(line, state.multiline)) state.multiline = "";
|
|
614
|
-
return null;
|
|
615
|
-
}
|
|
616
612
|
const trimmed = line.trimStart();
|
|
617
|
-
if (trimmed.startsWith("[")) {
|
|
613
|
+
if (!state.multiline && trimmed.startsWith("[")) {
|
|
618
614
|
try {
|
|
619
615
|
return findMarkerPath(parseTOML(`${line}\n__aipermission_header_marker = true\n`));
|
|
620
616
|
} catch {
|
|
621
|
-
|
|
617
|
+
// A string can start with a bracket; scan it before the next line.
|
|
622
618
|
}
|
|
623
619
|
}
|
|
624
|
-
|
|
625
|
-
if (!hasMultilineDelimiter(line, delimiter)) continue;
|
|
626
|
-
if ((line.split(delimiter).length - 1) % 2 === 1) state.multiline = delimiter;
|
|
627
|
-
break;
|
|
628
|
-
}
|
|
620
|
+
scanTOMLStrings(line, state);
|
|
629
621
|
return null;
|
|
630
622
|
}
|
|
631
623
|
|
|
632
|
-
function
|
|
633
|
-
|
|
634
|
-
|
|
624
|
+
function scanTOMLStrings(line, state) {
|
|
625
|
+
let quote = state.multiline;
|
|
626
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
627
|
+
const character = line[index];
|
|
628
|
+
if (!quote && character === "#") break;
|
|
629
|
+
if (quote.startsWith('"') && character === "\\") {
|
|
630
|
+
index += 1;
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (quote) {
|
|
634
|
+
if (line.startsWith(quote, index)) {
|
|
635
|
+
index += quote.length - 1;
|
|
636
|
+
quote = "";
|
|
637
|
+
}
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (character !== '"' && character !== "'") continue;
|
|
641
|
+
const triple = character.repeat(3);
|
|
642
|
+
quote = line.startsWith(triple, index) ? triple : character;
|
|
643
|
+
index += quote.length - 1;
|
|
644
|
+
}
|
|
645
|
+
state.multiline = quote.length === 3 ? quote : "";
|
|
635
646
|
}
|
|
636
647
|
|
|
637
648
|
function findMarkerPath(value, pathParts = []) {
|
|
@@ -113,6 +113,7 @@ Terminal statuses:
|
|
|
113
113
|
```text
|
|
114
114
|
completed
|
|
115
115
|
failed
|
|
116
|
+
canceled
|
|
116
117
|
declined
|
|
117
118
|
blocked
|
|
118
119
|
error
|
|
@@ -193,8 +194,11 @@ files or inspect remote paths. Prefer the smallest explicit path set. Do not use
|
|
|
193
194
|
globs, recursive copy, or directory transfer unless a connector action
|
|
194
195
|
explicitly supports that behavior.
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
staging paths, or local upload contents.
|
|
197
|
+
File-transfer queue and status responses do not include transferred file bytes,
|
|
198
|
+
gateway temp paths, archive staging paths, or local upload contents. Explicitly
|
|
199
|
+
authorized connector read actions may return bounded content, such as S3
|
|
200
|
+
`download_object` `content_base64` or SSH command output; treat it as sensitive
|
|
201
|
+
target data.
|
|
198
202
|
|
|
199
203
|
## S3/Object Storage Practice
|
|
200
204
|
|
|
@@ -259,7 +263,8 @@ the operator how to rotate or redact it.
|
|
|
259
263
|
Use Project Vault only through its dedicated tools:
|
|
260
264
|
|
|
261
265
|
1. Call `list_vault_items(project_ref)` to discover names and non-secret
|
|
262
|
-
metadata.
|
|
266
|
+
metadata. Prefer an explicit `id:<id>` or `slug:<slug>` reference. Never ask
|
|
267
|
+
the gateway to reveal values.
|
|
263
268
|
2. Use `call_vault_action` with `generate_item` only when the operator asked for
|
|
264
269
|
a new secret. Use a stable, unique `idempotency_key`. Send `tags` as a string
|
|
265
270
|
array, `shared_project_ids` as an integer array, and `usage_notes` as an
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { connectorActionStatuses, connectorRetryClasses } from "./generated-connector-contract.js";
|
|
2
3
|
|
|
3
4
|
const positiveID = z.number().int().positive();
|
|
4
5
|
const nonNegativeInteger = z.number().int().nonnegative();
|
|
@@ -97,7 +98,7 @@ const outputHintSchema = z
|
|
|
97
98
|
.strict();
|
|
98
99
|
const retryPolicySchema = z
|
|
99
100
|
.object({
|
|
100
|
-
class: z.
|
|
101
|
+
class: z.enum([...connectorRetryClasses]),
|
|
101
102
|
precondition_fields: z.array(z.string()).optional(),
|
|
102
103
|
guidance: z.string(),
|
|
103
104
|
})
|
|
@@ -119,28 +120,39 @@ const actionDefinitionSchema = z
|
|
|
119
120
|
|
|
120
121
|
const connectorActionsSchema = z.object({ items: z.array(actionDefinitionSchema) }).strict();
|
|
121
122
|
|
|
122
|
-
const
|
|
123
|
+
const connectorActionRequestSchema = z
|
|
123
124
|
.object({
|
|
124
|
-
status: z.
|
|
125
|
-
request_id: positiveID
|
|
126
|
-
target_ref: z.string()
|
|
125
|
+
status: z.enum([...connectorActionStatuses]),
|
|
126
|
+
request_id: positiveID,
|
|
127
|
+
target_ref: z.string(),
|
|
127
128
|
target_name: z.string().optional(),
|
|
128
|
-
connector_kind: z.string()
|
|
129
|
+
connector_kind: z.string(),
|
|
129
130
|
profile_label: z.string().optional(),
|
|
130
|
-
action_name: z.string()
|
|
131
|
+
action_name: z.string(),
|
|
131
132
|
input: z.record(z.unknown()).optional(),
|
|
132
133
|
// Connector-owned output is intentionally opaque. The gateway credential
|
|
133
134
|
// boundary redacts values; this schema owns only the shared MCP envelope.
|
|
134
135
|
output: z.unknown().optional(),
|
|
135
136
|
display_text: z.string().optional(),
|
|
136
137
|
error: z.string().optional(),
|
|
137
|
-
retry_policy: retryPolicySchema
|
|
138
|
-
retry_after_seconds: nonNegativeInteger.optional(),
|
|
138
|
+
retry_policy: retryPolicySchema,
|
|
139
|
+
retry_after_seconds: nonNegativeInteger.max(3600).optional(),
|
|
139
140
|
assistant_hint: z.string().optional(),
|
|
140
141
|
output_withheld: z.boolean().optional(),
|
|
141
142
|
replayed: z.boolean().optional(),
|
|
142
143
|
})
|
|
143
|
-
.strict()
|
|
144
|
+
.strict()
|
|
145
|
+
.superRefine((value, context) => {
|
|
146
|
+
if (value.output_withheld) {
|
|
147
|
+
if (value.input !== undefined || value.output !== undefined || value.display_text !== undefined || value.error !== undefined) {
|
|
148
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "withheld action output must not contain request or result content" });
|
|
149
|
+
}
|
|
150
|
+
} else if (!value.target_ref || !value.connector_kind || !value.action_name) {
|
|
151
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "action response identity is required" });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
const connectorActionStoppedSchema = z.object({ status: z.literal("stopped"), error: z.string().min(1) }).strict();
|
|
155
|
+
const connectorActionCallSchema = z.union([connectorActionRequestSchema, connectorActionStoppedSchema]);
|
|
144
156
|
|
|
145
157
|
const vaultItemSchema = z
|
|
146
158
|
.object({
|
|
@@ -225,40 +237,76 @@ const vaultSessionOutputSchema = z
|
|
|
225
237
|
})
|
|
226
238
|
.strict();
|
|
227
239
|
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
const vaultActionStatuses = ["approval_pending", "running", "completed", "failed", "declined", "stale", "canceled", "expired"];
|
|
241
|
+
const vaultActionRecordedShape = {
|
|
242
|
+
status: z.enum(vaultActionStatuses),
|
|
243
|
+
request_id: positiveID,
|
|
244
|
+
project_ref: z.string().min(1),
|
|
245
|
+
reason: z.string().optional(),
|
|
246
|
+
created_at: z.string().optional(),
|
|
247
|
+
expires_at: z.string().optional(),
|
|
248
|
+
secret_values_returned: z.literal(false),
|
|
249
|
+
output_withheld: z.literal(true).optional(),
|
|
250
|
+
retry_after_seconds: nonNegativeInteger.max(3600).optional(),
|
|
251
|
+
assistant_hint: z.string().optional(),
|
|
252
|
+
error: z.string().optional(),
|
|
253
|
+
};
|
|
254
|
+
const vaultActionRecordedSchema = z
|
|
255
|
+
.discriminatedUnion("action_name", [
|
|
256
|
+
z
|
|
257
|
+
.object({
|
|
258
|
+
...vaultActionRecordedShape,
|
|
259
|
+
action_name: z.literal("generate_item"),
|
|
260
|
+
input: vaultGenerateInputSchema.optional(),
|
|
261
|
+
output: generatedVaultOutputSchema.optional(),
|
|
262
|
+
})
|
|
263
|
+
.strict(),
|
|
264
|
+
z
|
|
265
|
+
.object({
|
|
266
|
+
...vaultActionRecordedShape,
|
|
267
|
+
action_name: z.literal("restart_session_with_environment"),
|
|
268
|
+
input: vaultSessionInputSchema.optional(),
|
|
269
|
+
output: vaultSessionOutputSchema.optional(),
|
|
270
|
+
})
|
|
271
|
+
.strict(),
|
|
272
|
+
])
|
|
273
|
+
.superRefine((value, context) => {
|
|
274
|
+
if (value.output_withheld && value.output !== undefined) {
|
|
275
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "withheld Vault output must not contain result content" });
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
const vaultActionStoppedSchema = z.object({ status: z.literal("stopped"), error: z.string().min(1) }).strict();
|
|
279
|
+
const vaultActionResponseSchema = z.union([vaultActionRecordedSchema, vaultActionStoppedSchema]);
|
|
246
280
|
|
|
247
281
|
export const responseContracts = Object.freeze({
|
|
248
282
|
connectorTargets: z.array(connectorTargetSchema),
|
|
249
283
|
connectorHelp: connectorHelpSchema,
|
|
250
284
|
connectorActions: connectorActionsSchema,
|
|
251
|
-
|
|
285
|
+
connectorActionCall: connectorActionCallSchema,
|
|
286
|
+
connectorActionRequest: connectorActionRequestSchema,
|
|
252
287
|
vaultItems: vaultItemsSchema,
|
|
253
288
|
vaultAction: vaultActionResponseSchema,
|
|
254
289
|
});
|
|
255
290
|
|
|
256
|
-
export function projectGatewaySuccess(schema, value) {
|
|
291
|
+
export function projectGatewaySuccess(schema, value, expected = undefined) {
|
|
257
292
|
const result = schema.safeParse(value);
|
|
258
293
|
if (!result.success) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
294
|
+
throw gatewayContractError();
|
|
295
|
+
}
|
|
296
|
+
if (expected && result.data?.status !== "stopped") {
|
|
297
|
+
for (const [field, expectedValue] of Object.entries(expected)) {
|
|
298
|
+
if (expectedValue !== undefined && result.data?.[field] !== expectedValue) {
|
|
299
|
+
throw gatewayContractError();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
} else if (expected && (expected.request_id !== undefined || expected.status !== undefined)) {
|
|
303
|
+
throw gatewayContractError();
|
|
262
304
|
}
|
|
263
305
|
return result.data;
|
|
264
306
|
}
|
|
307
|
+
|
|
308
|
+
function gatewayContractError() {
|
|
309
|
+
const error = new Error("Gateway success response failed MCP contract validation.");
|
|
310
|
+
error.code = "gateway_response_contract_invalid";
|
|
311
|
+
return error;
|
|
312
|
+
}
|
package/dist/results.js
CHANGED
|
@@ -45,7 +45,7 @@ export function errorResult(error) {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export async function jsonToolResult(callback, project, mutationContext = null) {
|
|
48
|
+
export async function jsonToolResult(callback, project, mutationContext = null, isFailure = () => false) {
|
|
49
49
|
if (typeof project !== "function") {
|
|
50
50
|
return errorResult(new Error("MCP tool result projector is required."));
|
|
51
51
|
}
|
|
@@ -56,12 +56,23 @@ export async function jsonToolResult(callback, project, mutationContext = null)
|
|
|
56
56
|
return errorResult(error);
|
|
57
57
|
}
|
|
58
58
|
try {
|
|
59
|
-
|
|
59
|
+
const projected = project(value);
|
|
60
|
+
const result = textResult(projected);
|
|
61
|
+
return isFailure(projected) ? { ...result, isError: true } : result;
|
|
60
62
|
} catch (error) {
|
|
61
63
|
return errorResult(mutationContext ? projectionOutcomeUnknown(error, mutationContext) : error);
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
export function jsonActionToolResult(callback, project, mutationContext) {
|
|
68
|
+
return jsonToolResult(
|
|
69
|
+
callback,
|
|
70
|
+
project,
|
|
71
|
+
mutationContext,
|
|
72
|
+
(value) => !["completed", "approval_pending", "running"].includes(value.status),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
function projectionOutcomeUnknown(cause, context) {
|
|
66
77
|
const error = new Error(
|
|
67
78
|
"The gateway accepted the mutation, but its response failed MCP contract validation. The operation may have completed.",
|
package/dist/server.js
CHANGED
|
@@ -17,7 +17,7 @@ import { parseHTTPTimeout } from "./config.js";
|
|
|
17
17
|
import { idempotencyKeySchema } from "./idempotency-key.js";
|
|
18
18
|
import { normalizeLocalAPIURL } from "./local-url.js";
|
|
19
19
|
import { projectGatewaySuccess, responseContracts } from "./response-contracts.js";
|
|
20
|
-
import { jsonToolResult } from "./results.js";
|
|
20
|
+
import { jsonActionToolResult, jsonToolResult } from "./results.js";
|
|
21
21
|
import { externalActionAnnotations, localMutationAnnotations, localReadAnnotations } from "./tool-annotations.js";
|
|
22
22
|
|
|
23
23
|
const packageMetadata = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
@@ -100,7 +100,7 @@ server.tool(
|
|
|
100
100
|
},
|
|
101
101
|
externalActionAnnotations,
|
|
102
102
|
async ({ target_ref, action_name, input, reason, idempotency_key }, { signal }) => {
|
|
103
|
-
return
|
|
103
|
+
return jsonActionToolResult(
|
|
104
104
|
() =>
|
|
105
105
|
apiPost(
|
|
106
106
|
"/api/mcp/connector-actions/call",
|
|
@@ -113,7 +113,7 @@ server.tool(
|
|
|
113
113
|
},
|
|
114
114
|
{ signal },
|
|
115
115
|
),
|
|
116
|
-
(value) => projectGatewaySuccess(responseContracts.
|
|
116
|
+
(value) => projectGatewaySuccess(responseContracts.connectorActionCall, value, { target_ref, action_name }),
|
|
117
117
|
{ idempotencyKey: idempotency_key },
|
|
118
118
|
);
|
|
119
119
|
},
|
|
@@ -129,7 +129,7 @@ server.tool(
|
|
|
129
129
|
async ({ request_id }, { signal }) => {
|
|
130
130
|
return jsonToolResult(
|
|
131
131
|
() => apiGet(`/api/mcp/connector-action-requests/${request_id}`, { signal }),
|
|
132
|
-
(value) => projectGatewaySuccess(responseContracts.
|
|
132
|
+
(value) => projectGatewaySuccess(responseContracts.connectorActionRequest, value, { request_id }),
|
|
133
133
|
);
|
|
134
134
|
},
|
|
135
135
|
);
|
|
@@ -154,11 +154,11 @@ server.tool(
|
|
|
154
154
|
|
|
155
155
|
server.tool(
|
|
156
156
|
"call_vault_action",
|
|
157
|
-
"Run a Vault action under the configured project capability. Prompt waits for local approval; Always executes immediately through the same tracked request path. generate_item input accepts name, secret_type, generator_kind, provider, environment, description, expires_at, expiry_warning_days, tags (string array), usage_notes (array of {location, notes}), and shared_project_ids (integer array). restart_session_with_environment input requires target_ref and items with item_id, source_project_id, and optional replace_existing. Never include raw secret values.",
|
|
157
|
+
"Run a Vault action under the configured project capability. Prompt waits for local approval; Always executes immediately through the same tracked request path. generate_item input accepts name, optional secret_type (defaults to generic_secret), generator_kind, provider, environment, description, expires_at, expiry_warning_days, tags (string array), usage_notes (array of {location, notes}), and shared_project_ids (integer array). restart_session_with_environment input requires target_ref and items with item_id, source_project_id, and optional replace_existing. Never include raw secret values.",
|
|
158
158
|
callVaultActionSchema,
|
|
159
159
|
externalActionAnnotations,
|
|
160
160
|
async ({ project_ref, action_name, input, reason, idempotency_key }, { signal }) => {
|
|
161
|
-
return
|
|
161
|
+
return jsonActionToolResult(
|
|
162
162
|
() =>
|
|
163
163
|
apiPost(
|
|
164
164
|
"/api/mcp/vault-actions/call",
|
|
@@ -171,7 +171,7 @@ server.tool(
|
|
|
171
171
|
},
|
|
172
172
|
{ signal },
|
|
173
173
|
),
|
|
174
|
-
(value) => projectGatewaySuccess(responseContracts.vaultAction, value),
|
|
174
|
+
(value) => projectGatewaySuccess(responseContracts.vaultAction, value, { project_ref, action_name }),
|
|
175
175
|
{ idempotencyKey: idempotency_key },
|
|
176
176
|
);
|
|
177
177
|
},
|
|
@@ -185,7 +185,7 @@ server.tool(
|
|
|
185
185
|
async ({ request_id }, { signal }) => {
|
|
186
186
|
return jsonToolResult(
|
|
187
187
|
() => apiGet(`/api/mcp/vault-action-requests/${request_id}`, { signal }),
|
|
188
|
-
(value) => projectGatewaySuccess(responseContracts.vaultAction, value),
|
|
188
|
+
(value) => projectGatewaySuccess(responseContracts.vaultAction, value, { request_id }),
|
|
189
189
|
);
|
|
190
190
|
},
|
|
191
191
|
);
|
|
@@ -198,7 +198,7 @@ server.tool(
|
|
|
198
198
|
async ({ request_id }, { signal }) => {
|
|
199
199
|
return jsonToolResult(
|
|
200
200
|
() => apiPost(`/api/mcp/vault-action-requests/${request_id}/cancel`, {}, { requestID: request_id, signal }),
|
|
201
|
-
(value) => projectGatewaySuccess(responseContracts.vaultAction, value),
|
|
201
|
+
(value) => projectGatewaySuccess(responseContracts.vaultAction, value, { request_id, status: "canceled" }),
|
|
202
202
|
{ requestID: request_id },
|
|
203
203
|
);
|
|
204
204
|
},
|
package/dist/vault-tools.js
CHANGED
|
@@ -2,11 +2,16 @@ import { z } from "zod";
|
|
|
2
2
|
import { idempotencyKeySchema } from "./idempotency-key.js";
|
|
3
3
|
|
|
4
4
|
export const listVaultItemsSchema = {
|
|
5
|
-
project_ref: z
|
|
5
|
+
project_ref: z
|
|
6
|
+
.string()
|
|
7
|
+
.trim()
|
|
8
|
+
.min(1)
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Optional project reference. Prefer id:<id> or slug:<slug>; omit to list every readable project."),
|
|
6
11
|
};
|
|
7
12
|
|
|
8
13
|
export const callVaultActionSchema = {
|
|
9
|
-
project_ref: z.string().min(1).describe("Owning project id or slug
|
|
14
|
+
project_ref: z.string().trim().min(1).describe("Owning project reference. Prefer id:<id> or slug:<slug>."),
|
|
10
15
|
action_name: z.enum(["generate_item", "restart_session_with_environment"]),
|
|
11
16
|
input: z.record(z.unknown()).describe("Action input. Never include raw secret values."),
|
|
12
17
|
reason: z.string().min(1).describe("Why this Vault action is needed."),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aipermission/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.56",
|
|
4
4
|
"mcpName": "io.github.aipermission/aipermission-mcp",
|
|
5
5
|
"description": "Local-only MCP bridge for the aipermission gateway.",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
53
53
|
"smol-toml": "1.8.0",
|
|
54
|
-
"yaml": "2.9.
|
|
54
|
+
"yaml": "2.9.1",
|
|
55
55
|
"zod": "3.25.76"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@eslint/js": "^10.0.1",
|
|
59
59
|
"eslint": "^10.10.0",
|
|
60
60
|
"globals": "^17.11.0",
|
|
61
|
-
"prettier": "^3.9.
|
|
61
|
+
"prettier": "^3.9.8"
|
|
62
62
|
}
|
|
63
63
|
}
|
package/server.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"name": "io.github.aipermission/aipermission-mcp",
|
|
4
4
|
"title": "AIPermission",
|
|
5
5
|
"description": "Local-only MCP bridge for the AIPermission gateway.",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.56",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "@aipermission/mcp",
|
|
11
|
-
"version": "0.2.
|
|
11
|
+
"version": "0.2.56",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|