m365connector 0.1.0 → 0.2.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 +4 -4
- package/package.json +1 -1
- package/src/index.js +10 -10
- package/src/ws-server.js +9 -9
package/README.md
CHANGED
|
@@ -33,8 +33,8 @@ npx m365connector
|
|
|
33
33
|
You should see:
|
|
34
34
|
|
|
35
35
|
```
|
|
36
|
-
[
|
|
37
|
-
[
|
|
36
|
+
[m365connector/ws] listening on ws://127.0.0.1:52365
|
|
37
|
+
[m365connector] MCP HTTP listening on http://127.0.0.1:52366/mcp
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Then add to your MCP client config (e.g. `~/.claude/mcp.json`):
|
|
@@ -61,8 +61,8 @@ m365connector
|
|
|
61
61
|
|
|
62
62
|
| Variable | Default | Description |
|
|
63
63
|
|----------|---------|-------------|
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
64
|
+
| `M365C_MCP_PORT` | 52366 | HTTP port for MCP clients |
|
|
65
|
+
| `M365C_WS_PORT` | 52365 | WebSocket port for extension IPC |
|
|
66
66
|
|
|
67
67
|
## Tools
|
|
68
68
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
|
|
|
9
9
|
import { WsServer } from "./ws-server.js";
|
|
10
10
|
|
|
11
11
|
const SERVER_INFO = {
|
|
12
|
-
name: "
|
|
12
|
+
name: "m365connector",
|
|
13
13
|
version: "0.1.0"
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -158,8 +158,8 @@ function sendJsonRpcError(res, status, code, message) {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
async function main() {
|
|
161
|
-
const mcpPort = parsePort(process.env.
|
|
162
|
-
const wsPort = parsePort(process.env.
|
|
161
|
+
const mcpPort = parsePort(process.env.M365C_MCP_PORT, "M365C_MCP_PORT", DEFAULT_MCP_PORT);
|
|
162
|
+
const wsPort = parsePort(process.env.M365C_WS_PORT, "M365C_WS_PORT", DEFAULT_WS_PORT);
|
|
163
163
|
|
|
164
164
|
// MCP responses are returned over HTTP; operational logs must go to stderr only.
|
|
165
165
|
const stderrLogger = {
|
|
@@ -205,7 +205,7 @@ async function main() {
|
|
|
205
205
|
});
|
|
206
206
|
|
|
207
207
|
transport.onerror = (err) => {
|
|
208
|
-
stderrLogger.warn("[
|
|
208
|
+
stderrLogger.warn("[m365connector] MCP transport error:", err);
|
|
209
209
|
};
|
|
210
210
|
|
|
211
211
|
transport.onclose = () => {
|
|
@@ -234,7 +234,7 @@ async function main() {
|
|
|
234
234
|
session.lastActivity = Date.now();
|
|
235
235
|
await session.transport.handleRequest(req, res, req.body);
|
|
236
236
|
} catch (err) {
|
|
237
|
-
stderrLogger.error("[
|
|
237
|
+
stderrLogger.error("[m365connector] failed to handle MCP request:", err);
|
|
238
238
|
if (!res.headersSent) {
|
|
239
239
|
sendJsonRpcError(res, 500, -32603, "Internal error");
|
|
240
240
|
}
|
|
@@ -249,7 +249,7 @@ async function main() {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
session.server.close().catch((err) => {
|
|
252
|
-
stderrLogger.warn(`[
|
|
252
|
+
stderrLogger.warn(`[m365connector] failed to close idle session ${sessionId}:`, err);
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
255
|
}, SESSION_SWEEP_INTERVAL_MS);
|
|
@@ -261,7 +261,7 @@ async function main() {
|
|
|
261
261
|
server.once("error", reject);
|
|
262
262
|
});
|
|
263
263
|
|
|
264
|
-
stderrLogger.error(`[
|
|
264
|
+
stderrLogger.error(`[m365connector] MCP HTTP listening on http://127.0.0.1:${mcpPort}/mcp`);
|
|
265
265
|
|
|
266
266
|
let shuttingDown = false;
|
|
267
267
|
const shutdown = async () => {
|
|
@@ -276,14 +276,14 @@ async function main() {
|
|
|
276
276
|
try {
|
|
277
277
|
await session.server.close();
|
|
278
278
|
} catch (err) {
|
|
279
|
-
stderrLogger.warn("[
|
|
279
|
+
stderrLogger.warn("[m365connector] failed to close session during shutdown:", err);
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
try {
|
|
284
284
|
await ws.stop();
|
|
285
285
|
} catch (err) {
|
|
286
|
-
stderrLogger.warn("[
|
|
286
|
+
stderrLogger.warn("[m365connector] failed to stop WebSocket server:", err);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
await new Promise((resolve) => {
|
|
@@ -298,6 +298,6 @@ async function main() {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
main().catch((err) => {
|
|
301
|
-
console.error("[
|
|
301
|
+
console.error("[m365connector] MCP server failed to start:", err);
|
|
302
302
|
process.exit(1);
|
|
303
303
|
});
|
package/src/ws-server.js
CHANGED
|
@@ -30,7 +30,7 @@ export class WsServer {
|
|
|
30
30
|
|
|
31
31
|
this.wss.on("connection", (socket, req) => {
|
|
32
32
|
this.handleConnection(socket, req).catch((err) => {
|
|
33
|
-
this.logger.error("[
|
|
33
|
+
this.logger.error("[m365connector/ws] connection handling failed:", err);
|
|
34
34
|
try {
|
|
35
35
|
socket.close(1011, "internal error");
|
|
36
36
|
} catch (_err) {
|
|
@@ -44,7 +44,7 @@ export class WsServer {
|
|
|
44
44
|
this.wss.once("error", reject);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
this.logger.error(`[
|
|
47
|
+
this.logger.error(`[m365connector/ws] listening on ws://${this.host}:${this.port}`);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
async stop() {
|
|
@@ -116,13 +116,13 @@ export class WsServer {
|
|
|
116
116
|
const origin = req.headers.origin;
|
|
117
117
|
|
|
118
118
|
if (!origin) {
|
|
119
|
-
this.logger.warn("[
|
|
119
|
+
this.logger.warn("[m365connector/ws] rejected connection: missing origin header");
|
|
120
120
|
socket.close(1008, "origin required");
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
if (!origin.startsWith("chrome-extension://")) {
|
|
125
|
-
this.logger.warn(`[
|
|
125
|
+
this.logger.warn(`[m365connector/ws] rejected connection from origin: ${origin}`);
|
|
126
126
|
socket.close(1008, "origin not allowed");
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
@@ -130,7 +130,7 @@ export class WsServer {
|
|
|
130
130
|
if (this.client && this.client.readyState === WebSocket.OPEN) {
|
|
131
131
|
// MV3 service workers can die silently without sending a close frame.
|
|
132
132
|
// When the extension reconnects, replace the stale connection.
|
|
133
|
-
this.logger.error("[
|
|
133
|
+
this.logger.error("[m365connector/ws] replacing existing connection with new one");
|
|
134
134
|
try { this.client.terminate(); } catch (_e) { /* ignored */ }
|
|
135
135
|
this.handleClose(this.client);
|
|
136
136
|
}
|
|
@@ -147,14 +147,14 @@ export class WsServer {
|
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
socket.on("close", (code, reason) => {
|
|
150
|
-
this.logger.error(`[
|
|
150
|
+
this.logger.error(`[m365connector/ws] socket close: code=${code}, reason=${String(reason)}`);
|
|
151
151
|
this.handleClose(socket);
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
socket.on("error", (err) => {
|
|
155
|
-
this.logger.warn("[
|
|
155
|
+
this.logger.warn("[m365connector/ws] client socket error:", err.message);
|
|
156
156
|
});
|
|
157
|
-
this.logger.error("[
|
|
157
|
+
this.logger.error("[m365connector/ws] extension connected");
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
async handleMessage(socket, rawData) {
|
|
@@ -197,6 +197,6 @@ export class WsServer {
|
|
|
197
197
|
this.pending.delete(id);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
this.logger.error("[
|
|
200
|
+
this.logger.error("[m365connector/ws] extension disconnected");
|
|
201
201
|
}
|
|
202
202
|
}
|