Files
mcp-wms-api/src/resources/apis.js
T
Arthur Ria 706e628715 L4.1 : expose query_type sur les outils de requête (D25)
QueryType était figé à 0 en dur dans executeQuery/executeScalarQuery : le
modèle Writing, opérationnel et mesuré, était inatteignable. Paramètre
query_type (défaut 0) sur call_query_api, query_wms_entities,
count_wms_entities — get_entity_schema et search_wms_data restent des
raccourcis Reading.

D3 reste la règle par défaut : la bascule est un opt-in, avertie dans les
descriptions d'outils (statuts en énumérations en Writing). Garde de valeur
assertValidQueryType dans le code (le wrapper D23 ne valide pas les valeurs),
avant tout réseau. En query_type != 0, un nom inconnu du Metadata Reading
passe tel quel avec warning (allowUnknown du resolver) — conservé aussi dans
la réponse d'erreur si le WMS échoue ensuite. Acté en D25 ; CLAUDE.md nuancé,
L4.1 retiré de la ROADMAP (reliquat : exploration Metrics, rapport à part).

Vérifications rejouées via le protocole (LIMAGRAIN / LIMAGRAI2512) :
- call_query_api(Products, query_type:1, limit:1) -> success, 1 ligne,
  queryType:1 dans la réponse.
- call_query_api(Products, query_type:3) -> erreur structurée contenant
  'ApplicationMetricDataContext' ne contient pas de définition pour 'Products'.
- call_query_api(Products, query_type:7) -> erreur locale nommant les 4
  contextes, aucun [API] POST/GET dans stderr.
- query_wms_entities(Container, limit:1) sans query_type -> comportement
  inchangé (resolvedTableName Containers, Reading, pas de champ queryType).
- call_query_api(FooBar123, query_type:1) -> transmis tel quel (payload
  QueryType:1 Expression Context.FooBar123...), erreur WMS
  ApplicationWritingRepository + warning de résolution dans la réponse.
- count_wms_entities(Product, query_type:1) -> count 51145 (~51160).
Baseline : tools/list 23, resources 6, rejet D23 d'un paramètre inconnu OK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 11:17:10 +02:00

232 lines
5.8 KiB
JavaScript

/**
* API Resources
* Provides catalog of WMS APIs available
*/
function listResources() {
return [
{
uri: 'api://catalog',
name: 'API Catalog',
description: 'Catalog of WMS APIs available with parameters and documentation',
mimeType: 'text/markdown',
},
];
}
async function readResource(uri) {
let content;
switch (uri) {
case 'api://catalog':
content = getAPICatalog();
break;
default:
throw new Error(`Unknown API resource: ${uri}`);
}
return {
contents: [{
uri,
mimeType: 'text/markdown',
text: content,
}],
};
}
function getAPICatalog() {
return `# WMS API Catalog
## Overview
The WMS provides several REST APIs for querying and modifying data.
**Base URL:** \`https://<host>/ApplicationService/api\` — built from the active
profile's host (see \`get_current_wms_profile\`).
**Authentication:** OAuth 2.0 Bearer Token (automatic)
The generated help page at \`https://<host>/ApplicationService/Help\` is the
authoritative reference for endpoints and fields.
---
## Query API
Execute LINQ queries against WMS entities.
**Endpoint:** \`/api/QueryExecute\`
**Method:** POST
**Authentication:** Required
### Request Format
\`\`\`json
{
"Application": "EasyWMS",
"QueryType": 0,
"Expression": "Context.Products.Where(z => z.Code == \\"X\\").OrderBy(z => z.Id)",
"Take": 100
}
\`\`\`
Rules (see the query tools for details):
- **\`QueryType: 0\` (Reading) is the default** — status fields are strings
(\`"Release"\`). \`QueryType: 1\` (Writing) exists but status fields become
enums there: string comparisons fail. Old examples using \`1\` must not be
copied. The query tools expose this as the opt-in \`query_type\` parameter.
- **\`Where\` and \`OrderBy\` go in the Expression; \`Take\`/\`Skip\` are API
parameters.** \`OrderBy\` is mandatory as soon as \`Take\` is used.
- **No \`Select\` projections** — the \`Select\` parameter causes server-side
compile errors. Query full rows.
- **No relative dates** (\`DateTime.Now\`, \`AddDays()\`) — write literal dates:
\`new DateTime(2026, 8, 1)\`.
### Entity Types
Common entities: Products, Containers, Stocks, ProductLocations, Tasks,
Accounts, Suppliers, Kits, Alias (invariant — no plural form), InboundOrders,
Receptions, OutboundOrders.
**The authoritative list (288 entities) comes from \`get_entity_metadata\`**
(Metadata API) — entity names are resolved case-insensitively from the AD name
(Container) or the TableName (Containers).
### Example Expressions
\`\`\`
# Filter + mandatory OrderBy (Take passed as API parameter, not in the expression)
Context.Products.Where(z => z.Code.Contains("ABC")).OrderBy(z => z.Id)
# Status comparison — strings in Reading (QueryType 0)
Context.OutboundOrders.Where(z => z.OutboundOrderStatus == "Release").OrderBy(z => z.Id)
\`\`\`
### Counting
**Endpoint:** \`/api/QueryScalarExecute\` — same body, expression ends with
\`.Count()\` / \`.Sum(...)\`. Prefer the \`count_wms_entities\` tool for any
"how many" question.
### MCP Tools
\`query_wms_entities\`, \`count_wms_entities\`, \`call_query_api\`,
\`get_entity_schema\`, \`search_wms_data\`.
---
## Command API
Execute commands to modify WMS data.
**Endpoint:** \`/api/CommandExecute\`
**Method:** POST
**Authentication:** Required
### Request Format
\`\`\`json
[
{
"Name": "Mecalux.ITSW.EasyWMS.Modules.MasterData.Contracts.Commands.ProductRemoveCommand",
"Properties": {
"Id": "product-guid-here"
}
}
]
\`\`\`
**\`Name\` is the \`InternalCommandName\` from the Application Dictionary, used
as-is.** Never append an assembly suffix (\`, Mecalux.ITSW...Contracts\`) — it
causes a \`FileLoadException\`. Retrieve the exact name via
\`get_ad_element_details\` before executing.
### MCP Tool
Use \`execute_command\` tool to execute commands.
**⚠️ WARNING:** Commands modify data. Use with caution.
---
## Workflow API (Application Dictionary)
Retrieve workflow definitions by application.
**Endpoint:** \`/AD/api/Workflow/GetByApplication\`
**Method:** POST
**Authentication:** Required
### Request Format
\`\`\`json
["EasyWMS", "<tenant>", 5000, 0]
\`\`\`
Parameters (positional): application name, tenant code, page size, offset.
### Response
An envelope object \`{ "entities": [...] }\` — **not** a bare array. Each
workflow object carries lowercase keys: \`id\`, \`name\`, \`version\`,
\`applicationName\`, \`commonInfo\` (createdBy, createDate, updateDate). There
is no category, code or description field.
### MCP Tools
- \`search_workflows\` - Search by name
- \`get_workflow_details\` - Get full workflow definition
- \`list_workflow_categories\` - List applications (workflows have no category field)
---
## Authentication
All APIs use OAuth 2.0 authentication.
**Token Endpoint:** \`/EasySTS/OAuth/Token\`
**Grant Types:** password, refresh_token (\`tenant_code\` is mandatory)
### Token Management
- Tokens expire after ~1200 seconds
- Automatic refresh when < 1000 seconds remaining
- Credentials come from the active profile (multi-profile \`.env\`)
The MCP server handles authentication automatically.
---
## Error Handling
### HTTP Status Codes
- \`200\` - Success
- \`400\` - Bad request (invalid query/command)
- \`401\` - Unauthorized (token expired or invalid)
- \`403\` - Forbidden (insufficient permissions)
- \`500\` - Internal server error (incl. LINQ compile errors)
The response body of a 500 carries the real diagnostic (e.g. the compile
error naming the context) — MCP tools surface it in their error messages.
---
## Rate Limits and Constraints
- **Query Limit:** Maximum 1000 rows per query (configurable)
- **Query Timeout:** 30 seconds (configurable)
- **Workflow Cache:** 1 hour TTL (configurable)
---
**Note:** Use MCP tools to interact with these APIs. Direct API calls require proper authentication handling.
`;
}
module.exports = {
listResources,
readResource,
};