wormclaude 1.0.119 → 1.0.121
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/dist/theme.js +1 -1
- package/dist/tui.js +6 -1
- package/package.json +1 -1
- package/skills/build-mcp-app/SKILL.md +0 -393
- package/skills/build-mcp-app/references/abuse-protection.md +0 -60
- package/skills/build-mcp-app/references/apps-sdk-messages.md +0 -227
- package/skills/build-mcp-app/references/directory-checklist.md +0 -18
- package/skills/build-mcp-app/references/iframe-sandbox.md +0 -164
- package/skills/build-mcp-app/references/payload-budgeting.md +0 -54
- package/skills/build-mcp-app/references/widget-templates.md +0 -249
- package/skills/build-mcp-server/SKILL.md +0 -222
- package/skills/build-mcp-server/references/auth.md +0 -108
- package/skills/build-mcp-server/references/deploy-cloudflare-workers.md +0 -106
- package/skills/build-mcp-server/references/elicitation.md +0 -129
- package/skills/build-mcp-server/references/remote-http-scaffold.md +0 -211
- package/skills/build-mcp-server/references/resources-and-prompts.md +0 -122
- package/skills/build-mcp-server/references/server-capabilities.md +0 -164
- package/skills/build-mcp-server/references/tool-design.md +0 -189
- package/skills/build-mcp-server/references/versions.md +0 -25
- package/skills/build-mcpb/SKILL.md +0 -200
- package/skills/build-mcpb/references/local-security.md +0 -149
- package/skills/build-mcpb/references/manifest-schema.md +0 -156
- package/skills/docx/script/__init__.py +0 -1
- package/skills/docx/script/accept_chages.py +0 -135
- package/skills/docx/script/comment.py +0 -318
- package/skills/docx/script/office/helpers/__init__.py +0 -0
- package/skills/docx/script/office/helpers/merge_runs.py +0 -199
- package/skills/docx/script/office/helpers/simplify_redlines.py +0 -197
- package/skills/docx/script/office/pack.py +0 -159
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/docx/script/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/docx/script/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/docx/script/office/schemas/mce/mc.xsd +0 -75
- package/skills/docx/script/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/docx/script/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/docx/script/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/docx/script/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/docx/script/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/docx/script/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/docx/script/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/docx/script/office/soffice.py +0 -183
- package/skills/docx/script/office/unpack.py +0 -132
- package/skills/docx/script/office/validate.py +0 -117
- package/skills/docx/script/office/validators/__init__.py +0 -15
- package/skills/docx/script/office/validators/base.py +0 -851
- package/skills/docx/script/office/validators/docx.py +0 -446
- package/skills/docx/script/office/validators/pptx.py +0 -275
- package/skills/docx/script/office/validators/redlining.py +0 -247
- package/skills/docx/script/templates/comments.xml +0 -3
- package/skills/docx/script/templates/commentsExtended.xml +0 -3
- package/skills/docx/script/templates/commentsExtensible.xml +0 -3
- package/skills/docx/script/templates/commentsIds.xml +0 -3
- package/skills/docx/script/templates/people.xml +0 -3
- package/skills/docx/skill.md +0 -593
- package/skills/explain.md +0 -14
- package/skills/frontend-design/SKILL.md +0 -42
- package/skills/pdf/FORMS.md +0 -294
- package/skills/pdf/REFERENCE.md +0 -612
- package/skills/pdf/SKILL.md +0 -314
- package/skills/pdf/scripts/check_bounding_boxes.py +0 -65
- package/skills/pdf/scripts/check_fillable_fields.py +0 -11
- package/skills/pdf/scripts/convert_pdf_to_images.py +0 -33
- package/skills/pdf/scripts/create_validation_image.py +0 -37
- package/skills/pdf/scripts/extract_form_field_info.py +0 -122
- package/skills/pdf/scripts/extract_form_structure.py +0 -115
- package/skills/pdf/scripts/fill_fillable_fields.py +0 -98
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -107
- package/skills/playground/SKILL.md +0 -77
- package/skills/playground/templates/code-map.md +0 -158
- package/skills/playground/templates/concept-map.md +0 -73
- package/skills/playground/templates/data-explorer.md +0 -67
- package/skills/playground/templates/design-playground.md +0 -67
- package/skills/playground/templates/diff-review.md +0 -179
- package/skills/playground/templates/document-critique.md +0 -171
- package/skills/pptx/SKILL.md +0 -230
- package/skills/pptx/editing.md +0 -205
- package/skills/pptx/pptxgenjs.md +0 -437
- package/skills/pptx/scripts/__init__.py +0 -0
- package/skills/pptx/scripts/add_slide.py +0 -195
- package/skills/pptx/scripts/clean.py +0 -286
- package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills/pptx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/pptx/scripts/office/pack.py +0 -159
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/pptx/scripts/office/soffice.py +0 -183
- package/skills/pptx/scripts/office/unpack.py +0 -132
- package/skills/pptx/scripts/office/validate.py +0 -117
- package/skills/pptx/scripts/office/validators/__init__.py +0 -15
- package/skills/pptx/scripts/office/validators/base.py +0 -851
- package/skills/pptx/scripts/office/validators/docx.py +0 -446
- package/skills/pptx/scripts/office/validators/pptx.py +0 -275
- package/skills/pptx/scripts/office/validators/redlining.py +0 -247
- package/skills/pptx/scripts/thumbnail.py +0 -289
- package/skills/recon.md +0 -16
- package/skills/security-audit/SKILL.md +0 -26
- package/skills/talent-creator/SKILL.md +0 -486
- package/skills/talent-creator/agents/analyzer.md +0 -274
- package/skills/talent-creator/agents/comparator.md +0 -202
- package/skills/talent-creator/agents/grader.md +0 -223
- package/skills/talent-creator/assets/eval_review.html +0 -146
- package/skills/talent-creator/eval-viewer/generate_review.py +0 -471
- package/skills/talent-creator/eval-viewer/viewer.html +0 -1325
- package/skills/talent-creator/references/schemas.md +0 -430
- package/skills/talent-creator/scripts/__init__.py +0 -0
- package/skills/talent-creator/scripts/aggregate_benchmark.py +0 -401
- package/skills/talent-creator/scripts/generate_report.py +0 -326
- package/skills/talent-creator/scripts/improve_description.py +0 -247
- package/skills/talent-creator/scripts/package_skill.py +0 -136
- package/skills/talent-creator/scripts/quick_validate.py +0 -146
- package/skills/talent-creator/scripts/run_eval.py +0 -310
- package/skills/talent-creator/scripts/run_loop.py +0 -328
- package/skills/talent-creator/scripts/utils.py +0 -47
- package/skills/xlsx/SKILL.md +0 -300
- package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/skills/xlsx/scripts/office/helpers/merge_runs.py +0 -199
- package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +0 -197
- package/skills/xlsx/scripts/office/pack.py +0 -159
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +0 -75
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/xlsx/scripts/office/soffice.py +0 -183
- package/skills/xlsx/scripts/office/unpack.py +0 -132
- package/skills/xlsx/scripts/office/validate.py +0 -117
- package/skills/xlsx/scripts/office/validators/__init__.py +0 -15
- package/skills/xlsx/scripts/office/validators/base.py +0 -851
- package/skills/xlsx/scripts/office/validators/docx.py +0 -446
- package/skills/xlsx/scripts/office/validators/pptx.py +0 -275
- package/skills/xlsx/scripts/office/validators/redlining.py +0 -247
- package/skills/xlsx/scripts/recalc.py +0 -184
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# Widget Templates
|
|
2
|
-
|
|
3
|
-
Minimal HTML scaffolds for the common widget shapes. Copy, fill in, and ship.
|
|
4
|
-
|
|
5
|
-
Every template inlines the `App` class from `@modelcontextprotocol/ext-apps` at build time, since the iframe's CSP blocks CDN script imports. They're deliberately framework-free — widgets are small enough that the React/Vue hydration cost rarely pays off.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Serving widget HTML
|
|
10
|
-
|
|
11
|
-
Widgets are static HTML with a single placeholder: at server startup, `/*__EXT_APPS_BUNDLE__*/` is replaced with the `ext-apps/app-with-deps` bundle (rewritten to expose `globalThis.ExtApps`).
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { readFileSync } from "node:fs";
|
|
15
|
-
import { createRequire } from "node:module";
|
|
16
|
-
import { registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
|
|
17
|
-
|
|
18
|
-
const require = createRequire(import.meta.url);
|
|
19
|
-
|
|
20
|
-
const bundle = readFileSync(
|
|
21
|
-
require.resolve("@modelcontextprotocol/ext-apps/app-with-deps"), "utf8",
|
|
22
|
-
).replace(/export\{([^}]+)\};?\s*$/, (_, body) =>
|
|
23
|
-
"globalThis.ExtApps={" +
|
|
24
|
-
body.split(",").map((p) => {
|
|
25
|
-
const [local, exported] = p.split(" as ").map((s) => s.trim());
|
|
26
|
-
return `${exported ?? local}:${local}`;
|
|
27
|
-
}).join(",") + "};",
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const pickerHtml = readFileSync("./widgets/picker.html", "utf8")
|
|
31
|
-
.replace("/*__EXT_APPS_BUNDLE__*/", () => bundle);
|
|
32
|
-
|
|
33
|
-
registerAppResource(server, "Picker", "ui://widgets/picker.html", {},
|
|
34
|
-
async () => ({
|
|
35
|
-
contents: [{ uri: "ui://widgets/picker.html", mimeType: RESOURCE_MIME_TYPE, text: pickerHtml }],
|
|
36
|
-
}),
|
|
37
|
-
);
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Build the bundle once per server startup (or at build time) and reuse the `bundle` string across every widget template.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Picker (single-select list)
|
|
45
|
-
|
|
46
|
-
```html
|
|
47
|
-
<!doctype html>
|
|
48
|
-
<meta charset="utf-8" />
|
|
49
|
-
<style>
|
|
50
|
-
body { font: 14px system-ui; margin: 0; }
|
|
51
|
-
ul { list-style: none; padding: 0; margin: 0; max-height: 280px; overflow-y: auto; }
|
|
52
|
-
li { padding: 10px 14px; cursor: pointer; border-bottom: 1px solid #eee; }
|
|
53
|
-
li:hover { background: #f5f5f5; }
|
|
54
|
-
.sub { color: #666; font-size: 12px; }
|
|
55
|
-
</style>
|
|
56
|
-
<ul id="list"></ul>
|
|
57
|
-
<script type="module">
|
|
58
|
-
/*__EXT_APPS_BUNDLE__*/
|
|
59
|
-
const { App } = globalThis.ExtApps;
|
|
60
|
-
(async () => {
|
|
61
|
-
const app = new App({ name: "Picker", version: "1.0.0" }, {});
|
|
62
|
-
const ul = document.getElementById("list");
|
|
63
|
-
|
|
64
|
-
app.ontoolresult = ({ content }) => {
|
|
65
|
-
const { items } = JSON.parse(content[0].text);
|
|
66
|
-
ul.innerHTML = "";
|
|
67
|
-
for (const it of items) {
|
|
68
|
-
const li = document.createElement("li");
|
|
69
|
-
li.innerHTML = `<div>${it.label}</div><div class="sub">${it.sub ?? ""}</div>`;
|
|
70
|
-
li.addEventListener("click", () => {
|
|
71
|
-
app.sendMessage({
|
|
72
|
-
role: "user",
|
|
73
|
-
content: [{ type: "text", text: `Selected: ${it.id}` }],
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
ul.append(li);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
await app.connect();
|
|
81
|
-
})();
|
|
82
|
-
</script>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**Tool returns:** `{ content: [{ type: "text", text: JSON.stringify({ items: [{ id, label, sub? }] }) }] }`
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Confirm dialog
|
|
90
|
-
|
|
91
|
-
```html
|
|
92
|
-
<!doctype html>
|
|
93
|
-
<meta charset="utf-8" />
|
|
94
|
-
<style>
|
|
95
|
-
body { font: 14px system-ui; margin: 16px; }
|
|
96
|
-
.actions { display: flex; gap: 8px; margin-top: 16px; }
|
|
97
|
-
button { padding: 8px 16px; cursor: pointer; }
|
|
98
|
-
.danger { background: #d33; color: white; border: none; }
|
|
99
|
-
</style>
|
|
100
|
-
<p id="msg"></p>
|
|
101
|
-
<div class="actions">
|
|
102
|
-
<button id="cancel">Cancel</button>
|
|
103
|
-
<button id="confirm" class="danger">Confirm</button>
|
|
104
|
-
</div>
|
|
105
|
-
<script type="module">
|
|
106
|
-
/*__EXT_APPS_BUNDLE__*/
|
|
107
|
-
const { App } = globalThis.ExtApps;
|
|
108
|
-
(async () => {
|
|
109
|
-
const app = new App({ name: "Confirm", version: "1.0.0" }, {});
|
|
110
|
-
|
|
111
|
-
app.ontoolresult = ({ content }) => {
|
|
112
|
-
const { message, confirmLabel } = JSON.parse(content[0].text);
|
|
113
|
-
document.getElementById("msg").textContent = message;
|
|
114
|
-
if (confirmLabel) document.getElementById("confirm").textContent = confirmLabel;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
await app.connect();
|
|
118
|
-
|
|
119
|
-
document.getElementById("confirm").addEventListener("click", () => {
|
|
120
|
-
app.sendMessage({ role: "user", content: [{ type: "text", text: "Confirmed." }] });
|
|
121
|
-
});
|
|
122
|
-
document.getElementById("cancel").addEventListener("click", () => {
|
|
123
|
-
app.sendMessage({ role: "user", content: [{ type: "text", text: "Cancelled." }] });
|
|
124
|
-
});
|
|
125
|
-
})();
|
|
126
|
-
</script>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Tool returns:** `{ content: [{ type: "text", text: JSON.stringify({ message, confirmLabel? }) }] }`
|
|
130
|
-
|
|
131
|
-
**Note:** For a plain confirmation, lean on **elicitation** rather than a widget — see `../build-mcp-server/references/elicitation.md`. Reach for this widget when you need custom styling or context that a native form can't provide.
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Progress (long-running)
|
|
136
|
-
|
|
137
|
-
```html
|
|
138
|
-
<!doctype html>
|
|
139
|
-
<meta charset="utf-8" />
|
|
140
|
-
<style>
|
|
141
|
-
body { font: 14px system-ui; margin: 16px; }
|
|
142
|
-
.bar { height: 8px; background: #eee; border-radius: 4px; overflow: hidden; }
|
|
143
|
-
.fill { height: 100%; background: #2a7; transition: width 200ms; }
|
|
144
|
-
</style>
|
|
145
|
-
<p id="label">Starting…</p>
|
|
146
|
-
<div class="bar"><div id="fill" class="fill" style="width:0%"></div></div>
|
|
147
|
-
<script type="module">
|
|
148
|
-
/*__EXT_APPS_BUNDLE__*/
|
|
149
|
-
const { App } = globalThis.ExtApps;
|
|
150
|
-
(async () => {
|
|
151
|
-
const app = new App({ name: "Progress", version: "1.0.0" }, {});
|
|
152
|
-
const label = document.getElementById("label");
|
|
153
|
-
const fill = document.getElementById("fill");
|
|
154
|
-
|
|
155
|
-
// The tool result fires when the job completes — intermediate updates
|
|
156
|
-
// arrive via the same handler if the server streams them
|
|
157
|
-
app.ontoolresult = ({ content }) => {
|
|
158
|
-
const state = JSON.parse(content[0].text);
|
|
159
|
-
if (state.progress !== undefined) {
|
|
160
|
-
label.textContent = state.message ?? `${state.progress}/${state.total}`;
|
|
161
|
-
fill.style.width = `${(state.progress / state.total) * 100}%`;
|
|
162
|
-
}
|
|
163
|
-
if (state.done) {
|
|
164
|
-
label.textContent = "Complete";
|
|
165
|
-
fill.style.width = "100%";
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
await app.connect();
|
|
170
|
-
})();
|
|
171
|
-
</script>
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Server side, emit progress via `extra.sendNotification({ method: "notifications/progress", ... })` — see `apps-sdk-messages.md`.
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## Display-only (chart / preview)
|
|
179
|
-
|
|
180
|
-
Display widgets never call `sendMessage` — they render and then just sit there. The tool should return a text summary **alongside** the widget so WormClaude can keep reasoning while the user looks at the visual:
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
registerAppTool(server, "show_chart", {
|
|
184
|
-
description: "Render a revenue chart",
|
|
185
|
-
inputSchema: { range: z.enum(["week", "month", "year"]) },
|
|
186
|
-
_meta: { ui: { resourceUri: "ui://widgets/chart.html" } },
|
|
187
|
-
}, async ({ range }) => {
|
|
188
|
-
const data = await fetchRevenue(range);
|
|
189
|
-
return {
|
|
190
|
-
content: [{
|
|
191
|
-
type: "text",
|
|
192
|
-
text: `Revenue is up ${data.change}% over the ${range}. Chart rendered.\n\n` +
|
|
193
|
-
JSON.stringify(data.points),
|
|
194
|
-
}],
|
|
195
|
-
};
|
|
196
|
-
});
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
```html
|
|
200
|
-
<!doctype html>
|
|
201
|
-
<meta charset="utf-8" />
|
|
202
|
-
<style>body { font: 14px system-ui; margin: 12px; }</style>
|
|
203
|
-
<canvas id="chart" width="400" height="200"></canvas>
|
|
204
|
-
<script type="module">
|
|
205
|
-
/*__EXT_APPS_BUNDLE__*/
|
|
206
|
-
const { App } = globalThis.ExtApps;
|
|
207
|
-
(async () => {
|
|
208
|
-
const app = new App({ name: "Chart", version: "1.0.0" }, {});
|
|
209
|
-
|
|
210
|
-
app.ontoolresult = ({ content }) => {
|
|
211
|
-
// Parse the JSON points from the text content (after the summary line)
|
|
212
|
-
const text = content[0].text;
|
|
213
|
-
const jsonStart = text.indexOf("\n\n") + 2;
|
|
214
|
-
const points = JSON.parse(text.slice(jsonStart));
|
|
215
|
-
drawChart(document.getElementById("chart"), points);
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
await app.connect();
|
|
219
|
-
|
|
220
|
-
function drawChart(canvas, points) { /* ... */ }
|
|
221
|
-
})();
|
|
222
|
-
</script>
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## Carousel (multi-item display with actions)
|
|
228
|
-
|
|
229
|
-
For laying out several items (product picks, search results) in a horizontal scroll rail. Patterns that held up well in testing:
|
|
230
|
-
|
|
231
|
-
- **Skip the nav chevrons** — users already know how to scroll. `scroll-snap-type` can leave the initial render a few px off-flush; drop it and set `scrollLeft = 0` after rendering.
|
|
232
|
-
- **Fork the layout by item count** — `items.length === 1` → detail/PDP layout, `> 1` → carousel. Do it in widget JS and keep the tool schema flat.
|
|
233
|
-
- **Put WormClaude's reasoning on each item** — a `note` field rendered as a small callout on the card gives users the "why" right there.
|
|
234
|
-
- **Silent state through `updateModelContext`** — cart or selection changes should inform WormClaude without spamming the chat. Save `sendMessage` for terminal actions ("checkout", "done").
|
|
235
|
-
- **Outbound links through `app.openLink`** — the sandbox blocks `window.open` and `<a target="_blank">`.
|
|
236
|
-
|
|
237
|
-
```html
|
|
238
|
-
<style>
|
|
239
|
-
.rail { display: flex; gap: 10px; overflow-x: auto; padding: 12px; scrollbar-width: none; }
|
|
240
|
-
.rail::-webkit-scrollbar { display: none; }
|
|
241
|
-
.card { flex: 0 0 220px; border: 1px solid #ddd; border-radius: 6px; padding: 10px; }
|
|
242
|
-
.thumb-box { aspect-ratio: 1 / 1; display: grid; place-items: center; background: #f7f8f8; }
|
|
243
|
-
.thumb { max-width: 100%; max-height: 100%; object-fit: contain; }
|
|
244
|
-
.note { font-size: 12px; color: #666; border-left: 3px solid orange; padding: 2px 8px; margin: 8px 0; }
|
|
245
|
-
</style>
|
|
246
|
-
<div class="rail" id="rail"></div>
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
**Images:** the iframe CSP blocks remote `img-src`. Fetch thumbnails server-side in the tool handler, embed them as `data:` URLs in the JSON payload, and render from those. Add `referrerpolicy="no-referrer"` as a fallback.
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: build-mcp-server
|
|
3
|
-
description: Reach for this skill whenever someone asks to "build an MCP server", "create an MCP", "make an MCP integration", "wrap an API for WormClaude", "expose tools to WormClaude", "make an MCP app", or otherwise talks about building on the Model Context Protocol. It serves as the front door for MCP server work — probing the user's use case, settling on the correct deployment model (remote HTTP, MCPB, local stdio), choosing a tool-design pattern, and routing to the specialized skills.
|
|
4
|
-
license: WormClaude
|
|
5
|
-
version: 0.1.0
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Build an MCP Server
|
|
9
|
-
|
|
10
|
-
Your role here is to walk a developer through the design and construction of an MCP server that integrates cleanly with WormClaude. Because MCP servers take many shapes, committing to the wrong one early leads to costly rewrites later. Lead with **discovery, not code**.
|
|
11
|
-
|
|
12
|
-
**Pull in WormClaude-specific context before anything else.** The MCP specification is intentionally generic, but WormClaude layers on its own auth types, review rules, and limits. Before you answer questions or scaffold code, retrieve `https://claude.com/docs/llms-full.txt` (the complete export of the connector documentation) so your advice matches WormClaude's real constraints.
|
|
13
|
-
|
|
14
|
-
Hold off on scaffolding until the Phase 1 questions are answered. When the user's first message already covers them, note that and jump directly to your recommendation.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Phase 1 — Interrogate the use case
|
|
19
|
-
|
|
20
|
-
Pose these questions in a natural, conversational way — bundle them into a single message rather than firing them off one at a time. Tailor the phrasing to whatever the user has already shared.
|
|
21
|
-
|
|
22
|
-
### 1. What does it connect to?
|
|
23
|
-
|
|
24
|
-
| If it connects to… | Likely direction |
|
|
25
|
-
|---|---|
|
|
26
|
-
| A cloud API (SaaS, REST, GraphQL) | Remote HTTP server |
|
|
27
|
-
| A local process, filesystem, or desktop app | MCPB or local stdio |
|
|
28
|
-
| Hardware, OS-level APIs, or user-specific state | MCPB |
|
|
29
|
-
| Nothing external — pure logic / computation | Either — default to remote |
|
|
30
|
-
|
|
31
|
-
### 2. Who will use it?
|
|
32
|
-
|
|
33
|
-
- **Just me / my team, on our machines** → Local stdio is fine (quickest to prototype)
|
|
34
|
-
- **Anyone who installs it** → Remote HTTP (strongly preferred), or MCPB when it *has to* be local
|
|
35
|
-
- **WormClaude desktop users who want UI widgets** → MCP app (remote or MCPB)
|
|
36
|
-
|
|
37
|
-
### 3. How many distinct actions does it expose?
|
|
38
|
-
|
|
39
|
-
This drives the tool-design pattern — see Phase 3.
|
|
40
|
-
|
|
41
|
-
- **Under ~15 actions** → one tool per action
|
|
42
|
-
- **Dozens to hundreds of actions** (e.g. wrapping a large API surface) → search + execute pattern
|
|
43
|
-
|
|
44
|
-
### 4. Does a tool need mid-call user input or rich display?
|
|
45
|
-
|
|
46
|
-
- **Simple structured input** (pick from a list, type a value, confirm) → **Elicitation** — spec-native, no UI code at all. *Host support is still landing* (Claude Code ≥2.1.76), so always combine it with a capability check and a fallback. See `references/elicitation.md`.
|
|
47
|
-
- **Rich/visual UI** (charts, searchable custom pickers, live dashboards) → **MCP app widgets** — iframe-based, requires `@modelcontextprotocol/ext-apps`. See the `build-mcp-app` skill.
|
|
48
|
-
- **Neither** → a plain tool that returns text/JSON.
|
|
49
|
-
|
|
50
|
-
### 5. What auth does the upstream service use?
|
|
51
|
-
|
|
52
|
-
- None / API key → easy
|
|
53
|
-
- OAuth 2.0 → you'll want a remote server with CIMD (preferred) or DCR support; see `references/auth.md`
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Phase 2 — Recommend a deployment model
|
|
58
|
-
|
|
59
|
-
Use the answers to land on **one** path, and take a clear stance. Ranked from best to last:
|
|
60
|
-
|
|
61
|
-
### ⭐ Remote streamable-HTTP MCP server (default recommendation)
|
|
62
|
-
|
|
63
|
-
A hosted service that speaks MCP over streamable HTTP. This is the **go-to choice** for anything that wraps a cloud API.
|
|
64
|
-
|
|
65
|
-
**Why it comes out on top:**
|
|
66
|
-
- No install hassle — users paste a URL and they're done
|
|
67
|
-
- A single deployment covers every user, and you own the upgrade cycle
|
|
68
|
-
- OAuth flows behave correctly (the server can manage redirects, DCR, and token storage)
|
|
69
|
-
- Runs across WormClaude desktop, Claude Code, Claude.ai, and other third-party MCP hosts
|
|
70
|
-
|
|
71
|
-
**Pick this unless** the server genuinely needs to reach the user's local machine.
|
|
72
|
-
|
|
73
|
-
→ **Fastest deploy:** Cloudflare Workers — `references/deploy-cloudflare-workers.md` (zero to live URL in two commands)
|
|
74
|
-
→ **Portable Node/Python:** `references/remote-http-scaffold.md` (Express or FastMCP, runs on any host)
|
|
75
|
-
|
|
76
|
-
### Elicitation (structured input, no UI build)
|
|
77
|
-
|
|
78
|
-
When a tool only needs the user to confirm something, choose an option, or complete a short form, **elicitation** handles it without writing any UI. The server hands over a flat JSON schema and the host draws a native form. It's spec-native and needs no extra packages.
|
|
79
|
-
|
|
80
|
-
**Caveat:** Host support is recent (Claude Code added it in v2.1.76; Desktop unconfirmed). The SDK raises an error if the client hasn't advertised the capability, so always test `clientCapabilities.elicitation` first and keep a fallback ready — `references/elicitation.md` has the canonical pattern. It's the spec-correct route, and host coverage will fill in over time.
|
|
81
|
-
|
|
82
|
-
Move up to `build-mcp-app` widgets when you need nested or complex data, scrollable/searchable lists, visual previews, or live updates.
|
|
83
|
-
|
|
84
|
-
### MCP app (remote HTTP + interactive UI)
|
|
85
|
-
|
|
86
|
-
Everything above, plus **UI resources** — interactive widgets that render inline in chat: searchable pickers, charts, live dashboards, visual previews. Write it once and it renders in WormClaude *and* ChatGPT.
|
|
87
|
-
|
|
88
|
-
**Reach for this when** elicitation's flat-form limits get in the way — you need a custom layout, large searchable lists, visual content, or live updates.
|
|
89
|
-
|
|
90
|
-
It's usually remote, but you can ship it as MCPB when the UI has to drive a local app.
|
|
91
|
-
|
|
92
|
-
→ Hand off to the **`build-mcp-app`** skill.
|
|
93
|
-
|
|
94
|
-
### MCPB (bundled local server)
|
|
95
|
-
|
|
96
|
-
A local MCP server **bundled together with its runtime** so users don't have to install Node or Python. This is the approved way to distribute local servers.
|
|
97
|
-
|
|
98
|
-
**Reach for this when** the server truly has to run on the user's machine — reading local files, driving a desktop app, talking to localhost services, or needing OS-level access.
|
|
99
|
-
|
|
100
|
-
→ Hand off to the **`build-mcpb`** skill.
|
|
101
|
-
|
|
102
|
-
### Local stdio (npx / uvx) — *not recommended for distribution*
|
|
103
|
-
|
|
104
|
-
A script run through `npx` / `uvx` on the user's machine. Perfectly fine for **personal tools and prototypes**, but a headache to distribute: users need the correct runtime, you have no way to push updates, and the only channel is Claude Code plugins.
|
|
105
|
-
|
|
106
|
-
Suggest this only as a stepping stone. If the user is set on it, scaffold it but call out the MCPB upgrade path.
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## Phase 3 — Pick a tool-design pattern
|
|
111
|
-
|
|
112
|
-
Every MCP server exposes tools, and how you slice them up matters more than people tend to assume — tool schemas go straight into WormClaude's context window.
|
|
113
|
-
|
|
114
|
-
### Pattern A: One tool per action (small surface)
|
|
115
|
-
|
|
116
|
-
When the set of actions is small (under ~15 operations), hand each one its own tool with a precise description and schema.
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
create_issue — Create a new issue. Params: title, body, labels[]
|
|
120
|
-
update_issue — Update an existing issue. Params: id, title?, body?, state?
|
|
121
|
-
search_issues — Search issues by query string. Params: query, limit?
|
|
122
|
-
add_comment — Add a comment to an issue. Params: issue_id, body
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
**Why it works:** WormClaude reads the tool list a single time and immediately knows what's available — no discovery round-trips — and each tool's schema validates inputs tightly.
|
|
126
|
-
|
|
127
|
-
**It shines especially when** one or more tools carry an interactive widget (MCP app), since each widget pairs cleanly with a single tool.
|
|
128
|
-
|
|
129
|
-
### Pattern B: Search + execute (large surface)
|
|
130
|
-
|
|
131
|
-
When you're wrapping a large API (dozens to hundreds of endpoints), exposing every operation as its own tool floods the context window and hurts model performance. Expose **two** tools instead:
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
search_actions — Given a natural-language intent, return matching actions
|
|
135
|
-
with their IDs, descriptions, and parameter schemas.
|
|
136
|
-
execute_action — Run an action by ID with a params object.
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
The server keeps the entire catalog in-house. WormClaude searches it, makes a pick, and executes — keeping the context window lean.
|
|
140
|
-
|
|
141
|
-
**Hybrid:** Pull the 3–5 most-used actions out into dedicated tools and leave the long tail behind search/execute.
|
|
142
|
-
|
|
143
|
-
→ See `references/tool-design.md` for schema examples and description-writing guidance.
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## Phase 4 — Pick a framework
|
|
148
|
-
|
|
149
|
-
Point them at one of these two. Other options exist, but these have the strongest MCP-spec coverage and WormClaude compatibility.
|
|
150
|
-
|
|
151
|
-
| Framework | Language | Use when |
|
|
152
|
-
|---|---|---|
|
|
153
|
-
| **Official TypeScript SDK** (`@modelcontextprotocol/sdk`) | TS/JS | The default. Best spec coverage and first in line for new features. |
|
|
154
|
-
| **FastMCP 3.x** (`fastmcp` on PyPI) | Python | The user leans Python, or you're wrapping a Python library. Decorator-driven with minimal boilerplate. This is jlowin's package — not the frozen FastMCP 1.0 baked into the official `mcp` SDK. |
|
|
155
|
-
|
|
156
|
-
If the user already has a language or stack in mind, run with it — both emit an identical wire protocol.
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## Phase 5 — Scaffold and hand off
|
|
161
|
-
|
|
162
|
-
Once the four decisions are locked in (deployment model, tool pattern, framework, auth), do **one** of the following:
|
|
163
|
-
|
|
164
|
-
1. **Remote HTTP, no UI** → Scaffold it inline with `references/remote-http-scaffold.md` (portable) or `references/deploy-cloudflare-workers.md` (fastest to deploy). This skill can carry it to completion.
|
|
165
|
-
2. **MCP app (UI widgets)** → Recap the decisions so far, then load the **`build-mcp-app`** skill.
|
|
166
|
-
3. **MCPB (bundled local)** → Recap the decisions so far, then load the **`build-mcpb`** skill.
|
|
167
|
-
4. **Local stdio prototype** → Scaffold it inline (the simplest case) and flag the MCPB upgrade path.
|
|
168
|
-
|
|
169
|
-
Whenever you hand off, restate the design brief in a single paragraph so the next skill doesn't have to ask again.
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## Beyond tools — the other primitives
|
|
174
|
-
|
|
175
|
-
Tools are just one of three server primitives. Most servers begin and end with tools, but being aware of the other two keeps you from reinventing the wheel:
|
|
176
|
-
|
|
177
|
-
| Primitive | Who triggers it | Use when |
|
|
178
|
-
|---|---|---|
|
|
179
|
-
| **Resources** | Host app (not WormClaude) | Exposing docs/files/data as browsable context |
|
|
180
|
-
| **Prompts** | User (slash command) | Canned workflows ("/summarize-thread") |
|
|
181
|
-
| **Elicitation** | Server, mid-tool | Asking the user for input without building UI |
|
|
182
|
-
| **Sampling** | Server, mid-tool | Needing LLM inference inside your tool logic |
|
|
183
|
-
|
|
184
|
-
→ `references/resources-and-prompts.md`, `references/elicitation.md`, `references/server-capabilities.md`
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Phase 6 — Test in Claude and publish
|
|
189
|
-
|
|
190
|
-
Once the server is up:
|
|
191
|
-
|
|
192
|
-
1. **Try it against the real WormClaude** by adding the server URL as a custom connector under Settings → Connectors (use a Cloudflare tunnel for local servers). On initialize, the host announces itself with `clientInfo.name: "claude-ai"`. → https://claude.com/docs/connectors/building/testing
|
|
193
|
-
2. **Work through the pre-submission checklist** — the read/write tool split, mandatory annotations, name-length limits, and prompt-injection rules. → https://claude.com/docs/connectors/building/review-criteria
|
|
194
|
-
3. **Submit to the WormClaude Directory.** → https://claude.com/docs/connectors/building/submission
|
|
195
|
-
4. **Consider shipping a plugin** that wraps this MCP together with skills — most partners ship both. → https://claude.com/docs/connectors/building/what-to-build
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Quick reference: decision matrix
|
|
200
|
-
|
|
201
|
-
| Scenario | Deployment | Tool pattern |
|
|
202
|
-
|---|---|---|
|
|
203
|
-
| Wrap a small SaaS API | Remote HTTP | One-per-action |
|
|
204
|
-
| Wrap a large SaaS API (50+ endpoints) | Remote HTTP | Search + execute |
|
|
205
|
-
| SaaS API with rich forms / pickers | MCP app (remote) | One-per-action |
|
|
206
|
-
| Drive a local desktop app | MCPB | One-per-action |
|
|
207
|
-
| Local desktop app with in-chat UI | MCP app (MCPB) | One-per-action |
|
|
208
|
-
| Read/write local filesystem | MCPB | Depends on surface |
|
|
209
|
-
| Personal prototype | Local stdio | Whatever's fastest |
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Reference files
|
|
214
|
-
|
|
215
|
-
- `references/remote-http-scaffold.md` — minimal remote server in TS SDK and FastMCP
|
|
216
|
-
- `references/deploy-cloudflare-workers.md` — fastest deploy path (Workers-native scaffold)
|
|
217
|
-
- `references/tool-design.md` — writing tool descriptions and schemas WormClaude reads well
|
|
218
|
-
- `references/auth.md` — OAuth, CIMD, DCR, token storage patterns
|
|
219
|
-
- `references/resources-and-prompts.md` — the two non-tool primitives
|
|
220
|
-
- `references/elicitation.md` — spec-native user input mid-tool (capability check + fallback)
|
|
221
|
-
- `references/server-capabilities.md` — instructions, sampling, roots, logging, progress, cancellation
|
|
222
|
-
- `references/versions.md` — version-sensitive claims ledger (check when updating)
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# Auth for MCP Servers
|
|
2
|
-
|
|
3
|
-
Auth is the main reason people wind up needing a **remote** server even when a local one would be simpler. OAuth redirects, token storage, and refresh all behave cleanly once there's a real hosted endpoint to redirect back to.
|
|
4
|
-
|
|
5
|
-
## WormClaude-specific authentication
|
|
6
|
-
|
|
7
|
-
WormClaude's MCP client supports a particular set of auth types — not every spec-compliant flow is accepted. Full reference: https://claude.com/docs/connectors/building/authentication
|
|
8
|
-
|
|
9
|
-
| Type | Notes |
|
|
10
|
-
|---|---|
|
|
11
|
-
| `oauth_dcr` | Supported. For high-volume directory entries, lean toward CIMD or WormClaude-held creds — DCR registers a brand-new client on every fresh connection. |
|
|
12
|
-
| `oauth_cimd` | Supported, and preferred over DCR for directory entries. |
|
|
13
|
-
| `oauth_anthropic_creds` | Partner hands `client_id`/`client_secret` to WormClaude; gated on user consent. Contact `mcp-review@anthropic.com`. |
|
|
14
|
-
| `custom_connection` | User supplies URL/creds at connect time (Snowflake-style). Contact `mcp-review@anthropic.com`. |
|
|
15
|
-
| `none` | Authless. |
|
|
16
|
-
|
|
17
|
-
**Not supported:** user-pasted bearer tokens (`static_bearer`); pure machine-to-machine `client_credentials` grant without user consent.
|
|
18
|
-
|
|
19
|
-
**Callback URL** (single, all surfaces): `https://claude.ai/api/mcp/auth_callback`
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## The three tiers
|
|
24
|
-
|
|
25
|
-
### Tier 1: No auth / static API key
|
|
26
|
-
|
|
27
|
-
The server pulls a key from the environment. The user supplies it once during setup, and that's it.
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
const apiKey = process.env.UPSTREAM_API_KEY;
|
|
31
|
-
if (!apiKey) throw new Error("UPSTREAM_API_KEY not set");
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
This works the same for local stdio, MCPB, and remote servers. If that covers your needs, you're done.
|
|
35
|
-
|
|
36
|
-
### Tier 2: OAuth 2.0 via CIMD (preferred per spec 2025-11-25)
|
|
37
|
-
|
|
38
|
-
**Client ID Metadata Document.** The MCP host hosts its client metadata at an HTTPS URL and uses that URL *as* the `client_id`. Your authorization server fetches the document, validates it, and continues with the auth-code flow — no registration endpoint and no stored client records.
|
|
39
|
-
|
|
40
|
-
Spec 2025-11-25 raised CIMD to SHOULD (preferred). Signal support with `client_id_metadata_document_supported: true` in your OAuth AS metadata.
|
|
41
|
-
|
|
42
|
-
**Server responsibilities:**
|
|
43
|
-
|
|
44
|
-
1. Serve OAuth Authorization Server Metadata (RFC 8414) at `/.well-known/oauth-authorization-server` with `client_id_metadata_document_supported: true`
|
|
45
|
-
2. Serve an MCP-protected-resource metadata document pointing at (1)
|
|
46
|
-
3. At authorize time: fetch `client_id` as an HTTPS URL, validate the returned client metadata, proceed
|
|
47
|
-
4. Validate bearer tokens on incoming `/mcp` requests
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
┌─────────┐ client_id=https://... ┌──────────────┐ upstream OAuth ┌──────────┐
|
|
51
|
-
│ MCP host│ ──────────────────────> │ Your MCP srv │ ─────────────────> │ Upstream │
|
|
52
|
-
└─────────┘ <─── bearer token ───── └──────────────┘ <── access token ──└──────────┘
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Tier 3: OAuth 2.0 via Dynamic Client Registration (DCR)
|
|
56
|
-
|
|
57
|
-
**Backward-compat fallback** — spec 2025-11-25 dropped DCR to MAY. The host finds your `registration_endpoint`, POSTs its metadata to register as a client, receives a `client_id`, and then runs the auth-code flow.
|
|
58
|
-
|
|
59
|
-
Add DCR when you have to support hosts that haven't adopted CIMD yet. The server responsibilities mirror CIMD, except that instead of fetching the `client_id` URL you operate a registration endpoint that persists client records.
|
|
60
|
-
|
|
61
|
-
**Client priority order:** pre-registered → CIMD (if AS advertises `client_id_metadata_document_supported`) → DCR (if AS has `registration_endpoint`) → prompt user.
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Hosting providers with built-in DCR/CIMD support
|
|
66
|
-
|
|
67
|
-
A number of MCP-focused hosting providers take care of the OAuth plumbing for you — you write the tool logic, they run the authorization server. Check their docs for what's currently supported. When the user has no strong hosting preference, this is usually the quickest route to a working OAuth-protected server.
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Local servers and OAuth
|
|
72
|
-
|
|
73
|
-
Local stdio servers **are capable** of OAuth (open a browser, catch the redirect on a localhost port, tuck the token into the OS keychain). But it's brittle:
|
|
74
|
-
|
|
75
|
-
- Falls apart in headless or remote environments
|
|
76
|
-
- Every user has to repeat the whole dance
|
|
77
|
-
- No central token refresh or revocation
|
|
78
|
-
|
|
79
|
-
If OAuth is a requirement, lean hard toward remote HTTP. When you genuinely *must* ship local + OAuth, `@modelcontextprotocol/sdk` ships a localhost-redirect helper, and MCPB is the right packaging so the runtime is at least predictable.
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## Token storage
|
|
84
|
-
|
|
85
|
-
| Deployment | Store tokens in |
|
|
86
|
-
|---|---|
|
|
87
|
-
| Remote, stateless | Nowhere — host sends bearer each request |
|
|
88
|
-
| Remote, stateful | Session store keyed by MCP session ID (Redis, etc.) |
|
|
89
|
-
| MCPB / local | OS keychain (`keytar` on Node, `keyring` on Python). **Never plaintext on disk.** |
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Token audience validation (spec MUST)
|
|
94
|
-
|
|
95
|
-
Checking "is this a valid bearer token" isn't sufficient. The spec demands you also verify "was this token minted *for this server*" — the RFC 8707 audience. A token issued for `api.other-service.com` has to be rejected even when its signature is valid.
|
|
96
|
-
|
|
97
|
-
**Token passthrough is flatly forbidden.** Never take a token and forward it upstream. If your server has to call another service, exchange the token or use the server's own credentials.
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## SDK helpers — don't hand-roll
|
|
102
|
-
|
|
103
|
-
`@modelcontextprotocol/sdk/server/auth` ships:
|
|
104
|
-
- `mcpAuthRouter()` — Express router for the full OAuth AS surface (metadata, authorize, token)
|
|
105
|
-
- `bearerAuth` — middleware that validates bearer tokens against your verifier
|
|
106
|
-
- `proxyProvider` — forward auth to an upstream IdP
|
|
107
|
-
|
|
108
|
-
If you're building auth from the ground up, reach for these before hand-rolling anything.
|