aura-courier-mcp 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/paperfly.d.ts +16 -0
- package/dist/adapters/paperfly.js +96 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +8 -0
- package/dist/http.js +5 -1
- package/dist/registry.js +3 -0
- package/dist/server.js +3 -3
- package/package.json +3 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CourierAdapter } from "./base.js";
|
|
2
|
+
import { BalanceResponse, ParcelCreateRequest, ParcelResponse, SupportedCourier, TrackingResponse } from "../types.js";
|
|
3
|
+
export declare class PaperflyAdapter implements CourierAdapter {
|
|
4
|
+
courierName: SupportedCourier;
|
|
5
|
+
private apiKey;
|
|
6
|
+
private username;
|
|
7
|
+
private password;
|
|
8
|
+
private storeName;
|
|
9
|
+
private client;
|
|
10
|
+
private enabled;
|
|
11
|
+
constructor(apiKey: string, username: string, password: string, storeName: string, baseUrl: string);
|
|
12
|
+
isConfigured(): boolean;
|
|
13
|
+
createParcel(req: ParcelCreateRequest): Promise<ParcelResponse>;
|
|
14
|
+
trackParcel(trackingCode: string): Promise<TrackingResponse>;
|
|
15
|
+
getBalance(): Promise<BalanceResponse>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
export class PaperflyAdapter {
|
|
3
|
+
courierName = "paperfly";
|
|
4
|
+
apiKey;
|
|
5
|
+
username;
|
|
6
|
+
password;
|
|
7
|
+
storeName;
|
|
8
|
+
client;
|
|
9
|
+
enabled;
|
|
10
|
+
constructor(apiKey, username, password, storeName, baseUrl) {
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
this.username = username;
|
|
13
|
+
this.password = password;
|
|
14
|
+
this.storeName = storeName;
|
|
15
|
+
this.enabled = Boolean(apiKey && username && password);
|
|
16
|
+
this.client = axios.create({
|
|
17
|
+
baseURL: baseUrl,
|
|
18
|
+
timeout: 15000,
|
|
19
|
+
headers: { "Content-Type": "application/json" },
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
isConfigured() {
|
|
23
|
+
return this.enabled;
|
|
24
|
+
}
|
|
25
|
+
async createParcel(req) {
|
|
26
|
+
if (!this.enabled) {
|
|
27
|
+
throw new Error("Paperfly credentials (paperflykey + merchant username & password) are not configured.");
|
|
28
|
+
}
|
|
29
|
+
if (!this.storeName) {
|
|
30
|
+
throw new Error("Paperfly store name is required to create a parcel.");
|
|
31
|
+
}
|
|
32
|
+
const payload = {
|
|
33
|
+
merchantOrderReference: req.invoice,
|
|
34
|
+
storeName: this.storeName,
|
|
35
|
+
productBrief: req.item_type || "Product",
|
|
36
|
+
packagePrice: String(req.value ?? req.cod_amount ?? 0),
|
|
37
|
+
max_weight: String(req.item_weight ?? 0.5),
|
|
38
|
+
customerName: req.recipient_name,
|
|
39
|
+
customerAddress: req.recipient_address,
|
|
40
|
+
customerPhone: req.recipient_phone,
|
|
41
|
+
};
|
|
42
|
+
const response = await this.client.post("/merchant/api/service/new_order_v2.php", payload, {
|
|
43
|
+
headers: { paperflykey: this.apiKey },
|
|
44
|
+
auth: { username: this.username, password: this.password },
|
|
45
|
+
});
|
|
46
|
+
const data = response.data;
|
|
47
|
+
const ok = data?.success;
|
|
48
|
+
if (!ok?.tracking_number) {
|
|
49
|
+
throw new Error(`Paperfly API error: ${JSON.stringify(data?.error || data?.message || data)}`);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
courier: "paperfly",
|
|
54
|
+
tracking_code: ok.tracking_number,
|
|
55
|
+
consignment_id: ok.tracking_barcode || ok.tracking_number,
|
|
56
|
+
invoice: req.invoice,
|
|
57
|
+
status: ok.message || "created",
|
|
58
|
+
cod_amount: req.cod_amount,
|
|
59
|
+
created_at: new Date().toISOString(),
|
|
60
|
+
raw_response: data,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async trackParcel(trackingCode) {
|
|
64
|
+
if (!this.enabled) {
|
|
65
|
+
throw new Error("Paperfly credentials are not configured.");
|
|
66
|
+
}
|
|
67
|
+
if (!this.username || !this.password) {
|
|
68
|
+
throw new Error("Paperfly tracking needs your merchant-panel username & password (Basic Auth). Add them to use track_parcel.");
|
|
69
|
+
}
|
|
70
|
+
// Paperfly tracks by your merchant order reference (merchantOrderReference), not its tracking number.
|
|
71
|
+
const response = await this.client.post("/API-Order-Tracking", { ReferenceNumber: trackingCode }, { headers: { paperflykey: this.apiKey }, auth: { username: this.username, password: this.password } });
|
|
72
|
+
const data = response.data;
|
|
73
|
+
const st = data?.success?.trackingStatus?.[0] || {};
|
|
74
|
+
const stages = [
|
|
75
|
+
[st.Delivered, "delivered"],
|
|
76
|
+
[st.Partial, "partial-delivery"],
|
|
77
|
+
[st.Returned, "returned"],
|
|
78
|
+
[st.PickedForDelivery, "out-for-delivery"],
|
|
79
|
+
[st.inTransit, "in-transit"],
|
|
80
|
+
[st.ReceivedAtPoint, "received-at-point"],
|
|
81
|
+
[st.Pick, "picked-up"],
|
|
82
|
+
];
|
|
83
|
+
const status = stages.find(([v]) => v && String(v).trim())?.[1] || data?.success?.message || "pending";
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
courier: "paperfly",
|
|
87
|
+
tracking_code: trackingCode,
|
|
88
|
+
status,
|
|
89
|
+
updated_at: new Date().toISOString(),
|
|
90
|
+
raw_response: data,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async getBalance() {
|
|
94
|
+
throw new Error("Paperfly does not expose a merchant balance endpoint via its public API — check the Paperfly merchant panel.");
|
|
95
|
+
}
|
|
96
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -20,6 +20,14 @@ export interface CourierConfig {
|
|
|
20
20
|
pickupStoreId: string;
|
|
21
21
|
enabled: boolean;
|
|
22
22
|
};
|
|
23
|
+
paperfly: {
|
|
24
|
+
apiKey: string;
|
|
25
|
+
username: string;
|
|
26
|
+
password: string;
|
|
27
|
+
storeName: string;
|
|
28
|
+
baseUrl: string;
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
};
|
|
23
31
|
}
|
|
24
32
|
export type EnvSource = Record<string, string | undefined>;
|
|
25
33
|
/**
|
package/dist/config.js
CHANGED
|
@@ -32,5 +32,13 @@ export function loadConfig(src = process.env) {
|
|
|
32
32
|
pickupStoreId: src.REDX_PICKUP_STORE_ID || "",
|
|
33
33
|
enabled: Boolean(src.REDX_API_TOKEN),
|
|
34
34
|
},
|
|
35
|
+
paperfly: {
|
|
36
|
+
apiKey: src.PAPERFLY_API_KEY || "",
|
|
37
|
+
username: src.PAPERFLY_USERNAME || "",
|
|
38
|
+
password: src.PAPERFLY_PASSWORD || "",
|
|
39
|
+
storeName: src.PAPERFLY_STORE_NAME || "",
|
|
40
|
+
baseUrl: src.PAPERFLY_BASE_URL || "https://api.paperfly.com.bd",
|
|
41
|
+
enabled: Boolean(src.PAPERFLY_API_KEY && src.PAPERFLY_STORE_NAME),
|
|
42
|
+
},
|
|
35
43
|
};
|
|
36
44
|
}
|
package/dist/http.js
CHANGED
|
@@ -33,6 +33,10 @@ function keysFromRequest(req) {
|
|
|
33
33
|
REDX_API_TOKEN: pick("x-redx-api-token", "redx_token"),
|
|
34
34
|
REDX_BASE_URL: pick("x-redx-base-url", "redx_base_url"),
|
|
35
35
|
REDX_PICKUP_STORE_ID: pick("x-redx-pickup-store-id", "redx_pickup_store_id"),
|
|
36
|
+
PAPERFLY_API_KEY: pick("x-paperfly-api-key", "paperfly_key"),
|
|
37
|
+
PAPERFLY_USERNAME: pick("x-paperfly-username", "paperfly_username"),
|
|
38
|
+
PAPERFLY_PASSWORD: pick("x-paperfly-password", "paperfly_password"),
|
|
39
|
+
PAPERFLY_STORE_NAME: pick("x-paperfly-store-name", "paperfly_store"),
|
|
36
40
|
};
|
|
37
41
|
}
|
|
38
42
|
const app = express();
|
|
@@ -40,7 +44,7 @@ app.use(express.json({ limit: "1mb" }));
|
|
|
40
44
|
// Allow browser-based and cross-origin MCP clients.
|
|
41
45
|
app.use((req, res, next) => {
|
|
42
46
|
res.header("Access-Control-Allow-Origin", "*");
|
|
43
|
-
res.header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, mcp-session-id, mcp-protocol-version, x-steadfast-api-key, x-steadfast-secret-key, x-steadfast-base-url, x-pathao-client-id, x-pathao-client-secret, x-pathao-username, x-pathao-password, x-pathao-store-id, x-pathao-base-url, x-redx-api-token, x-redx-base-url, x-redx-pickup-store-id");
|
|
47
|
+
res.header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, mcp-session-id, mcp-protocol-version, x-steadfast-api-key, x-steadfast-secret-key, x-steadfast-base-url, x-pathao-client-id, x-pathao-client-secret, x-pathao-username, x-pathao-password, x-pathao-store-id, x-pathao-base-url, x-redx-api-token, x-redx-base-url, x-redx-pickup-store-id, x-paperfly-api-key, x-paperfly-username, x-paperfly-password, x-paperfly-store-name");
|
|
44
48
|
res.header("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
45
49
|
res.header("Access-Control-Expose-Headers", "mcp-session-id");
|
|
46
50
|
if (req.method === "OPTIONS") {
|
package/dist/registry.js
CHANGED
|
@@ -2,6 +2,7 @@ import { SteadfastAdapter } from "./adapters/steadfast.js";
|
|
|
2
2
|
import { PathaoAdapter } from "./adapters/pathao.js";
|
|
3
3
|
import { FraudRiskEngine } from "./adapters/fraud_engine.js";
|
|
4
4
|
import { RedxAdapter } from "./adapters/redx.js";
|
|
5
|
+
import { PaperflyAdapter } from "./adapters/paperfly.js";
|
|
5
6
|
import { loadConfig } from "./config.js";
|
|
6
7
|
export class CourierRegistry {
|
|
7
8
|
adapters = new Map();
|
|
@@ -12,6 +13,8 @@ export class CourierRegistry {
|
|
|
12
13
|
this.adapters.set("pathao", pathao);
|
|
13
14
|
const redx = new RedxAdapter(config.redx.apiToken, config.redx.baseUrl, config.redx.pickupStoreId);
|
|
14
15
|
this.adapters.set("redx", redx);
|
|
16
|
+
const paperfly = new PaperflyAdapter(config.paperfly.apiKey, config.paperfly.username, config.paperfly.password, config.paperfly.storeName, config.paperfly.baseUrl);
|
|
17
|
+
this.adapters.set("paperfly", paperfly);
|
|
15
18
|
}
|
|
16
19
|
listCouriers() {
|
|
17
20
|
return Array.from(this.adapters.entries()).map(([name, adapter]) => ({
|
package/dist/server.js
CHANGED
|
@@ -9,11 +9,11 @@ export const TOOLS = [
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
name: "create_parcel",
|
|
12
|
-
description: "Book a new parcel delivery across Bangladesh (Steadfast, Pathao or
|
|
12
|
+
description: "Book a new parcel delivery across Bangladesh (Steadfast, Pathao, RedX or Paperfly) with normalized response.",
|
|
13
13
|
inputSchema: {
|
|
14
14
|
type: "object",
|
|
15
15
|
properties: {
|
|
16
|
-
courier: { type: "string", enum: ["steadfast", "pathao", "redx", "auto"], description: "Target courier or 'auto' for AI smart routing (default: auto)" },
|
|
16
|
+
courier: { type: "string", enum: ["steadfast", "pathao", "redx", "paperfly", "auto"], description: "Target courier or 'auto' for AI smart routing (default: auto)" },
|
|
17
17
|
invoice: { type: "string", description: "Unique order invoice number (e.g. INV-1002)" },
|
|
18
18
|
recipient_name: { type: "string", description: "Customer full name" },
|
|
19
19
|
recipient_phone: { type: "string", description: "11-digit Bangladeshi mobile number (e.g. 017XXXXXXXX)" },
|
|
@@ -36,7 +36,7 @@ export const TOOLS = [
|
|
|
36
36
|
type: "object",
|
|
37
37
|
properties: {
|
|
38
38
|
tracking_code: { type: "string", description: "Consignment ID or tracking code" },
|
|
39
|
-
courier: { type: "string", enum: ["steadfast", "pathao", "redx"], description: "Optional courier name if known" },
|
|
39
|
+
courier: { type: "string", enum: ["steadfast", "pathao", "redx", "paperfly"], description: "Optional courier name if known" },
|
|
40
40
|
},
|
|
41
41
|
required: ["tracking_code"],
|
|
42
42
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aura-courier-mcp",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Universal Bangladesh courier MCP server — Steadfast, Pathao &
|
|
3
|
+
"version": "2.3.1",
|
|
4
|
+
"description": "Universal Bangladesh courier MCP server — Steadfast, Pathao, RedX & Paperfly with a built-in fraud-risk engine — for Claude, Antigravity, Cursor & n8n AI agents. Runs as a local npx (STDIO) server or a remote HTTP endpoint.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"steadfast",
|
|
29
29
|
"pathao",
|
|
30
30
|
"redx",
|
|
31
|
+
"paperfly",
|
|
31
32
|
"bangladesh",
|
|
32
33
|
"antigravity",
|
|
33
34
|
"claude",
|