@lovable.dev/mcp-js 0.21.1-rc.1 → 0.22.0-rc.0
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/authorize-BMeXd_Sh.d.ts +25 -0
- package/dist/base-CM-KCpp6.d.ts +28 -0
- package/dist/chunk-4BAHMNLD.js +141 -0
- package/dist/chunk-6DXGZZA4.js +6 -0
- package/dist/chunk-6QFZYYUV.js +11 -0
- package/dist/chunk-BE6FQG4R.js +741 -0
- package/dist/chunk-H37EB22A.js +125 -0
- package/dist/chunk-KYZVRIEA.js +58 -0
- package/dist/chunk-MA5H6PSF.js +46 -0
- package/dist/chunk-PM4LYSXH.js +6 -0
- package/dist/chunk-S3OANL46.js +114 -0
- package/dist/chunk-UQK5UO6C.js +26 -0
- package/dist/chunk-V57YXRAR.js +79 -0
- package/dist/chunk-XQWJN6DC.js +14 -0
- package/dist/chunk-Y3ZFPEQH.js +8 -0
- package/dist/cli/extract-manifest.cjs +201 -116
- package/dist/cli/extract-manifest.d.cts +1 -1
- package/dist/cli/extract-manifest.d.ts +1 -1
- package/dist/cli/extract-manifest.js +156 -117
- package/dist/index.cjs +329 -129
- package/dist/index.d.cts +26 -26
- package/dist/index.d.ts +26 -26
- package/dist/index.js +177 -118
- package/dist/{io-CS4UL6_A.d.ts → io-D4srzRKc.d.ts} +4 -6
- package/dist/protocols/mcp/index.cjs +750 -3
- package/dist/protocols/mcp/index.d.cts +7 -6
- package/dist/protocols/mcp/index.d.ts +7 -6
- package/dist/protocols/mcp/index.js +12 -2
- package/dist/protocols/oauth-metadata.cjs +539 -48
- package/dist/protocols/oauth-metadata.d.cts +6 -5
- package/dist/protocols/oauth-metadata.d.ts +6 -5
- package/dist/protocols/oauth-metadata.js +10 -52
- package/dist/protocols/rest/index.cjs +843 -5
- package/dist/protocols/rest/index.d.cts +10 -7
- package/dist/protocols/rest/index.d.ts +10 -7
- package/dist/protocols/rest/index.js +16 -3
- package/dist/stacks/supabase/index.cjs +1318 -76
- package/dist/stacks/supabase/index.d.cts +30 -29
- package/dist/stacks/supabase/index.d.ts +30 -29
- package/dist/stacks/supabase/index.js +89 -73
- package/dist/stacks/supabase/vite.cjs +287 -258
- package/dist/stacks/supabase/vite.d.cts +24 -24
- package/dist/stacks/supabase/vite.d.ts +24 -24
- package/dist/stacks/supabase/vite.js +252 -252
- package/dist/stacks/tanstack/index.cjs +1272 -42
- package/dist/stacks/tanstack/index.d.cts +9 -8
- package/dist/stacks/tanstack/index.d.ts +9 -8
- package/dist/stacks/tanstack/index.js +41 -36
- package/dist/stacks/tanstack/vite.cjs +312 -223
- package/dist/stacks/tanstack/vite.d.cts +81 -80
- package/dist/stacks/tanstack/vite.d.ts +81 -80
- package/dist/stacks/tanstack/vite.js +282 -216
- package/dist/types-qqrmJ736.d.ts +321 -0
- package/package.json +28 -71
- package/dist/authorize-CumVyk7p.d.cts +0 -27
- package/dist/authorize-D6p4-9_D.d.ts +0 -27
- package/dist/base-CoIFvAmS.d.cts +0 -26
- package/dist/base-CoIFvAmS.d.ts +0 -26
- package/dist/content-D5LJAHyM.js +0 -12
- package/dist/content-NCYIGgOb.cjs +0 -17
- package/dist/context-BweeEcoA.cjs +0 -56
- package/dist/context-CIpPzN7P.js +0 -51
- package/dist/cors-B7CTXIHD.js +0 -829
- package/dist/cors-BebjKPrc.cjs +0 -912
- package/dist/forwarded--h4efJy-.js +0 -43
- package/dist/forwarded-Pi8Hs5Ps.cjs +0 -48
- package/dist/fs-errors-CWNzOV75.cjs +0 -11
- package/dist/fs-errors-PA2t1TIp.js +0 -6
- package/dist/io-CbbUbPY3.d.cts +0 -15
- package/dist/list-tools-CBCuS1Tv.cjs +0 -57
- package/dist/list-tools-CsWgiRy1.d.ts +0 -8
- package/dist/list-tools-CtZHOuPv.d.cts +0 -8
- package/dist/list-tools-D75RGtgs.js +0 -46
- package/dist/logger-2OXtfiIW.js +0 -141
- package/dist/logger-BqPOa_E1.cjs +0 -194
- package/dist/mcp-Cdj0AYst.cjs +0 -123
- package/dist/mcp-GngXbcqN.js +0 -118
- package/dist/metadata-path-CAkNcfyY.js +0 -12
- package/dist/metadata-path-zd7NSNoa.cjs +0 -17
- package/dist/package-7EUptuSJ.js +0 -4
- package/dist/package-BwCGVRcB.cjs +0 -9
- package/dist/paths-IS65L6TA.js +0 -7
- package/dist/paths-OP318a6c.cjs +0 -18
- package/dist/rest-CXH6-zv9.js +0 -113
- package/dist/rest-CyV8LHeB.cjs +0 -118
- package/dist/types-BYdYYTjk.d.cts +0 -321
- package/dist/types-BYdYYTjk.d.ts +0 -321
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface McpRuntimeOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Public MCP protocol path. REST companion handlers pass this so OAuth
|
|
4
|
+
* resource/audience checks bind to `/mcp`, not internal `/.mcp/*` RPC URLs.
|
|
5
|
+
*/
|
|
6
|
+
resourcePath?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Host-relative path of the SDK-served protected-resource metadata document.
|
|
9
|
+
* The Vite plugin injects it into every emitted handler when it generates the
|
|
10
|
+
* PRM route, so the 401 challenge advertises the same path the route serves.
|
|
11
|
+
* Its presence is the signal that the SDK owns the PRM document, so it is
|
|
12
|
+
* mutually exclusive with `auth.protectedResourceMetadataUrl` (which points at
|
|
13
|
+
* an externally hosted document). Defaults to the well-known path when absent.
|
|
14
|
+
*/
|
|
15
|
+
metadataPath?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Derive the request origin (and thus the advertised `resource`/metadata URLs)
|
|
18
|
+
* from `X-Forwarded-Host` rather than the rewritten `Host`. Stack adapters read
|
|
19
|
+
* this before invoking the handler, so the OAuth runtime never sees it; safe
|
|
20
|
+
* only behind a proxy that overwrites the header (see `core/forwarded.ts`).
|
|
21
|
+
*/
|
|
22
|
+
trustForwardedHost?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type { McpRuntimeOptions as M };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_config_error";
|
|
2
|
+
/** One recorded MCP call. Carries no arguments or response payloads — only the
|
|
3
|
+
* tool name, the JSON-RPC method, the result class, timing, and byte sizes.
|
|
4
|
+
* `errorText` is the sole exception: it is logged locally for debugging and
|
|
5
|
+
* deliberately never included in the OTLP payload (see `emit` / `buildLogsPayload`). */
|
|
6
|
+
interface InvocationRecord {
|
|
7
|
+
/** Tool name for `tools/call`; `null` for list/initialize, transport faults, and auth-config failures. */
|
|
8
|
+
tool: string | null;
|
|
9
|
+
/** JSON-RPC method, e.g. `tools/call`; `authorize` for auth-config failures. */
|
|
10
|
+
method: string;
|
|
11
|
+
outcome: InvocationOutcome;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
reqBytes?: number;
|
|
14
|
+
resBytes?: number;
|
|
15
|
+
/** The app end-user that made the call (the access token `sub`), or
|
|
16
|
+
* `undefined` when the request is unauthenticated. Not a Lovable identity. */
|
|
17
|
+
endUserId?: string;
|
|
18
|
+
/** The `tool_error` message (text content of an `isError` result). Local log
|
|
19
|
+
* only — never sent to the collector, so it stays on-box for the operator. */
|
|
20
|
+
errorText?: string;
|
|
21
|
+
}
|
|
22
|
+
/** A per-request telemetry recorder. `emit` logs the invocation and sends it as a
|
|
23
|
+
* single OTLP POST, awaited so it lands before the request ends. */
|
|
24
|
+
interface MetricsRecorder {
|
|
25
|
+
emit(ev: InvocationRecord): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type { MetricsRecorder as M };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractTextContent
|
|
3
|
+
} from "./chunk-6QFZYYUV.js";
|
|
4
|
+
import {
|
|
5
|
+
ToolContext
|
|
6
|
+
} from "./chunk-MA5H6PSF.js";
|
|
7
|
+
import {
|
|
8
|
+
JSON_HEADERS,
|
|
9
|
+
assertRestResourceBinding,
|
|
10
|
+
corsPreflightResponse,
|
|
11
|
+
createNoopRecorder,
|
|
12
|
+
createRequestAuthorizer,
|
|
13
|
+
methodNotAllowed,
|
|
14
|
+
nowMs,
|
|
15
|
+
withCors
|
|
16
|
+
} from "./chunk-BE6FQG4R.js";
|
|
17
|
+
|
|
18
|
+
// src/protocols/rest/invoke-tool.ts
|
|
19
|
+
import { getParseErrorMessage, objectFromShape, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
20
|
+
var MAX_REFLECTED_TOOL_NAME = 256;
|
|
21
|
+
function safeReflectName(name) {
|
|
22
|
+
const text = String(name);
|
|
23
|
+
return text.length > MAX_REFLECTED_TOOL_NAME ? `${text.slice(0, MAX_REFLECTED_TOOL_NAME)}\u2026` : text;
|
|
24
|
+
}
|
|
25
|
+
function isEmptyArgs(value) {
|
|
26
|
+
if (value == null)
|
|
27
|
+
return true;
|
|
28
|
+
if (typeof value !== "object" || Array.isArray(value))
|
|
29
|
+
return false;
|
|
30
|
+
return Object.keys(value).length === 0;
|
|
31
|
+
}
|
|
32
|
+
function createInvokeToolHandler(mcp, options = {}) {
|
|
33
|
+
assertRestResourceBinding(mcp, options);
|
|
34
|
+
const authorizer = createRequestAuthorizer(mcp, options);
|
|
35
|
+
const handle = async (request, toolName, recorder) => {
|
|
36
|
+
const authResult = await authorizer.authorize(request, recorder);
|
|
37
|
+
if (!authResult.ok)
|
|
38
|
+
return authResult.response;
|
|
39
|
+
const endUserId = authResult.auth?.principal.sub;
|
|
40
|
+
if (request.method !== "POST")
|
|
41
|
+
return methodNotAllowed("POST, OPTIONS");
|
|
42
|
+
const tool = mcp.tools.find((t) => t.name === toolName);
|
|
43
|
+
if (!tool) {
|
|
44
|
+
return new Response(JSON.stringify({ error: `unknown tool: ${safeReflectName(toolName)}` }), {
|
|
45
|
+
status: 404,
|
|
46
|
+
headers: JSON_HEADERS
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
let rawArgs = {};
|
|
50
|
+
const text = await request.text();
|
|
51
|
+
if (text) {
|
|
52
|
+
try {
|
|
53
|
+
rawArgs = JSON.parse(text);
|
|
54
|
+
} catch {
|
|
55
|
+
return new Response(JSON.stringify({ error: "invalid JSON body" }), {
|
|
56
|
+
status: 400,
|
|
57
|
+
headers: JSON_HEADERS
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let args = rawArgs;
|
|
62
|
+
if (tool.inputSchema) {
|
|
63
|
+
try {
|
|
64
|
+
const schema = objectFromShape(tool.inputSchema);
|
|
65
|
+
const parsed = await safeParseAsync(schema, rawArgs);
|
|
66
|
+
if (!parsed.success) {
|
|
67
|
+
return new Response(
|
|
68
|
+
JSON.stringify({
|
|
69
|
+
error: "validation failed",
|
|
70
|
+
details: getParseErrorMessage(parsed.error)
|
|
71
|
+
}),
|
|
72
|
+
{ status: 400, headers: JSON_HEADERS }
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
args = parsed.data;
|
|
76
|
+
} catch {
|
|
77
|
+
return new Response(JSON.stringify({ error: "schema error", tool: toolName }), {
|
|
78
|
+
status: 500,
|
|
79
|
+
headers: JSON_HEADERS
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
} else if (!isEmptyArgs(rawArgs)) {
|
|
83
|
+
return new Response(JSON.stringify({ error: "tool has no inputSchema; expected empty body" }), {
|
|
84
|
+
status: 400,
|
|
85
|
+
headers: JSON_HEADERS
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
let result;
|
|
89
|
+
const start = nowMs();
|
|
90
|
+
try {
|
|
91
|
+
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
92
|
+
} catch {
|
|
93
|
+
await recorder.emit({
|
|
94
|
+
tool: tool.name,
|
|
95
|
+
method: "tools/call",
|
|
96
|
+
outcome: "handler_error",
|
|
97
|
+
durationMs: nowMs() - start,
|
|
98
|
+
endUserId
|
|
99
|
+
});
|
|
100
|
+
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
101
|
+
status: 500,
|
|
102
|
+
headers: JSON_HEADERS
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (result == null) {
|
|
106
|
+
await recorder.emit({
|
|
107
|
+
tool: tool.name,
|
|
108
|
+
method: "tools/call",
|
|
109
|
+
outcome: "handler_error",
|
|
110
|
+
durationMs: nowMs() - start,
|
|
111
|
+
endUserId
|
|
112
|
+
});
|
|
113
|
+
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
114
|
+
status: 500,
|
|
115
|
+
headers: JSON_HEADERS
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
await recorder.emit({
|
|
119
|
+
tool: tool.name,
|
|
120
|
+
method: "tools/call",
|
|
121
|
+
outcome: result.isError ? "tool_error" : "ok",
|
|
122
|
+
durationMs: nowMs() - start,
|
|
123
|
+
errorText: result.isError ? extractTextContent(result.content) : void 0,
|
|
124
|
+
endUserId
|
|
125
|
+
});
|
|
126
|
+
return Response.json({
|
|
127
|
+
content: result.content ?? [],
|
|
128
|
+
structuredContent: result.structuredContent,
|
|
129
|
+
isError: result.isError
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
return async (request, toolName, recorder = createNoopRecorder()) => {
|
|
133
|
+
if (request.method === "OPTIONS")
|
|
134
|
+
return corsPreflightResponse("POST, OPTIONS");
|
|
135
|
+
return withCors(await handle(request, toolName, recorder));
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
createInvokeToolHandler
|
|
141
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/core/content.ts
|
|
2
|
+
function extractTextContent(content) {
|
|
3
|
+
if (!content)
|
|
4
|
+
return void 0;
|
|
5
|
+
const text = content.filter((block) => block.type === "text").map((block) => block.text).join("\n").trim();
|
|
6
|
+
return text.length > 0 ? text : void 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
extractTextContent
|
|
11
|
+
};
|