@leemour/cli-messaging 0.144.0 → 0.146.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/README.md +1 -1
- package/THIRD_PARTY_NOTICES +34 -0
- package/dist/cli/config-command.d.ts +9 -1
- package/dist/cli/config-command.d.ts.map +1 -1
- package/dist/cli/config-command.js +35 -1
- package/dist/cli/config-command.js.map +1 -1
- package/dist/cli/index.d.ts +6 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/messenger/chats-command.d.ts.map +1 -1
- package/dist/cli/messenger/chats-command.js +2 -0
- package/dist/cli/messenger/chats-command.js.map +1 -1
- package/dist/cli/messenger/chats-stats-command.d.ts +4 -0
- package/dist/cli/messenger/chats-stats-command.d.ts.map +1 -0
- package/dist/cli/messenger/chats-stats-command.js +59 -0
- package/dist/cli/messenger/chats-stats-command.js.map +1 -0
- package/dist/cli/messenger/context.d.ts +3 -0
- package/dist/cli/messenger/context.d.ts.map +1 -1
- package/dist/cli/messenger/context.js +4 -0
- package/dist/cli/messenger/context.js.map +1 -1
- package/dist/cli/messenger/conversations-command.d.ts.map +1 -1
- package/dist/cli/messenger/conversations-command.js +8 -3
- package/dist/cli/messenger/conversations-command.js.map +1 -1
- package/dist/cli/messenger/mcp-command.d.ts +6 -0
- package/dist/cli/messenger/mcp-command.d.ts.map +1 -1
- package/dist/cli/messenger/mcp-command.js +49 -2
- package/dist/cli/messenger/mcp-command.js.map +1 -1
- package/dist/cli/permission-keys.d.ts +12 -0
- package/dist/cli/permission-keys.d.ts.map +1 -0
- package/dist/cli/permission-keys.js +43 -0
- package/dist/cli/permission-keys.js.map +1 -0
- package/dist/mcp/http/node.d.ts +17 -0
- package/dist/mcp/http/node.d.ts.map +1 -0
- package/dist/mcp/http/node.js +74 -0
- package/dist/mcp/http/node.js.map +1 -0
- package/dist/mcp/http/oauth.d.ts +25 -0
- package/dist/mcp/http/oauth.d.ts.map +1 -0
- package/dist/mcp/http/oauth.js +264 -0
- package/dist/mcp/http/oauth.js.map +1 -0
- package/dist/mcp/http/serve.d.ts +21 -0
- package/dist/mcp/http/serve.d.ts.map +1 -0
- package/dist/mcp/http/serve.js +119 -0
- package/dist/mcp/http/serve.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +37 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/chats.d.ts.map +1 -1
- package/dist/mcp/tools/chats.js +21 -1
- package/dist/mcp/tools/chats.js.map +1 -1
- package/dist/mcp/tools/conversations.d.ts.map +1 -1
- package/dist/mcp/tools/conversations.js +7 -2
- package/dist/mcp/tools/conversations.js.map +1 -1
- package/dist/search/snowball/LICENSE +29 -0
- package/dist/search/snowball/base-stemmer.js +445 -0
- package/dist/search/snowball/english-stemmer.js +775 -0
- package/dist/search/snowball/russian-stemmer.js +468 -0
- package/dist/search/snowball/spanish-stemmer.js +722 -0
- package/dist/search/stem.d.ts +35 -0
- package/dist/search/stem.d.ts.map +1 -0
- package/dist/search/stem.js +76 -0
- package/dist/search/stem.js.map +1 -0
- package/dist/sends/index.d.ts +1 -1
- package/dist/sends/index.d.ts.map +1 -1
- package/dist/sends/index.js +1 -1
- package/dist/sends/index.js.map +1 -1
- package/dist/sends/permissions.d.ts +2 -0
- package/dist/sends/permissions.d.ts.map +1 -1
- package/dist/sends/permissions.js +40 -0
- package/dist/sends/permissions.js.map +1 -1
- package/dist/services/chat-stats.d.ts +70 -0
- package/dist/services/chat-stats.d.ts.map +1 -0
- package/dist/services/chat-stats.js +125 -0
- package/dist/services/chat-stats.js.map +1 -0
- package/dist/services/chats.d.ts +10 -0
- package/dist/services/chats.d.ts.map +1 -1
- package/dist/services/chats.js +44 -0
- package/dist/services/chats.js.map +1 -1
- package/dist/services/embeddings.d.ts +5 -1
- package/dist/services/embeddings.d.ts.map +1 -1
- package/dist/services/embeddings.js +4 -1
- package/dist/services/embeddings.js.map +1 -1
- package/dist/services/inbox.d.ts +7 -0
- package/dist/services/inbox.d.ts.map +1 -1
- package/dist/services/inbox.js +14 -8
- package/dist/services/inbox.js.map +1 -1
- package/dist/services/messages-search.d.ts +1 -0
- package/dist/services/messages-search.d.ts.map +1 -1
- package/dist/services/messages-search.js +1 -1
- package/dist/services/messages-search.js.map +1 -1
- package/package.json +2 -2
- package/parity.json +65 -1
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomInt, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { OAuthError, OAuthErrorCode, } from "@modelcontextprotocol/server";
|
|
5
|
+
const ACCESS_SECONDS = 60 * 60;
|
|
6
|
+
const REFRESH_SECONDS = 30 * 24 * 60 * 60;
|
|
7
|
+
const AUTH_CODE_MS = 60 * 1000;
|
|
8
|
+
const LOGIN_CODE_MS = 10 * 60 * 1000;
|
|
9
|
+
const WRONG_TRIES = 5;
|
|
10
|
+
const MAX_CLIENTS = 10;
|
|
11
|
+
const CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
12
|
+
const hash = (value) => createHash("sha256").update(value).digest("base64url");
|
|
13
|
+
const secret = () => randomBytes(32).toString("base64url");
|
|
14
|
+
const same = (given, expected) => given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
|
|
15
|
+
/** Only hashes reach the disk: the file is worth nothing to someone who copies it. */
|
|
16
|
+
const tokenFile = (path) => ({
|
|
17
|
+
read: () => existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : { clients: [], tokens: [] },
|
|
18
|
+
write: (stored) => {
|
|
19
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
20
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
21
|
+
writeFileSync(temporary, JSON.stringify(stored), { mode: 0o600 });
|
|
22
|
+
chmodSync(temporary, 0o600);
|
|
23
|
+
renameSync(temporary, path);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
export const revokeAll = (path) => rmSync(path, { force: true });
|
|
27
|
+
const json = (body, status = 200) => new Response(JSON.stringify(body), {
|
|
28
|
+
status,
|
|
29
|
+
headers: { "content-type": "application/json", "cache-control": "no-store" },
|
|
30
|
+
});
|
|
31
|
+
const oauthError = (error, description, status = 400) => json({ error, error_description: description }, status);
|
|
32
|
+
const escapeHtml = (value) => value.replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`);
|
|
33
|
+
const redirectAllowed = (uri) => {
|
|
34
|
+
try {
|
|
35
|
+
const url = new URL(uri);
|
|
36
|
+
if (url.hash)
|
|
37
|
+
return false;
|
|
38
|
+
return url.protocol === "https:" || (url.protocol === "http:" && ["localhost", "127.0.0.1"].includes(url.hostname));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* An OAuth 2.1 authorization server for exactly one owner (CLI-58). Anyone may register a client —
|
|
46
|
+
* the browser apps need dynamic registration — but nobody gets a token without the one-time code
|
|
47
|
+
* printed in the owner's terminal. Five wrong codes lock the page until the server restarts.
|
|
48
|
+
*/
|
|
49
|
+
export const ownerLogin = ({ issuer, resource, file, appName, onCode, now = () => Date.now(), }) => {
|
|
50
|
+
const store = tokenFile(file);
|
|
51
|
+
const codes = new Map();
|
|
52
|
+
let login = { value: "", expires: 0 };
|
|
53
|
+
let wrong = 0;
|
|
54
|
+
const freshCode = () => {
|
|
55
|
+
const part = () => Array.from({ length: 4 }, () => CODE_ALPHABET[randomInt(CODE_ALPHABET.length)]).join("");
|
|
56
|
+
login = { value: `${part()}-${part()}`, expires: now() + LOGIN_CODE_MS };
|
|
57
|
+
onCode(login.value, new Date(login.expires));
|
|
58
|
+
};
|
|
59
|
+
freshCode();
|
|
60
|
+
const endpoint = (path) => new URL(path, issuer).href;
|
|
61
|
+
const metadata = {
|
|
62
|
+
issuer: issuer.href,
|
|
63
|
+
authorization_endpoint: endpoint("/authorize"),
|
|
64
|
+
token_endpoint: endpoint("/token"),
|
|
65
|
+
registration_endpoint: endpoint("/register"),
|
|
66
|
+
response_types_supported: ["code"],
|
|
67
|
+
grant_types_supported: ["authorization_code", "refresh_token"],
|
|
68
|
+
code_challenge_methods_supported: ["S256"],
|
|
69
|
+
token_endpoint_auth_methods_supported: ["none", "client_secret_post", "client_secret_basic"],
|
|
70
|
+
};
|
|
71
|
+
const issue = (stored, clientId) => {
|
|
72
|
+
const access = secret();
|
|
73
|
+
const refresh = secret();
|
|
74
|
+
const seconds = Math.floor(now() / 1000);
|
|
75
|
+
stored.tokens = stored.tokens.filter((one) => one.expiresAt > seconds);
|
|
76
|
+
stored.tokens.push({ hash: hash(access), kind: "access", clientId, expiresAt: seconds + ACCESS_SECONDS }, { hash: hash(refresh), kind: "refresh", clientId, expiresAt: seconds + REFRESH_SECONDS });
|
|
77
|
+
store.write(stored);
|
|
78
|
+
return json({ access_token: access, token_type: "Bearer", expires_in: ACCESS_SECONDS, refresh_token: refresh });
|
|
79
|
+
};
|
|
80
|
+
const clientOf = (stored, request, form) => {
|
|
81
|
+
let id = form.get("client_id") ?? "";
|
|
82
|
+
let given = form.get("client_secret") ?? undefined;
|
|
83
|
+
const basic = request.headers.get("authorization");
|
|
84
|
+
if (basic?.startsWith("Basic ")) {
|
|
85
|
+
const [user = "", password = ""] = Buffer.from(basic.slice(6), "base64").toString().split(":");
|
|
86
|
+
id = decodeURIComponent(user);
|
|
87
|
+
given = decodeURIComponent(password);
|
|
88
|
+
}
|
|
89
|
+
const client = stored.clients.find((one) => one.id === id);
|
|
90
|
+
if (!client)
|
|
91
|
+
return undefined;
|
|
92
|
+
if (client.authMethod === "none")
|
|
93
|
+
return client;
|
|
94
|
+
return given !== undefined && client.secretHash && same(hash(given), client.secretHash) ? client : undefined;
|
|
95
|
+
};
|
|
96
|
+
const register = async (request) => {
|
|
97
|
+
const body = (await request.json().catch(() => null));
|
|
98
|
+
const uris = Array.isArray(body?.redirect_uris) ? body.redirect_uris.filter((one) => typeof one === "string") : [];
|
|
99
|
+
if (uris.length === 0 || !uris.every(redirectAllowed))
|
|
100
|
+
return oauthError("invalid_redirect_uri", "redirect_uris must be https URLs");
|
|
101
|
+
const requested = body?.token_endpoint_auth_method;
|
|
102
|
+
const authMethod = requested === "client_secret_post" || requested === "client_secret_basic" ? requested : "none";
|
|
103
|
+
const clientSecret = authMethod === "none" ? undefined : secret();
|
|
104
|
+
const name = typeof body?.client_name === "string" ? body.client_name.slice(0, 100) : undefined;
|
|
105
|
+
const client = {
|
|
106
|
+
id: secret(),
|
|
107
|
+
redirectUris: uris,
|
|
108
|
+
authMethod,
|
|
109
|
+
issuedAt: Math.floor(now() / 1000),
|
|
110
|
+
...(name ? { name } : {}),
|
|
111
|
+
...(clientSecret ? { secretHash: hash(clientSecret) } : {}),
|
|
112
|
+
};
|
|
113
|
+
const stored = store.read();
|
|
114
|
+
// Registration is open, so only clients that never got a token make room: a stranger's ten
|
|
115
|
+
// registrations push out each other, never the owner's app.
|
|
116
|
+
const seconds = Math.floor(now() / 1000);
|
|
117
|
+
const holding = new Set(stored.tokens.filter((one) => one.expiresAt > seconds).map((one) => one.clientId));
|
|
118
|
+
stored.clients.push(client);
|
|
119
|
+
while (stored.clients.length > MAX_CLIENTS) {
|
|
120
|
+
const idle = stored.clients.findIndex((one) => !holding.has(one.id));
|
|
121
|
+
if (idle === -1)
|
|
122
|
+
return oauthError("invalid_client_metadata", "too many logged-in apps — run mcp --revoke first");
|
|
123
|
+
stored.clients.splice(idle, 1);
|
|
124
|
+
}
|
|
125
|
+
store.write(stored);
|
|
126
|
+
return json({
|
|
127
|
+
client_id: client.id,
|
|
128
|
+
client_id_issued_at: client.issuedAt,
|
|
129
|
+
redirect_uris: uris,
|
|
130
|
+
token_endpoint_auth_method: authMethod,
|
|
131
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
132
|
+
response_types: ["code"],
|
|
133
|
+
...(name ? { client_name: name } : {}),
|
|
134
|
+
...(clientSecret ? { client_secret: clientSecret, client_secret_expires_at: 0 } : {}),
|
|
135
|
+
}, 201);
|
|
136
|
+
};
|
|
137
|
+
const page = (params, client, message) => {
|
|
138
|
+
const hidden = ["response_type", "client_id", "redirect_uri", "code_challenge", "code_challenge_method", "state"]
|
|
139
|
+
.map((name) => `<input type="hidden" name="${name}" value="${escapeHtml(params.get(name) ?? "")}">`)
|
|
140
|
+
.join("");
|
|
141
|
+
const who = escapeHtml(client.name ?? "an application");
|
|
142
|
+
const target = new URL(params.get("redirect_uri") ?? "");
|
|
143
|
+
const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${escapeHtml(appName)} login</title><style>body{font:16px system-ui,sans-serif;max-width:28rem;margin:3rem auto;padding:0 1rem;color:#1d2430}input[type=text]{font:20px ui-monospace,monospace;letter-spacing:.1em;width:100%;padding:.5rem;margin:.5rem 0 1rem;box-sizing:border-box}button{font:inherit;padding:.5rem 1rem}.error{color:#b42318}</style></head><body><h1>${escapeHtml(appName)}</h1><p>An app that calls itself <strong>${who}</strong> asks to reach your messages through <code>${escapeHtml(appName)} mcp --http</code>.</p><p>After you allow it, the login goes to <strong>${escapeHtml(target.host)}</strong>. Allow only if that is the app you are connecting, such as chatgpt.com or claude.ai.</p><p>Type the code shown in the terminal where it runs. If you did not start this login, close this page.</p>${message ? `<p class="error">${escapeHtml(message)}</p>` : ""}<form method="post" action="/authorize">${hidden}<label>Code from the terminal<input type="text" name="login_code" autocomplete="off" autofocus required></label><button type="submit">Allow</button></form></body></html>`;
|
|
144
|
+
return new Response(html, {
|
|
145
|
+
status: message ? 400 : 200,
|
|
146
|
+
headers: {
|
|
147
|
+
"content-type": "text/html; charset=utf-8",
|
|
148
|
+
"cache-control": "no-store",
|
|
149
|
+
"x-frame-options": "DENY",
|
|
150
|
+
"content-security-policy": `default-src 'none'; style-src 'unsafe-inline'; form-action 'self' ${target.origin}; frame-ancestors 'none'`,
|
|
151
|
+
"referrer-policy": "no-referrer",
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
const authorize = async (request) => {
|
|
156
|
+
const params = request.method === "POST" ? new URLSearchParams(await request.text()) : new URL(request.url).searchParams;
|
|
157
|
+
const stored = store.read();
|
|
158
|
+
const client = stored.clients.find((one) => one.id === params.get("client_id"));
|
|
159
|
+
const redirectUri = params.get("redirect_uri") ?? "";
|
|
160
|
+
// Never redirect to an address the client did not register: that would hand a code to anyone.
|
|
161
|
+
if (!client?.redirectUris.includes(redirectUri))
|
|
162
|
+
return new Response("Unknown client or redirect address.", { status: 400 });
|
|
163
|
+
if (params.get("response_type") !== "code" ||
|
|
164
|
+
params.get("code_challenge_method") !== "S256" ||
|
|
165
|
+
!params.get("code_challenge"))
|
|
166
|
+
return new Response("This server needs response_type=code and PKCE with S256.", { status: 400 });
|
|
167
|
+
if (wrong >= WRONG_TRIES)
|
|
168
|
+
return new Response("Too many wrong codes. Restart the server to log in again.", { status: 429 });
|
|
169
|
+
if (request.method !== "POST")
|
|
170
|
+
return page(params, client);
|
|
171
|
+
const typed = (params.get("login_code") ?? "").trim().toUpperCase();
|
|
172
|
+
if (login.expires < now()) {
|
|
173
|
+
freshCode();
|
|
174
|
+
return page(params, client, "The code expired. A new one is shown in the terminal.");
|
|
175
|
+
}
|
|
176
|
+
if (!same(typed, login.value)) {
|
|
177
|
+
wrong += 1;
|
|
178
|
+
return wrong >= WRONG_TRIES
|
|
179
|
+
? new Response("Too many wrong codes. Restart the server to log in again.", { status: 429 })
|
|
180
|
+
: page(params, client, `Wrong code. ${WRONG_TRIES - wrong} tries left.`);
|
|
181
|
+
}
|
|
182
|
+
freshCode();
|
|
183
|
+
const code = secret();
|
|
184
|
+
codes.set(hash(code), {
|
|
185
|
+
clientId: client.id,
|
|
186
|
+
redirectUri,
|
|
187
|
+
challenge: params.get("code_challenge") ?? "",
|
|
188
|
+
expires: now() + AUTH_CODE_MS,
|
|
189
|
+
});
|
|
190
|
+
const target = new URL(redirectUri);
|
|
191
|
+
target.searchParams.set("code", code);
|
|
192
|
+
const state = params.get("state");
|
|
193
|
+
if (state)
|
|
194
|
+
target.searchParams.set("state", state);
|
|
195
|
+
target.searchParams.set("iss", issuer.href);
|
|
196
|
+
return new Response(null, { status: 302, headers: { location: target.href, "cache-control": "no-store" } });
|
|
197
|
+
};
|
|
198
|
+
const token = async (request) => {
|
|
199
|
+
const form = new URLSearchParams(await request.text());
|
|
200
|
+
const stored = store.read();
|
|
201
|
+
const client = clientOf(stored, request, form);
|
|
202
|
+
if (!client)
|
|
203
|
+
return oauthError("invalid_client", "unknown client or wrong secret", 401);
|
|
204
|
+
const requestedResource = form.get("resource");
|
|
205
|
+
if (requestedResource && requestedResource !== resource.href)
|
|
206
|
+
return oauthError("invalid_target", "this server issues tokens only for its own MCP endpoint");
|
|
207
|
+
if (form.get("grant_type") === "authorization_code") {
|
|
208
|
+
const key = hash(form.get("code") ?? "");
|
|
209
|
+
const entry = codes.get(key);
|
|
210
|
+
codes.delete(key);
|
|
211
|
+
const verifier = form.get("code_verifier") ?? "";
|
|
212
|
+
const challenge = createHash("sha256").update(verifier).digest("base64url");
|
|
213
|
+
if (!entry ||
|
|
214
|
+
entry.expires < now() ||
|
|
215
|
+
entry.clientId !== client.id ||
|
|
216
|
+
entry.redirectUri !== form.get("redirect_uri") ||
|
|
217
|
+
!same(challenge, entry.challenge))
|
|
218
|
+
return oauthError("invalid_grant", "the code is wrong, used or expired");
|
|
219
|
+
return issue(stored, client.id);
|
|
220
|
+
}
|
|
221
|
+
if (form.get("grant_type") === "refresh_token") {
|
|
222
|
+
const key = hash(form.get("refresh_token") ?? "");
|
|
223
|
+
const seconds = Math.floor(now() / 1000);
|
|
224
|
+
const found = stored.tokens.find((one) => one.kind === "refresh" && one.hash === key);
|
|
225
|
+
if (!found || found.clientId !== client.id || found.expiresAt <= seconds)
|
|
226
|
+
return oauthError("invalid_grant", "the refresh token is wrong, used or expired");
|
|
227
|
+
// Rotation: a refresh token works once, so a copied one dies the moment either side uses it.
|
|
228
|
+
stored.tokens = stored.tokens.filter((one) => one !== found);
|
|
229
|
+
return issue(stored, client.id);
|
|
230
|
+
}
|
|
231
|
+
return oauthError("unsupported_grant_type", "use authorization_code or refresh_token");
|
|
232
|
+
};
|
|
233
|
+
const verifier = {
|
|
234
|
+
verifyAccessToken: async (presented) => {
|
|
235
|
+
const seconds = Math.floor(now() / 1000);
|
|
236
|
+
const found = store.read().tokens.find((one) => one.kind === "access" && one.hash === hash(presented));
|
|
237
|
+
if (!found || found.expiresAt <= seconds)
|
|
238
|
+
throw new OAuthError(OAuthErrorCode.InvalidToken, "the token is unknown or expired");
|
|
239
|
+
return {
|
|
240
|
+
token: presented,
|
|
241
|
+
clientId: found.clientId,
|
|
242
|
+
scopes: [],
|
|
243
|
+
expiresAt: found.expiresAt,
|
|
244
|
+
resource,
|
|
245
|
+
};
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
return {
|
|
249
|
+
code: () => login.value,
|
|
250
|
+
metadata,
|
|
251
|
+
verifier,
|
|
252
|
+
handle: async (request) => {
|
|
253
|
+
const path = new URL(request.url).pathname;
|
|
254
|
+
if (path === "/register" && request.method === "POST")
|
|
255
|
+
return register(request);
|
|
256
|
+
if (path === "/authorize" && (request.method === "GET" || request.method === "POST"))
|
|
257
|
+
return authorize(request);
|
|
258
|
+
if (path === "/token" && request.method === "POST")
|
|
259
|
+
return token(request);
|
|
260
|
+
return undefined;
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/mcp/http/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type McpServer } from "@modelcontextprotocol/server";
|
|
2
|
+
import { type Listening } from "./node.js";
|
|
3
|
+
export declare const MCP_PATH = "/mcp";
|
|
4
|
+
export interface HttpOptions {
|
|
5
|
+
/** The tunnel's address, as the browser apps reach it — `https://name.ts.net`. */
|
|
6
|
+
publicUrl: URL;
|
|
7
|
+
port: number;
|
|
8
|
+
/** Where the hashes of issued tokens and registered clients are kept. */
|
|
9
|
+
tokenFile: string;
|
|
10
|
+
appName: string;
|
|
11
|
+
onCode: (code: string, expires: Date) => void;
|
|
12
|
+
onError?: (error: Error) => void;
|
|
13
|
+
now?: () => number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* MCP over Streamable HTTP on 127.0.0.1, behind the owner's tunnel (CLI-58). Every MCP request needs
|
|
17
|
+
* a token from the owner login; the Host header must be the tunnel's or this machine's, so a page in
|
|
18
|
+
* the owner's browser cannot reach the port through a rebound DNS name.
|
|
19
|
+
*/
|
|
20
|
+
export declare const serveOverHttp: (build: () => McpServer, options: HttpOptions) => Promise<Listening>;
|
|
21
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/serve.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,SAAS,EAIf,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,KAAK,SAAS,EAAU,MAAM,WAAW,CAAA;AAGlD,eAAO,MAAM,QAAQ,SAAS,CAAA;AA+D9B,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,SAAS,EAAE,GAAG,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAAA;IAC7C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,UAAiB,MAAM,SAAS,WAAW,WAAW,KAAG,OAAO,CAAC,SAAS,CAmDnG,CAAA"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createMcpHandler, getOAuthProtectedResourceMetadataUrl, hostHeaderValidationResponse, isLegacyRequest, oauthMetadataResponse, requireBearerAuth, WebStandardStreamableHTTPServerTransport, } from "@modelcontextprotocol/server";
|
|
3
|
+
import { listen } from "./node.js";
|
|
4
|
+
import { ownerLogin } from "./oauth.js";
|
|
5
|
+
export const MCP_PATH = "/mcp";
|
|
6
|
+
const LOCAL = ["localhost", "127.0.0.1"];
|
|
7
|
+
const MAX_SESSIONS = 20;
|
|
8
|
+
const MAX_LOGIN_BODY = 64 * 1024;
|
|
9
|
+
const SESSION_IDLE_MS = 60 * 60 * 1000;
|
|
10
|
+
const sessionMissing = () => new Response(JSON.stringify({ jsonrpc: "2.0", error: { code: -32001, message: "Session not found" }, id: null }), {
|
|
11
|
+
status: 404,
|
|
12
|
+
headers: { "content-type": "application/json" },
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* 2025-era clients — the browser apps today — say once, in `initialize`, that they can show a form.
|
|
16
|
+
* A stateless server forgets that by the next request and refuses every confirmation, so these
|
|
17
|
+
* clients get a session: one server per session, bound to the OAuth client that opened it.
|
|
18
|
+
*/
|
|
19
|
+
const legacySessions = (build, now) => {
|
|
20
|
+
const sessions = new Map();
|
|
21
|
+
const drop = async (id) => {
|
|
22
|
+
const one = sessions.get(id);
|
|
23
|
+
sessions.delete(id);
|
|
24
|
+
await one?.close();
|
|
25
|
+
};
|
|
26
|
+
const handle = async (request, auth) => {
|
|
27
|
+
for (const [id, one] of sessions)
|
|
28
|
+
if (now() - one.seen > SESSION_IDLE_MS)
|
|
29
|
+
await drop(id);
|
|
30
|
+
const id = request.headers.get("mcp-session-id");
|
|
31
|
+
if (id) {
|
|
32
|
+
const known = sessions.get(id);
|
|
33
|
+
if (!known || known.clientId !== auth.clientId)
|
|
34
|
+
return sessionMissing();
|
|
35
|
+
known.seen = now();
|
|
36
|
+
return known.transport.handleRequest(request, { authInfo: auth });
|
|
37
|
+
}
|
|
38
|
+
const server = build();
|
|
39
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
40
|
+
sessionIdGenerator: () => randomUUID(),
|
|
41
|
+
onsessionclosed: (closed) => void sessions.delete(closed),
|
|
42
|
+
});
|
|
43
|
+
await server.connect(transport);
|
|
44
|
+
const response = await transport.handleRequest(request, { authInfo: auth });
|
|
45
|
+
if (!transport.sessionId) {
|
|
46
|
+
await server.close();
|
|
47
|
+
return response;
|
|
48
|
+
}
|
|
49
|
+
sessions.set(transport.sessionId, { transport, close: () => server.close(), clientId: auth.clientId, seen: now() });
|
|
50
|
+
while (sessions.size > MAX_SESSIONS)
|
|
51
|
+
await drop(sessions.keys().next().value);
|
|
52
|
+
return response;
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
handle,
|
|
56
|
+
close: async () => {
|
|
57
|
+
for (const id of [...sessions.keys()])
|
|
58
|
+
await drop(id);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* MCP over Streamable HTTP on 127.0.0.1, behind the owner's tunnel (CLI-58). Every MCP request needs
|
|
64
|
+
* a token from the owner login; the Host header must be the tunnel's or this machine's, so a page in
|
|
65
|
+
* the owner's browser cannot reach the port through a rebound DNS name.
|
|
66
|
+
*/
|
|
67
|
+
export const serveOverHttp = async (build, options) => {
|
|
68
|
+
const { publicUrl, port, tokenFile, appName, onCode, onError, now } = options;
|
|
69
|
+
const issuer = new URL(publicUrl.origin);
|
|
70
|
+
const resource = new URL(MCP_PATH, issuer);
|
|
71
|
+
const login = ownerLogin({ issuer, resource, file: tokenFile, appName, onCode, ...(now ? { now } : {}) });
|
|
72
|
+
const insecure = issuer.protocol === "http:" && LOCAL.includes(issuer.hostname);
|
|
73
|
+
const mcp = createMcpHandler(build, { legacy: "reject", ...(onError ? { onerror: onError } : {}) });
|
|
74
|
+
const legacy = legacySessions(build, now ?? Date.now);
|
|
75
|
+
const bearer = requireBearerAuth({
|
|
76
|
+
verifier: login.verifier,
|
|
77
|
+
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(resource),
|
|
78
|
+
});
|
|
79
|
+
const allowedHosts = [...new Set([publicUrl.hostname, ...LOCAL])];
|
|
80
|
+
const allowedOrigins = [publicUrl.origin];
|
|
81
|
+
const listening = await listen(async (request) => {
|
|
82
|
+
const refused = hostHeaderValidationResponse(request, allowedHosts);
|
|
83
|
+
if (refused)
|
|
84
|
+
return refused;
|
|
85
|
+
const discovery = oauthMetadataResponse(request, {
|
|
86
|
+
oauthMetadata: login.metadata,
|
|
87
|
+
resourceServerUrl: resource,
|
|
88
|
+
resourceName: appName,
|
|
89
|
+
...(insecure ? { dangerouslyAllowInsecureIssuerUrl: true } : {}),
|
|
90
|
+
});
|
|
91
|
+
if (discovery)
|
|
92
|
+
return discovery;
|
|
93
|
+
if (Number(request.headers.get("content-length") ?? 0) > MAX_LOGIN_BODY &&
|
|
94
|
+
new URL(request.url).pathname !== MCP_PATH)
|
|
95
|
+
return new Response("Request too large", { status: 413 });
|
|
96
|
+
const origin = request.headers.get("origin");
|
|
97
|
+
// The apps call from their servers, with no Origin; a page in some browser tab carries its own.
|
|
98
|
+
if (origin && !allowedOrigins.includes(origin))
|
|
99
|
+
return new Response("Origin not allowed", { status: 403 });
|
|
100
|
+
const answered = await login.handle(request);
|
|
101
|
+
if (answered)
|
|
102
|
+
return answered;
|
|
103
|
+
if (new URL(request.url).pathname !== MCP_PATH)
|
|
104
|
+
return new Response("Not found", { status: 404 });
|
|
105
|
+
const auth = await bearer(request);
|
|
106
|
+
if (auth instanceof Response)
|
|
107
|
+
return auth;
|
|
108
|
+
return (await isLegacyRequest(request)) ? legacy.handle(request, auth) : mcp.fetch(request, { authInfo: auth });
|
|
109
|
+
}, { host: "127.0.0.1", port });
|
|
110
|
+
return {
|
|
111
|
+
url: listening.url,
|
|
112
|
+
close: async () => {
|
|
113
|
+
await listening.close();
|
|
114
|
+
await legacy.close();
|
|
115
|
+
await mcp.close();
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/mcp/http/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAEL,gBAAgB,EAChB,oCAAoC,EACpC,4BAA4B,EAC5B,eAAe,EAEf,qBAAqB,EACrB,iBAAiB,EACjB,wCAAwC,GACzC,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAkB,MAAM,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;AACxC,MAAM,YAAY,GAAG,EAAE,CAAA;AACvB,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAA;AAChC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAStC,MAAM,cAAc,GAAG,GAAG,EAAE,CAC1B,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;IAChH,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;CAChD,CAAC,CAAA;AAEJ;;;;GAIG;AACH,MAAM,cAAc,GAAG,CAAC,KAAsB,EAAE,GAAiB,EAAE,EAAE;IACnE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IACjD,MAAM,IAAI,GAAG,KAAK,EAAE,EAAU,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACnB,MAAM,GAAG,EAAE,KAAK,EAAE,CAAA;IACpB,CAAC,CAAA;IACD,MAAM,MAAM,GAAG,KAAK,EAAE,OAAgB,EAAE,IAAc,EAAqB,EAAE;QAC3E,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,QAAQ;YAAE,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,GAAG,eAAe;gBAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAA;QACxF,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAChD,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,EAAE,CAAA;YACvE,KAAK,CAAC,IAAI,GAAG,GAAG,EAAE,CAAA;YAClB,OAAO,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAA;QACtB,MAAM,SAAS,GAAG,IAAI,wCAAwC,CAAC;YAC7D,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;YACtC,eAAe,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;SAC1D,CAAC,CAAA;QACF,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAC/B,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3E,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;YACzB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACpB,OAAO,QAAQ,CAAA;QACjB,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;QACnH,OAAO,QAAQ,CAAC,IAAI,GAAG,YAAY;YAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAe,CAAC,CAAA;QACvF,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAA;IACD,OAAO;QACL,MAAM;QACN,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAA;QACvD,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAcD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,KAAsB,EAAE,OAAoB,EAAsB,EAAE;IACtG,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;IAC7E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IACzG,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC/E,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IACnG,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,mBAAmB,EAAE,oCAAoC,CAAC,QAAQ,CAAC;KACpE,CAAC,CAAA;IACF,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACjE,MAAM,cAAc,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAEzC,MAAM,SAAS,GAAG,MAAM,MAAM,CAC5B,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,MAAM,OAAO,GAAG,4BAA4B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;QACnE,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;QAC3B,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE;YAC/C,aAAa,EAAE,KAAK,CAAC,QAAQ;YAC7B,iBAAiB,EAAE,QAAQ;YAC3B,YAAY,EAAE,OAAO;YACrB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,iCAAiC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC,CAAA;QACF,IAAI,SAAS;YAAE,OAAO,SAAS,CAAA;QAC/B,IACE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,cAAc;YACnE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAE1C,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC5C,gGAAgG;QAChG,IAAI,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,QAAQ,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC1G,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC5C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAC7B,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QACjG,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAA;QAClC,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAA;QACzC,OAAO,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACjH,CAAC,EACD,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAC5B,CAAA;IACD,OAAO;QACL,GAAG,EAAE,SAAS,CAAC,GAAG;QAClB,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAA;YACvB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACpB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
import { type Messenger, type MessengerContext } from "../cli/messenger/context.js";
|
|
3
|
+
import type { HttpOptions } from "./http/serve.js";
|
|
3
4
|
import { MessengerSession, type SessionOptions } from "./session.js";
|
|
4
5
|
export interface ServerOptions extends SessionOptions {
|
|
5
6
|
/** Every write through the form, whatever its level. */
|
|
@@ -26,5 +27,17 @@ export declare const createServer: (command: Invocation, context: MessengerConte
|
|
|
26
27
|
* the only other thing that could hold it open.
|
|
27
28
|
*/
|
|
28
29
|
export declare const serveOverStdio: (command: Invocation, context: MessengerContext, messenger: Messenger, options: ServerOptions) => Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Over HTTP every write goes through the form whatever its level (NEED-593): an app's model talked into
|
|
32
|
+
* sending by a message it read still has to get the owner's yes. It does not stop someone holding a
|
|
33
|
+
* stolen token, whose own client answers the form — short-lived tokens, rotation and `--revoke` do.
|
|
34
|
+
*/
|
|
35
|
+
export declare const OVER_HTTP: {
|
|
36
|
+
readonly confirmSend: true;
|
|
37
|
+
readonly yes: false;
|
|
38
|
+
readonly allowDangerous: false;
|
|
39
|
+
};
|
|
40
|
+
/** The same server over HTTP, until Ctrl-C (CLI-58). */
|
|
41
|
+
export declare const serveOverHttpUntilStopped: (command: Invocation, context: MessengerContext, messenger: Messenger, options: ServerOptions, http: Omit<HttpOptions, "onCode" | "onError" | "appName">) => Promise<void>;
|
|
29
42
|
export {};
|
|
30
43
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAMxD,OAAO,EAAa,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAK9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAKlD,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAGpE,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,+BAA+B;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,YACd,UAAU,WACV,gBAAgB,aACd,SAAS,2DAC6D,aAAa;;;iBAmC5E,SAAS;CAmE5B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,YAChB,UAAU,WACV,gBAAgB,aACd,SAAS,WACX,aAAa,KACrB,OAAO,CAAC,IAAI,CAiBd,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS;aAAK,WAAW;aAAQ,GAAG;aAAS,cAAc;CAAkB,CAAA;AAE1F,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,YAC3B,UAAU,WACV,gBAAgB,aACd,SAAS,WACX,aAAa,QAChB,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC,KACxD,OAAO,CAAC,IAAI,CAkCd,CAAA"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CliError } from "@leemour/cli-core";
|
|
1
2
|
import { skillResource } from "@leemour/cli-core/skill";
|
|
2
3
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
3
4
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
@@ -133,4 +134,40 @@ export const serveOverStdio = async (command, context, messenger, options) => {
|
|
|
133
134
|
await embedders.close();
|
|
134
135
|
}
|
|
135
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* Over HTTP every write goes through the form whatever its level (NEED-593): an app's model talked into
|
|
139
|
+
* sending by a message it read still has to get the owner's yes. It does not stop someone holding a
|
|
140
|
+
* stolen token, whose own client answers the form — short-lived tokens, rotation and `--revoke` do.
|
|
141
|
+
*/
|
|
142
|
+
export const OVER_HTTP = { confirmSend: true, yes: false, allowDangerous: false };
|
|
143
|
+
/** The same server over HTTP, until Ctrl-C (CLI-58). */
|
|
144
|
+
export const serveOverHttpUntilStopped = async (command, context, messenger, options, http) => {
|
|
145
|
+
const { session, embedders, build } = createServer(command, context, messenger, { ...options, ...OVER_HTTP });
|
|
146
|
+
const { serveOverHttp } = await import("./http/serve.js");
|
|
147
|
+
const appName = messenger.app.command;
|
|
148
|
+
const listening = await serveOverHttp(build, {
|
|
149
|
+
...http,
|
|
150
|
+
appName,
|
|
151
|
+
onCode: (code, expires) => context.renderer.note(`login code for a new browser app: ${code} (until ${expires.toTimeString().slice(0, 5)}; a new one after each login)`),
|
|
152
|
+
onError: (error) => context.renderer.note(`mcp: ${error.message}`),
|
|
153
|
+
}).catch(async (error) => {
|
|
154
|
+
await session.close();
|
|
155
|
+
await embedders.close();
|
|
156
|
+
if (error.code === "EADDRINUSE")
|
|
157
|
+
throw new CliError("configuration_error", `port ${http.port} is in use — pass another with --port`);
|
|
158
|
+
throw error;
|
|
159
|
+
});
|
|
160
|
+
context.renderer.note(`serving on ${listening.url.href} — point your tunnel at it; connectors use ${new URL("/mcp", http.publicUrl).href}`);
|
|
161
|
+
await new Promise((resolve) => {
|
|
162
|
+
process.once("SIGINT", resolve);
|
|
163
|
+
process.once("SIGTERM", resolve);
|
|
164
|
+
});
|
|
165
|
+
try {
|
|
166
|
+
await listening.close();
|
|
167
|
+
await session.close();
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
await embedders.close();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
136
173
|
//# sourceMappingURL=server.js.map
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAyC,MAAM,6BAA6B,CAAA;AAC9F,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/chats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAO/D,OAAO,EAAE,KAAK,OAAO,EAAqD,MAAM,YAAY,CAAA;AAE5F,eAAO,MAAM,UAAU,cAAe,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/chats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAO/D,OAAO,EAAE,KAAK,OAAO,EAAqD,MAAM,YAAY,CAAA;AAE5F,eAAO,MAAM,UAAU,cAAe,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAuGvE,CAAA"}
|
package/dist/mcp/tools/chats.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
2
|
import { listed } from "../../cli/paging.js";
|
|
3
3
|
import { checkedFilter } from "../../services/chats.js";
|
|
4
|
-
import { CHAT_SCAN, EVENTS_DAYS, onlineDeps, servicesFor } from "../../services/index.js";
|
|
4
|
+
import { CHAT_SCAN, EVENTS_DAYS, onlineDeps, servicesFor, storedDeps } from "../../services/index.js";
|
|
5
5
|
import { momentOf } from "../../services/moment.js";
|
|
6
6
|
import { chatOf, envelope, limit, page, paging, READ, tool } from "../tool.js";
|
|
7
7
|
export const chatsTools = (messenger) => {
|
|
@@ -47,6 +47,26 @@ export const chatsTools = (messenger) => {
|
|
|
47
47
|
return { ...listed(events), hasMore: more, ...rest };
|
|
48
48
|
},
|
|
49
49
|
}),
|
|
50
|
+
chats_stats: tool({
|
|
51
|
+
title: "A chat's numbers for a period",
|
|
52
|
+
description: `Counts over a chat's stored messages since \`since_time\` (${EVENTS_DAYS} days back if not given): messages, ` +
|
|
53
|
+
"senders, replies, threads, reactions, views and forwards where the messenger gave them, topPosts, and " +
|
|
54
|
+
"questions { asked, answered, medianMinutesToAnswer }. `by` adds a series row per day or week. Reads the local " +
|
|
55
|
+
"store only, so joins and leaves are not in it — chats_events has them. complete is false when the store does " +
|
|
56
|
+
"not hold the chat whole: then every number is a lower bound, and fetch names the CLI command that fills it.",
|
|
57
|
+
input: v.object({
|
|
58
|
+
chat,
|
|
59
|
+
since_time: v.optional(v.pipe(v.string(), v.description("an ISO 8601 time, or 2h / 1d ago"))),
|
|
60
|
+
by: v.optional(v.picklist(["day", "week"])),
|
|
61
|
+
timezone: v.optional(v.pipe(v.string(), v.description("the IANA timezone for calendar days"))),
|
|
62
|
+
}),
|
|
63
|
+
annotations: { ...READ, openWorldHint: false },
|
|
64
|
+
stored: (store, account, args, defaults) => servicesFor(storedDeps(messenger, store, account, defaults.guard)).chats.stats(args.chat, {
|
|
65
|
+
...(args.since_time === undefined ? {} : { since: momentOf(args.since_time, "since_time") }),
|
|
66
|
+
...(args.by ? { by: args.by } : {}),
|
|
67
|
+
...(args.timezone === undefined ? {} : { timezone: args.timezone }),
|
|
68
|
+
}),
|
|
69
|
+
}),
|
|
50
70
|
chats_members: tool({
|
|
51
71
|
title: "Everyone in a group",
|
|
52
72
|
description: "A group's members, a page at a time: { id, name, username, role?, lastSeenAt? }. role is owner, admin or " +
|