@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.
- package/CLAUDE.md +1 -1
- package/README.md +2 -2
- package/dist/mcp-server/apps/appBuilders.d.ts +9 -1
- package/dist/mcp-server/apps/appBuilders.d.ts.map +1 -1
- package/dist/mcp-server/apps/appBuilders.js +64 -2
- package/dist/mcp-server/apps/appBuilders.js.map +1 -1
- package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -1
- package/dist/mcp-server/resources/resource-registration.js +14 -5
- package/dist/mcp-server/resources/resource-registration.js.map +1 -1
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts +16 -8
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts.map +1 -1
- package/dist/mcp-server/resources/utils/resourceDefinition.js.map +1 -1
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -1
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +11 -1
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -1
- package/package.json +13 -13
- package/skills/add-app-tool/SKILL.md +54 -32
- package/skills/add-prompt/SKILL.md +16 -11
- package/skills/add-resource/SKILL.md +16 -11
- package/skills/add-service/SKILL.md +47 -6
- package/skills/add-test/SKILL.md +23 -24
- package/skills/add-tool/SKILL.md +55 -13
- package/skills/api-testing/SKILL.md +56 -10
- package/skills/api-workers/SKILL.md +9 -7
- package/skills/devcheck/SKILL.md +20 -6
- package/skills/field-test/SKILL.md +17 -2
- package/skills/maintenance/SKILL.md +4 -2
- package/skills/migrate-mcp-ts-template/SKILL.md +14 -12
- package/skills/polish-docs-meta/SKILL.md +4 -4
- package/skills/setup/SKILL.md +9 -9
- package/templates/AGENTS.md +4 -0
- package/templates/CLAUDE.md +3 -0
- 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.
|
|
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
|
-
[](./CHANGELOG.md) [](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [](https://modelcontextprotocol.io/) [](./LICENSE)
|
|
9
9
|
|
|
10
10
|
[](https://www.typescriptlang.org/) [](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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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;
|
|
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
|
-
|
|
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
|
-
}
|
|
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,
|
|
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,
|
|
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
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
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
|
|
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":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AACxF,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACd,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;IACpC,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,mBAAmB,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC;AAE/E;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CACjC,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,EAC/D,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,SAAS;IAE9D
|
|
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;
|
|
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;
|
|
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
|
|
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":"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,
|
|
1
|
+
{"version":3,"file":"resourceHandlerFactory.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/utils/resourceHandlerFactory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.3.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
180
|
-
"@vitest/ui": "4.1.
|
|
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.
|
|
189
|
+
"msw": "^2.13.2",
|
|
190
190
|
"node-cron": "^4.2.1",
|
|
191
|
-
"openai": "^6.
|
|
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.
|
|
204
|
-
"vitest": "^4.1.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:**
|
|
160
|
-
- **Client-side SDK:**
|
|
161
|
-
- **CSP:** MCP Apps iframes run under deny-by-default CSP.
|
|
162
|
-
- **format() for
|
|
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
|
-
##
|
|
187
|
+
## Registration
|
|
165
188
|
|
|
166
189
|
```typescript
|
|
167
|
-
// src/
|
|
168
|
-
import {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
]
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
- [ ]
|
|
192
|
-
- [ ]
|
|
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`
|