keycrm-mcp

keycrm-mcp

A Model Context Protocol server that lets Claude manage keyCRM catalogue, stock, orders, customers, pipelines, and more via natural language.

Category
Visit Server

README

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.

Author: Ivan Klymenko
License: MIT
Node.js: 23.6+
MCP SDK: @modelcontextprotocol/sdk


Table of Contents

  1. What This Is
  2. Requirements
  3. Installation
  4. Configuration
  5. MCP Client Setup
  6. Tool Reference
  7. Error Handling
  8. Logging
  9. Project Structure
  10. Implementation Notes
  11. Contributing

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/ivanklymenko/keycrm-mcp.git
cd keycrm-mcp

3.2 Install dependencies

npm install

3.3 Create environment file

cp .env.example .env

Edit .env with your values — see Section 4.

3.4 Verify the server starts

node index.js

The 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.log

Configuration reference

Variable Required Default Description
KEYCRM_API_KEY keyCRM API key
KEYCRM_API_URL https://openapi.keycrm.app/v1 keyCRM API base URL
LIST_DEFAULT_LIMIT 50 Default page size for list tools
LOG_LEVEL info Log verbosity
LOG_FILE ./logs/keycrm-mcp.log 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.js

Then set the environment variable:

claude mcp env set keycrm KEYCRM_API_KEY your_api_key_here

Running 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 startup

6. Tool Reference

6.1 Products


list_products

List products from the keyCRM catalogue with optional filters.

Input parameters:

Parameter Type Required Description
category_id number Filter by category ID
status string Filter by status: draft, published, archived
query string Search by product name
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset 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
product_id number keyCRM product ID

create_product

Create a new product in the keyCRM catalogue.

Input parameters:

Parameter Type Required Description
name string Product name
category_id number Category ID
description string Product description
price number Base price
sku string Product SKU
status string Initial status: draft (default) or published

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
product_id number keyCRM product ID
name string Product name
description string Product description
price number Product price
category_id number Category ID
sku 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
product_id 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
product_id 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
product_id 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
product_id number keyCRM product ID
photo_url string Publicly accessible URL of the new photo
replace_existing boolean If true, replaces all existing photos. If false, adds alongside existing ones (default: false)

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
filter object Filter defining which products to update
filter.category_id number Match products in this category
filter.status string Match products with this status
filter.query string Match products whose name contains this string
update object Fields to update and their new values (same fields as update_product)
dry_run boolean If true, returns preview without making changes
confirm boolean Must be true to execute when dry_run is false

Two-step flow:

  1. Call with dry_run: true → returns list of affected products
  2. Review 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
product_id number Filter offers by parent product ID
sku string Filter by SKU (partial match)
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset number Pagination offset (default: 0)

create_offer

Create one or more new variants for an existing product.

Input parameters:

Parameter Type Required Description
product_id number Parent product ID
offers array Array of offer objects to create
offers[].sku string Variant SKU
offers[].price number Variant price
offers[].properties array Array of {name, value} pairs (e.g. {name: "Розмір", value: "M"})

update_offer

Update fields on one or more existing product variants.

Input parameters:

Parameter Type Required Description
offers array Array of offer update objects
offers[].id number Offer ID
offers[].sku string New SKU
offers[].price number New price
offers[].properties array Updated properties

6.3 Product Categories


list_categories

List all product categories.

Input parameters:

Parameter Type Required Description
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset number Pagination offset (default: 0)

create_category

Create a new product category.

Input parameters:

Parameter Type Required Description
name string Category name
parent_id 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
sku string Product variant SKU
warehouse_id 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
sku string Product variant SKU
warehouse_id number Warehouse to adjust stock in
quantity number New absolute stock quantity
reason string Optional note explaining the adjustment

6.5 Orders


list_orders

List orders with optional filters.

Input parameters:

Parameter Type Required Description
status_id number Filter by order status ID (use list_order_statuses to get IDs)
date_from string Filter orders created from this date (ISO 8601: YYYY-MM-DD)
date_to string Filter orders created up to this date (ISO 8601: YYYY-MM-DD)
source_id number Filter by source ID (use list_sources to get IDs)
warehouse_id number Filter by fulfillment warehouse
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset 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
order_id number keyCRM order ID

create_order

Create a new order in keyCRM. Requires explicit confirmation.

Input parameters:

Parameter Type Required Description
buyer_id number Existing buyer ID
buyer_comment string Comment from the buyer
manager_comment string Internal manager comment
source_id number Source ID (use list_sources to get IDs)
status_id number Initial status ID (use list_order_statuses to get IDs)
payment_method_id number Payment method ID (use list_payment_methods to get IDs)
warehouse_id number Fulfillment warehouse ID
products array Array of line item objects
products[].offer_id number Offer (variant) ID
products[].quantity number Quantity
products[].price number Sale price (overrides catalogue price)
shipping object Shipping details (delivery service, address, TTN, etc.)
confirm boolean Must be true to execute

update_order

Update fields on an existing order.

Input parameters:

Parameter Type Required Description
order_id number keyCRM order ID
manager_comment string Internal manager comment
buyer_comment string Buyer comment
shipping object Updated shipping details
payment_method_id 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
order_id number keyCRM order ID
status_id number New status ID (use list_order_statuses to get IDs)
note string Optional internal note

add_order_payment

Record a payment against an existing order.

Input parameters:

Parameter Type Required Description
order_id number keyCRM order ID
amount number Payment amount
payment_method_id number Payment method ID (use list_payment_methods to get IDs)
description string Optional payment note

add_order_tag

Attach a tag to an existing order.

Input parameters:

Parameter Type Required Description
order_id number keyCRM order ID
tag_id number Tag ID (use list_tags to get IDs)

remove_order_tag

Remove a tag from an existing order.

Input parameters:

Parameter Type Required Description
order_id number keyCRM order ID
tag_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
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset 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
payment_id number keyCRM payment ID
transaction_id string External transaction identifier (e.g. from Monobank)
amount number Transaction amount
description string Optional description

6.8 Customers


list_customers

List customers with optional search.

Input parameters:

Parameter Type Required Description
query string Search by name, email, or phone
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset number Pagination offset (default: 0)

get_customer

Get a customer profile including full order history.

Input parameters:

Parameter Type Required Description
customer_id number keyCRM customer ID

create_customer

Create a new customer (buyer) record in keyCRM.

Input parameters:

Parameter Type Required Description
full_name string Customer full name
email string Email address
phone string Phone number
comment string Internal note

update_customer

Update an existing customer record.

Input parameters:

Parameter Type Required Description
customer_id number keyCRM customer ID
full_name string Customer full name
email string Email address
phone string Phone number
comment 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
customers array Array of customer objects
customers[].full_name string Customer full name
customers[].email string Email address
customers[].phone string Phone number
confirm boolean Must be true to execute

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
pipeline_id number Pipeline ID

list_pipeline_cards

List cards across pipelines with optional filters.

Input parameters:

Parameter Type Required Description
pipeline_id number Filter by pipeline ID
status_id number Filter by pipeline stage ID
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset 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
card_id number Pipeline card ID

create_pipeline_card

Create a new card in a pipeline.

Input parameters:

Parameter Type Required Description
pipeline_id number Pipeline ID
status_id number Initial stage ID (use list_pipeline_statuses to get IDs)
title string Card title
contact object Contact details (full_name, email, phone)
products array Array of product line items
manager_comment string Internal note

update_pipeline_card

Update an existing pipeline card (move stage, update contact, add notes, etc.).

Input parameters:

Parameter Type Required Description
card_id number Pipeline card ID
status_id number New stage ID
title string Updated title
manager_comment string Updated internal note
contact object Updated contact details (full_name, email, phone)

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
url string Publicly accessible URL of the file to upload
filename 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
entity_type string Filter by entity type: order, pipelines_card, product
entity_id number Filter by entity ID (requires entity_type)
limit number Number of results to return (default: LIST_DEFAULT_LIMIT)
offset 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


6.12 Warehouses


list_warehouses

List all warehouses configured in keyCRM with their IDs, names, and addresses.

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_API_ERROR keyCRM returned a non-2xx response
KEYCRM_AUTH_ERROR API key is invalid or missing
KEYCRM_RATE_LIMIT Rate limit hit — request will be retried
KEYCRM_TIMEOUT Request timed out
VALIDATION_ERROR Tool input failed validation before the API was called
INTERNAL_ERROR Unexpected server error

Rate limiting

The keyCRM API enforces a limit of 60 requests per minute per IP address per API key. 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_LIMIT error 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

All tool calls and API interactions are logged to a local file for debugging.

Log format

[2026-03-25T14:32:01.123Z] [INFO]  tool_call: list_products | params: {"status":"draft"} | duration: 312ms | status: ok
[2026-03-25T14:32:05.456Z] [ERROR] tool_call: get_product | params: {"product_id":9999} | duration: 201ms | status: error | code: KEYCRM_API_ERROR | message: Product not found

Log 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
│   │   └── warehouses.js     # list_warehouses
│   ├── 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/
    └── keycrm-mcp.log        # Runtime log (auto-created)

10. Implementation Notes

MCP SDK

This server is built with the official Anthropic MCP SDK:

npm install @modelcontextprotocol/sdk

Tools 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:

  1. POST /storage/upload — uploads the image from the provided URL to keyCRM Storage, returns a file_id
  2. PUT /products/{productId} — attaches the file_id to 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:

  1. Phase 1 (dry_run: true): Fetches matching products using the provided filter, returns the list without modifying anything
  2. Phase 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

Contributions are welcome. This is a generic keyCRM MCP server — pull requests that extend coverage of the keyCRM API are encouraged.

Before opening a PR:

  • Follow the existing file structure (one file per resource group in src/tools/)
  • Add input parameter validation using Zod for every new tool
  • Ensure errors are caught and returned as structured error objects, not thrown
  • Update this README with the new tool in Section 6

To report a bug or request a tool: open a GitHub issue with the keyCRM API endpoint you need covered and a description of the use case.


keycrm-mcp · Ivan Klymenko · MIT License

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured