@collage-dam/mcp-server 0.1.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/.env.example +56 -0
- package/CHANGELOG.md +90 -0
- package/LICENSE +21 -0
- package/README.md +512 -0
- package/dist/client.d.ts +497 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1162 -0
- package/dist/client.js.map +1 -0
- package/dist/conventions/confirmation.d.ts +89 -0
- package/dist/conventions/confirmation.d.ts.map +1 -0
- package/dist/conventions/confirmation.js +132 -0
- package/dist/conventions/confirmation.js.map +1 -0
- package/dist/conventions/dry-run/batch-executor.d.ts +36 -0
- package/dist/conventions/dry-run/batch-executor.d.ts.map +1 -0
- package/dist/conventions/dry-run/batch-executor.js +89 -0
- package/dist/conventions/dry-run/batch-executor.js.map +1 -0
- package/dist/conventions/dry-run/diff-renderer.d.ts +34 -0
- package/dist/conventions/dry-run/diff-renderer.d.ts.map +1 -0
- package/dist/conventions/dry-run/diff-renderer.js +158 -0
- package/dist/conventions/dry-run/diff-renderer.js.map +1 -0
- package/dist/conventions/dry-run/index.d.ts +13 -0
- package/dist/conventions/dry-run/index.d.ts.map +1 -0
- package/dist/conventions/dry-run/index.js +10 -0
- package/dist/conventions/dry-run/index.js.map +1 -0
- package/dist/conventions/dry-run/mutating-tool.d.ts +64 -0
- package/dist/conventions/dry-run/mutating-tool.d.ts.map +1 -0
- package/dist/conventions/dry-run/mutating-tool.js +88 -0
- package/dist/conventions/dry-run/mutating-tool.js.map +1 -0
- package/dist/conventions/dry-run/summary.d.ts +66 -0
- package/dist/conventions/dry-run/summary.d.ts.map +1 -0
- package/dist/conventions/dry-run/summary.js +185 -0
- package/dist/conventions/dry-run/summary.js.map +1 -0
- package/dist/conventions/dry-run/types.d.ts +597 -0
- package/dist/conventions/dry-run/types.d.ts.map +1 -0
- package/dist/conventions/dry-run/types.js +108 -0
- package/dist/conventions/dry-run/types.js.map +1 -0
- package/dist/conventions/dry-run/with-dry-run.d.ts +66 -0
- package/dist/conventions/dry-run/with-dry-run.d.ts.map +1 -0
- package/dist/conventions/dry-run/with-dry-run.js +219 -0
- package/dist/conventions/dry-run/with-dry-run.js.map +1 -0
- package/dist/conventions/env.d.ts +49 -0
- package/dist/conventions/env.d.ts.map +1 -0
- package/dist/conventions/env.js +84 -0
- package/dist/conventions/env.js.map +1 -0
- package/dist/conventions/errors.d.ts +68 -0
- package/dist/conventions/errors.d.ts.map +1 -0
- package/dist/conventions/errors.js +81 -0
- package/dist/conventions/errors.js.map +1 -0
- package/dist/conventions/logger.d.ts +28 -0
- package/dist/conventions/logger.d.ts.map +1 -0
- package/dist/conventions/logger.js +105 -0
- package/dist/conventions/logger.js.map +1 -0
- package/dist/conventions/pagination.d.ts +37 -0
- package/dist/conventions/pagination.d.ts.map +1 -0
- package/dist/conventions/pagination.js +53 -0
- package/dist/conventions/pagination.js.map +1 -0
- package/dist/conventions/rate-limiter.d.ts +54 -0
- package/dist/conventions/rate-limiter.d.ts.map +1 -0
- package/dist/conventions/rate-limiter.js +143 -0
- package/dist/conventions/rate-limiter.js.map +1 -0
- package/dist/conventions/response-budget.d.ts +66 -0
- package/dist/conventions/response-budget.d.ts.map +1 -0
- package/dist/conventions/response-budget.js +89 -0
- package/dist/conventions/response-budget.js.map +1 -0
- package/dist/conventions/schema-version.d.ts +27 -0
- package/dist/conventions/schema-version.d.ts.map +1 -0
- package/dist/conventions/schema-version.js +29 -0
- package/dist/conventions/schema-version.js.map +1 -0
- package/dist/conventions/state-store-redis.d.ts +32 -0
- package/dist/conventions/state-store-redis.d.ts.map +1 -0
- package/dist/conventions/state-store-redis.js +77 -0
- package/dist/conventions/state-store-redis.js.map +1 -0
- package/dist/conventions/state-store.d.ts +46 -0
- package/dist/conventions/state-store.d.ts.map +1 -0
- package/dist/conventions/state-store.js +105 -0
- package/dist/conventions/state-store.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +421 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/collection-audit.d.ts +13 -0
- package/dist/prompts/collection-audit.d.ts.map +1 -0
- package/dist/prompts/collection-audit.js +168 -0
- package/dist/prompts/collection-audit.js.map +1 -0
- package/dist/prompts/create-distribution.d.ts +15 -0
- package/dist/prompts/create-distribution.d.ts.map +1 -0
- package/dist/prompts/create-distribution.js +111 -0
- package/dist/prompts/create-distribution.js.map +1 -0
- package/dist/prompts/helpers.d.ts +20 -0
- package/dist/prompts/helpers.d.ts.map +1 -0
- package/dist/prompts/helpers.js +53 -0
- package/dist/prompts/helpers.js.map +1 -0
- package/dist/prompts/library-health-audit.d.ts +13 -0
- package/dist/prompts/library-health-audit.d.ts.map +1 -0
- package/dist/prompts/library-health-audit.js +131 -0
- package/dist/prompts/library-health-audit.js.map +1 -0
- package/dist/prompts/usage-insights.d.ts +13 -0
- package/dist/prompts/usage-insights.d.ts.map +1 -0
- package/dist/prompts/usage-insights.js +98 -0
- package/dist/prompts/usage-insights.js.map +1 -0
- package/dist/prompts/wrap-prompt-as-tool.d.ts +48 -0
- package/dist/prompts/wrap-prompt-as-tool.d.ts.map +1 -0
- package/dist/prompts/wrap-prompt-as-tool.js +61 -0
- package/dist/prompts/wrap-prompt-as-tool.js.map +1 -0
- package/dist/resources/asset-by-id.d.ts +4 -0
- package/dist/resources/asset-by-id.d.ts.map +1 -0
- package/dist/resources/asset-by-id.js +27 -0
- package/dist/resources/asset-by-id.js.map +1 -0
- package/dist/resources/collections.d.ts +5 -0
- package/dist/resources/collections.d.ts.map +1 -0
- package/dist/resources/collections.js +48 -0
- package/dist/resources/collections.js.map +1 -0
- package/dist/resources/custom-fields.d.ts +4 -0
- package/dist/resources/custom-fields.d.ts.map +1 -0
- package/dist/resources/custom-fields.js +30 -0
- package/dist/resources/custom-fields.js.map +1 -0
- package/dist/resources/folders.d.ts +5 -0
- package/dist/resources/folders.d.ts.map +1 -0
- package/dist/resources/folders.js +73 -0
- package/dist/resources/folders.js.map +1 -0
- package/dist/resources/helpers.d.ts +17 -0
- package/dist/resources/helpers.d.ts.map +1 -0
- package/dist/resources/helpers.js +59 -0
- package/dist/resources/helpers.js.map +1 -0
- package/dist/resources/portals.d.ts +5 -0
- package/dist/resources/portals.d.ts.map +1 -0
- package/dist/resources/portals.js +81 -0
- package/dist/resources/portals.js.map +1 -0
- package/dist/resources/recent-and-dashboard.d.ts +5 -0
- package/dist/resources/recent-and-dashboard.d.ts.map +1 -0
- package/dist/resources/recent-and-dashboard.js +42 -0
- package/dist/resources/recent-and-dashboard.js.map +1 -0
- package/dist/tools/asset-selection.d.ts +102 -0
- package/dist/tools/asset-selection.d.ts.map +1 -0
- package/dist/tools/asset-selection.js +133 -0
- package/dist/tools/asset-selection.js.map +1 -0
- package/dist/tools/audit/audit-folder-structure.d.ts +108 -0
- package/dist/tools/audit/audit-folder-structure.d.ts.map +1 -0
- package/dist/tools/audit/audit-folder-structure.js +260 -0
- package/dist/tools/audit/audit-folder-structure.js.map +1 -0
- package/dist/tools/audit/audit-naming-conventions.d.ts +83 -0
- package/dist/tools/audit/audit-naming-conventions.d.ts.map +1 -0
- package/dist/tools/audit/audit-naming-conventions.js +238 -0
- package/dist/tools/audit/audit-naming-conventions.js.map +1 -0
- package/dist/tools/audit/audit-tagging-hygiene.d.ts +77 -0
- package/dist/tools/audit/audit-tagging-hygiene.d.ts.map +1 -0
- package/dist/tools/audit/audit-tagging-hygiene.js +402 -0
- package/dist/tools/audit/audit-tagging-hygiene.js.map +1 -0
- package/dist/tools/audit/detect-duplicates.d.ts +62 -0
- package/dist/tools/audit/detect-duplicates.d.ts.map +1 -0
- package/dist/tools/audit/detect-duplicates.js +0 -0
- package/dist/tools/audit/detect-duplicates.js.map +1 -0
- package/dist/tools/audit/types.d.ts +526 -0
- package/dist/tools/audit/types.d.ts.map +1 -0
- package/dist/tools/audit/types.js +188 -0
- package/dist/tools/audit/types.js.map +1 -0
- package/dist/tools/bulk-move-assets.d.ts +78 -0
- package/dist/tools/bulk-move-assets.d.ts.map +1 -0
- package/dist/tools/bulk-move-assets.js +122 -0
- package/dist/tools/bulk-move-assets.js.map +1 -0
- package/dist/tools/bulk-normalize-filenames.d.ts +62 -0
- package/dist/tools/bulk-normalize-filenames.d.ts.map +1 -0
- package/dist/tools/bulk-normalize-filenames.js +237 -0
- package/dist/tools/bulk-normalize-filenames.js.map +1 -0
- package/dist/tools/bulk-rename-assets.d.ts +79 -0
- package/dist/tools/bulk-rename-assets.d.ts.map +1 -0
- package/dist/tools/bulk-rename-assets.js +139 -0
- package/dist/tools/bulk-rename-assets.js.map +1 -0
- package/dist/tools/bulk-tags.d.ts +107 -0
- package/dist/tools/bulk-tags.d.ts.map +1 -0
- package/dist/tools/bulk-tags.js +220 -0
- package/dist/tools/bulk-tags.js.map +1 -0
- package/dist/tools/client-adapters.d.ts +76 -0
- package/dist/tools/client-adapters.d.ts.map +1 -0
- package/dist/tools/client-adapters.js +648 -0
- package/dist/tools/client-adapters.js.map +1 -0
- package/dist/tools/collection-membership.d.ts +90 -0
- package/dist/tools/collection-membership.d.ts.map +1 -0
- package/dist/tools/collection-membership.js +195 -0
- package/dist/tools/collection-membership.js.map +1 -0
- package/dist/tools/create-collection.d.ts +63 -0
- package/dist/tools/create-collection.d.ts.map +1 -0
- package/dist/tools/create-collection.js +151 -0
- package/dist/tools/create-collection.js.map +1 -0
- package/dist/tools/create-folder.d.ts +46 -0
- package/dist/tools/create-folder.d.ts.map +1 -0
- package/dist/tools/create-folder.js +83 -0
- package/dist/tools/create-folder.js.map +1 -0
- package/dist/tools/create-share-link.d.ts +107 -0
- package/dist/tools/create-share-link.d.ts.map +1 -0
- package/dist/tools/create-share-link.js +239 -0
- package/dist/tools/create-share-link.js.map +1 -0
- package/dist/tools/get-asset-details.d.ts +401 -0
- package/dist/tools/get-asset-details.d.ts.map +1 -0
- package/dist/tools/get-asset-details.js +56 -0
- package/dist/tools/get-asset-details.js.map +1 -0
- package/dist/tools/get-collection.d.ts +126 -0
- package/dist/tools/get-collection.d.ts.map +1 -0
- package/dist/tools/get-collection.js +52 -0
- package/dist/tools/get-collection.js.map +1 -0
- package/dist/tools/get-embed-code.d.ts +195 -0
- package/dist/tools/get-embed-code.d.ts.map +1 -0
- package/dist/tools/get-embed-code.js +214 -0
- package/dist/tools/get-embed-code.js.map +1 -0
- package/dist/tools/insights/analyze-share-links.d.ts +159 -0
- package/dist/tools/insights/analyze-share-links.d.ts.map +1 -0
- package/dist/tools/insights/analyze-share-links.js +314 -0
- package/dist/tools/insights/analyze-share-links.js.map +1 -0
- package/dist/tools/insights/insight-cache.d.ts +36 -0
- package/dist/tools/insights/insight-cache.d.ts.map +1 -0
- package/dist/tools/insights/insight-cache.js +98 -0
- package/dist/tools/insights/insight-cache.js.map +1 -0
- package/dist/tools/insights/report-asset-activation.d.ts +149 -0
- package/dist/tools/insights/report-asset-activation.d.ts.map +1 -0
- package/dist/tools/insights/report-asset-activation.js +380 -0
- package/dist/tools/insights/report-asset-activation.js.map +1 -0
- package/dist/tools/insights/report-stale-assets.d.ts +120 -0
- package/dist/tools/insights/report-stale-assets.d.ts.map +1 -0
- package/dist/tools/insights/report-stale-assets.js +281 -0
- package/dist/tools/insights/report-stale-assets.js.map +1 -0
- package/dist/tools/insights/report-top-assets.d.ts +139 -0
- package/dist/tools/insights/report-top-assets.d.ts.map +1 -0
- package/dist/tools/insights/report-top-assets.js +407 -0
- package/dist/tools/insights/report-top-assets.js.map +1 -0
- package/dist/tools/list-categories.d.ts +127 -0
- package/dist/tools/list-categories.d.ts.map +1 -0
- package/dist/tools/list-categories.js +68 -0
- package/dist/tools/list-categories.js.map +1 -0
- package/dist/tools/list-collections.d.ts +127 -0
- package/dist/tools/list-collections.d.ts.map +1 -0
- package/dist/tools/list-collections.js +53 -0
- package/dist/tools/list-collections.js.map +1 -0
- package/dist/tools/list-custom-fields.d.ts +125 -0
- package/dist/tools/list-custom-fields.d.ts.map +1 -0
- package/dist/tools/list-custom-fields.js +51 -0
- package/dist/tools/list-custom-fields.js.map +1 -0
- package/dist/tools/list-share-links.d.ts +192 -0
- package/dist/tools/list-share-links.d.ts.map +1 -0
- package/dist/tools/list-share-links.js +92 -0
- package/dist/tools/list-share-links.js.map +1 -0
- package/dist/tools/list-workspaces.d.ts +88 -0
- package/dist/tools/list-workspaces.d.ts.map +1 -0
- package/dist/tools/list-workspaces.js +71 -0
- package/dist/tools/list-workspaces.js.map +1 -0
- package/dist/tools/move-asset.d.ts +48 -0
- package/dist/tools/move-asset.d.ts.map +1 -0
- package/dist/tools/move-asset.js +85 -0
- package/dist/tools/move-asset.js.map +1 -0
- package/dist/tools/rename-asset.d.ts +88 -0
- package/dist/tools/rename-asset.d.ts.map +1 -0
- package/dist/tools/rename-asset.js +100 -0
- package/dist/tools/rename-asset.js.map +1 -0
- package/dist/tools/rename-folder.d.ts +55 -0
- package/dist/tools/rename-folder.d.ts.map +1 -0
- package/dist/tools/rename-folder.js +101 -0
- package/dist/tools/rename-folder.js.map +1 -0
- package/dist/tools/revoke-share-link.d.ts +55 -0
- package/dist/tools/revoke-share-link.d.ts.map +1 -0
- package/dist/tools/revoke-share-link.js +77 -0
- package/dist/tools/revoke-share-link.js.map +1 -0
- package/dist/tools/search/facets.d.ts +34 -0
- package/dist/tools/search/facets.d.ts.map +1 -0
- package/dist/tools/search/facets.js +147 -0
- package/dist/tools/search/facets.js.map +1 -0
- package/dist/tools/search/filter-builder.d.ts +33 -0
- package/dist/tools/search/filter-builder.d.ts.map +1 -0
- package/dist/tools/search/filter-builder.js +111 -0
- package/dist/tools/search/filter-builder.js.map +1 -0
- package/dist/tools/search/search-assets.d.ts +41 -0
- package/dist/tools/search/search-assets.d.ts.map +1 -0
- package/dist/tools/search/search-assets.js +162 -0
- package/dist/tools/search/search-assets.js.map +1 -0
- package/dist/tools/search/search-collections.d.ts +35 -0
- package/dist/tools/search/search-collections.d.ts.map +1 -0
- package/dist/tools/search/search-collections.js +103 -0
- package/dist/tools/search/search-collections.js.map +1 -0
- package/dist/tools/search/types.d.ts +1047 -0
- package/dist/tools/search/types.d.ts.map +1 -0
- package/dist/tools/search/types.js +216 -0
- package/dist/tools/search/types.js.map +1 -0
- package/dist/tools/update-asset-metadata.d.ts +78 -0
- package/dist/tools/update-asset-metadata.d.ts.map +1 -0
- package/dist/tools/update-asset-metadata.js +203 -0
- package/dist/tools/update-asset-metadata.js.map +1 -0
- package/dist/tools/update-collection.d.ts +69 -0
- package/dist/tools/update-collection.d.ts.map +1 -0
- package/dist/tools/update-collection.js +142 -0
- package/dist/tools/update-collection.js.map +1 -0
- package/dist/tools/view-category-contents.d.ts +231 -0
- package/dist/tools/view-category-contents.d.ts.map +1 -0
- package/dist/tools/view-category-contents.js +97 -0
- package/dist/tools/view-category-contents.js.map +1 -0
- package/dist/types.d.ts +1326 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +288 -0
- package/dist/types.js.map +1 -0
- package/dist/typesense.d.ts +84 -0
- package/dist/typesense.d.ts.map +1 -0
- package/dist/typesense.js +243 -0
- package/dist/typesense.js.map +1 -0
- package/docs/api-field-verification.md +244 -0
- package/docs/deployment-runbook.md +446 -0
- package/docs/security-review.md +195 -0
- package/docs/typesense-filter-schema.md +262 -0
- package/docs/verified-endpoints.md +38 -0
- package/package.json +72 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ── usage_insights ──────────────────────────────────────────────────
|
|
2
|
+
// Distribution-engagement summary. MVP ships a degraded slice backed
|
|
3
|
+
// only by the dashboard and analytics resources — the deeper
|
|
4
|
+
// `analyze_share_links` / `report_*` tools are Phase 2.
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { parseEnum, playbookMessage } from './helpers.js';
|
|
7
|
+
export const USAGE_INSIGHTS_NAME = 'usage_insights';
|
|
8
|
+
export const USAGE_INSIGHTS_DESCRIPTION = 'Summarize how your distribution surfaces are performing — share-link ' +
|
|
9
|
+
'engagement, asset activation, top performers, stale content. MVP ships ' +
|
|
10
|
+
'a high-level overview backed by the workspace dashboard; richer ' +
|
|
11
|
+
'per-share-link and per-asset analytics arrive in a future release.';
|
|
12
|
+
export const USAGE_INSIGHTS_ARGS = {
|
|
13
|
+
time_window: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Time window: 7d | 30d | 90d | all. Default 30d.'),
|
|
17
|
+
scope: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('What to analyse: portals | share_links | assets | all. Default all.'),
|
|
21
|
+
};
|
|
22
|
+
const WINDOWS = ['7d', '30d', '90d', 'all'];
|
|
23
|
+
const SCOPES = ['portals', 'share_links', 'assets', 'all'];
|
|
24
|
+
export function buildUsageInsightsPrompt(args) {
|
|
25
|
+
const window = parseEnum(args.time_window, WINDOWS, '30d');
|
|
26
|
+
const scope = parseEnum(args.scope, SCOPES, 'all');
|
|
27
|
+
const body = {
|
|
28
|
+
workflow: 'usage_insights',
|
|
29
|
+
time_window: window,
|
|
30
|
+
scope,
|
|
31
|
+
degraded_in_mvp: true,
|
|
32
|
+
degraded_reason: 'Per-share-link engagement, per-asset activation, top-N performers, ' +
|
|
33
|
+
'and stale-content scoring depend on the Phase 2 distribution-insights ' +
|
|
34
|
+
'tools (analyze_share_links, report_asset_activation, ' +
|
|
35
|
+
'report_top_assets, report_stale_assets). MVP ships only the ' +
|
|
36
|
+
'workspace-level dashboard summary. Tell the user which analyses are ' +
|
|
37
|
+
'currently available and which are in a future release.',
|
|
38
|
+
instructions: 'Pull workspace-level engagement signals from the available resources, ' +
|
|
39
|
+
'compile a structured report, and tell the user which deeper analyses ' +
|
|
40
|
+
'are not yet available so they can decide whether to wait for them or ' +
|
|
41
|
+
'proceed with what we have.',
|
|
42
|
+
orchestration: [
|
|
43
|
+
{
|
|
44
|
+
step: 1,
|
|
45
|
+
action: 'Load dashboard resource',
|
|
46
|
+
resources: ['collage://dashboard'],
|
|
47
|
+
purpose: 'Workspace-level KPIs: total assets, total collections, recent ' +
|
|
48
|
+
'upload velocity, total share links, etc. Pass through the raw ' +
|
|
49
|
+
'projection — do not invent fields.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
step: 2,
|
|
53
|
+
action: 'Inventory share links (in scope)',
|
|
54
|
+
tools: ['list_share_links'],
|
|
55
|
+
args: { page_size: 100 },
|
|
56
|
+
purpose: 'List share links with their view counts, expiration, and download ' +
|
|
57
|
+
'flags. Sort by view_count desc to surface the most-engaged. The ' +
|
|
58
|
+
'list endpoint exposes total view counts but not time-bucketed ' +
|
|
59
|
+
'history — call out that limitation in the report.',
|
|
60
|
+
included_when: scope === 'share_links' || scope === 'all',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
step: 3,
|
|
64
|
+
action: 'Identify recently-uploaded assets (in scope)',
|
|
65
|
+
resources: ['collage://assets/recent'],
|
|
66
|
+
purpose: 'Pull recent uploads from the resource. The MVP dashboard does NOT ' +
|
|
67
|
+
'currently report per-asset download counts — flag that in the report.',
|
|
68
|
+
included_when: scope === 'assets' || scope === 'all',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
step: 4,
|
|
72
|
+
action: 'Compile the report',
|
|
73
|
+
purpose: 'Aggregate signals from steps 1-3 into a single structured report. ' +
|
|
74
|
+
'For every section that depends on Phase 2 tools, emit a placeholder ' +
|
|
75
|
+
'with a friendly "this analysis is in a future release" note rather ' +
|
|
76
|
+
'than fabricating numbers.',
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
output_shape: {
|
|
80
|
+
time_window: window,
|
|
81
|
+
scope,
|
|
82
|
+
workspace_summary: 'object — passthrough of collage://dashboard',
|
|
83
|
+
share_link_engagement: 'Array<{ id, title, view_count, expiration }> | "Phase 2: per-share-link analytics"',
|
|
84
|
+
top_assets: '"Phase 2: report_top_assets pending"',
|
|
85
|
+
stale_assets: '"Phase 2: report_stale_assets pending"',
|
|
86
|
+
asset_activation: '"Phase 2: report_asset_activation pending"',
|
|
87
|
+
degraded_notice: 'string — friendly summary of what is and isn\'t available',
|
|
88
|
+
next_actions: 'Array<{ tool, args }>',
|
|
89
|
+
},
|
|
90
|
+
guardrails: [
|
|
91
|
+
'Read-only — no mutations.',
|
|
92
|
+
'Never fabricate engagement numbers; if a metric requires Phase 2 tools, say so.',
|
|
93
|
+
'If collage://dashboard returns an UPSTREAM error, surface code+request_id; do not pretend the report succeeded.',
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
return playbookMessage(`Usage insights (window: ${window}, scope: ${scope}) — degraded MVP slice`, body);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=usage-insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-insights.js","sourceRoot":"","sources":["../../src/prompts/usage-insights.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z, type ZodTypeAny } from 'zod';
|
|
2
|
+
import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
export declare const FALLBACK_NOTICE: string;
|
|
4
|
+
interface PromptDefinition<Args extends Record<string, ZodTypeAny>> {
|
|
5
|
+
/** Underlying prompt name (the canonical MCP prompt). */
|
|
6
|
+
promptName: string;
|
|
7
|
+
/** Tool-alias name registered alongside the prompt. */
|
|
8
|
+
toolName: string;
|
|
9
|
+
/** Human-readable description for the underlying prompt. */
|
|
10
|
+
promptDescription: string;
|
|
11
|
+
/** Argument schema; mirrors the prompt's argsSchema exactly. */
|
|
12
|
+
argsSchema: Args;
|
|
13
|
+
/** Builder that returns the prompt's GetPromptResult. */
|
|
14
|
+
build: (args: z.objectOutputType<Args, ZodTypeAny>) => GetPromptResult;
|
|
15
|
+
}
|
|
16
|
+
export interface ToolAliasResult {
|
|
17
|
+
/** Always present — keeps the tool result self-describing. */
|
|
18
|
+
alias_for_prompt: string;
|
|
19
|
+
/** Free-text description copied from the underlying prompt. */
|
|
20
|
+
description: string | undefined;
|
|
21
|
+
/** Stringified playbook body (the JSON from the prompt's user message). */
|
|
22
|
+
playbook: unknown;
|
|
23
|
+
/** Notice telling the LLM this is a fallback. */
|
|
24
|
+
notice: string;
|
|
25
|
+
}
|
|
26
|
+
interface BuiltAliasTool<Args extends Record<string, ZodTypeAny>> {
|
|
27
|
+
toolName: string;
|
|
28
|
+
toolDescription: string;
|
|
29
|
+
argsSchema: Args;
|
|
30
|
+
handler: (args: z.objectOutputType<Args, ZodTypeAny>) => Promise<{
|
|
31
|
+
content: Array<{
|
|
32
|
+
type: 'text';
|
|
33
|
+
text: string;
|
|
34
|
+
}>;
|
|
35
|
+
structuredContent: Record<string, unknown>;
|
|
36
|
+
isError?: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wrap a prompt's builder as an MCP tool handler. The tool reads the
|
|
41
|
+
* playbook body from the prompt result, parses it back to JSON (since
|
|
42
|
+
* the prompt builder serialises before storing in the message), and
|
|
43
|
+
* re-emits it under a stable `playbook` key. Schema-version stamping
|
|
44
|
+
* mirrors the rest of the mutating-tool surface.
|
|
45
|
+
*/
|
|
46
|
+
export declare function wrapPromptAsTool<Args extends Record<string, ZodTypeAny>>(def: PromptDefinition<Args>): BuiltAliasTool<Args>;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=wrap-prompt-as-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-prompt-as-tool.d.ts","sourceRoot":"","sources":["../../src/prompts/wrap-prompt-as-tool.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAG1E,eAAO,MAAM,eAAe,QAKW,CAAC;AAExC,UAAU,gBAAgB,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;IAChE,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,UAAU,EAAE,IAAI,CAAC;IACjB,yDAAyD;IACzD,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,eAAe,CAAC;CACxE;AAED,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;IACjB,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,OAAO,CAAC;QAC/D,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC/C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC,CAAC;CACJ;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACtE,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAC1B,cAAc,CAAC,IAAI,CAAC,CA+BtB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// ── wrapPromptAsTool ─────────────────────────────────────────────────
|
|
2
|
+
// Temporary fallback while Claude Desktop's UI does not expose MCP
|
|
3
|
+
// prompts in its slash or attachment menus. Each guided-workflow prompt
|
|
4
|
+
// gets a thin tool wrapper that re-emits the same playbook body as a
|
|
5
|
+
// tool-call result — and tools DO surface in Claude Desktop today.
|
|
6
|
+
//
|
|
7
|
+
// Once Anthropic ships native prompt UI, the alias tools are sunset and
|
|
8
|
+
// callers move back to invoking the prompts directly. The tool
|
|
9
|
+
// descriptions name this explicitly so future readers know the wrappers
|
|
10
|
+
// are temporary.
|
|
11
|
+
//
|
|
12
|
+
// See spec `.mm/specs/2026-05-01-mcp-prompts-ui-fallback/spec.md`.
|
|
13
|
+
import { addSchemaVersion } from '../conventions/schema-version.js';
|
|
14
|
+
export const FALLBACK_NOTICE = 'TEMPORARY FALLBACK: Claude Desktop\'s current UI does not expose MCP ' +
|
|
15
|
+
'prompts. This tool re-emits the same guided-workflow playbook so it ' +
|
|
16
|
+
'can be invoked through the standard tool surface. Prefer the native ' +
|
|
17
|
+
'MCP prompt where supported; this alias will be removed once Claude ' +
|
|
18
|
+
'Desktop surfaces prompts in its UI.';
|
|
19
|
+
/**
|
|
20
|
+
* Wrap a prompt's builder as an MCP tool handler. The tool reads the
|
|
21
|
+
* playbook body from the prompt result, parses it back to JSON (since
|
|
22
|
+
* the prompt builder serialises before storing in the message), and
|
|
23
|
+
* re-emits it under a stable `playbook` key. Schema-version stamping
|
|
24
|
+
* mirrors the rest of the mutating-tool surface.
|
|
25
|
+
*/
|
|
26
|
+
export function wrapPromptAsTool(def) {
|
|
27
|
+
const toolDescription = `${def.promptDescription}\n\n${FALLBACK_NOTICE}`;
|
|
28
|
+
return {
|
|
29
|
+
toolName: def.toolName,
|
|
30
|
+
toolDescription,
|
|
31
|
+
argsSchema: def.argsSchema,
|
|
32
|
+
handler: async (args) => {
|
|
33
|
+
const promptResult = def.build(args);
|
|
34
|
+
const message = promptResult.messages[0];
|
|
35
|
+
const playbook = message !== undefined && message.content.type === 'text'
|
|
36
|
+
? safeJsonParse(message.content.text)
|
|
37
|
+
: null;
|
|
38
|
+
const structured = addSchemaVersion({
|
|
39
|
+
alias_for_prompt: def.promptName,
|
|
40
|
+
description: promptResult.description,
|
|
41
|
+
playbook,
|
|
42
|
+
notice: FALLBACK_NOTICE,
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{ type: 'text', text: JSON.stringify(structured, null, 2) },
|
|
47
|
+
],
|
|
48
|
+
structuredContent: structured,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function safeJsonParse(text) {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(text);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return text;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=wrap-prompt-as-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap-prompt-as-tool.js","sourceRoot":"","sources":["../../src/prompts/wrap-prompt-as-tool.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,mEAAmE;AACnE,wEAAwE;AACxE,qEAAqE;AACrE,mEAAmE;AACnE,EAAE;AACF,wEAAwE;AACxE,+DAA+D;AAC/D,wEAAwE;AACxE,iBAAiB;AACjB,EAAE;AACF,mEAAmE;AAInE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,MAAM,CAAC,MAAM,eAAe,GAC1B,uEAAuE;IACvE,sEAAsE;IACtE,sEAAsE;IACtE,qEAAqE;IACrE,qCAAqC,CAAC;AAqCxC;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAA2B;IAE3B,MAAM,eAAe,GACnB,GAAG,GAAG,CAAC,iBAAiB,OAAO,eAAe,EAAE,CAAC;IAEnD,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,eAAe;QACf,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,QAAQ,GACZ,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;gBACtD,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrC,CAAC,CAAC,IAAI,CAAC;YAEX,MAAM,UAAU,GAA8C,gBAAgB,CAAC;gBAC7E,gBAAgB,EAAE,GAAG,CAAC,UAAU;gBAChC,WAAW,EAAE,YAAY,CAAC,WAAW;gBACrC,QAAQ;gBACR,MAAM,EAAE,eAAe;aACxB,CAA8C,CAAC;YAEhD,OAAO;gBACL,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;iBACrE;gBACD,iBAAiB,EAAE,UAAU;aAC9B,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { CollageClient } from '../client.js';
|
|
3
|
+
export declare function buildAssetByIdReader(client: CollageClient): (uri: URL, variables: Record<string, string | string[]>) => Promise<ReadResourceResult>;
|
|
4
|
+
//# sourceMappingURL=asset-by-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-by-id.d.ts","sourceRoot":"","sources":["../../src/resources/asset-by-id.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,IAEtD,KAAK,GAAG,EACR,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAqB/B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ── collage://assets/{id} ─────────────────────────────────────────────
|
|
2
|
+
// Backed by POST /digital-assets/view-detail (CollageClient.getAssetDetails).
|
|
3
|
+
// Returns the full asset projection — metadata, tags, breadcrumb, and
|
|
4
|
+
// signed S3 thumbnail/compress URLs (24h expiry).
|
|
5
|
+
//
|
|
6
|
+
// Per the spec: visibility fields stay numeric (0=public, 1=private) and
|
|
7
|
+
// raw Collage field names (e.g. `digital_assets_id`) flow through as-is.
|
|
8
|
+
import { createToolError } from '../conventions/errors.js';
|
|
9
|
+
import { errorResource, jsonResource } from './helpers.js';
|
|
10
|
+
export function buildAssetByIdReader(client) {
|
|
11
|
+
return async (uri, variables) => {
|
|
12
|
+
const idVar = variables['id'];
|
|
13
|
+
const id = Array.isArray(idVar) ? idVar[0] : idVar;
|
|
14
|
+
if (id === undefined || id === '') {
|
|
15
|
+
return errorResource(uri, createToolError('VALIDATION', 'collage://assets/{id} requires an id'), 'no-request');
|
|
16
|
+
}
|
|
17
|
+
const result = await client.getAssetDetails(id);
|
|
18
|
+
if (!result.ok) {
|
|
19
|
+
return errorResource(uri, result.error, result.request_id);
|
|
20
|
+
}
|
|
21
|
+
return jsonResource(uri, {
|
|
22
|
+
asset: result.data,
|
|
23
|
+
request_id: result.request_id,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=asset-by-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-by-id.js","sourceRoot":"","sources":["../../src/resources/asset-by-id.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,8EAA8E;AAC9E,sEAAsE;AACtE,kDAAkD;AAClD,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AAIzE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,OAAO,KAAK,EACV,GAAQ,EACR,SAA4C,EACf,EAAE;QAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACnD,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClC,OAAO,aAAa,CAClB,GAAG,EACH,eAAe,CAAC,YAAY,EAAE,sCAAsC,CAAC,EACrE,YAAY,CACb,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,YAAY,CAAC,GAAG,EAAE;YACvB,KAAK,EAAE,MAAM,CAAC,IAAI;YAClB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { CollageClient } from '../client.js';
|
|
3
|
+
export declare function buildCollectionsListReader(client: CollageClient): (uri: URL) => Promise<ReadResourceResult>;
|
|
4
|
+
export declare function buildCollectionByIdReader(client: CollageClient): (uri: URL, variables: Record<string, string | string[]>) => Promise<ReadResourceResult>;
|
|
5
|
+
//# sourceMappingURL=collections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/resources/collections.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAUlD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,IAChD,KAAK,GAAG,KAAG,OAAO,CAAC,kBAAkB,CAAC,CAmBrD;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,IAE3D,KAAK,GAAG,EACR,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAwB/B"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ── collage://collections and collage://collections/{id} ──────────
|
|
2
|
+
// Backed by GET /digital-assets/collection/get-all. Collage exposes only
|
|
3
|
+
// the list endpoint for collections (no per-id route), so the by-id
|
|
4
|
+
// reader filters the list client-side via `getCollection(id)` — same
|
|
5
|
+
// trade-off the rest of the read-side surface uses.
|
|
6
|
+
//
|
|
7
|
+
// The static list resource budgets/paginates the response so very large
|
|
8
|
+
// workspaces stay within the 12K token cap.
|
|
9
|
+
import { createToolError } from '../conventions/errors.js';
|
|
10
|
+
import { budgetList, decodeOffsetCursor, errorResource, jsonResource, } from './helpers.js';
|
|
11
|
+
import { clampPageSize } from '../conventions/pagination.js';
|
|
12
|
+
export function buildCollectionsListReader(client) {
|
|
13
|
+
return async (uri) => {
|
|
14
|
+
const offset = decodeOffsetCursor(uri);
|
|
15
|
+
const pageSize = clampPageSize(Number(uri.searchParams.get('page_size') ?? undefined) || undefined);
|
|
16
|
+
const result = await client.listCollections();
|
|
17
|
+
if (!result.ok) {
|
|
18
|
+
return errorResource(uri, result.error, result.request_id);
|
|
19
|
+
}
|
|
20
|
+
const slice = result.data.slice(offset);
|
|
21
|
+
const budgeted = budgetList(slice, offset, pageSize);
|
|
22
|
+
return jsonResource(uri, {
|
|
23
|
+
items: budgeted.data,
|
|
24
|
+
total: result.data.length,
|
|
25
|
+
next_cursor: budgeted.next_cursor,
|
|
26
|
+
truncated: budgeted.truncated,
|
|
27
|
+
request_id: result.request_id,
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function buildCollectionByIdReader(client) {
|
|
32
|
+
return async (uri, variables) => {
|
|
33
|
+
const idVar = variables['id'];
|
|
34
|
+
const id = Array.isArray(idVar) ? idVar[0] : idVar;
|
|
35
|
+
if (id === undefined || id === '') {
|
|
36
|
+
return errorResource(uri, createToolError('VALIDATION', 'collage://collections/{id} requires an id'), 'no-request');
|
|
37
|
+
}
|
|
38
|
+
const result = await client.getCollection(id);
|
|
39
|
+
if (!result.ok) {
|
|
40
|
+
return errorResource(uri, result.error, result.request_id);
|
|
41
|
+
}
|
|
42
|
+
return jsonResource(uri, {
|
|
43
|
+
collection: result.data,
|
|
44
|
+
request_id: result.request_id,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=collections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/resources/collections.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yEAAyE;AACzE,oEAAoE;AACpE,qEAAqE;AACrE,oDAAoD;AACpD,EAAE;AACF,wEAAwE;AACxE,4CAA4C;AAI5C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,UAAU,0BAA0B,CAAC,MAAqB;IAC9D,OAAO,KAAK,EAAE,GAAQ,EAA+B,EAAE;QACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,aAAa,CAC5B,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,IAAI,SAAS,CACpE,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrD,OAAO,YAAY,CAAC,GAAG,EAAE;YACvB,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;YACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAqB;IAC7D,OAAO,KAAK,EACV,GAAQ,EACR,SAA4C,EACf,EAAE;QAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACnD,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClC,OAAO,aAAa,CAClB,GAAG,EACH,eAAe,CACb,YAAY,EACZ,2CAA2C,CAC5C,EACD,YAAY,CACb,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,YAAY,CAAC,GAAG,EAAE;YACvB,UAAU,EAAE,MAAM,CAAC,IAAI;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { CollageClient } from '../client.js';
|
|
3
|
+
export declare function buildCustomFieldsReader(client: CollageClient): (uri: URL) => Promise<ReadResourceResult>;
|
|
4
|
+
//# sourceMappingURL=custom-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-fields.d.ts","sourceRoot":"","sources":["../../src/resources/custom-fields.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AASlD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,IAC7C,KAAK,GAAG,KAAG,OAAO,CAAC,kBAAkB,CAAC,CAmBrD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// ── collage://custom-fields ──────────────────────────────────────────
|
|
2
|
+
// Backed by GET /digital-assets/custom-field/list (CollageClient.listCustomFields).
|
|
3
|
+
// Returns the workspace-scoped custom-field definitions used by the
|
|
4
|
+
// metadata-tagging tools — `{ id, field_label, field_type, status, ... }`.
|
|
5
|
+
//
|
|
6
|
+
// Workspace custom fields are typically a short list (< few dozen), so
|
|
7
|
+
// pagination is overkill. We still apply the response budget guard for
|
|
8
|
+
// the rare workspace that defines hundreds.
|
|
9
|
+
import { budgetList, decodeOffsetCursor, errorResource, jsonResource, } from './helpers.js';
|
|
10
|
+
import { clampPageSize } from '../conventions/pagination.js';
|
|
11
|
+
export function buildCustomFieldsReader(client) {
|
|
12
|
+
return async (uri) => {
|
|
13
|
+
const offset = decodeOffsetCursor(uri);
|
|
14
|
+
const pageSize = clampPageSize(Number(uri.searchParams.get('page_size') ?? undefined) || undefined);
|
|
15
|
+
const result = await client.listCustomFields();
|
|
16
|
+
if (!result.ok) {
|
|
17
|
+
return errorResource(uri, result.error, result.request_id);
|
|
18
|
+
}
|
|
19
|
+
const slice = result.data.slice(offset);
|
|
20
|
+
const budgeted = budgetList(slice, offset, pageSize);
|
|
21
|
+
return jsonResource(uri, {
|
|
22
|
+
items: budgeted.data,
|
|
23
|
+
total: result.data.length,
|
|
24
|
+
next_cursor: budgeted.next_cursor,
|
|
25
|
+
truncated: budgeted.truncated,
|
|
26
|
+
request_id: result.request_id,
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=custom-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-fields.js","sourceRoot":"","sources":["../../src/resources/custom-fields.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,oFAAoF;AACpF,oEAAoE;AACpE,2EAA2E;AAC3E,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,4CAA4C;AAI5C,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,UAAU,uBAAuB,CAAC,MAAqB;IAC3D,OAAO,KAAK,EAAE,GAAQ,EAA+B,EAAE;QACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,aAAa,CAC5B,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,IAAI,SAAS,CACpE,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrD,OAAO,YAAY,CAAC,GAAG,EAAE;YACvB,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;YACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { CollageClient } from '../client.js';
|
|
3
|
+
export declare function buildFoldersListReader(client: CollageClient): (uri: URL) => Promise<ReadResourceResult>;
|
|
4
|
+
export declare function buildFolderByIdReader(client: CollageClient): (uri: URL, variables: Record<string, string | string[]>) => Promise<ReadResourceResult>;
|
|
5
|
+
//# sourceMappingURL=folders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders.d.ts","sourceRoot":"","sources":["../../src/resources/folders.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAUlD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,IAC5C,KAAK,GAAG,KAAG,OAAO,CAAC,kBAAkB,CAAC,CAgBrD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,IAEvD,KAAK,GAAG,EACR,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CAmD/B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// ── collage://folders and collage://folders/{id} ──────────────────
|
|
2
|
+
// Two resources backed by the now-unblocked category endpoints.
|
|
3
|
+
//
|
|
4
|
+
// Static `collage://folders` returns the FULL folder tree as a flat list
|
|
5
|
+
// with `parent_id` populated on every row (null for roots). Upstream's
|
|
6
|
+
// `all-category-list` is flat-by-design and only returns roots, so this
|
|
7
|
+
// resource walks via `listAllCategoriesRecursive()` to recover the tree.
|
|
8
|
+
// Budget-applied so very large workspaces don't blow the 12K cap.
|
|
9
|
+
//
|
|
10
|
+
// Parameterised `collage://folders/{id}` returns one folder's row + its
|
|
11
|
+
// immediate sub-folders + a paginated page of assets. Asset paging uses
|
|
12
|
+
// `?cursor=` on the URI. Folder lookup also uses the recursive walk so
|
|
13
|
+
// nested folders resolve correctly.
|
|
14
|
+
import { createToolError } from '../conventions/errors.js';
|
|
15
|
+
import { clampPageSize } from '../conventions/pagination.js';
|
|
16
|
+
import { budgetList, decodeOffsetCursor, errorResource, jsonResource, } from './helpers.js';
|
|
17
|
+
export function buildFoldersListReader(client) {
|
|
18
|
+
return async (uri) => {
|
|
19
|
+
const offset = decodeOffsetCursor(uri);
|
|
20
|
+
const result = await client.listAllCategoriesRecursive();
|
|
21
|
+
if (!result.ok) {
|
|
22
|
+
return errorResource(uri, result.error, result.request_id);
|
|
23
|
+
}
|
|
24
|
+
const slice = result.data.slice(offset);
|
|
25
|
+
const budgeted = budgetList(slice, offset, slice.length);
|
|
26
|
+
return jsonResource(uri, {
|
|
27
|
+
items: budgeted.data,
|
|
28
|
+
total: result.data.length,
|
|
29
|
+
next_cursor: budgeted.next_cursor,
|
|
30
|
+
truncated: budgeted.truncated,
|
|
31
|
+
request_id: result.request_id,
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function buildFolderByIdReader(client) {
|
|
36
|
+
return async (uri, variables) => {
|
|
37
|
+
const idVar = variables['id'];
|
|
38
|
+
const id = Array.isArray(idVar) ? idVar[0] : idVar;
|
|
39
|
+
if (id === undefined || id === '') {
|
|
40
|
+
return errorResource(uri, createToolError('VALIDATION', 'collage://folders/{id} requires an id'), 'no-request');
|
|
41
|
+
}
|
|
42
|
+
const all = await client.listAllCategoriesRecursive();
|
|
43
|
+
if (!all.ok) {
|
|
44
|
+
return errorResource(uri, all.error, all.request_id);
|
|
45
|
+
}
|
|
46
|
+
const folder = all.data.find((c) => String(c.id) === String(id));
|
|
47
|
+
if (folder === undefined) {
|
|
48
|
+
return errorResource(uri, createToolError('NOT_FOUND', `folder ${id} not found in workspace`), all.request_id);
|
|
49
|
+
}
|
|
50
|
+
const subs = await client.listSubCategories(id);
|
|
51
|
+
if (!subs.ok) {
|
|
52
|
+
return errorResource(uri, subs.error, subs.request_id);
|
|
53
|
+
}
|
|
54
|
+
const pageSize = clampPageSize(Number(uri.searchParams.get('page_size') ?? undefined) || undefined);
|
|
55
|
+
const offset = decodeOffsetCursor(uri);
|
|
56
|
+
const upstreamPage = Math.floor(offset / pageSize) + 1;
|
|
57
|
+
const assets = await client.listAssetsByCategory(id, upstreamPage);
|
|
58
|
+
if (!assets.ok) {
|
|
59
|
+
return errorResource(uri, assets.error, assets.request_id);
|
|
60
|
+
}
|
|
61
|
+
const budgeted = budgetList(assets.data.assets, offset, pageSize);
|
|
62
|
+
return jsonResource(uri, {
|
|
63
|
+
folder,
|
|
64
|
+
subcategories: subs.data,
|
|
65
|
+
assets: budgeted.data,
|
|
66
|
+
total_assets: assets.data.total,
|
|
67
|
+
next_cursor: budgeted.next_cursor,
|
|
68
|
+
truncated: budgeted.truncated,
|
|
69
|
+
request_id: assets.request_id,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=folders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders.js","sourceRoot":"","sources":["../../src/resources/folders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { McpToolError } from '../conventions/errors.js';
|
|
3
|
+
import { type ResponseBudgetResult } from '../conventions/response-budget.js';
|
|
4
|
+
export declare function jsonResource(uri: URL, body: unknown): ReadResourceResult;
|
|
5
|
+
export declare function errorResource(uri: URL, error: McpToolError, request_id: string): ReadResourceResult;
|
|
6
|
+
/**
|
|
7
|
+
* Apply the shared 12K-token response budget to a list-shaped resource
|
|
8
|
+
* payload, returning the truncated slice plus a `next_cursor` when more
|
|
9
|
+
* remains.
|
|
10
|
+
*/
|
|
11
|
+
export declare function budgetList<T>(items: T[], offset: number, pageSize: number): ResponseBudgetResult<T[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Decode a `?cursor=…` (base64 of a non-negative integer offset). Defaults
|
|
14
|
+
* to 0 if absent or malformed — same lenient behaviour as the tools.
|
|
15
|
+
*/
|
|
16
|
+
export declare function decodeOffsetCursor(uri: URL): number;
|
|
17
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/resources/helpers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,mCAAmC,CAAC;AAI3C,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,GAAG,kBAAkB,CAQxE;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,GACjB,kBAAkB,CASpB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAM3B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAUnD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ── Resource helpers ─────────────────────────────────────────────────
|
|
2
|
+
// Small utilities shared by the MCP resource handlers. Resources return
|
|
3
|
+
// a `{ contents: [...] }` envelope per the SDK; we always emit a single
|
|
4
|
+
// JSON-stringified text item with mimeType `application/json`.
|
|
5
|
+
//
|
|
6
|
+
// Errors are converted to a structured JSON body (not thrown) so MCP
|
|
7
|
+
// clients always receive a parseable response — the upstream error code
|
|
8
|
+
// and request_id are surfaced in the body.
|
|
9
|
+
import { applyResponseBudget, estimateTokens, warnIfOverBudget, } from '../conventions/response-budget.js';
|
|
10
|
+
const JSON_MIME = 'application/json';
|
|
11
|
+
export function jsonResource(uri, body) {
|
|
12
|
+
const text = JSON.stringify(body, null, 2);
|
|
13
|
+
warnIfOverBudget(estimateTokens(text), uri.toString());
|
|
14
|
+
return {
|
|
15
|
+
contents: [
|
|
16
|
+
{ uri: uri.toString(), mimeType: JSON_MIME, text },
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function errorResource(uri, error, request_id) {
|
|
21
|
+
return jsonResource(uri, {
|
|
22
|
+
error: {
|
|
23
|
+
code: error.code,
|
|
24
|
+
message: error.message,
|
|
25
|
+
retriable: error.retriable,
|
|
26
|
+
},
|
|
27
|
+
request_id,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Apply the shared 12K-token response budget to a list-shaped resource
|
|
32
|
+
* payload, returning the truncated slice plus a `next_cursor` when more
|
|
33
|
+
* remains.
|
|
34
|
+
*/
|
|
35
|
+
export function budgetList(items, offset, pageSize) {
|
|
36
|
+
return applyResponseBudget(items, {
|
|
37
|
+
serialize: (item) => JSON.stringify(item),
|
|
38
|
+
offset,
|
|
39
|
+
pageSize,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Decode a `?cursor=…` (base64 of a non-negative integer offset). Defaults
|
|
44
|
+
* to 0 if absent or malformed — same lenient behaviour as the tools.
|
|
45
|
+
*/
|
|
46
|
+
export function decodeOffsetCursor(uri) {
|
|
47
|
+
const raw = uri.searchParams.get('cursor');
|
|
48
|
+
if (raw === null)
|
|
49
|
+
return 0;
|
|
50
|
+
try {
|
|
51
|
+
const decoded = Buffer.from(raw, 'base64').toString('utf-8');
|
|
52
|
+
const n = Number(decoded);
|
|
53
|
+
return Number.isFinite(n) && n >= 0 && Number.isInteger(n) ? n : 0;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/resources/helpers.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,+DAA+D;AAC/D,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,2CAA2C;AAI3C,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,GAEjB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,IAAa;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3C,gBAAgB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvD,OAAO;QACL,QAAQ,EAAE;YACR,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;SACnD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAQ,EACR,KAAmB,EACnB,UAAkB;IAElB,OAAO,YAAY,CAAC,GAAG,EAAE;QACvB,KAAK,EAAE;YACL,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;QACD,UAAU;KACX,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAU,EACV,MAAc,EACd,QAAgB;IAEhB,OAAO,mBAAmB,CAAC,KAAK,EAAE;QAChC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACzC,MAAM;QACN,QAAQ;KACT,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAQ;IACzC,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { CollageClient } from '../client.js';
|
|
3
|
+
export declare function buildPortalsListReader(client: CollageClient): (uri: URL) => Promise<ReadResourceResult>;
|
|
4
|
+
export declare function buildPortalByIdReader(client: CollageClient): (uri: URL, variables: Record<string, string | string[]>) => Promise<ReadResourceResult>;
|
|
5
|
+
//# sourceMappingURL=portals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portals.d.ts","sourceRoot":"","sources":["../../src/resources/portals.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,IAC5C,KAAK,GAAG,KAAG,OAAO,CAAC,kBAAkB,CAAC,CAUrD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,IAEvD,KAAK,GAAG,EACR,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,KAC3C,OAAO,CAAC,kBAAkB,CAAC,CA8B/B"}
|