@fleetx_io/fleetx-mcp-server 1.1.7 → 2.0.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/CHANGELOG.md +44 -12
- package/README.md +56 -6
- package/dist/auth/fleetx/exchange.d.ts +13 -0
- package/dist/auth/fleetx/exchange.d.ts.map +1 -0
- package/dist/auth/fleetx/exchange.js +27 -0
- package/dist/auth/fleetx/exchange.js.map +1 -0
- package/dist/auth/google/callback.d.ts +3 -0
- package/dist/auth/google/callback.d.ts.map +1 -0
- package/dist/auth/google/callback.js +98 -0
- package/dist/auth/google/callback.js.map +1 -0
- package/dist/auth/google/client.d.ts +17 -0
- package/dist/auth/google/client.d.ts.map +1 -0
- package/dist/auth/google/client.js +50 -0
- package/dist/auth/google/client.js.map +1 -0
- package/dist/auth/oauth/authorize.d.ts +3 -0
- package/dist/auth/oauth/authorize.d.ts.map +1 -0
- package/dist/auth/oauth/authorize.js +74 -0
- package/dist/auth/oauth/authorize.js.map +1 -0
- package/dist/auth/oauth/cimd.d.ts +33 -0
- package/dist/auth/oauth/cimd.d.ts.map +1 -0
- package/dist/auth/oauth/cimd.js +63 -0
- package/dist/auth/oauth/cimd.js.map +1 -0
- package/dist/auth/oauth/pending-sessions.d.ts +5 -0
- package/dist/auth/oauth/pending-sessions.d.ts.map +1 -0
- package/dist/auth/oauth/pending-sessions.js +24 -0
- package/dist/auth/oauth/pending-sessions.js.map +1 -0
- package/dist/auth/oauth/pkce.d.ts +3 -0
- package/dist/auth/oauth/pkce.d.ts.map +1 -0
- package/dist/auth/oauth/pkce.js +7 -0
- package/dist/auth/oauth/pkce.js.map +1 -0
- package/dist/auth/oauth/register.d.ts +8 -0
- package/dist/auth/oauth/register.d.ts.map +1 -0
- package/dist/auth/oauth/register.js +37 -0
- package/dist/auth/oauth/register.js.map +1 -0
- package/dist/auth/oauth/token.d.ts +3 -0
- package/dist/auth/oauth/token.d.ts.map +1 -0
- package/dist/auth/oauth/token.js +111 -0
- package/dist/auth/oauth/token.js.map +1 -0
- package/dist/auth/oauth/types.d.ts +11 -0
- package/dist/auth/oauth/types.d.ts.map +1 -0
- package/dist/auth/oauth/types.js +2 -0
- package/dist/auth/oauth/types.js.map +1 -0
- package/dist/auth/oauth/userinfo.d.ts +3 -0
- package/dist/auth/oauth/userinfo.d.ts.map +1 -0
- package/dist/auth/oauth/userinfo.js +29 -0
- package/dist/auth/oauth/userinfo.js.map +1 -0
- package/dist/auth/storage/authorization-code.d.ts +19 -0
- package/dist/auth/storage/authorization-code.d.ts.map +1 -0
- package/dist/auth/storage/authorization-code.js +44 -0
- package/dist/auth/storage/authorization-code.js.map +1 -0
- package/dist/auth/storage/connected-account.d.ts +24 -0
- package/dist/auth/storage/connected-account.d.ts.map +1 -0
- package/dist/auth/storage/connected-account.js +60 -0
- package/dist/auth/storage/connected-account.js.map +1 -0
- package/dist/auth/storage/db.d.ts +3 -0
- package/dist/auth/storage/db.d.ts.map +1 -0
- package/dist/auth/storage/db.js +110 -0
- package/dist/auth/storage/db.js.map +1 -0
- package/dist/auth/storage/oauth-client.d.ts +12 -0
- package/dist/auth/storage/oauth-client.d.ts.map +1 -0
- package/dist/auth/storage/oauth-client.js +28 -0
- package/dist/auth/storage/oauth-client.js.map +1 -0
- package/dist/auth/storage/refresh-token.d.ts +17 -0
- package/dist/auth/storage/refresh-token.d.ts.map +1 -0
- package/dist/auth/storage/refresh-token.js +46 -0
- package/dist/auth/storage/refresh-token.js.map +1 -0
- package/dist/auth/tokens/encryption.d.ts +5 -0
- package/dist/auth/tokens/encryption.d.ts.map +1 -0
- package/dist/auth/tokens/encryption.js +27 -0
- package/dist/auth/tokens/encryption.js.map +1 -0
- package/dist/auth/tokens/jwt.d.ts +8 -0
- package/dist/auth/tokens/jwt.d.ts.map +1 -0
- package/dist/auth/tokens/jwt.js +34 -0
- package/dist/auth/tokens/jwt.js.map +1 -0
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +2 -1
- package/dist/auth.js.map +1 -1
- package/dist/config/oauth.d.ts +21 -0
- package/dist/config/oauth.d.ts.map +1 -0
- package/dist/config/oauth.js +41 -0
- package/dist/config/oauth.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/middleware/auth.d.ts +18 -0
- package/dist/mcp/middleware/auth.d.ts.map +1 -0
- package/dist/mcp/middleware/auth.js +35 -0
- package/dist/mcp/middleware/auth.js.map +1 -0
- package/dist/server/createMcpServer.d.ts +8 -3
- package/dist/server/createMcpServer.d.ts.map +1 -1
- package/dist/server/createMcpServer.js +28 -12
- package/dist/server/createMcpServer.js.map +1 -1
- package/dist/transports/fastify.d.ts +2 -0
- package/dist/transports/fastify.d.ts.map +1 -0
- package/dist/transports/fastify.js +223 -0
- package/dist/transports/fastify.js.map +1 -0
- package/dist/transports/sse.d.ts +1 -1
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +162 -67
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/stdio.d.ts.map +1 -1
- package/dist/transports/stdio.js +8 -1
- package/dist/transports/stdio.js.map +1 -1
- package/dist/utils-http.d.ts +8 -0
- package/dist/utils-http.d.ts.map +1 -0
- package/dist/utils-http.js +15 -0
- package/dist/utils-http.js.map +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +12 -2
- package/dist/utils.js.map +1 -1
- package/dist/well-known/discovery.d.ts +4 -0
- package/dist/well-known/discovery.d.ts.map +1 -0
- package/dist/well-known/discovery.js +25 -0
- package/dist/well-known/discovery.js.map +1 -0
- package/package.json +15 -7
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import Fastify from "fastify";
|
|
2
|
+
import formbody from "@fastify/formbody";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { createMcpServer } from "../server/createMcpServer.js";
|
|
7
|
+
import { createTokenStore } from "../auth.js";
|
|
8
|
+
import { log } from "../utils.js";
|
|
9
|
+
import { isOAuthConfigured, getOAuthConfig } from "../config/oauth.js";
|
|
10
|
+
import { verifyMcpAccessToken } from "../auth/tokens/jwt.js";
|
|
11
|
+
import { findConnectedAccountByUserId, updateFleetxTokens } from "../auth/storage/connected-account.js";
|
|
12
|
+
import { refreshFleetxToken } from "../auth/fleetx/exchange.js";
|
|
13
|
+
import { handleAuthorize } from "../auth/oauth/authorize.js";
|
|
14
|
+
import { handleToken } from "../auth/oauth/token.js";
|
|
15
|
+
import { handleUserInfo } from "../auth/oauth/userinfo.js";
|
|
16
|
+
import { handleGoogleCallback } from "../auth/google/callback.js";
|
|
17
|
+
import { handleAuthorizationServerMetadata, handleProtectedResourceMetadata, } from "../well-known/discovery.js";
|
|
18
|
+
const transports = new Map();
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// Credential resolution
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
function parseBearer(header) {
|
|
23
|
+
if (!header?.startsWith("Bearer "))
|
|
24
|
+
return undefined;
|
|
25
|
+
return header.slice(7).trim() || undefined;
|
|
26
|
+
}
|
|
27
|
+
function parseBasic(header) {
|
|
28
|
+
if (!header?.startsWith("Basic "))
|
|
29
|
+
return undefined;
|
|
30
|
+
const decoded = Buffer.from(header.slice(6), "base64").toString("utf-8");
|
|
31
|
+
const sep = decoded.indexOf(":");
|
|
32
|
+
if (sep === -1)
|
|
33
|
+
return undefined;
|
|
34
|
+
const username = decoded.slice(0, sep);
|
|
35
|
+
const password = decoded.slice(sep + 1);
|
|
36
|
+
return username && password ? { type: "basic", username, password } : undefined;
|
|
37
|
+
}
|
|
38
|
+
async function resolveCredentials(authHeader) {
|
|
39
|
+
const bearerToken = parseBearer(authHeader);
|
|
40
|
+
if (bearerToken && isOAuthConfigured()) {
|
|
41
|
+
// Attempt to treat as MCP JWT → look up FleetX token
|
|
42
|
+
const payload = await verifyMcpAccessToken(bearerToken).catch(() => null);
|
|
43
|
+
if (payload) {
|
|
44
|
+
const account = findConnectedAccountByUserId(payload.sub);
|
|
45
|
+
if (account) {
|
|
46
|
+
// Refresh FleetX token if expiring soon
|
|
47
|
+
const BUFFER = 5 * 60 * 1000;
|
|
48
|
+
const expiringSoon = account.fleetxTokenExpiry !== null &&
|
|
49
|
+
account.fleetxTokenExpiry - Date.now() < BUFFER;
|
|
50
|
+
if (expiringSoon) {
|
|
51
|
+
const refreshed = await refreshFleetxToken(account.fleetxRefreshToken);
|
|
52
|
+
if (refreshed) {
|
|
53
|
+
updateFleetxTokens(account.userId, refreshed.accessToken, refreshed.refreshToken);
|
|
54
|
+
return { type: "bearer", token: refreshed.accessToken };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { type: "bearer", token: account.fleetxAccessToken };
|
|
58
|
+
}
|
|
59
|
+
// Valid JWT but no account — deny
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
// Not a valid MCP JWT — fall through to raw bearer / basic / env
|
|
63
|
+
}
|
|
64
|
+
const basic = parseBasic(authHeader);
|
|
65
|
+
if (basic)
|
|
66
|
+
return basic;
|
|
67
|
+
if (bearerToken)
|
|
68
|
+
return { type: "bearer", token: bearerToken };
|
|
69
|
+
const envToken = process.env.BEARER_ACCESS_TOKEN?.trim();
|
|
70
|
+
if (envToken)
|
|
71
|
+
return { type: "bearer", token: envToken };
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
75
|
+
// Raw-body parser (needed before passing to MCP transport)
|
|
76
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
77
|
+
function readRawBody(req) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const chunks = [];
|
|
80
|
+
req.on("data", (c) => chunks.push(c));
|
|
81
|
+
req.on("end", () => {
|
|
82
|
+
try {
|
|
83
|
+
resolve(JSON.parse(Buffer.concat(chunks).toString()));
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
reject(e);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
req.on("error", reject);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
93
|
+
// MCP session handlers (operate on Node raw req/res)
|
|
94
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
95
|
+
async function handleMcpPost(req, res, authHeader) {
|
|
96
|
+
const body = await readRawBody(req);
|
|
97
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
98
|
+
if (sessionId && transports.has(sessionId)) {
|
|
99
|
+
await transports.get(sessionId).handleRequest(req, res, body);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!sessionId && isInitializeRequest(body)) {
|
|
103
|
+
log(`New MCP session from ${req.socket?.remoteAddress}`);
|
|
104
|
+
const credentials = await resolveCredentials(authHeader);
|
|
105
|
+
const transport = new StreamableHTTPServerTransport({
|
|
106
|
+
sessionIdGenerator: () => randomUUID(),
|
|
107
|
+
onsessioninitialized: (id) => {
|
|
108
|
+
transports.set(id, transport);
|
|
109
|
+
log(`MCP session initialized: ${id}`);
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
transport.onclose = () => {
|
|
113
|
+
const sid = transport.sessionId;
|
|
114
|
+
if (sid) {
|
|
115
|
+
transports.delete(sid);
|
|
116
|
+
log(`MCP session closed: ${sid}`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const tokenStore = createTokenStore();
|
|
120
|
+
const server = await createMcpServer(tokenStore, credentials);
|
|
121
|
+
await server.connect(transport);
|
|
122
|
+
await transport.handleRequest(req, res, body);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
126
|
+
res.end(JSON.stringify({
|
|
127
|
+
jsonrpc: "2.0",
|
|
128
|
+
error: { code: -32000, message: "Bad Request: No valid session ID" },
|
|
129
|
+
id: null,
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
async function handleMcpGetDelete(req, res) {
|
|
133
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
134
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
135
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
136
|
+
res.end(JSON.stringify({ error: "Invalid or missing session ID" }));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await transports.get(sessionId).handleRequest(req, res);
|
|
140
|
+
}
|
|
141
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
142
|
+
// Fastify server bootstrap
|
|
143
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
144
|
+
export async function startFastify() {
|
|
145
|
+
const port = parseInt(process.env.PORT ?? "3000", 10);
|
|
146
|
+
const oauthEnabled = isOAuthConfigured();
|
|
147
|
+
const fastify = Fastify({ logger: false, disableRequestLogging: true });
|
|
148
|
+
// Parse application/x-www-form-urlencoded (token endpoint)
|
|
149
|
+
await fastify.register(formbody);
|
|
150
|
+
// ── Health ───────────────────────────────────────────────────────────────
|
|
151
|
+
fastify.get("/health", async () => ({
|
|
152
|
+
status: "ok",
|
|
153
|
+
message: "FleetX MCP Server is running",
|
|
154
|
+
oauth: oauthEnabled,
|
|
155
|
+
}));
|
|
156
|
+
// ── OAuth + discovery (only when configured) ─────────────────────────────
|
|
157
|
+
if (oauthEnabled) {
|
|
158
|
+
const cfg = getOAuthConfig();
|
|
159
|
+
fastify.get("/.well-known/oauth-authorization-server", handleAuthorizationServerMetadata);
|
|
160
|
+
fastify.get("/.well-known/oauth-protected-resource", handleProtectedResourceMetadata);
|
|
161
|
+
fastify.get("/oauth/authorize", handleAuthorize);
|
|
162
|
+
fastify.post("/oauth/token", handleToken);
|
|
163
|
+
fastify.get("/userinfo", handleUserInfo);
|
|
164
|
+
fastify.get("/google/callback", handleGoogleCallback);
|
|
165
|
+
log(`OAuth endpoints enabled (issuer: ${cfg.MCP_BASE_URL})`);
|
|
166
|
+
}
|
|
167
|
+
// ── MCP endpoint ─────────────────────────────────────────────────────────
|
|
168
|
+
fastify.all("/mcp", async (request, reply) => {
|
|
169
|
+
// Hand off raw req/res to the MCP transport; Fastify must not touch the response.
|
|
170
|
+
reply.hijack();
|
|
171
|
+
const req = request.raw;
|
|
172
|
+
const res = reply.raw;
|
|
173
|
+
try {
|
|
174
|
+
switch (req.method) {
|
|
175
|
+
case "POST":
|
|
176
|
+
await handleMcpPost(req, res, request.headers.authorization);
|
|
177
|
+
break;
|
|
178
|
+
case "GET":
|
|
179
|
+
case "DELETE":
|
|
180
|
+
await handleMcpGetDelete(req, res);
|
|
181
|
+
break;
|
|
182
|
+
default:
|
|
183
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
184
|
+
res.end(JSON.stringify({ error: "Method not allowed" }));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
log("MCP handler error:", err);
|
|
189
|
+
if (!res.headersSent) {
|
|
190
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
191
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
// ── 404 fallback ─────────────────────────────────────────────────────────
|
|
196
|
+
fastify.setNotFoundHandler(async (_, reply) => {
|
|
197
|
+
return reply.status(404).send({ error: "Not found" });
|
|
198
|
+
});
|
|
199
|
+
await fastify.listen({ port, host: "0.0.0.0" });
|
|
200
|
+
log(`FleetX MCP Server listening on http://0.0.0.0:${port}`);
|
|
201
|
+
log(` MCP endpoint : http://localhost:${port}/mcp`);
|
|
202
|
+
if (oauthEnabled) {
|
|
203
|
+
const cfg = getOAuthConfig();
|
|
204
|
+
log(` Authorize : ${cfg.MCP_BASE_URL}/oauth/authorize`);
|
|
205
|
+
log(` Token : ${cfg.MCP_BASE_URL}/oauth/token`);
|
|
206
|
+
log(` Discovery : ${cfg.MCP_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
207
|
+
}
|
|
208
|
+
process.on("SIGINT", async () => {
|
|
209
|
+
log("Shutting down…");
|
|
210
|
+
for (const [id, transport] of transports) {
|
|
211
|
+
try {
|
|
212
|
+
await transport.close();
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
/* best-effort */
|
|
216
|
+
}
|
|
217
|
+
transports.delete(id);
|
|
218
|
+
}
|
|
219
|
+
await fastify.close();
|
|
220
|
+
process.exit(0);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=fastify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/transports/fastify.ts"],"names":[],"mappings":"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"}
|
package/dist/transports/sse.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function startSSE(): Promise<void>;
|
|
2
2
|
//# sourceMappingURL=sse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"AA6MA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA+F9C"}
|
package/dist/transports/sse.js
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Fastify from "fastify";
|
|
2
|
+
import formbody from "@fastify/formbody";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
5
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
6
|
import { createMcpServer } from "../server/createMcpServer.js";
|
|
6
7
|
import { createTokenStore } from "../auth.js";
|
|
7
8
|
import { log } from "../utils.js";
|
|
9
|
+
import { isOAuthConfigured, getOAuthConfig } from "../config/oauth.js";
|
|
10
|
+
import { verifyMcpAccessToken } from "../auth/tokens/jwt.js";
|
|
11
|
+
import { findConnectedAccountByUserId, expireConnectedAccountToken } from "../auth/storage/connected-account.js";
|
|
12
|
+
import { handleAuthorize } from "../auth/oauth/authorize.js";
|
|
13
|
+
import { handleToken } from "../auth/oauth/token.js";
|
|
14
|
+
import { handleClientRegistration } from "../auth/oauth/register.js";
|
|
15
|
+
import { handleUserInfo } from "../auth/oauth/userinfo.js";
|
|
16
|
+
import { handleGoogleCallback } from "../auth/google/callback.js";
|
|
17
|
+
import { handleAuthorizationServerMetadata, handleProtectedResourceMetadata, } from "../well-known/discovery.js";
|
|
8
18
|
const transports = new Map();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
// Credential resolution
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
function parseBearer(header) {
|
|
23
|
+
if (!header?.startsWith("Bearer "))
|
|
24
|
+
return undefined;
|
|
25
|
+
return header.slice(7).trim() || undefined;
|
|
26
|
+
}
|
|
27
|
+
function parseBasic(header) {
|
|
17
28
|
if (!header?.startsWith("Basic "))
|
|
18
29
|
return undefined;
|
|
19
30
|
const decoded = Buffer.from(header.slice(6), "base64").toString("utf-8");
|
|
@@ -22,102 +33,175 @@ function parseBasicAuth(header) {
|
|
|
22
33
|
return undefined;
|
|
23
34
|
const username = decoded.slice(0, sep);
|
|
24
35
|
const password = decoded.slice(sep + 1);
|
|
25
|
-
return username && password ? { username, password } : undefined;
|
|
36
|
+
return username && password ? { type: "basic", username, password } : undefined;
|
|
26
37
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
resolve(JSON.parse(Buffer.concat(chunks).toString()));
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
reject(err);
|
|
37
|
-
}
|
|
38
|
+
async function resolveCredentials(authHeader) {
|
|
39
|
+
const bearerToken = parseBearer(authHeader);
|
|
40
|
+
if (bearerToken && isOAuthConfigured()) {
|
|
41
|
+
const payload = await verifyMcpAccessToken(bearerToken).catch((err) => {
|
|
42
|
+
log("MCP JWT verification failed:", err);
|
|
43
|
+
return null;
|
|
38
44
|
});
|
|
39
|
-
|
|
45
|
+
if (payload) {
|
|
46
|
+
const account = findConnectedAccountByUserId(payload.sub);
|
|
47
|
+
if (account && account.fleetxAccessToken) {
|
|
48
|
+
log("resolveCredentials: OAuth JWT → FleetX bearer for", payload.sub);
|
|
49
|
+
return { credentials: { type: "bearer", token: account.fleetxAccessToken }, userId: payload.sub };
|
|
50
|
+
}
|
|
51
|
+
log("resolveCredentials: JWT valid but no active FleetX token for sub:", payload.sub);
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
// Not a valid MCP JWT — fall through to raw bearer / basic / env
|
|
55
|
+
}
|
|
56
|
+
const basic = parseBasic(authHeader);
|
|
57
|
+
if (basic) {
|
|
58
|
+
log("resolveCredentials: basic auth");
|
|
59
|
+
return { credentials: basic };
|
|
60
|
+
}
|
|
61
|
+
if (bearerToken) {
|
|
62
|
+
log("resolveCredentials: raw bearer token");
|
|
63
|
+
return { credentials: { type: "bearer", token: bearerToken } };
|
|
64
|
+
}
|
|
65
|
+
const envToken = process.env.BEARER_ACCESS_TOKEN?.trim();
|
|
66
|
+
if (envToken) {
|
|
67
|
+
log("resolveCredentials: BEARER_ACCESS_TOKEN env");
|
|
68
|
+
return { credentials: { type: "bearer", token: envToken } };
|
|
69
|
+
}
|
|
70
|
+
log("resolveCredentials: no credentials (authHeader present:", !!authHeader, ")");
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
// Send 401 with WWW-Authenticate so Claude triggers the OAuth flow.
|
|
74
|
+
function sendUnauthorized(res) {
|
|
75
|
+
const base = process.env.MCP_BASE_URL ?? "https://mcp.fleetx.io";
|
|
76
|
+
res.writeHead(401, {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
"WWW-Authenticate": `Bearer resource_metadata="${base}/.well-known/oauth-protected-resource"`,
|
|
40
79
|
});
|
|
80
|
+
res.end(JSON.stringify({
|
|
81
|
+
error: "unauthorized",
|
|
82
|
+
error_description: "Authentication required. Please complete OAuth flow.",
|
|
83
|
+
}));
|
|
41
84
|
}
|
|
42
|
-
|
|
43
|
-
|
|
85
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
86
|
+
// MCP session handlers (operate on Node raw req/res)
|
|
87
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
88
|
+
async function handleMcpPost(req, res, authHeader, body) {
|
|
44
89
|
const sessionId = req.headers["mcp-session-id"];
|
|
90
|
+
// Existing session — forward directly (already authenticated when session was created)
|
|
45
91
|
if (sessionId && transports.has(sessionId)) {
|
|
92
|
+
log(`MCP POST session=${sessionId}`);
|
|
46
93
|
await transports.get(sessionId).handleRequest(req, res, body);
|
|
47
94
|
return;
|
|
48
95
|
}
|
|
96
|
+
// New session must start with initialize
|
|
49
97
|
if (!sessionId && isInitializeRequest(body)) {
|
|
50
|
-
log(`
|
|
98
|
+
log(`MCP initialize from ${req.socket?.remoteAddress} auth=${!!authHeader}`);
|
|
99
|
+
const resolved = await resolveCredentials(authHeader);
|
|
100
|
+
// OAuth is enabled but no valid token → tell Claude to authenticate
|
|
101
|
+
if (!resolved && isOAuthConfigured()) {
|
|
102
|
+
log("MCP initialize rejected: no credentials, sending 401");
|
|
103
|
+
sendUnauthorized(res);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
51
106
|
const transport = new StreamableHTTPServerTransport({
|
|
52
107
|
sessionIdGenerator: () => randomUUID(),
|
|
53
108
|
onsessioninitialized: (id) => {
|
|
54
109
|
transports.set(id, transport);
|
|
55
|
-
log(`
|
|
110
|
+
log(`MCP session created: ${id}`);
|
|
56
111
|
},
|
|
57
112
|
});
|
|
58
113
|
transport.onclose = () => {
|
|
59
114
|
const sid = transport.sessionId;
|
|
60
115
|
if (sid) {
|
|
61
116
|
transports.delete(sid);
|
|
62
|
-
log(`
|
|
117
|
+
log(`MCP session closed: ${sid}`);
|
|
63
118
|
}
|
|
64
119
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
120
|
+
// For OAuth sessions, when FleetX returns 401 the tokenStore.clearToken()
|
|
121
|
+
// also wipes the stored token in SQLite → next MCP connect gets 401 → Claude re-auths.
|
|
122
|
+
const onClear = resolved?.userId
|
|
123
|
+
? () => {
|
|
124
|
+
log("FleetX token expired for userId:", resolved.userId);
|
|
125
|
+
expireConnectedAccountToken(resolved.userId);
|
|
126
|
+
}
|
|
127
|
+
: undefined;
|
|
128
|
+
const tokenStore = createTokenStore(onClear);
|
|
129
|
+
const server = await createMcpServer(tokenStore, resolved?.credentials);
|
|
68
130
|
await server.connect(transport);
|
|
69
131
|
await transport.handleRequest(req, res, body);
|
|
70
132
|
return;
|
|
71
133
|
}
|
|
134
|
+
// Unknown session or non-initialize without session
|
|
135
|
+
log(`MCP POST bad request: sessionId=${sessionId} isInit=${isInitializeRequest(body)}`);
|
|
72
136
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
73
137
|
res.end(JSON.stringify({
|
|
74
138
|
jsonrpc: "2.0",
|
|
75
|
-
error: { code: -32000, message: "Bad Request:
|
|
139
|
+
error: { code: -32000, message: "Bad Request: send initialize first" },
|
|
76
140
|
id: null,
|
|
77
141
|
}));
|
|
78
142
|
}
|
|
79
|
-
async function
|
|
143
|
+
async function handleMcpGetDelete(req, res, authHeader) {
|
|
80
144
|
const sessionId = req.headers["mcp-session-id"];
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
res.end(JSON.stringify({ error: "Invalid or missing session ID" }));
|
|
145
|
+
if (sessionId && transports.has(sessionId)) {
|
|
146
|
+
await transports.get(sessionId).handleRequest(req, res);
|
|
84
147
|
return;
|
|
85
148
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (!sessionId || !transports.has(sessionId)) {
|
|
91
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
92
|
-
res.end(JSON.stringify({ error: "Invalid or missing session ID" }));
|
|
149
|
+
// No valid session — return 401 if OAuth enabled so Claude triggers the auth flow,
|
|
150
|
+
// otherwise 400.
|
|
151
|
+
if (isOAuthConfigured() && !(await resolveCredentials(authHeader))) {
|
|
152
|
+
sendUnauthorized(res);
|
|
93
153
|
return;
|
|
94
154
|
}
|
|
95
|
-
|
|
155
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
156
|
+
res.end(JSON.stringify({ error: "Invalid or missing session ID" }));
|
|
96
157
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
158
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
159
|
+
// Fastify server bootstrap
|
|
160
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
161
|
+
export async function startSSE() {
|
|
162
|
+
const port = parseInt(process.env.PORT ?? "3000", 10);
|
|
163
|
+
const oauthEnabled = isOAuthConfigured();
|
|
164
|
+
const fastify = Fastify({
|
|
165
|
+
logger: {
|
|
166
|
+
stream: process.stderr,
|
|
167
|
+
level: process.env.LOG_LEVEL ?? "info",
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
// Parse application/x-www-form-urlencoded (token endpoint)
|
|
171
|
+
await fastify.register(formbody);
|
|
172
|
+
// ── Health ───────────────────────────────────────────────────────────────
|
|
173
|
+
fastify.get("/health", async () => ({
|
|
174
|
+
status: "ok",
|
|
175
|
+
message: "FleetX MCP Server is running",
|
|
176
|
+
oauth: oauthEnabled,
|
|
177
|
+
}));
|
|
178
|
+
// ── OAuth + discovery (only when configured) ─────────────────────────────
|
|
179
|
+
if (oauthEnabled) {
|
|
180
|
+
const cfg = getOAuthConfig();
|
|
181
|
+
fastify.get("/.well-known/oauth-authorization-server", handleAuthorizationServerMetadata);
|
|
182
|
+
fastify.get("/.well-known/oauth-protected-resource", handleProtectedResourceMetadata);
|
|
183
|
+
fastify.get("/oauth/authorize", handleAuthorize);
|
|
184
|
+
fastify.post("/oauth/token", handleToken);
|
|
185
|
+
fastify.post("/oauth/register", handleClientRegistration);
|
|
186
|
+
fastify.get("/userinfo", handleUserInfo);
|
|
187
|
+
fastify.get("/google/callback", handleGoogleCallback);
|
|
188
|
+
log(`OAuth endpoints enaxbled (issuer: ${cfg.MCP_BASE_URL})`);
|
|
189
|
+
}
|
|
190
|
+
// ── MCP endpoint ─────────────────────────────────────────────────────────
|
|
191
|
+
fastify.all("/mcp", async (request, reply) => {
|
|
192
|
+
// Hand off raw req/res to the MCP transport; Fastify must not touch the response.
|
|
193
|
+
reply.hijack();
|
|
194
|
+
const req = request.raw;
|
|
195
|
+
const res = reply.raw;
|
|
111
196
|
try {
|
|
112
197
|
switch (req.method) {
|
|
113
198
|
case "POST":
|
|
114
|
-
|
|
199
|
+
// Pass Fastify's already-parsed body — raw stream is consumed by this point.
|
|
200
|
+
await handleMcpPost(req, res, request.headers.authorization, request.body);
|
|
115
201
|
break;
|
|
116
202
|
case "GET":
|
|
117
|
-
await handleGet(req, res);
|
|
118
|
-
break;
|
|
119
203
|
case "DELETE":
|
|
120
|
-
await
|
|
204
|
+
await handleMcpGetDelete(req, res, request.headers.authorization);
|
|
121
205
|
break;
|
|
122
206
|
default:
|
|
123
207
|
res.writeHead(405, { "Content-Type": "application/json" });
|
|
@@ -125,27 +209,38 @@ export async function startHTTP() {
|
|
|
125
209
|
}
|
|
126
210
|
}
|
|
127
211
|
catch (err) {
|
|
128
|
-
log("
|
|
212
|
+
log("MCP handler error:", err);
|
|
129
213
|
if (!res.headersSent) {
|
|
130
214
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
131
215
|
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
132
216
|
}
|
|
133
217
|
}
|
|
134
218
|
});
|
|
135
|
-
|
|
136
|
-
|
|
219
|
+
// ── 404 fallback ─────────────────────────────────────────────────────────
|
|
220
|
+
fastify.setNotFoundHandler(async (_, reply) => {
|
|
221
|
+
return reply.status(404).send({ error: "Not found" });
|
|
137
222
|
});
|
|
223
|
+
await fastify.listen({ port, host: "0.0.0.0" });
|
|
224
|
+
log(`FleetX MCP Server listening on http://0.0.0.0:${port}`);
|
|
225
|
+
log(`MCP endpoint : http://localhost:${port}/mcp`);
|
|
226
|
+
if (oauthEnabled) {
|
|
227
|
+
const cfg = getOAuthConfig();
|
|
228
|
+
log(` Authorize : ${cfg.MCP_BASE_URL}/oauth/authorize`);
|
|
229
|
+
log(` Token : ${cfg.MCP_BASE_URL}/oauth/token`);
|
|
230
|
+
log(` Discovery : ${cfg.MCP_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
231
|
+
}
|
|
138
232
|
process.on("SIGINT", async () => {
|
|
139
|
-
log("Shutting down
|
|
233
|
+
log("Shutting down…");
|
|
140
234
|
for (const [id, transport] of transports) {
|
|
141
235
|
try {
|
|
142
236
|
await transport.close();
|
|
143
|
-
transports.delete(id);
|
|
144
237
|
}
|
|
145
238
|
catch {
|
|
146
|
-
|
|
239
|
+
/* best-effort */
|
|
147
240
|
}
|
|
241
|
+
transports.delete(id);
|
|
148
242
|
}
|
|
243
|
+
await fastify.close();
|
|
149
244
|
process.exit(0);
|
|
150
245
|
});
|
|
151
246
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAMA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAMA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAehD"}
|
package/dist/transports/stdio.js
CHANGED
|
@@ -6,7 +6,14 @@ import { log } from "../utils.js";
|
|
|
6
6
|
export async function startStdio() {
|
|
7
7
|
const tokenStore = createTokenStore();
|
|
8
8
|
const { username, password } = getUsernameLoginDetails();
|
|
9
|
-
const
|
|
9
|
+
const envBearer = process.env.BEARER_ACCESS_TOKEN?.trim();
|
|
10
|
+
let credentials;
|
|
11
|
+
if (envBearer) {
|
|
12
|
+
credentials = { type: "bearer", token: envBearer };
|
|
13
|
+
}
|
|
14
|
+
else if (username && password) {
|
|
15
|
+
credentials = { type: "basic", username, password };
|
|
16
|
+
}
|
|
10
17
|
const server = await createMcpServer(tokenStore, credentials);
|
|
11
18
|
const transport = new StdioServerTransport();
|
|
12
19
|
await server.connect(transport);
|