@markstiles/sitecore-search-mcp
v1.0.1
Published
Model Context Protocol server for Sitecore Search APIs (Search, Ingestion, and Events)
Maintainers
Readme
Sitecore Search MCP Server
Model Context Protocol (MCP) server for Sitecore Search APIs, providing unified access to Search & Recommendation, Ingestion, and Events APIs.
Features
- Search API: Execute queries, faceted search, personalized recommendations, and AI-powered features
- Ingestion API: Create, update, and delete documents in the search index
- Events API: Track visitor events for analytics and personalization
- Multi-domain support: Configure multiple Sitecore domains
- Full Authentication Support: API key authentication with automatic token management and refresh
- Type-safe: Built with TypeScript and Zod validation
- Modular architecture: Clean separation of concerns for easy maintenance
Project Structure
mcp-sitecore-search-server/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── config.ts # Configuration management
│ ├── client/ # API clients
│ │ ├── base-client.ts # Base HTTP client with error handling
│ │ ├── search-client.ts # Search & Recommendation API client
│ │ ├── ingestion-client.ts # Ingestion API client
│ │ └── events-client.ts # Events API client
│ ├── tools/ # MCP tool implementations
│ │ ├── search/ # Search API tools
│ │ │ ├── basic-search.ts
│ │ │ ├── faceted-search.ts
│ │ │ ├── recommendations.ts
│ │ │ └── ai-search.ts
│ │ ├── ingestion/ # Ingestion API tools
│ │ │ ├── create-document.ts
│ │ │ ├── update-document.ts
│ │ │ ├── delete-document.ts
│ │ │ ├── ingest-from-source.ts
│ │ │ └── check-status.ts
│ │ └── events/ # Events API tools
│ │ ├── track-event.ts
│ │ └── validate-event.ts
│ └── utils/ # Utilities
│ ├── errors.ts # Error handling
│ ├── logger.ts # Structured logging
│ ├── schema.ts # Schema conversion
│ └── auth-manager.ts # Authentication & token management
├── specs/ # OpenAPI specifications
│ ├── openapi.json # Search & Recommendation API spec
│ ├── openapi (1).json # Ingestion API spec
│ └── openapi (2).json # Events API spec
├── test/ # Test and demo scripts
│ ├── search-integration-test.js # Search API integration tests
│ ├── search-demo.js # Search functionality demo
│ ├── ingestion-integration-test.js # Ingestion API integration tests
│ ├── events-integration-test.js # Events API integration tests
│ └── README.md # Test documentation
├── package.json
├── tsconfig.json
├── README.md
└── AUTHENTICATION.md # Detailed authentication guideInstallation
From npm (Recommended)
# Install globally
npm install -g @markstiles/sitecore-search-mcp
# Or use with npx (no installation needed)
npx @markstiles/sitecore-search-mcpFrom Source
git clone https://github.com/markstiles/mcp-sitecore-search-server.git
cd mcp-sitecore-search-server
npm install
npm run buildConfiguration
- Copy the example environment file:
cp .env.example .env- Configure your Sitecore domain:
SITECORE_DOMAIN_ID=12345678 # Just the domain ID (second part of client key)
SITECORE_CLIENT_KEY=123456789-12345678 # Full client key for Events APIUnderstanding Domain ID vs Client Key:
- Client Key: Full key in format
companyId-domainId(e.g.,123456789-987654321)- First part: Company ID
- Second part: Domain ID
- Domain ID: Just the second part after the dash (e.g.,
987654321) - Find both in Sitecore Search: Developer Resources > API Access
Authentication
This server supports two authentication methods:
Subdomain Authentication (Recommended)
If you have a subdomain, no explicit authentication is required. The subdomain host URL provides automatic authentication. Simply configure your domain ID and client key:
SITECORE_DOMAIN_ID=12345678 # Domain ID only
SITECORE_CLIENT_KEY=123456789-12345678 # Full client key for Events API
# No API key neededAPI Key Authentication
If you don't have a subdomain, use an API key for authentication:
SITECORE_DOMAIN_ID=12345678 # Domain ID only
SITECORE_CLIENT_KEY=123456789-12345678 # Full client key for Events API
SITECORE_API_KEY=01-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # API keyHow Authentication Works:
- API Key: A 52-character secret code from Sitecore Search (found in Developer Resources > API Access)
- Access Tokens: Automatically generated from your API key when needed (valid for 1 day by default)
- Refresh Tokens: Used to get new access tokens without re-authenticating (valid for 7 days by default)
- Auto-Refresh: Tokens are automatically refreshed before expiration
Authentication Scopes:
discover- Search & Recommendation APIevent- Events APIingestion- Ingestion API (always uses API key directly, per Sitecore requirements)
Optional Configuration:
# Customize authentication scopes (comma-separated)
SITECORE_AUTH_SCOPES=discover,event,ingestion
# Customize token expiry times (in milliseconds)
SITECORE_ACCESS_TOKEN_EXPIRY=43200000 # 12 hours
SITECORE_REFRESH_TOKEN_EXPIRY=259200000 # 3 daysWhere Authentication is Used:
- API keys/tokens are automatically added to request headers
- Search & Recommendation API:
Authorization: Bearer <access-token> - Events API:
Authorization: Bearer <access-token> - Ingestion API:
Authorization: <api-key>(no Bearer prefix)
Multiple Domains
To configure multiple domains with individual authentication settings:
SITECORE_DOMAINS_JSON={
"12345678": {
"searchBaseUrl": "https://discover.sitecorecloud.io",
"ingestionBaseUrl": "https://discover.sitecorecloud.io",
"eventsBaseUrl": "https://discover.sitecorecloud.io",
"apiKey": "01-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"clientKey": "123456789-12345678",
"authScopes": ["discover", "event", "ingestion"],
"accessTokenExpiry": 86400000,
"refreshTokenExpiry": 604800000
},
"87654321": {
"searchBaseUrl": "https://...",
"apiKey": "01-yyyyyyyy-yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"clientKey": "987654321-87654321"
}
}
SITECORE_DEFAULT_DOMAIN=12345678Build
npm run buildUsage
As MCP Server
Configure in your MCP client (e.g., Claude Desktop):
Using npx (Recommended - no installation needed)
{
"mcpServers": {
"sitecore-search": {
"command": "npx",
"args": [
"-y",
"@markstiles/sitecore-search-mcp"
],
"env": {
"SITECORE_DOMAIN_ID": "12345678",
"SITECORE_CLIENT_KEY": "123456789-12345678",
"SITECORE_API_KEY": "01-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Using Global Installation
npm install -g @markstiles/sitecore-search-mcp{
"mcpServers": {
"sitecore-search": {
"command": "mcp-sitecore-search-server",
"env": {
"SITECORE_DOMAIN_ID": "12345678",
"SITECORE_CLIENT_KEY": "123456789-12345678",
"SITECORE_API_KEY": "01-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Using Local Installation from Source
{
"mcpServers": {
"sitecore-search": {
"command": "node",
"args": ["/path/to/mcp-sitecore-search-server/dist/index.js"],
"env": {
"SITECORE_DOMAIN_ID": "12345678",
"SITECORE_CLIENT_KEY": "123456789-12345678",
"SITECORE_API_KEY": "01-xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Note:
SITECORE_DOMAIN_ID: Required - the domain ID (second part of client key)SITECORE_CLIENT_KEY: Required for Events API - full client key formatxxxxxxxxx-xxxxxxxxSITECORE_API_KEY: Optional if using subdomain authenticationSee AUTHENTICATION.md for detailed authentication setup.
Development
Watch mode for development:
npm run devTesting
Test the MCP server functionality with the included test scripts:
# Build the project first
npm run build
# Run all integration tests
node test/search-integration-test.js # Search API tests
node test/ingestion-integration-test.js # Ingestion API tests
node test/events-integration-test.js # Events API tests
# Or run the quick demo
node test/search-demo.jsThe test scripts validate:
- ✅ Search API: Basic search, faceted search, pagination
- ✅ Ingestion API: Document CRUD operations (Create, Update, Delete)
- ✅ Events API: Event tracking (view, click, add, identify)
- ✅ API connectivity and authentication
- ✅ Error handling and validation
See test/README.md for detailed test documentation.
Available Tools
Search API Tools
sitecore_search_query
Execute a basic search query.
Parameters:
domainId(string): Sitecore domain IDrfkId(string): RFK widget IDkeyphrase(string, optional): Search query textentity(string, optional): Entity type (e.g., content, product)page(number, optional): Page number (default: 1)limit(number, optional): Results per page (default: 24)locale(object, optional): Language and country settings
Example:
{
"domainId": "my-domain",
"rfkId": "rfkid_7",
"keyphrase": "laptop",
"entity": "product",
"page": 1,
"limit": 20
}sitecore_search_with_facets
Execute a faceted search with filtering and sorting.
Parameters:
- All basic search parameters, plus:
facets(array, optional): Facet configuration with filterssort(object, optional): Sort criteria
Example:
{
"domainId": "my-domain",
"rfkId": "rfkid_7",
"keyphrase": "laptop",
"facets": [
{
"name": "brand",
"type": "value",
"values": ["Dell", "HP"]
},
{
"name": "price",
"type": "range"
}
],
"sort": {
"price": "asc"
}
}sitecore_get_recommendations
Get personalized recommendations.
Parameters:
domainId(string): Domain IDrfkId(string): RFK widget IDrecommendationId(string, optional): Recipe IDentity(string, optional): Entity typeuserId(string, optional): User UUID for personalizationlimit(number, optional): Number of recommendations (default: 10)
sitecore_ai_search
Get AI-powered answers or related questions.
Parameters:
domainId(string): Domain IDrfkId(string): RFK widget IDkeyphrase(string): Search querytype(enum): "answer" or "question"entity(string, optional): Entity type
Ingestion API Tools
sitecore_create_document
Create a new document in the index.
Parameters:
domain(string): Domain IDsource(string): Source identifierentity(string): Entity typedocument(object): Document data as key-value pairs
Example:
{
"domain": "my-domain",
"source": "my-source",
"entity": "content",
"document": {
"id": "doc123",
"title": "My Article",
"content": "Article content...",
"author": "John Doe"
}
}sitecore_update_document
Update an existing document.
Parameters:
domain(string): Domain IDsource(string): Source identifierentity(string): Entity typedocumentId(string): Document ID to updatedocument(object): Document datapartial(boolean, optional): Use PATCH for partial update (default: false)
sitecore_delete_document
Delete a document from the index.
Parameters:
domain,source,entity,documentId
sitecore_ingest_from_source
Ingest a document from an external file or URL.
Parameters:
domain,source,entity,documentIdsourceType(enum): "file" or "url"sourceUrl(string): URL to the file or webpageextractors(object, optional): XPath, JavaScript, or CSS extractors
Example:
{
"domain": "my-domain",
"source": "web",
"entity": "content",
"documentId": "article-456",
"sourceType": "url",
"sourceUrl": "https://example.com/article",
"extractors": {
"css": [
{ "name": "title", "selector": "h1" },
{ "name": "content", "selector": "article" }
]
}
}sitecore_check_ingestion_status
Check status of an asynchronous ingestion operation.
Parameters:
domain,source,entityincrementalUpdateId(string): ID returned from ingestion operation
Events API Tools
sitecore_track_event
Track visitor events for analytics and personalization.
Parameters:
domainId(string, optional): Domain ID - uses default if not providedcustomerKey(string, optional): Customer key (ckey) - uses configured client key if not providedeventType(enum): Event type (view, click, add, remove, identify, order, etc.)value(object, optional): Event value datacontext(object, optional): User, page, browser, and geo context
Example:
{
"eventType": "view",
"value": {
"entity": "product",
"entity_id": "prod-123"
},
"context": {
"user": {
"uuid": "user-456"
},
"page": {
"uri": "/products/prod-123",
"title": "Product Name"
}
}
}Note: The
customerKeyis automatically retrieved from yourSITECORE_CLIENT_KEYconfiguration. You only need to provide it if you want to override the configured value.
sitecore_validate_event
Validate an event payload before sending.
Parameters:
- Same as
sitecore_track_event(without customerKey)
API Coverage
Search & Recommendation API (openapi.json)
- ✅ Basic search queries
- ✅ Faceted search with filtering
- ✅ Personalized recommendations
- ✅ AI-powered answers and questions
- 🔄 Advanced features (suggestions, rules engine) - Can be added as needed
Ingestion API (openapi (1).json)
- ✅ Create document (POST)
- ✅ Update document (PUT - full replacement)
- ✅ Patch document (PATCH - partial update)
- ✅ Delete document
- ✅ Create from file upload
- ✅ Create from URL
- ✅ Status checking for async operations
Events API (openapi (2).json)
- ✅ Track events (v4 endpoint - recommended)
- ✅ Validate events
- 🔄 Legacy endpoints (v3, v2) - Available via content event method
Error Handling
All tools include comprehensive error handling:
- Input validation using Zod schemas
- API error responses with status codes
- Structured error logging
- Graceful error messages returned to MCP clients
Logging
The server uses structured JSON logging with different levels:
info: General informationerror: Error conditionswarn: Warning conditionsdebug: Debug information (requires DEBUG=true)
Extending the Server
Adding New Tools
- Create a new tool file in the appropriate directory:
// src/tools/search/new-feature.ts
import { z } from 'zod';
import { SearchClient } from '../../client/search-client.js';
export const NewFeatureSchema = z.object({
// Define parameters
});
export async function executeNewFeature(client: SearchClient, input: unknown) {
// Implementation
}
export const newFeatureTool = {
name: 'sitecore_new_feature',
description: 'Description of the feature',
inputSchema: NewFeatureSchema,
};- Import and register in src/index.ts:
import { newFeatureTool, executeNewFeature } from './tools/search/new-feature.js';
// Add to ListToolsRequestSchema handler
// Add case to CallToolRequestSchema handlerModifying API Clients
API clients are in src/client/. Each client extends BaseClient which provides:
- HTTP methods (get, post, put, patch, delete)
- Error handling
- Request/response logging
- Retry logic
License
MIT
Contributing
Contributions are welcome! The modular structure makes it easy to:
- Add new tools for existing APIs
- Extend API clients with new methods
- Add support for additional Sitecore APIs
- Improve error handling and validation
Publishing
See PUBLISHING.md for detailed instructions on publishing this package to npm.
Quick publish steps:
# Update version
npm version patch|minor|major
# Build
npm run build
# Publish (first time with scoped package)
npm publish --access public
# Subsequent publishes
npm publishSupport
For Sitecore API documentation, visit:
For issues with this MCP server:
