Connects Claude to a personal AWS Bedrock AgentCore Topic Briefing Harness — a deployed agent with its own model, web search, memory, and Bedrock Guardrails — and adds a skill that relays its finished briefings.
This plugin is a client only — it doesn't deploy anything. The Harness (and the AgentCore Gateway it calls internally for web search) is deployed and managed by a separate, open-source project: aws-agentcore-web-search-demo. Deploy that first; this plugin just needs its HARNESS_NAME, GUARDRAIL_NAME, and AWS_REGION (see "Configuration" below).
| Component | Purpose |
|---|---|
MCP server agentcore-harness |
Local stdio MCP server (servers/agentcore_harness_proxy.py) exposing one tool, topic_briefing, that invokes the deployed Harness with your AWS credentials and returns its finished, guardrail-screened answer. |
Skill topic-briefing |
Triggers on requests for briefings, news summaries, or "what's happening with X"; tells Claude to call the tool once and relay its answer rather than re-searching or rewriting it. |
An earlier version of this plugin connected directly to the AgentCore Gateway's Web Search tool: Claude called the search tool itself and did its own reasoning and formatting. This version instead calls the Harness — a fully deployed agent that does the searching, reasoning, memory, and safety screening on its own, using its own model (not Claude) — and simply returns the finished briefing. Claude's job here is to ask the question and present the answer, not to research it.
flowchart TD
You(["You: 'briefing on...'"])
Skill["topic-briefing skill triggers"]
Claude["Claude calls topic_briefing"]
Proxy["agentcore-harness MCP server"]
Creds["Your AWS credentials<br/>(SSO / profile / etc.)"]
Harness["AgentCore Harness<br/>own model + web search + guardrails"]
Relay["Claude pastes the answer back verbatim"]
You --> Skill --> Claude --> Proxy
Proxy -->|SigV4| Creds --> Harness
Harness -->|finished, cited briefing| Proxy --> Relay --> You
That's the request path; the diagram below shows the same flow one layer down, by technology rather than by step:
flowchart TD
subgraph Local["Local (your Mac)"]
Claude["Claude desktop app"]
MCP["MCP stdio server<br/>Python + vendored boto3/botocore"]
end
subgraph IAM["AWS IAM"]
Cred["Credential chain<br/>SSO session / named profile / role"]
end
Guardrails["Amazon Bedrock Guardrails<br/>ApplyGuardrail (input + output)"]
subgraph AgentCore["Amazon Bedrock AgentCore"]
Harness["AgentCore Harness<br/>hosted agent runtime"]
Model["Bedrock model hosting<br/>Mantle inference profile"]
Memory["AgentCore Memory<br/>managed, SUMMARIZATION strategy"]
Gateway["AgentCore Gateway<br/>+ Web Search target"]
end
Claude <-->|MCP JSON-RPC over stdio| MCP
MCP -->|SigV4-signed requests| Cred
MCP -->|ApplyGuardrail: input| Guardrails
MCP -->|InvokeHarness| Harness
Harness -->|inference calls| Model
Harness <-->|session summaries| Memory
Harness -->|internal tool call| Gateway
Harness -->|response text| MCP
MCP -->|ApplyGuardrail: output| Guardrails
The Gateway-based version needed Cognito client_credentials because the Gateway's MCP endpoint is a machine-to-machine API meant to be called by arbitrary clients. The Harness is different: it's invoked through the AWS Bedrock AgentCore control/data-plane APIs (invoke_harness, list_guardrails, apply_guardrail), which are plain AWS IAM-authenticated API calls, signed with SigV4. There's no separate OAuth layer to configure — whatever AWS credentials are already available to python3 when Claude runs this server are what get used.
Unlike the old Cognito-based version, nothing in this plugin's .env is a secret — AWS_REGION, HARNESS_NAME, and GUARDRAIL_NAME are just deployment identifiers, and AWS_PROFILE is just a profile name. Authentication comes entirely from your ambient AWS credential chain (SSO session, default profile, exported env vars, etc.), never from anything written to disk by this plugin. Because of that, the built .plugin file ships with .env already filled in — installing it works with no manual setup step. If you're building the .plugin yourself, create your own first (it's gitignored, not part of the repo):
cp .env.template .envThen edit .env: fill in the three required values, and uncomment (remove the leading # from) whichever optional lines you actually want to set. Your filled-in .env gets bundled into the .plugin as-is (see "Building the installable .plugin file" below).
Three required values (from your Harness deployment): AWS_REGION, HARNESS_NAME, GUARDRAIL_NAME. Two optional values:
AWS_PROFILE— pins boto3 to a named profile in~/.aws/config. Leave unset and boto3 falls back to the profile literally nameddefault(orAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYenvironment variables, if those happen to be set) — not "whichever profile you last used." If your real profile isn't nameddefault, set this explicitly.HARNESS_ACTOR_ID— a stable, non-secret identifier used for the Harness's 30-day managed memory. Defaults to your local OS username.
To point an installed copy at a different deployment or a different AWS profile, edit .env in place (see "Using this with a different Harness deployment" below for where that file lives once installed) — no reinstall required, just reconnect the server.
Nothing in this plugin stores or transmits AWS credentials. The server never reads or writes access keys itself; it just tells boto3 which profile to use and lets boto3's standard credential chain do the rest. If your profile relies on SSO, make sure you're logged in (aws sso login --profile <name>) before the credentials are needed — boto3 won't interactively prompt you from inside an MCP server.
If you hand this .plugin file to a teammate, their AWS_PROFILE almost certainly won't match yours. HARNESS_NAME/GUARDRAIL_NAME/AWS_REGION describe the shared deployment and are fine as-is; they should delete or replace the AWS_PROFILE line in .env (in their installed copy) to either use their own profile name or fall back to their default AWS credentials.
At minimum, matching what the Harness's own invocation script requires:
bedrock:ListGuardrailsbedrock:ApplyGuardrailbedrock-agentcore:ListHarnessesbedrock-agentcore:GetHarnessbedrock-agentcore:InvokeHarness
The server generates one Harness runtimeSessionId when it starts and reuses it for every topic_briefing call in that process — in practice, one chat maps to one Harness conversation, so follow-up questions in the same chat share the Harness's 30-day summarized memory. A new chat (new server process) starts a fresh Harness session.
Edit .env in the installed plugin directory with that deployment's AWS_REGION, HARNESS_NAME, and GUARDRAIL_NAME, and point AWS_PROFILE at credentials authorized against that account/region.
First populate vendor/ (a trimmed, self-contained copy of boto3 + botocore, so the plugin never needs pip or network access at runtime — see "Why this is vendored, not pip-installed" below):
python -m pip install virtualenv -Uq --break-system-packages
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
./scripts/build_vendor.shThen, from the repository root, with your own filled-in .env present (this gets bundled intentionally — see "Configuration" above for why that's safe for this version):
zip -r agentcore-web-search.plugin . \
-x ".git/*" -x ".git/**/*" -x "*.pyc" -x "**/__pycache__/*" \
-x ".claude/*" -x ".claude/**/*"An earlier version of this plugin tried self-installing boto3 via pip on first run, targeting whichever interpreter Claude happened to spawn the script with. That turned out to be unreliable in practice — hard to distinguish "still installing, give it a moment" from "silently failing forever," and plausibly blocked outright if the host app sandboxes its subprocesses' network access. Vendoring removes the failure mode entirely: nothing to install, nothing that can time out, nothing that depends on outbound network access from a spawned subprocess. vendor/ is gitignored (rebuild it locally with the script above) since it's a build artifact, not source.
Claude for Mac (tested path): drag the built .plugin file into a chat (or use the upload control) and click Install on the resulting file card. Plugin changes don't hot-reload into an already-open conversation — after installing an update, test from a new chat.
Claude Code: this repo doesn't yet include a .claude-plugin/marketplace.json, which Claude Code's plugin installer requires (/plugin marketplace add + /plugin install). Not built here; ask if you want this added.
Just ask normally — e.g. "give me a briefing on the biggest AI announcements this week." Claude calls the Harness and relays its answer. No manual invocation needed.
- Server shows disconnected, no clear error — as of
v1.2.0, boto3 ships vendored invendor/next to the script, so there should be nothing to install at all. Ifvendor/is missing from the installed plugin (e.g. you built the.pluginwithout runningscripts/build_vendor.shfirst), the server falls back to self-installing boto3 via pip for whichever interpreter Claude spawned it with — which is the less reliable path this version exists to avoid. Rebuild withvendor/present and reinstall. - Error mentions
boto3 not foundand gives a manual install command — this only happens whenvendor/wasn't bundled. Either run the exact command shown (<that interpreter> -m pip install boto3), or rebuild the.pluginwithscripts/build_vendor.shrun first. Unknown service: 'sso'(or'sso-oidc','signin') — the vendoredbotocore/datais missing one of the services botocore's own credential resolution needs internally for SSO-based profiles. Fixed as ofv1.3.0'sscripts/build_vendor.sh; if you're building from an older checkout, pull latest and rebuildvendor/.Error loading SSO Token: Token for <session> does not exist/UnauthorizedSSOTokenError— this is a real, separate problem from the one above: your SSO session has expired or was never started. Runaws sso login --profile <name>(this writes a token cache to~/.aws/sso/cache/, which is shared across all processes reading your AWS config — not scoped to the terminal session you ran it from).- Server shows disconnected, error mentions a missing
.envsetting — one ofAWS_REGION,HARNESS_NAME, orGUARDRAIL_NAMEisn't set; the stderr message names which one. - "Guardrail ... was not found" —
GUARDRAIL_NAMEdoesn't match a guardrail your AWS credentials/profile can see in that region, or the guardrail isn'tREADY. - "Harness ... was not found" — same, for
HARNESS_NAME. Checkbedrock-agentcore:ListHarnesses/GetHarnesspermissions and that the Harness is actually deployed andREADYin that region. ExpiredTokenException/UnrecognizedClientException/ similar credential errors — the AWS credentials behindAWS_PROFILE(or the default chain) are missing, expired, or not authorized. For SSO profiles, runaws sso login --profile <name>in Terminal, then retry.- "Safety guardrail blocked input/output content" — the Guardrail rejected the question or the generated answer under its configured policy; this is expected behavior, not a bug.
- A plugin update seems to have no effect — the app doesn't hot-reload an already-running session when a plugin changes mid-conversation. Reinstall the updated
.pluginand test from a fresh chat.
v1.0.0 replaces the earlier Cognito/Gateway-based design (raw web search, Claude does its own reasoning) with this AWS IAM/Harness-based design (Claude relays a finished answer from a separately deployed agent). The two approaches aren't compatible — this version does not use Cognito, Keychain, or the Gateway MCP endpoint at all.
v1.1.0 had the server self-install boto3 via pip on first run, targeting whichever interpreter Claude spawned it with. v1.2.0 replaced that with a vendored copy (see "Why this is vendored, not pip-installed" above) after the pip approach proved unreliable in practice.
v1.2.0's vendored botocore/data only included the services this plugin calls directly (bedrock, bedrock-runtime, bedrock-agentcore, bedrock-agentcore-control, sts), which broke SSO-based AWS_PROFILE values with Unknown service: 'sso' — botocore's own credential resolution constructs internal sso/sso-oidc/signin clients to exchange a cached SSO token for real credentials, and that data wasn't there. v1.3.0 adds those three services to the vendor build (see scripts/build_vendor.sh).
v1.3.1 tightens the topic-briefing skill's instructions after Claude was observed reformatting a correctly-formatted Harness response (proper ## What happened/## Why it matters/## Sources contract, numbered citations) into its own bulleted prose, dropping the ## Why it matters section and collapsing numbered sources into a plain sentence. The skill now says explicitly to paste the tool's response through verbatim rather than "present it largely as-is," which wasn't forceful enough.
