keycrm-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@keycrm-mcpShow me all draft products in the Shirts category"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
keycrm-mcp
A Model Context Protocol (MCP) server for keyCRM — lets Claude manage your keyCRM catalogue, stock, orders, customers, pipelines, and more via natural language.
Original author: Ivan Klymenko
Maintainer: agente.dev
License: ISC (see LICENSE and License)
Node.js: 23.6+
MCP SDK: @modelcontextprotocol/sdk
This repository is the maintained agente-dev/keycrm-mcp fork of the source
project at IvanKlymenko/keycrm-mcp.
The package name and MCP server identity remain keycrm-mcp.
Table of Contents
Related MCP server: claude-mcp-server
1. What This Is
keycrm-mcp is a Model Context Protocol server that wraps the keyCRM REST API. It exposes Claude-callable tools for managing products, variants, stock, orders, customers, pipelines, payments, files, and more in keyCRM.
Once configured, you can ask Claude things like:
"Show me all draft products in the Shirts category"
"Update the price of SKU MNL-SRT-WHT-L to 890"
"What is the current stock level for SKU ABC-123?"
"List all orders placed today that are still pending"
"Publish all draft products in the Jackets category" (with preview + confirmation)
"Replace the photo on product ID 42 with this image URL"
"Create a new order for buyer 99 with two items"
"Show me all cards in the Sales pipeline"
The server runs as a local Node.js process and communicates with your MCP client (Claude Desktop or Claude Code) over stdio.
2. Requirements
Requirement | Version |
Node.js | 23.6+ |
npm | 10+ |
keyCRM account | Any plan |
keyCRM API key | Required |
3. Installation
3.1 Clone the repository
git clone https://github.com/agente-dev/keycrm-mcp.git
cd keycrm-mcp3.2 Install dependencies
npm install3.3 Create environment file
cp .env.example .envEdit .env with your values — see Section 4.
3.4 Verify the server starts
node index.jsThe server starts in stdio mode and waits for MCP client input. No output means it is working correctly — it only speaks when addressed by a client.
4. Configuration
All configuration is done via environment variables. Copy .env.example to .env and fill in the values.
.env.example
# ─── Required ────────────────────────────────────────────────
# Your keyCRM API key
# Found at: Налаштування → Інтеграції → API
KEYCRM_API_KEY=your_api_key_here
# ─── Optional ────────────────────────────────────────────────
# keyCRM API base URL — only change if keyCRM updates their API endpoint
KEYCRM_API_URL=https://openapi.keycrm.app/v1
# Maximum number of results returned by list tools (default: 50)
LIST_DEFAULT_LIMIT=50
# Log level: error | warn | info | debug (default: info)
LOG_LEVEL=info
# Path to the log file (default: ./logs/keycrm-mcp.log)
LOG_FILE=./logs/keycrm-mcp.logConfiguration reference
Variable | Required | Default | Description |
| ✅ | — | keyCRM API key |
| ❌ |
| keyCRM API base URL |
| ❌ |
| Default page size for list tools |
| ❌ |
| Log verbosity |
| ❌ |
| Log file path |
5. MCP Client Setup
Claude Desktop
Add the following to your claude_desktop_config.json:
{
"mcpServers": {
"keycrm": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/keycrm-mcp/index.js"],
"env": {
"KEYCRM_API_KEY": "your_api_key_here"
}
}
}
}Restart Claude Desktop after saving the config. The keyCRM tools will appear in the tool list automatically.
Claude Code
claude mcp add keycrm node /absolute/path/to/keycrm-mcp/index.jsThen set the environment variable:
claude mcp env set keycrm KEYCRM_API_KEY your_api_key_hereRunning with PM2 (server / VPS)
If you are running the MCP server on a VPS and connecting remotely:
npm install -g pm2
pm2 start index.js --name keycrm-mcp
pm2 save
pm2 startup6. Tool Reference
6.1 Products
list_products
List products from the keyCRM catalogue with optional filters.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Filter by category ID |
| string | ❌ | Filter by status: |
| string | ❌ | Search by product name |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
get_product
Get full details for a single product including all variants and stock levels per warehouse.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
create_product
Create a new product in the keyCRM catalogue.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Product name |
| number | ❌ | Category ID |
| string | ❌ | Product description |
| number | ❌ | Base price |
| string | ❌ | Product SKU |
| string | ❌ | Initial status: |
update_product
Update one or more fields on an existing product. Does not change product status — use publish_product, unpublish_product, or archive_product for status changes.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
| string | ❌ | Product name |
| string | ❌ | Product description |
| number | ❌ | Product price |
| number | ❌ | Category ID |
| string | ❌ | Product SKU |
At least one optional field must be provided.
publish_product
Change a product's status from draft to published. Makes the product visible on the storefront.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
unpublish_product
Change a product's status from published back to draft. Hides the product from the storefront without deleting it.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
archive_product
Archive a product. Archived products are hidden from the storefront but fully preserved in keyCRM and can be unarchived at any time. No confirmation required — this operation is reversible.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
update_product_photo
Replace or add a photo on an existing product. Accepts a publicly accessible image URL. Internally, the file is uploaded to keyCRM Storage first (POST /storage/upload), then attached to the product — this is handled automatically by the server.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM product ID |
| string | ✅ | Publicly accessible URL of the new photo |
| boolean | ❌ | If |
bulk_update_products
Apply a field update to multiple products matching a filter. Always call with dry_run: true first to preview affected products, then call again with dry_run: false and confirm: true to execute.
Input parameters:
Parameter | Type | Required | Description |
| object | ✅ | Filter defining which products to update |
| number | ❌ | Match products in this category |
| string | ❌ | Match products with this status |
| string | ❌ | Match products whose name contains this string |
| object | ✅ | Fields to update and their new values (same fields as |
| boolean | ✅ | If |
| boolean | ❌ | Must be |
Two-step flow:
Call with
dry_run: true→ returns list of affected productsReview the list, then call again with
dry_run: false, confirm: true→ executes the update
6.2 Product Variants (Offers)
In keyCRM, product variants (combinations of size, color, etc.) are called offers. Each offer has its own SKU, price, and stock level.
list_offers
List product variants with optional filters.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Filter offers by parent product ID |
| string | ❌ | Filter by SKU (partial match) |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
create_offer
Create one or more new variants for an existing product.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | Parent product ID |
| array | ✅ | Array of offer objects to create |
| string | ❌ | Variant SKU |
| number | ❌ | Variant price |
| array | ❌ | Array of |
update_offer
Update fields on one or more existing product variants.
Input parameters:
Parameter | Type | Required | Description |
| array | ✅ | Array of offer update objects |
| number | ✅ | Offer ID |
| string | ❌ | New SKU |
| number | ❌ | New price |
| array | ❌ | Updated properties |
6.3 Product Categories
list_categories
List all product categories.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
create_category
Create a new product category.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Category name |
| number | ❌ | Parent category ID for nested categories |
6.4 Stock
get_stock
Get stock levels for a specific SKU across all warehouses, or for a single warehouse.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Product variant SKU |
| number | ❌ | If provided, returns stock for this warehouse only |
adjust_stock
Manually adjust the stock level for a SKU in a specific warehouse. Sets an absolute quantity — not a delta.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Product variant SKU |
| number | ✅ | Warehouse to adjust stock in |
| number | ✅ | New absolute stock quantity |
| string | ❌ | Optional note explaining the adjustment |
6.5 Orders
list_orders
List orders with optional filters.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Filter by order status ID (use |
| string | ❌ | Filter orders created from this date (ISO 8601: |
| string | ❌ | Filter orders created up to this date (ISO 8601: |
| number | ❌ | Filter by source ID (use |
| number | ❌ | Filter by fulfillment warehouse |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
get_order
Get full details for a single order including line items, customer, payments, tags, and status history.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
create_order
Create a new order in keyCRM. Requires explicit confirmation.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Existing buyer ID |
| string | ❌ | Comment from the buyer |
| string | ❌ | Internal manager comment |
| number | ❌ | Source ID (use |
| number | ❌ | Initial status ID (use |
| number | ❌ | Payment method ID (use |
| number | ❌ | Fulfillment warehouse ID |
| array | ✅ | Array of line item objects |
| number | ✅ | Offer (variant) ID |
| number | ✅ | Quantity |
| number | ❌ | Sale price (overrides catalogue price) |
| object | ❌ | Shipping details (delivery service, address, TTN, etc.) |
| boolean | ✅ | Must be |
update_order
Update fields on an existing order.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
| string | ❌ | Internal manager comment |
| string | ❌ | Buyer comment |
| object | ❌ | Updated shipping details |
| number | ❌ | Payment method ID |
At least one optional field must be provided.
update_order_status
Update the status of an order.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
| number | ✅ | New status ID (use |
| string | ❌ | Optional internal note |
add_order_payment
Record a payment against an existing order.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
| number | ✅ | Payment amount |
| number | ❌ | Payment method ID (use |
| string | ❌ | Optional payment note |
add_order_tag
Attach a tag to an existing order.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
| number | ✅ | Tag ID (use |
remove_order_tag
Remove a tag from an existing order.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM order ID |
| number | ✅ | Tag ID |
6.6 Order Reference Data
These tools return the lookup data needed to build valid order requests. Call them to get correct IDs before creating or updating orders.
list_order_statuses
List all available order statuses with their IDs and names.
Input parameters: None
list_payment_methods
List all available payment methods with their IDs and names.
Input parameters: None
list_sources
List all available order sources (e.g. WooCommerce, POS, Telegram) with their IDs and names.
Input parameters: None
list_tags
List all available order tags with their IDs and names.
Input parameters: None
list_delivery_services
List all available delivery services with their IDs and names.
Input parameters: None
6.7 Payments
list_external_transactions
List external payment transactions recorded in keyCRM (e.g. from Monobank or other payment providers).
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
attach_external_transaction
Attach an external transaction to an existing payment record in keyCRM. Used to link a bank transaction to a keyCRM order payment.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM payment ID |
| string | ✅ | External transaction identifier (e.g. from Monobank) |
| number | ✅ | Transaction amount |
| string | ❌ | Optional description |
6.8 Customers
list_customers
List customers with optional name, email, or phone search. KeyCRM does not accept
the filter[query] parameter, so searches scan supported /buyer pages
client-side, up to 20 pages of 50 rows. A bounded search returns
search_truncated: true when the API does not provide enough pagination
metadata to prove that all customers were scanned. offset is zero-based. For
an unfiltered request whose offset falls inside a native page, the server
fetches that page and at most its immediate successor, then slices the result
locally; it never performs an unbounded page scan. Because that slice is local,
stale pagination URL/link fields are omitted from the returned metadata.
Input parameters:
Parameter | Type | Required | Description |
| string | ❌ | Search by name, email, or phone |
| number | ❌ | Number of results to return (maximum 50; default: |
| number | ❌ | Pagination offset (default: 0) |
get_customer
Get a customer profile including full order history.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM customer ID |
create_customer
Create a new customer (buyer) record in keyCRM.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Customer full name |
| string | ❌ | Email address |
| string | ❌ | Phone number |
| string | ❌ | Internal note |
update_customer
Update an existing customer record.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | keyCRM customer ID |
| string | ❌ | Customer full name |
| string | ❌ | Email address |
| string | ❌ | Phone number |
| string | ❌ | Internal note |
At least one optional field must be provided.
import_customers
Bulk import a list of customer records into keyCRM. Requires explicit confirmation.
Input parameters:
Parameter | Type | Required | Description |
| array | ✅ | Array of customer objects |
| string | ✅ | Customer full name |
| string | ❌ | Email address |
| string | ❌ | Phone number |
| boolean | ✅ | Must be |
6.9 Pipelines
Pipelines are keyCRM's sales funnel and lead management feature. Each pipeline contains cards (leads or deals) that move through defined stages.
list_pipelines
List all pipelines with their IDs and names.
Input parameters: None
list_pipeline_statuses
List all stages for a specific pipeline with their IDs and names.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | Pipeline ID |
list_pipeline_cards
List cards across pipelines with optional filters.
Input parameters:
Parameter | Type | Required | Description |
| number | ❌ | Filter by pipeline ID |
| number | ❌ | Filter by pipeline stage ID |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
get_pipeline_card
Get full details for a single pipeline card including contact, products, payments, and status.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | Pipeline card ID |
create_pipeline_card
Create a new card in a pipeline.
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | Pipeline ID |
| number | ✅ | Initial stage ID (use |
| string | ❌ | Card title |
| object | ❌ | Contact details ( |
| array | ❌ | Array of product line items |
| string | ❌ | Internal note |
update_pipeline_card
Update an existing pipeline card (move stage, update contact, add notes, etc.).
Input parameters:
Parameter | Type | Required | Description |
| number | ✅ | Pipeline card ID |
| number | ❌ | New stage ID |
| string | ❌ | Updated title |
| string | ❌ | Updated internal note |
| object | ❌ | Updated contact details ( |
At least one optional field must be provided.
6.10 Storage
upload_file
Upload a file to keyCRM Storage from a publicly accessible URL. Returns a file_id that can be used to attach the file to orders, pipeline cards, or products.
Input parameters:
Parameter | Type | Required | Description |
| string | ✅ | Publicly accessible URL of the file to upload |
| string | ❌ | Optional filename override |
list_files
List files stored in keyCRM Storage, optionally filtered by the entity they are attached to.
Input parameters:
Parameter | Type | Required | Description |
| string | ❌ | Filter by entity type: |
| number | ❌ | Filter by entity ID (requires |
| number | ❌ | Number of results to return (default: |
| number | ❌ | Pagination offset (default: 0) |
6.11 Custom Fields
list_custom_fields
List all custom fields configured in keyCRM with their IDs, names, types, and allowed values.
Input parameters: None
7. Error Handling
All keyCRM API errors are caught and returned to Claude as structured error messages — they are never thrown as unhandled exceptions.
Error response shape
{
"error": true,
"code": "KEYCRM_API_ERROR",
"status": 404,
"message": "Product not found",
"detail": "No product with ID 9999 exists in keyCRM"
}Error codes
Code | Description |
| keyCRM returned a non-2xx response |
| API key is invalid or missing |
| Rate limit hit — request will be retried |
| Request timed out |
| Tool input failed validation before the API was called |
| Unexpected server error |
Rate limiting
According to the official keyCRM API-key guidance, the API limit is up to 20 requests per minute per API key; keyCRM recommends a 3-second interval between requests. The server handles HTTP 429 responses automatically with exponential backoff:
First retry: 1 second
Second retry: 2 seconds
Third retry: 4 seconds
After 3 retries: returns a
KEYCRM_RATE_LIMITerror to Claude
Timezone
All timestamps in the keyCRM API use UTC (GMT+0) — for reads, filters, and writes. The server does not perform timezone conversion. Pass and expect UTC values in all date/time fields.
8. Logging
Tool calls and API interactions are logged to a local file for debugging. Input parameters are intentionally omitted so customer names, email addresses, phone numbers, and other request data do not enter the log.
Log format
[2026-03-25T14:32:01.123Z] [INFO] tool_call: list_products | duration: 312ms | status: ok
[2026-03-25T14:32:05.456Z] [ERROR] tool_call: get_product | duration: 201ms | status: error | code: KEYCRM_API_ERROR | message: Product not foundLog location
Default: ./logs/keycrm-mcp.log
Override with the LOG_FILE environment variable.
Logs are appended — no automatic rotation is implemented. Use logrotate on Linux/VPS deployments or clear manually as needed.
9. Project Structure
keycrm-mcp/
├── index.js # Entry point — starts the MCP server
├── .env.example # Environment variable template
├── .env # Your local config (not committed)
├── package.json
├── src/
│ ├── server.js # MCP server setup and tool registration
│ ├── tools/
│ │ ├── products.js # list_products, get_product, create_product,
│ │ │ # update_product, publish_product, unpublish_product,
│ │ │ # archive_product, update_product_photo,
│ │ │ # bulk_update_products
│ │ ├── offers.js # list_offers, create_offer, update_offer
│ │ ├── categories.js # list_categories, create_category
│ │ ├── stock.js # get_stock, adjust_stock
│ │ ├── orders.js # list_orders, get_order, create_order,
│ │ │ # update_order, update_order_status,
│ │ │ # add_order_payment, add_order_tag,
│ │ │ # remove_order_tag
│ │ ├── order-reference.js # list_order_statuses, list_payment_methods,
│ │ │ # list_sources, list_tags, list_delivery_services
│ │ ├── payments.js # list_external_transactions,
│ │ │ # attach_external_transaction
│ │ ├── customers.js # list_customers, get_customer, create_customer,
│ │ │ # update_customer, import_customers
│ │ ├── pipelines.js # list_pipelines, list_pipeline_statuses,
│ │ │ # list_pipeline_cards, get_pipeline_card,
│ │ │ # create_pipeline_card, update_pipeline_card
│ │ ├── storage.js # upload_file, list_files
│ │ ├── custom-fields.js # list_custom_fields
│ ├── keycrm/
│ │ ├── client.js # keyCRM REST API client (fetch wrapper, auth, retry)
│ │ └── errors.js # Error normalisation
│ └── utils/
│ ├── logger.js # File logger
│ └── validate.js # Input validation helpers
└── logs/ # Runtime logs (ignored by git)10. Implementation Notes
MCP SDK
This server is built with the official Anthropic MCP SDK:
npm install @modelcontextprotocol/sdkTools are registered using the SDK's server.tool() method. Input schemas are defined using Zod for runtime validation.
Transport
The server uses StdioServerTransport from the MCP SDK:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new McpServer({ name: 'keycrm-mcp', version: '1.0.0' });
const transport = new StdioServerTransport();
await server.connect(transport);keyCRM API client
All keyCRM API calls go through a single client module (src/keycrm/client.js) that handles:
Base URL and API key injection from environment variables
Bearer token authentication (
Authorization: Bearer YOUR_KEY)JSON request/response serialisation
HTTP error normalisation
Rate limit retry with exponential backoff (max 3 retries)
Request timeout (default: 10 seconds)
update_product_photo — Storage API flow
This tool performs two sequential API calls internally:
POST /storage/upload— uploads the image from the provided URL to keyCRM Storage, returns afile_idPUT /products/{productId}— attaches thefile_idto the product, optionally replacing existing photos
If the upload succeeds but the attach fails, the error is returned with the file_id included so the attach can be retried manually if needed.
bulk_update_products dry-run flow
Two-phase call on the same tool:
Phase 1 (
dry_run: true): Fetches matching products using the provided filter, returns the list without modifying anythingPhase 2 (
dry_run: false, confirm: true): Executes the update on all matching products
If dry_run: false is passed without confirm: true, the tool returns a VALIDATION_ERROR — it will not execute without explicit confirmation.
ESM
The project uses ES modules ("type": "module" in package.json). All imports use ESM syntax.
11. Contributing
See CONTRIBUTING.md for the public contribution and
maintenance workflow. Before proposing a connector change, verify the live
KeyCRM endpoint and add a focused test at the affected tool boundary.
License
This project is licensed under the ISC License. The authoritative text lives
in LICENSE, added on main on 2026-08-26 with the copyright of
the original author (IvanKlymenko) preserved and the Agente Dev LTD
modifications noted. The package.json manifest declares ISC, matching the
LICENSE file; the historical MIT line that appeared in earlier README
revisions is superseded. The public-maintenance readiness gate that waited on
an owner license decision is closed.
keycrm-mcp · maintained by agente.dev; original project by Ivan Klymenko
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseCqualityCmaintenanceA Model Context Protocol server that enables Claude and other AI assistants to access and update Kintone data through natural language commands, supporting operations like record management, file handling, app administration, and space collaboration.7911AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables Claude AI to interact with Paybyrd's payment processing API, allowing for creating payment links, processing refunds, and retrieving order information.6MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server designed to integrate with Claude Desktop, allowing users to interact with Prestashop e-commerce platforms through natural language interfaces.202ISC
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables Claude Desktop integration with AARO ERP system, allowing users to perform stock management, customer management, order processing, and other core ERP operations through natural language commands.2526MIT
Related MCP Connectors
A Model Context Protocol server for Wix AI tools
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/agente-dev/keycrm-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server