@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.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(http_exports, {
|
|
|
23
23
|
createHostedMcpApp: () => createHostedMcpApp
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(http_exports);
|
|
26
|
+
var import_node_path3 = require("path");
|
|
26
27
|
var import_server4 = require("@modelcontextprotocol/server");
|
|
27
28
|
var import_node_sdk3 = require("@tinycloud/node-sdk");
|
|
28
29
|
|
|
@@ -356,7 +357,7 @@ var RemoteTenantStore = class {
|
|
|
356
357
|
async approvalRedirect(state) {
|
|
357
358
|
const pending = await this.#readPending(state, false);
|
|
358
359
|
const tenant = await this.#readTenant(pending.tenantId);
|
|
359
|
-
const callback = new URL("/connect/callback
|
|
360
|
+
const callback = new URL(`${this.#config.approvalPath ?? "/connect"}/callback`, this.#config.publicUrl);
|
|
360
361
|
callback.searchParams.set("state", state);
|
|
361
362
|
const params = new URLSearchParams({
|
|
362
363
|
did: tenant.sessionDid,
|
|
@@ -775,7 +776,7 @@ var RemoteTenantStore = class {
|
|
|
775
776
|
await (0, import_promises.rename)(`${path}.processing`, path);
|
|
776
777
|
}
|
|
777
778
|
#connectUrl(pending) {
|
|
778
|
-
const url = new URL("/connect", this.#config.publicUrl);
|
|
779
|
+
const url = new URL(this.#config.approvalPath ?? "/connect", this.#config.publicUrl);
|
|
779
780
|
url.searchParams.set("state", `${pending.tenantId}.${pending.nonce}.${this.#signState(pending.tenantId, pending.nonce)}`);
|
|
780
781
|
return url.toString();
|
|
781
782
|
}
|
|
@@ -954,7 +955,7 @@ function toMcpToolResult(result, bindings = [], options = {}) {
|
|
|
954
955
|
let serialized;
|
|
955
956
|
if (options.surface === "hosted") {
|
|
956
957
|
serialized = JSON.stringify(canonical);
|
|
957
|
-
if (options.readOnly === true && serialized.length > 1e5) {
|
|
958
|
+
if ((options.readOnly === true || options.operationId === "tinycloud.apps.context" || options.operationId === "tinycloud.apps.query") && serialized.length > 1e5) {
|
|
958
959
|
const sql = options.operationId?.startsWith("tinycloud.sql.") || options.operationId === "tinycloud.apps.query";
|
|
959
960
|
canonical = {
|
|
960
961
|
status: "error",
|
|
@@ -1008,6 +1009,44 @@ function resultSummary(status) {
|
|
|
1008
1009
|
}
|
|
1009
1010
|
}
|
|
1010
1011
|
|
|
1012
|
+
// src/schemas.ts
|
|
1013
|
+
var DRAFT_7 = "http://json-schema.org/draft-07/schema#";
|
|
1014
|
+
var DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
|
|
1015
|
+
var schemaMaps = /* @__PURE__ */ new Set(["properties", "patternProperties", "definitions", "$defs"]);
|
|
1016
|
+
var schemaArrays = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf"]);
|
|
1017
|
+
var schemaValues = /* @__PURE__ */ new Set([
|
|
1018
|
+
"additionalProperties",
|
|
1019
|
+
"items",
|
|
1020
|
+
"contains",
|
|
1021
|
+
"propertyNames",
|
|
1022
|
+
"not",
|
|
1023
|
+
"if",
|
|
1024
|
+
"then",
|
|
1025
|
+
"else"
|
|
1026
|
+
]);
|
|
1027
|
+
function toMcpJsonSchema(schema) {
|
|
1028
|
+
if (typeof schema === "boolean") return schema;
|
|
1029
|
+
if (Array.isArray(schema.items) || "additionalItems" in schema || "dependencies" in schema || "$ref" in schema && Object.keys(schema).some((key) => key !== "$ref")) {
|
|
1030
|
+
throw new Error("The operations schema needs a semantic migration to JSON Schema 2020-12.");
|
|
1031
|
+
}
|
|
1032
|
+
const projected = {};
|
|
1033
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
1034
|
+
if (key === "$schema") {
|
|
1035
|
+
if (value !== DRAFT_7) throw new Error(`Unsupported operations schema dialect: ${String(value)}.`);
|
|
1036
|
+
projected[key] = DRAFT_2020_12;
|
|
1037
|
+
} else if (schemaMaps.has(key)) {
|
|
1038
|
+
projected[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [name, toMcpJsonSchema(child)]));
|
|
1039
|
+
} else if (schemaArrays.has(key)) {
|
|
1040
|
+
projected[key] = value.map(toMcpJsonSchema);
|
|
1041
|
+
} else if (schemaValues.has(key)) {
|
|
1042
|
+
projected[key] = toMcpJsonSchema(value);
|
|
1043
|
+
} else {
|
|
1044
|
+
projected[key] = value;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
return projected;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1011
1050
|
// src/tools.ts
|
|
1012
1051
|
var import_meta = {};
|
|
1013
1052
|
function invocationTargetForMcp(selection) {
|
|
@@ -1026,9 +1065,9 @@ var generatedCatalog = packageRequire(
|
|
|
1026
1065
|
var stableErrorCodes = Object.fromEntries(
|
|
1027
1066
|
generatedCatalog.stableErrors.map((code) => [code, true])
|
|
1028
1067
|
);
|
|
1029
|
-
var
|
|
1068
|
+
var PRIVATE_SURFACES = ["local", "hosted"];
|
|
1030
1069
|
function bindingSurfaces(binding) {
|
|
1031
|
-
return binding.surfaces ??
|
|
1070
|
+
return binding.surfaces ?? PRIVATE_SURFACES;
|
|
1032
1071
|
}
|
|
1033
1072
|
var TOOL_BINDINGS = [
|
|
1034
1073
|
{
|
|
@@ -1212,11 +1251,11 @@ var TOOL_BINDINGS = [
|
|
|
1212
1251
|
name: "tinycloud_apps_context",
|
|
1213
1252
|
operationId: "tinycloud.apps.context",
|
|
1214
1253
|
operationVersion: 1,
|
|
1215
|
-
readOnlyHint:
|
|
1254
|
+
readOnlyHint: false,
|
|
1216
1255
|
idempotentHint: true,
|
|
1217
|
-
destructiveHint:
|
|
1218
|
-
openWorldHint:
|
|
1219
|
-
surfaces: ["hosted"]
|
|
1256
|
+
destructiveHint: true,
|
|
1257
|
+
openWorldHint: false,
|
|
1258
|
+
surfaces: ["hosted", "public"]
|
|
1220
1259
|
},
|
|
1221
1260
|
{
|
|
1222
1261
|
name: "tinycloud_apps_read",
|
|
@@ -1225,8 +1264,8 @@ var TOOL_BINDINGS = [
|
|
|
1225
1264
|
readOnlyHint: true,
|
|
1226
1265
|
idempotentHint: true,
|
|
1227
1266
|
destructiveHint: false,
|
|
1228
|
-
openWorldHint:
|
|
1229
|
-
surfaces: ["hosted"]
|
|
1267
|
+
openWorldHint: false,
|
|
1268
|
+
surfaces: ["hosted", "public"]
|
|
1230
1269
|
},
|
|
1231
1270
|
{
|
|
1232
1271
|
name: "tinycloud_apps_write",
|
|
@@ -1235,34 +1274,34 @@ var TOOL_BINDINGS = [
|
|
|
1235
1274
|
readOnlyHint: false,
|
|
1236
1275
|
idempotentHint: false,
|
|
1237
1276
|
destructiveHint: true,
|
|
1238
|
-
openWorldHint:
|
|
1239
|
-
surfaces: ["hosted"]
|
|
1277
|
+
openWorldHint: false,
|
|
1278
|
+
surfaces: ["hosted", "public"]
|
|
1240
1279
|
},
|
|
1241
1280
|
{
|
|
1242
1281
|
name: "tinycloud_apps_query",
|
|
1243
1282
|
operationId: "tinycloud.apps.query",
|
|
1244
1283
|
operationVersion: 1,
|
|
1245
|
-
readOnlyHint:
|
|
1284
|
+
readOnlyHint: false,
|
|
1246
1285
|
idempotentHint: true,
|
|
1247
|
-
destructiveHint:
|
|
1248
|
-
openWorldHint:
|
|
1249
|
-
surfaces: ["hosted"]
|
|
1286
|
+
destructiveHint: true,
|
|
1287
|
+
openWorldHint: false,
|
|
1288
|
+
surfaces: ["hosted", "public"]
|
|
1250
1289
|
}
|
|
1251
1290
|
];
|
|
1291
|
+
var definitions = new Map(generatedCatalog.operations.map((operation) => [
|
|
1292
|
+
`${operation.id}@${operation.version}`,
|
|
1293
|
+
{
|
|
1294
|
+
...operation,
|
|
1295
|
+
input: toMcpJsonSchema(operation.input),
|
|
1296
|
+
result: toMcpJsonSchema(operation.result)
|
|
1297
|
+
}
|
|
1298
|
+
]));
|
|
1252
1299
|
function createJsonSchemaValidator() {
|
|
1253
|
-
|
|
1254
|
-
(0, import_ajv.addFormats)(ajv);
|
|
1255
|
-
return new import_ajv.AjvJsonSchemaValidator(ajv);
|
|
1300
|
+
return new import_ajv.AjvJsonSchemaValidator();
|
|
1256
1301
|
}
|
|
1257
1302
|
function registerTinyCloudTools(server, selection, validator) {
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
`${operation.id}@${operation.version}`,
|
|
1261
|
-
operation
|
|
1262
|
-
])
|
|
1263
|
-
);
|
|
1264
|
-
for (const binding of TOOL_BINDINGS) {
|
|
1265
|
-
if (!bindingSurfaces(binding).includes(selection.surface)) continue;
|
|
1303
|
+
const bindings = TOOL_BINDINGS.filter((binding) => bindingSurfaces(binding).includes(selection.surface));
|
|
1304
|
+
for (const binding of bindings) {
|
|
1266
1305
|
const operation = definitions.get(`${binding.operationId}@${binding.operationVersion}`);
|
|
1267
1306
|
if (operation === void 0) {
|
|
1268
1307
|
throw new Error(`Generated operations catalog is missing ${binding.operationId}@${binding.operationVersion}.`);
|
|
@@ -1308,15 +1347,15 @@ function registerTinyCloudTools(server, selection, validator) {
|
|
|
1308
1347
|
operationVersion: binding.operationVersion,
|
|
1309
1348
|
input
|
|
1310
1349
|
});
|
|
1311
|
-
const response = toMcpToolResult(projected,
|
|
1312
|
-
surface: selection.surface,
|
|
1350
|
+
const response = toMcpToolResult(projected, bindings, {
|
|
1351
|
+
surface: selection.surface === "local" ? "local" : "hosted",
|
|
1313
1352
|
readOnly: binding.readOnlyHint,
|
|
1314
1353
|
operationId: binding.operationId
|
|
1315
1354
|
});
|
|
1316
1355
|
code = outcomeCode(response.structuredContent);
|
|
1317
1356
|
return response;
|
|
1318
1357
|
} finally {
|
|
1319
|
-
if (selection.surface
|
|
1358
|
+
if (selection.surface !== "local") {
|
|
1320
1359
|
logToolCall(binding.name, code, startedAt, metrics.replayedGrants);
|
|
1321
1360
|
}
|
|
1322
1361
|
}
|
|
@@ -1339,7 +1378,7 @@ function outcomeCode(result) {
|
|
|
1339
1378
|
// package.json
|
|
1340
1379
|
var package_default = {
|
|
1341
1380
|
name: "@tinycloud/mcp",
|
|
1342
|
-
version: "0.
|
|
1381
|
+
version: "0.8.0-beta.2",
|
|
1343
1382
|
description: "TinyCloud delegated operations MCP server",
|
|
1344
1383
|
keywords: [
|
|
1345
1384
|
"tinycloud",
|
|
@@ -1410,9 +1449,9 @@ var package_default = {
|
|
|
1410
1449
|
dependencies: {
|
|
1411
1450
|
"@modelcontextprotocol/node": "2.0.0-beta.5",
|
|
1412
1451
|
"@modelcontextprotocol/server": "2.0.0-beta.5",
|
|
1413
|
-
"@tinycloud/node-sdk": "3.6.0-beta.
|
|
1452
|
+
"@tinycloud/node-sdk": "3.6.0-beta.2",
|
|
1414
1453
|
"@tinycloud/node-sdk-wasm": "1.7.8",
|
|
1415
|
-
"@tinycloud/operations": "0.7.4-beta.
|
|
1454
|
+
"@tinycloud/operations": "0.7.4-beta.2",
|
|
1416
1455
|
jose: "6.2.4"
|
|
1417
1456
|
},
|
|
1418
1457
|
devDependencies: {
|
|
@@ -1438,6 +1477,29 @@ var MCP_SERVER_NAME = "tinycloud-mcp";
|
|
|
1438
1477
|
var REQUIRED_SCOPE = "tinycloud:mcp";
|
|
1439
1478
|
function createHostedMcpApp(config) {
|
|
1440
1479
|
const resourceUrl = canonicalResourceUrl(config.publicUrl);
|
|
1480
|
+
const pluginUrl = new URL("./chatgpt/mcp", resourceUrl);
|
|
1481
|
+
const hosted = createHostedSurface(config, resourceUrl, "hosted");
|
|
1482
|
+
const plugin = createHostedSurface({
|
|
1483
|
+
...config,
|
|
1484
|
+
stateDir: (0, import_node_path3.join)(config.stateDir, "chatgpt"),
|
|
1485
|
+
approvalPath: new URL("./connect", pluginUrl).pathname
|
|
1486
|
+
}, pluginUrl, "public");
|
|
1487
|
+
const pluginPaths = {
|
|
1488
|
+
[pluginUrl.pathname]: true,
|
|
1489
|
+
[new URL("./connect", pluginUrl).pathname]: true,
|
|
1490
|
+
[new URL("./connect/callback", pluginUrl).pathname]: true,
|
|
1491
|
+
[new URL((0, import_server4.getOAuthProtectedResourceMetadataUrl)(pluginUrl)).pathname]: true
|
|
1492
|
+
};
|
|
1493
|
+
return {
|
|
1494
|
+
fetch: (request) => (pluginPaths[new URL(request.url).pathname] === true ? plugin : hosted).fetch(request),
|
|
1495
|
+
close: async () => {
|
|
1496
|
+
await Promise.all([hosted.close(), plugin.close()]);
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
function createHostedSurface(config, resourceUrl, surface) {
|
|
1501
|
+
const connectPath = config.approvalPath ?? "/connect";
|
|
1502
|
+
const callbackPath = `${connectPath}/callback`;
|
|
1441
1503
|
const issuer = String(config.oauthMetadata.issuer);
|
|
1442
1504
|
const jwksUri = String(config.oauthMetadata.jwks_uri);
|
|
1443
1505
|
const verifier = createOpenKeyTokenVerifier({
|
|
@@ -1462,11 +1524,11 @@ function createHostedMcpApp(config) {
|
|
|
1462
1524
|
{ name: MCP_SERVER_NAME, version: MCP_VERSION },
|
|
1463
1525
|
{
|
|
1464
1526
|
jsonSchemaValidator: validator,
|
|
1465
|
-
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."
|
|
1527
|
+
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."
|
|
1466
1528
|
}
|
|
1467
1529
|
);
|
|
1468
1530
|
registerTinyCloudTools(server, {
|
|
1469
|
-
surface
|
|
1531
|
+
surface,
|
|
1470
1532
|
profile: "agent",
|
|
1471
1533
|
explicitProfile: true,
|
|
1472
1534
|
allowOwnerProfile: false,
|
|
@@ -1474,7 +1536,7 @@ function createHostedMcpApp(config) {
|
|
|
1474
1536
|
beforeOperation: () => store.validateTenant(subject, ownerDids),
|
|
1475
1537
|
transformOperationResult: (result, invocation) => store.decorateAuthorityResult(subject, ownerDids, result, invocation)
|
|
1476
1538
|
}, validator);
|
|
1477
|
-
registerConnectTool(server, validator, store, identity);
|
|
1539
|
+
registerConnectTool(server, validator, store, identity, surface);
|
|
1478
1540
|
return server;
|
|
1479
1541
|
}, {
|
|
1480
1542
|
legacy: "stateless",
|
|
@@ -1485,7 +1547,7 @@ function createHostedMcpApp(config) {
|
|
|
1485
1547
|
resourceServerUrl: resourceUrl,
|
|
1486
1548
|
serviceDocumentationUrl: new URL("https://docs.tinycloud.xyz/cli/mcp"),
|
|
1487
1549
|
scopesSupported: [REQUIRED_SCOPE],
|
|
1488
|
-
resourceName: "TinyCloud hosted MCP"
|
|
1550
|
+
resourceName: surface === "public" ? "TinyCloud personal records" : "TinyCloud hosted MCP"
|
|
1489
1551
|
};
|
|
1490
1552
|
const allowedHosts = [resourceUrl.hostname];
|
|
1491
1553
|
return {
|
|
@@ -1498,16 +1560,32 @@ function createHostedMcpApp(config) {
|
|
|
1498
1560
|
}
|
|
1499
1561
|
const hostFailure = (0, import_server4.hostHeaderValidationResponse)(request, allowedHosts);
|
|
1500
1562
|
if (hostFailure !== void 0) return hostFailure;
|
|
1501
|
-
if (url.pathname ===
|
|
1563
|
+
if (url.pathname === connectPath) {
|
|
1502
1564
|
if (request.method !== "GET") return methodNotAllowed("GET");
|
|
1503
1565
|
try {
|
|
1504
1566
|
const destination = await store.approvalRedirect(requiredState(url));
|
|
1505
1567
|
return Response.redirect(destination, 302);
|
|
1506
1568
|
} catch {
|
|
1569
|
+
if (request.headers.get("accept")?.includes("text/html")) {
|
|
1570
|
+
return new Response(
|
|
1571
|
+
'<!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>',
|
|
1572
|
+
{
|
|
1573
|
+
status: 400,
|
|
1574
|
+
headers: {
|
|
1575
|
+
"content-type": "text/html; charset=utf-8",
|
|
1576
|
+
"cache-control": "no-store",
|
|
1577
|
+
"content-security-policy": "default-src 'none'; base-uri 'none'; frame-ancestors 'none'",
|
|
1578
|
+
"referrer-policy": "no-referrer",
|
|
1579
|
+
"x-content-type-options": "nosniff",
|
|
1580
|
+
vary: "Accept"
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1507
1585
|
return json({ error: "The approval link is invalid or expired." }, 400);
|
|
1508
1586
|
}
|
|
1509
1587
|
}
|
|
1510
|
-
if (url.pathname ===
|
|
1588
|
+
if (url.pathname === callbackPath) {
|
|
1511
1589
|
if (request.method === "OPTIONS") return callbackCors(new Response(null, { status: 204 }), config.openkeyHost);
|
|
1512
1590
|
if (request.method !== "POST") return methodNotAllowed("POST");
|
|
1513
1591
|
const originFailure2 = validateCallbackOrigin(request, config.openkeyHost);
|
|
@@ -1547,17 +1625,17 @@ function createHostedMcpApp(config) {
|
|
|
1547
1625
|
close: () => handler.close()
|
|
1548
1626
|
};
|
|
1549
1627
|
}
|
|
1550
|
-
function registerConnectTool(server, validator, store, identity) {
|
|
1628
|
+
function registerConnectTool(server, validator, store, identity, surface) {
|
|
1551
1629
|
const inputSchema = (0, import_server4.fromJsonSchema)({ type: "object", properties: {}, additionalProperties: false }, validator);
|
|
1552
1630
|
const outputSchema = (0, import_server4.fromJsonSchema)({
|
|
1553
1631
|
type: "object",
|
|
1554
1632
|
properties: {
|
|
1555
1633
|
connected: { type: "boolean" },
|
|
1556
|
-
sessionDid: { type: "string" },
|
|
1634
|
+
...surface === "hosted" ? { sessionDid: { type: "string" } } : {},
|
|
1557
1635
|
approvalUrl: { type: "string", format: "uri" },
|
|
1558
1636
|
expiresAt: { type: "string", format: "date-time" }
|
|
1559
1637
|
},
|
|
1560
|
-
required: ["connected", "sessionDid"],
|
|
1638
|
+
required: surface === "hosted" ? ["connected", "sessionDid"] : ["connected"],
|
|
1561
1639
|
additionalProperties: false
|
|
1562
1640
|
}, validator);
|
|
1563
1641
|
server.registerTool(
|
|
@@ -1571,7 +1649,7 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1571
1649
|
readOnlyHint: false,
|
|
1572
1650
|
idempotentHint: true,
|
|
1573
1651
|
destructiveHint: false,
|
|
1574
|
-
openWorldHint:
|
|
1652
|
+
openWorldHint: false
|
|
1575
1653
|
}
|
|
1576
1654
|
},
|
|
1577
1655
|
async () => {
|
|
@@ -1580,12 +1658,17 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1580
1658
|
try {
|
|
1581
1659
|
const status = await store.connectStatus(identity.subject, identity.ownerDids);
|
|
1582
1660
|
code = status.connected ? "ok" : "authority_required";
|
|
1661
|
+
const visibleStatus = surface === "hosted" ? status : {
|
|
1662
|
+
connected: status.connected,
|
|
1663
|
+
...status.approvalUrl === void 0 ? {} : { approvalUrl: status.approvalUrl },
|
|
1664
|
+
...status.expiresAt === void 0 ? {} : { expiresAt: status.expiresAt }
|
|
1665
|
+
};
|
|
1583
1666
|
return {
|
|
1584
1667
|
content: [{
|
|
1585
1668
|
type: "text",
|
|
1586
1669
|
text: status.connected ? "TinyCloud is connected." : `TinyCloud approval is required. Open ${status.approvalUrl}, then call this tool again. This link expires at ${status.expiresAt}.`
|
|
1587
1670
|
}],
|
|
1588
|
-
structuredContent:
|
|
1671
|
+
structuredContent: visibleStatus
|
|
1589
1672
|
};
|
|
1590
1673
|
} finally {
|
|
1591
1674
|
logToolCall("tinycloud_connect", code, startedAt, 0);
|