Batteries Plus MCP Demo Server
Enables Salesforce Agentforce agents to find compatible replacement batteries, check store inventory, and create store visit summaries for battery service handoffs.
README
Batteries Plus MCP Demo Server
A production-ready Model Context Protocol (MCP) server for the Batteries Plus Service Workflow demo. This server connects Salesforce Agentforce agents to Batteries Plus product catalog, store inventory, and service handoff capabilities.
What This Server Does
This MCP server enables Salesforce Agentforce agents to:
- Find Compatible Replacement Batteries — Match customer vehicles to the right battery using product fit logic
- Check Store Availability — Find nearby stores with inventory and service capabilities
- Create Store Visit Summaries — Generate service handoffs for in-store battery testing and installation
Demo Story: A customer's car won't start. The agent identifies the right replacement battery, checks local availability, and creates a store visit summary—all without human handoff.
What This Server Does NOT Do
This is a service workflow demo, not a transactional system. It explicitly does NOT:
- Create orders, reservations, or POS transactions
- Process payments or checkout flows
- Take employee-attributed actions
Architecture
- MCP SDK:
@modelcontextprotocol/sdkv1.0.4 - Transport: Streamable HTTP (recommended for remote MCP servers)
- Runtime: Node.js 20+ with TypeScript
- Authentication: OAuth 2.0 Client Credentials OR
nonemode for fast testing - Data Storage: In-memory (optionally persisted to
/tmpfor handoffs) - Deployment: Render.com (free tier)
Project Structure
batteries-plus-mcp/
├── src/
│ ├── server.ts # Express + MCP SDK + tool registration
│ ├── auth.ts # OAuth 2.0 implementation
│ ├── data/
│ │ ├── batteries.ts # Vehicle fit database
│ │ └── stores.ts # Store + inventory database
│ ├── services/
│ │ ├── handoffStore.ts # In-memory handoff storage
│ │ └── salesforceWriter.ts # Placeholder for Salesforce integration
│ ├── tools/
│ │ ├── findCompatibleReplacement.ts # MCP tool 1
│ │ ├── checkStoreAvailability.ts # MCP tool 2
│ │ └── createStoreHandoff.ts # MCP tool 3
│ └── utils/
│ ├── ids.ts # Handoff ID generation
│ └── validation.ts # Input validation utilities
├── test/
│ └── smoke.test.js # Basic health checks
├── package.json
├── tsconfig.json
├── render.yaml # Render deployment config
└── .env.example # Environment template
Quick Start
Prerequisites
- Node.js 20+
- npm 9+
Local Development
-
Clone and Install
cd batteries-plus-mcp npm install -
Configure Environment
cp .env.example .envFor fast local testing, use
MCP_AUTH_MODE=none:PORT=3000 NODE_ENV=development MCP_AUTH_MODE=none WRITE_MODE=memory -
Start Dev Server
npm run devThe server starts at
http://localhost:3000with hot-reload enabled. -
Verify Health
curl http://localhost:3000/healthExpected response:
{ "status": "healthy", "service": "batteries-plus-service-mcp", "version": "1.0.0", "auth_mode": "none", "write_mode": "memory", "uptime_seconds": 12.4, "handoffs_created": 0 }
Production Build
npm run build # Compile TypeScript to ./dist
npm start # Run compiled server
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 3000 |
Server port |
NODE_ENV |
No | development |
Runtime environment |
MCP_AUTH_MODE |
No | none |
Auth mode: none or oauth |
MCP_CLIENT_ID |
OAuth only | — | OAuth client ID |
MCP_CLIENT_SECRET |
OAuth only | — | OAuth client secret |
MCP_TOKEN_TTL_SECONDS |
No | 3600 |
Token lifetime (1 hour) |
WRITE_MODE |
No | memory |
Handoff storage: memory or salesforce |
For Render deployment, set MCP_AUTH_MODE=oauth and configure MCP_CLIENT_ID and MCP_CLIENT_SECRET in the Render dashboard.
API Endpoints
GET /health
Health check endpoint. Returns server status, auth mode, uptime, and handoff count.
POST /oauth/token
OAuth 2.0 token endpoint (only active when MCP_AUTH_MODE=oauth).
Request:
curl -X POST https://your-server.onrender.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "mcp.tools"
}
POST /mcp
MCP protocol endpoint. Agentforce sends tool requests here via Streamable HTTP transport.
GET /demo/handoffs
View all store visit summaries created by the agent. Returns HTML in browsers, JSON for API clients.
MCP Tools
1. find_compatible_replacement
Finds a compatible replacement battery for a customer's vehicle.
Input:
{
"vehicle_year": 2019,
"vehicle_make": "Honda",
"vehicle_model": "CR-V",
"vehicle_engine": "1.5L L4",
"postal_code": "53202"
}
Output:
{
"fit_status": "compatible",
"fit_confidence": "high",
"vehicle": {
"year": 2019,
"make": "Honda",
"model": "CR-V",
"engine": "1.5L L4"
},
"recommended_product": {
"sku": "SLI51RAGM",
"name": "X2Power Premium AGM Battery - Group 51R",
"group_size": "51R",
"cold_cranking_amps": 500,
"reserve_capacity_minutes": 90,
"warranty_months": 36,
"install_eligible": true
},
"recommendation_reason": "This battery matches the vehicle's group size and cold-cranking amp requirements."
}
2. check_store_availability
Checks nearby Batteries Plus stores for a specific SKU.
Input:
{
"sku": "SLI51RAGM",
"postal_code": "53202",
"radius_miles": 15
}
Output:
{
"sku": "SLI51RAGM",
"postal_code": "53202",
"availability_status": "available_nearby",
"stores": [
{
"store_id": "BP-MKE-001",
"store_name": "Batteries Plus - Milwaukee East",
"address": "2401 S. Kinnickinnic Ave, Milwaukee, WI 53207",
"distance_miles": 2.3,
"phone": "(414) 555-0101",
"today_hours": "8:00 AM - 7:00 PM",
"quantity_available": 4,
"service_context": {
"battery_testing_available": true,
"installation_available": true,
"estimated_service_time": "20-30 minutes",
"note": "Store can test the current battery before installation."
}
}
]
}
3. create_store_handoff
Creates a store visit summary after the customer selects a store. This tool will block unless customer_confirmed_store is true.
Input:
{
"customer_name": "Jane Doe",
"customer_issue": "Car will not start",
"vehicle_year": 2019,
"vehicle_make": "Honda",
"vehicle_model": "CR-V",
"vehicle_engine": "1.5L L4",
"recommended_sku": "SLI51RAGM",
"recommended_product_name": "X2Power Premium AGM Battery - Group 51R",
"selected_store_id": "BP-MKE-001",
"selected_store_name": "Batteries Plus - Milwaukee East",
"availability_result": "4 units available",
"customer_confirmed_store": true
}
Output:
{
"status": "created",
"handoff_id": "SVS-20260622-1430",
"created_at": "2026-06-22T14:30:12.456Z",
"service_workflow": "Store Visit Summary",
"summary": {
"customer_issue": "Car will not start",
"vehicle": "2019 Honda CR-V 1.5L L4",
"recommended_sku": "SLI51RAGM",
"recommended_product_name": "X2Power Premium AGM Battery - Group 51R",
"selected_store": "Batteries Plus - Milwaukee East",
"availability_result": "4 units available",
"store_note": "Customer may need battery testing before replacement. Store has installation available today."
},
"demo_record_url": "https://example.salesforce.com/lightning/r/Store_Visit_Summary__c/SVS-20260622-1430/view"
}
Testing Locally
Smoke Tests
npm test
Runs basic health checks on /health and /demo/handoffs.
Manual Tool Testing
You can test MCP tools manually using curl (when MCP_AUTH_MODE=none):
Example: List Tools
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
Example: Call Tool
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "find_compatible_replacement",
"arguments": {
"vehicle_year": 2019,
"vehicle_make": "Honda",
"vehicle_model": "CR-V"
}
}
}'
Deploying to Render
Initial Setup
-
Create Render Account
- Sign up at render.com
- Connect your GitHub account
-
Push to GitHub
git init git add . git commit -m "Initial commit: Batteries Plus MCP server" git remote add origin https://github.com/YOUR_USERNAME/batteries-plus-mcp.git git push -u origin main -
Create Render Service
- Dashboard → New + → Web Service
- Connect repository:
batteries-plus-mcp - Render auto-detects
render.yaml✅
-
Configure Environment Variables (in Render dashboard)
MCP_CLIENT_ID=batteries-plus-agentforce-client(or your custom value)MCP_CLIENT_SECRET= Generate a strong secret (e.g.,openssl rand -base64 32)
-
Deploy
- Render automatically builds and deploys
- Wait for "Live" status (2-3 minutes)
-
Note Your MCP Endpoint URL Your server URL will be:
https://batteries-plus-mcp.onrender.comYour MCP Endpoint URL for Salesforce registration is:
https://batteries-plus-mcp.onrender.com/mcp
Health Check
curl https://batteries-plus-mcp.onrender.com/health
Render Free Tier Notes
- Server sleeps after 15 minutes of inactivity
- First request after sleep takes ~30-60 seconds to wake up
- Monthly limit: 750 hours (adequate for demos)
- For production, upgrade to paid tier for always-on service
Salesforce Agentforce Setup
Step 1: Authenticate Salesforce CLI
If you haven't already authenticated to your Salesforce org:
sf org login web --alias batteries-demo
Use your admin credentials (not the Agentforce agent user credentials).
Step 2: Register the MCP Server in Agentforce Registry
Manual steps (you will do this in the Salesforce UI):
-
Open Salesforce Setup
- Login to your Salesforce org
- Setup → Quick Find → "Agentforce"
-
Register MCP Server
- Agentforce → Agentforce Registry → MCP Servers tab
- Click Register MCP Server
-
Enter Connection Details
Field Value MCP Server Name Batteries Plus ServiceMCP Endpoint URL https://batteries-plus-mcp.onrender.com/mcpAuthorization Token URL https://batteries-plus-mcp.onrender.com/oauth/tokenClient ID batteries-plus-agentforce-clientClient Secret Your MCP_CLIENT_SECRETfrom RenderScope mcp.toolsClick Save & Test Connection. You should see "✅ Connection successful".
-
Manage Tools
- After saving, click Manage Tools
- You should see 3 tools:
find_compatible_replacementcheck_store_availabilitycreate_store_handoff
- Select all 3 and click Allow and Continue
- Click Save
Step 3: Add Tools to Your Agent
-
Open Agentforce Builder
- Setup → Agentforce → Agents
- Select or create your agent (e.g., "Batteries Plus Agent")
-
Add Actions
- In the agent builder, go to Actions & Instructions
- Click Add Action
- Search for "batteries" or "compatible"
- Add all 3 MCP tools:
find_compatible_replacementcheck_store_availabilitycreate_store_handoff
-
Configure Agent Instructions
Add this to your agent instructions:
You are the Batteries Plus Service Agent. You help customers find the right replacement battery, check local store availability, and create store visit summaries. When a customer describes a vehicle issue (e.g., "car won't start"), follow this workflow: 1. Ask for vehicle details: year, make, model (and engine if possible) 2. Use find_compatible_replacement to identify the right battery 3. Ask for customer location (postal code) 4. Use check_store_availability to find nearby stores with inventory 5. Present store options with availability, distance, and services 6. IMPORTANT: Wait for the customer to confirm their store choice 7. Only after confirmation, use create_store_handoff with customer_confirmed_store=true Do not create orders, reservations, or process payments. Your role is to prepare a service handoff for in-store battery testing and installation. -
Activate the Agent
- Click Activate in the agent builder
- Choose your deployment channel (e.g., Salesforce Experience Cloud, Messaging for In-App and Web)
Step 4: Test the Agent
Test Conversation Script:
Customer: My car won't start and I think I need a new battery. I drive a 2019 Honda CR-V and I'm near 53202. Can you help me find the right one nearby?
Expected Agent Behavior:
- Agent calls
find_compatible_replacement→ identifiesSLI51RAGM(X2Power Premium AGM Battery - Group 51R) - Agent calls
check_store_availability→ finds stores near 53202 - Agent presents: "I found the X2Power Premium AGM Battery - Group 51R for your 2019 Honda CR-V. The closest store with availability is Batteries Plus - Milwaukee East (2.3 miles away, 4 units in stock). They offer free battery testing and installation. Would you like me to create a store visit summary?"
- Customer confirms: "Yes, that works for me."
- Agent calls
create_store_handoffwithcustomer_confirmed_store=true - Agent responds: "Great! I've created a store visit summary (ID: SVS-20260622-1430). The store knows you're coming and can test your current battery before replacement. Installation takes 20-30 minutes."
Troubleshooting
Problem: MCP tools don't appear in Agentforce actions picker
- Switch to legacy Agentforce Builder (toggle at top of screen)
- Verify that
Agentforce MCP Support Pilotpermission is enabled on your org
Problem: Connection test fails with "401 Unauthorized"
- Check that
MCP_CLIENT_IDandMCP_CLIENT_SECRETmatch between Render and Salesforce - Verify
MCP_AUTH_MODE=oauthis set in Render environment
Problem: Tools return empty or error responses
- Check Render logs: Dashboard →
batteries-plus-mcp→ Logs - Add debug header in Salesforce: Setup → Named Credentials → Custom Headers →
x-sfdc-mcp-debug=0x3f
Problem: Agent doesn't use MCP tools
- Review agent instructions—ensure tools are mentioned in the workflow
- Check agent trace logs: Agent Builder → Session History → select test session
Development Notes
Adding New Vehicles
Edit src/data/batteries.ts and add entries to the vehicleFitDatabase array:
{
vehicle_year: 2022,
vehicle_make: 'Tesla',
vehicle_model: 'Model 3',
vehicle_engine: 'Electric',
recommended_sku: 'EV12V-AUX',
product_name: 'Auxiliary 12V Battery for Tesla',
group_size: 'Tesla OEM',
cold_cranking_amps: 340,
reserve_capacity_minutes: 50,
warranty_months: 24,
install_eligible: false
}
Adding New Stores
Edit src/data/stores.ts and add entries to the storeDatabase array:
{
store_id: 'BP-CHI-004',
store_name: 'Batteries Plus - Chicago Loop',
postal_codes: ['60601', '60602'],
address: '123 State St, Chicago, IL 60601',
distance_miles: 0.5,
phone: '(312) 555-0200',
today_hours: '9:00 AM - 6:00 PM',
services: ['Battery testing', 'Battery installation', 'Curbside pickup'],
inventory: {
'SLI51RAGM': 3,
'SLI24FAGM': 2,
'SLI35AGM': 5
}
}
Enabling Salesforce Write Mode
This is for future integration. To write handoffs to Salesforce instead of memory:
- Set
WRITE_MODE=salesforcein.env - Add Salesforce credentials:
SF_LOGIN_URL=https://login.salesforce.com SF_CLIENT_ID=<connected_app_consumer_key> SF_CLIENT_SECRET=<connected_app_consumer_secret> SF_USERNAME=<integration_user_username> SF_PASSWORD=<integration_user_password> SF_INSTANCE_URL=https://yourorg.my.salesforce.com - Implement Salesforce REST API calls in src/services/salesforceWriter.ts
Current implementation throws "not yet implemented" when WRITE_MODE=salesforce.
Technical Details
MCP Protocol
This server implements MCP via Streamable HTTP transport (recommended for remote servers). Agentforce sends JSON-RPC 2.0 requests to the /mcp endpoint using Server-Sent Events (SSE) for streaming responses.
Supported Methods:
tools/list— Returns tool schemastools/call— Executes a tool with provided arguments
Authentication Flow
When MCP_AUTH_MODE=oauth:
- Agentforce requests a token from
/oauth/tokenusing client credentials grant - Server validates
client_idandclient_secret - Server issues a JWT signed with
MCP_CLIENT_SECRET - Agentforce includes
Authorization: Bearer <token>on subsequent/mcprequests - Server validates JWT signature and checks issued token set
Tokens expire after MCP_TOKEN_TTL_SECONDS (default: 1 hour).
Data Storage
- Batteries Fit Database: In-memory array in src/data/batteries.ts
- Store Database: In-memory array in src/data/stores.ts
- Handoff Storage: In-memory Map with optional persistence to
/tmp/batteries-plus-handoffs.json
For production, replace with:
- PostgreSQL or Snowflake for product/store data
- Redis for token management
- Salesforce REST API for handoff records
License
MIT
Support
For issues or questions about this demo server, contact:
- Alisha Christy (alishachisty@outlook.com)
- Open an issue in the GitHub repository
Built with Model Context Protocol SDK v1.0.4
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。