@contextstream/mcp-server 0.3.62 → 0.3.63
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/dist/index.js +254 -32
- package/dist/test-server.js +7 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
10
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
11
|
|
|
12
12
|
// node_modules/zod/v3/external.js
|
|
@@ -4057,16 +4057,19 @@ var configSchema = external_exports.object({
|
|
|
4057
4057
|
jwt: external_exports.string().min(1).optional(),
|
|
4058
4058
|
defaultWorkspaceId: external_exports.string().uuid().optional(),
|
|
4059
4059
|
defaultProjectId: external_exports.string().uuid().optional(),
|
|
4060
|
-
userAgent: external_exports.string().default("contextstream-mcp/0.1.0")
|
|
4060
|
+
userAgent: external_exports.string().default("contextstream-mcp/0.1.0"),
|
|
4061
|
+
allowHeaderAuth: external_exports.boolean().optional()
|
|
4061
4062
|
});
|
|
4062
4063
|
function loadConfig() {
|
|
4064
|
+
const allowHeaderAuth = process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "1" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "true" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "yes";
|
|
4063
4065
|
const parsed = configSchema.safeParse({
|
|
4064
4066
|
apiUrl: process.env.CONTEXTSTREAM_API_URL,
|
|
4065
4067
|
apiKey: process.env.CONTEXTSTREAM_API_KEY,
|
|
4066
4068
|
jwt: process.env.CONTEXTSTREAM_JWT,
|
|
4067
4069
|
defaultWorkspaceId: process.env.CONTEXTSTREAM_WORKSPACE_ID,
|
|
4068
4070
|
defaultProjectId: process.env.CONTEXTSTREAM_PROJECT_ID,
|
|
4069
|
-
userAgent: process.env.CONTEXTSTREAM_USER_AGENT
|
|
4071
|
+
userAgent: process.env.CONTEXTSTREAM_USER_AGENT,
|
|
4072
|
+
allowHeaderAuth
|
|
4070
4073
|
});
|
|
4071
4074
|
if (!parsed.success) {
|
|
4072
4075
|
const missing = parsed.error.errors.map((e) => e.path.join(".")).join(", ");
|
|
@@ -4074,8 +4077,8 @@ function loadConfig() {
|
|
|
4074
4077
|
`Invalid configuration. Set CONTEXTSTREAM_API_URL (and API key or JWT). Missing/invalid: ${missing}`
|
|
4075
4078
|
);
|
|
4076
4079
|
}
|
|
4077
|
-
if (!parsed.data.apiKey && !parsed.data.jwt) {
|
|
4078
|
-
throw new Error("Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication.");
|
|
4080
|
+
if (!parsed.data.apiKey && !parsed.data.jwt && !parsed.data.allowHeaderAuth) {
|
|
4081
|
+
throw new Error("Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication (or CONTEXTSTREAM_ALLOW_HEADER_AUTH=true for header-based auth).");
|
|
4079
4082
|
}
|
|
4080
4083
|
return parsed.data;
|
|
4081
4084
|
}
|
|
@@ -4084,6 +4087,16 @@ function loadConfig() {
|
|
|
4084
4087
|
import { randomUUID } from "node:crypto";
|
|
4085
4088
|
import * as path3 from "node:path";
|
|
4086
4089
|
|
|
4090
|
+
// src/auth-context.ts
|
|
4091
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4092
|
+
var authContext = new AsyncLocalStorage();
|
|
4093
|
+
function runWithAuthOverride(override, fn) {
|
|
4094
|
+
return authContext.run(override, fn);
|
|
4095
|
+
}
|
|
4096
|
+
function getAuthOverride() {
|
|
4097
|
+
return authContext.getStore() ?? null;
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4087
4100
|
// src/http.ts
|
|
4088
4101
|
var HttpError = class extends Error {
|
|
4089
4102
|
constructor(status, message, body) {
|
|
@@ -4139,7 +4152,10 @@ async function sleep(ms) {
|
|
|
4139
4152
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
4140
4153
|
}
|
|
4141
4154
|
async function request(config, path7, options = {}) {
|
|
4142
|
-
const { apiUrl,
|
|
4155
|
+
const { apiUrl, userAgent } = config;
|
|
4156
|
+
const authOverride = getAuthOverride();
|
|
4157
|
+
const apiKey = authOverride?.apiKey ?? config.apiKey;
|
|
4158
|
+
const jwt = authOverride?.jwt ?? config.jwt;
|
|
4143
4159
|
const apiPath = path7.startsWith("/api/") ? path7 : `/api/v1${path7}`;
|
|
4144
4160
|
const url = `${apiUrl.replace(/\/$/, "")}${apiPath}`;
|
|
4145
4161
|
const maxRetries = options.retries ?? MAX_RETRIES;
|
|
@@ -4151,7 +4167,7 @@ async function request(config, path7, options = {}) {
|
|
|
4151
4167
|
};
|
|
4152
4168
|
if (apiKey) headers["X-API-Key"] = apiKey;
|
|
4153
4169
|
if (jwt) headers["Authorization"] = `Bearer ${jwt}`;
|
|
4154
|
-
const workspaceId = options.workspaceId || inferWorkspaceIdFromBody(options.body) || inferWorkspaceIdFromPath(apiPath) || config.defaultWorkspaceId;
|
|
4170
|
+
const workspaceId = authOverride?.workspaceId || options.workspaceId || inferWorkspaceIdFromBody(options.body) || inferWorkspaceIdFromPath(apiPath) || config.defaultWorkspaceId;
|
|
4155
4171
|
if (workspaceId) headers["X-Workspace-Id"] = workspaceId;
|
|
4156
4172
|
const fetchOptions = {
|
|
4157
4173
|
method: options.method || (options.body ? "POST" : "GET"),
|
|
@@ -7772,6 +7788,34 @@ function getCoreToolsHint() {
|
|
|
7772
7788
|
// src/tools.ts
|
|
7773
7789
|
var LESSON_DEDUP_WINDOW_MS = 2 * 60 * 1e3;
|
|
7774
7790
|
var recentLessonCaptures = /* @__PURE__ */ new Map();
|
|
7791
|
+
function normalizeHeaderValue(value) {
|
|
7792
|
+
if (!value) return void 0;
|
|
7793
|
+
return Array.isArray(value) ? value[0] : value;
|
|
7794
|
+
}
|
|
7795
|
+
function resolveAuthOverride(extra) {
|
|
7796
|
+
const token = extra?.authInfo?.token;
|
|
7797
|
+
const tokenType = extra?.authInfo?.extra?.tokenType;
|
|
7798
|
+
const headers = extra?.requestInfo?.headers;
|
|
7799
|
+
const existing = getAuthOverride();
|
|
7800
|
+
const workspaceId = normalizeHeaderValue(headers?.["x-contextstream-workspace-id"]) || normalizeHeaderValue(headers?.["x-workspace-id"]);
|
|
7801
|
+
const projectId = normalizeHeaderValue(headers?.["x-contextstream-project-id"]) || normalizeHeaderValue(headers?.["x-project-id"]);
|
|
7802
|
+
if (token) {
|
|
7803
|
+
if (tokenType === "jwt") {
|
|
7804
|
+
return { jwt: token, workspaceId, projectId };
|
|
7805
|
+
}
|
|
7806
|
+
return { apiKey: token, workspaceId, projectId };
|
|
7807
|
+
}
|
|
7808
|
+
if (existing?.apiKey || existing?.jwt) {
|
|
7809
|
+
return {
|
|
7810
|
+
apiKey: existing.apiKey,
|
|
7811
|
+
jwt: existing.jwt,
|
|
7812
|
+
workspaceId: workspaceId ?? existing.workspaceId,
|
|
7813
|
+
projectId: projectId ?? existing.projectId
|
|
7814
|
+
};
|
|
7815
|
+
}
|
|
7816
|
+
if (!workspaceId && !projectId) return null;
|
|
7817
|
+
return { workspaceId, projectId };
|
|
7818
|
+
}
|
|
7775
7819
|
var LIGHT_TOOLSET = /* @__PURE__ */ new Set([
|
|
7776
7820
|
// Core session tools (13)
|
|
7777
7821
|
"session_init",
|
|
@@ -8149,29 +8193,35 @@ function registerTools(server, client, sessionManager) {
|
|
|
8149
8193
|
}
|
|
8150
8194
|
function wrapWithAutoContext(toolName, handler) {
|
|
8151
8195
|
if (!sessionManager) {
|
|
8152
|
-
return
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
if (r.content && r.content.length > 0 && r.content[0].type === "text") {
|
|
8168
|
-
r.content[0] = {
|
|
8169
|
-
...r.content[0],
|
|
8170
|
-
text: contextPrefix + "--- Tool Response ---\n\n" + r.content[0].text
|
|
8171
|
-
};
|
|
8196
|
+
return async (input, extra) => {
|
|
8197
|
+
const authOverride = resolveAuthOverride(extra);
|
|
8198
|
+
return runWithAuthOverride(authOverride, async () => handler(input, extra));
|
|
8199
|
+
};
|
|
8200
|
+
}
|
|
8201
|
+
return async (input, extra) => {
|
|
8202
|
+
const authOverride = resolveAuthOverride(extra);
|
|
8203
|
+
return runWithAuthOverride(authOverride, async () => {
|
|
8204
|
+
const skipAutoInit = toolName === "session_init";
|
|
8205
|
+
let contextPrefix = "";
|
|
8206
|
+
if (!skipAutoInit) {
|
|
8207
|
+
const autoInitResult = await sessionManager.autoInitialize();
|
|
8208
|
+
if (autoInitResult) {
|
|
8209
|
+
contextPrefix = autoInitResult.contextSummary + "\n\n";
|
|
8210
|
+
}
|
|
8172
8211
|
}
|
|
8173
|
-
|
|
8174
|
-
|
|
8212
|
+
sessionManager.warnIfContextSmartNotCalled(toolName);
|
|
8213
|
+
const result = await handler(input, extra);
|
|
8214
|
+
if (contextPrefix && result && typeof result === "object") {
|
|
8215
|
+
const r = result;
|
|
8216
|
+
if (r.content && r.content.length > 0 && r.content[0].type === "text") {
|
|
8217
|
+
r.content[0] = {
|
|
8218
|
+
...r.content[0],
|
|
8219
|
+
text: contextPrefix + "--- Tool Response ---\n\n" + r.content[0].text
|
|
8220
|
+
};
|
|
8221
|
+
}
|
|
8222
|
+
}
|
|
8223
|
+
return result;
|
|
8224
|
+
});
|
|
8175
8225
|
};
|
|
8176
8226
|
}
|
|
8177
8227
|
function registerTool(name, config, handler) {
|
|
@@ -8187,11 +8237,11 @@ function registerTools(server, client, sessionManager) {
|
|
|
8187
8237
|
|
|
8188
8238
|
Access: ${accessLabel}${showUpgrade ? ` (upgrade: ${upgradeUrl})` : ""}`
|
|
8189
8239
|
};
|
|
8190
|
-
const safeHandler = async (input) => {
|
|
8240
|
+
const safeHandler = async (input, extra) => {
|
|
8191
8241
|
try {
|
|
8192
8242
|
const gated = await gateIfProTool(name);
|
|
8193
8243
|
if (gated) return gated;
|
|
8194
|
-
return await handler(input);
|
|
8244
|
+
return await handler(input, extra);
|
|
8195
8245
|
} catch (error) {
|
|
8196
8246
|
const errorMessage = error?.message || String(error);
|
|
8197
8247
|
const errorDetails = error?.body || error?.details || null;
|
|
@@ -11407,6 +11457,163 @@ var SessionManager = class {
|
|
|
11407
11457
|
}
|
|
11408
11458
|
};
|
|
11409
11459
|
|
|
11460
|
+
// src/http-gateway.ts
|
|
11461
|
+
import { createServer } from "node:http";
|
|
11462
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11463
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11464
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
11465
|
+
var HOST = process.env.MCP_HTTP_HOST || "0.0.0.0";
|
|
11466
|
+
var PORT = Number.parseInt(process.env.MCP_HTTP_PORT || "8787", 10);
|
|
11467
|
+
var MCP_PATH = process.env.MCP_HTTP_PATH || "/mcp";
|
|
11468
|
+
var REQUIRE_AUTH = (process.env.MCP_HTTP_REQUIRE_AUTH || "true").toLowerCase() !== "false";
|
|
11469
|
+
var ENABLE_JSON_RESPONSE = (process.env.MCP_HTTP_JSON_RESPONSE || "false").toLowerCase() === "true";
|
|
11470
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
11471
|
+
function normalizeHeaderValue2(value) {
|
|
11472
|
+
if (!value) return void 0;
|
|
11473
|
+
return Array.isArray(value) ? value[0] : value;
|
|
11474
|
+
}
|
|
11475
|
+
function looksLikeJwt(token) {
|
|
11476
|
+
const parts = token.split(".");
|
|
11477
|
+
return parts.length === 3 && parts.every((part) => part.length > 0);
|
|
11478
|
+
}
|
|
11479
|
+
function extractAuthOverride(req, fallback) {
|
|
11480
|
+
const apiKey = normalizeHeaderValue2(req.headers["x-api-key"]) || normalizeHeaderValue2(req.headers["x-contextstream-api-key"]);
|
|
11481
|
+
const jwtHeader = normalizeHeaderValue2(req.headers["x-contextstream-jwt"]);
|
|
11482
|
+
const authHeader = normalizeHeaderValue2(req.headers["authorization"]);
|
|
11483
|
+
let token;
|
|
11484
|
+
if (authHeader) {
|
|
11485
|
+
const [type, ...rest] = authHeader.split(" ");
|
|
11486
|
+
if (type && type.toLowerCase() === "bearer" && rest.length > 0) {
|
|
11487
|
+
token = rest.join(" ").trim();
|
|
11488
|
+
}
|
|
11489
|
+
}
|
|
11490
|
+
const workspaceId = normalizeHeaderValue2(req.headers["x-contextstream-workspace-id"]) || normalizeHeaderValue2(req.headers["x-workspace-id"]);
|
|
11491
|
+
const projectId = normalizeHeaderValue2(req.headers["x-contextstream-project-id"]) || normalizeHeaderValue2(req.headers["x-project-id"]);
|
|
11492
|
+
if (jwtHeader) {
|
|
11493
|
+
return { override: { jwt: jwtHeader, workspaceId, projectId }, tokenType: "jwt" };
|
|
11494
|
+
}
|
|
11495
|
+
if (apiKey) {
|
|
11496
|
+
return { override: { apiKey, workspaceId, projectId }, tokenType: "api_key" };
|
|
11497
|
+
}
|
|
11498
|
+
if (token) {
|
|
11499
|
+
if (looksLikeJwt(token)) {
|
|
11500
|
+
return { override: { jwt: token, workspaceId, projectId }, tokenType: "jwt" };
|
|
11501
|
+
}
|
|
11502
|
+
return { override: { apiKey: token, workspaceId, projectId }, tokenType: "api_key" };
|
|
11503
|
+
}
|
|
11504
|
+
if (workspaceId || projectId) {
|
|
11505
|
+
return { override: { workspaceId, projectId }, tokenType: void 0 };
|
|
11506
|
+
}
|
|
11507
|
+
return { override: fallback, tokenType: void 0 };
|
|
11508
|
+
}
|
|
11509
|
+
function attachAuthInfo(req, token, tokenType) {
|
|
11510
|
+
req.auth = {
|
|
11511
|
+
token,
|
|
11512
|
+
clientId: "contextstream-mcp-http",
|
|
11513
|
+
scopes: [],
|
|
11514
|
+
extra: { tokenType }
|
|
11515
|
+
};
|
|
11516
|
+
}
|
|
11517
|
+
async function createSession() {
|
|
11518
|
+
const config = loadConfig();
|
|
11519
|
+
const client = new ContextStreamClient(config);
|
|
11520
|
+
const server = new McpServer({
|
|
11521
|
+
name: "contextstream-mcp",
|
|
11522
|
+
version: VERSION
|
|
11523
|
+
});
|
|
11524
|
+
const sessionManager = new SessionManager(server, client);
|
|
11525
|
+
registerTools(server, client, sessionManager);
|
|
11526
|
+
registerResources(server, client, config.apiUrl);
|
|
11527
|
+
const transport = new StreamableHTTPServerTransport({
|
|
11528
|
+
sessionIdGenerator: () => randomUUID2(),
|
|
11529
|
+
enableJsonResponse: ENABLE_JSON_RESPONSE,
|
|
11530
|
+
onsessionclosed: (sessionId) => {
|
|
11531
|
+
sessions.delete(sessionId);
|
|
11532
|
+
}
|
|
11533
|
+
});
|
|
11534
|
+
await server.connect(transport);
|
|
11535
|
+
const now = Date.now();
|
|
11536
|
+
return {
|
|
11537
|
+
server,
|
|
11538
|
+
transport,
|
|
11539
|
+
sessionManager,
|
|
11540
|
+
client,
|
|
11541
|
+
authOverride: null,
|
|
11542
|
+
createdAt: now,
|
|
11543
|
+
lastSeenAt: now
|
|
11544
|
+
};
|
|
11545
|
+
}
|
|
11546
|
+
function writeJson(res, status, payload) {
|
|
11547
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
11548
|
+
res.end(JSON.stringify(payload));
|
|
11549
|
+
}
|
|
11550
|
+
async function handleMcpRequest(req, res) {
|
|
11551
|
+
const sessionId = normalizeHeaderValue2(req.headers["mcp-session-id"]);
|
|
11552
|
+
const existingSession = sessionId ? sessions.get(sessionId) : void 0;
|
|
11553
|
+
const { override, tokenType } = extractAuthOverride(req, existingSession?.authOverride ?? null);
|
|
11554
|
+
const token = override?.jwt || override?.apiKey;
|
|
11555
|
+
if (REQUIRE_AUTH && !token) {
|
|
11556
|
+
writeJson(res, 401, { error: "Missing authorization token. Use Authorization: Bearer <API_KEY> or X-API-Key." });
|
|
11557
|
+
return;
|
|
11558
|
+
}
|
|
11559
|
+
if (sessionId && !existingSession) {
|
|
11560
|
+
writeJson(res, 404, { error: "Unknown MCP session. Re-initialize your MCP connection." });
|
|
11561
|
+
return;
|
|
11562
|
+
}
|
|
11563
|
+
let entry = existingSession;
|
|
11564
|
+
if (!entry) {
|
|
11565
|
+
entry = await createSession();
|
|
11566
|
+
}
|
|
11567
|
+
entry.lastSeenAt = Date.now();
|
|
11568
|
+
if (override) {
|
|
11569
|
+
entry.authOverride = override;
|
|
11570
|
+
}
|
|
11571
|
+
if (token && tokenType) {
|
|
11572
|
+
attachAuthInfo(req, token, tokenType);
|
|
11573
|
+
}
|
|
11574
|
+
await runWithAuthOverride(override ?? null, async () => {
|
|
11575
|
+
await entry.transport.handleRequest(req, res);
|
|
11576
|
+
});
|
|
11577
|
+
const newSessionId = entry.transport.sessionId;
|
|
11578
|
+
if (!existingSession && newSessionId) {
|
|
11579
|
+
sessions.set(newSessionId, entry);
|
|
11580
|
+
}
|
|
11581
|
+
}
|
|
11582
|
+
async function runHttpGateway() {
|
|
11583
|
+
const config = loadConfig();
|
|
11584
|
+
console.error(`[ContextStream] MCP HTTP gateway v${VERSION} starting...`);
|
|
11585
|
+
console.error(`[ContextStream] API URL: ${config.apiUrl}`);
|
|
11586
|
+
console.error(`[ContextStream] Auth: ${config.apiKey ? "API Key" : config.jwt ? "JWT" : "Header-based"}`);
|
|
11587
|
+
console.error(`[ContextStream] MCP endpoint: http://${HOST}:${PORT}${MCP_PATH}`);
|
|
11588
|
+
const server = createServer(async (req, res) => {
|
|
11589
|
+
if (!req.url) {
|
|
11590
|
+
writeJson(res, 404, { error: "Not found" });
|
|
11591
|
+
return;
|
|
11592
|
+
}
|
|
11593
|
+
const url = new URL(req.url, `http://${req.headers.host || "localhost"}`);
|
|
11594
|
+
if (url.pathname === "/health") {
|
|
11595
|
+
writeJson(res, 200, { status: "ok", version: VERSION });
|
|
11596
|
+
return;
|
|
11597
|
+
}
|
|
11598
|
+
if (url.pathname !== MCP_PATH) {
|
|
11599
|
+
writeJson(res, 404, { error: "Not found" });
|
|
11600
|
+
return;
|
|
11601
|
+
}
|
|
11602
|
+
if (!["GET", "POST", "DELETE"].includes(req.method || "")) {
|
|
11603
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
11604
|
+
return;
|
|
11605
|
+
}
|
|
11606
|
+
try {
|
|
11607
|
+
await handleMcpRequest(req, res);
|
|
11608
|
+
} catch (error) {
|
|
11609
|
+
writeJson(res, 500, { error: error?.message || "Internal server error" });
|
|
11610
|
+
}
|
|
11611
|
+
});
|
|
11612
|
+
server.listen(PORT, HOST, () => {
|
|
11613
|
+
console.error(`[ContextStream] MCP HTTP gateway listening on http://${HOST}:${PORT}${MCP_PATH}`);
|
|
11614
|
+
});
|
|
11615
|
+
}
|
|
11616
|
+
|
|
11410
11617
|
// src/index.ts
|
|
11411
11618
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
11412
11619
|
import { homedir as homedir4 } from "os";
|
|
@@ -12475,20 +12682,28 @@ Usage:
|
|
|
12475
12682
|
npx -y @contextstream/mcp-server
|
|
12476
12683
|
contextstream-mcp
|
|
12477
12684
|
contextstream-mcp setup
|
|
12685
|
+
contextstream-mcp http
|
|
12478
12686
|
|
|
12479
12687
|
Commands:
|
|
12480
12688
|
setup Interactive onboarding wizard (rules + workspace mapping)
|
|
12689
|
+
http Run HTTP MCP gateway (streamable HTTP transport)
|
|
12481
12690
|
|
|
12482
12691
|
Environment variables:
|
|
12483
12692
|
CONTEXTSTREAM_API_URL Base API URL (e.g. https://api.contextstream.io)
|
|
12484
12693
|
CONTEXTSTREAM_API_KEY API key for authentication (or use CONTEXTSTREAM_JWT)
|
|
12485
12694
|
CONTEXTSTREAM_JWT JWT for authentication (alternative to API key)
|
|
12695
|
+
CONTEXTSTREAM_ALLOW_HEADER_AUTH Allow header-based auth when no API key/JWT is set
|
|
12486
12696
|
CONTEXTSTREAM_WORKSPACE_ID Optional default workspace ID
|
|
12487
12697
|
CONTEXTSTREAM_PROJECT_ID Optional default project ID
|
|
12488
12698
|
CONTEXTSTREAM_TOOLSET Tool mode: light|standard|complete (default: standard)
|
|
12489
12699
|
CONTEXTSTREAM_TOOL_ALLOWLIST Optional comma-separated tool names to expose (overrides toolset)
|
|
12490
12700
|
CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
|
|
12491
12701
|
CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
|
|
12702
|
+
MCP_HTTP_HOST HTTP gateway host (default: 0.0.0.0)
|
|
12703
|
+
MCP_HTTP_PORT HTTP gateway port (default: 8787)
|
|
12704
|
+
MCP_HTTP_PATH HTTP gateway path (default: /mcp)
|
|
12705
|
+
MCP_HTTP_REQUIRE_AUTH Require auth headers for HTTP gateway (default: true)
|
|
12706
|
+
MCP_HTTP_JSON_RESPONSE Enable JSON responses (default: false)
|
|
12492
12707
|
|
|
12493
12708
|
Examples:
|
|
12494
12709
|
CONTEXTSTREAM_API_URL="https://api.contextstream.io" \\
|
|
@@ -12517,9 +12732,16 @@ async function main() {
|
|
|
12517
12732
|
await runSetupWizard(args.slice(1));
|
|
12518
12733
|
return;
|
|
12519
12734
|
}
|
|
12735
|
+
if (args[0] === "http") {
|
|
12736
|
+
if (!process.env.CONTEXTSTREAM_API_KEY && !process.env.CONTEXTSTREAM_JWT && !process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH) {
|
|
12737
|
+
process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH = "true";
|
|
12738
|
+
}
|
|
12739
|
+
await runHttpGateway();
|
|
12740
|
+
return;
|
|
12741
|
+
}
|
|
12520
12742
|
const config = loadConfig();
|
|
12521
12743
|
const client = new ContextStreamClient(config);
|
|
12522
|
-
const server = new
|
|
12744
|
+
const server = new McpServer2({
|
|
12523
12745
|
name: "contextstream-mcp",
|
|
12524
12746
|
version: VERSION
|
|
12525
12747
|
});
|
package/dist/test-server.js
CHANGED
|
@@ -4057,16 +4057,19 @@ var configSchema = external_exports.object({
|
|
|
4057
4057
|
jwt: external_exports.string().min(1).optional(),
|
|
4058
4058
|
defaultWorkspaceId: external_exports.string().uuid().optional(),
|
|
4059
4059
|
defaultProjectId: external_exports.string().uuid().optional(),
|
|
4060
|
-
userAgent: external_exports.string().default("contextstream-mcp/0.1.0")
|
|
4060
|
+
userAgent: external_exports.string().default("contextstream-mcp/0.1.0"),
|
|
4061
|
+
allowHeaderAuth: external_exports.boolean().optional()
|
|
4061
4062
|
});
|
|
4062
4063
|
function loadConfig() {
|
|
4064
|
+
const allowHeaderAuth = process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "1" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "true" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "yes";
|
|
4063
4065
|
const parsed = configSchema.safeParse({
|
|
4064
4066
|
apiUrl: process.env.CONTEXTSTREAM_API_URL,
|
|
4065
4067
|
apiKey: process.env.CONTEXTSTREAM_API_KEY,
|
|
4066
4068
|
jwt: process.env.CONTEXTSTREAM_JWT,
|
|
4067
4069
|
defaultWorkspaceId: process.env.CONTEXTSTREAM_WORKSPACE_ID,
|
|
4068
4070
|
defaultProjectId: process.env.CONTEXTSTREAM_PROJECT_ID,
|
|
4069
|
-
userAgent: process.env.CONTEXTSTREAM_USER_AGENT
|
|
4071
|
+
userAgent: process.env.CONTEXTSTREAM_USER_AGENT,
|
|
4072
|
+
allowHeaderAuth
|
|
4070
4073
|
});
|
|
4071
4074
|
if (!parsed.success) {
|
|
4072
4075
|
const missing = parsed.error.errors.map((e) => e.path.join(".")).join(", ");
|
|
@@ -4074,8 +4077,8 @@ function loadConfig() {
|
|
|
4074
4077
|
`Invalid configuration. Set CONTEXTSTREAM_API_URL (and API key or JWT). Missing/invalid: ${missing}`
|
|
4075
4078
|
);
|
|
4076
4079
|
}
|
|
4077
|
-
if (!parsed.data.apiKey && !parsed.data.jwt) {
|
|
4078
|
-
throw new Error("Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication.");
|
|
4080
|
+
if (!parsed.data.apiKey && !parsed.data.jwt && !parsed.data.allowHeaderAuth) {
|
|
4081
|
+
throw new Error("Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication (or CONTEXTSTREAM_ALLOW_HEADER_AUTH=true for header-based auth).");
|
|
4079
4082
|
}
|
|
4080
4083
|
return parsed.data;
|
|
4081
4084
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contextstream/mcp-server",
|
|
3
3
|
"mcpName": "io.github.contextstreamio/mcp-server",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.63",
|
|
5
5
|
"description": "MCP server exposing ContextStream public API - code context, memory, search, and AI tools for developers",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|