version mise à jour par claude , à tester
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* 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:** \`${process.env.WMS_API_BASE_URL || 'https://10.255.255.2/ApplicationService/api'}\`
|
||||
**Authentication:** OAuth 2.0 Bearer Token (automatic)
|
||||
|
||||
---
|
||||
|
||||
## Query API
|
||||
|
||||
Execute LINQ queries against WMS entities.
|
||||
|
||||
**Endpoint:** \`/api/QueryExecute\`
|
||||
**Method:** POST
|
||||
**Authentication:** Required
|
||||
|
||||
### Request Format
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"Application": "EasyWMS",
|
||||
"QueryType": 1,
|
||||
"Expression": "Context.{EntityType}.Select(z => z)"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Supported Entity Types
|
||||
|
||||
| Entity Type | Description |
|
||||
|-------------|-------------|
|
||||
| Products | Product references and SKUs |
|
||||
| Containers | Pallets, boxes, and container types |
|
||||
| Stocks | Available inventory by location |
|
||||
| ProductLocations | Product placement in warehouse |
|
||||
| Tasks | WMS tasks (picks, puts, moves, etc.) |
|
||||
| Accounts | Customer accounts |
|
||||
| Suppliers | Supplier information |
|
||||
| Kits | Product kits and bundles |
|
||||
| Aliases | Product aliases and alternative codes |
|
||||
| InboundOrders | Inbound/receiving orders |
|
||||
| Receptions | Actual receptions |
|
||||
| OutboundOrders | Outbound/shipping orders |
|
||||
|
||||
### Example Queries
|
||||
|
||||
\`\`\`
|
||||
# Get all products (limited)
|
||||
Context.Products.Take(100).Select(z => z)
|
||||
|
||||
# Get specific fields
|
||||
Context.Products.Select(z => new { z.Id, z.Code, z.Name })
|
||||
|
||||
# Filter and select
|
||||
Context.Tasks.Where(z => z.Status == "Pending").Take(50).Select(z => z)
|
||||
\`\`\`
|
||||
|
||||
### MCP Tool
|
||||
|
||||
Use \`call_query_api\` tool to execute queries.
|
||||
|
||||
---
|
||||
|
||||
## Command API
|
||||
|
||||
Execute commands to modify WMS data.
|
||||
|
||||
**Endpoint:** \`/api/CommandExecute\`
|
||||
**Method:** POST
|
||||
**Authentication:** Required
|
||||
|
||||
### Request Format
|
||||
|
||||
\`\`\`json
|
||||
[
|
||||
{
|
||||
"Name": "CommandName, Mecalux.ITSW.EasyWMS.Modules.Contracts",
|
||||
"Properties": {
|
||||
"PropertyName": "value"
|
||||
}
|
||||
}
|
||||
]
|
||||
\`\`\`
|
||||
|
||||
### Common Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| ProductRemoveCommand | Remove a product |
|
||||
| ProductUpdateCommand | Update product information |
|
||||
| ContainerCreateCommand | Create a new container |
|
||||
| TaskCancelCommand | Cancel a task |
|
||||
| InboundOrderCancelCommandV2 | Cancel an inbound order |
|
||||
| OutboundOrderCancelCommand | Cancel an outbound order |
|
||||
|
||||
### Example Command
|
||||
|
||||
\`\`\`json
|
||||
[
|
||||
{
|
||||
"Name": "Mecalux.ITSW.EasyWMS.Modules.MasterData.Contracts.Commands.ProductRemoveCommand, Mecalux.ITSW.EasyWMS.Modules.Contracts",
|
||||
"Properties": {
|
||||
"Id": "product-guid-here"
|
||||
}
|
||||
}
|
||||
]
|
||||
\`\`\`
|
||||
|
||||
### MCP Tool
|
||||
|
||||
Use \`execute_command\` tool to execute commands.
|
||||
|
||||
**⚠️ WARNING:** Commands modify data. Use with caution.
|
||||
|
||||
---
|
||||
|
||||
## Workflow API
|
||||
|
||||
Retrieve workflow definitions by application.
|
||||
|
||||
**Endpoint:** \`/AD/api/Workflow/GetByApplication\`
|
||||
**Method:** POST
|
||||
**Authentication:** Required
|
||||
|
||||
### Request Format
|
||||
|
||||
\`\`\`json
|
||||
["EasyWMS", "AD", 5000, 0]
|
||||
\`\`\`
|
||||
|
||||
Parameters:
|
||||
1. Application name (e.g., "EasyWMS")
|
||||
2. Tenant code (e.g., "AD")
|
||||
3. Page size (e.g., 5000)
|
||||
4. Offset (e.g., 0 for first page)
|
||||
|
||||
### Response
|
||||
|
||||
Array of workflow objects with:
|
||||
- Id, Code, Name
|
||||
- Category, Description
|
||||
- Version, Status
|
||||
- Created, Modified
|
||||
- Definition (JSON)
|
||||
|
||||
### MCP Tools
|
||||
|
||||
Use workflow tools to interact with workflows:
|
||||
- \`search_workflows\` - Search by name, code, description
|
||||
- \`get_workflow_details\` - Get full workflow definition
|
||||
- \`list_workflow_categories\` - List all categories
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
All APIs use OAuth 2.0 authentication.
|
||||
|
||||
**Token Endpoint:** \`/EasySTS/OAuth/Token\`
|
||||
**Grant Types:** password, refresh_token
|
||||
|
||||
### Token Management
|
||||
|
||||
- Tokens expire after ~1200 seconds
|
||||
- Automatic refresh when < 1000 seconds remaining
|
||||
- Credentials configured in .env file
|
||||
|
||||
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
|
||||
|
||||
### Error Response Format
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"error": "Error message",
|
||||
"details": "Detailed error information"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Rate Limits and Constraints
|
||||
|
||||
- **Query Limit:** Maximum 1000 rows per query (configurable)
|
||||
- **Query Timeout:** 30 seconds (configurable)
|
||||
- **Workflow Cache:** 1 hour TTL (configurable)
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
API settings are configured via environment variables:
|
||||
|
||||
\`\`\`env
|
||||
WMS_API_BASE_URL=https://10.255.255.2/ApplicationService/api
|
||||
WMS_API_TOKEN_URL=https://10.255.255.2/EasySTS/OAuth/Token
|
||||
WMS_API_TENANT=AD
|
||||
WMS_API_USERNAME=your-username
|
||||
WMS_API_PASSWORD=your-password
|
||||
WORKFLOW_API_BASE=https://10.255.255.2/AD/api
|
||||
WORKFLOW_PAGE_SIZE=5000
|
||||
MAX_QUERY_ROWS=1000
|
||||
QUERY_TIMEOUT=30000
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
**Note:** Use MCP tools to interact with these APIs. Direct API calls require proper authentication handling.
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,193 @@
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Resources MCP pour la documentation
|
||||
* Permet à Claude d'accéder à la documentation structurée en fichiers Markdown
|
||||
*/
|
||||
|
||||
// Chemin vers le dossier de documentation
|
||||
const DOCS_PATH = process.env.DOCS_PATH || path.join(__dirname, '..', '..', 'docs');
|
||||
|
||||
/**
|
||||
* Scanne récursivement un dossier pour trouver tous les fichiers .md
|
||||
* @param {string} dir - Dossier à scanner
|
||||
* @param {string} baseDir - Dossier de base pour les chemins relatifs
|
||||
* @returns {Promise<Array>} - Liste des fichiers .md
|
||||
*/
|
||||
async function scanMarkdownFiles(dir, baseDir = dir) {
|
||||
let files = [];
|
||||
|
||||
try {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Récursion dans les sous-dossiers
|
||||
const subFiles = await scanMarkdownFiles(fullPath, baseDir);
|
||||
files = files.concat(subFiles);
|
||||
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
||||
// Fichier Markdown trouvé
|
||||
const relativePath = path.relative(baseDir, fullPath);
|
||||
files.push({
|
||||
name: entry.name,
|
||||
path: fullPath,
|
||||
relativePath: relativePath.replace(/\\/g, '/'), // Normaliser les slashes
|
||||
uri: `docs://${relativePath.replace(/\\/g, '/')}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Dossier n'existe pas ou erreur de lecture
|
||||
console.error(`Error scanning directory ${dir}:`, err.message);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste les resources disponibles pour la documentation
|
||||
* @returns {Promise<Array>} - Liste des resources
|
||||
*/
|
||||
async function listResources() {
|
||||
try {
|
||||
// Scanner les fichiers Markdown
|
||||
const mdFiles = await scanMarkdownFiles(DOCS_PATH);
|
||||
|
||||
const resources = [
|
||||
{
|
||||
uri: 'docs://index',
|
||||
name: 'Documentation Index',
|
||||
description: 'Sommaire de toute la documentation disponible',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
|
||||
// Ajouter chaque fichier .md comme resource
|
||||
mdFiles.forEach((file) => {
|
||||
resources.push({
|
||||
uri: file.uri,
|
||||
name: file.name.replace('.md', ''),
|
||||
description: `Documentation: ${file.relativePath}`,
|
||||
mimeType: 'text/markdown',
|
||||
});
|
||||
});
|
||||
|
||||
return resources;
|
||||
} catch (err) {
|
||||
console.error('Error listing documentation resources:', err);
|
||||
return [
|
||||
{
|
||||
uri: 'docs://index',
|
||||
name: 'Documentation Index',
|
||||
description: 'Sommaire de toute la documentation disponible',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un index/sommaire de la documentation
|
||||
* @returns {Promise<string>} - Markdown avec le sommaire
|
||||
*/
|
||||
async function generateIndex() {
|
||||
try {
|
||||
const mdFiles = await scanMarkdownFiles(DOCS_PATH);
|
||||
|
||||
if (mdFiles.length === 0) {
|
||||
return `# Documentation\n\n*Aucun fichier de documentation trouvé dans \`${DOCS_PATH}\`*\n\n` +
|
||||
`Pour ajouter de la documentation :\n` +
|
||||
`1. Créez un dossier \`docs\` à la racine du projet\n` +
|
||||
`2. Ajoutez vos fichiers .md (organisation libre avec sous-dossiers)\n` +
|
||||
`3. Redémarrez le serveur MCP\n`;
|
||||
}
|
||||
|
||||
let markdown = '# Documentation WMS\n\n';
|
||||
markdown += `**${mdFiles.length} fichiers de documentation disponibles**\n\n`;
|
||||
markdown += `📁 Emplacement : \`${DOCS_PATH}\`\n\n`;
|
||||
|
||||
// Grouper par dossier
|
||||
const grouped = {};
|
||||
mdFiles.forEach((file) => {
|
||||
const dir = path.dirname(file.relativePath);
|
||||
const folder = dir === '.' ? '📄 Racine' : `📁 ${dir}`;
|
||||
|
||||
if (!grouped[folder]) {
|
||||
grouped[folder] = [];
|
||||
}
|
||||
grouped[folder].push(file);
|
||||
});
|
||||
|
||||
// Générer le sommaire
|
||||
markdown += '## Sommaire\n\n';
|
||||
|
||||
Object.keys(grouped).sort().forEach((folder) => {
|
||||
markdown += `### ${folder}\n\n`;
|
||||
|
||||
grouped[folder].forEach((file) => {
|
||||
markdown += `- **${file.name.replace('.md', '')}** - \`${file.uri}\`\n`;
|
||||
});
|
||||
|
||||
markdown += '\n';
|
||||
});
|
||||
|
||||
markdown += '---\n\n';
|
||||
markdown += '*Pour lire un fichier, demandez à Claude de lire la resource correspondante (par exemple: "Lis la documentation X")*\n';
|
||||
|
||||
return markdown;
|
||||
} catch (err) {
|
||||
return `# Erreur\n\nImpossible de générer l'index de documentation: ${err.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lit un fichier de documentation
|
||||
* @param {string} relativePath - Chemin relatif du fichier
|
||||
* @returns {Promise<string>} - Contenu Markdown du fichier
|
||||
*/
|
||||
async function readDocFile(relativePath) {
|
||||
try {
|
||||
const filePath = path.join(DOCS_PATH, relativePath);
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
return content;
|
||||
} catch (err) {
|
||||
return `# Erreur\n\nImpossible de lire le fichier \`${relativePath}\`: ${err.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lit une resource documentation selon son URI
|
||||
* @param {string} uri - URI de la resource (format: docs://path/to/file.md)
|
||||
* @returns {Promise<Object>} - Contenu de la resource
|
||||
*/
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
if (uri === 'docs://index') {
|
||||
content = await generateIndex();
|
||||
} else if (uri.startsWith('docs://')) {
|
||||
// Extraire le chemin relatif de l'URI
|
||||
const relativePath = uri.replace('docs://', '');
|
||||
content = await readDocFile(relativePath);
|
||||
} else {
|
||||
throw new Error(`Unknown documentation resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Entity Schema Resources
|
||||
* Provides schema information for WMS entity types
|
||||
*/
|
||||
|
||||
function listResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'wms://entity-schemas',
|
||||
name: 'Entity Schemas',
|
||||
description: 'Schema information and common fields for WMS entities',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
switch (uri) {
|
||||
case 'wms://entity-schemas':
|
||||
content = getEntitySchemas();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown entity schema resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
function getEntitySchemas() {
|
||||
return `# WMS Entity Schemas
|
||||
|
||||
## Overview
|
||||
|
||||
Entity schemas define the structure and available fields for each entity type.
|
||||
Use the \`get_entity_schema\` tool to retrieve the actual schema from the API by querying one entity.
|
||||
|
||||
## Common Field Patterns
|
||||
|
||||
Most WMS entities follow these patterns:
|
||||
|
||||
### Standard Fields
|
||||
- \`Id\` - Unique identifier (GUID or integer)
|
||||
- \`Code\` - Business code/reference
|
||||
- \`Name\` - Display name
|
||||
- \`Description\` - Detailed description
|
||||
- \`Created\` - Creation timestamp
|
||||
- \`Modified\` - Last modification timestamp
|
||||
- \`Status\` - Entity status
|
||||
|
||||
### Relationship Fields
|
||||
- \`{Entity}Id\` - Foreign key to related entity (e.g., ProductId, AccountId)
|
||||
- \`{Entity}Code\` - Related entity code
|
||||
- \`{Entity}Name\` - Related entity name
|
||||
|
||||
## Entity-Specific Schemas
|
||||
|
||||
### Products
|
||||
Common fields:
|
||||
- Id, Code, Name, Description
|
||||
- Category, Family, SubFamily
|
||||
- Weight, Volume, Height, Width, Length
|
||||
- UnitOfMeasure, BaseUnit
|
||||
- Barcode, AlternativeCodes
|
||||
- Active, Blocked
|
||||
|
||||
### Containers
|
||||
Common fields:
|
||||
- Id, Code, Name, Type
|
||||
- Status, Location, Zone
|
||||
- Weight, Tare, MaxWeight
|
||||
- ProductId, Quantity
|
||||
- Created, Modified
|
||||
|
||||
### Tasks
|
||||
Common fields:
|
||||
- Id, Code, Type, Status
|
||||
- Priority, Sequence
|
||||
- SourceLocation, TargetLocation
|
||||
- ProductId, Quantity
|
||||
- AssignedUser, AssignedDevice
|
||||
- StartedAt, CompletedAt
|
||||
|
||||
### Stocks
|
||||
Common fields:
|
||||
- ProductId, ProductCode, ProductName
|
||||
- LocationId, LocationCode
|
||||
- Quantity, AvailableQuantity, ReservedQuantity
|
||||
- UnitOfMeasure
|
||||
- LotNumber, SerialNumber
|
||||
- ExpirationDate
|
||||
|
||||
### InboundOrders / OutboundOrders
|
||||
Common fields:
|
||||
- Id, Code, ExternalCode
|
||||
- Type, Status, Priority
|
||||
- AccountId, AccountCode, AccountName
|
||||
- SupplierId, SupplierCode (inbound only)
|
||||
- ExpectedDate, PlannedDate, ActualDate
|
||||
- TotalLines, TotalQuantity
|
||||
- Created, Modified
|
||||
|
||||
## Retrieving Schemas
|
||||
|
||||
Use the \`get_entity_schema\` tool to dynamically retrieve the schema:
|
||||
|
||||
\`\`\`
|
||||
# Get Products schema
|
||||
get_entity_schema(entity_type="Products")
|
||||
|
||||
# Get Tasks schema
|
||||
get_entity_schema(entity_type="Tasks")
|
||||
\`\`\`
|
||||
|
||||
This will query one entity from the API and return all available fields with sample values.
|
||||
|
||||
## LINQ Field Selection
|
||||
|
||||
You can select specific fields using LINQ expressions:
|
||||
|
||||
\`\`\`
|
||||
# Select specific fields
|
||||
query_wms_entities(
|
||||
entity_type="Products",
|
||||
select_expression="z => new { z.Id, z.Code, z.Name, z.Category }"
|
||||
)
|
||||
|
||||
# Nested object creation
|
||||
query_wms_entities(
|
||||
entity_type="Tasks",
|
||||
select_expression="z => new {
|
||||
Task = z.Code,
|
||||
Product = z.ProductName,
|
||||
Status = z.Status
|
||||
}"
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
**Note:** Field availability may vary depending on WMS configuration and version.
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* Logs Resources
|
||||
* Provides guide for WMS log files
|
||||
*/
|
||||
|
||||
function listResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'logs://guide',
|
||||
name: 'Logs Guide',
|
||||
description: 'Guide for WMS log files: formats, locations, common error patterns',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
switch (uri) {
|
||||
case 'logs://guide':
|
||||
content = getLogsGuide();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown logs resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
function getLogsGuide() {
|
||||
return `# WMS Logs Guide
|
||||
|
||||
## Log File Locations
|
||||
|
||||
**Primary Logs:** \`${process.env.LOGS_PATH || 'C:\\inetpub\\logs\\LogFiles\\Mecalux'}\`
|
||||
|
||||
Log files are typically named with date patterns:
|
||||
- \`application_YYYYMMDD.log\`
|
||||
- \`error_YYYYMMDD.log\`
|
||||
- \`api_YYYYMMDD.log\`
|
||||
|
||||
---
|
||||
|
||||
## Log File Format
|
||||
|
||||
WMS logs typically follow this format:
|
||||
|
||||
\`\`\`
|
||||
[YYYY-MM-DD HH:MM:SS.fff] [LEVEL] [Module] Message
|
||||
Additional context or stack trace (if applicable)
|
||||
\`\`\`
|
||||
|
||||
### Example Log Entries
|
||||
|
||||
\`\`\`
|
||||
[2024-01-15 10:23:45.123] [INFO] [TaskService] Task TASK-001 created successfully
|
||||
[2024-01-15 10:23:46.456] [ERROR] [StockService] Insufficient stock for product PROD-123
|
||||
[2024-01-15 10:23:47.789] [WARN] [OrderService] Order ORD-456 delayed - expected date passed
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Log Levels
|
||||
|
||||
| Level | Description | Severity |
|
||||
|-------|-------------|----------|
|
||||
| DEBUG | Detailed diagnostic information | Low |
|
||||
| INFO | General informational messages | Low |
|
||||
| WARN | Warning messages for potential issues | Medium |
|
||||
| ERROR | Error messages for failures | High |
|
||||
| FATAL | Critical errors causing system failure | Critical |
|
||||
|
||||
---
|
||||
|
||||
## Common Error Patterns
|
||||
|
||||
### Database Errors
|
||||
|
||||
\`\`\`
|
||||
ORA-00001: unique constraint violated
|
||||
ORA-01017: invalid username/password
|
||||
ORA-12170: connection timeout
|
||||
ORA-00060: deadlock detected
|
||||
Connection timeout
|
||||
Constraint violation
|
||||
Foreign key violation
|
||||
\`\`\`
|
||||
|
||||
### WMS Business Errors
|
||||
|
||||
\`\`\`
|
||||
Insufficient stock
|
||||
Stock not found
|
||||
Product not found
|
||||
Location occupied
|
||||
Location not available
|
||||
Task already completed
|
||||
Order already processed
|
||||
Invalid product code
|
||||
Invalid container code
|
||||
\`\`\`
|
||||
|
||||
### Integration Errors
|
||||
|
||||
\`\`\`
|
||||
API call failed
|
||||
Authentication failed
|
||||
Token expired
|
||||
Request timeout
|
||||
JSON parse error
|
||||
XML parse error
|
||||
Connection refused
|
||||
Service unavailable
|
||||
\`\`\`
|
||||
|
||||
### System Errors
|
||||
|
||||
\`\`\`
|
||||
Out of memory
|
||||
OutOfMemoryException
|
||||
StackOverflowException
|
||||
File not found
|
||||
Access denied
|
||||
Permission denied
|
||||
Disk full
|
||||
Network unreachable
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## MCP Tools for Logs
|
||||
|
||||
### read_recent_logs
|
||||
|
||||
Read the most recent log entries from a log file.
|
||||
|
||||
**Parameters:**
|
||||
- \`count\` - Number of lines to read (default: 100)
|
||||
- \`log_file\` - Specific log file name (optional, uses most recent if not specified)
|
||||
|
||||
**Example:**
|
||||
\`\`\`
|
||||
read_recent_logs(count=200)
|
||||
read_recent_logs(count=50, log_file="error_20240115.log")
|
||||
\`\`\`
|
||||
|
||||
### search_logs
|
||||
|
||||
Search for a keyword across all log files with context.
|
||||
|
||||
**Parameters:**
|
||||
- \`keyword\` - Search term (e.g., "ERROR", "PROD-123", "timeout")
|
||||
- \`max_results\` - Maximum results to return (default: 50)
|
||||
- \`context_lines\` - Lines of context before/after match (default: 2)
|
||||
|
||||
**Example:**
|
||||
\`\`\`
|
||||
search_logs(keyword="ERROR", max_results=100)
|
||||
search_logs(keyword="PROD-123", context_lines=5)
|
||||
search_logs(keyword="timeout", max_results=20)
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Debugging Workflow
|
||||
|
||||
### 1. Check Recent Activity
|
||||
|
||||
Start by reading recent logs to understand current system state:
|
||||
|
||||
\`\`\`
|
||||
read_recent_logs(count=200)
|
||||
\`\`\`
|
||||
|
||||
### 2. Search for Errors
|
||||
|
||||
Look for error patterns:
|
||||
|
||||
\`\`\`
|
||||
search_logs(keyword="ERROR", max_results=50)
|
||||
search_logs(keyword="EXCEPTION", max_results=50)
|
||||
search_logs(keyword="FAILED", max_results=50)
|
||||
\`\`\`
|
||||
|
||||
### 3. Search for Specific Entity
|
||||
|
||||
Find references to specific orders, products, or tasks:
|
||||
|
||||
\`\`\`
|
||||
search_logs(keyword="ORDER-123", context_lines=5)
|
||||
search_logs(keyword="PROD-456", context_lines=5)
|
||||
\`\`\`
|
||||
|
||||
### 4. Correlate with API/Database
|
||||
|
||||
Once you find relevant log entries:
|
||||
- Use \`query_wms_entities\` to check current entity state
|
||||
- Use \`search_workflows\` to find related workflows
|
||||
- Use \`call_query_api\` to verify data consistency
|
||||
|
||||
---
|
||||
|
||||
## Log Analysis Tips
|
||||
|
||||
### Time-Based Analysis
|
||||
|
||||
Log timestamps help correlate events:
|
||||
- Look for errors occurring at the same time
|
||||
- Check for patterns (e.g., errors every hour, at specific times)
|
||||
- Correlate with known system events (deployments, restarts)
|
||||
|
||||
### Frequency Analysis
|
||||
|
||||
- How often does this error occur?
|
||||
- Is it increasing or decreasing over time?
|
||||
- Does it happen at specific intervals?
|
||||
|
||||
### Context Analysis
|
||||
|
||||
Always request context lines when searching:
|
||||
- See what happened before the error
|
||||
- See what happened after the error
|
||||
- Understand the execution flow
|
||||
|
||||
### Pattern Recognition
|
||||
|
||||
Look for common patterns:
|
||||
- Same error message repeatedly
|
||||
- Same product/order/task in multiple errors
|
||||
- Same module or service causing issues
|
||||
- Cascading failures (one error leading to others)
|
||||
|
||||
---
|
||||
|
||||
## Common Debugging Scenarios
|
||||
|
||||
### Scenario 1: Order Not Processing
|
||||
|
||||
\`\`\`
|
||||
1. search_logs(keyword="ORDER-123", context_lines=5)
|
||||
2. query_wms_entities(entity_type="OutboundOrders", filter='z.Code == "ORDER-123"')
|
||||
3. Check order status and error messages in both logs and database
|
||||
\`\`\`
|
||||
|
||||
### Scenario 2: Stock Discrepancy
|
||||
|
||||
\`\`\`
|
||||
1. search_logs(keyword="PROD-456", context_lines=3)
|
||||
2. query_wms_entities(entity_type="Stocks", filter='z.ProductCode == "PROD-456"')
|
||||
3. Compare expected vs actual stock levels
|
||||
4. Check for stock movement tasks
|
||||
\`\`\`
|
||||
|
||||
### Scenario 3: Task Failures
|
||||
|
||||
\`\`\`
|
||||
1. search_logs(keyword="TASK-789", context_lines=5)
|
||||
2. query_wms_entities(entity_type="Tasks", filter='z.Code == "TASK-789"')
|
||||
3. Check task status, error message, and assigned user/device
|
||||
\`\`\`
|
||||
|
||||
### Scenario 4: Performance Issues
|
||||
|
||||
\`\`\`
|
||||
1. search_logs(keyword="timeout", max_results=100)
|
||||
2. search_logs(keyword="slow", max_results=100)
|
||||
3. Look for patterns in timeouts (specific operations, times, modules)
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Log Retention
|
||||
|
||||
- Log files are typically rotated daily
|
||||
- Older logs may be compressed or archived
|
||||
- Check with system administrator for retention policy
|
||||
|
||||
---
|
||||
|
||||
**Note:** Use log tools in combination with WMS entity queries for complete debugging picture.
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Query Examples Resources
|
||||
* Provides example LINQ queries and diagnostic recipes for WMS entities.
|
||||
*/
|
||||
|
||||
function listResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'wms://query-examples',
|
||||
name: 'Query Examples',
|
||||
description: 'LINQ query examples and diagnostic recipes for WMS entities',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
switch (uri) {
|
||||
case 'wms://query-examples':
|
||||
content = getQueryExamples();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown query examples resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
function getQueryExamples() {
|
||||
return `# WMS LINQ Query Examples & Diagnostic Recipes
|
||||
|
||||
> **Reading model** — \`query_wms_entities\` / \`count_wms_entities\` use \`QueryExecute\`
|
||||
> (QueryType=Reading). Status/enum fields are **strings** (enum names), never integers.
|
||||
> Always verify enum values via \`docs://entities/\` or \`get_entity_metadata\` before filtering.
|
||||
|
||||
---
|
||||
|
||||
## Diagnostic Recipes
|
||||
|
||||
Recipes below were validated against a live WMS. Use them as-is, substituting the
|
||||
\`X\` placeholders.
|
||||
|
||||
### OS incomplètes par classe d'expédition
|
||||
|
||||
Compter les ordres de sortie incomplets, actifs, d'une classe donnée
|
||||
(\`OutboundClassCode\`). Fields verified on the \`OutboundOrder\` Reading entity:
|
||||
\`OutboundClassCode\` (string), \`IncompleteOrder\` (bool), \`IsActive\` (bool).
|
||||
|
||||
\`\`\`
|
||||
# Toutes classes confondues
|
||||
count_wms_entities(
|
||||
entity_type="OutboundOrders",
|
||||
filter='z.IncompleteOrder == true && z.IsActive == true'
|
||||
)
|
||||
|
||||
# Pour une classe précise
|
||||
count_wms_entities(
|
||||
entity_type="OutboundOrders",
|
||||
filter='z.OutboundClassCode == "SHIPPING_GROUP_01" && z.IncompleteOrder == true && z.IsActive == true'
|
||||
)
|
||||
|
||||
# Lister le détail des OS concernées
|
||||
query_wms_entities(
|
||||
entity_type="OutboundOrders",
|
||||
filter='z.OutboundClassCode == "SHIPPING_GROUP_01" && z.IncompleteOrder == true && z.IsActive == true',
|
||||
limit=200
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
### Containers bloquants sur un emplacement
|
||||
|
||||
Identifier les conteneurs qui retiennent un emplacement parce qu'ils ont des tâches
|
||||
en attente. Fields verified on the \`Container\` Reading entity:
|
||||
\`LocationCode\` (string), \`NumContainerPendingTasks\` (long).
|
||||
|
||||
\`\`\`
|
||||
# Combien de containers ont des tâches en attente sur l'emplacement
|
||||
count_wms_entities(
|
||||
entity_type="Containers",
|
||||
filter='z.LocationCode == "QUAI_EXP_01" && z.NumContainerPendingTasks > 0'
|
||||
)
|
||||
|
||||
# Lister ces containers (renvoie toutes les colonnes du container)
|
||||
query_wms_entities(
|
||||
entity_type="Containers",
|
||||
filter='z.LocationCode == "QUAI_EXP_01" && z.NumContainerPendingTasks > 0',
|
||||
limit=200
|
||||
)
|
||||
|
||||
# Vue globale : tous les containers bloquants du WMS
|
||||
count_wms_entities(
|
||||
entity_type="Containers",
|
||||
filter='z.NumContainerPendingTasks > 0'
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
### Paramètres système d'un entrepôt
|
||||
|
||||
Pour lire les paramètres de configuration WMS et leurs valeurs par entrepôt,
|
||||
utiliser l'outil dédié \`get_system_parameters\` plutôt qu'une requête LINQ :
|
||||
|
||||
\`\`\`
|
||||
get_system_parameters(warehouse="DOMBASLE") # tous les paramètres
|
||||
get_system_parameters(warehouse="DOMBASLE", param_class="Shipping")
|
||||
get_system_parameters(search="CROSSDOCK")
|
||||
\`\`\`
|
||||
|
||||
### Modèles d'expédition — suivi des exécutions
|
||||
|
||||
> ⚠️ L'API ne conserve que la **dernière** exécution de chaque modèle d'expédition
|
||||
> (\`ShipmentTemplate.LastExecuteDate\`). L'historique complet des exécutions n'existe
|
||||
> que dans les logs serveur \`ApplyShipmentTemplates\`, non exposés par ce MCP.
|
||||
|
||||
Fields verified on the \`ShipmentTemplate\` Reading entity: \`Code\`, \`Status\`,
|
||||
\`IsEnabled\`, \`IsActive\`, \`LastExecuteDate\`, \`WarehouseCode\`, \`Priority\`,
|
||||
\`DirectiveCode\`.
|
||||
|
||||
\`\`\`
|
||||
# Tous les modèles d'un entrepôt + leur dernière exécution et leur statut
|
||||
query_wms_entities(
|
||||
entity_type="ShipmentTemplates",
|
||||
filter='z.WarehouseCode == "DOMBASLE"',
|
||||
limit=200
|
||||
)
|
||||
|
||||
# Modèles activés mais jamais exécutés (LastExecuteDate null)
|
||||
query_wms_entities(
|
||||
entity_type="ShipmentTemplates",
|
||||
filter='z.IsEnabled == true && z.LastExecuteDate == null',
|
||||
limit=200
|
||||
)
|
||||
|
||||
# Combien de modèles exécutés au moins une fois
|
||||
count_wms_entities(
|
||||
entity_type="ShipmentTemplates",
|
||||
filter='z.LastExecuteDate != null'
|
||||
)
|
||||
|
||||
# Modèles exécutés depuis une date (littéral DateTime obligatoire — voir Date filters)
|
||||
count_wms_entities(
|
||||
entity_type="ShipmentTemplates",
|
||||
filter='z.LastExecuteDate >= new DateTime(2025, 1, 1)'
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Counting (\`count_wms_entities\`)
|
||||
|
||||
Always prefer \`count_wms_entities\` for any "combien" / "how many" question — it uses
|
||||
\`QueryScalarExecute\` and never materialises rows.
|
||||
|
||||
\`\`\`
|
||||
count_wms_entities(entity_type="OutboundOrders")
|
||||
count_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "InProcess"')
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Basic Queries
|
||||
|
||||
### Get rows (with limit)
|
||||
|
||||
\`\`\`
|
||||
query_wms_entities(entity_type="Products", limit=100)
|
||||
query_wms_entities(entity_type="Tasks", limit=50)
|
||||
\`\`\`
|
||||
|
||||
> Note: the \`select_expression\` parameter (LINQ projections) is currently unreliable
|
||||
> against \`QueryExecute\` — prefer querying full rows and reading the fields you need.
|
||||
|
||||
## Filtering Examples
|
||||
|
||||
### Status filters (string enum names)
|
||||
|
||||
\`\`\`
|
||||
# Tâches en cours / en attente
|
||||
query_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "InProcess"', limit=100)
|
||||
query_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "Pending"', limit=100)
|
||||
|
||||
# Ordres de sortie lancés
|
||||
query_wms_entities(entity_type="OutboundOrders", filter='z.OutboundOrderStatus == "Release"', limit=100)
|
||||
\`\`\`
|
||||
|
||||
### Date filters
|
||||
|
||||
> ⚠️ \`AddDays()\` et les dates relatives (\`DateTime.Now\`, \`DateTime.Today\`) ne sont
|
||||
> **pas traduisibles** par le moteur de requête — toujours utiliser un littéral
|
||||
> \`new DateTime(année, mois, jour)\`. Le nom du champ date dépend de l'entité
|
||||
> (\`LastExecuteDate\`, \`InternalInfo.CreationDate\`, …) — le vérifier via
|
||||
> \`get_entity_metadata\` ou \`docs://entities/\`.
|
||||
|
||||
\`\`\`
|
||||
# Éléments depuis une date donnée (littéral DateTime obligatoire)
|
||||
count_wms_entities(
|
||||
entity_type="ShipmentTemplates",
|
||||
filter='z.LastExecuteDate >= new DateTime(2025, 1, 1)'
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
### Numeric filters
|
||||
|
||||
\`\`\`
|
||||
query_wms_entities(entity_type="Stocks", filter="z.Quantity > 0", limit=100)
|
||||
\`\`\`
|
||||
|
||||
### String filters
|
||||
|
||||
\`\`\`
|
||||
query_wms_entities(entity_type="Products", filter='z.Code.StartsWith("ABC")', limit=100)
|
||||
query_wms_entities(entity_type="Products", filter='z.Code.Contains("test")', limit=100)
|
||||
\`\`\`
|
||||
|
||||
## Complex Filters
|
||||
|
||||
### Multiple conditions (AND / OR)
|
||||
|
||||
\`\`\`
|
||||
query_wms_entities(
|
||||
entity_type="Tasks",
|
||||
filter='z.TaskStatus == "Pending" && z.Priority > 50',
|
||||
limit=100
|
||||
)
|
||||
|
||||
query_wms_entities(
|
||||
entity_type="OutboundOrders",
|
||||
filter='z.OutboundOrderStatus == "Release" || z.OutboundOrderStatus == "Creating"',
|
||||
limit=100
|
||||
)
|
||||
\`\`\`
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Find an entity by code
|
||||
|
||||
\`\`\`
|
||||
query_wms_entities(entity_type="Products", filter='z.Code == "PROD123"', limit=1)
|
||||
query_wms_entities(entity_type="OutboundOrders", filter='z.Code == "ORDER123"', limit=1)
|
||||
\`\`\`
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Always use limits** — max 1000 rows per query.
|
||||
2. **Use \`count_wms_entities\` for counts** — never fetch rows just to count them.
|
||||
3. **Verify enum values first** — Reading model uses string enum names.
|
||||
4. **Use specific filters** — narrow results at the API level.
|
||||
|
||||
---
|
||||
|
||||
**Note:** All queries respect the maximum limit of 1000 rows configured in the server.
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* WMS Entity Resources
|
||||
* Provides overview of WMS entity types available via Query API
|
||||
*/
|
||||
|
||||
function listResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'wms://entities',
|
||||
name: 'WMS Entities Overview',
|
||||
description: 'Overview of all WMS entity types available for querying',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
switch (uri) {
|
||||
case 'wms://entities':
|
||||
content = getEntitiesOverview();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown WMS entity resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
function getEntitiesOverview() {
|
||||
return `# WMS Entities — Reference Guide
|
||||
|
||||
## Tools to use
|
||||
|
||||
- **\`count_wms_entities\`** — count with optional filter (use for "combien", "nombre de")
|
||||
- **\`query_wms_entities\`** — fetch rows with select/filter/limit
|
||||
- **\`get_entity_schema\`** — discover field names by fetching one sample record
|
||||
- **\`call_query_api\`** — raw LINQ query, full control
|
||||
|
||||
---
|
||||
|
||||
## Note importante : Reading model vs Writing model
|
||||
|
||||
Le \`QueryExecute\` (Context.*) interroge le **Reading model** — les champs de statut sont des **strings**, pas des entiers ni des enums C#.
|
||||
|
||||
---
|
||||
|
||||
## OutboundOrders — Ordres de sortie
|
||||
|
||||
**Reading model:** \`Mecalux.ITSW.EasyWMS.Modules.Expeditions.Reading.Domain.OutboundOrder\`
|
||||
**Status field:** \`OutboundOrderStatus\` → **string**
|
||||
|
||||
| Statut | Filtre LINQ |
|
||||
|---|---|
|
||||
| Lancé | \`z.OutboundOrderStatus == "Launched"\` |
|
||||
| En attente | \`z.OutboundOrderStatus == "Waiting"\` |
|
||||
| En création | \`z.OutboundOrderStatus == "Creating"\` |
|
||||
|
||||
**Champs clés :** \`Code\`, \`OutboundOrderStatus\`, \`WarehouseCode\`, \`AccountCode\`, \`RouteCode\`, \`Priority\`, \`AssignedUser\`, \`NumPendingTasks\`, \`NumReleasedLines\`, \`HasTroubles\`, \`ShippingDeadline\`
|
||||
|
||||
**Exemples:**
|
||||
\`\`\`
|
||||
// Compter les ODS lancés
|
||||
count_wms_entities(entity_type="OutboundOrders", filter='z.OutboundOrderStatus == "Launched"')
|
||||
|
||||
// Lister les ODS lancés avec infos clés
|
||||
query_wms_entities(entity_type="OutboundOrders",
|
||||
select_expression="z => new { z.Code, z.OutboundOrderStatus, z.AccountCode, z.NumPendingTasks, z.HasTroubles }",
|
||||
filter='z.OutboundOrderStatus == "Launched"', limit=100)
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## InboundOrders — Ordres d'entrée
|
||||
|
||||
**Status field:** \`InboundStatus\` → **string**
|
||||
|
||||
| Statut | Filtre LINQ |
|
||||
|---|---|
|
||||
| Réception en attente | \`z.InboundStatus == "ReceptionPending"\` |
|
||||
| Réception en cours | \`z.InboundStatus == "Receiving"\` |
|
||||
| Complété | \`z.InboundStatus == "Completed"\` |
|
||||
| Reçu partiellement | \`z.InboundStatus == "PartiallyReceived"\` |
|
||||
| Annulé | \`z.InboundStatus == "Cancelled"\` |
|
||||
| Fermeture | \`z.InboundStatus == "Closing"\` |
|
||||
|
||||
---
|
||||
|
||||
## Tasks — Tâches
|
||||
|
||||
**Status field:** \`TaskStatus\` → **string** (valeurs à confirmer via get_entity_schema)
|
||||
|
||||
\`\`\`
|
||||
// Schéma exact avec valeurs d'exemple
|
||||
get_entity_schema(entity_type="Tasks")
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Kits
|
||||
|
||||
\`\`\`
|
||||
count_wms_entities(entity_type="Kits", filter="z.IsEnable == true")
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## Autres entités disponibles (Reading model, 278 au total)
|
||||
|
||||
**Opérations :** Tasks, Stocks, ProductLocations, ContainerLock, CountOrder, CountOrderLine
|
||||
**Entrepôt :** Location, Aisle, AisleType, Division, Container, ContainerType
|
||||
**Entrées :** InboundOrders, Receptions, InboundClass
|
||||
**Sorties :** OutboundOrders, Shipment, OutboundClass, Wave
|
||||
**Référentiel :** Products, Accounts, Suppliers, Kits, Aliases, Agency, Route
|
||||
|
||||
**Pour connaître les champs exacts d'une entité :**
|
||||
1. \`get_entity_metadata(entity_name="...")\` — métadonnées officielles via l'API
|
||||
2. \`get_entity_schema(entity_type="...")\` — exemple live avec tous les champs
|
||||
|
||||
---
|
||||
|
||||
## Note sur \`Take()\`
|
||||
|
||||
Certaines entités (dont OutboundOrders) peuvent retourner HTTP 500 si \`Take()\` est ajouté.
|
||||
- **count_wms_entities** n'utilise jamais \`Take()\` → toujours sûr
|
||||
- **query_wms_entities** utilise \`Take(limit)\` → préférer une limite raisonnable (100-500)
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Workflow Resources
|
||||
* Provides context about workflows available via API
|
||||
*/
|
||||
|
||||
function listResources() {
|
||||
return [
|
||||
{
|
||||
uri: 'workflows://overview',
|
||||
name: 'Workflow Overview',
|
||||
description: 'Overview of workflow system and available categories',
|
||||
mimeType: 'text/markdown',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function readResource(uri) {
|
||||
let content;
|
||||
|
||||
switch (uri) {
|
||||
case 'workflows://overview':
|
||||
content = getWorkflowOverview();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown workflow resource: ${uri}`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: [{
|
||||
uri,
|
||||
mimeType: 'text/markdown',
|
||||
text: content,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
function getWorkflowOverview() {
|
||||
return `# WMS Workflows
|
||||
|
||||
## Overview
|
||||
|
||||
Workflows are retrieved via the **Workflow API** (\`/AD/api/Workflow/GetByApplication\`).
|
||||
|
||||
**Total Workflows:** ~3712
|
||||
**Data Source:** API endpoint (lazy loaded with 1-hour cache)
|
||||
**Pagination:** Configurable page size (default: 5000)
|
||||
|
||||
## Available Tools
|
||||
|
||||
Use these tools to interact with workflows:
|
||||
|
||||
### \`search_workflows\`
|
||||
Search workflows by name, description, or code.
|
||||
- Supports category filtering
|
||||
- Returns workflow metadata
|
||||
- Workflows are cached after first request
|
||||
|
||||
### \`get_workflow_details\`
|
||||
Get complete details of a specific workflow by ID or code.
|
||||
|
||||
### \`list_workflow_categories\`
|
||||
List all available workflow categories with statistics.
|
||||
|
||||
## Common Workflow Categories
|
||||
|
||||
- **EasyWMS**: Core WMS workflows
|
||||
- **CustomApplication**: Custom workflows
|
||||
- **Deliveries**: Delivery and shipping workflows
|
||||
- **AccountDirective**: Account management workflows
|
||||
- **Notifications**: Notification workflows
|
||||
- **LaborManagement**: Labor management workflows
|
||||
|
||||
## Usage Examples
|
||||
|
||||
\`\`\`
|
||||
# Search for order-related workflows
|
||||
search_workflows(query="Order", limit=20)
|
||||
|
||||
# Get workflow details
|
||||
get_workflow_details(workflow_id="abc123")
|
||||
|
||||
# List all categories
|
||||
list_workflow_categories()
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
**Note:** Workflows are fetched from the API only when first requested, then cached for 1 hour to improve performance.
|
||||
`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listResources,
|
||||
readResource,
|
||||
};
|
||||
Reference in New Issue
Block a user