@lunora/mcp 1.0.0-alpha.13 → 1.0.0-alpha.15

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/bin.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { connectStdio } from './packem_shared/connectStdio-C_mvQBs2.mjs';
2
+ import { connectStdio } from './packem_shared/connectStdio-nl-Tt_T1.mjs';
3
3
 
4
+ const ENABLED_ENV_VALUES = /* @__PURE__ */ new Set(["1", "on", "true", "yes"]);
5
+ const isEnvEnabled = (value) => value !== void 0 && ENABLED_ENV_VALUES.has(value.trim().toLowerCase());
4
6
  class BinError extends Error {
5
7
  code;
6
8
  constructor(message, code) {
@@ -20,7 +22,7 @@ const runBin = async (environment, dependencies = {}) => {
20
22
  throw new BinError("LUNORA_URL environment variable is required", 1);
21
23
  }
22
24
  try {
23
- await connect({ token: environment.LUNORA_ADMIN_TOKEN, url });
25
+ await connect({ allowWrites: isEnvEnabled(environment.LUNORA_MCP_ALLOW_WRITES), token: environment.LUNORA_ADMIN_TOKEN, url });
24
26
  } catch (error) {
25
27
  const message = error instanceof Error ? error.message : String(error);
26
28
  writeError(`lunora-mcp: failed to start — ${message}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
2
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  interface LunoraMcpServerOptions {
4
+ allowWrites?: boolean;
4
5
  client?: LunoraClient;
5
6
  fetch?: typeof fetch;
6
7
  token?: string;
@@ -25,6 +26,8 @@ interface ToolResult {
25
26
  }[];
26
27
  isError?: boolean;
27
28
  }
28
- declare const TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
29
- declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>) => Promise<ToolResult>;
30
- export { type LunoraMcpServerOptions, TOOL_DEFINITIONS, type ToolDefinition, type ToolInputSchema, type ToolResult, callTool, connectStdio, createLunoraMcpServer };
29
+ declare const READ_ONLY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
30
+ declare const WRITE_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
31
+ declare const toolDefinitions: (allowWrites: boolean) => ReadonlyArray<ToolDefinition>;
32
+ declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean) => Promise<ToolResult>;
33
+ export { type LunoraMcpServerOptions, READ_ONLY_TOOL_DEFINITIONS, type ToolDefinition, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, callTool, connectStdio, createLunoraMcpServer, toolDefinitions };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
2
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  interface LunoraMcpServerOptions {
4
+ allowWrites?: boolean;
4
5
  client?: LunoraClient;
5
6
  fetch?: typeof fetch;
6
7
  token?: string;
@@ -25,6 +26,8 @@ interface ToolResult {
25
26
  }[];
26
27
  isError?: boolean;
27
28
  }
28
- declare const TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
29
- declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>) => Promise<ToolResult>;
30
- export { type LunoraMcpServerOptions, TOOL_DEFINITIONS, type ToolDefinition, type ToolInputSchema, type ToolResult, callTool, connectStdio, createLunoraMcpServer };
29
+ declare const READ_ONLY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
30
+ declare const WRITE_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
31
+ declare const toolDefinitions: (allowWrites: boolean) => ReadonlyArray<ToolDefinition>;
32
+ declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean) => Promise<ToolResult>;
33
+ export { type LunoraMcpServerOptions, READ_ONLY_TOOL_DEFINITIONS, type ToolDefinition, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, callTool, connectStdio, createLunoraMcpServer, toolDefinitions };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export { connectStdio, createLunoraMcpServer } from './packem_shared/connectStdio-C_mvQBs2.mjs';
2
- export { TOOL_DEFINITIONS, callTool } from './packem_shared/TOOL_DEFINITIONS-Dpiu38ji.mjs';
1
+ export { connectStdio, createLunoraMcpServer } from './packem_shared/connectStdio-nl-Tt_T1.mjs';
2
+ export { READ_ONLY_TOOL_DEFINITIONS, WRITE_TOOL_DEFINITIONS, callTool, toolDefinitions } from './packem_shared/READ_ONLY_TOOL_DEFINITIONS-DV2VkuuU.mjs';
@@ -15,7 +15,7 @@ const FUNCTION_PATH_INPUT_SCHEMA = {
15
15
  required: ["functionPath"],
16
16
  type: "object"
17
17
  };
18
- const TOOL_DEFINITIONS = [
18
+ const READ_ONLY_TOOL_DEFINITIONS = [
19
19
  {
20
20
  description: "List the deployment's public functions (queries, mutations, actions) with their kinds.",
21
21
  inputSchema: NO_INPUT_SCHEMA,
@@ -35,7 +35,9 @@ const TOOL_DEFINITIONS = [
35
35
  description: "Run a query and return its result. Read-only.",
36
36
  inputSchema: RUN_INPUT_SCHEMA,
37
37
  name: "lunora_run_query"
38
- },
38
+ }
39
+ ];
40
+ const WRITE_TOOL_DEFINITIONS = [
39
41
  {
40
42
  description: "Run a mutation and return its result. Writes data — use with care.",
41
43
  inputSchema: RUN_INPUT_SCHEMA,
@@ -47,6 +49,14 @@ const TOOL_DEFINITIONS = [
47
49
  name: "lunora_run_action"
48
50
  }
49
51
  ];
52
+ const WRITE_TOOL_NAMES = new Set(WRITE_TOOL_DEFINITIONS.map((tool) => tool.name));
53
+ const toolDefinitions = (allowWrites) => (
54
+ // Fail closed: only the boolean `true` opts in. These are exported helpers, so
55
+ // an env-plumbed/JS caller could pass a truthy string like `"false"`/`"0"` —
56
+ // the explicit `=== true` guards that despite the declared `boolean` type.
57
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-boolean-literal-compare -- intentional runtime guard at an exported API boundary against non-boolean callers
58
+ allowWrites === true ? [...READ_ONLY_TOOL_DEFINITIONS, ...WRITE_TOOL_DEFINITIONS] : READ_ONLY_TOOL_DEFINITIONS
59
+ );
50
60
  const readFunctionPath = (input) => {
51
61
  const { functionPath } = input;
52
62
  if (typeof functionPath !== "string" || functionPath.length === 0) {
@@ -69,8 +79,26 @@ const ok = (value) => {
69
79
  const text = value === void 0 ? "null" : JSON.stringify(value, void 0, 2);
70
80
  return { content: [{ text, type: "text" }] };
71
81
  };
72
- const callTool = async (client, name, input) => {
82
+ const assertRunnable = async (client, functionPath, expectedKind) => {
83
+ const functions = await client.listFunctions();
84
+ const descriptor = functions.find((function_) => function_.path === functionPath);
85
+ if (descriptor === void 0) {
86
+ throw new Error(`function not found or not public: ${functionPath}`);
87
+ }
88
+ if (descriptor.kind !== expectedKind) {
89
+ throw new Error(`function ${functionPath} is a ${descriptor.kind}, not a ${expectedKind}`);
90
+ }
91
+ };
92
+ const callTool = async (client, name, input, allowWrites = false) => {
73
93
  try {
94
+ if (allowWrites !== true && WRITE_TOOL_NAMES.has(name)) {
95
+ return {
96
+ content: [
97
+ { text: `tool "${name}" is disabled: this MCP server is read-only. Enable writes with the LUNORA_MCP_ALLOW_WRITES env var.`, type: "text" }
98
+ ],
99
+ isError: true
100
+ };
101
+ }
74
102
  switch (name) {
75
103
  case "lunora_get_function_schema": {
76
104
  const functionPath = readFunctionPath(input);
@@ -89,14 +117,17 @@ const callTool = async (client, name, input) => {
89
117
  }
90
118
  case "lunora_run_action": {
91
119
  const { args, functionPath, shardKey } = readRunArguments(input);
120
+ await assertRunnable(client, functionPath, "action");
92
121
  return ok(await client.action(reference(functionPath), args, { shardKey }));
93
122
  }
94
123
  case "lunora_run_mutation": {
95
124
  const { args, functionPath, shardKey } = readRunArguments(input);
125
+ await assertRunnable(client, functionPath, "mutation");
96
126
  return ok(await client.mutation(reference(functionPath), args, { shardKey }));
97
127
  }
98
128
  case "lunora_run_query": {
99
129
  const { args, functionPath, shardKey } = readRunArguments(input);
130
+ await assertRunnable(client, functionPath, "query");
100
131
  return ok(await client.query(reference(functionPath), args, { shardKey }));
101
132
  }
102
133
  default: {
@@ -109,4 +140,4 @@ const callTool = async (client, name, input) => {
109
140
  }
110
141
  };
111
142
 
112
- export { TOOL_DEFINITIONS, callTool };
143
+ export { READ_ONLY_TOOL_DEFINITIONS, WRITE_TOOL_DEFINITIONS, callTool, toolDefinitions };
@@ -5,7 +5,7 @@ import { LunoraClient } from '@lunora/client';
5
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
6
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
7
7
  import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
8
- import { TOOL_DEFINITIONS, callTool } from './TOOL_DEFINITIONS-Dpiu38ji.mjs';
8
+ import { toolDefinitions, callTool } from './READ_ONLY_TOOL_DEFINITIONS-DV2VkuuU.mjs';
9
9
 
10
10
  const resolveVersion = () => {
11
11
  try {
@@ -45,12 +45,13 @@ const resolveClient = (options) => {
45
45
  };
46
46
  const createLunoraMcpServer = (options) => {
47
47
  const client = resolveClient(options);
48
+ const allowWrites = options.allowWrites ?? false;
48
49
  const server = new Server(SERVER_INFO, { capabilities: { tools: {} } });
49
50
  server.setRequestHandler(ListToolsRequestSchema, () => {
50
- return { tools: [...TOOL_DEFINITIONS] };
51
+ return { tools: [...toolDefinitions(allowWrites)] };
51
52
  });
52
53
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
53
- const result = await callTool(client, request.params.name, request.params.arguments ?? {});
54
+ const result = await callTool(client, request.params.name, request.params.arguments ?? {}, allowWrites);
54
55
  return result;
55
56
  });
56
57
  return server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/mcp",
3
- "version": "1.0.0-alpha.13",
3
+ "version": "1.0.0-alpha.15",
4
4
  "description": "Model Context Protocol server exposing a Lunora deployment to AI agents",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -49,7 +49,7 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@lunora/client": "1.0.0-alpha.13",
52
+ "@lunora/client": "1.0.0-alpha.15",
53
53
  "@modelcontextprotocol/sdk": "^1.29.0"
54
54
  },
55
55
  "engines": {