Salesforce Headless MCP AI
README.md
# Salesforce Headless MCP AI
A production-oriented Frappe v15+ application that gives each authorized Frappe user a web AI assistant backed by a configurable AI provider and Salesforce Hosted MCP. Salesforce OAuth tokens and AI API keys remain encrypted on the Frappe server; browser code calls only whitelisted Frappe methods.
> Salesforce Headless 360 MCP is currently a Salesforce Beta service. Validate availability, limits, and terms for your org before production use.
<img width="1631" height="966" alt="image" src="https://github.com/user-attachments/assets/94650778-bb24-4d66-a742-ecd6887705fd" />
## Project documentation
- [Development technical documentation](docs/DEVELOPMENT_TECHNICAL_DOCUMENTATION.md)
- [Complete project presentation script](docs/PROJECT_PRESENTATION_SCRIPT.md)
## Architecture
```text
Frappe browser page (/salesforce-ai)
↓ authenticated frappe.call
Frappe Python services
├── OpenAI / Claude / Gemini / Azure / local LLM (tool calling)
└── Salesforce Hosted MCP (Streamable HTTP + OAuth bearer token)
↓
Salesforce org
```
The MCP tool list is retrieved at runtime. In read-only mode the server permits only `discover`, `describe`, and `dispatch_readonly`; `dispatch` is removed from the model's tools and independently blocked in Python. When writes are enabled, `dispatch` is held in a ten-minute, user-bound confirmation record until the user explicitly confirms.
The app also supports Salesforce SObject servers. For `platform/sobject-all`, read-only mode exposes only tools marked read-only (plus Salesforce's known schema/query/search/identity/relationship read tools). When writes are enabled, discovered mutation tools are exposed and every create/update/delete call uses the same confirmation gate.
## Requirements
- Frappe Framework v15 or newer and a working Bench site
- Python 3.10+
- A Salesforce org with API v67.0+ and Headless 360 activated
- A Salesforce External Client App configured for OAuth Authorization Code + PKCE S256
- An OpenAI API key with access to the configured model
- HTTPS for the public Frappe site
Python dependencies (`httpx` and `openai`) are declared in `pyproject.toml` and install with the app.
## Installation
```bash
cd ~/frappe-bench
bench get-app https://github.com/TechwithZakir/salesforce_mcp_ai
bench --site yoursite.example install-app salesforce_mcp_ai
bench --site yoursite.example migrate
bench build --app salesforce_mcp_ai
bench restart
```
For local development:
```bash
cd ~/frappe-bench
bench new-app salesforce_mcp_ai
# Replace the generated app with this repository, or clone it into apps/salesforce_mcp_ai.
bench --site development.localhost install-app salesforce_mcp_ai
bench --site development.localhost migrate
bench build --app salesforce_mcp_ai
```
Assign `Salesforce MCP Manager` to administrators and `Salesforce MCP User` to workshop users. Open **Salesforce MCP Settings** as a manager and save the configuration, then visit `/salesforce-ai`.
After upgrading an existing installation, run `bench --site yoursite.example migrate` and `bench --site yoursite.example clear-cache`. The public **Salesforce MCP AI** workspace then appears in Desk for users assigned `Salesforce MCP User`, `Salesforce MCP Manager`, or `System Manager`.
## Salesforce setup
1. In Salesforce Setup, search for **MCP Servers**.
2. Select **MCP Servers**, find **headless-360**, and activate it.
3. Go to **External Client App Manager** and create an External Client App.
4. Enable OAuth Authorization Code flow and require PKCE using S256.
5. Add scopes `mcp_api`, `refresh_token`, and `offline_access` (use the labels/options exposed by your Salesforce release).
6. Set the callback URL exactly to:
```text
https://YOUR-FRAPPE-DOMAIN/api/method/salesforce_mcp_ai.api.auth.salesforce_callback
```
7. Copy the consumer key and, when required by the app policy, client secret into **Salesforce MCP Settings**.
Salesforce enforces the connected user's CRUD, field-level security, sharing, profiles, and permission sets for every MCP operation. Give workshop users only the Salesforce permissions they require.
## Configuration
Recommended production configuration:
```text
Enabled: On
AI Provider: OpenAI
API Key: (encrypted)
Model: gpt-5.6
Temperature: 0.2
Max Tokens: 4000
Salesforce Login URL: https://login.salesforce.com
Salesforce MCP URL: https://api.salesforce.com/platform/mcp/v1/platform/headless-360
Allow Write Operations: Off
Require Write Confirmation: On
Enable MCP Trace: On
Enable Audit Logging: On
Maximum MCP Tool Calls: 6
Request Timeout: 60
```
The OpenAI API key and External Client App client secret are Frappe `Password` fields. Access and refresh tokens are also `Password` fields on the per-user **Salesforce Connection** document. They are read only by backend code using Frappe's encrypted-password API.
### Sandbox
Switch without code changes:
```text
Salesforce Login URL: https://test.salesforce.com
Salesforce MCP URL: https://api.salesforce.com/platform/mcp/v1/sandbox/platform/headless-360
```
Use a sandbox External Client App with the same callback and scopes.
### SObject All server
Activate **SObject All** under Salesforce Setup → MCP Servers, then configure:
```text
Production/Developer org: https://api.salesforce.com/platform/mcp/v1/platform/sobject-all
Sandbox/Scratch org: https://api.salesforce.com/platform/mcp/v1/sandbox/platform/sobject-all
```
Use read-only mode for querying Cases, Opportunities, Accounts, and other records. Turn writes on only when create/update/delete operations are required; confirmation should normally remain enabled.
## AI provider configuration
Choose one provider in **Salesforce MCP Settings**:
- **OpenAI**: enter an OpenAI API key and model.
- **Claude**: enter an Anthropic API key and Claude model name.
- **Gemini**: enter a Gemini API key and model name.
- **Azure OpenAI**: enter the key, HTTPS resource endpoint, and deployment name. The current v1 endpoint is used.
- **Local LLM (OpenAI-compatible)**: enter an OpenAI-compatible `/v1` base URL and model name. The key may be blank for an unsecured loopback server.
Examples for local servers:
```text
Ollama: http://127.0.0.1:11434/v1
LM Studio: http://127.0.0.1:1234/v1
LiteLLM: https://llm.example.com/v1
vLLM: https://vllm.example.com/v1
```
The selected model must support tool/function calling. Local HTTP is accepted only for a loopback hostname or address; remote endpoints require HTTPS. The agent sends fixed safety instructions and only dynamically returned, policy-filtered MCP schemas. The maximum is counted across individual tool calls, not merely iterations.
## Security and production notes
- Keep **Allow Write Operations** off unless mutations are required. Leave confirmation enabled when writes are on.
- OAuth state and PKCE verifier are server-cache entries, expire after ten minutes, and are consumed once.
- Pending writes are user-bound, single-use, and expire after ten minutes.
- The configured MCP host is restricted to HTTPS on `api.salesforce.com` to reduce SSRF risk.
- Authorization errors trigger exactly one refresh attempt. Failed refreshes disconnect the account.
- Audit payloads are redacted and truncated. Do not add secret fields to traces or custom logs.
- Serve Frappe only over HTTPS, secure Redis and the encryption key, rotate secrets, use restrictive roles, and configure backups.
- Review Salesforce Beta terms and your organization's data-handling policy before sending Salesforce data to an LLM.
- Normal chat is synchronous for workshop clarity. Service classes are isolated so a later endpoint can invoke them through `frappe.enqueue`.
## Permissions
- **Salesforce MCP User**: use the assistant, connect/disconnect their own Salesforce account, and view only their own logs.
- **Salesforce MCP Manager**: configure settings and view all audit logs/connections. Secret values are never returned by an API.
Ownership is enforced by DocType permission hooks as well as filters in each whitelisted method.
## Tests and verification
Tests use mocks and do not require a live Salesforce org or OpenAI call:
```bash
bench --site development.localhost run-tests --app salesforce_mcp_ai
bench --site development.localhost migrate
bench build --app salesforce_mcp_ai
```
Coverage includes PKCE, one-time OAuth state, token refresh, read-only tool filtering and blocking, connection/log ownership, and the tool-call limit setting. For a release, also perform a browser smoke test of `/salesforce-ai`, OAuth callback, tool discovery, and one read-only prompt against a dedicated Salesforce test user.
## Workshop demo
1. Sign in as a user with the `Salesforce MCP User` role.
2. Open `/salesforce-ai`, click **Connect Salesforce**, and complete OAuth.
3. Confirm that the badge is green, mode says **Read Only**, and the MCP tools appear.
4. Ask: “Find Acme Corporation.” Expand the trace to show `discover`, `describe`, and `dispatch_readonly`.
5. Ask: “Show its open opportunities,” then “Which opportunity should I prioritize?”
6. Optionally enable writes as a manager. Ask to create a follow-up task, review the proposed `dispatch` arguments, and click **Confirm & Execute**.
7. Open **Salesforce MCP Log** to show the truncated audit trail.
## Troubleshooting
- **OAuth state invalid or expired**: restart Connect Salesforce and finish within ten minutes; verify Redis/cache health and that the callback returns to the same Frappe deployment.
- **redirect_uri mismatch**: copy the callback shown above exactly, including scheme and hostname.
- **invalid scope / MCP access denied**: activate Headless 360, confirm API v67.0+, the `mcp_api` scope, and the user's Salesforce permissions.
- **401 after connection**: reconnect if refresh failed; verify the External Client App refresh-token policy and client secret requirement.
- **No MCP tools**: confirm the configured production/sandbox endpoint and server activation.
- **OpenAI error**: verify the API key, model access, quota, outbound network access, and timeout.
- **Maximum tool calls reached**: make the prompt more specific or cautiously raise the limit (maximum accepted by this app is 20).
- **Page redirects to login / permission denied**: sign in and assign one of the Salesforce MCP roles.
Technical failures are recorded with `frappe.log_error`; browser responses do not include stack traces or secrets.
## Source layout
```text
salesforce_mcp_ai/
├── api/ # whitelisted auth, MCP, and agent methods
├── services/ # OAuth, token, MCP transport, OpenAI orchestration
├── utils/ # PKCE, validation, redaction
├── salesforce_mcp_ai/doctype/
├── tests/
└── www/salesforce-ai/
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues