@promptpartner/bexio-mcp-server 2.0.0 → 2.0.2

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.
@@ -1,81 +0,0 @@
1
- import { App } from "@modelcontextprotocol/ext-apps";
2
- const appEl = document.getElementById("app");
3
- const app = new App({ name: "Bexio Dashboard", version: "1.0.0" });
4
- app.ontoolresult = (result) => {
5
- const text = result.content?.find((c) => c.type === "text")?.text;
6
- if (text) {
7
- try {
8
- const data = JSON.parse(text);
9
- renderDashboard(data);
10
- }
11
- catch (e) {
12
- appEl.innerHTML = `<div class="loading">Error parsing dashboard data</div>`;
13
- }
14
- }
15
- };
16
- app.connect();
17
- function formatCurrency(amount, currency) {
18
- return `${currency} ${amount.toLocaleString("de-CH", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
19
- }
20
- function getInitials(name1, name2) {
21
- const parts = [name1, name2].filter(Boolean);
22
- return parts.map(p => p.charAt(0).toUpperCase()).join("").slice(0, 2) || "?";
23
- }
24
- function renderDashboard(data) {
25
- appEl.className = "dashboard";
26
- appEl.innerHTML = `
27
- <div class="header">
28
- <h1>Bexio Dashboard</h1>
29
- <p class="subtitle">Overview of your invoices and recent contacts</p>
30
- </div>
31
-
32
- <div class="grid">
33
- <div class="card">
34
- <div class="card-header">
35
- <div class="card-icon blue">
36
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
37
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
38
- </svg>
39
- </div>
40
- <span class="card-title">Open Invoices</span>
41
- </div>
42
- <div class="card-value">${data.open_invoices_count}</div>
43
- <div class="card-subtitle">${formatCurrency(data.open_invoices_total, data.currency)} total</div>
44
- </div>
45
-
46
- <div class="card">
47
- <div class="card-header">
48
- <div class="card-icon yellow">
49
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
50
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
51
- </svg>
52
- </div>
53
- <span class="card-title">Overdue</span>
54
- </div>
55
- <div class="card-value">${data.overdue_count}</div>
56
- <div class="card-subtitle">${formatCurrency(data.overdue_total, data.currency)} outstanding</div>
57
- </div>
58
-
59
- <div class="card">
60
- <div class="card-header">
61
- <div class="card-icon green">
62
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
63
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"/>
64
- </svg>
65
- </div>
66
- <span class="card-title">Recent Contacts</span>
67
- </div>
68
- <div class="contacts-list">
69
- ${data.recent_contacts.length > 0 ? data.recent_contacts.slice(0, 5).map(contact => `
70
- <div class="contact-item">
71
- <div class="contact-avatar">${getInitials(contact.name_1, contact.name_2)}</div>
72
- <span class="contact-name">${[contact.name_1, contact.name_2].filter(Boolean).join(" ")}</span>
73
- </div>
74
- `).join("") : `
75
- <div class="empty-state">No recent contacts</div>
76
- `}
77
- </div>
78
- </div>
79
- </div>
80
- `;
81
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,96 +0,0 @@
1
- import { App } from "@modelcontextprotocol/ext-apps";
2
- const appEl = document.getElementById("app");
3
- const app = new App({ name: "Invoice Preview", version: "1.0.0" });
4
- app.ontoolresult = (result) => {
5
- const text = result.content?.find((c) => c.type === "text")?.text;
6
- if (text) {
7
- try {
8
- const invoice = JSON.parse(text);
9
- renderInvoice(invoice);
10
- }
11
- catch (e) {
12
- appEl.innerHTML = `<div class="loading">Error parsing invoice data</div>`;
13
- }
14
- }
15
- };
16
- app.connect();
17
- function getStatusInfo(statusId) {
18
- switch (statusId) {
19
- case 7: return { label: "Draft", className: "status-draft" };
20
- case 8: return { label: "Pending", className: "status-pending" };
21
- case 9: return { label: "Sent", className: "status-sent" };
22
- case 16: return { label: "Paid", className: "status-paid" };
23
- case 17: return { label: "Overdue", className: "status-overdue" };
24
- case 19: return { label: "Cancelled", className: "status-cancelled" };
25
- default: return { label: `Status ${statusId}`, className: "status-draft" };
26
- }
27
- }
28
- function formatCurrency(amount, currencyId) {
29
- const value = typeof amount === "string" ? parseFloat(amount) : amount;
30
- const currency = currencyId === 1 ? "CHF" : currencyId === 2 ? "EUR" : "USD";
31
- return `${currency} ${value.toFixed(2)}`;
32
- }
33
- function formatDate(dateStr) {
34
- if (!dateStr)
35
- return "";
36
- const date = new Date(dateStr);
37
- return date.toLocaleDateString("de-CH", { day: "2-digit", month: "2-digit", year: "numeric" });
38
- }
39
- function renderInvoice(invoice) {
40
- const status = getStatusInfo(invoice.kb_item_status_id);
41
- const positions = invoice.positions || [];
42
- appEl.className = "invoice";
43
- appEl.innerHTML = `
44
- <div class="header">
45
- <div class="header-left">
46
- <h1>Invoice ${invoice.document_nr}</h1>
47
- <p class="title">${invoice.title || ""}</p>
48
- </div>
49
- <div class="header-right">
50
- <div class="dates">
51
- <div>Issue: ${formatDate(invoice.is_valid_from)}</div>
52
- <div>Due: ${formatDate(invoice.is_valid_to)}</div>
53
- </div>
54
- <span class="status-badge ${status.className}">${status.label}</span>
55
- </div>
56
- </div>
57
-
58
- <div class="contact-section">
59
- <h2>Bill To</h2>
60
- <div class="name">${invoice.contact_address?.split("\n")[0] || `Contact #${invoice.contact_id}`}</div>
61
- <div class="email">${invoice.contact_address?.split("\n").slice(1).join(", ") || ""}</div>
62
- </div>
63
-
64
- <table class="line-items">
65
- <thead>
66
- <tr>
67
- <th>Description</th>
68
- <th>Qty</th>
69
- <th>Price</th>
70
- <th>Amount</th>
71
- </tr>
72
- </thead>
73
- <tbody>
74
- ${positions.length > 0 ? positions.map((p) => `
75
- <tr>
76
- <td>${p.text}</td>
77
- <td>${p.amount}</td>
78
- <td>${formatCurrency(p.unit_price, invoice.currency_id)}</td>
79
- <td>${formatCurrency(p.amount * p.unit_price * (1 - (p.discount_in_percent || 0) / 100), invoice.currency_id)}</td>
80
- </tr>
81
- `).join("") : `
82
- <tr>
83
- <td colspan="4" style="text-align: center; color: #6b7280;">No line items available</td>
84
- </tr>
85
- `}
86
- </tbody>
87
- </table>
88
-
89
- <div class="total-section">
90
- <div class="total-row">
91
- <span class="total-label">Total:</span>
92
- <span class="total-amount">${formatCurrency(invoice.total_gross, invoice.currency_id)}</span>
93
- </div>
94
- </div>
95
- `;
96
- }