Skip to main content
Glama
sridharbabukodavaluru

AgentCore MCP Reverse Connector

README.md
# AgentCore MCP Reverse Connector on Amazon EKS

This project deploys a minimal MCP-compatible Python tool server on Amazon EKS. The pod opens an outbound secure WebSocket connection to `AGENTCORE_GATEWAY_ENDPOINT` and authenticates with `AGENTCORE_AUTH_TOKEN`.

The connector implements the MCP JSON-RPC methods required for tool discovery and invocation:

- `initialize`
- `tools/list`
- `tools/call`
- `ping`

It exposes two tools:

- `get_system_info`
- `echo_data`

## Architecture Note

Amazon Bedrock AgentCore Gateway documentation describes Gateway as an MCP endpoint for agents and as a service that can invoke configured targets such as Lambda, OpenAPI, Smithy, and remote MCP server endpoints. A reverse dial-out WebSocket connector requires your AgentCore Gateway endpoint, relay, or fronting service to support a persistent outbound WebSocket contract.

This implementation assumes that contract exists and that the gateway sends MCP JSON-RPC request messages over the WebSocket. If your Gateway is configured for a standard MCP server target instead, expose this server through a normal MCP HTTP/SSE endpoint or put it behind an internal/external load balancer and register that endpoint with AgentCore.

## Project Tree

```text
agentcore-mcp-eks/
├── .dockerignore
├── .gitignore
├── Dockerfile
├── Makefile
├── README.md
├── k8s/
│   ├── base/
│   │   ├── configmap.yaml
│   │   ├── deployment.yaml
│   │   ├── hpa.yaml
│   │   ├── kustomization.yaml
│   │   ├── namespace.yaml
│   │   ├── networkpolicy.yaml
│   │   ├── pdb.yaml
│   │   ├── service.yaml
│   │   └── serviceaccount.yaml
│   └── examples/
│       └── secret.example.yaml
├── requirements.txt
└── src/
    ├── pyproject.toml
    └── agentcore_mcp_server/
        ├── __init__.py
        ├── __main__.py
        ├── config.py
        ├── connector.py
        ├── health.py
        ├── protocol.py
        └── tools.py
```

## Prerequisites

- An existing Amazon EKS cluster with worker nodes that can egress to the AgentCore Gateway endpoint over TCP 443.
- `aws` CLI configured for the target AWS account.
- `kubectl` configured for the EKS cluster.
- Docker or another OCI-compatible image builder.
- Terraform or your preferred IaC workflow if you still need to create EKS.
- A container registry, for example Amazon ECR or GitHub Container Registry.
- Kubernetes Metrics Server if you want the HPA to scale on CPU metrics.
- Known values for:
  - `AGENTCORE_GATEWAY_ENDPOINT`
  - `AGENTCORE_AUTH_TOKEN`

## Build and Publish

Set your image name:

```bash
cd agentcore-mcp-eks
export IMAGE="123456789012.dkr.ecr.us-east-1.amazonaws.com/agentcore-mcp-server"
export TAG="0.1.0"
```

Build and push:

```bash
docker build -t "${IMAGE}:${TAG}" .
docker push "${IMAGE}:${TAG}"
```

Update the Deployment image in `k8s/base/deployment.yaml` or use Kustomize:

```bash
kubectl kustomize k8s/base
```

## Configure Kubernetes

Create the namespace first so the Secret can be created safely:

```bash
kubectl apply -f k8s/base/namespace.yaml
```

Create the auth token secret without storing a real token in Git:

```bash
kubectl -n mcp-system create secret generic agentcore-mcp-secret \
  --from-literal=AGENTCORE_AUTH_TOKEN='replace-with-real-token'
```

Set the gateway endpoint by editing `k8s/base/configmap.yaml`:

```yaml
data:
  AGENTCORE_GATEWAY_ENDPOINT: "wss://gateway.example.com/mcp/reverse"
  MCP_SERVER_NAME: "eks-agentcore-mcp"
```

If you want to use the example Secret manifest instead, copy `k8s/examples/secret.example.yaml`, replace the placeholder, and apply it from a secure private location.

## Deploy

Apply the manifests:

```bash
kubectl apply -k k8s/base
```

Check rollout:

```bash
kubectl -n mcp-system rollout status deployment/agentcore-mcp-server
kubectl -n mcp-system get pods -l app.kubernetes.io/name=agentcore-mcp-server
```

Tail logs:

```bash
kubectl -n mcp-system logs deployment/agentcore-mcp-server -f
```

## Operational Checks

Port-forward the internal service for health checks:

```bash
kubectl -n mcp-system port-forward svc/agentcore-mcp-server 8080:8080
curl -fsS http://127.0.0.1:8080/healthz
curl -fsS http://127.0.0.1:8080/readyz
```

Expected behavior:

- `/healthz` returns `200` when the process is running.
- `/readyz` returns `200` only after the WebSocket connection to the gateway is established.

## Troubleshooting Gateway Connectivity

Check pod environment wiring without printing the token:

```bash
kubectl -n mcp-system describe pod -l app.kubernetes.io/name=agentcore-mcp-server
```

Look for connector log messages:

```bash
kubectl -n mcp-system logs deployment/agentcore-mcp-server --tail=200
```

Common issues:

- `AGENTCORE_GATEWAY_ENDPOINT is required`: the ConfigMap is missing or the key is misspelled.
- `AGENTCORE_AUTH_TOKEN is required`: the Secret is missing or the key is misspelled.
- Repeated connect failures: verify the endpoint starts with `wss://`, DNS resolves from inside the cluster, and node security groups/NACLs permit egress to TCP 443.
- Authentication failures: rotate the Secret and restart the Deployment with `kubectl -n mcp-system rollout restart deployment/agentcore-mcp-server`.
- Readiness never becomes healthy: confirm the gateway supports the reverse WebSocket connector contract and accepts MCP JSON-RPC messages over the socket.
- NetworkPolicy blocks traffic: start by applying the Deployment without `networkpolicy.yaml`, confirm connectivity, then reapply and tighten egress for your CNI.

Run an in-cluster DNS/connectivity test:

```bash
kubectl -n mcp-system run netcheck --rm -it --restart=Never \
  --image=curlimages/curl:8.10.1 -- sh
```

Then inside the shell:

```sh
nslookup gateway.example.com
curl -vk https://gateway.example.com/
```

## Security Notes

- Do not commit real tokens. Use Kubernetes Secrets, External Secrets Operator, AWS Secrets Manager, or Sealed Secrets.
- The container runs as a non-root user with a read-only root filesystem and dropped Linux capabilities.
- The default Service is `ClusterIP`; there is no public inbound endpoint because the server dials out.
- The example NetworkPolicy allows DNS and outbound HTTPS. For strict FQDN egress controls, use a CNI that supports FQDN policies such as Cilium or Calico Enterprise and restrict access to the exact AgentCore Gateway hostname.
- Tool input schemas are fully inlined and do not use JSON Schema `$ref` or `$defs`.

## References

- [Amazon Bedrock AgentCore Gateway overview](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway.html)
- [AgentCore Gateway MCP usage](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-using.html)
- [AgentCore Gateway MCP server targets](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-target-MCPservers.html)
- [MCP Python SDK package](https://pypi.org/project/mcp/)