CRM自然语言管理协议

keycrm-mcp是一个基于Model Context Protocol的服务器,允许通过自然语言管理keyCRM的产品目录、库存、订单、客户、管道等。

  • by IvanKlymenko
  • JavaScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 IvanKlymenko/keycrm-mcp

使用说明

keycrm mcp

一种模型上下文协议(MCP)服务器 keyCRM --让Claude通过自然语言管理您的关键CRM目录、库存、订单、客户、管道等。

作者 伊万·克利门科
许可证: 麻省理工学院
Node.js: 23.6+
MCP-SDK: @modelcontextprotocol/sdk


目录

  1. 这是什么
  2. 需求
  3. 安装
  4. 配置
  5. MCP客户端设置
  6. 工具参考
  7. 错误处理
  8. 日志记录
  9. 项目结构
  10. 实施说明
  11. 贡献

1.这是什么

keycrm-mcp 是一个 模型上下文协议 包装的服务器 keyCRM REST API它公开了Claude可调用工具,用于在keyCRM中管理产品、变体、库存、订单、客户、管道、付款、文件等。

配置后,您可以向Claude询问以下问题:

  • “显示衬衫类别中的所有草稿产品”
  • “将SKU MNL-SRT-WHT-L的价格更新为890”
  • “SKU ABC-123的当前库存水平是多少?”
  • “列出今天下达的所有尚未处理的订单”
  • “发布夹克类别中的所有草稿产品” (带预览+确认)
  • “用此图像URL替换产品ID 42上的照片”
  • “用两件商品为买家99创建新订单”
  • “显示销售渠道中的所有卡片”

服务器作为本地Node.js进程运行,并通过stdio与MCP客户端(Claude Desktop或Claude Code)通信。


2.要求

要求 版本
Node.js 23.6+
npm 10+
keyCRM帐户 任何计划
keyCRM API密钥 必需

3.安装

3.1克隆存储库

git clone https://github.com/ivanklymenko/keycrm-mcp.git
cd keycrm-mcp

3.2安装依赖项

npm install

3.3创建环境文件

cp .env.example .env

编辑 .env 根据您的价值观——请参阅 第4节.

3.4验证服务器是否启动

node index.js

服务器以stdio模式启动并等待MCP客户端输入。没有输出意味着它工作正常——它只在客户端寻址时才说话。


4.配置

所有配置都是通过环境变量完成的。复制 .env.example 到 .env 并填写数值。

.env.示例

# ─── 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

配置参考

变量 必填 默认 描述
KEYCRM_API_KEY ✅ — keyCRM API密钥
KEYCRM_API_URL ❌ https://openapi.keycrm.app/v1 keyCRM API基础URL
LIST_DEFAULT_LIMIT ❌ 50 列表工具的默认页面大小
LOG_LEVEL ❌ info 日志冗长
LOG_FILE ❌ ./logs/keycrm-mcp.log 日志文件路径

5.MCP客户端设置

克劳德桌面版

将以下内容添加到您的 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"
      }
    }
  }
}

保存配置后重新启动Claude Desktop。关键CRM工具将自动出现在工具列表中。

克劳德代码

claude mcp add keycrm node /absolute/path/to/keycrm-mcp/index.js

然后设置环境变量:

claude mcp env set keycrm KEYCRM_API_KEY your_api_key_here

使用PM2(服务器/VPS)运行

如果您在VPS上运行MCP服务器并远程连接:

npm install -g pm2
pm2 start index.js --name keycrm-mcp
pm2 save
pm2 startup

6.工具参考

6.1产品


list_products

列出带有可选过滤器的keyCRM目录中的产品。

输入参数:

参数 类型 必填 说明
category_id 编号 ❌ 按类别ID筛选
status string ❌ 按状态筛选: draft, published, archived
query string ❌ 按产品名称搜索
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

get_product

获取单个产品的完整详细信息,包括每个仓库的所有变体和库存水平。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID

create_product

在keyCRM目录中创建新产品。

输入参数:

参数 类型 必填 说明
name string ✅ 产品名称
category_id 编号 ❌ 类别ID
description string ❌ 产品描述
price 编号 ❌ 基准价格
sku string ❌ 产品SKU
status string ❌ 初始状态: draft (默认)或 published

update_product

更新现有产品上的一个或多个字段。不改变产品状态--使用 publish_product, unpublish_product,或 archive_product 状态更改。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID
name string ❌ 产品名称
description string ❌ 产品描述
price 编号 ❌ 产品价格
category_id 编号 ❌ 类别ID
sku string ❌ 产品SKU

必须至少提供一个可选字段。


publish_product

更改产品的状态 draft 到 published。使产品在店面上可见。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID

unpublish_product

更改产品的状态 published 回到 draft。在店面中隐藏产品而不将其删除。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID

archive_product

将产品存档。存档的产品隐藏在店面之外,但完全保存在keyCRM中,可以随时取消存档。无需确认——此操作是可逆的。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID

update_product_photo

在现有产品上替换或添加照片。接受可公开访问的图像URL。在内部,文件首先上传到keyCRM存储(POST /storage/upload),然后附加到产品上——这由服务器自动处理。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ keyCRM产品ID
photo_url string ✅ 新照片的可公开访问的URL
replace_existing boolean ❌ 如果 true,替换所有现有照片。如果 false,与现有的一起添加(默认值: false)

bulk_update_products

将字段更新应用于与筛选器匹配的多个产品。总是打电话给 dry_run: true 首先预览受影响的产品,然后再次致电 dry_run: false 和 confirm: true 执行。

输入参数:

参数 类型 必填 说明
filter 对象 ✅ 定义要更新哪些产品的筛选器
filter.category_id 编号 ❌ 匹配此类别中的产品
filter.status string ❌ 将产品与此状态匹配
filter.query string ❌ 匹配名称包含此字符串的产品
update 对象 ✅ 要更新的字段及其新值(与 update_product)
dry_run boolean ✅ 如果 true,返回预览而不进行更改
confirm boolean ❌ 必须 true 执行时间 dry_run 是 false

两步流程:

  1. 致电 dry_run: true → 受影响产品的退货清单
  2. 查看列表,然后再次致电 dry_run: false, confirm: true → 执行更新

6.2产品变体(报价)

在keyCRM中,产品变体(尺寸、颜色等的组合)被称为 提供。每个报价都有自己的SKU、价格和库存水平。


list_offers

列出带有可选过滤器的产品变体。

输入参数:

参数 类型 必填 说明
product_id 编号 ❌ 按父产品ID筛选报价
sku string ❌ 按SKU筛选(部分匹配)
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

create_offer

为现有产品创建一个或多个新变体。

输入参数:

参数 类型 必填 说明
product_id 编号 ✅ 父产品ID
offers 数组 ✅ 要创建的报价对象数组
offers[].sku string ❌ 变体SKU
offers[].price 编号 ❌ 可变价格
offers[].properties 数组 ❌ 一大批 {name, value} 配对(例如。 {name: "Розмір", value: "M"})

update_offer

更新一个或多个现有产品变体上的字段。

输入参数:

参数 类型 必填 说明
offers 数组 ✅ 报价更新对象数组
offers[].id 编号 ✅ 优惠ID
offers[].sku string ❌ 新SKU
offers[].price 编号 ❌ 新价格
offers[].properties 数组 ❌ 更新属性

6.3产品类别


list_categories

列出所有产品类别。

输入参数:

参数 类型 必填 说明
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

create_category

创建新的产品类别。

输入参数:

参数 类型 必填 说明
name string ✅ 类别名称
parent_id 编号 ❌ 嵌套类别的父类别ID

6.4库存


get_stock

获取所有仓库或单个仓库中特定SKU的库存水平。

输入参数:

参数 类型 必填 说明
sku string ✅ 产品变体SKU
warehouse_id 编号 ❌ 如果提供,仅退回此仓库的库存

adjust_stock

手动调整特定仓库中SKU的库存水平。设置绝对量,而不是增量。

输入参数:

参数 类型 必填 说明
sku string ✅ 产品变体SKU
warehouse_id 编号 ✅ 仓库调整入库
quantity 编号 ✅ 新的绝对库存量
reason string ❌ 解释调整的可选注释

6.5订单


list_orders

列出带有可选过滤器的订单。

输入参数:

参数 类型 必填 说明
status_id 编号 ❌ 按订单状态ID筛选(使用 list_order_statuses 获取ID)
date_from string ❌ 从此日期创建的筛选订单(ISO 8601: YYYY-MM-DD)
date_to string ❌ 迄今为止创建的筛选订单(ISO 8601: YYYY-MM-DD)
source_id 编号 ❌ 按源ID筛选(使用 list_sources 获取ID)
warehouse_id 编号 ❌ 按履行仓库筛选
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

get_order

获取单个订单的完整详细信息,包括行项目、客户、付款、标签和状态历史记录。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID

create_order

在keyCRM中创建新订单。需要明确确认。

输入参数:

参数 类型 必填 说明
buyer_id 编号 ❌ 现有买家ID
buyer_comment string ❌ 买家的评论
manager_comment string ❌ 内部经理评论
source_id 编号 ❌ 源ID(使用 list_sources 获取ID)
status_id 编号 ❌ 初始状态ID(使用 list_order_statuses 获取ID)
payment_method_id 编号 ❌ 付款方式ID(使用 list_payment_methods 获取ID)
warehouse_id 编号 ❌ 配送仓库ID
products 数组 ✅ 行项目对象数组
products[].offer_id 编号 ✅ 报价(变体)ID
products[].quantity 编号 ✅ 数量
products[].price 编号 ❌ 销售价格(优先于目录价格)
shipping 对象 ❌ 发货详情(送货服务、地址、TTN等)
confirm boolean ✅ 必须 true 执行

update_order

更新现有订单上的字段。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID
manager_comment string ❌ 内部经理评论
buyer_comment string ❌ 买家评论
shipping 对象 ❌ 更新的装运详细信息
payment_method_id 编号 ❌ 付款方式ID

必须至少提供一个可选字段。


update_order_status

更新订单状态。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID
status_id 编号 ✅ 新状态ID(使用 list_order_statuses 获取ID)
note string ❌ 可选内部注释

add_order_payment

记录现有订单的付款。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID
amount 编号 ✅ 付款金额
payment_method_id 编号 ❌ 付款方式ID(使用 list_payment_methods 获取ID)
description string ❌ 可选付款单

add_order_tag

为现有订单添加标签。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID
tag_id 编号 ✅ 标签ID(使用 list_tags 获取ID)

remove_order_tag

从现有订单中删除标签。

输入参数:

参数 类型 必填 说明
order_id 编号 ✅ keyCRM订单ID
tag_id 编号 ✅ 标签ID

6.6订单参考数据

这些工具返回构建有效订单请求所需的查找数据。在创建或更新订单之前,请致电他们以获取正确的ID。


list_order_statuses

列出所有可用的订单状态及其ID和名称。

输入参数: 无


list_payment_methods

列出所有可用的付款方式及其ID和名称。

输入参数: 无


list_sources

列出所有可用的订单来源(例如WooCommerce、POS、Telegram)及其ID和名称。

输入参数: 无


list_tags

列出所有可用的订单标签及其ID和名称。

输入参数: 无


list_delivery_services

列出所有可用的送货服务及其ID和名称。

输入参数: 无


6.7付款


list_external_transactions

列出keyCRM中记录的外部支付交易(例如来自Monobank或其他支付提供商)。

输入参数:

参数 类型 必填 说明
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

attach_external_transaction

将外部交易附加到keyCRM中的现有付款记录。用于将银行交易链接到keyCRM订单付款。

输入参数:

参数 类型 必填 说明
payment_id 编号 ✅ keyCRM支付ID
transaction_id string ✅ 外部交易标识符(例如来自Monobank)
amount 编号 ✅ 交易金额
description string ❌ 可选描述

6.8客户


list_customers

使用可选搜索列出客户。

输入参数:

参数 类型 必填 说明
query string ❌ 按姓名、电子邮件或电话搜索
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

get_customer

获取客户资料,包括完整的订单历史记录。

输入参数:

参数 类型 必填 说明
customer_id 编号 ✅ keyCRM客户ID

create_customer

在keyCRM中创建新的客户(买方)记录。

输入参数:

参数 类型 必填 说明
full_name string ✅ 客户全名
email string ❌ 电子邮件地址
phone string ❌ 电话号码
comment string ❌ 内部注释

update_customer

更新现有客户记录。

输入参数:

参数 类型 必填 说明
customer_id 编号 ✅ keyCRM客户ID
full_name string ❌ 客户全名
email string ❌ 电子邮件地址
phone string ❌ 电话号码
comment string ❌ 内部注释

必须至少提供一个可选字段。


import_customers

将客户记录列表批量导入keyCRM。需要明确确认。

输入参数:

参数 类型 必填 说明
customers 数组 ✅ 客户对象数组
customers[].full_name string ✅ 客户全名
customers[].email string ❌ 电子邮件地址
customers[].phone string ❌ 电话号码
confirm boolean ✅ 必须 true 执行

6.9管道

渠道是CRM的关键销售渠道和潜在客户管理功能。每个管道都包含经过定义阶段的卡片(线索或交易)。


list_pipelines

列出所有管道及其ID和名称。

输入参数: 无


list_pipeline_statuses

列出特定管道的所有阶段及其ID和名称。

输入参数:

参数 类型 必填 说明
pipeline_id 编号 ✅ 管道ID

list_pipeline_cards

列出带有可选过滤器的管道中的卡片。

输入参数:

参数 类型 必填 说明
pipeline_id 编号 ❌ 按管道ID筛选
status_id 编号 ❌ 按管道阶段ID过滤
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

get_pipeline_card

获取单个管道卡的完整详细信息,包括联系人、产品、付款和状态。

输入参数:

参数 类型 必填 说明
card_id 编号 ✅ 管道卡ID

create_pipeline_card

在管道中创建新卡。

输入参数:

参数 类型 必填 说明
pipeline_id 编号 ✅ 管道ID
status_id 编号 ✅ 初始阶段ID(使用 list_pipeline_statuses 获取ID)
title string ❌ 卡片标题
contact 对象 ❌ 联系方式(full_name, email, phone)
products 数组 ❌ 产品线项目数组
manager_comment string ❌ 内部注释

update_pipeline_card

更新现有的管道卡(移动舞台、更新联系人、添加注释等)。

输入参数:

参数 类型 必填 说明
card_id 编号 ✅ 管道卡ID
status_id 编号 ❌ 新阶段ID
title string ❌ 更新标题
manager_comment string ❌ 更新内部说明
contact 对象 ❌ 更新联系方式(full_name, email, phone)

必须至少提供一个可选字段。


6.10储存


upload_file

将文件从可公开访问的URL上传到keyCRM存储。返回 file_id 可用于将文件附加到订单、管道卡或产品。

输入参数:

参数 类型 必填 说明
url string ✅ 要上传的文件的可公开访问的URL
filename string ❌ 可选文件名覆盖

list_files

列出存储在keyCRM存储中的文件,可选择按它们所连接的实体进行筛选。

输入参数:

参数 类型 必填 说明
entity_type string ❌ 按实体类型筛选: order, pipelines_card, product
entity_id 编号 ❌ 按实体ID筛选(需要 entity_type)
limit 编号 ❌ 要返回的结果数(默认值: LIST_DEFAULT_LIMIT)
offset 编号 ❌ 分页偏移量(默认值:0)

6.11自定义字段


list_custom_fields

列出在keyCRM中配置的所有自定义字段及其ID、名称、类型和允许值。

输入参数: 无


6.12仓库


list_warehouses

列出在keyCRM中配置的所有仓库及其ID、名称和地址。

输入参数: 无


7.错误处理

所有keyCRM API错误都会被捕获并作为结构化错误消息返回给Claude-它们不会作为未处理的异常抛出。

错误响应形状

{
  "error": true,
  "code": "KEYCRM_API_ERROR",
  "status": 404,
  "message": "Product not found",
  "detail": "No product with ID 9999 exists in keyCRM"
}

错误代码

代码 描述
KEYCRM_API_ERROR keyCRM返回了非2xx响应
KEYCRM_AUTH_ERROR API密钥无效或丢失
KEYCRM_RATE_LIMIT 速率限制命中--将重试请求
KEYCRM_TIMEOUT 请求超时
VALIDATION_ERROR 调用API之前,工具输入验证失败
INTERNAL_ERROR 意外的服务器错误

速率限制

keyCRM API强制限制 每个API密钥每个IP地址每分钟60个请求服务器以指数回退自动处理HTTP 429响应:

  • 第一次重试:1秒
  • 第二次重试:2秒
  • 第三次重试:4秒
  • 重试3次后:返回a KEYCRM_RATE_LIMIT 克劳德的错误

时区

keyCRM API中的所有时间戳都使用 UTC(GMT+0) --用于读取、筛选和写入。服务器不执行时区转换。在所有日期/时间字段中传递和期望UTC值。


8.日志记录

所有工具调用和API交互都记录到本地文件中进行调试。

日志格式

[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

日志位置

违约: ./logs/keycrm-mcp.log

用覆盖 LOG_FILE 环境变量。

附加日志——不实现自动轮换。使用 logrotate 在Linux/VPS部署上,或根据需要手动清除。


9.项目结构

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.实施说明

MCP-SDK

此服务器使用官方Anthropic MCP SDK构建:

npm install @modelcontextprotocol/sdk

使用SDK注册工具 server.tool() 方法。输入模式是通过以下方式定义的 佐德 用于运行时验证。

运输

服务器使用 StdioServerTransport 从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客户端

所有keyCRM API调用都通过单个客户端模块(src/keycrm/client.js)它处理:

  • 从环境变量中注入基本URL和API密钥
  • 承载令牌身份验证(Authorization: Bearer YOUR_KEY)
  • JSON请求/响应序列化
  • HTTP错误标准化
  • 具有指数回退的速率限制重试(最多3次重试)
  • 请求超时(默认值:10秒)

update_product_photo -存储API流程

此工具在内部执行两个顺序的API调用:

  1. POST /storage/upload --将图像从提供的URL上传到keyCRM存储,返回 file_id
  2. PUT /products/{productId} --附上 file_id 到产品,可选择替换现有照片

如果上传成功但附加失败,则返回错误 file_id 包括在内,因此如果需要,可以手动重试连接。

bulk_update_products 干运行流量

同一工具的两个阶段调用:

  1. 第一阶段 (dry_run: true):使用提供的筛选器获取匹配的产品,返回列表而不修改任何内容
  2. 第2阶段 (dry_run: false, confirm: true):对所有匹配的产品执行更新

如果 dry_run: false 没有通过 confirm: true,工具返回a VALIDATION_ERROR --未经明确确认,它将不会执行。

欧洲稳定机制

该项目使用ES模块("type": "module" 在 package.json).所有导入都使用ESM语法。


11.贡献

欢迎捐款。这是一个通用的keyCRMCP-server-pull请求,扩展了keyCRMneneneba API的覆盖范围是受鼓励的。

在打开PR之前:

  • 遵循现有的文件结构(中的每个资源组一个文件 src/tools/)
  • 为每个新工具添加使用Zod的输入参数验证
  • 确保错误被捕获并作为结构化错误对象返回,而不是抛出
  • 使用第6节中的新工具更新此README

要报告错误或请求工具: 打开一个GitHub问题,其中包含您需要覆盖的keyCRMneneneba API端点和用例描述。


keycrm mcp·Ivan Klymenko·麻省理工学院许可证