@aws/agentcore 0.3.0-preview.2.0 → 0.3.0-preview.3.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.
- package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +486 -133
- package/dist/assets/cdk/README.md +19 -7
- package/dist/assets/cdk/bin/cdk.ts +37 -2
- package/dist/assets/cdk/lib/cdk-stack.ts +25 -2
- package/dist/assets/cdk/package.json +1 -1
- package/dist/assets/cdk/test/cdk.test.ts +18 -14
- package/dist/assets/cdk/tsconfig.json +4 -4
- package/dist/assets/container/python/Dockerfile +19 -9
- package/dist/assets/container/python/dockerignore.template +7 -0
- package/dist/assets/python/autogen/base/README.md +9 -11
- package/dist/assets/python/autogen/base/mcp_client/__init__.py +1 -1
- package/dist/assets/python/autogen/base/model/__init__.py +1 -1
- package/dist/assets/python/crewai/base/README.md +9 -11
- package/dist/assets/python/crewai/base/model/__init__.py +1 -1
- package/dist/assets/python/googleadk/base/README.md +9 -9
- package/dist/assets/python/googleadk/base/main.py +10 -1
- package/dist/assets/python/googleadk/base/mcp_client/__init__.py +1 -1
- package/dist/assets/python/googleadk/base/mcp_client/client.py +54 -3
- package/dist/assets/python/googleadk/base/model/__init__.py +1 -1
- package/dist/assets/python/googleadk/base/pyproject.toml +2 -0
- package/dist/assets/python/langchain_langgraph/base/README.md +9 -11
- package/dist/assets/python/langchain_langgraph/base/main.py +11 -1
- package/dist/assets/python/langchain_langgraph/base/mcp_client/__init__.py +1 -1
- package/dist/assets/python/langchain_langgraph/base/mcp_client/client.py +52 -3
- package/dist/assets/python/langchain_langgraph/base/model/__init__.py +1 -1
- package/dist/assets/python/langchain_langgraph/base/pyproject.toml +2 -1
- package/dist/assets/python/openaiagents/base/README.md +9 -9
- package/dist/assets/python/openaiagents/base/main.py +43 -3
- package/dist/assets/python/openaiagents/base/mcp_client/__init__.py +1 -1
- package/dist/assets/python/openaiagents/base/mcp_client/client.py +54 -3
- package/dist/assets/python/openaiagents/base/model/__init__.py +1 -1
- package/dist/assets/python/openaiagents/base/pyproject.toml +2 -0
- package/dist/assets/python/strands/base/README.md +10 -12
- package/dist/assets/python/strands/base/main.py +16 -3
- package/dist/assets/python/strands/base/mcp_client/__init__.py +1 -1
- package/dist/assets/python/strands/base/mcp_client/client.py +56 -4
- package/dist/assets/python/strands/base/model/__init__.py +1 -1
- package/dist/assets/python/strands/base/pyproject.toml +4 -1
- package/dist/assets/python/strands/capabilities/memory/__init__.py +1 -0
- package/dist/cli/index.mjs +290 -286
- package/dist/lib/packaging/build-args.d.ts +6 -0
- package/dist/lib/packaging/build-args.d.ts.map +1 -0
- package/dist/lib/packaging/build-args.js +18 -0
- package/dist/lib/packaging/build-args.js.map +1 -0
- package/dist/lib/packaging/container.d.ts.map +1 -1
- package/dist/lib/packaging/container.js +2 -1
- package/dist/lib/packaging/container.js.map +1 -1
- package/dist/lib/schemas/io/cli-config.d.ts +10 -0
- package/dist/lib/schemas/io/cli-config.d.ts.map +1 -0
- package/dist/lib/schemas/io/cli-config.js +27 -0
- package/dist/lib/schemas/io/cli-config.js.map +1 -0
- package/dist/lib/schemas/io/index.d.ts +1 -0
- package/dist/lib/schemas/io/index.d.ts.map +1 -1
- package/dist/lib/schemas/io/index.js +3 -1
- package/dist/lib/schemas/io/index.js.map +1 -1
- package/dist/lib/utils/subprocess.d.ts.map +1 -1
- package/dist/lib/utils/subprocess.js +32 -10
- package/dist/lib/utils/subprocess.js.map +1 -1
- package/dist/schema/constants.d.ts.map +1 -1
- package/dist/schema/constants.js +0 -1
- package/dist/schema/constants.js.map +1 -1
- package/dist/schema/schemas/agentcore-project.d.ts +48 -5
- package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
- package/dist/schema/schemas/agentcore-project.js +19 -4
- package/dist/schema/schemas/agentcore-project.js.map +1 -1
- package/dist/schema/schemas/aws-targets.js +1 -1
- package/dist/schema/schemas/aws-targets.js.map +1 -1
- package/dist/schema/schemas/deployed-state.d.ts +32 -0
- package/dist/schema/schemas/deployed-state.d.ts.map +1 -1
- package/dist/schema/schemas/deployed-state.js +11 -1
- package/dist/schema/schemas/deployed-state.js.map +1 -1
- package/dist/schema/schemas/mcp-defs.d.ts +1 -1
- package/dist/schema/schemas/mcp-defs.js +1 -1
- package/dist/schema/schemas/mcp.d.ts +146 -6
- package/dist/schema/schemas/mcp.d.ts.map +1 -1
- package/dist/schema/schemas/mcp.js +49 -4
- package/dist/schema/schemas/mcp.js.map +1 -1
- package/package.json +8 -8
|
@@ -13,20 +13,32 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/.prettierrc should ma
|
|
|
13
13
|
`;
|
|
14
14
|
|
|
15
15
|
exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/README.md should match snapshot 1`] = `
|
|
16
|
-
"#
|
|
16
|
+
"# AgentCore CDK Project
|
|
17
17
|
|
|
18
|
-
This is
|
|
18
|
+
This CDK project is managed by the AgentCore CLI. It deploys your agent infrastructure into AWS using the \`@aws/agentcore-cdk\` L3 constructs.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## Structure
|
|
21
|
+
|
|
22
|
+
- \`bin/cdk.ts\` — Entry point. Reads project configuration from \`agentcore/\` and creates a stack per deployment target.
|
|
23
|
+
- \`lib/cdk-stack.ts\` — Defines \`AgentCoreStack\`, which wraps the \`AgentCoreApplication\` L3 construct.
|
|
24
|
+
- \`test/cdk.test.ts\` — Unit tests for stack synthesis.
|
|
21
25
|
|
|
22
26
|
## Useful commands
|
|
23
27
|
|
|
24
|
-
- \`npm run build\` compile
|
|
25
|
-
- \`npm run
|
|
26
|
-
- \`
|
|
28
|
+
- \`npm run build\` compile TypeScript to JavaScript
|
|
29
|
+
- \`npm run test\` run unit tests
|
|
30
|
+
- \`npx cdk synth\` emit the synthesized CloudFormation template
|
|
27
31
|
- \`npx cdk deploy\` deploy this stack to your default AWS account/region
|
|
28
32
|
- \`npx cdk diff\` compare deployed stack with current state
|
|
29
|
-
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
You typically don't need to interact with this directory directly. The AgentCore CLI handles synthesis and deployment:
|
|
37
|
+
|
|
38
|
+
\`\`\`bash
|
|
39
|
+
agentcore deploy # synthesizes and deploys via CDK
|
|
40
|
+
agentcore status # checks deployment status
|
|
41
|
+
\`\`\`
|
|
30
42
|
"
|
|
31
43
|
`;
|
|
32
44
|
|
|
@@ -36,6 +48,7 @@ import { AgentCoreStack } from '../lib/cdk-stack';
|
|
|
36
48
|
import { ConfigIO, type AwsDeploymentTarget } from '@aws/agentcore-cdk';
|
|
37
49
|
import { App, type Environment } from 'aws-cdk-lib';
|
|
38
50
|
import * as path from 'path';
|
|
51
|
+
import * as fs from 'fs';
|
|
39
52
|
|
|
40
53
|
function toEnvironment(target: AwsDeploymentTarget): Environment {
|
|
41
54
|
return {
|
|
@@ -44,8 +57,12 @@ function toEnvironment(target: AwsDeploymentTarget): Environment {
|
|
|
44
57
|
};
|
|
45
58
|
}
|
|
46
59
|
|
|
60
|
+
function sanitize(name: string): string {
|
|
61
|
+
return name.replace(/_/g, '-');
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
function toStackName(projectName: string, targetName: string): string {
|
|
48
|
-
return \`AgentCore-\${projectName}-\${targetName}\`;
|
|
65
|
+
return \`AgentCore-\${sanitize(projectName)}-\${sanitize(targetName)}\`;
|
|
49
66
|
}
|
|
50
67
|
|
|
51
68
|
async function main() {
|
|
@@ -56,6 +73,22 @@ async function main() {
|
|
|
56
73
|
const spec = await configIO.readProjectSpec();
|
|
57
74
|
const targets = await configIO.readAWSDeploymentTargets();
|
|
58
75
|
|
|
76
|
+
// Read MCP configuration if it exists
|
|
77
|
+
let mcpSpec;
|
|
78
|
+
try {
|
|
79
|
+
mcpSpec = await configIO.readMcpSpec();
|
|
80
|
+
} catch {
|
|
81
|
+
// MCP config is optional
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Read deployed state for credential ARNs (populated by pre-deploy identity setup)
|
|
85
|
+
let deployedState: Record<string, unknown> | undefined;
|
|
86
|
+
try {
|
|
87
|
+
deployedState = JSON.parse(fs.readFileSync(path.join(configRoot, '.cli', 'deployed-state.json'), 'utf8'));
|
|
88
|
+
} catch {
|
|
89
|
+
// Deployed state may not exist on first deploy
|
|
90
|
+
}
|
|
91
|
+
|
|
59
92
|
if (targets.length === 0) {
|
|
60
93
|
throw new Error('No deployment targets configured. Please define targets in agentcore/aws-targets.json');
|
|
61
94
|
}
|
|
@@ -66,8 +99,19 @@ async function main() {
|
|
|
66
99
|
const env = toEnvironment(target);
|
|
67
100
|
const stackName = toStackName(spec.name, target.name);
|
|
68
101
|
|
|
102
|
+
// Extract credentials from deployed state for this target
|
|
103
|
+
const targetState = (deployedState as Record<string, unknown>)?.targets as
|
|
104
|
+
| Record<string, Record<string, unknown>>
|
|
105
|
+
| undefined;
|
|
106
|
+
const targetResources = targetState?.[target.name]?.resources as Record<string, unknown> | undefined;
|
|
107
|
+
const credentials = targetResources?.credentials as
|
|
108
|
+
| Record<string, { credentialProviderArn: string; clientSecretArn?: string }>
|
|
109
|
+
| undefined;
|
|
110
|
+
|
|
69
111
|
new AgentCoreStack(app, stackName, {
|
|
70
112
|
spec,
|
|
113
|
+
mcpSpec,
|
|
114
|
+
credentials,
|
|
71
115
|
env,
|
|
72
116
|
description: \`AgentCore stack for \${spec.name} deployed to \${target.name} (\${target.region})\`,
|
|
73
117
|
tags: {
|
|
@@ -80,7 +124,10 @@ async function main() {
|
|
|
80
124
|
app.synth();
|
|
81
125
|
}
|
|
82
126
|
|
|
83
|
-
main()
|
|
127
|
+
main().catch((error: unknown) => {
|
|
128
|
+
console.error('AgentCore CDK synthesis failed:', error instanceof Error ? error.message : error);
|
|
129
|
+
process.exitCode = 1;
|
|
130
|
+
});
|
|
84
131
|
"
|
|
85
132
|
`;
|
|
86
133
|
|
|
@@ -203,7 +250,12 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/jest.config.js should
|
|
|
203
250
|
`;
|
|
204
251
|
|
|
205
252
|
exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/lib/cdk-stack.ts should match snapshot 1`] = `
|
|
206
|
-
"import {
|
|
253
|
+
"import {
|
|
254
|
+
AgentCoreApplication,
|
|
255
|
+
AgentCoreMcp,
|
|
256
|
+
type AgentCoreProjectSpec,
|
|
257
|
+
type AgentCoreMcpSpec,
|
|
258
|
+
} from '@aws/agentcore-cdk';
|
|
207
259
|
import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
|
|
208
260
|
import { Construct } from 'constructs';
|
|
209
261
|
|
|
@@ -212,6 +264,14 @@ export interface AgentCoreStackProps extends StackProps {
|
|
|
212
264
|
* The AgentCore project specification containing agents, memories, and credentials.
|
|
213
265
|
*/
|
|
214
266
|
spec: AgentCoreProjectSpec;
|
|
267
|
+
/**
|
|
268
|
+
* The MCP specification containing gateways and servers.
|
|
269
|
+
*/
|
|
270
|
+
mcpSpec?: AgentCoreMcpSpec;
|
|
271
|
+
/**
|
|
272
|
+
* Credential provider ARNs from deployed state, keyed by credential name.
|
|
273
|
+
*/
|
|
274
|
+
credentials?: Record<string, { credentialProviderArn: string; clientSecretArn?: string }>;
|
|
215
275
|
}
|
|
216
276
|
|
|
217
277
|
/**
|
|
@@ -227,13 +287,23 @@ export class AgentCoreStack extends Stack {
|
|
|
227
287
|
constructor(scope: Construct, id: string, props: AgentCoreStackProps) {
|
|
228
288
|
super(scope, id, props);
|
|
229
289
|
|
|
230
|
-
const { spec } = props;
|
|
290
|
+
const { spec, mcpSpec, credentials } = props;
|
|
231
291
|
|
|
232
292
|
// Create AgentCoreApplication with all agents
|
|
233
293
|
this.application = new AgentCoreApplication(this, 'Application', {
|
|
234
294
|
spec,
|
|
235
295
|
});
|
|
236
296
|
|
|
297
|
+
// Create AgentCoreMcp if there are gateways configured
|
|
298
|
+
if (mcpSpec?.agentCoreGateways && mcpSpec.agentCoreGateways.length > 0) {
|
|
299
|
+
new AgentCoreMcp(this, 'Mcp', {
|
|
300
|
+
projectName: spec.name,
|
|
301
|
+
mcpSpec,
|
|
302
|
+
agentCoreApplication: this.application,
|
|
303
|
+
credentials,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
237
307
|
// Stack-level output
|
|
238
308
|
new CfnOutput(this, 'StackNameOutput', {
|
|
239
309
|
description: 'Name of the CloudFormation Stack',
|
|
@@ -281,7 +351,7 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/package.json should m
|
|
|
281
351
|
},
|
|
282
352
|
"dependencies": {
|
|
283
353
|
"@aws/agentcore-cdk": "^0.1.0-alpha.1",
|
|
284
|
-
"aws-cdk-lib": "2.
|
|
354
|
+
"aws-cdk-lib": "2.239.0",
|
|
285
355
|
"constructs": "^10.0.0"
|
|
286
356
|
}
|
|
287
357
|
}
|
|
@@ -289,21 +359,25 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/package.json should m
|
|
|
289
359
|
`;
|
|
290
360
|
|
|
291
361
|
exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/test/cdk.test.ts should match snapshot 1`] = `
|
|
292
|
-
"
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
362
|
+
"import * as cdk from 'aws-cdk-lib';
|
|
363
|
+
import { Template } from 'aws-cdk-lib/assertions';
|
|
364
|
+
import { AgentCoreStack } from '../lib/cdk-stack';
|
|
365
|
+
|
|
366
|
+
test('AgentCoreStack synthesizes with empty spec', () => {
|
|
367
|
+
const app = new cdk.App();
|
|
368
|
+
const stack = new AgentCoreStack(app, 'TestStack', {
|
|
369
|
+
spec: {
|
|
370
|
+
name: 'testproject',
|
|
371
|
+
version: 1,
|
|
372
|
+
agents: [],
|
|
373
|
+
memories: [],
|
|
374
|
+
credentials: [],
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
const template = Template.fromStack(stack);
|
|
378
|
+
template.hasOutput('StackNameOutput', {
|
|
379
|
+
Description: 'Name of the CloudFormation Stack',
|
|
380
|
+
});
|
|
307
381
|
});
|
|
308
382
|
"
|
|
309
383
|
`;
|
|
@@ -321,14 +395,14 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/tsconfig.json should
|
|
|
321
395
|
"strictNullChecks": true,
|
|
322
396
|
"noImplicitThis": true,
|
|
323
397
|
"alwaysStrict": true,
|
|
324
|
-
"noUnusedLocals":
|
|
325
|
-
"noUnusedParameters":
|
|
398
|
+
"noUnusedLocals": true,
|
|
399
|
+
"noUnusedParameters": true,
|
|
326
400
|
"noImplicitReturns": true,
|
|
327
|
-
"noFallthroughCasesInSwitch":
|
|
401
|
+
"noFallthroughCasesInSwitch": true,
|
|
328
402
|
"inlineSourceMap": true,
|
|
329
403
|
"inlineSources": true,
|
|
330
404
|
"experimentalDecorators": true,
|
|
331
|
-
"strictPropertyInitialization":
|
|
405
|
+
"strictPropertyInitialization": true,
|
|
332
406
|
"skipLibCheck": true,
|
|
333
407
|
"typeRoots": ["./node_modules/@types"],
|
|
334
408
|
"rootDir": ".",
|
|
@@ -792,25 +866,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/au
|
|
|
792
866
|
|
|
793
867
|
# Layout
|
|
794
868
|
|
|
795
|
-
|
|
796
|
-
|
|
869
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
870
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
797
871
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
798
872
|
|
|
799
|
-
##
|
|
873
|
+
## Agent Root
|
|
800
874
|
|
|
801
|
-
The main entrypoint to your app is defined in \`
|
|
875
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
802
876
|
file defines a Starlette ASGI app with the AutoGen framework running within.
|
|
803
877
|
|
|
804
|
-
\`
|
|
878
|
+
\`model/load.py\` instantiates your chosen model provider.
|
|
805
879
|
|
|
806
880
|
## Environment Variables
|
|
807
881
|
|
|
808
|
-
| Variable
|
|
809
|
-
|
|
|
810
|
-
| \`
|
|
811
|
-
| \`
|
|
812
|
-
| \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
|
|
813
|
-
| \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
|
|
882
|
+
| Variable | Required | Description |
|
|
883
|
+
| --- | --- | --- |
|
|
884
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
885
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
814
886
|
|
|
815
887
|
# Developing locally
|
|
816
888
|
|
|
@@ -934,7 +1006,7 @@ if __name__ == "__main__":
|
|
|
934
1006
|
`;
|
|
935
1007
|
|
|
936
1008
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/autogen/base/mcp_client/__init__.py should match snapshot 1`] = `
|
|
937
|
-
"
|
|
1009
|
+
"# Package marker
|
|
938
1010
|
"
|
|
939
1011
|
`;
|
|
940
1012
|
|
|
@@ -961,7 +1033,7 @@ async def get_streamable_http_mcp_tools() -> List[StreamableHttpMcpToolAdapter]:
|
|
|
961
1033
|
`;
|
|
962
1034
|
|
|
963
1035
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/autogen/base/model/__init__.py should match snapshot 1`] = `
|
|
964
|
-
"
|
|
1036
|
+
"# Package marker
|
|
965
1037
|
"
|
|
966
1038
|
`;
|
|
967
1039
|
|
|
@@ -1148,25 +1220,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/cr
|
|
|
1148
1220
|
|
|
1149
1221
|
# Layout
|
|
1150
1222
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1223
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
1224
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
1153
1225
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
1154
1226
|
|
|
1155
|
-
##
|
|
1227
|
+
## Agent Root
|
|
1156
1228
|
|
|
1157
|
-
The main entrypoint to your app is defined in \`
|
|
1229
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
1158
1230
|
file defines a Starlette ASGI app with the CrewAI framework running within.
|
|
1159
1231
|
|
|
1160
|
-
\`
|
|
1232
|
+
\`model/load.py\` instantiates your chosen model provider.
|
|
1161
1233
|
|
|
1162
1234
|
## Environment Variables
|
|
1163
1235
|
|
|
1164
|
-
| Variable
|
|
1165
|
-
|
|
|
1166
|
-
| \`
|
|
1167
|
-
| \`
|
|
1168
|
-
| \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
|
|
1169
|
-
| \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
|
|
1236
|
+
| Variable | Required | Description |
|
|
1237
|
+
| --- | --- | --- |
|
|
1238
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
1239
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
1170
1240
|
|
|
1171
1241
|
# Developing locally
|
|
1172
1242
|
|
|
@@ -1293,7 +1363,7 @@ if __name__ == "__main__":
|
|
|
1293
1363
|
`;
|
|
1294
1364
|
|
|
1295
1365
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/crewai/base/model/__init__.py should match snapshot 1`] = `
|
|
1296
|
-
"
|
|
1366
|
+
"# Package marker
|
|
1297
1367
|
"
|
|
1298
1368
|
`;
|
|
1299
1369
|
|
|
@@ -1474,23 +1544,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/go
|
|
|
1474
1544
|
|
|
1475
1545
|
# Layout
|
|
1476
1546
|
|
|
1477
|
-
|
|
1478
|
-
|
|
1547
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
1548
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
1479
1549
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
1480
1550
|
|
|
1481
|
-
##
|
|
1551
|
+
## Agent Root
|
|
1482
1552
|
|
|
1483
|
-
The main entrypoint to your app is defined in \`
|
|
1553
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
1484
1554
|
file defines a Starlette ASGI app with the Google ADK framework running within.
|
|
1485
1555
|
|
|
1486
|
-
\`
|
|
1556
|
+
\`model/load.py\` instantiates your chosen model provider (Gemini).
|
|
1487
1557
|
|
|
1488
1558
|
## Environment Variables
|
|
1489
1559
|
|
|
1490
|
-
| Variable
|
|
1491
|
-
|
|
|
1492
|
-
| \`
|
|
1493
|
-
| \`LOCAL_DEV\`
|
|
1560
|
+
| Variable | Required | Description |
|
|
1561
|
+
| --- | --- | --- |
|
|
1562
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
1563
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
1494
1564
|
|
|
1495
1565
|
# Developing locally
|
|
1496
1566
|
|
|
@@ -1565,7 +1635,11 @@ from google.adk.sessions import InMemorySessionService
|
|
|
1565
1635
|
from google.genai import types
|
|
1566
1636
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
1567
1637
|
from model.load import load_model
|
|
1638
|
+
{{#if hasGateway}}
|
|
1639
|
+
from mcp_client.client import get_all_gateway_mcp_toolsets
|
|
1640
|
+
{{else}}
|
|
1568
1641
|
from mcp_client.client import get_streamable_http_mcp_client
|
|
1642
|
+
{{/if}}
|
|
1569
1643
|
|
|
1570
1644
|
app = BedrockAgentCoreApp()
|
|
1571
1645
|
log = app.logger
|
|
@@ -1583,7 +1657,12 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
1583
1657
|
|
|
1584
1658
|
|
|
1585
1659
|
# Get MCP Toolset
|
|
1586
|
-
|
|
1660
|
+
{{#if hasGateway}}
|
|
1661
|
+
mcp_toolset = get_all_gateway_mcp_toolsets()
|
|
1662
|
+
{{else}}
|
|
1663
|
+
mcp_client = get_streamable_http_mcp_client()
|
|
1664
|
+
mcp_toolset = [mcp_client] if mcp_client else []
|
|
1665
|
+
{{/if}}
|
|
1587
1666
|
|
|
1588
1667
|
_credentials_loaded = False
|
|
1589
1668
|
|
|
@@ -1653,31 +1732,82 @@ if __name__ == "__main__":
|
|
|
1653
1732
|
`;
|
|
1654
1733
|
|
|
1655
1734
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/mcp_client/__init__.py should match snapshot 1`] = `
|
|
1656
|
-
"
|
|
1735
|
+
"# Package marker
|
|
1657
1736
|
"
|
|
1658
1737
|
`;
|
|
1659
1738
|
|
|
1660
1739
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/mcp_client/client.py should match snapshot 1`] = `
|
|
1661
|
-
"
|
|
1740
|
+
"import os
|
|
1741
|
+
import logging
|
|
1742
|
+
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
|
|
1662
1743
|
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
|
|
1663
1744
|
|
|
1745
|
+
logger = logging.getLogger(__name__)
|
|
1746
|
+
|
|
1747
|
+
{{#if hasGateway}}
|
|
1748
|
+
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
|
|
1749
|
+
import httpx
|
|
1750
|
+
from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
|
|
1751
|
+
{{/if}}
|
|
1752
|
+
{{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
|
|
1753
|
+
from bedrock_agentcore.identity import requires_access_token
|
|
1754
|
+
{{/if}}
|
|
1755
|
+
|
|
1756
|
+
{{#each gatewayProviders}}
|
|
1757
|
+
{{#if (eq authType "CUSTOM_JWT")}}
|
|
1758
|
+
@requires_access_token(
|
|
1759
|
+
provider_name="{{credentialProviderName}}",
|
|
1760
|
+
scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
|
|
1761
|
+
auth_flow="M2M",
|
|
1762
|
+
)
|
|
1763
|
+
def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
|
|
1764
|
+
"""Obtain OAuth access token via AgentCore Identity for {{name}}."""
|
|
1765
|
+
return access_token
|
|
1766
|
+
|
|
1767
|
+
{{/if}}
|
|
1768
|
+
{{/each}}
|
|
1769
|
+
|
|
1770
|
+
def get_all_gateway_mcp_toolsets() -> list[MCPToolset]:
|
|
1771
|
+
"""Returns MCP Toolsets for all configured gateways."""
|
|
1772
|
+
toolsets = []
|
|
1773
|
+
{{#each gatewayProviders}}
|
|
1774
|
+
url = os.environ.get("{{envVarName}}")
|
|
1775
|
+
if url:
|
|
1776
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
1777
|
+
session = create_aws_session()
|
|
1778
|
+
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
1779
|
+
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(
|
|
1780
|
+
url=url,
|
|
1781
|
+
httpx_client_factory=lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)
|
|
1782
|
+
)))
|
|
1783
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
1784
|
+
token = _get_bearer_token_{{snakeCase name}}()
|
|
1785
|
+
headers = {"Authorization": f"Bearer {token}"} if token else None
|
|
1786
|
+
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url, headers=headers)))
|
|
1787
|
+
{{else}}
|
|
1788
|
+
toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url)))
|
|
1789
|
+
{{/if}}
|
|
1790
|
+
else:
|
|
1791
|
+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
1792
|
+
{{/each}}
|
|
1793
|
+
return toolsets
|
|
1794
|
+
{{else}}
|
|
1664
1795
|
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
|
|
1665
1796
|
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
|
|
1666
1797
|
|
|
1667
1798
|
|
|
1668
1799
|
def get_streamable_http_mcp_client() -> MCPToolset:
|
|
1669
|
-
"""
|
|
1670
|
-
Returns an MCP Toolset compatible with Google ADK.
|
|
1671
|
-
"""
|
|
1800
|
+
"""Returns an MCP Toolset compatible with Google ADK."""
|
|
1672
1801
|
# to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
|
|
1673
1802
|
return MCPToolset(
|
|
1674
1803
|
connection_params=StreamableHTTPConnectionParams(url=EXAMPLE_MCP_ENDPOINT)
|
|
1675
1804
|
)
|
|
1805
|
+
{{/if}}
|
|
1676
1806
|
"
|
|
1677
1807
|
`;
|
|
1678
1808
|
|
|
1679
1809
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/model/__init__.py should match snapshot 1`] = `
|
|
1680
|
-
"
|
|
1810
|
+
"# Package marker
|
|
1681
1811
|
"
|
|
1682
1812
|
`;
|
|
1683
1813
|
|
|
@@ -1743,6 +1873,8 @@ dependencies = [
|
|
|
1743
1873
|
"google-adk >= 1.17.0",
|
|
1744
1874
|
"bedrock-agentcore >= 1.0.3",
|
|
1745
1875
|
"botocore[crt] >= 1.35.0",
|
|
1876
|
+
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
1877
|
+
{{/if}}{{/if}}
|
|
1746
1878
|
]
|
|
1747
1879
|
|
|
1748
1880
|
[tool.hatch.build.targets.wheel]
|
|
@@ -1755,25 +1887,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/la
|
|
|
1755
1887
|
|
|
1756
1888
|
# Layout
|
|
1757
1889
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1890
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
1891
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
1760
1892
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
1761
1893
|
|
|
1762
|
-
##
|
|
1894
|
+
## Agent Root
|
|
1763
1895
|
|
|
1764
|
-
The main entrypoint to your app is defined in \`
|
|
1896
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
1765
1897
|
file defines a Starlette ASGI app with the LangChain/LangGraph framework running within.
|
|
1766
1898
|
|
|
1767
|
-
\`
|
|
1899
|
+
\`model/load.py\` instantiates your chosen model provider.
|
|
1768
1900
|
|
|
1769
1901
|
## Environment Variables
|
|
1770
1902
|
|
|
1771
|
-
| Variable
|
|
1772
|
-
|
|
|
1773
|
-
| \`
|
|
1774
|
-
| \`
|
|
1775
|
-
| \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
|
|
1776
|
-
| \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
|
|
1903
|
+
| Variable | Required | Description |
|
|
1904
|
+
| --- | --- | --- |
|
|
1905
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
1906
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
1777
1907
|
|
|
1778
1908
|
# Developing locally
|
|
1779
1909
|
|
|
@@ -1847,7 +1977,11 @@ from langgraph.prebuilt import create_react_agent
|
|
|
1847
1977
|
from langchain.tools import tool
|
|
1848
1978
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
1849
1979
|
from model.load import load_model
|
|
1980
|
+
{{#if hasGateway}}
|
|
1981
|
+
from mcp_client.client import get_all_gateway_mcp_client
|
|
1982
|
+
{{else}}
|
|
1850
1983
|
from mcp_client.client import get_streamable_http_mcp_client
|
|
1984
|
+
{{/if}}
|
|
1851
1985
|
|
|
1852
1986
|
app = BedrockAgentCoreApp()
|
|
1853
1987
|
log = app.logger
|
|
@@ -1877,10 +2011,16 @@ async def invoke(payload, context):
|
|
|
1877
2011
|
log.info("Invoking Agent.....")
|
|
1878
2012
|
|
|
1879
2013
|
# Get MCP Client
|
|
2014
|
+
{{#if hasGateway}}
|
|
2015
|
+
mcp_client = get_all_gateway_mcp_client()
|
|
2016
|
+
{{else}}
|
|
1880
2017
|
mcp_client = get_streamable_http_mcp_client()
|
|
2018
|
+
{{/if}}
|
|
1881
2019
|
|
|
1882
2020
|
# Load MCP Tools
|
|
1883
|
-
mcp_tools =
|
|
2021
|
+
mcp_tools = []
|
|
2022
|
+
if mcp_client:
|
|
2023
|
+
mcp_tools = await mcp_client.get_tools()
|
|
1884
2024
|
|
|
1885
2025
|
# Define the agent using create_react_agent
|
|
1886
2026
|
graph = create_react_agent(get_or_create_model(), tools=mcp_tools + tools)
|
|
@@ -1901,21 +2041,69 @@ if __name__ == "__main__":
|
|
|
1901
2041
|
`;
|
|
1902
2042
|
|
|
1903
2043
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/__init__.py should match snapshot 1`] = `
|
|
1904
|
-
"
|
|
2044
|
+
"# Package marker
|
|
1905
2045
|
"
|
|
1906
2046
|
`;
|
|
1907
2047
|
|
|
1908
2048
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/client.py should match snapshot 1`] = `
|
|
1909
|
-
"
|
|
2049
|
+
"import os
|
|
2050
|
+
import logging
|
|
2051
|
+
from langchain_mcp_adapters.client import MultiServerMCPClient
|
|
2052
|
+
|
|
2053
|
+
logger = logging.getLogger(__name__)
|
|
2054
|
+
|
|
2055
|
+
{{#if hasGateway}}
|
|
2056
|
+
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
|
|
2057
|
+
from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
|
|
2058
|
+
{{/if}}
|
|
2059
|
+
{{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
|
|
2060
|
+
from bedrock_agentcore.identity import requires_access_token
|
|
2061
|
+
{{/if}}
|
|
2062
|
+
|
|
2063
|
+
{{#each gatewayProviders}}
|
|
2064
|
+
{{#if (eq authType "CUSTOM_JWT")}}
|
|
2065
|
+
@requires_access_token(
|
|
2066
|
+
provider_name="{{credentialProviderName}}",
|
|
2067
|
+
scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
|
|
2068
|
+
auth_flow="M2M",
|
|
2069
|
+
)
|
|
2070
|
+
def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
|
|
2071
|
+
"""Obtain OAuth access token via AgentCore Identity for {{name}}."""
|
|
2072
|
+
return access_token
|
|
1910
2073
|
|
|
2074
|
+
{{/if}}
|
|
2075
|
+
{{/each}}
|
|
2076
|
+
|
|
2077
|
+
def get_all_gateway_mcp_client() -> MultiServerMCPClient | None:
|
|
2078
|
+
"""Returns an MCP Client connected to all configured gateways."""
|
|
2079
|
+
servers = {}
|
|
2080
|
+
{{#each gatewayProviders}}
|
|
2081
|
+
url = os.environ.get("{{envVarName}}")
|
|
2082
|
+
if url:
|
|
2083
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
2084
|
+
session = create_aws_session()
|
|
2085
|
+
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
2086
|
+
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "auth": auth}
|
|
2087
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
2088
|
+
token = _get_bearer_token_{{snakeCase name}}()
|
|
2089
|
+
headers = {"Authorization": f"Bearer {token}"} if token else None
|
|
2090
|
+
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "headers": headers}
|
|
2091
|
+
{{else}}
|
|
2092
|
+
servers["{{name}}"] = {"transport": "streamable_http", "url": url}
|
|
2093
|
+
{{/if}}
|
|
2094
|
+
else:
|
|
2095
|
+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
2096
|
+
{{/each}}
|
|
2097
|
+
if not servers:
|
|
2098
|
+
return None
|
|
2099
|
+
return MultiServerMCPClient(servers)
|
|
2100
|
+
{{else}}
|
|
1911
2101
|
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
|
|
1912
2102
|
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
|
|
1913
2103
|
|
|
1914
2104
|
|
|
1915
2105
|
def get_streamable_http_mcp_client() -> MultiServerMCPClient:
|
|
1916
|
-
"""
|
|
1917
|
-
Returns an MCP Client compatible with LangChain/LangGraph.
|
|
1918
|
-
"""
|
|
2106
|
+
"""Returns an MCP Client compatible with LangChain/LangGraph."""
|
|
1919
2107
|
# to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
|
|
1920
2108
|
return MultiServerMCPClient(
|
|
1921
2109
|
{
|
|
@@ -1925,11 +2113,12 @@ def get_streamable_http_mcp_client() -> MultiServerMCPClient:
|
|
|
1925
2113
|
}
|
|
1926
2114
|
}
|
|
1927
2115
|
)
|
|
2116
|
+
{{/if}}
|
|
1928
2117
|
"
|
|
1929
2118
|
`;
|
|
1930
2119
|
|
|
1931
2120
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/model/__init__.py should match snapshot 1`] = `
|
|
1932
|
-
"
|
|
2121
|
+
"# Package marker
|
|
1933
2122
|
"
|
|
1934
2123
|
`;
|
|
1935
2124
|
|
|
@@ -2078,7 +2267,6 @@ dependencies = [
|
|
|
2078
2267
|
"mcp >= 1.19.0",
|
|
2079
2268
|
"langchain-mcp-adapters >= 0.1.11",
|
|
2080
2269
|
"langchain >= 1.0.3",
|
|
2081
|
-
"tiktoken == 0.11.0",
|
|
2082
2270
|
"bedrock-agentcore >= 1.0.3",
|
|
2083
2271
|
"botocore[crt] >= 1.35.0",
|
|
2084
2272
|
{{#if (eq modelProvider "Bedrock")}}
|
|
@@ -2093,6 +2281,8 @@ dependencies = [
|
|
|
2093
2281
|
{{#if (eq modelProvider "Gemini")}}
|
|
2094
2282
|
"langchain-google-genai >= 3.0.3",
|
|
2095
2283
|
{{/if}}
|
|
2284
|
+
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
2285
|
+
{{/if}}{{/if}}
|
|
2096
2286
|
]
|
|
2097
2287
|
|
|
2098
2288
|
[tool.hatch.build.targets.wheel]
|
|
@@ -2105,23 +2295,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
|
|
|
2105
2295
|
|
|
2106
2296
|
# Layout
|
|
2107
2297
|
|
|
2108
|
-
|
|
2109
|
-
|
|
2298
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
2299
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
2110
2300
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
2111
2301
|
|
|
2112
|
-
##
|
|
2302
|
+
## Agent Root
|
|
2113
2303
|
|
|
2114
|
-
The main entrypoint to your app is defined in \`
|
|
2304
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
2115
2305
|
file defines a Starlette ASGI app with the OpenAI Agents SDK framework running within.
|
|
2116
2306
|
|
|
2117
|
-
\`
|
|
2307
|
+
\`model/load.py\` instantiates your chosen model provider (OpenAI).
|
|
2118
2308
|
|
|
2119
2309
|
## Environment Variables
|
|
2120
2310
|
|
|
2121
|
-
| Variable
|
|
2122
|
-
|
|
|
2123
|
-
| \`
|
|
2124
|
-
| \`LOCAL_DEV\`
|
|
2311
|
+
| Variable | Required | Description |
|
|
2312
|
+
| --- | --- | --- |
|
|
2313
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
2314
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
2125
2315
|
|
|
2126
2316
|
# Developing locally
|
|
2127
2317
|
|
|
@@ -2193,13 +2383,22 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
|
|
|
2193
2383
|
from agents import Agent, Runner, function_tool
|
|
2194
2384
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
2195
2385
|
from model.load import load_model
|
|
2386
|
+
{{#if hasGateway}}
|
|
2387
|
+
from mcp_client.client import get_all_gateway_mcp_servers
|
|
2388
|
+
{{else}}
|
|
2196
2389
|
from mcp_client.client import get_streamable_http_mcp_client
|
|
2390
|
+
{{/if}}
|
|
2197
2391
|
|
|
2198
2392
|
app = BedrockAgentCoreApp()
|
|
2199
2393
|
log = app.logger
|
|
2200
2394
|
|
|
2201
2395
|
# Get MCP Server
|
|
2396
|
+
{{#if hasGateway}}
|
|
2397
|
+
mcp_servers = get_all_gateway_mcp_servers()
|
|
2398
|
+
{{else}}
|
|
2202
2399
|
mcp_server = get_streamable_http_mcp_client()
|
|
2400
|
+
mcp_servers = [mcp_server] if mcp_server else []
|
|
2401
|
+
{{/if}}
|
|
2203
2402
|
|
|
2204
2403
|
_credentials_loaded = False
|
|
2205
2404
|
|
|
@@ -2221,16 +2420,47 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
2221
2420
|
async def main(query):
|
|
2222
2421
|
ensure_credentials_loaded()
|
|
2223
2422
|
try:
|
|
2224
|
-
|
|
2225
|
-
|
|
2423
|
+
{{#if hasGateway}}
|
|
2424
|
+
if mcp_servers:
|
|
2425
|
+
agent = Agent(
|
|
2426
|
+
name="{{ name }}",
|
|
2427
|
+
model="gpt-4.1",
|
|
2428
|
+
mcp_servers=mcp_servers,
|
|
2429
|
+
tools=[add_numbers]
|
|
2430
|
+
)
|
|
2431
|
+
result = await Runner.run(agent, query)
|
|
2432
|
+
return result
|
|
2433
|
+
else:
|
|
2434
|
+
agent = Agent(
|
|
2435
|
+
name="{{ name }}",
|
|
2436
|
+
model="gpt-4.1",
|
|
2437
|
+
mcp_servers=[],
|
|
2438
|
+
tools=[add_numbers]
|
|
2439
|
+
)
|
|
2440
|
+
result = await Runner.run(agent, query)
|
|
2441
|
+
return result
|
|
2442
|
+
{{else}}
|
|
2443
|
+
if mcp_servers:
|
|
2444
|
+
async with mcp_servers[0] as server:
|
|
2445
|
+
active_servers = [server]
|
|
2446
|
+
agent = Agent(
|
|
2447
|
+
name="{{ name }}",
|
|
2448
|
+
model="gpt-4.1",
|
|
2449
|
+
mcp_servers=active_servers,
|
|
2450
|
+
tools=[add_numbers]
|
|
2451
|
+
)
|
|
2452
|
+
result = await Runner.run(agent, query)
|
|
2453
|
+
return result
|
|
2454
|
+
else:
|
|
2226
2455
|
agent = Agent(
|
|
2227
2456
|
name="{{ name }}",
|
|
2228
2457
|
model="gpt-4.1",
|
|
2229
|
-
mcp_servers=
|
|
2458
|
+
mcp_servers=[],
|
|
2230
2459
|
tools=[add_numbers]
|
|
2231
2460
|
)
|
|
2232
2461
|
result = await Runner.run(agent, query)
|
|
2233
2462
|
return result
|
|
2463
|
+
{{/if}}
|
|
2234
2464
|
except Exception as e:
|
|
2235
2465
|
log.error(f"Error during agent execution: {e}", exc_info=True)
|
|
2236
2466
|
raise e
|
|
@@ -2256,30 +2486,81 @@ if __name__ == "__main__":
|
|
|
2256
2486
|
`;
|
|
2257
2487
|
|
|
2258
2488
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/mcp_client/__init__.py should match snapshot 1`] = `
|
|
2259
|
-
"
|
|
2489
|
+
"# Package marker
|
|
2260
2490
|
"
|
|
2261
2491
|
`;
|
|
2262
2492
|
|
|
2263
2493
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/mcp_client/client.py should match snapshot 1`] = `
|
|
2264
|
-
"
|
|
2494
|
+
"import os
|
|
2495
|
+
import logging
|
|
2496
|
+
from agents.mcp import MCPServerStreamableHttp
|
|
2497
|
+
|
|
2498
|
+
logger = logging.getLogger(__name__)
|
|
2499
|
+
|
|
2500
|
+
{{#if hasGateway}}
|
|
2501
|
+
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
|
|
2502
|
+
import httpx
|
|
2503
|
+
from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
|
|
2504
|
+
{{/if}}
|
|
2505
|
+
{{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
|
|
2506
|
+
from bedrock_agentcore.identity import requires_access_token
|
|
2507
|
+
{{/if}}
|
|
2508
|
+
|
|
2509
|
+
{{#each gatewayProviders}}
|
|
2510
|
+
{{#if (eq authType "CUSTOM_JWT")}}
|
|
2511
|
+
@requires_access_token(
|
|
2512
|
+
provider_name="{{credentialProviderName}}",
|
|
2513
|
+
scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
|
|
2514
|
+
auth_flow="M2M",
|
|
2515
|
+
)
|
|
2516
|
+
def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
|
|
2517
|
+
"""Obtain OAuth access token via AgentCore Identity for {{name}}."""
|
|
2518
|
+
return access_token
|
|
2265
2519
|
|
|
2520
|
+
{{/if}}
|
|
2521
|
+
{{/each}}
|
|
2522
|
+
|
|
2523
|
+
def get_all_gateway_mcp_servers() -> list[MCPServerStreamableHttp]:
|
|
2524
|
+
"""Returns MCP servers for all configured gateways."""
|
|
2525
|
+
servers = []
|
|
2526
|
+
{{#each gatewayProviders}}
|
|
2527
|
+
url = os.environ.get("{{envVarName}}")
|
|
2528
|
+
if url:
|
|
2529
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
2530
|
+
session = create_aws_session()
|
|
2531
|
+
auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
|
|
2532
|
+
servers.append(MCPServerStreamableHttp(
|
|
2533
|
+
name="{{name}}",
|
|
2534
|
+
params={"url": url, "httpx_client_factory": lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)}
|
|
2535
|
+
))
|
|
2536
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
2537
|
+
token = _get_bearer_token_{{snakeCase name}}()
|
|
2538
|
+
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
2539
|
+
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url, "headers": headers}))
|
|
2540
|
+
{{else}}
|
|
2541
|
+
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url}))
|
|
2542
|
+
{{/if}}
|
|
2543
|
+
else:
|
|
2544
|
+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
2545
|
+
{{/each}}
|
|
2546
|
+
return servers
|
|
2547
|
+
{{else}}
|
|
2266
2548
|
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
|
|
2267
2549
|
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
|
|
2268
2550
|
|
|
2269
2551
|
|
|
2270
2552
|
def get_streamable_http_mcp_client() -> MCPServerStreamableHttp:
|
|
2271
|
-
"""
|
|
2272
|
-
Returns an MCP Client compatible with OpenAI Agents SDK.
|
|
2273
|
-
"""
|
|
2553
|
+
"""Returns an MCP Client compatible with OpenAI Agents SDK."""
|
|
2274
2554
|
# to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
|
|
2275
2555
|
return MCPServerStreamableHttp(
|
|
2276
2556
|
name="AgentCore Gateway MCP", params={"url": EXAMPLE_MCP_ENDPOINT}
|
|
2277
2557
|
)
|
|
2558
|
+
{{/if}}
|
|
2278
2559
|
"
|
|
2279
2560
|
`;
|
|
2280
2561
|
|
|
2281
2562
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/model/__init__.py should match snapshot 1`] = `
|
|
2282
|
-
"
|
|
2563
|
+
"# Package marker
|
|
2283
2564
|
"
|
|
2284
2565
|
`;
|
|
2285
2566
|
|
|
@@ -2340,6 +2621,8 @@ dependencies = [
|
|
|
2340
2621
|
"openai-agents >= 0.4.2",
|
|
2341
2622
|
"bedrock-agentcore >= 1.0.3",
|
|
2342
2623
|
"botocore[crt] >= 1.35.0",
|
|
2624
|
+
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
2625
|
+
{{/if}}{{/if}}
|
|
2343
2626
|
]
|
|
2344
2627
|
|
|
2345
2628
|
[tool.hatch.build.targets.wheel]
|
|
@@ -2348,29 +2631,27 @@ packages = ["."]
|
|
|
2348
2631
|
`;
|
|
2349
2632
|
|
|
2350
2633
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/README.md should match snapshot 1`] = `
|
|
2351
|
-
"This is a project generated by the
|
|
2634
|
+
"This is a project generated by the AgentCore CLI!
|
|
2352
2635
|
|
|
2353
2636
|
# Layout
|
|
2354
2637
|
|
|
2355
|
-
|
|
2356
|
-
|
|
2638
|
+
The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
|
|
2639
|
+
\`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
|
|
2357
2640
|
commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
|
|
2358
2641
|
|
|
2359
|
-
##
|
|
2642
|
+
## Agent Root
|
|
2360
2643
|
|
|
2361
|
-
The main entrypoint to your app is defined in \`
|
|
2644
|
+
The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
|
|
2362
2645
|
file defines a Starlette ASGI app with the chosen Agent framework SDK running within.
|
|
2363
2646
|
|
|
2364
|
-
\`
|
|
2647
|
+
\`model/load.py\` instantiates your chosen model provider.
|
|
2365
2648
|
|
|
2366
2649
|
## Environment Variables
|
|
2367
2650
|
|
|
2368
|
-
| Variable
|
|
2369
|
-
|
|
|
2370
|
-
| \`
|
|
2371
|
-
| \`
|
|
2372
|
-
| \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
|
|
2373
|
-
| \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
|
|
2651
|
+
| Variable | Required | Description |
|
|
2652
|
+
| --- | --- | --- |
|
|
2653
|
+
{{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
|
|
2654
|
+
{{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
|
|
2374
2655
|
|
|
2375
2656
|
# Developing locally
|
|
2376
2657
|
|
|
@@ -2440,7 +2721,11 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/st
|
|
|
2440
2721
|
"from strands import Agent, tool
|
|
2441
2722
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
2442
2723
|
from model.load import load_model
|
|
2724
|
+
{{#if hasGateway}}
|
|
2725
|
+
from mcp_client.client import get_all_gateway_mcp_clients
|
|
2726
|
+
{{else}}
|
|
2443
2727
|
from mcp_client.client import get_streamable_http_mcp_client
|
|
2728
|
+
{{/if}}
|
|
2444
2729
|
{{#if hasMemory}}
|
|
2445
2730
|
from memory.session import get_memory_session_manager
|
|
2446
2731
|
{{/if}}
|
|
@@ -2449,7 +2734,11 @@ app = BedrockAgentCoreApp()
|
|
|
2449
2734
|
log = app.logger
|
|
2450
2735
|
|
|
2451
2736
|
# Define a Streamable HTTP MCP Client
|
|
2452
|
-
|
|
2737
|
+
{{#if hasGateway}}
|
|
2738
|
+
mcp_clients = get_all_gateway_mcp_clients()
|
|
2739
|
+
{{else}}
|
|
2740
|
+
mcp_clients = [get_streamable_http_mcp_client()]
|
|
2741
|
+
{{/if}}
|
|
2453
2742
|
|
|
2454
2743
|
# Define a collection of tools used by the model
|
|
2455
2744
|
tools = []
|
|
@@ -2461,6 +2750,11 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
2461
2750
|
return a+b
|
|
2462
2751
|
tools.append(add_numbers)
|
|
2463
2752
|
|
|
2753
|
+
# Add MCP client to tools if available
|
|
2754
|
+
for mcp_client in mcp_clients:
|
|
2755
|
+
if mcp_client:
|
|
2756
|
+
tools.append(mcp_client)
|
|
2757
|
+
|
|
2464
2758
|
|
|
2465
2759
|
{{#if hasMemory}}
|
|
2466
2760
|
def agent_factory():
|
|
@@ -2475,7 +2769,7 @@ def agent_factory():
|
|
|
2475
2769
|
system_prompt="""
|
|
2476
2770
|
You are a helpful assistant. Use tools when appropriate.
|
|
2477
2771
|
""",
|
|
2478
|
-
tools=tools
|
|
2772
|
+
tools=tools
|
|
2479
2773
|
)
|
|
2480
2774
|
return cache[key]
|
|
2481
2775
|
return get_or_create_agent
|
|
@@ -2491,7 +2785,7 @@ def get_or_create_agent():
|
|
|
2491
2785
|
system_prompt="""
|
|
2492
2786
|
You are a helpful assistant. Use tools when appropriate.
|
|
2493
2787
|
""",
|
|
2494
|
-
tools=tools
|
|
2788
|
+
tools=tools
|
|
2495
2789
|
)
|
|
2496
2790
|
return _agent
|
|
2497
2791
|
{{/if}}
|
|
@@ -2524,27 +2818,80 @@ if __name__ == "__main__":
|
|
|
2524
2818
|
`;
|
|
2525
2819
|
|
|
2526
2820
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/mcp_client/__init__.py should match snapshot 1`] = `
|
|
2527
|
-
"
|
|
2821
|
+
"# Package marker
|
|
2528
2822
|
"
|
|
2529
2823
|
`;
|
|
2530
2824
|
|
|
2531
2825
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/mcp_client/client.py should match snapshot 1`] = `
|
|
2532
|
-
"
|
|
2826
|
+
"import os
|
|
2827
|
+
import logging
|
|
2828
|
+
from mcp.client.streamable_http import streamablehttp_client
|
|
2533
2829
|
from strands.tools.mcp.mcp_client import MCPClient
|
|
2534
2830
|
|
|
2831
|
+
logger = logging.getLogger(__name__)
|
|
2832
|
+
|
|
2833
|
+
{{#if hasGateway}}
|
|
2834
|
+
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
|
|
2835
|
+
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
|
|
2836
|
+
{{/if}}
|
|
2837
|
+
{{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
|
|
2838
|
+
from bedrock_agentcore.identity import requires_access_token
|
|
2839
|
+
{{/if}}
|
|
2840
|
+
|
|
2841
|
+
{{#each gatewayProviders}}
|
|
2842
|
+
{{#if (eq authType "CUSTOM_JWT")}}
|
|
2843
|
+
@requires_access_token(
|
|
2844
|
+
provider_name="{{credentialProviderName}}",
|
|
2845
|
+
scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
|
|
2846
|
+
auth_flow="M2M",
|
|
2847
|
+
)
|
|
2848
|
+
def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
|
|
2849
|
+
"""Obtain OAuth access token via AgentCore Identity for {{name}}."""
|
|
2850
|
+
return access_token
|
|
2851
|
+
|
|
2852
|
+
{{/if}}
|
|
2853
|
+
{{/each}}
|
|
2854
|
+
{{#each gatewayProviders}}
|
|
2855
|
+
def get_{{snakeCase name}}_mcp_client() -> MCPClient | None:
|
|
2856
|
+
"""Returns an MCP Client connected to the {{name}} gateway."""
|
|
2857
|
+
url = os.environ.get("{{envVarName}}")
|
|
2858
|
+
if not url:
|
|
2859
|
+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
|
|
2860
|
+
return None
|
|
2861
|
+
{{#if (eq authType "AWS_IAM")}}
|
|
2862
|
+
return MCPClient(lambda: aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore", aws_region=os.environ.get("AWS_REGION", os.environ.get("AWS_DEFAULT_REGION"))))
|
|
2863
|
+
{{else if (eq authType "CUSTOM_JWT")}}
|
|
2864
|
+
token = _get_bearer_token_{{snakeCase name}}()
|
|
2865
|
+
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
|
2866
|
+
return MCPClient(lambda: streamablehttp_client(url, headers=headers))
|
|
2867
|
+
{{else}}
|
|
2868
|
+
return MCPClient(lambda: streamablehttp_client(url))
|
|
2869
|
+
{{/if}}
|
|
2870
|
+
|
|
2871
|
+
{{/each}}
|
|
2872
|
+
def get_all_gateway_mcp_clients() -> list[MCPClient]:
|
|
2873
|
+
"""Returns MCP clients for all configured gateways."""
|
|
2874
|
+
clients = []
|
|
2875
|
+
{{#each gatewayProviders}}
|
|
2876
|
+
client = get_{{snakeCase name}}_mcp_client()
|
|
2877
|
+
if client:
|
|
2878
|
+
clients.append(client)
|
|
2879
|
+
{{/each}}
|
|
2880
|
+
return clients
|
|
2881
|
+
{{else}}
|
|
2535
2882
|
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
|
|
2536
2883
|
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
|
|
2537
2884
|
|
|
2538
2885
|
def get_streamable_http_mcp_client() -> MCPClient:
|
|
2539
|
-
"""
|
|
2540
|
-
Returns an MCP Client compatible with Strands
|
|
2541
|
-
"""
|
|
2886
|
+
"""Returns an MCP Client compatible with Strands"""
|
|
2542
2887
|
# to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
|
|
2543
|
-
return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
|
|
2888
|
+
return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
|
|
2889
|
+
{{/if}}
|
|
2890
|
+
"
|
|
2544
2891
|
`;
|
|
2545
2892
|
|
|
2546
2893
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/model/__init__.py should match snapshot 1`] = `
|
|
2547
|
-
"
|
|
2894
|
+
"# Package marker
|
|
2548
2895
|
"
|
|
2549
2896
|
`;
|
|
2550
2897
|
|
|
@@ -2692,8 +3039,11 @@ dependencies = [
|
|
|
2692
3039
|
"bedrock-agentcore >= 1.0.3",
|
|
2693
3040
|
"botocore[crt] >= 1.35.0",
|
|
2694
3041
|
{{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
|
|
2695
|
-
{{/if}}
|
|
3042
|
+
{{/if}}"mcp >= 1.19.0",
|
|
3043
|
+
{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
|
|
2696
3044
|
{{/if}}"strands-agents >= 1.13.0",
|
|
3045
|
+
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
3046
|
+
{{/if}}{{/if}}
|
|
2697
3047
|
]
|
|
2698
3048
|
|
|
2699
3049
|
[tool.hatch.build.targets.wheel]
|
|
@@ -2701,7 +3051,10 @@ packages = ["."]
|
|
|
2701
3051
|
"
|
|
2702
3052
|
`;
|
|
2703
3053
|
|
|
2704
|
-
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/__init__.py should match snapshot 1`] = `
|
|
3054
|
+
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/__init__.py should match snapshot 1`] = `
|
|
3055
|
+
"# Package marker
|
|
3056
|
+
"
|
|
3057
|
+
`;
|
|
2705
3058
|
|
|
2706
3059
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/session.py should match snapshot 1`] = `
|
|
2707
3060
|
"import os
|