@tinycloud/mcp 0.7.4-beta.1 → 0.8.0-beta.3
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/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
|
10
10
|
import { createRequire } from "module";
|
|
11
11
|
import { join } from "path";
|
|
12
12
|
import { fromJsonSchema } from "@modelcontextprotocol/server";
|
|
13
|
-
import {
|
|
13
|
+
import { AjvJsonSchemaValidator } from "@modelcontextprotocol/server/validators/ajv";
|
|
14
14
|
import { invokeOperation } from "@tinycloud/operations";
|
|
15
15
|
|
|
16
16
|
// src/results.ts
|
|
@@ -24,7 +24,7 @@ function toMcpToolResult(result, bindings = [], options = {}) {
|
|
|
24
24
|
let serialized;
|
|
25
25
|
if (options.surface === "hosted") {
|
|
26
26
|
serialized = JSON.stringify(canonical);
|
|
27
|
-
if (options.readOnly === true && serialized.length > 1e5) {
|
|
27
|
+
if ((options.readOnly === true || options.operationId === "tinycloud.apps.context" || options.operationId === "tinycloud.apps.query") && serialized.length > 1e5) {
|
|
28
28
|
const sql = options.operationId?.startsWith("tinycloud.sql.") || options.operationId === "tinycloud.apps.query";
|
|
29
29
|
canonical = {
|
|
30
30
|
status: "error",
|
|
@@ -92,6 +92,44 @@ function logToolCall(tool, code, startedAt, replayedGrants) {
|
|
|
92
92
|
`);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
// src/schemas.ts
|
|
96
|
+
var DRAFT_7 = "http://json-schema.org/draft-07/schema#";
|
|
97
|
+
var DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
|
|
98
|
+
var schemaMaps = /* @__PURE__ */ new Set(["properties", "patternProperties", "definitions", "$defs"]);
|
|
99
|
+
var schemaArrays = /* @__PURE__ */ new Set(["allOf", "anyOf", "oneOf"]);
|
|
100
|
+
var schemaValues = /* @__PURE__ */ new Set([
|
|
101
|
+
"additionalProperties",
|
|
102
|
+
"items",
|
|
103
|
+
"contains",
|
|
104
|
+
"propertyNames",
|
|
105
|
+
"not",
|
|
106
|
+
"if",
|
|
107
|
+
"then",
|
|
108
|
+
"else"
|
|
109
|
+
]);
|
|
110
|
+
function toMcpJsonSchema(schema) {
|
|
111
|
+
if (typeof schema === "boolean") return schema;
|
|
112
|
+
if (Array.isArray(schema.items) || "additionalItems" in schema || "dependencies" in schema || "$ref" in schema && Object.keys(schema).some((key) => key !== "$ref")) {
|
|
113
|
+
throw new Error("The operations schema needs a semantic migration to JSON Schema 2020-12.");
|
|
114
|
+
}
|
|
115
|
+
const projected = {};
|
|
116
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
117
|
+
if (key === "$schema") {
|
|
118
|
+
if (value !== DRAFT_7) throw new Error(`Unsupported operations schema dialect: ${String(value)}.`);
|
|
119
|
+
projected[key] = DRAFT_2020_12;
|
|
120
|
+
} else if (schemaMaps.has(key)) {
|
|
121
|
+
projected[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [name, toMcpJsonSchema(child)]));
|
|
122
|
+
} else if (schemaArrays.has(key)) {
|
|
123
|
+
projected[key] = value.map(toMcpJsonSchema);
|
|
124
|
+
} else if (schemaValues.has(key)) {
|
|
125
|
+
projected[key] = toMcpJsonSchema(value);
|
|
126
|
+
} else {
|
|
127
|
+
projected[key] = value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return projected;
|
|
131
|
+
}
|
|
132
|
+
|
|
95
133
|
// src/tools.ts
|
|
96
134
|
var TOOL_NAMES = [
|
|
97
135
|
"tinycloud_status",
|
|
@@ -134,9 +172,9 @@ var generatedCatalog = packageRequire(
|
|
|
134
172
|
var stableErrorCodes = Object.fromEntries(
|
|
135
173
|
generatedCatalog.stableErrors.map((code) => [code, true])
|
|
136
174
|
);
|
|
137
|
-
var
|
|
175
|
+
var PRIVATE_SURFACES = ["local", "hosted"];
|
|
138
176
|
function bindingSurfaces(binding) {
|
|
139
|
-
return binding.surfaces ??
|
|
177
|
+
return binding.surfaces ?? PRIVATE_SURFACES;
|
|
140
178
|
}
|
|
141
179
|
var TOOL_BINDINGS = [
|
|
142
180
|
{
|
|
@@ -320,11 +358,11 @@ var TOOL_BINDINGS = [
|
|
|
320
358
|
name: "tinycloud_apps_context",
|
|
321
359
|
operationId: "tinycloud.apps.context",
|
|
322
360
|
operationVersion: 1,
|
|
323
|
-
readOnlyHint:
|
|
361
|
+
readOnlyHint: false,
|
|
324
362
|
idempotentHint: true,
|
|
325
|
-
destructiveHint:
|
|
326
|
-
openWorldHint:
|
|
327
|
-
surfaces: ["hosted"]
|
|
363
|
+
destructiveHint: true,
|
|
364
|
+
openWorldHint: false,
|
|
365
|
+
surfaces: ["hosted", "public"]
|
|
328
366
|
},
|
|
329
367
|
{
|
|
330
368
|
name: "tinycloud_apps_read",
|
|
@@ -333,8 +371,8 @@ var TOOL_BINDINGS = [
|
|
|
333
371
|
readOnlyHint: true,
|
|
334
372
|
idempotentHint: true,
|
|
335
373
|
destructiveHint: false,
|
|
336
|
-
openWorldHint:
|
|
337
|
-
surfaces: ["hosted"]
|
|
374
|
+
openWorldHint: false,
|
|
375
|
+
surfaces: ["hosted", "public"]
|
|
338
376
|
},
|
|
339
377
|
{
|
|
340
378
|
name: "tinycloud_apps_write",
|
|
@@ -343,34 +381,34 @@ var TOOL_BINDINGS = [
|
|
|
343
381
|
readOnlyHint: false,
|
|
344
382
|
idempotentHint: false,
|
|
345
383
|
destructiveHint: true,
|
|
346
|
-
openWorldHint:
|
|
347
|
-
surfaces: ["hosted"]
|
|
384
|
+
openWorldHint: false,
|
|
385
|
+
surfaces: ["hosted", "public"]
|
|
348
386
|
},
|
|
349
387
|
{
|
|
350
388
|
name: "tinycloud_apps_query",
|
|
351
389
|
operationId: "tinycloud.apps.query",
|
|
352
390
|
operationVersion: 1,
|
|
353
|
-
readOnlyHint:
|
|
391
|
+
readOnlyHint: false,
|
|
354
392
|
idempotentHint: true,
|
|
355
|
-
destructiveHint:
|
|
356
|
-
openWorldHint:
|
|
357
|
-
surfaces: ["hosted"]
|
|
393
|
+
destructiveHint: true,
|
|
394
|
+
openWorldHint: false,
|
|
395
|
+
surfaces: ["hosted", "public"]
|
|
358
396
|
}
|
|
359
397
|
];
|
|
398
|
+
var definitions = new Map(generatedCatalog.operations.map((operation) => [
|
|
399
|
+
`${operation.id}@${operation.version}`,
|
|
400
|
+
{
|
|
401
|
+
...operation,
|
|
402
|
+
input: toMcpJsonSchema(operation.input),
|
|
403
|
+
result: toMcpJsonSchema(operation.result)
|
|
404
|
+
}
|
|
405
|
+
]));
|
|
360
406
|
function createJsonSchemaValidator() {
|
|
361
|
-
|
|
362
|
-
addFormats(ajv);
|
|
363
|
-
return new AjvJsonSchemaValidator(ajv);
|
|
407
|
+
return new AjvJsonSchemaValidator();
|
|
364
408
|
}
|
|
365
409
|
function registerTinyCloudTools(server, selection, validator) {
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
`${operation.id}@${operation.version}`,
|
|
369
|
-
operation
|
|
370
|
-
])
|
|
371
|
-
);
|
|
372
|
-
for (const binding of TOOL_BINDINGS) {
|
|
373
|
-
if (!bindingSurfaces(binding).includes(selection.surface)) continue;
|
|
410
|
+
const bindings = TOOL_BINDINGS.filter((binding) => bindingSurfaces(binding).includes(selection.surface));
|
|
411
|
+
for (const binding of bindings) {
|
|
374
412
|
const operation = definitions.get(`${binding.operationId}@${binding.operationVersion}`);
|
|
375
413
|
if (operation === void 0) {
|
|
376
414
|
throw new Error(`Generated operations catalog is missing ${binding.operationId}@${binding.operationVersion}.`);
|
|
@@ -416,15 +454,15 @@ function registerTinyCloudTools(server, selection, validator) {
|
|
|
416
454
|
operationVersion: binding.operationVersion,
|
|
417
455
|
input
|
|
418
456
|
});
|
|
419
|
-
const response = toMcpToolResult(projected,
|
|
420
|
-
surface: selection.surface,
|
|
457
|
+
const response = toMcpToolResult(projected, bindings, {
|
|
458
|
+
surface: selection.surface === "local" ? "local" : "hosted",
|
|
421
459
|
readOnly: binding.readOnlyHint,
|
|
422
460
|
operationId: binding.operationId
|
|
423
461
|
});
|
|
424
462
|
code = outcomeCode(response.structuredContent);
|
|
425
463
|
return response;
|
|
426
464
|
} finally {
|
|
427
|
-
if (selection.surface
|
|
465
|
+
if (selection.surface !== "local") {
|
|
428
466
|
logToolCall(binding.name, code, startedAt, metrics.replayedGrants);
|
|
429
467
|
}
|
|
430
468
|
}
|
|
@@ -447,7 +485,7 @@ function outcomeCode(result) {
|
|
|
447
485
|
// package.json
|
|
448
486
|
var package_default = {
|
|
449
487
|
name: "@tinycloud/mcp",
|
|
450
|
-
version: "0.
|
|
488
|
+
version: "0.8.0-beta.3",
|
|
451
489
|
description: "TinyCloud delegated operations MCP server",
|
|
452
490
|
keywords: [
|
|
453
491
|
"tinycloud",
|
|
@@ -518,9 +556,9 @@ var package_default = {
|
|
|
518
556
|
dependencies: {
|
|
519
557
|
"@modelcontextprotocol/node": "2.0.0-beta.5",
|
|
520
558
|
"@modelcontextprotocol/server": "2.0.0-beta.5",
|
|
521
|
-
"@tinycloud/node-sdk": "3.6.0-beta.
|
|
559
|
+
"@tinycloud/node-sdk": "3.6.0-beta.3",
|
|
522
560
|
"@tinycloud/node-sdk-wasm": "1.7.8",
|
|
523
|
-
"@tinycloud/operations": "0.7.4-beta.
|
|
561
|
+
"@tinycloud/operations": "0.7.4-beta.3",
|
|
524
562
|
jose: "6.2.4"
|
|
525
563
|
},
|
|
526
564
|
devDependencies: {
|
|
@@ -659,6 +697,7 @@ if (isDirectInvocation()) {
|
|
|
659
697
|
}
|
|
660
698
|
|
|
661
699
|
// src/http.ts
|
|
700
|
+
import { join as join3 } from "path";
|
|
662
701
|
import {
|
|
663
702
|
McpServer as McpServer2,
|
|
664
703
|
createMcpHandler,
|
|
@@ -1001,7 +1040,7 @@ var RemoteTenantStore = class {
|
|
|
1001
1040
|
async approvalRedirect(state) {
|
|
1002
1041
|
const pending = await this.#readPending(state, false);
|
|
1003
1042
|
const tenant = await this.#readTenant(pending.tenantId);
|
|
1004
|
-
const callback = new URL("/connect/callback
|
|
1043
|
+
const callback = new URL(`${this.#config.approvalPath ?? "/connect"}/callback`, this.#config.publicUrl);
|
|
1005
1044
|
callback.searchParams.set("state", state);
|
|
1006
1045
|
const params = new URLSearchParams({
|
|
1007
1046
|
did: tenant.sessionDid,
|
|
@@ -1420,7 +1459,7 @@ var RemoteTenantStore = class {
|
|
|
1420
1459
|
await rename(`${path}.processing`, path);
|
|
1421
1460
|
}
|
|
1422
1461
|
#connectUrl(pending) {
|
|
1423
|
-
const url = new URL("/connect", this.#config.publicUrl);
|
|
1462
|
+
const url = new URL(this.#config.approvalPath ?? "/connect", this.#config.publicUrl);
|
|
1424
1463
|
url.searchParams.set("state", `${pending.tenantId}.${pending.nonce}.${this.#signState(pending.tenantId, pending.nonce)}`);
|
|
1425
1464
|
return url.toString();
|
|
1426
1465
|
}
|
|
@@ -1581,6 +1620,29 @@ function samePendingRequest(pending, expected) {
|
|
|
1581
1620
|
var REQUIRED_SCOPE = "tinycloud:mcp";
|
|
1582
1621
|
function createHostedMcpApp(config) {
|
|
1583
1622
|
const resourceUrl = canonicalResourceUrl(config.publicUrl);
|
|
1623
|
+
const pluginUrl = new URL("./chatgpt/mcp", resourceUrl);
|
|
1624
|
+
const hosted = createHostedSurface(config, resourceUrl, "hosted");
|
|
1625
|
+
const plugin = createHostedSurface({
|
|
1626
|
+
...config,
|
|
1627
|
+
stateDir: join3(config.stateDir, "chatgpt"),
|
|
1628
|
+
approvalPath: new URL("./connect", pluginUrl).pathname
|
|
1629
|
+
}, pluginUrl, "public");
|
|
1630
|
+
const pluginPaths = {
|
|
1631
|
+
[pluginUrl.pathname]: true,
|
|
1632
|
+
[new URL("./connect", pluginUrl).pathname]: true,
|
|
1633
|
+
[new URL("./connect/callback", pluginUrl).pathname]: true,
|
|
1634
|
+
[new URL(getOAuthProtectedResourceMetadataUrl(pluginUrl)).pathname]: true
|
|
1635
|
+
};
|
|
1636
|
+
return {
|
|
1637
|
+
fetch: (request) => (pluginPaths[new URL(request.url).pathname] === true ? plugin : hosted).fetch(request),
|
|
1638
|
+
close: async () => {
|
|
1639
|
+
await Promise.all([hosted.close(), plugin.close()]);
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
function createHostedSurface(config, resourceUrl, surface) {
|
|
1644
|
+
const connectPath = config.approvalPath ?? "/connect";
|
|
1645
|
+
const callbackPath = `${connectPath}/callback`;
|
|
1584
1646
|
const issuer = String(config.oauthMetadata.issuer);
|
|
1585
1647
|
const jwksUri = String(config.oauthMetadata.jwks_uri);
|
|
1586
1648
|
const verifier = createOpenKeyTokenVerifier({
|
|
@@ -1605,11 +1667,11 @@ function createHostedMcpApp(config) {
|
|
|
1605
1667
|
{ name: MCP_SERVER_NAME, version: MCP_VERSION },
|
|
1606
1668
|
{
|
|
1607
1669
|
jsonSchemaValidator: validator,
|
|
1608
|
-
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."
|
|
1670
|
+
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."
|
|
1609
1671
|
}
|
|
1610
1672
|
);
|
|
1611
1673
|
registerTinyCloudTools(server, {
|
|
1612
|
-
surface
|
|
1674
|
+
surface,
|
|
1613
1675
|
profile: "agent",
|
|
1614
1676
|
explicitProfile: true,
|
|
1615
1677
|
allowOwnerProfile: false,
|
|
@@ -1617,7 +1679,7 @@ function createHostedMcpApp(config) {
|
|
|
1617
1679
|
beforeOperation: () => store.validateTenant(subject, ownerDids),
|
|
1618
1680
|
transformOperationResult: (result, invocation) => store.decorateAuthorityResult(subject, ownerDids, result, invocation)
|
|
1619
1681
|
}, validator);
|
|
1620
|
-
registerConnectTool(server, validator, store, identity);
|
|
1682
|
+
registerConnectTool(server, validator, store, identity, surface);
|
|
1621
1683
|
return server;
|
|
1622
1684
|
}, {
|
|
1623
1685
|
legacy: "stateless",
|
|
@@ -1628,7 +1690,7 @@ function createHostedMcpApp(config) {
|
|
|
1628
1690
|
resourceServerUrl: resourceUrl,
|
|
1629
1691
|
serviceDocumentationUrl: new URL("https://docs.tinycloud.xyz/cli/mcp"),
|
|
1630
1692
|
scopesSupported: [REQUIRED_SCOPE],
|
|
1631
|
-
resourceName: "TinyCloud hosted MCP"
|
|
1693
|
+
resourceName: surface === "public" ? "TinyCloud personal records" : "TinyCloud hosted MCP"
|
|
1632
1694
|
};
|
|
1633
1695
|
const allowedHosts = [resourceUrl.hostname];
|
|
1634
1696
|
return {
|
|
@@ -1641,16 +1703,32 @@ function createHostedMcpApp(config) {
|
|
|
1641
1703
|
}
|
|
1642
1704
|
const hostFailure = hostHeaderValidationResponse(request, allowedHosts);
|
|
1643
1705
|
if (hostFailure !== void 0) return hostFailure;
|
|
1644
|
-
if (url.pathname ===
|
|
1706
|
+
if (url.pathname === connectPath) {
|
|
1645
1707
|
if (request.method !== "GET") return methodNotAllowed("GET");
|
|
1646
1708
|
try {
|
|
1647
1709
|
const destination = await store.approvalRedirect(requiredState(url));
|
|
1648
1710
|
return Response.redirect(destination, 302);
|
|
1649
1711
|
} catch {
|
|
1712
|
+
if (request.headers.get("accept")?.includes("text/html")) {
|
|
1713
|
+
return new Response(
|
|
1714
|
+
'<!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>',
|
|
1715
|
+
{
|
|
1716
|
+
status: 400,
|
|
1717
|
+
headers: {
|
|
1718
|
+
"content-type": "text/html; charset=utf-8",
|
|
1719
|
+
"cache-control": "no-store",
|
|
1720
|
+
"content-security-policy": "default-src 'none'; base-uri 'none'; frame-ancestors 'none'",
|
|
1721
|
+
"referrer-policy": "no-referrer",
|
|
1722
|
+
"x-content-type-options": "nosniff",
|
|
1723
|
+
vary: "Accept"
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1650
1728
|
return json({ error: "The approval link is invalid or expired." }, 400);
|
|
1651
1729
|
}
|
|
1652
1730
|
}
|
|
1653
|
-
if (url.pathname ===
|
|
1731
|
+
if (url.pathname === callbackPath) {
|
|
1654
1732
|
if (request.method === "OPTIONS") return callbackCors(new Response(null, { status: 204 }), config.openkeyHost);
|
|
1655
1733
|
if (request.method !== "POST") return methodNotAllowed("POST");
|
|
1656
1734
|
const originFailure2 = validateCallbackOrigin(request, config.openkeyHost);
|
|
@@ -1690,17 +1768,17 @@ function createHostedMcpApp(config) {
|
|
|
1690
1768
|
close: () => handler.close()
|
|
1691
1769
|
};
|
|
1692
1770
|
}
|
|
1693
|
-
function registerConnectTool(server, validator, store, identity) {
|
|
1771
|
+
function registerConnectTool(server, validator, store, identity, surface) {
|
|
1694
1772
|
const inputSchema = fromJsonSchema2({ type: "object", properties: {}, additionalProperties: false }, validator);
|
|
1695
1773
|
const outputSchema = fromJsonSchema2({
|
|
1696
1774
|
type: "object",
|
|
1697
1775
|
properties: {
|
|
1698
1776
|
connected: { type: "boolean" },
|
|
1699
|
-
sessionDid: { type: "string" },
|
|
1777
|
+
...surface === "hosted" ? { sessionDid: { type: "string" } } : {},
|
|
1700
1778
|
approvalUrl: { type: "string", format: "uri" },
|
|
1701
1779
|
expiresAt: { type: "string", format: "date-time" }
|
|
1702
1780
|
},
|
|
1703
|
-
required: ["connected", "sessionDid"],
|
|
1781
|
+
required: surface === "hosted" ? ["connected", "sessionDid"] : ["connected"],
|
|
1704
1782
|
additionalProperties: false
|
|
1705
1783
|
}, validator);
|
|
1706
1784
|
server.registerTool(
|
|
@@ -1714,7 +1792,7 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1714
1792
|
readOnlyHint: false,
|
|
1715
1793
|
idempotentHint: true,
|
|
1716
1794
|
destructiveHint: false,
|
|
1717
|
-
openWorldHint:
|
|
1795
|
+
openWorldHint: false
|
|
1718
1796
|
}
|
|
1719
1797
|
},
|
|
1720
1798
|
async () => {
|
|
@@ -1723,12 +1801,17 @@ function registerConnectTool(server, validator, store, identity) {
|
|
|
1723
1801
|
try {
|
|
1724
1802
|
const status = await store.connectStatus(identity.subject, identity.ownerDids);
|
|
1725
1803
|
code = status.connected ? "ok" : "authority_required";
|
|
1804
|
+
const visibleStatus = surface === "hosted" ? status : {
|
|
1805
|
+
connected: status.connected,
|
|
1806
|
+
...status.approvalUrl === void 0 ? {} : { approvalUrl: status.approvalUrl },
|
|
1807
|
+
...status.expiresAt === void 0 ? {} : { expiresAt: status.expiresAt }
|
|
1808
|
+
};
|
|
1726
1809
|
return {
|
|
1727
1810
|
content: [{
|
|
1728
1811
|
type: "text",
|
|
1729
1812
|
text: status.connected ? "TinyCloud is connected." : `TinyCloud approval is required. Open ${status.approvalUrl}, then call this tool again. This link expires at ${status.expiresAt}.`
|
|
1730
1813
|
}],
|
|
1731
|
-
structuredContent:
|
|
1814
|
+
structuredContent: visibleStatus
|
|
1732
1815
|
};
|
|
1733
1816
|
} finally {
|
|
1734
1817
|
logToolCall("tinycloud_connect", code, startedAt, 0);
|