Skip to content

Commit e230e5a

Browse files
chore: sync upstream main
2 parents bd04910 + 9ddd561 commit e230e5a

30 files changed

Lines changed: 5613 additions & 32 deletions

docs/runtime-api.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,39 @@ keep `GET` SSE streams open.
4545
The MCP server exposes a small discovery-oriented tool set:
4646

4747
- `list_apps`
48+
- `list_connections`
4849
- `search_actions`
4950
- `get_action_guide`
5051
- `execute_action`
5152

53+
Use `list_connections` to discover configured accounts before selecting one. Both
54+
`get_action_guide` and `execute_action` accept an optional `connectionName`:
55+
56+
`get_action_guide` request:
57+
58+
```json
59+
{
60+
"actionId": "example.get_record",
61+
"connectionName": "secondary"
62+
}
63+
```
64+
65+
`execute_action` request:
66+
67+
```json
68+
{
69+
"actionId": "example.get_record",
70+
"connectionName": "secondary",
71+
"input": {
72+
"recordId": "record-123"
73+
}
74+
}
75+
```
76+
77+
Omitting `connectionName` uses the `default` connection. A requested named connection must exist;
78+
the runtime does not silently fall back to another account. Connection results expose only safe
79+
account identity fields and never include stored credentials.
80+
5281
Preview MCP tool metadata:
5382

5483
```bash

examples/aliyun-sls-query-logs.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import type { ExecutionContext, ResolvedCredential } from "../src/core/types.ts";
2+
3+
import { executors } from "../src/providers/aliyun_sls/executors.ts";
4+
import { parseAliyunSlsCredential, resolveAliyunSlsLogstoreTarget } from "../src/providers/aliyun_sls/resources.ts";
5+
6+
const requiredEnvironment = [
7+
"ALIYUN_SLS_ACCESS_KEY_ID",
8+
"ALIYUN_SLS_ACCESS_KEY_SECRET",
9+
"ALIYUN_SLS_ENDPOINT",
10+
] as const;
11+
12+
async function main(): Promise<void> {
13+
const missing = requiredEnvironment.filter((name) => !process.env[name]?.trim());
14+
if (missing.length > 0) {
15+
console.log(`Skip Alibaba Cloud SLS example: missing ${missing.join(", ")}.`);
16+
return;
17+
}
18+
19+
const values: Record<string, string> = {
20+
accessKeyId: process.env.ALIYUN_SLS_ACCESS_KEY_ID!,
21+
accessKeySecret: process.env.ALIYUN_SLS_ACCESS_KEY_SECRET!,
22+
endpoint: process.env.ALIYUN_SLS_ENDPOINT!,
23+
};
24+
if (process.env.ALIYUN_SLS_SECURITY_TOKEN?.trim()) {
25+
values.securityToken = process.env.ALIYUN_SLS_SECURITY_TOKEN;
26+
}
27+
if (process.env.ALIYUN_SLS_RESOURCE_SCOPE?.trim()) {
28+
values.resourceScope = process.env.ALIYUN_SLS_RESOURCE_SCOPE;
29+
}
30+
31+
const credential = parseAliyunSlsCredential(values);
32+
let target;
33+
try {
34+
target = resolveAliyunSlsLogstoreTarget(
35+
credential,
36+
undefined,
37+
process.env.ALIYUN_SLS_PROJECT,
38+
process.env.ALIYUN_SLS_LOGSTORE,
39+
);
40+
} catch {
41+
console.log(
42+
"Skip Alibaba Cloud SLS example: set ALIYUN_SLS_PROJECT and ALIYUN_SLS_LOGSTORE, or configure resourceScope with exactly one candidate Project and Logstore.",
43+
);
44+
return;
45+
}
46+
47+
const resolvedCredential: ResolvedCredential = {
48+
authType: "custom_credential",
49+
values,
50+
profile: {
51+
accountId: credential.accessKeyId,
52+
displayName: `${credential.accessKeyId}@${credential.endpoint}`,
53+
grantedScopes: [],
54+
},
55+
metadata: {},
56+
};
57+
const context: ExecutionContext = {
58+
async getCredential(service) {
59+
return service === "aliyun_sls" ? resolvedCredential : undefined;
60+
},
61+
};
62+
63+
const to = Math.floor(Date.now() / 1000);
64+
const result = await executors["aliyun_sls.query_logs"]!(
65+
{
66+
endpoint: target.endpoint,
67+
project: target.project,
68+
logstore: target.logstore,
69+
from: to - 900,
70+
to,
71+
query: process.env.ALIYUN_SLS_QUERY ?? "*",
72+
line: 100,
73+
reverse: true,
74+
},
75+
context,
76+
);
77+
console.log(JSON.stringify(result, null, 2));
78+
if (!result.ok) process.exitCode = 1;
79+
}
80+
81+
await main();

src/core/guarded-fetch.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ describe("createGuardedFetch redirects", () => {
210210
"x-api-key": "provider-secret",
211211
"x-auth-token": "tok",
212212
"x-seq-apikey": "seq-secret",
213+
"x-acs-security-token": "aliyun-sts-secret",
213214
"x-trace": "keep",
214215
// Look-alike but non-credential headers must survive cross-origin.
215216
"idempotency-key": "abc",
@@ -221,12 +222,14 @@ describe("createGuardedFetch redirects", () => {
221222
expect(sameOriginHeaders.get("authorization")).toBe("Bearer secret");
222223
expect(sameOriginHeaders.get("x-api-key")).toBe("provider-secret");
223224
expect(sameOriginHeaders.get("x-seq-apikey")).toBe("seq-secret");
225+
expect(sameOriginHeaders.get("x-acs-security-token")).toBe("aliyun-sts-secret");
224226
const crossOriginHeaders = new Headers(calls[2]?.init?.headers);
225227
expect(crossOriginHeaders.has("authorization")).toBe(false);
226228
expect(crossOriginHeaders.has("cookie")).toBe(false);
227229
expect(crossOriginHeaders.has("x-api-key")).toBe(false);
228230
expect(crossOriginHeaders.has("x-auth-token")).toBe(false);
229231
expect(crossOriginHeaders.has("x-seq-apikey")).toBe(false);
232+
expect(crossOriginHeaders.has("x-acs-security-token")).toBe(false);
230233
expect(crossOriginHeaders.get("x-trace")).toBe("keep");
231234
expect(crossOriginHeaders.get("idempotency-key")).toBe("abc");
232235
expect(crossOriginHeaders.get("x-correlation-id")).toBe("cid");

src/core/guarded-fetch.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const crossOriginCredentialHeaders = new Set([
9494
"x-csrf-token",
9595
"x-xsrf-token",
9696
"x-goog-api-key",
97+
"x-acs-security-token",
9798
"x-amz-security-token",
9899
]);
99100
/** Body-describing headers dropped when a redirect rewrites the method to GET, mirroring the fetch spec. */

0 commit comments

Comments
 (0)