@cyanheads/mcp-ts-core 0.3.2 → 0.3.4

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.
Files changed (33) hide show
  1. package/CLAUDE.md +1 -1
  2. package/README.md +2 -2
  3. package/dist/mcp-server/apps/appBuilders.d.ts +9 -1
  4. package/dist/mcp-server/apps/appBuilders.d.ts.map +1 -1
  5. package/dist/mcp-server/apps/appBuilders.js +64 -2
  6. package/dist/mcp-server/apps/appBuilders.js.map +1 -1
  7. package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -1
  8. package/dist/mcp-server/resources/resource-registration.js +14 -5
  9. package/dist/mcp-server/resources/resource-registration.js.map +1 -1
  10. package/dist/mcp-server/resources/utils/resourceDefinition.d.ts +16 -8
  11. package/dist/mcp-server/resources/utils/resourceDefinition.d.ts.map +1 -1
  12. package/dist/mcp-server/resources/utils/resourceDefinition.js.map +1 -1
  13. package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -1
  14. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +11 -1
  15. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -1
  16. package/package.json +13 -13
  17. package/skills/add-app-tool/SKILL.md +54 -32
  18. package/skills/add-prompt/SKILL.md +16 -11
  19. package/skills/add-resource/SKILL.md +16 -11
  20. package/skills/add-service/SKILL.md +47 -6
  21. package/skills/add-test/SKILL.md +23 -24
  22. package/skills/add-tool/SKILL.md +55 -13
  23. package/skills/api-testing/SKILL.md +56 -10
  24. package/skills/api-workers/SKILL.md +9 -7
  25. package/skills/devcheck/SKILL.md +20 -6
  26. package/skills/field-test/SKILL.md +17 -2
  27. package/skills/maintenance/SKILL.md +4 -2
  28. package/skills/migrate-mcp-ts-template/SKILL.md +14 -12
  29. package/skills/polish-docs-meta/SKILL.md +4 -4
  30. package/skills/setup/SKILL.md +9 -9
  31. package/templates/AGENTS.md +4 -0
  32. package/templates/CLAUDE.md +3 -0
  33. package/templates/src/mcp-server/resources/definitions/echo-app-ui.app-resource.ts +25 -14
package/CLAUDE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agent Protocol
2
2
 
3
- **Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.3.2
3
+ **Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.3.4
4
4
  **npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) · **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
5
5
 
6
6
  > **Developer note:** Never assume. Read related files and docs before making changes. Read full file content for context. Never edit a file before reading it.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  <div align="center">
7
7
 
8
- [![Version](https://img.shields.io/badge/Version-0.3.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE)
8
+ [![Version](https://img.shields.io/badge/Version-0.3.4-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE)
9
9
 
10
10
  [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
@@ -163,7 +163,7 @@ See [CLAUDE.md](CLAUDE.md) for the full configuration reference.
163
163
  | `resource(uriTemplate, options)` | Define a resource with `handler(params, ctx)` |
164
164
  | `prompt(name, options)` | Define a prompt with `generate(args)` |
165
165
  | `appTool(name, options)` | Define an MCP Apps tool with auto-populated `_meta.ui` |
166
- | `appResource(uriTemplate, options)` | Define an MCP Apps HTML resource with correct MIME type |
166
+ | `appResource(uriTemplate, options)` | Define an MCP Apps HTML resource with the correct MIME type and `_meta.ui` mirroring for read content |
167
167
 
168
168
  ### Context
169
169
 
@@ -2,7 +2,8 @@
2
2
  * @fileoverview Convenience builders for MCP Apps — `appTool()` and `appResource()`.
3
3
  * Wraps the standard `tool()` and `resource()` builders with MCP Apps-specific
4
4
  * defaults: auto-populates `_meta.ui.resourceUri`, sets the correct MIME type,
5
- * and handles the compat key (`ui/resourceUri`) required by some hosts.
5
+ * handles the compat key (`ui/resourceUri`) required by some hosts, and mirrors
6
+ * app resource `_meta.ui` into `resources/read` content items.
6
7
  * @module src/mcp-server/apps/appBuilders
7
8
  */
8
9
  import type { ZodObject, ZodRawShape } from 'zod';
@@ -53,6 +54,8 @@ type AppResourceOptions<TParams extends ZodObject<ZodRawShape>, TOutput extends
53
54
  * Creates an MCP Apps resource definition. Wraps `resource()` with:
54
55
  * - `mimeType` defaulting to `text/html;profile=mcp-app`
55
56
  * - `annotations.audience` defaulting to `['user']`
57
+ * - `_meta.ui` preserved on the definition and mirrored into `resources/read`
58
+ * content items so hosts receive the same CSP/permission metadata at read time
56
59
  *
57
60
  * The `uriTemplate` should use the `ui://` scheme.
58
61
  *
@@ -64,6 +67,11 @@ type AppResourceOptions<TParams extends ZodObject<ZodRawShape>, TOutput extends
64
67
  * name: 'my-app-ui',
65
68
  * description: 'Interactive UI for my_app_tool.',
66
69
  * params: z.object({}).describe('No parameters.'),
70
+ * _meta: {
71
+ * ui: {
72
+ * csp: { resourceDomains: ['https://cdn.example.com'] },
73
+ * },
74
+ * },
67
75
  * handler(_params, ctx) {
68
76
  * return '<html>...</html>';
69
77
  * },
@@ -1 +1 @@
1
- {"version":3,"file":"appBuilders.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/apps/appBuilders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AAE7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAGjF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,8BAA8B,CAAC;AAYlE,wFAAwF;AACxF,KAAK,cAAc,CACjB,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,EACrC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,IACpC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC5D;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,0FAA0F;IAC1F,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,EACrC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzF;AAMD,0FAA0F;AAC1F,KAAK,kBAAkB,CACrB,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS,IAC5D,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,GAAG;IAC3E,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS,EAE9D,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,GAC5C,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAWtC"}
1
+ {"version":3,"file":"appBuilders.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/apps/appBuilders.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AAE7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAGjF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,8BAA8B,CAAC;AAuFlE,wFAAwF;AACxF,KAAK,cAAc,CACjB,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,EACrC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,IACpC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC5D;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,0FAA0F;IAC1F,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,EACrC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzF;AAMD,0FAA0F;AAC1F,KAAK,kBAAkB,CACrB,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS,IAC5D,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,GAAG;IAC3E,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EACtC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS,EAE9D,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,GAC5C,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAetC"}
@@ -2,7 +2,8 @@
2
2
  * @fileoverview Convenience builders for MCP Apps — `appTool()` and `appResource()`.
3
3
  * Wraps the standard `tool()` and `resource()` builders with MCP Apps-specific
4
4
  * defaults: auto-populates `_meta.ui.resourceUri`, sets the correct MIME type,
5
- * and handles the compat key (`ui/resourceUri`) required by some hosts.
5
+ * handles the compat key (`ui/resourceUri`) required by some hosts, and mirrors
6
+ * app resource `_meta.ui` into `resources/read` content items.
6
7
  * @module src/mcp-server/apps/appBuilders
7
8
  */
8
9
  import { resource } from '../../mcp-server/resources/utils/resourceDefinition.js';
@@ -18,6 +19,56 @@ export const APP_RESOURCE_MIME_TYPE = 'text/html;profile=mcp-app';
18
19
  * Matches `RESOURCE_URI_META_KEY` from `@modelcontextprotocol/ext-apps/server`.
19
20
  */
20
21
  const RESOURCE_URI_META_KEY = 'ui/resourceUri';
22
+ function isPlainObject(value) {
23
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
24
+ }
25
+ function isJsonMimeType(mimeType) {
26
+ const normalizedMimeType = mimeType.split(';', 1)[0]?.trim().toLowerCase() ?? '';
27
+ return normalizedMimeType === 'application/json' || normalizedMimeType.endsWith('+json');
28
+ }
29
+ function formatResourceText(result, mimeType) {
30
+ return typeof result === 'string' && !isJsonMimeType(mimeType)
31
+ ? result
32
+ : JSON.stringify(result, null, 2);
33
+ }
34
+ function mergeNestedRecords(base, override) {
35
+ const merged = { ...base };
36
+ for (const [key, value] of Object.entries(override)) {
37
+ const existing = merged[key];
38
+ merged[key] =
39
+ isPlainObject(existing) && isPlainObject(value) ? mergeNestedRecords(existing, value) : value;
40
+ }
41
+ return merged;
42
+ }
43
+ function mirrorUiMetaIntoContents(contents, defaultUiMeta) {
44
+ return contents.map((content) => {
45
+ const contentMeta = isPlainObject(content._meta) ? content._meta : {};
46
+ const contentUiMeta = contentMeta.ui;
47
+ return {
48
+ ...content,
49
+ _meta: {
50
+ ...contentMeta,
51
+ ui: isPlainObject(contentUiMeta)
52
+ ? mergeNestedRecords(defaultUiMeta, contentUiMeta)
53
+ : (contentUiMeta ?? defaultUiMeta),
54
+ },
55
+ };
56
+ });
57
+ }
58
+ function createAppResourceFormat(format, defaultUiMeta) {
59
+ if (!defaultUiMeta)
60
+ return format;
61
+ return (result, meta) => {
62
+ const contents = format?.(result, meta) ?? [
63
+ {
64
+ uri: meta.uri.href,
65
+ text: formatResourceText(result, meta.mimeType),
66
+ mimeType: meta.mimeType,
67
+ },
68
+ ];
69
+ return mirrorUiMetaIntoContents(contents, defaultUiMeta);
70
+ };
71
+ }
21
72
  /**
22
73
  * Creates an MCP Apps tool definition. Wraps `tool()` with:
23
74
  * - `_meta.ui.resourceUri` set automatically
@@ -57,6 +108,8 @@ export function appTool(name, options) {
57
108
  * Creates an MCP Apps resource definition. Wraps `resource()` with:
58
109
  * - `mimeType` defaulting to `text/html;profile=mcp-app`
59
110
  * - `annotations.audience` defaulting to `['user']`
111
+ * - `_meta.ui` preserved on the definition and mirrored into `resources/read`
112
+ * content items so hosts receive the same CSP/permission metadata at read time
60
113
  *
61
114
  * The `uriTemplate` should use the `ui://` scheme.
62
115
  *
@@ -68,6 +121,11 @@ export function appTool(name, options) {
68
121
  * name: 'my-app-ui',
69
122
  * description: 'Interactive UI for my_app_tool.',
70
123
  * params: z.object({}).describe('No parameters.'),
124
+ * _meta: {
125
+ * ui: {
126
+ * csp: { resourceDomains: ['https://cdn.example.com'] },
127
+ * },
128
+ * },
71
129
  * handler(_params, ctx) {
72
130
  * return '<html>...</html>';
73
131
  * },
@@ -75,9 +133,13 @@ export function appTool(name, options) {
75
133
  * ```
76
134
  */
77
135
  export function appResource(uriTemplate, options) {
78
- const { mimeType, annotations, ...rest } = options;
136
+ const { mimeType, annotations, _meta, format, ...rest } = options;
137
+ const defaultUiMeta = isPlainObject(_meta?.ui) ? _meta.ui : undefined;
138
+ const appResourceFormat = createAppResourceFormat(format, defaultUiMeta);
79
139
  return resource(uriTemplate, {
80
140
  ...rest,
141
+ ...(_meta && { _meta }),
142
+ ...(appResourceFormat && { format: appResourceFormat }),
81
143
  mimeType: mimeType ?? APP_RESOURCE_MIME_TYPE,
82
144
  annotations: {
83
145
  audience: ['user'],
@@ -1 +1 @@
1
- {"version":3,"file":"appBuilders.js","sourceRoot":"","sources":["../../../src/mcp-server/apps/appBuilders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,oDAAoD,CAAC;AAE9E,OAAO,EAAE,IAAI,EAAE,MAAM,4CAA4C,CAAC;AAElE;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAElE;;;GAGG;AACH,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AAqB/C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,OAAO,CAGrB,IAAY,EAAE,OAAwC;IACtD,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACpD,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,GAAG,SAAS,IAAI,EAAE,CAAC;IAE1D,OAAO,IAAI,CAAC,IAAI,EAAE;QAChB,GAAG,IAAI;QACP,KAAK,EAAE;YACL,GAAG,aAAa;YAChB,EAAE,EAAE;gBACF,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;oBACjD,CAAC,CAAE,OAAmC;oBACtC,CAAC,CAAC,EAAE,CAAC;gBACP,WAAW;aACZ;YACD,CAAC,qBAAqB,CAAC,EAAE,WAAW;SACrC;KACF,CAAC,CAAC;AACL,CAAC;AAeD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,WAAW,CAIzB,WAAmB,EACnB,OAA6C;IAE7C,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEnD,OAAO,QAAQ,CAAC,WAAW,EAAE;QAC3B,GAAG,IAAI;QACP,QAAQ,EAAE,QAAQ,IAAI,sBAAsB;QAC5C,WAAW,EAAE;YACX,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,GAAG,WAAW;SACf;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"appBuilders.js","sourceRoot":"","sources":["../../../src/mcp-server/apps/appBuilders.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-registration.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/resources/resource-registration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAE3F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,wDAAwD,CAAC;AAUhE,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;IALlB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;gBAG3C,YAAY,EAAE,qBAAqB,EAAE,EACrC,QAAQ,EAAE,8BAA8B;IAGlD;;OAEG;IACU,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB1D,iFAAiF;IACjF,OAAO,CAAC,gBAAgB;YAUV,gBAAgB;CA8C/B"}
1
+ {"version":3,"file":"resource-registration.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/resources/resource-registration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAE3F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,wDAAwD,CAAC;AAchE,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;IALlB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;gBAG3C,YAAY,EAAE,qBAAqB,EAAE,EACrC,QAAQ,EAAE,8BAA8B;IAGlD;;OAEG;IACU,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB1D,iFAAiF;IACjF,OAAO,CAAC,gBAAgB;YAUV,gBAAgB;CAgD/B"}
@@ -8,6 +8,9 @@ import { JsonRpcErrorCode } from '../../types-global/errors.js';
8
8
  import { ErrorHandler } from '../../utils/internal/error-handler/errorHandler.js';
9
9
  import { logger } from '../../utils/internal/logger.js';
10
10
  import { requestContextService } from '../../utils/internal/requestContext.js';
11
+ function hasUriTemplateVariables(uriTemplate) {
12
+ return /\{[^}]+\}/.test(uriTemplate);
13
+ }
11
14
  export class ResourceRegistry {
12
15
  resourceDefs;
13
16
  services;
@@ -55,13 +58,10 @@ export class ResourceRegistry {
55
58
  logger.debug(`Registering resource: '${resourceName}'`, registrationContext);
56
59
  this.assertUniqueName(resourceName);
57
60
  await ErrorHandler.tryCatch(() => {
58
- const template = new ResourceTemplate(def.uriTemplate, {
59
- list: def.list,
60
- });
61
61
  const handler = createResourceHandler(def, this.services);
62
62
  const title = def.title ?? resourceName;
63
63
  const mimeType = def.mimeType ?? 'application/json';
64
- server.resource(resourceName, template, {
64
+ const metadata = {
65
65
  title,
66
66
  description: def.description,
67
67
  mimeType,
@@ -69,7 +69,16 @@ export class ResourceRegistry {
69
69
  ...(def.examples && { examples: def.examples }),
70
70
  ...(def.annotations && { annotations: def.annotations }),
71
71
  ...(def._meta && { _meta: def._meta }),
72
- }, handler);
72
+ };
73
+ if (hasUriTemplateVariables(def.uriTemplate)) {
74
+ const template = new ResourceTemplate(def.uriTemplate, {
75
+ list: def.list,
76
+ });
77
+ server.resource(resourceName, template, metadata, handler);
78
+ }
79
+ else {
80
+ server.resource(resourceName, def.uriTemplate, metadata, (uri, extra) => handler(uri, {}, extra));
81
+ }
73
82
  logger.debug(`Resource '${resourceName}' registered successfully.`, registrationContext);
74
83
  }, {
75
84
  operation: `RegisteringResource_${resourceName}`,
@@ -1 +1 @@
1
- {"version":3,"file":"resource-registration.js","sourceRoot":"","sources":["../../../src/mcp-server/resources/resource-registration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAkB,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3F,OAAO,EACL,qBAAqB,GAEtB,MAAM,wDAAwD,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAM3E,MAAM,OAAO,gBAAgB;IAKjB;IACA;IALV,wEAAwE;IACvD,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAErD,YACU,YAAqC,EACrC,QAAwC;QADxC,iBAAY,GAAZ,YAAY,CAAyB;QACrC,aAAQ,GAAR,QAAQ,CAAgC;IAC/C,CAAC;IAEJ;;OAEG;IACI,KAAK,CAAC,WAAW,CAAC,MAAiB;QACxC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7B,kEAAkE;QAClE,oEAAoE;QACpE,IAAI,CAAC,QAAQ,CAAC,yBAAyB,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,EAAE,CAAC;QACjF,IAAI,CAAC,QAAQ,CAAC,qBAAqB,GAAG,CAAC,GAAW,EAAE,EAAE,CACpD,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAE7C,MAAM,OAAO,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;YACzD,SAAS,EAAE,8BAA8B;SAC1C,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,YAAY,CAAC,MAAM,iBAAiB,EAAE,OAAO,CAAC,CAAC;QAEhF,2EAA2E;QAC3E,0EAA0E;QAC1E,+CAA+C;QAC9C,MAAsD,CAAC,0BAA0B,EAAE,CAAC;QAErF,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,iFAAiF;IACzE,gBAAgB,CAAC,IAAY;QACnC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,sDAAsD;gBACpF,wCAAwC,CAC3C,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,MAAiB,EAAE,GAA0B;QAC1E,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC;QACjD,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;YACrE,SAAS,EAAE,mCAAmC;YAC9C,iBAAiB,EAAE,EAAE,YAAY,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,0BAA0B,YAAY,GAAG,EAAE,mBAAmB,CAAC,CAAC;QAE7E,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAEpC,MAAM,YAAY,CAAC,QAAQ,CACzB,GAAG,EAAE;YACH,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,CAAC,WAAW,EAAE;gBACrD,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,YAAY,CAAC;YACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,kBAAkB,CAAC;YAEpD,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,QAAQ,EACR;gBACE,KAAK;gBACL,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,QAAQ;gBACR,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC3C,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAC/C,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;gBACxD,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;aACvC,EACD,OAAO,CACR,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,aAAa,YAAY,4BAA4B,EAAE,mBAAmB,CAAC,CAAC;QAC3F,CAAC,EACD;YACE,SAAS,EAAE,uBAAuB,YAAY,EAAE;YAChD,OAAO,EAAE,mBAAmB;YAC5B,SAAS,EAAE,gBAAgB,CAAC,oBAAoB;YAChD,QAAQ,EAAE,IAAI;SACf,CACF,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"resource-registration.js","sourceRoot":"","sources":["../../../src/mcp-server/resources/resource-registration.ts"],"names":[],"mappings":"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"}
@@ -30,15 +30,22 @@ export type ListExtra = RequestHandlerExtra<ServerRequest, ServerNotification>;
30
30
  */
31
31
  export interface ResourceDefinition<TParams extends ZodObject<ZodRawShape> = ZodObject<ZodRawShape>, TOutput extends ZodObject<ZodRawShape> | undefined = undefined> {
32
32
  /**
33
- * Protocol-level metadata for the resource.
34
- * For MCP Apps UI resources, use `_meta.ui` to declare CSP and permissions:
33
+ * Protocol-level metadata for the resource registration itself.
34
+ * For plain `resource()` MCP Apps UI resources, host-consumed UI metadata that
35
+ * must travel with `resources/read` content (for example `_meta.ui.csp` or
36
+ * permissions) should be attached to the returned content item from `format()`:
35
37
  * ```ts
36
- * _meta: {
37
- * ui: {
38
- * csp: { resourceDomains: ['https://cdn.example.com'] },
39
- * permissions: ['microphone'],
38
+ * format: (html, meta) => [{
39
+ * uri: meta.uri.href,
40
+ * text: html as string,
41
+ * mimeType: meta.mimeType,
42
+ * _meta: {
43
+ * ui: {
44
+ * csp: { resourceDomains: ['https://cdn.example.com'] },
45
+ * permissions: { microphone: {} },
46
+ * },
40
47
  * },
41
- * }
48
+ * }]
42
49
  * ```
43
50
  */
44
51
  _meta?: Record<string, unknown>;
@@ -55,7 +62,8 @@ export interface ResourceDefinition<TParams extends ZodObject<ZodRawShape> = Zod
55
62
  }[];
56
63
  /**
57
64
  * Optional formatter mapping output to ReadResourceResult contents.
58
- * If omitted, a default JSON formatter is used.
65
+ * If omitted, a default formatter is used: string results pass through for
66
+ * non-JSON MIME types, and JSON MIME types stringify all values.
59
67
  */
60
68
  format?: (result: unknown, meta: {
61
69
  uri: URL;
@@ -1 +1 @@
1
- {"version":3,"file":"resourceDefinition.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceDefinition.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resourceDefinition.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceDefinition.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resourceDefinition.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceDefinition.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsGH,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,QAAQ,CAItB,WAAmB,EACnB,OAAkE;IAElE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"resourceDefinition.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceDefinition.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA8GH,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,QAAQ,CAItB,WAAmB,EACnB,OAAkE;IAElE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC;AACrC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"resourceHandlerFactory.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceHandlerFactory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACxF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACd,MAAM,oCAAoC,CAAC;AAK5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAEhG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAQzD,KAAK,QAAQ,GAAG,mBAAmB,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;AAOvE,qEAAqE;AACrE,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB,CAAC,EAAE,MAAM,IAAI,CAAC;IACvC,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,cAAc,CAAC;CACzB;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,8BAA8B,GACvC,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAyElF"}
1
+ {"version":3,"file":"resourceHandlerFactory.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceHandlerFactory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACxF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACd,MAAM,oCAAoC,CAAC;AAK5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oDAAoD,CAAC;AAEhG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAQzD,KAAK,QAAQ,GAAG,mBAAmB,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;AAOvE,qEAAqE;AACrE,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB,CAAC,EAAE,MAAM,IAAI,CAAC;IACvC,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,cAAc,CAAC;CACzB;AAqDD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,8BAA8B,GACvC,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAyElF"}
@@ -12,11 +12,21 @@ import { requestContextService } from '../../../utils/internal/requestContext.js
12
12
  // ---------------------------------------------------------------------------
13
13
  // Default formatter
14
14
  // ---------------------------------------------------------------------------
15
+ function isJsonMimeType(mimeType) {
16
+ const normalizedMimeType = mimeType.split(';', 1)[0]?.trim().toLowerCase() ?? '';
17
+ return normalizedMimeType === 'application/json' || normalizedMimeType.endsWith('+json');
18
+ }
19
+ function formatResourceText(result, mimeType) {
20
+ return typeof result === 'string' && !isJsonMimeType(mimeType)
21
+ ? result
22
+ : JSON.stringify(result, null, 2);
23
+ }
15
24
  function defaultResponseFormatter(result, meta) {
25
+ const text = formatResourceText(result, meta.mimeType);
16
26
  return [
17
27
  {
18
28
  uri: meta.uri.href,
19
- text: JSON.stringify(result, null, 2),
29
+ text,
20
30
  mimeType: meta.mimeType,
21
31
  },
22
32
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"resourceHandlerFactory.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceHandlerFactory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resourceHandlerFactory.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceHandlerFactory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AAEnF,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AAE9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAqB3E,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IACjF,OAAO,kBAAkB,KAAK,kBAAkB,IAAI,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAe,EAAE,QAAgB;IAC3D,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;QAC5D,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,wBAAwB,CAC/B,MAAe,EACf,IAAoC;IAEpC,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,OAAO;QACL;YACE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;YAClB,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB;KACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,+BAA+B;AAC/B,8EAA8E;AAE9E,SAAS,UAAU,CAAC,UAAkC;IACpD,IAAI,OAAO,UAAU,CAAC,WAAW,KAAK,UAAU;QAAE,OAAO;IACzD,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC;IAClC,OAAO,CAAC,GAAW,EAAE,MAA8B,EAAE,EAAE,CACrD,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,CAA+C,CAAC;AAChG,CAAC;AAED,SAAS,UAAU,CAAC,UAAkC;IACpD,IAAI,OAAO,UAAU,CAAC,aAAa,KAAK,UAAU;QAAE,OAAO;IAC3D,MAAM,EAAE,GAAG,UAAU,CAAC,aAAa,CAAC;IACpC,OAAO,CAAC,IAAmD,EAAE,IAAmB,EAAE,EAAE,CAClF,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAA+C,CAAC;AAClF,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAA0B,EAC1B,QAAwC;IAExC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,kBAAkB,CAAC;IACpD,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,IAAI,wBAAwB,CAAC;IAEzD,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAA+B,EAAE;QACxE,MAAM,UAAU,GAAG,WAAkC,CAAC;QACtD,MAAM,OAAO,GAAG,WAAgD,CAAC;QAEjE,MAAM,SAAS,GAAG,OAAO,UAAU,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAE/F,MAAM,UAAU,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;YAC5D,aAAa,EAAE;gBACb,GAAG,CAAC,OAAO,UAAU,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzF,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpC;YACD,SAAS,EAAE,oBAAoB;YAC/B,iBAAiB,EAAE;gBACjB,YAAY,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW;gBACzC,WAAW,EAAE,GAAG,CAAC,IAAI;gBACrB,SAAS;gBACT,WAAW,EAAE,SAAS;aACvB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,2BAA2B;YAC3B,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAC3C,CAAC;YAED,wCAAwC;YACxC,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAE7E,iCAAiC;YACjC,MAAM,GAAG,GAAG,aAAa,CAAC;gBACxB,UAAU;gBACV,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC;gBAC3B,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC;gBAC3B,yBAAyB,EAAE,QAAQ,CAAC,yBAAyB;gBAC7D,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;gBACrD,GAAG;aACJ,CAAC,CAAC;YAEH,+CAA+C;YAC/C,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC;YACjD,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAClD,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,EACxD,EAAE,GAAG,UAAU,EAAE,YAAY,EAAE,EAC/B,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,CAC5B,CAAC;YAEF,8CAA8C;YAC9C,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAErF,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/D,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,4EAA4E;YAC5E,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;gBAC9B,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAC3D,MAAM,IAAI,QAAQ,CAChB,IAAI,EACJ,qBAAqB,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,KAAK,OAAO,EAAE,EAC9D,SAAS,EACT,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/mcp-ts-core",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-core",
5
5
  "description": "Agent-native TypeScript framework for building MCP servers. Build tools, not infrastructure. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Node.js and Cloudflare Workers.",
6
6
  "main": "dist/core/index.js",
@@ -141,14 +141,14 @@
141
141
  "publish-mcp": "bunx mcp-publisher publish"
142
142
  },
143
143
  "resolutions": {
144
- "@hono/node-server": "1.19.12",
144
+ "@hono/node-server": "1.19.13",
145
145
  "chrono-node": "2.9.0",
146
146
  "diff": "8.0.4",
147
147
  "dotenv": "17.4.1",
148
148
  "brace-expansion": "1.1.13",
149
149
  "flatted": "3.4.2",
150
150
  "handlebars": "4.7.9",
151
- "hono": "4.12.11",
151
+ "hono": "4.12.12",
152
152
  "lodash": "4.18.1",
153
153
  "path-to-regexp": "8.4.0",
154
154
  "picomatch": "2.3.2",
@@ -157,7 +157,7 @@
157
157
  },
158
158
  "devDependencies": {
159
159
  "@biomejs/biome": "2.4.10",
160
- "@cloudflare/workers-types": "^4.20260405.1",
160
+ "@cloudflare/workers-types": "^4.20260409.1",
161
161
  "@hono/otel": "^1.1.1",
162
162
  "@opentelemetry/instrumentation-http": "^0.214.0",
163
163
  "@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
@@ -168,7 +168,7 @@
168
168
  "@opentelemetry/sdk-node": "^0.214.0",
169
169
  "@opentelemetry/sdk-trace-node": "^2.6.1",
170
170
  "@opentelemetry/semantic-conventions": "^1.40.0",
171
- "@supabase/supabase-js": "^2.101.1",
171
+ "@supabase/supabase-js": "^2.102.1",
172
172
  "@types/bun": "^1.3.11",
173
173
  "@types/diff": "^8.0.0",
174
174
  "@types/js-yaml": "^4.0.9",
@@ -176,8 +176,8 @@
176
176
  "@types/papaparse": "^5.5.2",
177
177
  "@types/sanitize-html": "^2.16.1",
178
178
  "@types/validator": "^13.15.10",
179
- "@vitest/coverage-istanbul": "4.1.2",
180
- "@vitest/ui": "4.1.2",
179
+ "@vitest/coverage-istanbul": "4.1.3",
180
+ "@vitest/ui": "4.1.3",
181
181
  "bun-types": "^1.3.11",
182
182
  "chrono-node": "^2.9.0",
183
183
  "clipboardy": "^5.3.1",
@@ -186,9 +186,9 @@
186
186
  "fast-check": "^4.6.0",
187
187
  "js-yaml": "^4.1.1",
188
188
  "ignore": "^7.0.5",
189
- "msw": "^2.13.0",
189
+ "msw": "^2.13.2",
190
190
  "node-cron": "^4.2.1",
191
- "openai": "^6.33.0",
191
+ "openai": "^6.34.0",
192
192
  "papaparse": "^5.5.3",
193
193
  "partial-json": "^0.1.7",
194
194
  "pdf-lib": "^1.17.1",
@@ -200,8 +200,8 @@
200
200
  "typescript": "^6.0.2",
201
201
  "unpdf": "^1.4.0",
202
202
  "validator": "^13.15.35",
203
- "vite": "8.0.5",
204
- "vitest": "^4.1.2"
203
+ "vite": "8.0.8",
204
+ "vitest": "^4.1.3"
205
205
  },
206
206
  "keywords": [
207
207
  "agent",
@@ -253,12 +253,12 @@
253
253
  },
254
254
  "dependencies": {
255
255
  "@hono/mcp": "^0.2.5",
256
- "@hono/node-server": "^1.19.12",
256
+ "@hono/node-server": "^1.19.13",
257
257
  "@modelcontextprotocol/ext-apps": "^1.5.0",
258
258
  "@modelcontextprotocol/sdk": "^1.29.0",
259
259
  "@opentelemetry/api": "^1.9.1",
260
260
  "dotenv": "^17.4.1",
261
- "hono": "^4.12.11",
261
+ "hono": "^4.12.12",
262
262
  "jose": "^6.2.2",
263
263
  "pino": "^10.3.1",
264
264
  "zod": "^4.3.6"
@@ -4,7 +4,7 @@ description: >
4
4
  Scaffold an MCP App tool + UI resource pair. Use when the user asks to add a tool with interactive UI, create an MCP App, or build a visual/interactive tool.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.0"
7
+ version: "1.2"
8
8
  audience: external
9
9
  type: reference
10
10
  ---
@@ -28,7 +28,7 @@ For the full API, Context interface, and error codes, read:
28
28
  2. **Choose a URI** — convention: `ui://{{tool-name}}/app.html`
29
29
  3. **Create the app tool** at `src/mcp-server/tools/definitions/{{tool-name}}.app-tool.ts`
30
30
  4. **Create the app resource** at `src/mcp-server/resources/definitions/{{tool-name}}-ui.app-resource.ts`
31
- 5. **Register both** in their respective `definitions/index.ts` barrels
31
+ 5. **Register both** in the project's existing `createApp()` arrays (directly in `src/index.ts` for fresh scaffolds, or via barrels if the repo already has them)
32
32
  6. **Run `bun run devcheck`** — the linter validates `_meta.ui` and cross-checks tool/resource pairing
33
33
  7. **Smoke-test** with `bun run dev:stdio` or `dev:http`
34
34
 
@@ -64,11 +64,11 @@ export const {{TOOL_EXPORT}} = appTool('{{tool_name}}', {
64
64
 
65
65
  // format() serves dual purpose for app tools:
66
66
  // 1. First text block: JSON for the UI (app.ontoolresult parses it)
67
- // 2. Subsequent blocks: human-readable fallback for non-app hosts and LLM context
67
+ // 2. Subsequent blocks: human-readable, content-complete fallback for non-app hosts and LLM context
68
68
  format(result) {
69
69
  return [
70
70
  { type: 'text', text: JSON.stringify(result) },
71
- { type: 'text', text: '/* human-readable summary */' },
71
+ { type: 'text', text: '/* human-readable summary with all LLM-needed fields */' },
72
72
  ];
73
73
  },
74
74
  });
@@ -98,10 +98,29 @@ const APP_HTML = `<!DOCTYPE html>
98
98
  <!-- your UI markup -->
99
99
 
100
100
  <script type="module">
101
- import { App } from "https://unpkg.com/@modelcontextprotocol/ext-apps@1/app-with-deps";
101
+ // Prefer a bundled or inlined SDK for the final shipped HTML. Leaving a live
102
+ // CDN import in the served ui:// resource is not the recommended default.
103
+ import {
104
+ App,
105
+ applyDocumentTheme,
106
+ applyHostFonts,
107
+ applyHostStyleVariables,
108
+ } from "https://unpkg.com/@modelcontextprotocol/ext-apps@1/app-with-deps";
102
109
 
103
110
  const app = new App({ name: "{{TOOL_TITLE}}", version: "1.0.0" });
104
111
 
112
+ function applyHostContext(hostContext) {
113
+ if (hostContext?.theme) {
114
+ applyDocumentTheme(hostContext.theme);
115
+ }
116
+ if (hostContext?.styles?.variables) {
117
+ applyHostStyleVariables(hostContext.styles.variables);
118
+ }
119
+ if (hostContext?.styles?.css?.fonts) {
120
+ applyHostFonts(hostContext.styles.css.fonts);
121
+ }
122
+ }
123
+
105
124
  // Receive initial tool result from the host
106
125
  app.ontoolresult = (result) => {
107
126
  const text = result.content?.find(c => c.type === "text")?.text;
@@ -109,6 +128,7 @@ const APP_HTML = `<!DOCTYPE html>
109
128
  const data = JSON.parse(text);
110
129
  // render data into the DOM
111
130
  };
131
+ app.onhostcontextchanged = applyHostContext;
112
132
 
113
133
  // Proactively call tools from the UI
114
134
  document.getElementById("action-btn").addEventListener("click", async () => {
@@ -119,7 +139,10 @@ const APP_HTML = `<!DOCTYPE html>
119
139
  // handle result
120
140
  });
121
141
 
122
- await app.connect();
142
+ app.connect().then(() => {
143
+ const hostContext = app.getHostContext();
144
+ if (hostContext) applyHostContext(hostContext);
145
+ });
123
146
  </script>
124
147
  </body>
125
148
  </html>`;
@@ -128,14 +151,13 @@ export const {{RESOURCE_EXPORT}} = appResource('ui://{{tool-name}}/app.html', {
128
151
  name: '{{tool-name}}-ui',
129
152
  title: '{{TOOL_TITLE}} UI',
130
153
  description: 'Interactive HTML app for {{tool_name}}.',
131
- // CSP allowlist for external CDN imports (MCP Apps iframes use deny-by-default CSP)
154
+ params: ParamsSchema,
155
+ // auth: ['resource:{{tool-name}}-ui:read'],
132
156
  _meta: {
133
157
  ui: {
134
158
  csp: { resourceDomains: ['https://unpkg.com'] },
135
159
  },
136
160
  },
137
- params: ParamsSchema,
138
- // auth: ['resource:{{tool-name}}-ui:read'],
139
161
 
140
162
  handler(_params, ctx) {
141
163
  ctx.log.debug('Serving app UI.', { resourceUri: ctx.uri?.href });
@@ -156,39 +178,39 @@ export const {{RESOURCE_EXPORT}} = appResource('ui://{{tool-name}}/app.html', {
156
178
 
157
179
  ## UI Design Notes
158
180
 
159
- - **Bundling:** The simplest approach is inlining HTML/CSS/JS as a template literal (shown above). For complex UIs, use Vite + `vite-plugin-singlefile` to bundle into a single HTML file and read it from disk in the handler.
160
- - **Client-side SDK:** Import `App` from `@modelcontextprotocol/ext-apps` via CDN or bundle it. The `App` class provides `connect()`, `ontoolresult`, `callServerTool()`, `sendMessage()`, and `sendOpenLink()`.
161
- - **CSP:** MCP Apps iframes run under deny-by-default CSP. Inline scripts and styles work by default. External resources (CDN imports, API endpoints) require `_meta.ui.csp.resourceDomains` on the resource definition e.g., `_meta: { ui: { csp: { resourceDomains: ['https://unpkg.com'] } } }`. Without this, hosts that enforce CSP will block the import and the app will not boot.
162
- - **format() for app tools:** The first `text` content block is typically JSON that the UI parses via `ontoolresult`. Additional blocks provide a human-readable fallback that non-app hosts and LLMs consume.
181
+ - **Bundling:** Prefer Vite + `vite-plugin-singlefile` for any UI that uses `@modelcontextprotocol/ext-apps`. The served `ui://` HTML should ideally be self-contained. The inline template literal pattern is fine for zero-dependency UIs or when you inline the SDK yourself.
182
+ - **Client-side SDK:** Author against `@modelcontextprotocol/ext-apps`, but ship a bundled or inlined artifact when possible. Avoid relying on a live CDN import as the default final pattern for portable host compatibility.
183
+ - **CSP:** MCP Apps iframes run under deny-by-default CSP. With `appResource()`, put `_meta.ui.csp.resourceDomains` on the definition and the builder will mirror it into returned `resources/read` content items. With plain `resource()`, you still need to attach `_meta.ui` yourself in `format()`.
184
+ - **App resource `format()`:** `appResource()` already preserves raw HTML for the default app MIME type and mirrors definition `_meta.ui` into content items. Add a custom `format()` only when you need extra per-read metadata or non-default content shaping.
185
+ - **format() for app tools:** The first `text` content block is typically JSON that the UI parses via `ontoolresult`. Additional blocks provide a human-readable fallback that non-app hosts and LLMs consume. Do not rely on the JSON block alone for model-visible detail; the fallback blocks still need to render the fields the LLM must reason about.
163
186
 
164
- ## Barrel Registration
187
+ ## Registration
165
188
 
166
189
  ```typescript
167
- // src/mcp-server/tools/definitions/index.ts
168
- import { {{TOOL_EXPORT}} } from './{{tool-name}}.app-tool.js';
169
-
170
- export const allToolDefinitions = [
171
- // ... existing tools,
172
- {{TOOL_EXPORT}},
173
- ];
174
-
175
- // src/mcp-server/resources/definitions/index.ts
176
- import { {{RESOURCE_EXPORT}} } from './{{tool-name}}-ui.app-resource.js';
177
-
178
- export const allResourceDefinitions = [
179
- // ... existing resources,
180
- {{RESOURCE_EXPORT}},
181
- ];
190
+ // src/index.ts (fresh scaffold default)
191
+ import { createApp } from '@cyanheads/mcp-ts-core';
192
+ import { {{TOOL_EXPORT}} } from './mcp-server/tools/definitions/{{tool-name}}.app-tool.js';
193
+ import { {{RESOURCE_EXPORT}} } from './mcp-server/resources/definitions/{{tool-name}}-ui.app-resource.js';
194
+
195
+ await createApp({
196
+ tools: [{{TOOL_EXPORT}}],
197
+ resources: [{{RESOURCE_EXPORT}}],
198
+ prompts: [/* existing prompts */],
199
+ });
182
200
  ```
183
201
 
202
+ If the repo already uses `definitions/index.ts` barrels, update those instead of changing the registration pattern.
203
+
184
204
  ## Checklist
185
205
 
186
206
  - [ ] App tool created at `src/mcp-server/tools/definitions/{{tool-name}}.app-tool.ts` using `appTool()`
187
207
  - [ ] App resource created at `src/mcp-server/resources/definitions/{{tool-name}}-ui.app-resource.ts` using `appResource()`
188
208
  - [ ] `resourceUri` matches between tool and resource (`ui://{{tool-name}}/app.html`)
189
209
  - [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types
190
- - [ ] `format()` renders JSON first block (for UI) + human-readable blocks (for non-app hosts)
191
- - [ ] UI calls `app.connect()` and handles `app.ontoolresult`
192
- - [ ] Both registered in their respective `definitions/index.ts` barrels
210
+ - [ ] `format()` renders JSON first block (for UI) + human-readable, content-complete fallback blocks (for non-app hosts and LLMs)
211
+ - [ ] App resource `_meta.ui.csp` covers any external iframe dependencies, or a custom `format()` adds equivalent per-read metadata
212
+ - [ ] UI bundles or inlines the client SDK for the shipped HTML, and handles `app.ontoolresult`
213
+ - [ ] UI applies host context updates via `app.onhostcontextchanged`
214
+ - [ ] Both registered in the project's existing `createApp()` arrays (directly or via barrels)
193
215
  - [ ] `bun run devcheck` passes (linter validates `_meta.ui` and tool/resource pairing)
194
216
  - [ ] Smoke-tested with `bun run dev:stdio` or `dev:http`