@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 +4 -2
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.mjs +2 -2
- package/dist/packem_shared/{TOOL_DEFINITIONS-Dpiu38ji.mjs → READ_ONLY_TOOL_DEFINITIONS-DV2VkuuU.mjs} +35 -4
- package/dist/packem_shared/{connectStdio-C_mvQBs2.mjs → connectStdio-nl-Tt_T1.mjs} +4 -3
- package/package.json +2 -2
package/dist/bin.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { connectStdio } from './packem_shared/connectStdio-
|
|
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
|
|
29
|
-
declare const
|
|
30
|
-
|
|
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
|
|
29
|
-
declare const
|
|
30
|
-
|
|
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-
|
|
2
|
-
export {
|
|
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';
|
package/dist/packem_shared/{TOOL_DEFINITIONS-Dpiu38ji.mjs → READ_ONLY_TOOL_DEFINITIONS-DV2VkuuU.mjs}
RENAMED
|
@@ -15,7 +15,7 @@ const FUNCTION_PATH_INPUT_SCHEMA = {
|
|
|
15
15
|
required: ["functionPath"],
|
|
16
16
|
type: "object"
|
|
17
17
|
};
|
|
18
|
-
const
|
|
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
|
|
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 {
|
|
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 {
|
|
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: [...
|
|
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.
|
|
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.
|
|
52
|
+
"@lunora/client": "1.0.0-alpha.15",
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|