+29
packages/mcp/env.ts
+29
packages/mcp/env.ts
···
1
+
import { getLogger } from "@logtape/logtape";
2
+
import type { ConsumerOptions } from "@cistern/consumer";
3
+
4
+
export function collectOptions(): ConsumerOptions {
5
+
const logger = getLogger(["cistern", "mcp"]);
6
+
const handle = Deno.env.get("CISTERN_MCP_HANDLE");
7
+
const appPassword = Deno.env.get("CISTERN_MCP_APP_PASSWORD");
8
+
9
+
if (!handle || !appPassword) {
10
+
logger.error(
11
+
"CISTERN_MCP_HANDLE or CISTERN_MCP_APP_PASSWORD are not set in the environment",
12
+
);
13
+
return Deno.exit(1);
14
+
}
15
+
16
+
const privateKey = Deno.env.get("CISTERN_MCP_PRIVATE_KEY");
17
+
const publicKeyUri = Deno.env.get("CISTERN_MCP_PUBLIC_KEY_URI");
18
+
19
+
return {
20
+
appPassword,
21
+
handle,
22
+
keypair: privateKey && publicKeyUri
23
+
? {
24
+
privateKey,
25
+
publicKey: publicKeyUri,
26
+
}
27
+
: undefined,
28
+
};
29
+
}
+5
-1
packages/mcp/hono.ts
+5
-1
packages/mcp/hono.ts
···
1
1
import { Hono } from "hono";
2
2
import { cors } from "hono/cors";
3
+
import { createConsumer } from "@cistern/consumer";
3
4
import { getLogger, withContext } from "@logtape/logtape";
4
5
import { toFetchResponse, toReqRes } from "fetch-to-node";
5
6
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
+
import { collectOptions } from "./env.ts";
6
8
import { createServer } from "./server.ts";
7
9
8
10
export function createApp() {
···
78
80
} else {
79
81
logger.info("creating new session {sessionId}", { sessionId });
80
82
81
-
const server = createServer();
83
+
const options = collectOptions();
84
+
const consumer = await createConsumer(options);
85
+
const server = createServer(consumer);
82
86
83
87
session = new StreamableHTTPServerTransport({
84
88
sessionIdGenerator: () => sessionId,
+8
-1
packages/mcp/index.ts
+8
-1
packages/mcp/index.ts
···
1
1
import { parseArgs } from "@std/cli";
2
+
import { createConsumer } from "@cistern/consumer";
2
3
import { AsyncLocalStorage } from "node:async_hooks";
3
4
import { configure, getConsoleSink, getLogger } from "@logtape/logtape";
4
5
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
6
6
7
import { createServer } from "./server.ts";
7
8
import { createApp } from "./hono.ts";
9
+
import { collectOptions } from "./env.ts";
8
10
9
11
async function main() {
10
12
await configure({
···
32
34
if (!args.http) {
33
35
logger.info("starting in stdio mode");
34
36
37
+
const options = collectOptions();
38
+
const consumer = await createConsumer(options);
35
39
const transport = new StdioServerTransport();
36
-
const server = createServer();
40
+
const server = createServer(consumer);
37
41
38
42
await server.connect(transport);
39
43
} else {
40
44
logger.info("starting in streamable HTTP mode");
45
+
46
+
// Validate environment before starting the server
47
+
collectOptions();
41
48
42
49
const app = createApp();
43
50
+2
-1
packages/mcp/server.ts
+2
-1
packages/mcp/server.ts
···
1
1
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
import { getLogger } from "@logtape/logtape";
3
3
import { z } from "zod";
4
+
import type { Consumer } from "@cistern/consumer";
4
5
5
-
export function createServer() {
6
+
export function createServer(consumer: Consumer) {
6
7
const logger = getLogger("cistern-mcp");
7
8
const server = new McpServer({
8
9
name: "cistern-mcp",