@setluca/mcp 0.3.0 → 0.3.1
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/CHANGELOG.md +15 -0
- package/dist/http.js +7 -6
- package/dist/remote.js +1 -1
- package/dist/token-verification.js +9 -4
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,21 @@ input schema, or changing what a tool does to a workspace.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.3.1] - 2026-10-06
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Restore authenticated remote MCP discovery and tool calls on Cloudflare.
|
|
18
|
+
Token checks and tool requests now use a direct service binding to Luca's API,
|
|
19
|
+
avoiding the public API's WAF challenge. Both paths use Cloudflare's supported
|
|
20
|
+
manual redirect mode and still reject redirected responses without forwarding
|
|
21
|
+
credentials.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- The remote tool catalog includes explicit safety annotations for directory
|
|
26
|
+
review. The protocol suite checks the published `tools/list` shape.
|
|
27
|
+
|
|
13
28
|
## [0.3.0] - 2026-10-05
|
|
14
29
|
|
|
15
30
|
This is the first Luca MCP release from its own repository. The package and
|
package/dist/http.js
CHANGED
|
@@ -136,17 +136,18 @@ function errorBody(text) {
|
|
|
136
136
|
*/
|
|
137
137
|
const describeUrl = (url) => `${url.origin}${url.pathname}`;
|
|
138
138
|
/** One trip to the API, with no retry and no timeout of its own. */
|
|
139
|
-
function sendOnce(config, input, requestIdempotencyKey) {
|
|
139
|
+
function sendOnce(config, input, requestIdempotencyKey, fetchImpl) {
|
|
140
140
|
return Effect.gen(function* () {
|
|
141
141
|
const url = yield* buildUrl(config, input);
|
|
142
142
|
const init = buildRequestInit(config, input, requestIdempotencyKey);
|
|
143
143
|
const response = yield* Effect.tryPromise({
|
|
144
144
|
try: (signal) =>
|
|
145
145
|
// fallow-ignore-next-line security-sink -- the origin is the configured Luca api base url and the path comes from the generated operation manifest with its params encoded, so a tool argument can never move the destination host
|
|
146
|
-
|
|
146
|
+
fetchImpl(url, {
|
|
147
147
|
...init,
|
|
148
|
-
//
|
|
149
|
-
|
|
148
|
+
// Cloudflare supports manual redirects, not `error`. A 3xx response
|
|
149
|
+
// falls through as an HTTP error without forwarding the API key.
|
|
150
|
+
redirect: "manual",
|
|
150
151
|
signal,
|
|
151
152
|
}),
|
|
152
153
|
catch: (cause) => new LucaNetworkError({
|
|
@@ -190,12 +191,12 @@ function sendOnce(config, input, requestIdempotencyKey) {
|
|
|
190
191
|
}));
|
|
191
192
|
});
|
|
192
193
|
}
|
|
193
|
-
export function createLucaApi(config) {
|
|
194
|
+
export function createLucaApi(config, fetchImpl = fetch) {
|
|
194
195
|
const timeoutMs = config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
195
196
|
return {
|
|
196
197
|
// The key each attempt carries is minted by `resilient`, which also decides
|
|
197
198
|
// whether a failure may be replayed under it.
|
|
198
|
-
request: (input) => resilient(input, timeoutMs, (key) => sendOnce(config, input, key)),
|
|
199
|
+
request: (input) => resilient(input, timeoutMs, (key) => sendOnce(config, input, key, fetchImpl)),
|
|
199
200
|
};
|
|
200
201
|
}
|
|
201
202
|
export const LucaApiLive = Layer.effect(LucaApi, Effect.gen(function* () {
|
package/dist/remote.js
CHANGED
|
@@ -168,7 +168,7 @@ export function createRemoteResponder(options) {
|
|
|
168
168
|
return yield* Effect.fail(invalidToken(options.resourceMetadataUrl));
|
|
169
169
|
}
|
|
170
170
|
const handler = createMcpHandler(() => createLucaServer({
|
|
171
|
-
lucaLayer: Layer.succeed(LucaApi, createLucaApi(config.value)),
|
|
171
|
+
lucaLayer: Layer.succeed(LucaApi, createLucaApi(config.value, options.apiFetch)),
|
|
172
172
|
...optionalField("toolset", options.toolset),
|
|
173
173
|
...optionalField("resourceMetadataUrl", options.resourceMetadataUrl),
|
|
174
174
|
}), { ...optionalField("onerror", options.onError) });
|
|
@@ -16,8 +16,9 @@ export const sha256Hex = (value) => Effect.tryPromise(() => crypto.subtle.digest
|
|
|
16
16
|
* One bounded call to the Luca API that carries a token, with `read` turning
|
|
17
17
|
* the response into the verdict. Timeout but no retry: this is on the auth
|
|
18
18
|
* path of every request, and the client retries a 503 on its own schedule. A
|
|
19
|
-
* redirect is
|
|
20
|
-
* named.
|
|
19
|
+
* redirect is refused, because it would carry the token to a host we never
|
|
20
|
+
* named. Cloudflare Workers does not support `redirect: "error"`, so fetch
|
|
21
|
+
* uses `manual` and we reject 3xx responses before the resolver reads them.
|
|
21
22
|
*/
|
|
22
23
|
export function callApi(settings, fetchImpl, request, read) {
|
|
23
24
|
const controller = new AbortController();
|
|
@@ -25,11 +26,15 @@ export function callApi(settings, fetchImpl, request, read) {
|
|
|
25
26
|
return Effect.tryPromise({
|
|
26
27
|
try: () => fetchImpl(`${settings.apiBaseUrl}${request.path}`, {
|
|
27
28
|
...request.init,
|
|
28
|
-
redirect: "
|
|
29
|
+
redirect: "manual",
|
|
29
30
|
signal: controller.signal,
|
|
30
31
|
}),
|
|
31
32
|
catch: unavailable("Could not reach token verification"),
|
|
32
|
-
}).pipe(Effect.flatMap(
|
|
33
|
+
}).pipe(Effect.flatMap((response) => response.status >= 300 && response.status < 400
|
|
34
|
+
? Effect.fail(new TokenVerificationUnavailable({
|
|
35
|
+
message: "Token verification redirected",
|
|
36
|
+
}))
|
|
37
|
+
: read(response)), Effect.timeoutOrElse({
|
|
33
38
|
duration: Duration.millis(timeoutMs),
|
|
34
39
|
orElse: () => Effect.fail(new TokenVerificationUnavailable({
|
|
35
40
|
message: `Token verification did not answer within ${timeoutMs}ms`,
|
package/dist/version.js
CHANGED
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Bump this in the same commit as package.json and server.json.
|
|
11
11
|
*/
|
|
12
|
-
export const LUCA_MCP_VERSION = "0.3.
|
|
12
|
+
export const LUCA_MCP_VERSION = "0.3.1";
|
|
13
13
|
/** The user-agent every outbound Luca API call identifies itself with. */
|
|
14
14
|
export const LUCA_MCP_USER_AGENT = `luca-mcp/${LUCA_MCP_VERSION}`;
|