@aiotic/mcp
Click on "Deploy 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., "@@aiotic/mcp find the endpoint contract for creating a purchase order"
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.
@aiotic/mcp
The Model Context Protocol server for the AIOTIC Integrator Guide. It gives your coding assistant (Claude Code, Cursor, VS Code or any other MCP client) exact answers while you integrate AIOTIC purchase-order processing with your ERP: it searches the guide, returns endpoint contracts and schemas from the public OpenAPI document and hands out payload examples. On your own machine it can also look at your test tenant.
Documentation: https://developers.aiotic.ai/ai/mcp-server — tools, security model, setup per assistant.
Changes: CHANGELOG.md.
Questions and problems: open an issue in this repository.
Use it
The entry differs per assistant: Claude Code and Cursor read mcpServers, VS Code reads servers.
Claude Code, in .mcp.json in your project:
{ "mcpServers": { "aiotic": { "command": "npx", "args": ["-y", "@aiotic/mcp"] } } }Cursor, in .cursor/mcp.json in your project, or in ~/.cursor/mcp.json for every project:
{ "mcpServers": { "aiotic": { "type": "stdio", "command": "npx", "args": ["-y", "@aiotic/mcp"] } } }VS Code, in .vscode/mcp.json in your project:
{ "servers": { "aiotic": { "type": "stdio", "command": "npx", "args": ["-y", "@aiotic/mcp"] } } }Other assistants and where their configuration lives: MCP server in the guide. Node.js 20 or newer. There is nothing else to configure: docs mode needs no key and sends nothing anywhere.
Each version carries one edition of the guide and of the API document, so pin a version
("args": ["-y", "@aiotic/mcp@<version>"]) when you want the same answers every time. The server reports the edition
to your client when it connects.
Prefer no installation at all? The hosted endpoint https://mcp.aiotic.ai/mcp runs the same server in docs mode and
always serves the latest revision of the guide. For Claude Code:
{ "mcpServers": { "aiotic": { "type": "http", "url": "https://mcp.aiotic.ai/mcp" } } }The guide has the entry, a one-line command or a one-click link for every other assistant: Connect your coding assistant.
Related MCP server: MCP Server for Odoo
Docs mode (default)
Tool | What it returns |
| Best-matching sections with page, heading and snippet |
| Every page of the guide with section, title and summary |
| One page as Markdown |
| Method, path, summary and authentication per endpoint, plus the outbound webhooks |
| The full contract: parameters, request and response schemas, examples |
| One schema from the OpenAPI components |
| Payload samples |
| Status values, their meaning and the transitions between them |
Tenant mode (opt-in, local only)
Set AIOTIC_BASE_URL and AIOTIC_API_KEY in the server's environment and the assistant can also read your test
tenant or the mock from the AIOTIC Python SDK: orders and
their status, rejected e-mails, customers, products and customer item mappings.
{ "mcpServers": { "aiotic": {
"command": "npx", "args": ["-y", "@aiotic/mcp"],
"env": { "AIOTIC_BASE_URL": "http://localhost:8080", "AIOTIC_API_KEY": "mock-integration-key" } } } }That is the entry for Claude Code and Cursor; in VS Code the same command, args and env go under servers,
with "type": "stdio".
Read tools are on. Write tools need
AIOTIC_MCP_ALLOW_WRITES=true. Deletes andsend_order_to_erpalso needAIOTIC_MCP_ALLOW_DANGEROUS=trueandconfirm: truein the call.Keys come from the environment, never from tool arguments, and are removed from everything the server returns.
Tenant tools exist on the stdio transport only. Use a test tenant: whatever key you put in an assistant's environment, the assistant can use.
Run it over HTTP yourself
npx -y @aiotic/mcp --http 3333 # http://127.0.0.1:3333/mcp and /healthz, docs mode onlyThe HTTP transport refuses to start when any tenant variable is set. Behind a reverse proxy, set
AIOTIC_MCP_TRUST_PROXY to the peers whose X-Real-IP and X-Forwarded-For headers may be believed: 1
(loopback), gateway (the container's default gateway), private, CIDR ranges or any.
Variable | Purpose | Default |
| Address the server listens on |
|
| Requests per client address: a burst, then a steady rate |
|
|
| any host |
| Browser origins that may call; a request with any other | none |
| Largest request body, in bytes |
|
| File with addresses and CIDR ranges to refuse | none |
| Usage log, one JSON line per request; | off |
| Days the usage log is kept |
|
| Size limits of the usage log, per day and in total |
|
| MMDB country database for the usage log | none |
Development
npm ci
npm test # builds, then runs the smoke test over stdio and HTTPThis repository is published release by release from the AIOTIC documentation sources, one commit per release, and
each release is published to npm from here by .github/workflows/publish-npm.yml. Pull requests cannot be merged here
directly; please open an issue and we will take the change into the next release.
License
MIT, see LICENSE.
Available Tools
28 toolsdelete_customerDelete customer (dangerous)B
DELETE /customer/{number}. Requires AIOTIC_MCP_ALLOW_DANGEROUS=true and confirm:true.
Inputs: number (required), confirm.
delete_customer_productDelete customer item mapping (dangerous)A
DELETE /customer-product/{customer_number}/{customer_item_number}. Requires AIOTIC_MCP_ALLOW_DANGEROUS=true and confirm:true.
Inputs: customer_number (required), customer_item_number (required), confirm.
delete_productDelete product (dangerous)B
DELETE /product/{item_number}/{language_code}. Requires AIOTIC_MCP_ALLOW_DANGEROUS=true and confirm:true.
Inputs: item_number (required), language_code (required), confirm.
get_customerGet customerD
GET /customer/{number}.
Inputs: number (required).
get_endpointGet an endpoint contractA
Full contract of one endpoint by operationId (e.g. sendOrderToErp, uploadOrder, upsertCustomer) or "METHOD /path", or a webhook name (erpReceiveOrder, processingCompleted). Schemas are inlined.
Inputs: ref (required).
get_exampleGet a payload exampleB
Real payload samples. Names: erp-receive-request, erp-receive-response-accepted, erp-receive-response-rejected, order-status, upload-response-split, raw-upload-rejection, customer-upsert, product-upsert, customer-product-upsert, sync-events.
Inputs: name (required).
get_order_groupGet split e-mail groupD
GET /order/group/{email_group_id}.
Inputs: email_group_id (required).
get_order_statusGet order statusB
GET /order_status/{request_id} — status, extracted purchase order (result), erp_ref, errors.
Inputs: request_id (required).
get_pageGet a guide pageA
Return one guide page as Markdown. Paths look like /receiving/erp-receive-endpoint or /sdk/pipeline. Use list_pages to discover paths.
Inputs: path (required).
get_productGet productD
GET /product/{item_number}/{language_code}.
Inputs: item_number (required), language_code (required).
get_schemaGet a schemaA
One JSON schema from the API components, with $refs inlined. Names: Address, ClassifiedEmail, Customer, CustomerListResponse, CustomerProduct, CustomerProductListResponse, CustomerProductUpsert, CustomerSearchResponse, CustomerUpsert, EmailClassificationResponse, ErpAddress, ErpCustomer, ErpOrderItem, ErpPurchaseOrder, ErpReceiveRequest, ErpReceiveResponse, ErpRecipient, ErpSendResponse, ErpShippingDetails, ErrorResponse, FetchAllEmailsResponse, HTTPValidationError, OrderCustomer, OrderGroup, OrderItem, OrderListResponse, OrderRef, OrderRetryBody, OrderStatus, OrderStatusValue, OrderUploadBody, OrderUploadResponse, ProcessingWebhookRequest, Product, ProductListResponse, ProductUpsert, PurchaseOrder, RawEmailClassifyBody, RawEmailUploadBody, RawUploadRejection, RejectedEmailListResponse, ReprocessResponse, ShippingDetails, ShippingRecipient, Supplier, SystemStatus, ValidationError.
Inputs: name (required).
get_status_lifecycleOrder status lifecycleB
Status values, which are sendable / landed / terminal, and the transitions between them.
Inputs: no named parameters.
list_customer_productsList customer item mappingsC
GET /customer-product/list with optional filters.
Inputs: size, item_number, customer_number.
list_endpointsList API endpointsA
Every public AIOTIC endpoint (method, path, summary, auth) plus the outbound webhooks you implement. Optional tag filter: health, orders, order-status, erp, rejected, customers, products, customer-products, email-watcher, webhooks.
Inputs: tag.
list_ordersList ordersC
GET /order_status/list — newest first.
Inputs: page, size.
list_pagesList guide pagesA
All pages of the guide with section, title and one-line summary, in reading order.
Inputs: no named parameters.
list_productsList productsD
GET /product/list.
Inputs: page, size, language_code.
list_rejected_emailsList rejected e-mailsD
GET /rejected/list.
Inputs: size, status.
reprocess_rejected_emailReprocess a rejected e-mail (write)C
POST /rejected/{request_id}/reprocess. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: request_id (required).
retry_orderRetry a FAILED order (write)B
POST /order/retry/{request_id}. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: request_id (required).
search_customersSearch customersC
GET /customer/search/{query} — fuzzy search over your customer records, comparable to how AIOTIC matches order senders.
Inputs: query (required), top_k.
search_guideSearch the Integrator GuideA
Full-text search over the guide (sections). Returns page, heading, URL and a snippet. Use before answering any AIOTIC integration question.
Inputs: query (required), limit.
send_order_to_erpSend order to ERP (dangerous)A
POST /erp/send/{request_id} — calls the tenant's ERP receive endpoint. Requires AIOTIC_MCP_ALLOW_DANGEROUS=true and confirm:true.
Inputs: request_id (required), confirm.
tenant_healthTenant healthA
GET /healthcheck and /system-status of the configured tenant (no key needed).
Inputs: no named parameters.
upload_orderUpload a text order (write)B
POST /order/upload with one text/markdown file built from the given content — for exercising the flow against the mock/test tenant. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: content (required), filename (required), request_id.
upsert_customerUpsert customer (write)C
PUT /customer/{number}. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: data (required), number (required).
upsert_customer_productUpsert customer item mapping (write)C
PUT /customer-product/{customer_number}/{customer_item_number}. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: item_number (required), language_code (required), customer_number (required), customer_item_number (required).
upsert_productUpsert product (write)C
PUT /product/{item_number}/{language_code}. Requires AIOTIC_MCP_ALLOW_WRITES=true.
Inputs: description (required), item_number (required), language_code (required), remark.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Tools are largely distinct: documentation tools (search_guide, get_page, list_pages) vs. contract tools (list_endpoints, get_endpoint, get_schema, get_example) vs. domain operations are clearly separated by resource and action. The only mild overlap is among the order-flow write tools (retry_order, upload_order, send_order_to_erp, reprocess_rejected_email), but their descriptions distinguish them well enough.
The set follows a consistent snake_case verb_noun pattern (list_orders, get_customer, upsert_product, delete_customer, search_customers). The main deviation is tenant_health, which uses a noun_noun form rather than a verb prefix, but everything else is predictable.
At 28 tools this is heavy and sits at the upper edge of what an agent can scan efficiently. The breadth is partly justified by the wide domain (full docs surface plus orders, customers, products, and rejected-email operations), and most tools earn their place, but the count is borderline excessive.
Coverage is strong: full CRUD for customers, products, and customer-products, plus order lifecycle (upload, retry, send, status, group), rejected-email handling, and comprehensive docs/contract tooling. Minor gaps remain (no explicit order deletion, webhook configuration management, or batch operations), but core workflows have no dead ends.
Maintenance
Related MCP Connectors
Connect AI to store orders, products and inventory with scoped access and human approvals.
Connect AI to Odoo ERP 14-20: search, create, update and manage records in natural language.
Gives AI agents direct access to your Sanity projects and guidance for working with them
Read, write and run Odoo actions from any AI app, as each user, with approval rules per colleague.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Odoo ERP systems through natural language to search records, create entries, update data, and manage business operations. Supports secure authentication and configurable access controls for production environments.Mozilla Public 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with Odoo ERP systems through natural language, allowing users to search, create, update, and manage business records like customers, products, and invoices across any Odoo instance.1Mozilla Public 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query and operate on ERP data through a unified tool interface, working across CSV exports, SFTP drop folders, SQLite/ODBC, and optional enterprise APIs. It supports purchase orders, vendors, and inventory lookups while keeping agent-facing tools consistent regardless of backend.MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to query and execute Slingrs ERP endpoints for sales orders, inventory, production, purchasing, shipments, and custom entities through dynamically loaded OpenAPI tools.9 npm-