Initial commit
This commit is contained in:
112
skills/mxcp-expert/assets/project-templates/salesforce/README.md
Normal file
112
skills/mxcp-expert/assets/project-templates/salesforce/README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# MXCP Salesforce Python Endpoints Example
|
||||
|
||||
This example demonstrates how to use MXCP with Salesforce data using **Python endpoints**.
|
||||
|
||||
## Overview
|
||||
|
||||
This example provides Python MCP endpoints that allow you to:
|
||||
- Execute SOQL queries to retrieve Salesforce data
|
||||
- Execute SOSL searches across multiple objects
|
||||
- List all available Salesforce objects
|
||||
- Get detailed object descriptions
|
||||
- Retrieve specific records by ID
|
||||
- Perform simple text searches across common objects
|
||||
|
||||
## Configuration
|
||||
|
||||
### 1. Getting Salesforce Credentials
|
||||
|
||||
To use this example, you'll need:
|
||||
|
||||
1. **Salesforce Username**: Your Salesforce username (email address)
|
||||
2. **Salesforce Password**: Your Salesforce password
|
||||
3. **Security Token**: Your Salesforce security token (get from Setup → My Personal Information → Reset My Security Token)
|
||||
4. **Instance URL**: Your Salesforce instance URL (e.g., https://your-domain.salesforce.com)
|
||||
5. **Client ID**: A connected app client ID (you can use any valid client ID)
|
||||
|
||||
### 2. User Configuration
|
||||
|
||||
Add the following to your MXCP user config (`~/.mxcp/config.yml`):
|
||||
|
||||
```yaml
|
||||
mxcp: 1
|
||||
|
||||
projects:
|
||||
salesforce-demo:
|
||||
profiles:
|
||||
dev:
|
||||
secrets:
|
||||
salesforce:
|
||||
instance_url: "https://your-instance.salesforce.com"
|
||||
username: "your-username@example.com"
|
||||
password: "your-password"
|
||||
security_token: "your-security-token"
|
||||
client_id: "your-client-id"
|
||||
```
|
||||
|
||||
### 3. Site Configuration
|
||||
|
||||
Create an `mxcp-site.yml` file:
|
||||
|
||||
```yaml
|
||||
mxcp: 1
|
||||
project: salesforce-demo
|
||||
profile: dev
|
||||
secrets:
|
||||
- salesforce
|
||||
```
|
||||
|
||||
## Available Tools
|
||||
|
||||
### SOQL Query
|
||||
Execute SOQL queries directly as Python function calls:
|
||||
```bash
|
||||
mxcp run tool soql --param query="SELECT Id, Name FROM Account LIMIT 10"
|
||||
```
|
||||
|
||||
### SOSL Search
|
||||
Execute SOSL searches across multiple objects:
|
||||
```bash
|
||||
mxcp run tool sosl --param query="FIND {Acme} IN ALL FIELDS RETURNING Account(Name, Phone)"
|
||||
```
|
||||
|
||||
### Simple Search
|
||||
Perform simple text searches across common objects:
|
||||
```bash
|
||||
mxcp run tool search --param search_term="Acme"
|
||||
```
|
||||
|
||||
### List Objects
|
||||
List all available Salesforce objects:
|
||||
```bash
|
||||
mxcp run tool list_sobjects
|
||||
```
|
||||
|
||||
### Describe Object
|
||||
Get detailed information about a specific object:
|
||||
```bash
|
||||
mxcp run tool describe_sobject --param sobject_name="Account"
|
||||
```
|
||||
|
||||
### Get Object
|
||||
Get a specific record by its ID:
|
||||
```bash
|
||||
mxcp run tool get_sobject --param sobject_name="Account" --param record_id="001xx000003DIloAAG"
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
salesforce/
|
||||
├── mxcp-site.yml # Site configuration
|
||||
├── python/ # Python implementations
|
||||
│ └── salesforce_endpoints.py # All Salesforce endpoint functions
|
||||
├── tools/ # Tool definitions
|
||||
│ ├── soql.yml
|
||||
│ ├── sosl.yml
|
||||
│ ├── search.yml
|
||||
│ ├── list_sobjects.yml
|
||||
│ ├── describe_sobject.yml
|
||||
│ └── get_sobject.yml
|
||||
└── README.md
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
mxcp: 1
|
||||
|
||||
projects:
|
||||
salesforce-demo:
|
||||
profiles:
|
||||
dev:
|
||||
secrets:
|
||||
- name: salesforce
|
||||
type: python
|
||||
parameters:
|
||||
instance_url: "${SALESFORCE_URL}"
|
||||
username: "${SALESFORCE_USERNAME}"
|
||||
password: "${SALESFORCE_PASSWORD}"
|
||||
security_token: "${SALESFORCE_TOKEN}"
|
||||
client_id: "${SALESFORCE_CLIENT_ID}"
|
||||
@@ -0,0 +1,5 @@
|
||||
mxcp: 1
|
||||
project: salesforce-demo
|
||||
profile: dev
|
||||
secrets:
|
||||
- salesforce
|
||||
@@ -0,0 +1,330 @@
|
||||
"""
|
||||
Salesforce Python Endpoints
|
||||
|
||||
This module provides direct Python MCP endpoints for querying Salesforce.
|
||||
This is a simpler alternative to the plugin-based approach.
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List, Optional, Callable
|
||||
import logging
|
||||
import time
|
||||
import functools
|
||||
import threading
|
||||
from simple_salesforce import Salesforce # type: ignore[attr-defined]
|
||||
from simple_salesforce.exceptions import SalesforceExpiredSession
|
||||
|
||||
from mxcp.runtime import config, on_init, on_shutdown
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Global Salesforce client for reuse across all function calls
|
||||
sf_client: Optional[Salesforce] = None
|
||||
# Thread lock to protect client initialization
|
||||
_client_lock = threading.Lock()
|
||||
|
||||
|
||||
@on_init
|
||||
def setup_salesforce_client() -> None:
|
||||
"""Initialize Salesforce client when server starts.
|
||||
|
||||
Thread-safe: multiple threads can safely call this simultaneously.
|
||||
"""
|
||||
global sf_client
|
||||
|
||||
with _client_lock:
|
||||
logger.info("Initializing Salesforce client...")
|
||||
|
||||
sf_config = config.get_secret("salesforce")
|
||||
if not sf_config:
|
||||
raise ValueError(
|
||||
"Salesforce configuration not found. Please configure Salesforce secrets in your user config."
|
||||
)
|
||||
|
||||
required_keys = ["username", "password", "security_token", "instance_url", "client_id"]
|
||||
missing_keys = [key for key in required_keys if not sf_config.get(key)]
|
||||
if missing_keys:
|
||||
raise ValueError(f"Missing Salesforce configuration keys: {', '.join(missing_keys)}")
|
||||
|
||||
sf_client = Salesforce(
|
||||
username=sf_config["username"],
|
||||
password=sf_config["password"],
|
||||
security_token=sf_config["security_token"],
|
||||
instance_url=sf_config["instance_url"],
|
||||
client_id=sf_config["client_id"],
|
||||
)
|
||||
|
||||
logger.info("Salesforce client initialized successfully")
|
||||
|
||||
|
||||
@on_shutdown
|
||||
def cleanup_salesforce_client() -> None:
|
||||
"""Clean up Salesforce client when server stops."""
|
||||
global sf_client
|
||||
if sf_client:
|
||||
# Salesforce client doesn't need explicit cleanup, but we'll clear the reference
|
||||
sf_client = None
|
||||
logger.info("Salesforce client cleaned up")
|
||||
|
||||
|
||||
def retry_on_session_expiration(func: Callable[..., Any]) -> Callable[..., Any]:
|
||||
"""
|
||||
Decorator that automatically retries functions on session expiration.
|
||||
|
||||
This only retries on SalesforceExpiredSession, not SalesforceAuthenticationFailed.
|
||||
Authentication failures (wrong credentials) should not be retried.
|
||||
|
||||
Retries up to 2 times on session expiration (3 total attempts).
|
||||
Thread-safe: setup_salesforce_client() handles concurrent access internally.
|
||||
|
||||
Usage:
|
||||
@retry_on_session_expiration
|
||||
def my_salesforce_function():
|
||||
# Function that might fail due to session expiration
|
||||
pass
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
||||
max_retries = 2 # Hardcoded: 2 retries = 3 total attempts
|
||||
|
||||
for attempt in range(max_retries + 1):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except SalesforceExpiredSession as e:
|
||||
if attempt < max_retries:
|
||||
logger.warning(
|
||||
f"Session expired on attempt {attempt + 1} in {func.__name__}: {e}"
|
||||
)
|
||||
logger.info(
|
||||
f"Retrying after re-initializing client (attempt {attempt + 2}/{max_retries + 1})"
|
||||
)
|
||||
|
||||
try:
|
||||
setup_salesforce_client() # Thread-safe internally
|
||||
time.sleep(0.1) # Small delay to avoid immediate retry
|
||||
except Exception as setup_error:
|
||||
logger.error(f"Failed to re-initialize Salesforce client: {setup_error}")
|
||||
raise setup_error # Raise the setup error, not the original session error
|
||||
else:
|
||||
# Last attempt failed, re-raise the session expiration error
|
||||
raise e
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def _get_salesforce_client() -> Salesforce:
|
||||
"""Get the global Salesforce client."""
|
||||
if sf_client is None:
|
||||
raise RuntimeError(
|
||||
"Salesforce client not initialized. Make sure the server is started properly."
|
||||
)
|
||||
return sf_client
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def soql(query: str) -> List[Dict[str, Any]]:
|
||||
"""Execute an SOQL query against Salesforce.
|
||||
|
||||
Args:
|
||||
query: The SOQL query to execute
|
||||
|
||||
Returns:
|
||||
List of records returned by the query, with 'attributes' field removed
|
||||
|
||||
Example:
|
||||
>>> soql("SELECT Id, Name FROM Account")
|
||||
"""
|
||||
logger.info("Executing SOQL query: %s", query)
|
||||
|
||||
sf = _get_salesforce_client()
|
||||
result = sf.query(query)
|
||||
|
||||
# Remove 'attributes' field from each record for cleaner output
|
||||
if "records" not in result:
|
||||
raise ValueError(f"Unexpected SOQL response format: missing 'records' field in {result}")
|
||||
|
||||
records = result["records"]
|
||||
return [{k: v for k, v in record.items() if k != "attributes"} for record in records]
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def sosl(query: str) -> List[Dict[str, Any]]:
|
||||
"""Execute a SOSL query against Salesforce.
|
||||
|
||||
Args:
|
||||
query: The SOSL query to execute
|
||||
|
||||
Returns:
|
||||
List of search results from searchRecords
|
||||
|
||||
Example:
|
||||
>>> sosl("FIND {Acme} IN ALL FIELDS RETURNING Account(Name), Contact(FirstName,LastName)")
|
||||
"""
|
||||
logger.info("Executing SOSL query: %s", query)
|
||||
|
||||
sf = _get_salesforce_client()
|
||||
result = sf.search(query)
|
||||
|
||||
# Return the searchRecords directly as a list
|
||||
if "searchRecords" not in result:
|
||||
raise ValueError(
|
||||
f"Unexpected SOSL response format: missing 'searchRecords' field in {result}"
|
||||
)
|
||||
|
||||
search_records: List[Dict[str, Any]] = result["searchRecords"]
|
||||
return search_records
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def search(search_term: str) -> List[Dict[str, Any]]:
|
||||
"""Search across all Salesforce objects using a simple search term.
|
||||
|
||||
Args:
|
||||
search_term: The term to search for
|
||||
|
||||
Returns:
|
||||
List of search results
|
||||
|
||||
Example:
|
||||
>>> search("Acme") # Searches for "Acme" across all objects
|
||||
"""
|
||||
logger.info("Searching for term: %s", search_term)
|
||||
|
||||
# Build a SOSL query that searches across common objects
|
||||
sosl_query = f"FIND {{{search_term}}} IN ALL FIELDS RETURNING Account(Name, Phone, BillingCity), Contact(FirstName, LastName, Email), Lead(FirstName, LastName, Company), Opportunity(Name, Amount, StageName)"
|
||||
|
||||
result: List[Dict[str, Any]] = sosl(sosl_query)
|
||||
return result
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def list_sobjects(filter: Optional[str] = None) -> List[str]:
|
||||
"""List all available Salesforce objects (sObjects) in the org.
|
||||
|
||||
Args:
|
||||
filter: Optional fuzzy filter to match object names (case-insensitive substring search).
|
||||
Examples: "account", "__c" for custom objects, "contact", etc.
|
||||
|
||||
Returns:
|
||||
list: List of Salesforce object names as strings
|
||||
"""
|
||||
sf = _get_salesforce_client()
|
||||
describe_result = sf.describe()
|
||||
|
||||
if not describe_result:
|
||||
raise ValueError("Salesforce describe() returned empty result")
|
||||
|
||||
if "sobjects" not in describe_result:
|
||||
raise ValueError(
|
||||
f"Unexpected describe response format: missing 'sobjects' field in {describe_result}"
|
||||
)
|
||||
|
||||
sobjects = describe_result["sobjects"]
|
||||
object_names = []
|
||||
|
||||
for obj in sobjects:
|
||||
if not isinstance(obj, dict):
|
||||
raise ValueError(f"Unexpected sobject format: expected dict, got {type(obj)}: {obj}")
|
||||
if "name" not in obj:
|
||||
raise ValueError(f"Sobject missing 'name' field: {obj}")
|
||||
object_names.append(obj["name"])
|
||||
|
||||
if filter is not None and filter.strip():
|
||||
filter_lower = filter.lower()
|
||||
object_names = [name for name in object_names if filter_lower in name.lower()]
|
||||
|
||||
object_names.sort()
|
||||
return object_names
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def describe_sobject(sobject_name: str) -> Dict[str, Any]:
|
||||
"""Get the description of a Salesforce object type.
|
||||
|
||||
Args:
|
||||
sobject_name: The name of the Salesforce object type
|
||||
|
||||
Returns:
|
||||
Dictionary containing the object's field descriptions
|
||||
|
||||
Example:
|
||||
>>> describe_sobject("Account")
|
||||
"""
|
||||
logger.info("Describing Salesforce object: %s", sobject_name)
|
||||
|
||||
sf = _get_salesforce_client()
|
||||
|
||||
# Try to get the object - catch this specifically for "object doesn't exist"
|
||||
try:
|
||||
sobject = getattr(sf, sobject_name)
|
||||
except AttributeError:
|
||||
raise ValueError(f"Salesforce object '{sobject_name}' does not exist")
|
||||
|
||||
# Let API errors from describe() propagate naturally with their original messages
|
||||
describe_result = sobject.describe()
|
||||
|
||||
if not describe_result:
|
||||
raise ValueError(f"Salesforce object '{sobject_name}' describe() returned empty result")
|
||||
|
||||
if "fields" not in describe_result:
|
||||
raise ValueError(
|
||||
f"Unexpected describe response format for '{sobject_name}': missing 'fields' field in {describe_result}"
|
||||
)
|
||||
|
||||
# Process fields into the required format
|
||||
fields_info = {}
|
||||
for field in describe_result["fields"]:
|
||||
if not isinstance(field, dict):
|
||||
raise ValueError(
|
||||
f"Unexpected field format in '{sobject_name}': expected dict, got {type(field)}: {field}"
|
||||
)
|
||||
|
||||
required_fields = ["name", "type", "label"]
|
||||
for required_field in required_fields:
|
||||
if required_field not in field:
|
||||
raise ValueError(f"Field missing '{required_field}' in '{sobject_name}': {field}")
|
||||
|
||||
field_name = field["name"]
|
||||
field_info = {"type": field["type"], "label": field["label"]}
|
||||
|
||||
# Add referenceTo information for reference fields
|
||||
if field["type"] == "reference" and field.get("referenceTo"):
|
||||
field_info["referenceTo"] = field["referenceTo"]
|
||||
|
||||
fields_info[field_name] = field_info
|
||||
|
||||
return fields_info
|
||||
|
||||
|
||||
@retry_on_session_expiration
|
||||
def get_sobject(sobject_name: str, record_id: str) -> Dict[str, Any]:
|
||||
"""Get a specific Salesforce object by its ID.
|
||||
|
||||
Args:
|
||||
sobject_name: The name of the Salesforce object type
|
||||
record_id: The Salesforce ID of the object
|
||||
|
||||
Returns:
|
||||
Dictionary containing the object's field values
|
||||
|
||||
Example:
|
||||
>>> get_sobject("Account", "001xx000003DIloAAG")
|
||||
"""
|
||||
logger.info("Getting Salesforce object: %s with ID: %s", sobject_name, record_id)
|
||||
|
||||
sf = _get_salesforce_client()
|
||||
|
||||
# Try to get the object - catch this specifically for "object doesn't exist"
|
||||
try:
|
||||
sobject = getattr(sf, sobject_name)
|
||||
except AttributeError:
|
||||
raise ValueError(f"Salesforce object '{sobject_name}' does not exist")
|
||||
|
||||
result = sobject.get(record_id)
|
||||
|
||||
# Remove 'attributes' field for consistency with other functions
|
||||
if isinstance(result, dict) and "attributes" in result:
|
||||
cleaned_result: Dict[str, Any] = {k: v for k, v in result.items() if k != "attributes"}
|
||||
return cleaned_result
|
||||
|
||||
return dict(result) if result else {}
|
||||
@@ -0,0 +1,27 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "describe_sobject"
|
||||
description: "Use this tool to get detailed information about a specific Salesforce object's structure. This is crucial for understanding what fields are available, their types, and their properties. The tool returns comprehensive metadata including field types, picklist values, required fields, and field-level security settings. Use this before querying an object to ensure you're using valid field names and to understand the data types. For example, use this to discover all available fields on an Account or to find the valid values for a picklist field."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: sobject_name
|
||||
type: string
|
||||
description: "The API name of the Salesforce object to describe (e.g., 'Account', 'Contact', 'CustomObject__c'). The name is case-sensitive and must match exactly how it appears in Salesforce. You can use list_sobjects() to see all available object names."
|
||||
examples:
|
||||
- "Account"
|
||||
- "Contact"
|
||||
- "Opportunity"
|
||||
- "CustomObject__c"
|
||||
return:
|
||||
type: object
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Describe Account object"
|
||||
description: "Verify Account object description contains expected fields"
|
||||
arguments:
|
||||
- key: sobject_name
|
||||
value: "Account"
|
||||
@@ -0,0 +1,34 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "get_sobject"
|
||||
description: "Use this tool when you have a specific Salesforce record ID and need to retrieve all fields for that record. This is ideal for getting complete details about a known record, like when you have an Account ID from a previous query and need all its information. The tool requires both the object type (e.g., 'Account', 'Contact') and the record's unique ID. This is different from search or SOQL queries which find records based on field values - this tool is for direct record lookup by ID."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: sobject_name
|
||||
type: string
|
||||
description: "The API name of the Salesforce object (e.g., 'Account', 'Contact', 'CustomObject__c'). The name is case-sensitive and must match exactly how it appears in Salesforce. You can use list_sobjects() to see all available object names."
|
||||
examples:
|
||||
- "Account"
|
||||
- "Contact"
|
||||
- "Opportunity"
|
||||
- name: record_id
|
||||
type: string
|
||||
description: "The unique identifier (ID) of the record to retrieve. This is the 15 or 18 character ID assigned by Salesforce when the record is created. You can get these IDs from other queries or from the Salesforce UI."
|
||||
examples:
|
||||
- "001xx000003DIloAAG"
|
||||
- "003xx000004TmiAAE"
|
||||
return:
|
||||
type: object
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Get Account record structure"
|
||||
description: "Verify Account record has expected fields like Id, Name"
|
||||
arguments:
|
||||
- key: sobject_name
|
||||
value: "Account"
|
||||
- key: record_id
|
||||
value: "001Qy00000pxRDKIA2"
|
||||
@@ -0,0 +1,38 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "list_sobjects"
|
||||
description: "Use this tool to get a list of all Salesforce object names available in your org. This is essential for exploring your Salesforce instance and understanding what data you can access. The tool returns a simple list of object names (e.g., ['Account', 'Contact', 'Opportunity']). Use this before using other tools to ensure you're using valid object names. For example, use this to find custom objects in your org or to verify the exact spelling of standard objects. If you need detailed information about a specific object's structure, use the describe_sobject tool instead."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: filter
|
||||
type: string
|
||||
description: "Optional fuzzy filter to match object names (case-insensitive substring search). Examples: 'account', '__c' for custom objects, 'contact', etc. If not provided, all objects are returned."
|
||||
examples:
|
||||
- "account"
|
||||
- "__c"
|
||||
- "contact"
|
||||
default: null
|
||||
return:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Contains standard objects"
|
||||
description: "Verify standard Salesforce objects are present"
|
||||
arguments: []
|
||||
result_contains_all:
|
||||
- "Account"
|
||||
- "Contact"
|
||||
- "Opportunity"
|
||||
- name: "filter"
|
||||
description: "Verify the filter is applied"
|
||||
arguments:
|
||||
- key: filter
|
||||
value: "count"
|
||||
result_contains_all:
|
||||
- "Account"
|
||||
@@ -0,0 +1,28 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "search"
|
||||
description: "Use this tool when you want to quickly search for records across multiple Salesforce objects without knowing the exact field names. It's perfect for finding records by company names, people names, or locations. The search is case-insensitive and will match partial words. For example, searching for 'Acme' will find 'Acme Corp', 'Acme Inc', etc. across Account, Contact, Lead, and Opportunity records. If you need more control over which fields to search or which objects to include, use the sosl tool instead."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: search_term
|
||||
type: string
|
||||
description: "The term to search for. This will be matched against all searchable fields in the specified objects. For example, searching for 'Acme' will find records containing 'Acme', 'acme', 'ACME', etc."
|
||||
examples:
|
||||
- "Acme"
|
||||
- "John Smith"
|
||||
- "New York"
|
||||
return:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Basic search"
|
||||
description: "Verify search returns array of results"
|
||||
arguments:
|
||||
- key: search_term
|
||||
value: "Test"
|
||||
@@ -0,0 +1,43 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "soql"
|
||||
description: "Use this tool when you need to query specific fields from a single Salesforce object, similar to SQL. It's ideal for getting structured data like 'all accounts in New York' or 'all contacts for a specific account'. SOQL is more precise than search or SOSL because you specify exactly which fields you want. For example, use this when you need to get a list of accounts with their phone numbers and addresses, or when you need to find all opportunities over a certain amount. If you need to search across multiple objects or don't know the exact field names, use the search or sosl tools instead."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: query
|
||||
type: string
|
||||
description: "The SOQL query to execute. The query should follow SOQL syntax: SELECT field1, field2 FROM object_type [WHERE conditions] [ORDER BY field] [LIMIT n]. For example: 'SELECT Id, Name, Phone FROM Account WHERE BillingCity = 'New York' LIMIT 10'"
|
||||
examples:
|
||||
- "SELECT Id, Name FROM Account"
|
||||
- "SELECT Id, Name, Email FROM Contact WHERE AccountId = '001xx000003DIloAAG'"
|
||||
- "SELECT Id, Name, Amount, StageName FROM Opportunity WHERE IsWon = true ORDER BY Amount DESC LIMIT 5"
|
||||
return:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Basic Account query"
|
||||
description: "Verify SOQL query returns array of Account records"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "SELECT Id, Name FROM Account LIMIT 1"
|
||||
- name: "Query with LIMIT"
|
||||
description: "Verify SOQL query respects LIMIT clause"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "SELECT Id FROM Account LIMIT 2"
|
||||
- name: "Contact query structure"
|
||||
description: "Verify Contact query returns expected fields"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "SELECT Id, FirstName, LastName FROM Contact LIMIT 1"
|
||||
- name: "Results should not contain attributes"
|
||||
description: "Verify attributes field is filtered out from results"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "SELECT Id, Name FROM Account LIMIT 1"
|
||||
@@ -0,0 +1,43 @@
|
||||
mxcp: 1
|
||||
|
||||
tool:
|
||||
name: "sosl"
|
||||
description: "Use this tool when you need advanced search capabilities across multiple Salesforce objects. It's perfect for complex search scenarios like 'find all records containing this text in any field' or 'search only in name fields across accounts and contacts'. SOSL gives you fine-grained control over which objects to search and which fields to return. For example, use this when you need to find all records mentioning a specific product across accounts, contacts, and opportunities. If you just need a simple search, use the search tool instead. If you need to query specific fields from a single object, use the soql tool instead."
|
||||
language: python
|
||||
source:
|
||||
file: ../python/salesforce_endpoints.py
|
||||
parameters:
|
||||
- name: query
|
||||
type: string
|
||||
description: "The SOSL query to execute. The query should follow SOSL syntax: FIND {search_term} IN ALL FIELDS RETURNING object_type(field1, field2, ...). For example: 'FIND {Acme} IN ALL FIELDS RETURNING Account(Name, Phone), Contact(FirstName, LastName)'"
|
||||
examples:
|
||||
- "FIND {Acme} IN ALL FIELDS RETURNING Account(Name, Phone)"
|
||||
- "FIND {John} IN NAME FIELDS RETURNING Contact(FirstName, LastName, Email)"
|
||||
- "FIND {New York} IN ALL FIELDS RETURNING Account(Name, BillingCity), Lead(Company, City)"
|
||||
return:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
annotations:
|
||||
readOnlyHint: true
|
||||
tests:
|
||||
- name: "Basic SOSL search"
|
||||
description: "Verify SOSL search returns array of search results"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "FIND {Test} IN ALL FIELDS RETURNING Account(Name)"
|
||||
- name: "Multi-object search"
|
||||
description: "Verify SOSL can search across multiple objects"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "FIND {Test} IN ALL FIELDS RETURNING Account(Name), Contact(FirstName, LastName)"
|
||||
- name: "Name field search"
|
||||
description: "Verify SOSL can search in specific fields"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "FIND {Test} IN NAME FIELDS RETURNING Account(Name)"
|
||||
- name: "Search with specific fields"
|
||||
description: "Verify SOSL returns specified fields"
|
||||
arguments:
|
||||
- key: query
|
||||
value: "FIND {Test} IN ALL FIELDS RETURNING Account(Name, Phone)"
|
||||
Reference in New Issue
Block a user