Note: This project code was created with Cursor using Codex 5.3.
Python-first proof-of-concept web app with:
- Browser chat UI
- Server that hosts the frontend and API
- Persistent multi-chat management in SQLite (create/select/delete/clear)
- Chat rename support
- Single local user model stored in DB (preparation for multi-user)
- Agent connected to AWS Bedrock
- MCP tool execution through a separate collocated MCP client layer
- Streaming token output in chat UI
- Status badges for agent mode and MCP reachability
- Clear conversation button
No user authentication is included (per PoC scope).
Note: the app supports either a single MCP server endpoint or multiple named MCP servers.
Use this path if you want the app running quickly before exploring details.
- macOS or Linux shell environment
- Python 3.11+
make- OpenSSL CLI (
openssl) nginx(required formake upflow)- Optional: AWS CLI credentials if you want live Bedrock responses
- Clone and enter repo:
git clone <your-public-repo-url>
cd ai-agent-webapp-oss- Create local env file from template:
cp environment.env.example environment.env- Set minimum required values in
environment.env:
HTTPS_PORT=3000CHAT_DB_PATH=data/chat.dbAPP_USER_ID=local-userAPP_USER_NAME=Local User
- Install dependencies:
pip install -r requirements.txt- Start app stack:
make up- Validate:
make status
curl -k -i https://localhost:3000/api/status- Open in browser:
- Browser UI loads over HTTPS on port 3000.
GET /api/statusreturns HTTP200.- You can create chats and see persisted history across restarts.
- If Bedrock is not configured yet, app still runs in non-Bedrock mode.
app/web_app_server.py- FastAPI app, static hosting, chat APIapp/agent/bedrock_agent.py- Bedrock agent logicapp/mcp/mcp_transport_client.py- MCP JSON-RPC transport client (HTTP/stdio)static/index.html+static/app.js- browser UI
-
Create env file:
cp environment.env.example environment.env
-
Set values in
environment.env:HTTPS_PORT(where your TLS app listens)ENABLE_HSTS(trueby default)CHAT_DB_PATH(SQLite database path, defaultdata/chat.db)APP_USER_ID(current local user id, defaultlocal-user)APP_USER_NAME(current local user display name)AWS_REGIONBEDROCK_MODEL_IDMCP_SERVER_URL(single-server mode, streamable HTTP)MCP_SERVER_NAME(single-server display name, defaultcatalyst-center)MCP_HEALTH_URL(single-server optional health endpoint)MCP_SERVERS_JSON(multi-server mode; object or array of named servers)MCP_API_KEY(optional; sent asX-API-Keyto remote MCP servers)MCP_VERIFY_TLS(trueby default)MCP_CA_CERT(optional custom CA path)
environment.env is loaded first, then .env is loaded as a fallback.
Chat data is persisted in SQLite at CHAT_DB_PATH, so chats survive backend restarts.
Each server in MCP_SERVERS_JSON can define one of:
transport: "streamable_http"withurl(and optionalhealth_url)transport: "stdio"withcommandand optionalargs,cwd,env
Example mixed configuration:
[
{
"name": "remote-http",
"transport": "streamable_http",
"url": "http://127.0.0.1:8001/mcp/",
"health_url": "http://127.0.0.1:8001/health",
"headers": {
"X-API-Key": "${MCP_API_KEY}"
}
},
{
"name": "local-stdio",
"transport": "stdio",
"command": "python",
"args": ["-m", "my_mcp_server"]
}
]Remote MCP auth:
- If
MCP_API_KEYis set, the webapp MCP client automatically sendsX-API-Keyon remote MCP requests. - You can override/add per-server headers explicitly via
MCP_SERVERS_JSON[*].headers.
From project root:
make upmake up now performs a restart sequence:
- stops existing webapp processes
- starts webapp (nginx + backend)
Useful targets:
make down # stop webapp stack
make status # check webapp statusUse your existing virtual environment in this folder:
source .venv/bin/activate
pip install -U pip
pip install -e .
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
-keyout certs/local-dev.key \
-out certs/local-dev.crt \
-subj "/CN=localhost"
uvicorn app.web_app_server:app --host 0.0.0.0 --port 3000 --reload \
--ssl-keyfile certs/local-dev.key \
--ssl-certfile certs/local-dev.crtOpen:
HTTP redirect listener is intentionally disabled in this setup. Use HTTPS directly.
- Install nginx (macOS/Homebrew):
brew install nginx- Start app behind nginx (single command):
bash scripts/start_with_nginx.shThis starts:
- backend on
127.0.0.1:3001(HTTP, internal only) - nginx HTTPS proxy on
https://localhost:3000
Override ports if needed:
BACKEND_PORT=3101 HTTPS_PROXY_PORT=3443 bash scripts/start_with_nginx.sh- In
environment.env:
AWS_REGION=us-east-1
BEDROCK_MODEL_ID=anthropic.claude-sonnet-4-20250514-v1:0- Configure AWS credentials on the host (example):
aws configure- Restart backend and verify
/api/statusreturns:
agent_mode=bedrockbedrock_enabled=truebedrock_configured=true
- HTTPS is the only frontend listener in this setup.
- HSTS is enabled when
ENABLE_HSTS=true. - MCP HTTPS uses TLS verification by default (
MCP_VERIFY_TLS=true). - For self-signed MCP certs in dev, set
MCP_CA_CERTto your CA file.
For baseline PoC tool testing from chat input:
/tool <tool_name> {"key":"value"}
The server forwards this to MCP using JSON-RPC tools/call.
Use the MCP Tools panel in the UI (Refresh tools) to verify tool discovery from your local MCP server.
When multiple MCP servers are configured:
- Use
server::tool_nameto target one server explicitly. - For duplicate tool names, calling unqualified
tool_namefans out to all matching servers. - You can force a server with tool args using
{"__mcp_server":"server-name"}.
GET /api/health- liveness checkGET /api/status- current agent mode and MCP connectivityGET /api/me- current user identityGET /api/mcp/tools- list merged tools from all configured MCP serversGET /api/mcp/tools?server=<name>- list tools for one specific MCP serverGET /api/chats- list chatsPOST /api/chats- create chatGET /api/chats/{chat_id}- get one chat + conversationPATCH /api/chats/{chat_id}- rename a chatDELETE /api/chats/{chat_id}- delete a chatPOST /api/chats/{chat_id}/clear- clear a specific chatPOST /api/chat/clear- clears the in-memory conversationPOST /api/chat- non-streaming chat responsePOST /api/chat/stream- Server-Sent Events token stream
- Default consolidated log file:
logs/ai_agent_webapp.log - Launcher + backend + nginx entries are written to the same file.
- Uvicorn access noise is reduced so nginx access lines are the primary request log source.
make up
make status
curl -k -i https://localhost:3000/api/statusExpected:
- HTTP
200from/api/status - MCP server connectivity is reported in
/api/statuswhen configured
- Port conflict (
3000already in use): setHTTPS_PORTto another value inenvironment.env, then rerunmake up. make upfails becausenginxis missing: install it (brew install nginxon macOS) and retry.- TLS warning in browser: expected for local/self-signed certs; proceed in local dev only.
bedrock_configured=false: setAWS_REGIONandBEDROCK_MODEL_ID, then runaws configure.- MCP tools not visible: verify
MCP_SERVER_URLorMCP_SERVERS_JSONvalues, then use the UI "Refresh tools" button.
- This project is a PoC/demo and is not production-hardened.
- Do not commit
environment.env; keep secrets only in local env files or a secret manager. - This public repo intentionally uses
environment.env.exampleas the safe template.
This repository is distributed under the terms in LICENSE (Cisco Sample Code License 1.1).
See NOTICE for copyright information.