operata/operata-mcp-recipes
The runnable version of everything on this page: the deploy scripts, the Lambda code, and a teardown. Fork it, set six values, run three scripts.
Use cases
The shape is the same wherever something automated needs evidence from Operata:- A monitoring alarm fires. The Lambda passes the alarm detail to the model, which queries traces and agent reports, and posts a diagnosis to the incident channel before anyone opens a dashboard.
- A support ticket arrives naming a bad call. The Lambda passes the contact ID, and the model returns that call’s media quality, the agent’s device and network conditions, and what the agent reported.
- A scheduled run each morning. The model compares yesterday against the fleet baseline and writes up the sites, carriers, or agents that moved.
How it works
Your Lambda keeps owning the workflow. The gateway sits between it and Operata, and the Operata API key lives in the gateway rather than in your function. The gateway authenticates on both sides. Inbound isAWS_IAM, so the Lambda execution role signs each request with SigV4 — no Amazon Cognito user pool, no client secret, and no token cache to run. Outbound is the Operata API key, which the gateway reads from the credential provider and sends as a bearer token.
Before you start
- An AWS account with Bedrock model access for Claude, in a region where AgentCore Gateway is available. This recipe was deployed and verified in
us-west-2. - Permission to create IAM roles, AgentCore gateways and targets, and a Lambda function.
git, AWS CLI v2,curl7.75 or later,jq, andzip. The scripts sign gateway calls withcurl --aws-sigv4.- An Operata API key, created in the Operata console at
app.operata.iounder Group Settings → API Management → Create New Key.
https://api.operata.io/v1/mcp.
Why this recipe uses an API key
Operata’s authorization server advertises theauthorization_code and refresh_token grant types. Every OAuth token it issues is bound to a person who consented in a browser, which does not suit a Lambda that a monitoring alarm triggers with nobody present. The API-key endpoint is the path for unattended callers.
For a Lambda, that trade is narrow: the key is fixed to one Operata group, and all activity is attributed to the key rather than to an individual. See Choose how to connect for how the two paths differ across clients.
Quickstart
deploy-gateway.sh checks your key against Operata before it creates anything in AWS, so a rejected key fails in the first few seconds rather than part-way through. Both deploy scripts are re-runnable: they reuse what exists and update it in place. ./scripts/teardown.sh removes everything they made.
The rest of this page explains what those scripts build, so you can read the result or rebuild it yourself.
What the deploy creates
Four AWS resources, in order. Each one exists for a reason worth knowing before you run it.A gateway service role
The gateway assumes this role to fetch your Operata key at call time. Trustbedrock-agentcore.amazonaws.com, and condition that trust on your own account so no other account can assume it:
bedrock-agentcore:GetWorkloadAccessToken and GetResourceApiKey to fetch the credential, secretsmanager:GetSecretValue on arn:aws:secretsmanager:<region>:<account-id>:secret:bedrock-agentcore* to read where AgentCore stored it, and SynchronizeGatewayTargets to re-index the tool catalogue.
A credential provider holding the Operata key
AgentCore Identity takes the key and writes it to AWS Secrets Manager under abedrock-agentcore prefix, which is what that secret ARN pattern above matches.
The key never reaches your Lambda, your deployment package, or the model. Only the gateway reads it.
The gateway
--authorizer-type AWS_IAM is what removes the token plumbing: callers prove who they are with SigV4, using credentials they already hold. searchType: SEMANTIC adds a tool the model can use to search the tool catalogue, so it carries fewer schemas in context.
The scripts also set exceptionLevel: DEBUG, which returns readable target errors while you build. Remove it before production, because it exposes upstream detail in responses.
A target pointing at Operata
The target names the Operata endpoint and says where the credential goes. Operata authenticates withAuthorization: Bearer <api key>, so the key goes in the standard header with a Bearer prefix:
tools/list upstream and index what it finds, so the target reaching READY confirms the key and the endpoint agree.
The target name becomes a prefix on every tool it exposes. With the target named operata, the traces_query tool arrives as operata___traces_query — three underscores.
Full scripts, including the polling and the re-run handling: scripts/deploy-gateway.sh.
Verify
x_amz_bedrock_agentcore_search, comes from the gateway because searchType is SEMANTIC. It lets the model search the tool catalogue instead of carrying every schema in context.
To exercise the credential against a single tool, call one directly:
Use it in your own Lambda
Three files inlambda/ are the whole integration:
mcp_gateway_client.py— an MCP client that signs each request with SigV4 and negotiates the protocol version from what the gateway advertises. Standard library andbotocoreonly, both already in the Lambda Python runtime, so the deployment package needs no vendored dependencies.incident_agent.py— the Bedrock Converse tool-calling loop.handler.py— turns an incident event into a prompt and returns the diagnosis with a trace of every tool call.
GATEWAY_URL and MODEL_ID. The loop itself is short — hand the gateway’s tools to converse, run whatever the model asks for, and send the results back until it stops asking:
toolResult with status: "error" rather than raising. The model reads the message and adjusts its next call.
Beyond writing logs, the execution role needs two statements: bedrock:InvokeModel, and bedrock-agentcore:InvokeGateway on the gateway ARN. That second one is the inbound half of AWS_IAM auth — the role itself is what authorizes the call.
What you get
run-incident.sh prints each tool call the model makes, then its diagnosis. One run against the sample incident took 9 turns and 12 tool calls. The model chose the sequence itself, starting with get_schema so the fields in its later queries would exist.
Its conclusion: 130 calls averaging MOS 2.93 against a fleet baseline of 3.90, with jitter at 37.8 ms against 11.3 ms and round-trip time at 458 ms against 95 ms — all on one internet service provider in one city, which is narrow enough to raise with that provider.
These figures, and the ones in the opening, come from a single account on one day. Your turn count, token count, and numbers will differ.
Limits
- An API key is fixed to the group it was created in. Calling
switch_groupfor a different group returns403 "API key access is restricted to its own group". Switching to the key’s own group succeeds. - 100 requests per minute per key, shared across every caller of the gateway. See Rate limits.
- The gateway indexes the tool list when you create the target. After Operata changes a tool, re-run
deploy-gateway.shor callSynchronizeGatewayTargetsto pick up the new schema. - Remove
exceptionLevel: DEBUGbefore production.
Troubleshooting
More failure modes in MCP troubleshooting.
Related
- operata/operata-mcp-recipes — the scripts, the Lambda code, and a teardown.
- Operata MCP server — authentication, groups, and regions.
- MCP tool reference — what each tool takes and returns.
- API authentication — where Operata credentials come from.
- MCP server targets — AWS documentation.
- Bedrock Converse tool use — AWS documentation.