@tinycloud/mcp 0.7.4-beta.0 → 0.8.0-beta.2
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 +65 -9
- package/dist/cli.cjs +70 -32
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +71 -33
- package/dist/cli.js.map +1 -1
- package/dist/http-cli.cjs +131 -48
- package/dist/http-cli.cjs.map +1 -1
- package/dist/http-cli.js +129 -46
- package/dist/http-cli.js.map +1 -1
- package/dist/http.cjs +128 -45
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +2 -0
- package/dist/http.d.ts +2 -0
- package/dist/http.js +129 -46
- package/dist/http.js.map +1 -1
- package/dist/index.cjs +128 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +129 -46
- package/dist/index.js.map +1 -1
- package/dist/results.cjs +1 -1
- package/dist/results.cjs.map +1 -1
- package/dist/results.js +1 -1
- package/dist/results.js.map +1 -1
- package/dist/server.cjs +70 -32
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +71 -33
- package/dist/server.js.map +1 -1
- package/dist/tools.cjs +67 -29
- package/dist/tools.cjs.map +1 -1
- package/dist/tools.d.cts +3 -3
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +68 -30
- package/dist/tools.js.map +1 -1
- package/generated/mcp-facts.json +13 -6
- package/package.json +3 -3
- package/skills/tinycloud-delegated-secrets/SKILL.md +4 -4
package/dist/http-cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { isAbsolute, resolve } from "path";
|
|
|
4
4
|
import { toNodeHandler } from "@modelcontextprotocol/node";
|
|
5
5
|
|
|
6
6
|
// src/http.ts
|
|
7
|
+
import { join as join3 } from "path";
|
|
7
8
|
import {
|
|
8
9
|
McpServer as McpServer2,
|
|
9
10
|
createMcpHandler,
|
|
@@ -369,7 +370,7 @@ var RemoteTenantStore = class {
|
|
|
369
370
|
async approvalRedirect(state) {
|
|
370
371
|
const pending = await this.#readPending(state, false);
|
|
371
372
|
const tenant = await this.#readTenant(pending.tenantId);
|
|
372
|
-
const callback = new URL("/connect/callback
|
|
373
|
+
const callback = new URL(`${this.#config.approvalPath ?? "/connect"}/callback`, this.#config.publicUrl);
|
|
373
374
|
callback.searchParams.set("state", state);
|
|
374
375
|
const params = new URLSearchParams({
|
|
375
376
|
did: tenant.sessionDid,
|
|
@@ -788,7 +789,7 @@ var RemoteTenantStore = class {
|
|
|
788
789
|
await rename(`${path}.processing`, path);
|
|
789
790
|
}
|
|
790
791
|
#connectUrl(pending) {
|
|
791
|
-
const url = new URL("/connect", this.#config.publicUrl);
|
|
792
|
+
const url = new URL(this.#config.approvalPath ?? "/connect", this.#config.publicUrl);
|
|
792
793
|
url.searchParams.set("state", `${pending.tenantId}.${pending.nonce}.${this.#signState(pending.tenantId, pending.nonce)}`);
|
|
793
794
|
return url.toString();
|
|
794
795
|
}
|
|
@@ -953,7 +954,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
|
953
954
|
import { createRequire } from "module";
|
|
954
955
|
import { join as join2 } from "path";
|
|
955
956
|
import { fromJsonSchema } from "@modelcontextprotocol/server";
|
|
956
|
-
import {
|
|
957
|
+
import { AjvJsonSchemaValidator } from "@modelcontextprotocol/server/validators/ajv";
|
|
957
958
|
import { invokeOperation as invokeOperation2 } from "@tinycloud/operations";
|
|
958
959
|
|
|
959
960
|
// src/results.ts
|
|
@@ -967,7 +968,7 @@ function toMcpToolResult(result, bindings = [], options = {}) {
|
|
|
967
968
|
let serialized;
|
|
968
969
|
if (options.surface === "hosted") {
|
|
969
970
|
serialized = JSON.stringify(canonical);
|
|
970
|
-
if (options.readOnly === true && serialized.length > 1e5) {
|
|
971
|
+
if ((options.readOnly === true || options.operationId === "tinycloud.apps.context" || options.operationId === "tinycloud.apps.query") && serialized.length > 1e5) {
|
|
971
972
|
const sql = options.operationId?.startsWith("tinycloud.sql.") || options.operationId === "tinycloud.apps.query";
|
|
972
973
|
canonical = {
|
|
973
974
|
status: "error",
|
|
@@ -1021,6 +1022,44 @@ function resultSummary(status) {
|
|
|
1021
1022
|
}
|
|
1022
1023
|
}
|
|
1023
1024
|
|
|
1025
|
+
// src/schemas.ts
|
|
1026
|
+
var DRAFT_7 = "http://json-schema.org/draft-07/schema#";
|
|
1027
|
+
var DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
|
|
1028
|
+
var schemaMaps = /* @__PURE__ */ new Set(["properties", "patternProperties", "definitions", "$defs"]);
|
|
1029
|
+
var schemaArrays = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf"]);
|
|
1030
|
+
var schemaValues = /* @__PURE__ */ new Set([
|
|
1031
|
+
"additionalProperties",
|
|
1032
|
+
"items",
|
|
1033
|
+
"contains",
|
|
1034
|
+
"propertyNames",
|
|
1035
|
+
"not",
|
|
1036
|
+
"if",
|
|
1037
|
+
"then",
|
|
1038
|
+
"else"
|
|
1039
|
+
]);
|
|
1040
|
+
function toMcpJsonSchema(schema) {
|
|
1041
|
+
if (typeof schema === "boolean") return schema;
|
|
1042
|
+
if (Array.isArray(schema.items) || "additionalItems" in schema || "dependencies" in schema || "$ref" in schema && Object.keys(schema).some((key) => key !== "$ref")) {
|
|
1043
|
+
throw new Error("The operations schema needs a semantic migration to JSON Schema 2020-12.");
|
|
1044
|
+
}
|
|
1045
|
+
const projected = {};
|
|
1046
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
1047
|
+
if (key === "$schema") {
|
|
1048
|
+
if (value !== DRAFT_7) throw new Error(`Unsupported operations schema dialect: ${String(value)}.`);
|
|
1049
|
+
projected[key] = DRAFT_2020_12;
|
|
1050
|
+
} else if (schemaMaps.has(key)) {
|
|
1051
|
+
projected[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [name, toMcpJsonSchema(child)]));
|
|
1052
|
+
} else if (schemaArrays.has(key)) {
|
|
1053
|
+
projected[key] = value.map(toMcpJsonSchema);
|
|
1054
|
+
} else if (schemaValues.has(key)) {
|
|
1055
|
+
projected[key] = toMcpJsonSchema(value);
|
|
1056
|
+
} else {
|
|
1057
|
+
projected[key] = value;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return projected;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1024
1063
|
// src/tools.ts
|
|
1025
1064
|
function invocationTargetForMcp(selection) {
|
|
1026
1065
|
return {
|
|
@@ -1038,9 +1077,9 @@ var generatedCatalog = packageRequire(
|
|
|
1038
1077
|
var stableErrorCodes = Object.fromEntries(
|
|
1039
1078
|
generatedCatalog.stableErrors.map((code) => [code, true])
|
|
1040
1079
|
);
|
|
1041
|
-
var
|
|
1080
|
+
var PRIVATE_SURFACES = ["local", "hosted"];
|
|
1042
1081
|
function bindingSurfaces(binding) {
|
|
1043
|
-
return binding.surfaces ??
|
|
1082
|
+
return binding.surfaces ?? PRIVATE_SURFACES;
|
|
1044
1083
|
}
|
|
1045
1084
|
var TOOL_BINDINGS = [
|
|
1046
1085
|
{
|
|
@@ -1224,11 +1263,11 @@ var TOOL_BINDINGS = [
|
|
|
1224
1263
|
name: "tinycloud_apps_context",
|
|
1225
1264
|
operationId: "tinycloud.apps.context",
|
|
1226
1265
|
operationVersion: 1,
|
|
1227
|
-
readOnlyHint:
|
|
1266
|
+
readOnlyHint: false,
|
|
1228
1267
|
idempotentHint: true,
|
|
1229
|
-
destructiveHint:
|
|
1230
|
-
openWorldHint:
|
|
1231
|
-
surfaces: ["hosted"]
|
|
1268
|
+
destructiveHint: true,
|
|
1269
|
+
openWorldHint: false,
|
|
1270
|
+
surfaces: ["hosted", "public"]
|
|
1232
1271
|
},
|
|
1233
1272
|
{
|
|
1234
1273
|
name: "tinycloud_apps_read",
|
|
@@ -1237,8 +1276,8 @@ var TOOL_BINDINGS = [
|
|
|
1237
1276
|
readOnlyHint: true,
|
|
1238
1277
|
idempotentHint: true,
|
|
1239
1278
|
destructiveHint: false,
|
|
1240
|
-
openWorldHint:
|
|
1241
|
-
surfaces: ["hosted"]
|
|
1279
|
+
openWorldHint: false,
|
|
1280
|
+
surfaces: ["hosted", "public"]
|
|
1242
1281
|
},
|
|
1243
1282
|
{
|
|
1244
1283
|
name: "tinycloud_apps_write",
|
|
@@ -1247,34 +1286,34 @@ var TOOL_BINDINGS = [
|
|
|
1247
1286
|
readOnlyHint: false,
|
|
1248
1287
|
idempotentHint: false,
|
|
1249
1288
|
destructiveHint: true,
|
|
1250
|
-
openWorldHint:
|
|
1251
|
-
surfaces: ["hosted"]
|
|
1289
|
+
openWorldHint: false,
|
|
1290
|
+
surfaces: ["hosted", "public"]
|
|
1252
1291
|
},
|
|
1253
1292
|
{
|
|
1254
1293
|
name: "tinycloud_apps_query",
|
|
1255
1294
|
operationId: "tinycloud.apps.query",
|
|
1256
1295
|
operationVersion: 1,
|
|
1257
|
-
readOnlyHint:
|
|
1296
|
+
readOnlyHint: false,
|
|
1258
1297
|
idempotentHint: true,
|
|
1259
|
-
destructiveHint:
|
|
1260
|
-
openWorldHint:
|
|
1261
|
-
surfaces: ["hosted"]
|
|
1298
|
+
destructiveHint: true,
|
|
1299
|
+
openWorldHint: false,
|
|
1300
|
+
surfaces: ["hosted", "public"]
|
|
1262
1301
|
}
|
|
1263
1302
|
];
|
|
1303
|
+
var definitions = new Map(generatedCatalog.operations.map((operation) => [
|
|
1304
|
+
`${operation.id}@${operation.version}`,
|
|
1305
|
+
{
|
|
1306
|
+
...operation,
|
|
1307
|
+
input: toMcpJsonSchema(operation.input),
|
|
1308
|
+
result: toMcpJsonSchema(operation.result)
|
|
1309
|
+
}
|
|
1310
|
+
]));
|
|
1264
1311
|
function createJsonSchemaValidator() {
|
|
1265
|
-
|
|
1266
|
-
addFormats(ajv);
|
|
1267
|
-
return new AjvJsonSchemaValidator(ajv);
|
|
1312
|
+
return new AjvJsonSchemaValidator();
|
|
1268
1313
|
}
|
|
1269
1314
|
function registerTinyCloudTools(server, selection, validator) {
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
`${operation.id}@${operation.version}`,
|
|
1273
|
-
operation
|
|
1274
|
-
])
|
|
1275
|
-
);
|
|
1276
|
-
for (const binding of TOOL_BINDINGS) {
|
|
1277
|
-
if (!bindingSurfaces(binding).includes(selection.surface)) continue;
|
|
1315
|
+
const bindings = TOOL_BINDINGS.filter((binding) => bindingSurfaces(binding).includes(selection.surface));
|
|
1316
|
+
for (const binding of bindings) {
|
|
1278
1317
|
const operation = definitions.get(`${binding.operationId}@${binding.operationVersion}`);
|
|
1279
1318
|
if (operation === void 0) {
|
|
1280
1319
|
throw new Error(`Generated operations catalog is missing ${binding.operationId}@${binding.operationVersion}.`);
|
|
@@ -1320,15 +1359,15 @@ function registerTinyCloudTools(server, selection, validator) {
|
|
|
1320
1359
|
operationVersion: binding.operationVersion,
|
|
1321
1360
|
input
|
|
1322
1361
|
});
|
|
1323
|
-
const response = toMcpToolResult(projected,
|
|
1324
|
-
surface: selection.surface,
|
|
1362
|
+
const response = toMcpToolResult(projected, bindings, {
|
|
1363
|
+
surface: selection.surface === "local" ? "local" : "hosted",
|
|
1325
1364
|
readOnly: binding.readOnlyHint,
|
|
1326
1365
|
operationId: binding.operationId
|
|
1327
1366
|
});
|
|
1328
1367
|
code = outcomeCode(response.structuredContent);
|
|
1329
1368
|
return response;
|
|
1330
1369
|
} finally {
|
|
1331
|
-
if (selection.surface
|
|
1370
|
+
if (selection.surface !== "local") {
|
|
1332
1371
|
logToolCall(binding.name, code, startedAt, metrics.replayedGrants);
|
|
1333
1372
|
}
|
|
1334
1373
|
}
|
|
@@ -1351,7 +1390,7 @@ function outcomeCode(result) {
|
|
|
1351
1390
|
// package.json
|
|
1352
1391
|
var package_default = {
|
|
1353
1392
|
name: "@tinycloud/mcp",
|
|
1354
|
-
version: "0.
|
|
1393
|
+
version: "0.8.0-beta.2",
|
|
1355
1394
|
description: "TinyCloud delegated operations MCP server",
|
|
1356
1395
|
keywords: [
|
|
1357
1396
|
"tinycloud",
|
|
@@ -1422,9 +1461,9 @@ var package_default = {
|
|
|
1422
1461
|
dependencies: {
|
|
1423
1462
|
"@modelcontextprotocol/node": "2.0.0-beta.5",
|
|
1424
1463
|
"@modelcontextprotocol/server": "2.0.0-beta.5",
|
|
1425
|
-
"@tinycloud/node-sdk": "3.6.0-beta.
|
|
1464
|
+
"@tinycloud/node-sdk": "3.6.0-beta.2",
|
|
1426
1465
|
"@tinycloud/node-sdk-wasm": "1.7.8",
|
|
1427
|
-
"@tinycloud/operations": "0.7.4-beta.
|
|
1466
|
+
"@tinycloud/operations": "0.7.4-beta.2",
|
|
1428
1467
|
jose: "6.2.4"
|
|
1429
1468
|
},
|
|
1430
1469
|
devDependencies: {
|
|
@@ -1450,6 +1489,29 @@ var MCP_SERVER_NAME = "tinycloud-mcp";
|
|
|
1450
1489
|
var REQUIRED_SCOPE = "tinycloud:mcp";
|
|
1451
1490
|
function createHostedMcpApp(config) {
|
|
1452
1491
|
const resourceUrl = canonicalResourceUrl(config.publicUrl);
|
|
1492
|
+
const pluginUrl = new URL("./chatgpt/mcp", resourceUrl);
|
|
1493
|
+
const hosted = createHostedSurface(config, resourceUrl, "hosted");
|
|
1494
|
+
const plugin = createHostedSurface({
|
|
1495
|
+
...config,
|
|
1496
|
+
stateDir: join3(config.stateDir, "chatgpt"),
|
|
1497
|
+
approvalPath: new URL("./connect", pluginUrl).pathname
|
|
1498
|
+
}, pluginUrl, "public");
|
|
1499
|
+
const pluginPaths = {
|
|
1500
|
+
[pluginUrl.pathname]: true,
|
|
1501
|
+
[new URL("./connect", pluginUrl).pathname]: true,
|
|
1502
|
+
[new URL("./connect/callback", pluginUrl).pathname]: true,
|
|
1503
|
+
[new URL(getOAuthProtectedResourceMetadataUrl(pluginUrl)).pathname]: true
|
|
1504
|
+
};
|
|
1505
|
+
return {
|
|
1506
|
+
fetch: (request) => (pluginPaths[new URL(request.url).pathname] === true ? plugin : hosted).fetch(request),
|
|
1507
|
+
close: async () => {
|
|
1508
|
+
await Promise.all([hosted.close(), plugin.close()]);
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
function createHostedSurface(config, resourceUrl, surface) {
|
|
1513
|
+
const connectPath = config.approvalPath ?? "/connect";
|
|
1514
|
+
const callbackPath = `${connectPath}/callback`;
|
|
1453
1515
|
const issuer = String(config.oauthMetadata.issuer);
|
|
1454
1516
|
const jwksUri = String(config.oauthMetadata.jwks_uri);
|
|
1455
1517
|
const verifier = createOpenKeyTokenVerifier({
|
|
@@ -1474,11 +1536,11 @@ function createHostedMcpApp(config) {
|
|
|
1474
1536
|
{ name: MCP_SERVER_NAME, version: MCP_VERSION },
|
|
1475
1537
|
{
|
|
1476
1538
|
jsonSchemaValidator: validator,
|
|
1477
|
-
instructions: "Call tinycloud_connect first. If an operation returns authority_required, open approval.url, then retry that operation unchanged. For personal records such as weight, workouts, goals or todos, call tinycloud_apps_context first."
|
|
1539
|
+
instructions: surface === "public" ? "Use TinyCloud only for the user's requested task. Call tinycloud_connect first. If an operation returns authority_required, present approval.url and wait for the user's approval before retrying. If approval is declined, stop that operation. For personal records, call tinycloud_apps_context first. Never request or store passwords, API keys, authentication codes, government identifiers, payment-card data, or protected health information." : "Call tinycloud_connect first. If an operation returns authority_required, open approval.url, then retry that operation unchanged. For personal records such as weight, workouts, goals or todos, call tinycloud_apps_context first."
|
|
1478
1540
|
}
|
|
1479
1541
|
);
|
|
1480
1542
|
registerTinyCloudTools(server, {
|
|
1481
|
-
surface
|
|
1543
|
+
surface,
|
|
1482
1544
|
profile: "agent",
|
|
1483
1545
|
explicitProfile: true,
|
|
1484
1546
|
allowOwnerProfile: false,
|
|
@@ -1486,7 +1548,7 @@ function createHostedMcpApp(config) {
|
|
|
1486
1548
|
beforeOperation: () => store.validateTenant(subject, ownerDids),
|
|
1487
1549
|
transformOperationResult: (result, invocation) => store.decorateAuthorityResult(subject, ownerDids, result, invocation)
|
|
1488
1550
|
}, validator);
|
|
1489
|
-
registerConnectTool(server, validator, store, identity);
|
|
1551
|
+
registerConnectTool(server, validator, store, identity, surface);
|
|
1490
1552
|
return server;
|
|
1491
1553
|
}, {
|
|
1492
1554
|
legacy: "stateless",
|
|
@@ -1497,7 +1559,7 @@ function createHostedMcpApp(config) {
|
|
|
1497
1559
|
resourceServerUrl: resourceUrl,
|
|
1498
1560
|
serviceDocumentationUrl: new URL("https://docs.tinycloud.xyz/cli/mcp"),
|
|
1499
1561
|
scopesSupported: [REQUIRED_SCOPE],
|
|
1500
|
-
resourceName: "TinyCloud hosted MCP"
|
|
1562
|
+
resourceName: surface === "public" ? "TinyCloud personal records" : "TinyCloud hosted MCP"
|
|
1501
1563
|
};
|
|
1502
1564
|
const allowedHosts = [resourceUrl.hostname];
|
|
1503
1565
|
return {
|
|
@@ -1510,16 +1572,32 @@ function createHostedMcpApp(config) {
|
|
|
1510
1572
|
}
|
|
1511
1573
|
const hostFailure = hostHeaderValidationResponse(request, allowedHosts);
|
|
1512
1574
|
if (hostFailure !== void 0) return hostFailure;
|
|
1513
|
-
if (url.pathname ===
|
|
1575
|
+
if (url.pathname === connectPath) {
|
|
1514
1576
|
if (request.method !== "GET") return methodNotAllowed("GET");
|
|
1515
1577
|
try {
|
|
1516
1578
|
const destination = await store.approvalRedirect(requiredState(url));
|
|
1517
1579
|
return Response.redirect(destination, 302);
|
|
1518
1580
|
} catch {
|
|
1581
|
+
if (request.headers.get("accept")?.includes("text/html")) {
|
|
1582
|
+
return new Response(
|
|
1583
|
+
'<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>TinyCloud approval unavailable</title><main><h1>This approval link is unavailable</h1><p>It may have expired or already been used. No new approval was accepted through this link.</p><p>Return to the conversation that requested access. In ChatGPT, select @TinyCloud and ask it to continue your original request. If access is still needed, it can provide a fresh approval link.</p><p>If you declined access, no further approval is required. Never paste passwords, codes or approval links into support messages.</p></main></html>',
|
|
1584
|
+
{
|
|
1585
|
+
status: 400,
|
|
1586
|
+
headers: {
|
|
1587
|
+
"content-type": "text/html; charset=utf-8",
|
|
1588
|
+
"cache-control": "no-store",
|
|
1589
|
+
"content-security-policy": "default-src 'none'; base-uri 'none'; frame-ancestors 'none'",
|
|
1590
|
+
"referrer-policy": "no-referrer",
|
|
1591
|
+
"x-content-type-options": "nosniff",
|
|
1592
|
+
vary: "Accept"
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1519
1597
|
return json({ error: "The approval link is invalid or expired." }, 400);
|
|
1520
1598
|
}
|
|
1521
1599
|
}
|
|
1522
|
-
if (url.pathname ===
|
|
1600
|
+
if (url.pathname === callbackPath) {
|
|
1523
1601
|
if (request.method === "OPTIONS") return callbackCors(new Response(null, { status: 204 }), config.openkeyHost);
|
|
1524
1602
|
if (request.method !== "POST") return methodNotAllowed("POST");
|
|
1525
1603
|
const originFailure2 = validateCallbackOrigin(request, config.openkeyHost);
|
|
@@ -1559,17 +1637,17 @@ function createHostedMcpApp(config) {
|
|
|
1559
1637
|
close: () => handler.close()
|
|
1560
1638
|
};
|
|
1561
1639
|
}
|
|
1562
|
-
function registerConnectTool(server, validator, store, identity) {
|
|
1640
|
+
function registerConnectTool(server, validator, store, identity, surface) {
|
|
1563
1641
|
const inputSchema = fromJsonSchema2({ type: "object", properties: {}, additionalProperties: false }, validator);
|
|
1564
1642
|
const outputSchema = fromJsonSchema2({
|
|
1565
1643
|
type: "object",
|
|
1566
1644
|
properties: {
|
|
1567
1645
|
connected: { type: "boolean" },
|
|
1568
|
-
sessionDid: { type: "string" },
|
|
1646
|
+
...surface === "hosted" ? { sessionDid: { type: "string" } } : {},
|
|
1569
1647
|
approvalUrl: { type: "string", format: "uri" },
|
|
1570
1648
|
expiresAt: { type: "string", format: "date-time" }
|
|
1571
1649
|
},
|
|
1572
|
-
required: ["connected", "sessionDid"],
|
|
1650
|
+
required: surface === "hosted" ? ["connected", "sessionDid"] : ["connected"],
|
|
1573
1651
|
additionalProperties: false
|
|
1574
1652
|
}, validator);
|
|
1575
1653
|
server.registerTool(
|
|
@@ -1583,7 +1661,7 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1583
1661
|
readOnlyHint: false,
|
|
1584
1662
|
idempotentHint: true,
|
|
1585
1663
|
destructiveHint: false,
|
|
1586
|
-
openWorldHint:
|
|
1664
|
+
openWorldHint: false
|
|
1587
1665
|
}
|
|
1588
1666
|
},
|
|
1589
1667
|
async () => {
|
|
@@ -1592,12 +1670,17 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1592
1670
|
try {
|
|
1593
1671
|
const status = await store.connectStatus(identity.subject, identity.ownerDids);
|
|
1594
1672
|
code = status.connected ? "ok" : "authority_required";
|
|
1673
|
+
const visibleStatus = surface === "hosted" ? status : {
|
|
1674
|
+
connected: status.connected,
|
|
1675
|
+
...status.approvalUrl === void 0 ? {} : { approvalUrl: status.approvalUrl },
|
|
1676
|
+
...status.expiresAt === void 0 ? {} : { expiresAt: status.expiresAt }
|
|
1677
|
+
};
|
|
1595
1678
|
return {
|
|
1596
1679
|
content: [{
|
|
1597
1680
|
type: "text",
|
|
1598
1681
|
text: status.connected ? "TinyCloud is connected." : `TinyCloud approval is required. Open ${status.approvalUrl}, then call this tool again. This link expires at ${status.expiresAt}.`
|
|
1599
1682
|
}],
|
|
1600
|
-
structuredContent:
|
|
1683
|
+
structuredContent: visibleStatus
|
|
1601
1684
|
};
|
|
1602
1685
|
} finally {
|
|
1603
1686
|
logToolCall("tinycloud_connect", code, startedAt, 0);
|