@prbartosh/poczta-mcp 0.1.0
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/.env.example +19 -0
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/config.example.json +50 -0
- package/cron.example +19 -0
- package/dist/auth/google.js +29 -0
- package/dist/auth/google.js.map +1 -0
- package/dist/auth/index.js +31 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/microsoft.js +44 -0
- package/dist/auth/microsoft.js.map +1 -0
- package/dist/config.js +201 -0
- package/dist/config.js.map +1 -0
- package/dist/digest.js +82 -0
- package/dist/digest.js.map +1 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/install.js +209 -0
- package/dist/install.js.map +1 -0
- package/dist/mail/imap.js +192 -0
- package/dist/mail/imap.js.map +1 -0
- package/dist/mail/smtp.js +50 -0
- package/dist/mail/smtp.js.map +1 -0
- package/dist/oauth.js +138 -0
- package/dist/oauth.js.map +1 -0
- package/dist/server.js +201 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.js +444 -0
- package/dist/setup.js.map +1 -0
- package/package.json +62 -0
- package/skills/daily-briefing/SKILL.md +57 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import nodemailer from "nodemailer";
|
|
2
|
+
import { resolveCreds } from "../auth/index.js";
|
|
3
|
+
import { getMessageId } from "./imap.js";
|
|
4
|
+
async function transport(acc) {
|
|
5
|
+
const creds = await resolveCreds(acc);
|
|
6
|
+
const base = {
|
|
7
|
+
host: acc.smtp.host,
|
|
8
|
+
port: acc.smtp.port,
|
|
9
|
+
secure: acc.smtp.secure, // true = implicit TLS (465); false = STARTTLS (587)
|
|
10
|
+
requireTLS: !acc.smtp.secure,
|
|
11
|
+
};
|
|
12
|
+
if (creds.kind === "password") {
|
|
13
|
+
return nodemailer.createTransport({ ...base, auth: { user: creds.user, pass: creds.pass } });
|
|
14
|
+
}
|
|
15
|
+
return nodemailer.createTransport({
|
|
16
|
+
...base,
|
|
17
|
+
auth: { type: "OAuth2", user: creds.user, accessToken: creds.accessToken },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export async function sendEmail(acc, opts) {
|
|
21
|
+
const mail = {
|
|
22
|
+
from: acc.email,
|
|
23
|
+
to: opts.to,
|
|
24
|
+
subject: opts.subject,
|
|
25
|
+
text: opts.body,
|
|
26
|
+
...(opts.html ? { html: opts.html } : {}),
|
|
27
|
+
};
|
|
28
|
+
if (opts.replyToUid) {
|
|
29
|
+
const mid = await getMessageId(acc, opts.replyToUid).catch(() => undefined);
|
|
30
|
+
if (mid) {
|
|
31
|
+
mail.inReplyTo = mid;
|
|
32
|
+
mail.references = mid;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const tx = await transport(acc);
|
|
36
|
+
try {
|
|
37
|
+
const info = await tx.sendMail(mail);
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
from: acc.email,
|
|
41
|
+
to: opts.to,
|
|
42
|
+
subject: opts.subject,
|
|
43
|
+
messageId: info.messageId,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
tx.close();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=smtp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp.js","sourceRoot":"","sources":["../../src/mail/smtp.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAIzC,KAAK,UAAU,SAAS,CAAC,GAAY;IACnC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;QACnB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;QACnB,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,oDAAoD;QAC7E,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;KAC7B,CAAC;IACF,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC,eAAe,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,UAAU,CAAC,eAAe,CAAC;QAChC,GAAG,IAAI;QACP,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE;KAC3E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAY,EACZ,IAMC;IAED,MAAM,IAAI,GAA+B;QACvC,IAAI,EAAE,GAAG,CAAC,KAAK;QACf,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1C,CAAC;IAEF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5E,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,GAAG,CAAC,KAAK;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
/**
|
|
4
|
+
* Loopback OAuth2 flow: spin a local http server on 127.0.0.1, open the consent
|
|
5
|
+
* URL in the browser, catch the redirect with ?code=, exchange it for a refresh
|
|
6
|
+
* token. No copy-pasting tokens by hand.
|
|
7
|
+
*
|
|
8
|
+
* Google: "Desktop app" client type allows any 127.0.0.1:<port> redirect, so this
|
|
9
|
+
* is seamless.
|
|
10
|
+
* Microsoft: the redirect URI must be registered in Azure (App registration ->
|
|
11
|
+
* Authentication -> add platform "Mobile and desktop applications" ->
|
|
12
|
+
* http://localhost). We use a FIXED port so it matches the registration.
|
|
13
|
+
*/
|
|
14
|
+
function openBrowser(url) {
|
|
15
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
16
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
17
|
+
try {
|
|
18
|
+
spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* user can open manually from the printed URL */
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const DONE_HTML = "<html><body style='font-family:sans-serif;padding:3rem;text-align:center'>" +
|
|
25
|
+
"<h2>OK</h2><p>Token zapisany. Mozesz zamknac te karte i wrocic do terminala.</p></body></html>";
|
|
26
|
+
const ERR_HTML = "<html><body style='font-family:sans-serif;padding:3rem;text-align:center'>" +
|
|
27
|
+
"<h2>Blad</h2><p>{msg}</p></body></html>";
|
|
28
|
+
/**
|
|
29
|
+
* Start a one-shot loopback server on 127.0.0.1:<port> (port 0 = random).
|
|
30
|
+
* `onReady(redirectUri)` fires once the server is listening — the caller builds the
|
|
31
|
+
* authorize URL with that redirect and opens the browser. Resolves with the auth code.
|
|
32
|
+
*/
|
|
33
|
+
function awaitCode(port, onReady) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const server = http.createServer((reqMsg, res) => {
|
|
36
|
+
const u = new URL(reqMsg.url ?? "/", "http://127.0.0.1");
|
|
37
|
+
const code = u.searchParams.get("code");
|
|
38
|
+
const err = u.searchParams.get("error");
|
|
39
|
+
if (err) {
|
|
40
|
+
res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
|
|
41
|
+
res.end(ERR_HTML.replace("{msg}", err));
|
|
42
|
+
server.close();
|
|
43
|
+
reject(new Error(`consent error: ${err}`));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (code) {
|
|
47
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
48
|
+
res.end(DONE_HTML);
|
|
49
|
+
server.close();
|
|
50
|
+
resolve(code);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
res.writeHead(404);
|
|
54
|
+
res.end();
|
|
55
|
+
});
|
|
56
|
+
server.on("error", reject);
|
|
57
|
+
server.listen(port, "127.0.0.1", () => {
|
|
58
|
+
const actual = server.address().port;
|
|
59
|
+
onReady(`http://127.0.0.1:${actual}`);
|
|
60
|
+
});
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
server.close();
|
|
63
|
+
reject(new Error("timeout: brak zgody w 5 min"));
|
|
64
|
+
}, 5 * 60_000).unref();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export async function googleLoopback(args) {
|
|
68
|
+
let redirectUri = "";
|
|
69
|
+
const code = await awaitCode(0, (redirect) => {
|
|
70
|
+
redirectUri = redirect;
|
|
71
|
+
const authUrl = "https://accounts.google.com/o/oauth2/v2/auth?" +
|
|
72
|
+
new URLSearchParams({
|
|
73
|
+
client_id: args.clientId,
|
|
74
|
+
redirect_uri: redirect,
|
|
75
|
+
response_type: "code",
|
|
76
|
+
scope: "https://mail.google.com/",
|
|
77
|
+
access_type: "offline",
|
|
78
|
+
prompt: "consent",
|
|
79
|
+
}).toString();
|
|
80
|
+
process.stderr.write(`\nOtwieram przegladarke. Jesli nie ruszy, otworz recznie:\n${authUrl}\n`);
|
|
81
|
+
openBrowser(authUrl);
|
|
82
|
+
});
|
|
83
|
+
const res = await fetch("https://oauth2.googleapis.com/token", {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
86
|
+
body: new URLSearchParams({
|
|
87
|
+
code,
|
|
88
|
+
client_id: args.clientId,
|
|
89
|
+
client_secret: args.clientSecret,
|
|
90
|
+
redirect_uri: redirectUri,
|
|
91
|
+
grant_type: "authorization_code",
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
const json = (await res.json());
|
|
95
|
+
if (!res.ok || !json.refresh_token) {
|
|
96
|
+
throw new Error(`wymiana kodu nieudana: ${json.error ?? res.status} ${json.error_description ?? ""}`.trim() +
|
|
97
|
+
" (jesli brak refresh_token: usun aplikacje z myaccount.google.com/permissions i sprobuj ponownie)");
|
|
98
|
+
}
|
|
99
|
+
return { refreshToken: json.refresh_token };
|
|
100
|
+
}
|
|
101
|
+
export async function microsoftLoopback(args) {
|
|
102
|
+
const port = args.port ?? 3000; // must match the redirect URI registered in Azure
|
|
103
|
+
const scope = "offline_access https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send";
|
|
104
|
+
let redirectUri = "";
|
|
105
|
+
const code = await awaitCode(port, (redirect) => {
|
|
106
|
+
redirectUri = redirect;
|
|
107
|
+
const authUrl = `https://login.microsoftonline.com/${args.tenantId}/oauth2/v2.0/authorize?` +
|
|
108
|
+
new URLSearchParams({
|
|
109
|
+
client_id: args.clientId,
|
|
110
|
+
response_type: "code",
|
|
111
|
+
redirect_uri: redirect,
|
|
112
|
+
response_mode: "query",
|
|
113
|
+
scope,
|
|
114
|
+
prompt: "consent",
|
|
115
|
+
}).toString();
|
|
116
|
+
process.stderr.write(`\nW Azure App registration -> Authentication dodaj redirect (Mobile/desktop): ${redirect}\n` +
|
|
117
|
+
`Otwieram przegladarke. Recznie:\n${authUrl}\n`);
|
|
118
|
+
openBrowser(authUrl);
|
|
119
|
+
});
|
|
120
|
+
const res = await fetch(`https://login.microsoftonline.com/${args.tenantId}/oauth2/v2.0/token`, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
123
|
+
body: new URLSearchParams({
|
|
124
|
+
code,
|
|
125
|
+
client_id: args.clientId,
|
|
126
|
+
client_secret: args.clientSecret,
|
|
127
|
+
redirect_uri: redirectUri,
|
|
128
|
+
grant_type: "authorization_code",
|
|
129
|
+
scope,
|
|
130
|
+
}),
|
|
131
|
+
});
|
|
132
|
+
const json = (await res.json());
|
|
133
|
+
if (!res.ok || !json.refresh_token) {
|
|
134
|
+
throw new Error(`wymiana kodu nieudana: ${json.error ?? res.status} ${json.error_description ?? ""}`.trim());
|
|
135
|
+
}
|
|
136
|
+
return { refreshToken: json.refresh_token };
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { loadConfig, getAccount } from "./config.js";
|
|
5
|
+
import { getUnread, getBody, searchEmails, markRead, listFolders, } from "./mail/imap.js";
|
|
6
|
+
import { sendEmail } from "./mail/smtp.js";
|
|
7
|
+
import { deliverDigest } from "./digest.js";
|
|
8
|
+
const jsonText = (obj) => ({
|
|
9
|
+
content: [{ type: "text", text: JSON.stringify(obj, null, 2) }],
|
|
10
|
+
});
|
|
11
|
+
const errText = (e) => ({
|
|
12
|
+
content: [{ type: "text", text: JSON.stringify({ error: e.message }) }],
|
|
13
|
+
isError: true,
|
|
14
|
+
});
|
|
15
|
+
export function createServer(cfg) {
|
|
16
|
+
const server = new McpServer({ name: "poczta-mcp", version: "0.1.0" }, {
|
|
17
|
+
instructions: "Narzedzia do obslugi wielu skrzynek pocztowych (IMAP/SMTP). " +
|
|
18
|
+
"Kazdy tool wymaga 'account' (id konta z list_accounts), poza list_accounts i get_unread bez argumentu (wszystkie konta). " +
|
|
19
|
+
"UID sa zalezne od konta i folderu: bierz je z get_unread/search_emails. " +
|
|
20
|
+
"Pelna tresc pobieraj tylko get_email_body, gdy jest potrzebna. " +
|
|
21
|
+
"NIGDY nie wywoluj send_email bez wyraznego potwierdzenia tresci przez uzytkownika. " +
|
|
22
|
+
"Regula mark_as_read przy codziennym przegladzie: oznaczaj tylko maile bez wymaganej akcji.",
|
|
23
|
+
});
|
|
24
|
+
server.registerTool("list_accounts", {
|
|
25
|
+
title: "Lista kont",
|
|
26
|
+
description: "Zwraca skonfigurowane konta pocztowe (id, label, email, dostawca/typ auth).",
|
|
27
|
+
inputSchema: {},
|
|
28
|
+
}, async () => jsonText({
|
|
29
|
+
accounts: cfg.accounts.map((a) => ({
|
|
30
|
+
id: a.id,
|
|
31
|
+
label: a.label ?? a.id,
|
|
32
|
+
email: a.email,
|
|
33
|
+
auth: a.auth.type === "password" ? "password" : `oauth2:${a.auth.provider}`,
|
|
34
|
+
})),
|
|
35
|
+
digestChannels: cfg.digest.channels.map((c) => c.type),
|
|
36
|
+
}));
|
|
37
|
+
server.registerTool("get_unread", {
|
|
38
|
+
title: "Nieprzeczytane maile",
|
|
39
|
+
description: "Lista nieprzeczytanych maili. Bez 'account' przeszukuje WSZYSTKIE konta. " +
|
|
40
|
+
"Domyslnie 35 najnowszych i nie starszych niz 3 dni. Zwraca uid, account, from, subject, date (ISO), preview. " +
|
|
41
|
+
"UID i account potrzebne do kolejnych operacji.",
|
|
42
|
+
inputSchema: {
|
|
43
|
+
account: z.string().optional().describe("id konta; pomin aby objac wszystkie konta"),
|
|
44
|
+
folder: z.string().default("INBOX"),
|
|
45
|
+
max_results: z.number().int().positive().max(100).default(35).describe("limit najnowszych; domyslnie 35"),
|
|
46
|
+
max_age_days: z
|
|
47
|
+
.number()
|
|
48
|
+
.int()
|
|
49
|
+
.min(0)
|
|
50
|
+
.max(365)
|
|
51
|
+
.default(3)
|
|
52
|
+
.describe("pomin maile starsze niz N dni; 0 = bez limitu wieku; domyslnie 3"),
|
|
53
|
+
},
|
|
54
|
+
}, async ({ account, folder, max_results, max_age_days }) => {
|
|
55
|
+
try {
|
|
56
|
+
const targets = account ? [getAccount(cfg, account)] : cfg.accounts;
|
|
57
|
+
const all = [];
|
|
58
|
+
const errors = [];
|
|
59
|
+
await Promise.all(targets.map(async (acc) => {
|
|
60
|
+
try {
|
|
61
|
+
all.push(...(await getUnread(acc, folder, max_results, max_age_days)));
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
errors.push({ account: acc.id, error: e.message });
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
all.sort((a, b) => (b.date > a.date ? 1 : b.date < a.date ? -1 : 0));
|
|
68
|
+
const capped = all.slice(0, max_results); // global cap across accounts
|
|
69
|
+
return jsonText({ count: capped.length, messages: capped, errors });
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
return errText(e);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
server.registerTool("get_email_body", {
|
|
76
|
+
title: "Tresc maila",
|
|
77
|
+
description: "Pelna tresc maila po account+uid. Najpierw uzyskaj uid z get_unread/search_emails.",
|
|
78
|
+
inputSchema: {
|
|
79
|
+
account: z.string(),
|
|
80
|
+
uid: z.string(),
|
|
81
|
+
folder: z.string().default("INBOX"),
|
|
82
|
+
},
|
|
83
|
+
}, async ({ account, uid, folder }) => {
|
|
84
|
+
try {
|
|
85
|
+
const acc = getAccount(cfg, account);
|
|
86
|
+
const msg = await getBody(acc, uid, folder);
|
|
87
|
+
if (!msg)
|
|
88
|
+
return jsonText({ error: `Nie znaleziono uid ${uid} w ${folder} (${account})` });
|
|
89
|
+
return jsonText(msg);
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
return errText(e);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
server.registerTool("search_emails", {
|
|
96
|
+
title: "Szukaj maili",
|
|
97
|
+
description: "Wyszukiwanie po nadawcy, temacie i/lub dacie. since w formacie YYYY-MM-DD. unread_only ogranicza do nieprzeczytanych.",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
account: z.string(),
|
|
100
|
+
from: z.string().optional(),
|
|
101
|
+
subject: z.string().optional(),
|
|
102
|
+
since: z.string().optional().describe("YYYY-MM-DD"),
|
|
103
|
+
unread_only: z.boolean().default(false),
|
|
104
|
+
folder: z.string().default("INBOX"),
|
|
105
|
+
max_results: z.number().int().positive().max(100).default(20),
|
|
106
|
+
},
|
|
107
|
+
}, async ({ account, from, subject, since, unread_only, folder, max_results }) => {
|
|
108
|
+
try {
|
|
109
|
+
const acc = getAccount(cfg, account);
|
|
110
|
+
const msgs = await searchEmails(acc, { from, subject, since, unreadOnly: unread_only }, folder, max_results);
|
|
111
|
+
return jsonText({ count: msgs.length, messages: msgs });
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
return errText(e);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
server.registerTool("mark_as_read", {
|
|
118
|
+
title: "Oznacz jako przeczytane",
|
|
119
|
+
description: "Oznacza maile (\\Seen) po account + lista uid (batch). " +
|
|
120
|
+
"Przy codziennym przegladzie oznaczaj tylko maile NIE wymagajace akcji.",
|
|
121
|
+
inputSchema: {
|
|
122
|
+
account: z.string(),
|
|
123
|
+
uids: z.array(z.string()).min(1),
|
|
124
|
+
folder: z.string().default("INBOX"),
|
|
125
|
+
},
|
|
126
|
+
}, async ({ account, uids, folder }) => {
|
|
127
|
+
try {
|
|
128
|
+
const acc = getAccount(cfg, account);
|
|
129
|
+
return jsonText(await markRead(acc, uids, folder));
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
return errText(e);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
server.registerTool("send_email", {
|
|
136
|
+
title: "Wyslij maila",
|
|
137
|
+
description: "Wysyla maila z wybranego konta. WAZNE: wywoluj dopiero po wyraznym potwierdzeniu tresci przez uzytkownika. " +
|
|
138
|
+
"reply_to_uid ustawia naglowki watku (In-Reply-To/References).",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
account: z.string(),
|
|
141
|
+
to: z.string(),
|
|
142
|
+
subject: z.string(),
|
|
143
|
+
body: z.string(),
|
|
144
|
+
reply_to_uid: z.string().optional(),
|
|
145
|
+
},
|
|
146
|
+
}, async ({ account, to, subject, body, reply_to_uid }) => {
|
|
147
|
+
try {
|
|
148
|
+
const acc = getAccount(cfg, account);
|
|
149
|
+
return jsonText(await sendEmail(acc, { to, subject, body, replyToUid: reply_to_uid }));
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
return errText(e);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
server.registerTool("deliver_digest", {
|
|
156
|
+
title: "Dostarcz podsumowanie",
|
|
157
|
+
description: "Wysyla gotowe podsumowanie (markdown) do kanalow z konfiguracji (file/email/webhook). " +
|
|
158
|
+
"Bez 'channels' uzywa kanalow domyslnych z config. Kanal 'chat' tylko zwraca tresc.",
|
|
159
|
+
inputSchema: {
|
|
160
|
+
markdown: z.string(),
|
|
161
|
+
channels: z
|
|
162
|
+
.array(z.enum(["chat", "file", "email", "webhook"]))
|
|
163
|
+
.optional()
|
|
164
|
+
.describe("ogranicz do wybranych typow kanalow; pomin = wszystkie z config"),
|
|
165
|
+
},
|
|
166
|
+
}, async ({ markdown, channels }) => {
|
|
167
|
+
try {
|
|
168
|
+
const sel = channels
|
|
169
|
+
? cfg.digest.channels.filter((c) => channels.includes(c.type))
|
|
170
|
+
: undefined;
|
|
171
|
+
const results = await deliverDigest(cfg, markdown, sel);
|
|
172
|
+
return jsonText({ delivered: results });
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
return errText(e);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
server.registerTool("get_folders", {
|
|
179
|
+
title: "Foldery IMAP",
|
|
180
|
+
description: "Lista folderow IMAP danego konta (znalezienie Spam, Wyslane itd.).",
|
|
181
|
+
inputSchema: { account: z.string() },
|
|
182
|
+
}, async ({ account }) => {
|
|
183
|
+
try {
|
|
184
|
+
const acc = getAccount(cfg, account);
|
|
185
|
+
return jsonText({ folders: await listFolders(acc) });
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
return errText(e);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return server;
|
|
192
|
+
}
|
|
193
|
+
export async function runServer() {
|
|
194
|
+
const cfg = loadConfig();
|
|
195
|
+
const server = createServer(cfg);
|
|
196
|
+
const transport = new StdioServerTransport();
|
|
197
|
+
await server.connect(transport);
|
|
198
|
+
// stderr is safe; stdout is the MCP channel.
|
|
199
|
+
process.stderr.write(`poczta-mcp running (stdio). Accounts: ${cfg.accounts.map((a) => a.id).join(", ")}\n`);
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|