@lunora/mcp 1.0.0-alpha.60 → 1.0.0-alpha.61

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/README.md CHANGED
@@ -45,16 +45,21 @@ Part of the [Lunora](https://github.com/anolilab/lunora) framework — a type-sa
45
45
 
46
46
  ## Tools
47
47
 
48
- | Tool | Description |
49
- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
- | `lunora_list_functions` | List the deployment's public functions (queries, mutations, actions) with their kinds. |
51
- | `lunora_list_tables` | List the deployment's `.global()` tables with their row counts. |
52
- | `lunora_get_function_schema` | Return a function's argument descriptors and kind by path, so a caller can construct a valid arguments object. |
53
- | `lunora_run_query` | Run a query and return its result. Read-only. |
54
- | `lunora_run_mutation` | Run a mutation and return its result. Writes data — use with care. |
55
- | `lunora_run_action` | Run an action and return its result. May call external services. |
56
- | `agent_<name>` | Start a durable [`@lunora/agent`](https://www.npmjs.com/package/@lunora/agent) run and await its answer. One tool per exposed agent. Requires agents enabled. |
57
- | `lunora_agent_status` | Poll a running agent by `threadKey` and return its answer once finished. Requires agents enabled. |
48
+ | Tool | Description |
49
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | `lunora_list_functions` | List the deployment's public functions (queries, mutations, actions) with their kinds. |
51
+ | `lunora_list_tables` | List the deployment's `.global()` tables with their row counts. |
52
+ | `lunora_get_function_schema` | Return a function's argument descriptors and kind by path, so a caller can construct a valid arguments object. |
53
+ | `lunora_run_query` | Run a query and return its result. Read-only. |
54
+ | `lunora_run_mutation` | Run a mutation and return its result. Writes data — use with care. |
55
+ | `lunora_run_action` | Run an action and return its result. May call external services. |
56
+ | `lunora_get_logs` | Read the deployment's recent log entries (newest first). Requires an admin token. |
57
+ | `lunora_get_issues` | List errors grouped into Issues by fingerprint, with counts and triage status. Requires an admin token. |
58
+ | `lunora_get_advisories` | List the deployment's schema/query advisories. Requires an admin token. |
59
+ | `lunora_get_query_insights` | Per-statement execution counts and latency over a recent window. Requires an admin token. |
60
+ | `lunora_get_migration_status` | Which migrations are applied and which are pending. Requires an admin token. |
61
+ | `agent_<name>` | Start a durable [`@lunora/agent`](https://www.npmjs.com/package/@lunora/agent) run and await its answer. One tool per exposed agent. Requires agents enabled. |
62
+ | `lunora_agent_status` | Poll a running agent by `threadKey` and return its answer once finished. Requires agents enabled. |
58
63
 
59
64
  ### Recommended agent flow
60
65
 
@@ -65,6 +70,25 @@ Part of the [Lunora](https://github.com/anolilab/lunora) framework — a type-sa
65
70
  → call the function with a well-formed arguments object
66
71
  ```
67
72
 
73
+ ### Observability tools (privileged)
74
+
75
+ The five `lunora_get_*` observability tools are read-only, but they surface the
76
+ deployment's **operational data** — log lines, request metadata, and grouped
77
+ error messages, all of which may contain user data, and all of which land in the
78
+ model's context (and therefore at its provider). They are exposed **only when an
79
+ admin token resolved**: without one they are omitted from `ListTools` entirely
80
+ and refused at dispatch, the same omit-don't-refuse rule the write tools use.
81
+ They are independent of `--allow-writes`, which is about changing data, not
82
+ reading operational data.
83
+
84
+ They return `structuredContent` alongside the usual text block, described by each
85
+ tool's `outputSchema` (MCP revision `2025-06-18` and later; older clients keep
86
+ reading the text block). All but `lunora_get_migration_status` take a `limit`
87
+ clamped server-side; migration status takes only `shardKey` and returns every
88
+ migration, because truncating that list would hide the pending one. Each also
89
+ takes an optional `shardKey` — on a `.shardBy()`-partitioned deployment these
90
+ reads are **per-shard**, not deployment-wide.
91
+
68
92
  `lunora_get_function_schema` returns a JSON object with three fields:
69
93
 
70
94
  - `path` — the function path (e.g. `"messages:send"`)
package/dist/bin.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{parseAgentsEnv as A}from"./packem_shared/AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{connectStdio as N}from"./packem_shared/connectStdio-Dt-DqEgA.mjs";const d=new Set(["1","on","true","yes"]),L=r=>r!==void 0&&d.has(r.trim().toLowerCase());class a extends Error{code;constructor(e,o){super(e),this.name="BinError",this.code=o}}const l=async(r,e={})=>{const o=e.connect??N,n=e.writeError??(t=>{process.stderr.write(t)}),s=r.LUNORA_URL;if(s===void 0||s.length===0)throw n(`lunora-mcp: LUNORA_URL environment variable is required
2
+ import{parseAgentsEnv as A}from"./packem_shared/AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{connectStdio as N}from"./packem_shared/connectStdio-nqnOab_d.mjs";const d=new Set(["1","on","true","yes"]),L=r=>r!==void 0&&d.has(r.trim().toLowerCase());class a extends Error{code;constructor(e,o){super(e),this.name="BinError",this.code=o}}const l=async(r,e={})=>{const o=e.connect??N,n=e.writeError??(t=>{process.stderr.write(t)}),s=r.LUNORA_URL;if(s===void 0||s.length===0)throw n(`lunora-mcp: LUNORA_URL environment variable is required
3
3
  `),new a("LUNORA_URL environment variable is required",1);const i=Number(r.LUNORA_MCP_AGENT_TIMEOUT_MS),c=Number.isFinite(i)&&i>0?i:void 0;try{await o({agents:A(r.LUNORA_MCP_AGENTS),allowAgents:L(r.LUNORA_MCP_ALLOW_AGENTS),allowWrites:L(r.LUNORA_MCP_ALLOW_WRITES),token:r.LUNORA_ADMIN_TOKEN,url:s,...c===void 0?{}:{agentMaxWaitMs:c}})}catch(t){const _=t instanceof Error?t.message:String(t);throw n(`lunora-mcp: failed to start — ${_}
4
4
  `),new a(`failed to start — ${_}`,1)}};try{await l(process.env)}catch(r){process.exit(r instanceof a?r.code:1)}
@@ -1,5 +1,5 @@
1
- import { M as McpResourceProvider, a as McpFetchHandler, T as ToolDefinition, b as McpTool } from "../packem_shared/serve-stateless.d-DX0di_lv.mjs";
2
- export type { c as McpResourceSummary, d as McpServerInfo, e as ToolInputSchema, f as ToolResult } from "../packem_shared/serve-stateless.d-DX0di_lv.mjs";
1
+ import { M as McpResourceProvider, a as McpFetchHandler, T as ToolDefinition, b as McpTool } from "../packem_shared/serve-stateless.d-B_q8q39X.mjs";
2
+ export type { c as McpResourceSummary, d as McpServerInfo, e as ToolInputSchema, f as ToolResult } from "../packem_shared/serve-stateless.d-B_q8q39X.mjs";
3
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
4
  import '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { M as McpResourceProvider, a as McpFetchHandler, T as ToolDefinition, b as McpTool } from "../packem_shared/serve-stateless.d-DX0di_lv.js";
2
- export type { c as McpResourceSummary, d as McpServerInfo, e as ToolInputSchema, f as ToolResult } from "../packem_shared/serve-stateless.d-DX0di_lv.js";
1
+ import { M as McpResourceProvider, a as McpFetchHandler, T as ToolDefinition, b as McpTool } from "../packem_shared/serve-stateless.d-B_q8q39X.js";
2
+ export type { c as McpResourceSummary, d as McpServerInfo, e as ToolInputSchema, f as ToolResult } from "../packem_shared/serve-stateless.d-B_q8q39X.js";
3
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
4
  import '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
5
5
  /**
package/dist/index.d.mts CHANGED
@@ -1,29 +1,44 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
- import { T as ToolDefinition, f as ToolResult, e as ToolInputSchema, a as McpFetchHandler, b as McpTool } from "./packem_shared/serve-stateless.d-DX0di_lv.mjs";
3
- export { type d as McpServerInfo, g as createToolServer, s as serveStateless } from "./packem_shared/serve-stateless.d-DX0di_lv.mjs";
2
+ import { T as ToolDefinition, f as ToolResult, e as ToolInputSchema, a as McpFetchHandler, b as McpTool } from "./packem_shared/serve-stateless.d-B_q8q39X.mjs";
3
+ export { type d as McpServerInfo, g as createToolServer, s as serveStateless } from "./packem_shared/serve-stateless.d-B_q8q39X.mjs";
4
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
6
6
  import '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
7
+ /**
8
+ * The observability tools. Descriptions say WHEN to call the tool, not just
9
+ * what it returns — an agent picking between five similar reads needs the
10
+ * trigger, and it pays for these strings on every turn.
11
+ */
12
+ declare const OBSERVABILITY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
7
13
  /** The read-only tool surface: introspection + query. Always exposed. */
8
14
  declare const READ_ONLY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
9
15
  /** The write tool surface (mutations + actions). Exposed ONLY when writes are enabled. */
10
16
  declare const WRITE_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
11
17
  /**
12
- * The tools this server advertises. When `allowWrites` is false (the default),
13
- * only the read-only surface is exposed — the mutation/action tools are omitted
14
- * from `ListTools` entirely, so an AI agent can't invoke a write it can't see.
18
+ * The tools this server advertises, in three tiers:
19
+ *
20
+ * - the read-only surface, always exposed;
21
+ * - the observability surface, exposed only when an admin token resolved —
22
+ * read-only, but it surfaces production logs and grouped errors, so an
23
+ * unauthenticated server must not even advertise that it exists;
24
+ * - the write surface, exposed only when `allowWrites` is set.
25
+ *
26
+ * Both gates OMIT rather than refuse: an AI agent can't invoke what it can't
27
+ * see. Dispatch re-checks both in {@link callTool}, so the guarantee does not
28
+ * depend on a client honouring the advertised list.
15
29
  */
16
- declare const toolDefinitions: (allowWrites: boolean) => ReadonlyArray<ToolDefinition>;
30
+ declare const toolDefinitions: (allowWrites: boolean, hasAdminToken?: boolean) => ReadonlyArray<ToolDefinition>;
17
31
  /**
18
32
  * Dispatch a tool call against `client`. Unknown tools and thrown errors are
19
33
  * returned as `isError` results (rather than rejections) so the calling model
20
34
  * sees the failure as tool output, per the MCP convention.
21
35
  *
22
- * `allowWrites` gates the mutation/action tools: when false (the default) a call
23
- * to a write tool is refused even if the client somehow names it, so the
24
- * read-only guarantee holds at dispatch, not just in the advertised tool list.
36
+ * `allowWrites` gates the mutation/action tools and `hasAdminToken` gates the
37
+ * observability tools: when either is false a call to the gated tool is refused
38
+ * even if the client somehow names it, so both guarantees hold at dispatch, not
39
+ * just in the advertised tool list.
25
40
  */
26
- declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean) => Promise<ToolResult>;
41
+ declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean, hasAdminToken?: boolean) => Promise<ToolResult>;
27
42
  /**
28
43
  * Agent exposure for the MCP server: a durable `@lunora/agent` run fronted as an
29
44
  * MCP tool an external agent can call. The capability boundary is the MCP-server
@@ -125,6 +140,10 @@ interface LunoraMcpServerOptions {
125
140
  * therefore NOT enforced by the token's scope; it is enforced in-process via
126
141
  * `allowWrites: false` (the default), which omits the write tools from the
127
142
  * advertised list and refuses them at dispatch.
143
+ *
144
+ * Its presence is also what gates the observability tools (logs, Issues,
145
+ * advisories, query insights, migration status): without a token they are
146
+ * omitted from `ListTools` and refused at dispatch.
128
147
  */
129
148
  token?: string;
130
149
  /** Base URL of the deployed Lunora Worker. Required unless `client` is given. */
@@ -299,4 +318,4 @@ interface PaidMcpServer {
299
318
  * transient facilitator outage retries on the next call.
300
319
  */
301
320
  declare const createPaidMcpServer: (config: PaidMcpServerConfig) => PaidMcpServer;
302
- export { AGENT_RUN_INPUT_SCHEMA, AGENT_STATUS_TOOL_NAME, type CallAgentToolOptions, LOCAL_SERVER_NAME, type LocalDeployment, type LocalDeploymentSource, type LocalMcpServerOptions, type LunoraMcpServerOptions, type McpAgentExposure, type McpFetchHandler, type McpTool, NO_DEPLOYMENT_MESSAGE, type PaidMcpChargeConfig, type PaidMcpServer, type PaidMcpServerConfig, READ_ONLY_TOOL_DEFINITIONS, type RegisterPaidToolOptions, type RegisterToolOptions, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, agentToolDefinitions, callAgentTool, callTool, connectLocalStdio, connectStdio, createLocalMcpServer, createLunoraMcpServer, createMcpFetchHandler, createPaidMcpServer, localTools, parseAgentsEnv, toolDefinitions };
321
+ export { AGENT_RUN_INPUT_SCHEMA, AGENT_STATUS_TOOL_NAME, type CallAgentToolOptions, LOCAL_SERVER_NAME, type LocalDeployment, type LocalDeploymentSource, type LocalMcpServerOptions, type LunoraMcpServerOptions, type McpAgentExposure, type McpFetchHandler, type McpTool, NO_DEPLOYMENT_MESSAGE, OBSERVABILITY_TOOL_DEFINITIONS, type PaidMcpChargeConfig, type PaidMcpServer, type PaidMcpServerConfig, READ_ONLY_TOOL_DEFINITIONS, type RegisterPaidToolOptions, type RegisterToolOptions, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, agentToolDefinitions, callAgentTool, callTool, connectLocalStdio, connectStdio, createLocalMcpServer, createLunoraMcpServer, createMcpFetchHandler, createPaidMcpServer, localTools, parseAgentsEnv, toolDefinitions };
package/dist/index.d.ts CHANGED
@@ -1,29 +1,44 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
- import { T as ToolDefinition, f as ToolResult, e as ToolInputSchema, a as McpFetchHandler, b as McpTool } from "./packem_shared/serve-stateless.d-DX0di_lv.js";
3
- export { type d as McpServerInfo, g as createToolServer, s as serveStateless } from "./packem_shared/serve-stateless.d-DX0di_lv.js";
2
+ import { T as ToolDefinition, f as ToolResult, e as ToolInputSchema, a as McpFetchHandler, b as McpTool } from "./packem_shared/serve-stateless.d-B_q8q39X.js";
3
+ export { type d as McpServerInfo, g as createToolServer, s as serveStateless } from "./packem_shared/serve-stateless.d-B_q8q39X.js";
4
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
6
6
  import '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
7
+ /**
8
+ * The observability tools. Descriptions say WHEN to call the tool, not just
9
+ * what it returns — an agent picking between five similar reads needs the
10
+ * trigger, and it pays for these strings on every turn.
11
+ */
12
+ declare const OBSERVABILITY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
7
13
  /** The read-only tool surface: introspection + query. Always exposed. */
8
14
  declare const READ_ONLY_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
9
15
  /** The write tool surface (mutations + actions). Exposed ONLY when writes are enabled. */
10
16
  declare const WRITE_TOOL_DEFINITIONS: ReadonlyArray<ToolDefinition>;
11
17
  /**
12
- * The tools this server advertises. When `allowWrites` is false (the default),
13
- * only the read-only surface is exposed — the mutation/action tools are omitted
14
- * from `ListTools` entirely, so an AI agent can't invoke a write it can't see.
18
+ * The tools this server advertises, in three tiers:
19
+ *
20
+ * - the read-only surface, always exposed;
21
+ * - the observability surface, exposed only when an admin token resolved —
22
+ * read-only, but it surfaces production logs and grouped errors, so an
23
+ * unauthenticated server must not even advertise that it exists;
24
+ * - the write surface, exposed only when `allowWrites` is set.
25
+ *
26
+ * Both gates OMIT rather than refuse: an AI agent can't invoke what it can't
27
+ * see. Dispatch re-checks both in {@link callTool}, so the guarantee does not
28
+ * depend on a client honouring the advertised list.
15
29
  */
16
- declare const toolDefinitions: (allowWrites: boolean) => ReadonlyArray<ToolDefinition>;
30
+ declare const toolDefinitions: (allowWrites: boolean, hasAdminToken?: boolean) => ReadonlyArray<ToolDefinition>;
17
31
  /**
18
32
  * Dispatch a tool call against `client`. Unknown tools and thrown errors are
19
33
  * returned as `isError` results (rather than rejections) so the calling model
20
34
  * sees the failure as tool output, per the MCP convention.
21
35
  *
22
- * `allowWrites` gates the mutation/action tools: when false (the default) a call
23
- * to a write tool is refused even if the client somehow names it, so the
24
- * read-only guarantee holds at dispatch, not just in the advertised tool list.
36
+ * `allowWrites` gates the mutation/action tools and `hasAdminToken` gates the
37
+ * observability tools: when either is false a call to the gated tool is refused
38
+ * even if the client somehow names it, so both guarantees hold at dispatch, not
39
+ * just in the advertised tool list.
25
40
  */
26
- declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean) => Promise<ToolResult>;
41
+ declare const callTool: (client: LunoraClient, name: string, input: Record<string, unknown>, allowWrites?: boolean, hasAdminToken?: boolean) => Promise<ToolResult>;
27
42
  /**
28
43
  * Agent exposure for the MCP server: a durable `@lunora/agent` run fronted as an
29
44
  * MCP tool an external agent can call. The capability boundary is the MCP-server
@@ -125,6 +140,10 @@ interface LunoraMcpServerOptions {
125
140
  * therefore NOT enforced by the token's scope; it is enforced in-process via
126
141
  * `allowWrites: false` (the default), which omits the write tools from the
127
142
  * advertised list and refuses them at dispatch.
143
+ *
144
+ * Its presence is also what gates the observability tools (logs, Issues,
145
+ * advisories, query insights, migration status): without a token they are
146
+ * omitted from `ListTools` and refused at dispatch.
128
147
  */
129
148
  token?: string;
130
149
  /** Base URL of the deployed Lunora Worker. Required unless `client` is given. */
@@ -299,4 +318,4 @@ interface PaidMcpServer {
299
318
  * transient facilitator outage retries on the next call.
300
319
  */
301
320
  declare const createPaidMcpServer: (config: PaidMcpServerConfig) => PaidMcpServer;
302
- export { AGENT_RUN_INPUT_SCHEMA, AGENT_STATUS_TOOL_NAME, type CallAgentToolOptions, LOCAL_SERVER_NAME, type LocalDeployment, type LocalDeploymentSource, type LocalMcpServerOptions, type LunoraMcpServerOptions, type McpAgentExposure, type McpFetchHandler, type McpTool, NO_DEPLOYMENT_MESSAGE, type PaidMcpChargeConfig, type PaidMcpServer, type PaidMcpServerConfig, READ_ONLY_TOOL_DEFINITIONS, type RegisterPaidToolOptions, type RegisterToolOptions, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, agentToolDefinitions, callAgentTool, callTool, connectLocalStdio, connectStdio, createLocalMcpServer, createLunoraMcpServer, createMcpFetchHandler, createPaidMcpServer, localTools, parseAgentsEnv, toolDefinitions };
321
+ export { AGENT_RUN_INPUT_SCHEMA, AGENT_STATUS_TOOL_NAME, type CallAgentToolOptions, LOCAL_SERVER_NAME, type LocalDeployment, type LocalDeploymentSource, type LocalMcpServerOptions, type LunoraMcpServerOptions, type McpAgentExposure, type McpFetchHandler, type McpTool, NO_DEPLOYMENT_MESSAGE, OBSERVABILITY_TOOL_DEFINITIONS, type PaidMcpChargeConfig, type PaidMcpServer, type PaidMcpServerConfig, READ_ONLY_TOOL_DEFINITIONS, type RegisterPaidToolOptions, type RegisterToolOptions, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolResult, WRITE_TOOL_DEFINITIONS, agentToolDefinitions, callAgentTool, callTool, connectLocalStdio, connectStdio, createLocalMcpServer, createLunoraMcpServer, createMcpFetchHandler, createPaidMcpServer, localTools, parseAgentsEnv, toolDefinitions };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{AGENT_RUN_INPUT_SCHEMA as r,AGENT_STATUS_TOOL_NAME as t,agentToolDefinitions as c,callAgentTool as T,parseAgentsEnv as a}from"./packem_shared/AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{createToolServer as E}from"./packem_shared/createToolServer-CP5bNUcS.mjs";import{createMcpFetchHandler as _}from"./packem_shared/createMcpFetchHandler-DjvXAX80.mjs";import{LOCAL_SERVER_NAME as p,NO_DEPLOYMENT_MESSAGE as N,connectLocalStdio as O,createLocalMcpServer as A,localTools as f}from"./packem_shared/LOCAL_SERVER_NAME-BoQv1iu8.mjs";import{createPaidMcpServer as i}from"./packem_shared/createPaidMcpServer-CwdcSPpN.mjs";import{connectStdio as m,createLunoraMcpServer as s}from"./packem_shared/connectStdio-Dt-DqEgA.mjs";import{READ_ONLY_TOOL_DEFINITIONS as I,WRITE_TOOL_DEFINITIONS as v,callTool as D,toolDefinitions as R}from"./packem_shared/READ_ONLY_TOOL_DEFINITIONS-48jMcpI-.mjs";import{serveStateless as g}from"./packem_shared/serveStateless-BqoRk-xU.mjs";export{r as AGENT_RUN_INPUT_SCHEMA,t as AGENT_STATUS_TOOL_NAME,p as LOCAL_SERVER_NAME,N as NO_DEPLOYMENT_MESSAGE,I as READ_ONLY_TOOL_DEFINITIONS,v as WRITE_TOOL_DEFINITIONS,c as agentToolDefinitions,T as callAgentTool,D as callTool,O as connectLocalStdio,m as connectStdio,A as createLocalMcpServer,s as createLunoraMcpServer,_ as createMcpFetchHandler,i as createPaidMcpServer,E as createToolServer,f as localTools,a as parseAgentsEnv,g as serveStateless,R as toolDefinitions};
1
+ import{AGENT_RUN_INPUT_SCHEMA as r,AGENT_STATUS_TOOL_NAME as t,agentToolDefinitions as T,callAgentTool as c,parseAgentsEnv as E}from"./packem_shared/AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{createToolServer as S}from"./packem_shared/createToolServer-CP5bNUcS.mjs";import{createMcpFetchHandler as l}from"./packem_shared/createMcpFetchHandler-Cz_tRkpm.mjs";import{LOCAL_SERVER_NAME as N,NO_DEPLOYMENT_MESSAGE as n,connectLocalStdio as p,createLocalMcpServer as A,localTools as I}from"./packem_shared/LOCAL_SERVER_NAME-BFbVWtCm.mjs";import{createPaidMcpServer as f}from"./packem_shared/createPaidMcpServer-CwdcSPpN.mjs";import{connectStdio as m,createLunoraMcpServer as s}from"./packem_shared/connectStdio-nqnOab_d.mjs";import{READ_ONLY_TOOL_DEFINITIONS as M,WRITE_TOOL_DEFINITIONS as D,callTool as v,toolDefinitions as R}from"./packem_shared/READ_ONLY_TOOL_DEFINITIONS-BygXkni2.mjs";import{A as F}from"./packem_shared/observability-tools-GVGcK_kZ.mjs";import{serveStateless as G}from"./packem_shared/serveStateless-BqoRk-xU.mjs";export{r as AGENT_RUN_INPUT_SCHEMA,t as AGENT_STATUS_TOOL_NAME,N as LOCAL_SERVER_NAME,n as NO_DEPLOYMENT_MESSAGE,F as OBSERVABILITY_TOOL_DEFINITIONS,M as READ_ONLY_TOOL_DEFINITIONS,D as WRITE_TOOL_DEFINITIONS,T as agentToolDefinitions,c as callAgentTool,v as callTool,p as connectLocalStdio,m as connectStdio,A as createLocalMcpServer,s as createLunoraMcpServer,l as createMcpFetchHandler,f as createPaidMcpServer,S as createToolServer,I as localTools,E as parseAgentsEnv,G as serveStateless,R as toolDefinitions};
@@ -0,0 +1 @@
1
+ import{LunoraClient as u}from"@lunora/client";import{StdioServerTransport as f}from"@modelcontextprotocol/sdk/server/stdio.js";import{createToolServer as m}from"./createToolServer-CP5bNUcS.mjs";import{createRemoteDocsIndex as v}from"./DEFAULT_DOCS_BASE_URL-DhaPz6PK.mjs";import{docsResources as h}from"./DOCS_URI_SCHEME-DbyotZvf.mjs";import{docsTools as y}from"./DEFAULT_SEARCH_LIMIT-CKtOASrB.mjs";import{toolDefinitions as O,callTool as R}from"./READ_ONLY_TOOL_DEFINITIONS-BygXkni2.mjs";const E=(t,n)=>{if(t.size<n)return;const o=t.keys().next().value;o!==void 0&&t.delete(o)},l=t=>t.docs===!1?void 0:v({...t.docs?.baseUrl===void 0?{}:{baseUrl:t.docs.baseUrl},...t.fetch===void 0?{}:{fetch:t.fetch}}),_="lunora",g="no Lunora dev server is running for this project — start one with `lunora dev`, then call this tool again (call lunora_dev_status to check).",w=8,d=t=>{const n=new Map;return o=>{const e=JSON.stringify([o.url,o.token??""]),i=n.get(e);if(i!==void 0)return i;const r=new u({fetch:t,url:o.url});return o.token!==void 0&&o.token.length>0&&r.setAuthToken(o.token),E(n,w),n.set(e,r),r}},a=t=>t?.token!==void 0&&t.token.length>0,P=(t,n,o)=>{const e=typeof t=="function"?t:()=>t;return O(n,a(e())).map(i=>({definition:i,handle:async r=>{const s=e();return s===void 0?{content:[{text:g,type:"text"}],isError:!0}:R(o(s),i.name,r,n,a(s))}}))},S="lunora-spec:openrpc",T="lunora-spec:openapi",c=[{description:"The deployment's generated OpenRPC 1.x document — every RPC function's path, kind, and argument schema in one read, instead of list_functions plus one get_function_schema call per function.",fetch:async t=>t.fetchOpenRpc(),name:"OpenRPC specification",uri:S},{description:"The deployment's generated OpenAPI 3.1 document.",fetch:async t=>t.fetchOpenApi(),name:"OpenAPI specification",uri:T}],k=(t,n)=>{const o=typeof t=="function"?t:()=>t,e=async i=>{const r=o();if(r!==void 0)try{return await i.fetch(n(r))}catch{return}};return{list:async()=>(await Promise.all(c.map(async i=>await e(i)===void 0?void 0:{description:i.description,mimeType:"application/json",name:i.name,uri:i.uri}))).filter(i=>i!==void 0),read:async i=>{const r=c.find(p=>p.uri===i);if(r===void 0)return;const s=await e(r);return s===void 0?void 0:{mimeType:"application/json",text:JSON.stringify(s,void 0,2)}}}},A=t=>({list:async()=>(await Promise.all(t.map(async n=>n.list()))).flat(),read:async n=>{for(const o of t){const e=await o.read(n);if(e!==void 0)return e}}}),x=(t,n)=>{const o=[],e=l(t);return e!==void 0&&o.push(...y(e)),o.push(...t.extraTools??[]),t.deployment!==void 0&&o.push(...P(t.deployment,t.allowWrites??!1,n??d(t.fetch))),o},C=(t={})=>{const n=l(t),o=[];n!==void 0&&o.push(h(n));const e=d(t.fetch);return t.deployment!==void 0&&o.push(k(t.deployment,e)),m({name:_,version:t.version??"0.0.0"},x(t,e),o.length===0?void 0:A(o))},b=async(t={})=>{const n=C(t);return await n.connect(new f),n};export{_ as LOCAL_SERVER_NAME,g as NO_DEPLOYMENT_MESSAGE,T as OPENAPI_RESOURCE_URI,S as OPENRPC_RESOURCE_URI,b as connectLocalStdio,C as createLocalMcpServer,x as localTools};
@@ -0,0 +1 @@
1
+ import"@lunora/errors";import"@lunora/shard-engine";import{S as L,a as o,A as s,q as A,D as _}from"./observability-tools-GVGcK_kZ.mjs";export{L as DEFAULT_LIMIT,o as MAX_LIMIT,s as OBSERVABILITY_TOOL_DEFINITIONS,A as OBSERVABILITY_TOOL_NAMES,_ as callObservabilityTool};
@@ -0,0 +1 @@
1
+ import{LunoraError as u}from"@lunora/errors";import{A as E,f as l,q as N,D as R,u as o}from"./observability-tools-GVGcK_kZ.mjs";const y={properties:{args:{description:"Arguments object passed to the function",type:"object"},functionPath:{description:'Function reference, e.g. "messages:send"',type:"string"},shardKey:{description:"Optional shard key when the function is .shardBy()-partitioned",type:"string"}},required:["functionPath"],type:"object"},g={properties:{},type:"object"},v={properties:{functionPath:{description:'Function reference, e.g. "messages:send"',type:"string"}},required:["functionPath"],type:"object"},d={destructiveHint:!1,idempotentHint:!0,openWorldHint:!0,readOnlyHint:!0},A=[{annotations:{...d,title:"List deployment functions"},description:"List the deployment's public functions (queries, mutations, actions) with their kinds.",inputSchema:g,name:"lunora_list_functions"},{annotations:{...d,title:"List global tables"},description:"List the deployment's .global() tables and their column shapes.",inputSchema:g,name:"lunora_list_tables"},{annotations:{...d,title:"Describe a function's arguments"},description:"Return a function's argument JSON Schema and kind, so a caller can construct a valid arguments object. Call lunora_list_functions first to discover available function paths.",inputSchema:v,name:"lunora_get_function_schema"},{annotations:{...d,title:"Run a query"},description:"Run a query and return its result. Read-only.",inputSchema:y,name:"lunora_run_query"}],O=[{annotations:{destructiveHint:!0,idempotentHint:!1,openWorldHint:!0,readOnlyHint:!1,title:"Run a mutation (writes data)"},description:"Run a mutation and return its result. Writes data — use with care.",inputSchema:y,name:"lunora_run_mutation"},{annotations:{destructiveHint:!0,idempotentHint:!1,openWorldHint:!0,readOnlyHint:!1,title:"Run an action (may call external services)"},description:"Run an action and return its result. May call external services.",inputSchema:y,name:"lunora_run_action"}],T=new Set(O.map(t=>t.name)),$=(t,e=!1)=>[...A,...e===!0?E:[],...t===!0?O:[]],S=t=>{const{functionPath:e}=t;if(typeof e!="string"||e.length===0)throw new u("INTERNAL",'"functionPath" is required and must be a non-empty string');return e},w=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),b=t=>Array.isArray(t)?"an array":`a ${typeof t}`,D=t=>{if(t==null)return{};if(typeof t=="string"){let e;try{e=JSON.parse(t)}catch{throw new u("BAD_REQUEST",'"args" must be a JSON object; received a string that is not valid JSON')}if(!w(e))throw new u("BAD_REQUEST",`"args" must be a JSON object; the provided string decoded to ${b(e)}`);return e}if(!w(t))throw new u("BAD_REQUEST",`"args" must be a JSON object, got ${b(t)}`);return t},p=t=>{const e=S(t),a=D(t.args),i=typeof t.shardKey=="string"&&t.shardKey.length>0?t.shardKey:void 0;return{args:a,functionPath:e,shardKey:i}},f=t=>({__lunoraRef:t}),L=3e4,h=new WeakMap,_=t=>{const e=Date.now(),a=h.get(t);if(a!==void 0&&a.expiresAt>e)return a.promise;const i=t.listFunctions().catch(c=>{throw h.get(t)?.promise===i&&h.delete(t),c});return h.set(t,{expiresAt:e+L,promise:i}),i},m=async(t,e,a)=>{const i=(await _(t)).find(c=>c.path===e);if(i===void 0)throw new u("NOT_FOUND",`function not found or not public: ${e}`);if(i.kind!==a)throw new u("BAD_REQUEST",`function ${e} is a ${i.kind}, not a ${a}`)},k=async(t,e,a,i=!1,c=!1)=>{try{if(i!==!0&&T.has(e))return l(`tool "${e}" is disabled: this MCP server is read-only. Enable writes with the LUNORA_MCP_ALLOW_WRITES env var.`);if(N.has(e))return c!==!0?l(`tool "${e}" is unavailable: it reads the deployment's logs and errors, which needs an admin token. Set LUNORA_ADMIN_TOKEN (or pass --token) and reconnect.`):await R(t,e,a);switch(e){case"lunora_get_function_schema":{const r=S(a),n=(await _(t)).find(s=>s.path===r);return n===void 0?l(`function not found: ${r}`):o({args:n.args??[],kind:n.kind,path:n.path})}case"lunora_list_functions":return o(await _(t));case"lunora_list_tables":return o(await t.listGlobalTables());case"lunora_run_action":{const{args:r,functionPath:n,shardKey:s}=p(a);return await m(t,n,"action"),o(await t.action(f(n),r,{shardKey:s}))}case"lunora_run_mutation":{const{args:r,functionPath:n,shardKey:s}=p(a);return await m(t,n,"mutation"),o(await t.mutation(f(n),r,{shardKey:s}))}case"lunora_run_query":{const{args:r,functionPath:n,shardKey:s}=p(a);return await m(t,n,"query"),o(await t.query(f(n),r,{shardKey:s}))}default:return l(`unknown tool: ${e}`)}}catch(r){const n=r instanceof Error?r.message:String(r);return l(n)}};export{E as OBSERVABILITY_TOOL_DEFINITIONS,A as READ_ONLY_TOOL_DEFINITIONS,O as WRITE_TOOL_DEFINITIONS,k as callTool,$ as toolDefinitions};
@@ -0,0 +1 @@
1
+ import{readFileSync as f}from"node:fs";import{dirname as c,join as p}from"node:path";import{fileURLToPath as v}from"node:url";import{LunoraClient as g}from"@lunora/client";import{LunoraError as h}from"@lunora/errors";import{Server as d}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as w}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as M,CallToolRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{agentToolDefinitions as T,isAgentToolName as k,callAgentTool as y}from"./AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{toolDefinitions as L,callTool as x}from"./READ_ONLY_TOOL_DEFINITIONS-BygXkni2.mjs";const A=()=>{try{let t=c(v(import.meta.url));for(let r=0;r<8;r+=1){try{const n=f(p(t,"package.json"),"utf8"),o=JSON.parse(n);if(o.name==="@lunora/mcp"&&typeof o.version=="string"&&o.version.length>0)return o.version}catch{}const e=c(t);if(e===t)break;t=e}}catch{}return"0.0.0"},R={name:"lunora",version:A()},q=t=>{if(t.client!==void 0)return t.client;if(t.url===void 0)throw new h("INTERNAL","createLunoraMcpServer requires either a `client` or a `url`");const r=new g({fetch:t.fetch,url:t.url});return t.token!==void 0&&r.setAuthToken(t.token),r},W=t=>{const r=q(t),e=t.allowWrites??!1,n=t.allowAgents??!1,o=t.agents??[],i=typeof t.token=="string"&&t.token.length>0,a=new d(R,{capabilities:{tools:{}}});return a.setRequestHandler(M,()=>({tools:[...L(e,i),...T(o,n)]})),a.setRequestHandler(S,async m=>{const{arguments:u,name:s}=m.params,l=u??{};return k(s,o)?await y(r,s,l,{allowAgents:n,exposures:o,...t.agentMaxWaitMs===void 0?{}:{maxWaitMs:t.agentMaxWaitMs},...t.agentPollIntervalMs===void 0?{}:{pollIntervalMs:t.agentPollIntervalMs}}):await x(r,s,l,e,i)}),a},O=async t=>{const r=W(t);return await r.connect(new w),r};export{O as connectStdio,W as createLunoraMcpServer};
@@ -0,0 +1 @@
1
+ import{serveStateless as s}from"./serveStateless-BqoRk-xU.mjs";import{createLunoraMcpServer as t}from"./connectStdio-nqnOab_d.mjs";const c=e=>r=>s(t(e),r);export{c as createMcpFetchHandler,s as serveStateless};
@@ -0,0 +1 @@
1
+ import{LunoraError as N}from"@lunora/errors";import{ADMIN_FUNCTIONS as u}from"@lunora/shard-engine";const b=e=>{let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)},v=(e,t)=>{if(typeof t=="bigint")return t.toString();if(t instanceof ArrayBuffer)return b(new Uint8Array(t));if(ArrayBuffer.isView(t)){const r=t;return b(new Uint8Array(r.buffer,r.byteOffset,r.byteLength))}return t},R=e=>JSON.parse(JSON.stringify(e,v)),x=e=>({content:[{text:e===void 0?"null":JSON.stringify(e,v,2),type:"text"}]}),p=e=>({...x(e),structuredContent:R(e)}),F=e=>({content:[{text:e,type:"text"}],isError:!0}),d={destructiveHint:!1,idempotentHint:!0,openWorldHint:!0,readOnlyHint:!0},S=50,_=500,k=["1m","5m","15m","1h"],j=["open","resolved","ignored"],q=["trace","debug","log","info","warn","error","fatal"],h={description:"Shard to read from on a .shardBy()-partitioned deployment. Omit for the default (unsharded) shard — these reads are PER-SHARD, not deployment-wide.",type:"string"},y={description:`Maximum rows to return (default ${S.toString()}, clamped to ${_.toString()}).`,type:"number"},I=e=>{const t=typeof e=="number"?e:Number.NaN;return Number.isFinite(t)?Math.max(1,Math.min(Math.floor(t),_)):S},g=(e,t)=>t.includes(e)?e:void 0,w=e=>typeof e=="string"&&e.length>0?e:void 0,O={properties:{level:{description:`Keep only entries at this severity. One of: ${q.join(", ")}.`,type:"string"},limit:y,shardKey:h},type:"object"},P={properties:{functionPathPrefix:{description:'Keep only Issues whose function path starts with this, e.g. "messages:".',type:"string"},limit:y,shardKey:h,status:{description:`Triage status to keep. One of: ${j.join(", ")}. Default: all.`,type:"string"}},type:"object"},E={properties:{limit:y,shardKey:h},type:"object"},K={properties:{limit:y,range:{description:`Time window to report over. One of: ${k.join(", ")}. Default: 15m.`,type:"string"},shardKey:h},type:"object"},L={properties:{shardKey:h},type:"object"},T={properties:{entries:{description:"Recent log entries, NEWEST FIRST: { level, message, timestamp, functionPath?, fields? }.",type:"array"},total:{description:"Entries available before `limit`/`level` narrowed them.",type:"number"}},required:["entries","total"],type:"object"},$={properties:{issues:{description:"Grouped error Issues, newest first: { hash, title, count, status, functionPath, lastSeen, … }.",type:"array"}},required:["issues"],type:"object"},C={properties:{advisories:{description:"Schema/query advisories: { id, level, title, detail, … }.",type:"array"},total:{description:"Advisories available before `limit` narrowed them.",type:"number"}},required:["advisories","total"],type:"object"},D={properties:{buckets:{description:"Combined throughput/latency series across the range.",type:"array"},capped:{description:"True when the deployment's tracked-statement cap was reached, so coverage is partial.",type:"boolean"},entries:{description:"Per-statement activity in the range, hottest first.",type:"array"},total:{description:"Statements available before `limit` narrowed them.",type:"number"},trackedStatements:{description:"Distinct statements the deployment is tracking.",type:"number"}},required:["entries","buckets"],type:"object"},H={properties:{migrations:{description:"Every declared migration with its applied/pending state.",type:"array"}},required:["migrations"],type:"object"},M=[{annotations:{...d,title:"Read recent logs"},description:"Read the deployment's recent log entries (newest first) after running a function, to see what it printed and where it failed. In-memory and per-shard: resets when the shard hibernates.",inputSchema:O,name:"lunora_get_logs",outputSchema:T},{annotations:{...d,title:"List grouped error Issues"},description:"List errors grouped into Issues by fingerprint, with occurrence counts and triage status — the first call when asking what is currently broken, rather than reading raw logs.",inputSchema:P,name:"lunora_get_issues",outputSchema:$},{annotations:{...d,title:"List schema and query advisories"},description:"List the deployment's schema/query advisories (missing indexes, unsafe policies, and similar lints) before or after changing the schema.",inputSchema:E,name:"lunora_get_advisories",outputSchema:C},{annotations:{...d,title:"Read query insights"},description:"Read per-statement execution counts and latency over a recent time window, to find which query is slow or hot before optimizing one.",inputSchema:K,name:"lunora_get_query_insights",outputSchema:D},{annotations:{...d,title:"Read migration status"},description:"Read which migrations have been applied and which are pending, to check whether a schema change has actually landed on the deployment.",inputSchema:L,name:"lunora_get_migration_status",outputSchema:H}],J=new Set(M.map(e=>e.name)),c=async(e,t,r,s)=>{const o={__lunoraRef:t};return e.query(o,r,{...s===void 0?{}:{shardKey:s}})},l=(e,t)=>{const r=e?.[t];return Array.isArray(r)?r:[]},W=async(e,t,r)=>{const s=w(r.shardKey),o=I(r.limit);switch(t){case"lunora_get_advisories":{const i=await c(e,u.getAdvisories,{},s),n=l(i,"advisories");return p({advisories:n.slice(0,o),total:n.length})}case"lunora_get_issues":{const i=g(r.status,j),n=w(r.functionPathPrefix),a=await c(e,u.getIssues,{limit:o,...i===void 0?{}:{status:i},...n===void 0?{}:{functionPathPrefix:n}},s);return p({issues:l(a,"issues")})}case"lunora_get_logs":{const i=g(r.level,q),n=await c(e,u.getLogs,{},s),a=l(n,"entries").filter(m=>i===void 0||m.level===i);return p({entries:a.slice(0,o),total:a.length})}case"lunora_get_migration_status":{const i=await c(e,u.migrationStatus,{},s);return p({migrations:l(i,"migrations")})}case"lunora_get_query_insights":{const i=g(r.range,k),n=await c(e,u.getQueryInsights,{...i===void 0?{}:{range:i}},s),a=l(n,"entries"),{buckets:m,capped:A,trackedStatements:f}=n??{};return p({buckets:Array.isArray(m)?m:[],capped:A===!0,entries:a.slice(0,o),total:a.length,trackedStatements:typeof f=="number"?f:a.length})}default:throw new N("INTERNAL",`unknown observability tool: ${t}`)}};export{M as A,W as D,S,_ as a,F as f,J as q,x as u};
@@ -42,6 +42,12 @@ interface ToolDefinition {
42
42
  description: string;
43
43
  inputSchema: ToolInputSchema;
44
44
  name: string;
45
+ /**
46
+ * JSON Schema for the tool's `structuredContent`. Optional: a tool that
47
+ * emits only a text block declares none, and a client that negotiated an
48
+ * MCP revision older than `2025-06-18` ignores it either way.
49
+ */
50
+ outputSchema?: ToolInputSchema;
45
51
  }
46
52
  /** The MCP `CallToolResult` shape this package's tools return. */
47
53
  interface ToolResult {
@@ -50,6 +56,14 @@ interface ToolResult {
50
56
  type: "text";
51
57
  }[];
52
58
  isError?: boolean;
59
+ /**
60
+ * The machine-readable result, mirroring the text block. Present only for
61
+ * tools that declare an `outputSchema`; per the MCP spec it must be a JSON
62
+ * OBJECT (never a bare array) and must survive `JSON.stringify` — the
63
+ * transport serializes it, so an un-mapped `bigint` here fails the whole
64
+ * response rather than one field.
65
+ */
66
+ structuredContent?: Record<string, unknown>;
53
67
  }
54
68
  /** A tool: what to advertise in `ListTools`, and what to run on `CallTool`. */
55
69
  interface McpTool {
@@ -42,6 +42,12 @@ interface ToolDefinition {
42
42
  description: string;
43
43
  inputSchema: ToolInputSchema;
44
44
  name: string;
45
+ /**
46
+ * JSON Schema for the tool's `structuredContent`. Optional: a tool that
47
+ * emits only a text block declares none, and a client that negotiated an
48
+ * MCP revision older than `2025-06-18` ignores it either way.
49
+ */
50
+ outputSchema?: ToolInputSchema;
45
51
  }
46
52
  /** The MCP `CallToolResult` shape this package's tools return. */
47
53
  interface ToolResult {
@@ -50,6 +56,14 @@ interface ToolResult {
50
56
  type: "text";
51
57
  }[];
52
58
  isError?: boolean;
59
+ /**
60
+ * The machine-readable result, mirroring the text block. Present only for
61
+ * tools that declare an `outputSchema`; per the MCP spec it must be a JSON
62
+ * OBJECT (never a bare array) and must survive `JSON.stringify` — the
63
+ * transport serializes it, so an un-mapped `bigint` here fails the whole
64
+ * response rather than one field.
65
+ */
66
+ structuredContent?: Record<string, unknown>;
53
67
  }
54
68
  /** A tool: what to advertise in `ListTools`, and what to run on `CallTool`. */
55
69
  interface McpTool {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/mcp",
3
- "version": "1.0.0-alpha.60",
3
+ "version": "1.0.0-alpha.61",
4
4
  "description": "Model Context Protocol server exposing a Lunora deployment to AI agents",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -55,6 +55,7 @@
55
55
  "dependencies": {
56
56
  "@lunora/client": "1.0.0-alpha.43",
57
57
  "@lunora/errors": "1.0.0-alpha.16",
58
+ "@lunora/shard-engine": "1.0.0-alpha.16",
58
59
  "@modelcontextprotocol/sdk": "^1.29.0"
59
60
  },
60
61
  "peerDependencies": {
@@ -1 +0,0 @@
1
- import{LunoraClient as p}from"@lunora/client";import{StdioServerTransport as u}from"@modelcontextprotocol/sdk/server/stdio.js";import{createToolServer as f}from"./createToolServer-CP5bNUcS.mjs";import{createRemoteDocsIndex as m}from"./DEFAULT_DOCS_BASE_URL-DhaPz6PK.mjs";import{docsResources as v}from"./DOCS_URI_SCHEME-DbyotZvf.mjs";import{docsTools as h}from"./DEFAULT_SEARCH_LIMIT-CKtOASrB.mjs";import{toolDefinitions as y,callTool as O}from"./READ_ONLY_TOOL_DEFINITIONS-48jMcpI-.mjs";const R=(t,e)=>{if(t.size<e)return;const o=t.keys().next().value;o!==void 0&&t.delete(o)},c=t=>t.docs===!1?void 0:m({...t.docs?.baseUrl===void 0?{}:{baseUrl:t.docs.baseUrl},...t.fetch===void 0?{}:{fetch:t.fetch}}),E="lunora",P="no Lunora dev server is running for this project — start one with `lunora dev`, then call this tool again (call lunora_dev_status to check).",_=8,l=t=>{const e=new Map;return o=>{const n=JSON.stringify([o.url,o.token??""]),r=e.get(n);if(r!==void 0)return r;const i=new p({fetch:t,url:o.url});return o.token!==void 0&&o.token.length>0&&i.setAuthToken(o.token),R(e,_),e.set(n,i),i}},w=(t,e,o)=>{const n=typeof t=="function"?t:()=>t;return y(e).map(r=>({definition:r,handle:async i=>{const s=n();return s===void 0?{content:[{text:P,type:"text"}],isError:!0}:O(o(s),r.name,i,e)}}))},S="lunora-spec:openrpc",T="lunora-spec:openapi",a=[{description:"The deployment's generated OpenRPC 1.x document — every RPC function's path, kind, and argument schema in one read, instead of list_functions plus one get_function_schema call per function.",fetch:async t=>t.fetchOpenRpc(),name:"OpenRPC specification",uri:S},{description:"The deployment's generated OpenAPI 3.1 document.",fetch:async t=>t.fetchOpenApi(),name:"OpenAPI specification",uri:T}],g=(t,e)=>{const o=typeof t=="function"?t:()=>t,n=async r=>{const i=o();if(i!==void 0)try{return await r.fetch(e(i))}catch{return}};return{list:async()=>(await Promise.all(a.map(async r=>await n(r)===void 0?void 0:{description:r.description,mimeType:"application/json",name:r.name,uri:r.uri}))).filter(r=>r!==void 0),read:async r=>{const i=a.find(d=>d.uri===r);if(i===void 0)return;const s=await n(i);return s===void 0?void 0:{mimeType:"application/json",text:JSON.stringify(s,void 0,2)}}}},A=t=>({list:async()=>(await Promise.all(t.map(async e=>e.list()))).flat(),read:async e=>{for(const o of t){const n=await o.read(e);if(n!==void 0)return n}}}),x=(t,e)=>{const o=[],n=c(t);return n!==void 0&&o.push(...h(n)),o.push(...t.extraTools??[]),t.deployment!==void 0&&o.push(...w(t.deployment,t.allowWrites??!1,e??l(t.fetch))),o},C=(t={})=>{const e=c(t),o=[];e!==void 0&&o.push(v(e));const n=l(t.fetch);return t.deployment!==void 0&&o.push(g(t.deployment,n)),f({name:E,version:t.version??"0.0.0"},x(t,n),o.length===0?void 0:A(o))},$=async(t={})=>{const e=C(t);return await e.connect(new u),e};export{E as LOCAL_SERVER_NAME,P as NO_DEPLOYMENT_MESSAGE,T as OPENAPI_RESOURCE_URI,S as OPENRPC_RESOURCE_URI,$ as connectLocalStdio,C as createLocalMcpServer,x as localTools};
@@ -1 +0,0 @@
1
- import{LunoraError as u}from"@lunora/errors";const h={properties:{args:{description:"Arguments object passed to the function",type:"object"},functionPath:{description:'Function reference, e.g. "messages:send"',type:"string"},shardKey:{description:"Optional shard key when the function is .shardBy()-partitioned",type:"string"}},required:["functionPath"],type:"object"},m={properties:{},type:"object"},E={properties:{functionPath:{description:'Function reference, e.g. "messages:send"',type:"string"}},required:["functionPath"],type:"object"},c={destructiveHint:!1,idempotentHint:!0,openWorldHint:!0,readOnlyHint:!0},g=[{annotations:{...c,title:"List deployment functions"},description:"List the deployment's public functions (queries, mutations, actions) with their kinds.",inputSchema:m,name:"lunora_list_functions"},{annotations:{...c,title:"List global tables"},description:"List the deployment's .global() tables and their column shapes.",inputSchema:m,name:"lunora_list_tables"},{annotations:{...c,title:"Describe a function's arguments"},description:"Return a function's argument JSON Schema and kind, so a caller can construct a valid arguments object. Call lunora_list_functions first to discover available function paths.",inputSchema:E,name:"lunora_get_function_schema"},{annotations:{...c,title:"Run a query"},description:"Run a query and return its result. Read-only.",inputSchema:h,name:"lunora_run_query"}],S=[{annotations:{destructiveHint:!0,idempotentHint:!1,openWorldHint:!0,readOnlyHint:!1,title:"Run a mutation (writes data)"},description:"Run a mutation and return its result. Writes data — use with care.",inputSchema:h,name:"lunora_run_mutation"},{annotations:{destructiveHint:!0,idempotentHint:!1,openWorldHint:!0,readOnlyHint:!1,title:"Run an action (may call external services)"},description:"Run an action and return its result. May call external services.",inputSchema:h,name:"lunora_run_action"}],A=new Set(S.map(t=>t.name)),T=t=>t===!0?[...g,...S]:g,O=t=>{const{functionPath:e}=t;if(typeof e!="string"||e.length===0)throw new u("INTERNAL",'"functionPath" is required and must be a non-empty string');return e},_=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),w=t=>Array.isArray(t)?"an array":`a ${typeof t}`,v=t=>{if(t==null)return{};if(typeof t=="string"){let e;try{e=JSON.parse(t)}catch{throw new u("BAD_REQUEST",'"args" must be a JSON object; received a string that is not valid JSON')}if(!_(e))throw new u("BAD_REQUEST",`"args" must be a JSON object; the provided string decoded to ${w(e)}`);return e}if(!_(t))throw new u("BAD_REQUEST",`"args" must be a JSON object, got ${w(t)}`);return t},d=t=>{const e=O(t),n=v(t.args),i=typeof t.shardKey=="string"&&t.shardKey.length>0?t.shardKey:void 0;return{args:n,functionPath:e,shardKey:i}},f=t=>({__lunoraRef:t}),b=t=>{let e="";for(let n=0;n<t.length;n+=32768)e+=String.fromCharCode(...t.subarray(n,n+32768));return btoa(e)},R=(t,e)=>{if(typeof e=="bigint")return e.toString();if(e instanceof ArrayBuffer)return b(new Uint8Array(e));if(ArrayBuffer.isView(e)){const n=e;return b(new Uint8Array(n.buffer,n.byteOffset,n.byteLength))}return e},s=t=>({content:[{text:t===void 0?"null":JSON.stringify(t,R,2),type:"text"}]}),N=3e4,l=new WeakMap,y=t=>{const e=Date.now(),n=l.get(t);if(n!==void 0&&n.expiresAt>e)return n.promise;const i=t.listFunctions().catch(r=>{throw l.get(t)?.promise===i&&l.delete(t),r});return l.set(t,{expiresAt:e+N,promise:i}),i},p=async(t,e,n)=>{const i=(await y(t)).find(r=>r.path===e);if(i===void 0)throw new u("NOT_FOUND",`function not found or not public: ${e}`);if(i.kind!==n)throw new u("BAD_REQUEST",`function ${e} is a ${i.kind}, not a ${n}`)},L=async(t,e,n,i=!1)=>{try{if(i!==!0&&A.has(e))return{content:[{text:`tool "${e}" is disabled: this MCP server is read-only. Enable writes with the LUNORA_MCP_ALLOW_WRITES env var.`,type:"text"}],isError:!0};switch(e){case"lunora_get_function_schema":{const r=O(n),a=(await y(t)).find(o=>o.path===r);return a===void 0?{content:[{text:`function not found: ${r}`,type:"text"}],isError:!0}:s({args:a.args??[],kind:a.kind,path:a.path})}case"lunora_list_functions":return s(await y(t));case"lunora_list_tables":return s(await t.listGlobalTables());case"lunora_run_action":{const{args:r,functionPath:a,shardKey:o}=d(n);return await p(t,a,"action"),s(await t.action(f(a),r,{shardKey:o}))}case"lunora_run_mutation":{const{args:r,functionPath:a,shardKey:o}=d(n);return await p(t,a,"mutation"),s(await t.mutation(f(a),r,{shardKey:o}))}case"lunora_run_query":{const{args:r,functionPath:a,shardKey:o}=d(n);return await p(t,a,"query"),s(await t.query(f(a),r,{shardKey:o}))}default:return{content:[{text:`unknown tool: ${e}`,type:"text"}],isError:!0}}}catch(r){return{content:[{text:r instanceof Error?r.message:String(r),type:"text"}],isError:!0}}};export{g as READ_ONLY_TOOL_DEFINITIONS,S as WRITE_TOOL_DEFINITIONS,L as callTool,T as toolDefinitions};
@@ -1 +0,0 @@
1
- import{readFileSync as u}from"node:fs";import{dirname as l,join as f}from"node:path";import{fileURLToPath as p}from"node:url";import{LunoraClient as v}from"@lunora/client";import{LunoraError as g}from"@lunora/errors";import{Server as d}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as h}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as w,CallToolRequestSchema as M}from"@modelcontextprotocol/sdk/types.js";import{agentToolDefinitions as S,isAgentToolName as T,callAgentTool as L}from"./AGENT_RUN_INPUT_SCHEMA-ihZg6vIZ.mjs";import{toolDefinitions as k,callTool as x}from"./READ_ONLY_TOOL_DEFINITIONS-48jMcpI-.mjs";const y=()=>{try{let t=l(p(import.meta.url));for(let r=0;r<8;r+=1){try{const a=u(f(t,"package.json"),"utf8"),o=JSON.parse(a);if(o.name==="@lunora/mcp"&&typeof o.version=="string"&&o.version.length>0)return o.version}catch{}const e=l(t);if(e===t)break;t=e}}catch{}return"0.0.0"},A={name:"lunora",version:y()},R=t=>{if(t.client!==void 0)return t.client;if(t.url===void 0)throw new g("INTERNAL","createLunoraMcpServer requires either a `client` or a `url`");const r=new v({fetch:t.fetch,url:t.url});return t.token!==void 0&&r.setAuthToken(t.token),r},q=t=>{const r=R(t),e=t.allowWrites??!1,a=t.allowAgents??!1,o=t.agents??[],n=new d(A,{capabilities:{tools:{}}});return n.setRequestHandler(w,()=>({tools:[...k(e),...S(o,a)]})),n.setRequestHandler(M,async c=>{const{arguments:m,name:s}=c.params,i=m??{};return T(s,o)?await L(r,s,i,{allowAgents:a,exposures:o,...t.agentMaxWaitMs===void 0?{}:{maxWaitMs:t.agentMaxWaitMs},...t.agentPollIntervalMs===void 0?{}:{pollIntervalMs:t.agentPollIntervalMs}}):await x(r,s,i,e)}),n},O=async t=>{const r=q(t);return await r.connect(new h),r};export{O as connectStdio,q as createLunoraMcpServer};
@@ -1 +0,0 @@
1
- import{serveStateless as s}from"./serveStateless-BqoRk-xU.mjs";import{createLunoraMcpServer as t}from"./connectStdio-Dt-DqEgA.mjs";const o=e=>r=>s(t(e),r);export{o as createMcpFetchHandler,s as serveStateless};