@frontmcp/skills 1.0.0-beta.13 → 1.0.0-beta.14
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/catalog/TEMPLATE.md +55 -0
- package/catalog/frontmcp-config/SKILL.md +2 -2
- package/catalog/frontmcp-config/examples/configure-auth/multi-app-auth.md +87 -0
- package/catalog/frontmcp-config/examples/configure-auth/public-mode-setup.md +63 -0
- package/catalog/frontmcp-config/examples/configure-auth/remote-oauth-with-vault.md +76 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +77 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +73 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/transparent-jwt-validation.md +64 -0
- package/catalog/frontmcp-config/examples/configure-elicitation/basic-confirmation-gate.md +83 -0
- package/catalog/frontmcp-config/examples/configure-elicitation/distributed-elicitation-redis.md +87 -0
- package/catalog/frontmcp-config/examples/configure-http/cors-restricted-origins.md +52 -0
- package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +72 -0
- package/catalog/frontmcp-config/examples/configure-http/unix-socket-local.md +64 -0
- package/catalog/frontmcp-config/examples/configure-session/multi-server-key-prefix.md +68 -0
- package/catalog/frontmcp-config/examples/configure-session/redis-session-store.md +52 -0
- package/catalog/frontmcp-config/examples/configure-session/vercel-kv-session.md +52 -0
- package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +94 -0
- package/catalog/frontmcp-config/examples/configure-throttle/per-tool-rate-limit.md +92 -0
- package/catalog/frontmcp-config/examples/configure-throttle/server-level-rate-limit.md +83 -0
- package/catalog/frontmcp-config/examples/configure-throttle-guard-config/full-guard-config.md +99 -0
- package/catalog/frontmcp-config/examples/configure-throttle-guard-config/minimal-guard-config.md +55 -0
- package/catalog/frontmcp-config/examples/configure-transport/custom-protocol-flags.md +74 -0
- package/catalog/frontmcp-config/examples/configure-transport/distributed-sessions-redis.md +86 -0
- package/catalog/frontmcp-config/examples/configure-transport/stateless-serverless.md +69 -0
- package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/legacy-preset-nodejs.md +65 -0
- package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/stateless-api-serverless.md +69 -0
- package/catalog/frontmcp-config/references/configure-auth-modes.md +10 -0
- package/catalog/frontmcp-config/references/configure-auth.md +10 -0
- package/catalog/frontmcp-config/references/configure-elicitation.md +9 -0
- package/catalog/frontmcp-config/references/configure-http.md +10 -0
- package/catalog/frontmcp-config/references/configure-session.md +10 -0
- package/catalog/frontmcp-config/references/configure-throttle-guard-config.md +9 -0
- package/catalog/frontmcp-config/references/configure-throttle.md +10 -0
- package/catalog/frontmcp-config/references/configure-transport-protocol-presets.md +9 -0
- package/catalog/frontmcp-config/references/configure-transport.md +10 -0
- package/catalog/frontmcp-config/references/setup-redis.md +5 -0
- package/catalog/frontmcp-config/references/setup-sqlite.md +5 -0
- package/catalog/frontmcp-deployment/SKILL.md +2 -2
- package/catalog/frontmcp-deployment/examples/build-for-browser/browser-build-with-custom-entry.md +43 -0
- package/catalog/frontmcp-deployment/examples/build-for-browser/browser-crypto-and-storage.md +85 -0
- package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +61 -0
- package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +66 -0
- package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +76 -0
- package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +78 -0
- package/catalog/frontmcp-deployment/examples/build-for-sdk/create-flat-config.md +85 -0
- package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +104 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +82 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +97 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +92 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/cdk-deployment.md +92 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +113 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/sam-template-basic.md +100 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-node/docker-compose-with-redis.md +101 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-node/pm2-with-nginx.md +79 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-node/resource-limits.md +92 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/basic-multistage-dockerfile.md +63 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/secure-nonroot-dockerfile.md +89 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +69 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +82 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +90 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +49 -0
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +92 -0
- package/catalog/frontmcp-deployment/references/build-for-browser.md +10 -0
- package/catalog/frontmcp-deployment/references/build-for-cli.md +9 -0
- package/catalog/frontmcp-deployment/references/build-for-sdk.md +10 -0
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +10 -0
- package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +10 -0
- package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +9 -0
- package/catalog/frontmcp-deployment/references/deploy-to-node.md +10 -0
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +9 -0
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +10 -0
- package/catalog/frontmcp-development/SKILL.md +2 -2
- package/catalog/frontmcp-development/examples/create-adapter/basic-api-adapter.md +92 -0
- package/catalog/frontmcp-development/examples/create-adapter/namespaced-adapter.md +124 -0
- package/catalog/frontmcp-development/examples/create-agent/basic-agent-with-tools.md +121 -0
- package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +95 -0
- package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +111 -0
- package/catalog/frontmcp-development/examples/create-agent-llm-config/anthropic-config.md +81 -0
- package/catalog/frontmcp-development/examples/create-agent-llm-config/openai-config.md +80 -0
- package/catalog/frontmcp-development/examples/create-job/basic-report-job.md +87 -0
- package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +117 -0
- package/catalog/frontmcp-development/examples/create-job/job-with-retry.md +88 -0
- package/catalog/frontmcp-development/examples/create-plugin/basic-plugin-with-provider.md +69 -0
- package/catalog/frontmcp-development/examples/create-plugin/configurable-dynamic-plugin.md +178 -0
- package/catalog/frontmcp-development/examples/create-plugin/plugin-with-context-extension.md +107 -0
- package/catalog/frontmcp-development/examples/create-plugin-hooks/basic-logging-plugin.md +69 -0
- package/catalog/frontmcp-development/examples/create-plugin-hooks/caching-with-around.md +80 -0
- package/catalog/frontmcp-development/examples/create-plugin-hooks/tool-level-hooks-and-stage-replacement.md +100 -0
- package/catalog/frontmcp-development/examples/create-prompt/basic-prompt.md +72 -0
- package/catalog/frontmcp-development/examples/create-prompt/dynamic-rag-prompt.md +92 -0
- package/catalog/frontmcp-development/examples/create-prompt/multi-turn-debug-session.md +86 -0
- package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +113 -0
- package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +107 -0
- package/catalog/frontmcp-development/examples/create-resource/basic-static-resource.md +72 -0
- package/catalog/frontmcp-development/examples/create-resource/binary-and-multi-content.md +111 -0
- package/catalog/frontmcp-development/examples/create-resource/parameterized-template.md +84 -0
- package/catalog/frontmcp-development/examples/create-skill/basic-inline-skill.md +96 -0
- package/catalog/frontmcp-development/examples/create-skill/directory-based-skill.md +115 -0
- package/catalog/frontmcp-development/examples/create-skill/parameterized-skill.md +96 -0
- package/catalog/frontmcp-development/examples/create-skill-with-tools/basic-tool-orchestration.md +76 -0
- package/catalog/frontmcp-development/examples/create-skill-with-tools/directory-skill-with-tools.md +149 -0
- package/catalog/frontmcp-development/examples/create-skill-with-tools/incident-response-skill.md +92 -0
- package/catalog/frontmcp-development/examples/create-tool/basic-class-tool.md +62 -0
- package/catalog/frontmcp-development/examples/create-tool/tool-with-di-and-errors.md +84 -0
- package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +93 -0
- package/catalog/frontmcp-development/examples/create-tool-annotations/destructive-delete-tool.md +94 -0
- package/catalog/frontmcp-development/examples/create-tool-annotations/readonly-query-tool.md +60 -0
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/primitive-and-media-outputs.md +104 -0
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-raw-shape-output.md +63 -0
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-schema-advanced-output.md +103 -0
- package/catalog/frontmcp-development/examples/create-workflow/basic-deploy-pipeline.md +91 -0
- package/catalog/frontmcp-development/examples/create-workflow/parallel-validation-pipeline.md +90 -0
- package/catalog/frontmcp-development/examples/create-workflow/webhook-triggered-workflow.md +136 -0
- package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +145 -0
- package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +124 -0
- package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +149 -0
- package/catalog/frontmcp-development/examples/official-adapters/authenticated-adapter-with-polling.md +84 -0
- package/catalog/frontmcp-development/examples/official-adapters/basic-openapi-adapter.md +54 -0
- package/catalog/frontmcp-development/examples/official-adapters/multi-api-hub-with-inline-spec.md +130 -0
- package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +117 -0
- package/catalog/frontmcp-development/examples/official-plugins/production-multi-plugin-setup.md +147 -0
- package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +104 -0
- package/catalog/frontmcp-development/references/create-adapter.md +9 -0
- package/catalog/frontmcp-development/references/create-agent-llm-config.md +9 -0
- package/catalog/frontmcp-development/references/create-agent.md +10 -0
- package/catalog/frontmcp-development/references/create-job.md +10 -0
- package/catalog/frontmcp-development/references/create-plugin-hooks.md +10 -0
- package/catalog/frontmcp-development/references/create-plugin.md +10 -0
- package/catalog/frontmcp-development/references/create-prompt.md +10 -0
- package/catalog/frontmcp-development/references/create-provider.md +9 -0
- package/catalog/frontmcp-development/references/create-resource.md +52 -15
- package/catalog/frontmcp-development/references/create-skill-with-tools.md +10 -0
- package/catalog/frontmcp-development/references/create-skill.md +10 -0
- package/catalog/frontmcp-development/references/create-tool-annotations.md +9 -0
- package/catalog/frontmcp-development/references/create-tool-output-schema-types.md +10 -0
- package/catalog/frontmcp-development/references/create-tool.md +10 -0
- package/catalog/frontmcp-development/references/create-workflow.md +10 -0
- package/catalog/frontmcp-development/references/decorators-guide.md +10 -0
- package/catalog/frontmcp-development/references/official-adapters.md +10 -0
- package/catalog/frontmcp-development/references/official-plugins.md +10 -0
- package/catalog/frontmcp-extensibility/SKILL.md +1 -1
- package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +175 -0
- package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +138 -0
- package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +103 -0
- package/catalog/frontmcp-extensibility/references/vectoriadb.md +10 -0
- package/catalog/frontmcp-guides/SKILL.md +2 -2
- package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +160 -0
- package/catalog/frontmcp-guides/examples/example-knowledge-base/multi-app-composition.md +92 -0
- package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +135 -0
- package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +135 -0
- package/catalog/frontmcp-guides/examples/example-task-manager/authenticated-e2e-tests.md +148 -0
- package/catalog/frontmcp-guides/examples/example-task-manager/redis-provider-with-di.md +129 -0
- package/catalog/frontmcp-guides/examples/example-weather-api/server-and-app-setup.md +75 -0
- package/catalog/frontmcp-guides/examples/example-weather-api/unit-and-e2e-tests.md +142 -0
- package/catalog/frontmcp-guides/examples/example-weather-api/weather-tool-with-schemas.md +74 -0
- package/catalog/frontmcp-guides/references/example-knowledge-base.md +10 -0
- package/catalog/frontmcp-guides/references/example-task-manager.md +10 -0
- package/catalog/frontmcp-guides/references/example-weather-api.md +10 -0
- package/catalog/frontmcp-production-readiness/SKILL.md +2 -2
- package/catalog/frontmcp-production-readiness/examples/common-checklist/caching-and-performance.md +102 -0
- package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +104 -0
- package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +95 -0
- package/catalog/frontmcp-production-readiness/examples/production-browser/browser-bundle-config.md +93 -0
- package/catalog/frontmcp-production-readiness/examples/production-browser/cross-platform-crypto.md +116 -0
- package/catalog/frontmcp-production-readiness/examples/production-browser/security-and-performance.md +128 -0
- package/catalog/frontmcp-production-readiness/examples/production-cli-binary/binary-build-config.md +109 -0
- package/catalog/frontmcp-production-readiness/examples/production-cli-binary/stdio-transport-error-handling.md +132 -0
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/daemon-socket-config.md +82 -0
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/graceful-shutdown-cleanup.md +107 -0
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/security-and-permissions.md +119 -0
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +124 -0
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/workers-runtime-constraints.md +103 -0
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/wrangler-config.md +89 -0
- package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +122 -0
- package/catalog/frontmcp-production-readiness/examples/production-lambda/sam-template.md +107 -0
- package/catalog/frontmcp-production-readiness/examples/production-lambda/scaling-and-monitoring.md +138 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-sdk/basic-sdk-lifecycle.md +85 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-sdk/multi-instance-cleanup.md +110 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-sdk/package-json-config.md +107 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-server/docker-multi-stage.md +103 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-server/graceful-shutdown.md +87 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-server/redis-session-scaling.md +97 -0
- package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +104 -0
- package/catalog/frontmcp-production-readiness/examples/production-vercel/stateless-serverless-design.md +91 -0
- package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +78 -0
- package/catalog/frontmcp-production-readiness/references/common-checklist.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-browser.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-binary.md +9 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-lambda.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-node-server.md +10 -0
- package/catalog/frontmcp-production-readiness/references/production-vercel.md +10 -0
- package/catalog/frontmcp-setup/examples/frontmcp-skills-usage/bundle-presets-scaffolding.md +61 -0
- package/catalog/frontmcp-setup/examples/frontmcp-skills-usage/install-and-search-skills.md +83 -0
- package/catalog/frontmcp-setup/examples/multi-app-composition/local-apps-with-shared-tools.md +87 -0
- package/catalog/frontmcp-setup/examples/multi-app-composition/per-app-auth-and-isolation.md +88 -0
- package/catalog/frontmcp-setup/examples/multi-app-composition/remote-and-esm-apps.md +81 -0
- package/catalog/frontmcp-setup/examples/nx-workflow/build-test-affected.md +77 -0
- package/catalog/frontmcp-setup/examples/nx-workflow/multi-server-deployment.md +93 -0
- package/catalog/frontmcp-setup/examples/nx-workflow/scaffold-and-generate.md +62 -0
- package/catalog/frontmcp-setup/examples/project-structure-nx/nx-generator-scaffolding.md +73 -0
- package/catalog/frontmcp-setup/examples/project-structure-nx/nx-workspace-with-apps.md +85 -0
- package/catalog/frontmcp-setup/examples/project-structure-nx/shared-library-usage.md +89 -0
- package/catalog/frontmcp-setup/examples/project-structure-standalone/dev-workflow-commands.md +64 -0
- package/catalog/frontmcp-setup/examples/project-structure-standalone/feature-folder-organization.md +111 -0
- package/catalog/frontmcp-setup/examples/project-structure-standalone/minimal-standalone-layout.md +73 -0
- package/catalog/frontmcp-setup/examples/readme-guide/node-server-readme.md +89 -0
- package/catalog/frontmcp-setup/examples/readme-guide/vercel-deployment-readme.md +90 -0
- package/catalog/frontmcp-setup/examples/setup-project/basic-node-server.md +99 -0
- package/catalog/frontmcp-setup/examples/setup-project/cli-scaffold-with-flags.md +77 -0
- package/catalog/frontmcp-setup/examples/setup-project/vercel-serverless-server.md +89 -0
- package/catalog/frontmcp-setup/examples/setup-redis/docker-redis-local-dev.md +88 -0
- package/catalog/frontmcp-setup/examples/setup-redis/hybrid-vercel-kv-with-pubsub.md +78 -0
- package/catalog/frontmcp-setup/examples/setup-redis/vercel-kv-serverless.md +78 -0
- package/catalog/frontmcp-setup/examples/setup-sqlite/basic-sqlite-setup.md +75 -0
- package/catalog/frontmcp-setup/examples/setup-sqlite/encrypted-sqlite-storage.md +55 -0
- package/catalog/frontmcp-setup/examples/setup-sqlite/unix-socket-daemon.md +70 -0
- package/catalog/frontmcp-setup/references/frontmcp-skills-usage.md +9 -0
- package/catalog/frontmcp-setup/references/multi-app-composition.md +10 -0
- package/catalog/frontmcp-setup/references/nx-workflow.md +10 -0
- package/catalog/frontmcp-setup/references/project-structure-nx.md +10 -0
- package/catalog/frontmcp-setup/references/project-structure-standalone.md +10 -0
- package/catalog/frontmcp-setup/references/readme-guide.md +9 -0
- package/catalog/frontmcp-setup/references/setup-project.md +10 -0
- package/catalog/frontmcp-setup/references/setup-redis.md +10 -0
- package/catalog/frontmcp-setup/references/setup-sqlite.md +10 -0
- package/catalog/frontmcp-testing/examples/setup-testing/fixture-based-e2e-test.md +70 -0
- package/catalog/frontmcp-testing/examples/setup-testing/jest-config-with-coverage.md +59 -0
- package/catalog/frontmcp-testing/examples/setup-testing/unit-test-tool-resource-prompt.md +115 -0
- package/catalog/frontmcp-testing/examples/test-auth/oauth-flow-test.md +78 -0
- package/catalog/frontmcp-testing/examples/test-auth/role-based-access-test.md +88 -0
- package/catalog/frontmcp-testing/examples/test-auth/token-factory-test.md +71 -0
- package/catalog/frontmcp-testing/examples/test-browser-build/browser-bundle-validation.md +58 -0
- package/catalog/frontmcp-testing/examples/test-browser-build/playwright-browser-test.md +69 -0
- package/catalog/frontmcp-testing/examples/test-cli-binary/binary-startup-test.md +77 -0
- package/catalog/frontmcp-testing/examples/test-cli-binary/js-bundle-import-test.md +56 -0
- package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +74 -0
- package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +79 -0
- package/catalog/frontmcp-testing/examples/test-e2e-handler/basic-e2e-test.md +67 -0
- package/catalog/frontmcp-testing/examples/test-e2e-handler/manual-client-with-transport.md +72 -0
- package/catalog/frontmcp-testing/examples/test-e2e-handler/tool-call-and-error-e2e.md +73 -0
- package/catalog/frontmcp-testing/examples/test-tool-unit/basic-tool-test.md +69 -0
- package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +82 -0
- package/catalog/frontmcp-testing/examples/test-tool-unit/tool-error-handling-test.md +92 -0
- package/catalog/frontmcp-testing/references/setup-testing.md +10 -0
- package/catalog/frontmcp-testing/references/test-auth.md +10 -0
- package/catalog/frontmcp-testing/references/test-browser-build.md +9 -0
- package/catalog/frontmcp-testing/references/test-cli-binary.md +9 -0
- package/catalog/frontmcp-testing/references/test-direct-client.md +9 -0
- package/catalog/frontmcp-testing/references/test-e2e-handler.md +10 -0
- package/catalog/frontmcp-testing/references/test-tool-unit.md +10 -0
- package/catalog/skills-manifest.json +2383 -67
- package/package.json +1 -1
- package/src/manifest.d.ts +23 -0
- package/src/manifest.js +3 -1
- package/src/manifest.js.map +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fixture-based-e2e-test
|
|
3
|
+
reference: setup-testing
|
|
4
|
+
level: advanced
|
|
5
|
+
description: 'Write E2E tests using the fixture API from `@frontmcp/testing` that manages server lifecycle automatically and uses MCP-specific custom matchers.'
|
|
6
|
+
tags: [testing, jest, e2e, setup, fixture, based]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using `test.use()` to configure server path and port for automatic lifecycle management'
|
|
9
|
+
- 'Importing `test` and `expect` from `@frontmcp/testing` (not from Jest) to access MCP-specific matchers'
|
|
10
|
+
- 'Custom matchers: `toContainTool()`, `toBeSuccessful()`, `toHaveTextContent()` for MCP assertions'
|
|
11
|
+
- 'Testing all three MCP primitives (tools, resources, prompts) in a single E2E suite'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Fixture-Based E2E Test with Custom Matchers
|
|
15
|
+
|
|
16
|
+
Write E2E tests using the fixture API from `@frontmcp/testing` that manages server lifecycle automatically and uses MCP-specific custom matchers.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// my-server.e2e.spec.ts
|
|
22
|
+
import { test, expect } from '@frontmcp/testing';
|
|
23
|
+
|
|
24
|
+
test.use({
|
|
25
|
+
server: './src/main.ts',
|
|
26
|
+
port: 3003,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('server exposes expected tools', async ({ mcp }) => {
|
|
30
|
+
const tools = await mcp.tools.list();
|
|
31
|
+
expect(tools).toContainTool('create_record');
|
|
32
|
+
expect(tools).toContainTool('delete_record');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('create_record tool returns success', async ({ mcp }) => {
|
|
36
|
+
const result = await mcp.tools.call('create_record', {
|
|
37
|
+
name: 'Test Record',
|
|
38
|
+
type: 'example',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(result).toBeSuccessful();
|
|
42
|
+
expect(result).toHaveTextContent('created');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('reading a resource returns valid content', async ({ mcp }) => {
|
|
46
|
+
const result = await mcp.resources.read('config://server-info');
|
|
47
|
+
|
|
48
|
+
expect(result.contents).toHaveLength(1);
|
|
49
|
+
expect(result.contents[0]).toHaveProperty('mimeType', 'application/json');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('prompts return well-formed messages', async ({ mcp }) => {
|
|
53
|
+
const result = await mcp.prompts.get('summarize', { topic: 'testing' });
|
|
54
|
+
|
|
55
|
+
expect(result.messages).toBeDefined();
|
|
56
|
+
expect(result.messages.length).toBeGreaterThan(0);
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## What This Demonstrates
|
|
61
|
+
|
|
62
|
+
- Using `test.use()` to configure server path and port for automatic lifecycle management
|
|
63
|
+
- Importing `test` and `expect` from `@frontmcp/testing` (not from Jest) to access MCP-specific matchers
|
|
64
|
+
- Custom matchers: `toContainTool()`, `toBeSuccessful()`, `toHaveTextContent()` for MCP assertions
|
|
65
|
+
- Testing all three MCP primitives (tools, resources, prompts) in a single E2E suite
|
|
66
|
+
|
|
67
|
+
## Related
|
|
68
|
+
|
|
69
|
+
- See `setup-testing` for the full testing setup reference
|
|
70
|
+
- See `test-e2e-handler` for manual `McpTestClient` E2E patterns
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jest-config-with-coverage
|
|
3
|
+
reference: setup-testing
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Set up a Jest configuration file that enforces 95%+ coverage across all metrics for a FrontMCP library.'
|
|
6
|
+
tags: [testing, jest, setup, config, coverage]
|
|
7
|
+
features:
|
|
8
|
+
- 'How to configure Jest with `ts-jest` for TypeScript test files'
|
|
9
|
+
- 'Setting 95%+ coverage thresholds required by FrontMCP standards'
|
|
10
|
+
- 'Proper `tsconfig.spec.json` that extends the base config and includes `.spec.ts` files'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Jest Configuration with Coverage Thresholds
|
|
14
|
+
|
|
15
|
+
Set up a Jest configuration file that enforces 95%+ coverage across all metrics for a FrontMCP library.
|
|
16
|
+
|
|
17
|
+
## Code
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// jest.config.ts
|
|
21
|
+
export default {
|
|
22
|
+
displayName: 'my-lib',
|
|
23
|
+
preset: '../../jest.preset.js',
|
|
24
|
+
transform: {
|
|
25
|
+
'^.+\\.tsx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
|
26
|
+
},
|
|
27
|
+
coverageThreshold: {
|
|
28
|
+
global: {
|
|
29
|
+
statements: 95,
|
|
30
|
+
branches: 95,
|
|
31
|
+
functions: 95,
|
|
32
|
+
lines: 95,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
// tsconfig.spec.json
|
|
40
|
+
{
|
|
41
|
+
"extends": "./tsconfig.json",
|
|
42
|
+
"compilerOptions": {
|
|
43
|
+
"outDir": "../../dist/out-tsc",
|
|
44
|
+
"module": "commonjs",
|
|
45
|
+
"types": ["jest", "node"]
|
|
46
|
+
},
|
|
47
|
+
"include": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.spec.tsx"]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## What This Demonstrates
|
|
52
|
+
|
|
53
|
+
- How to configure Jest with `ts-jest` for TypeScript test files
|
|
54
|
+
- Setting 95%+ coverage thresholds required by FrontMCP standards
|
|
55
|
+
- Proper `tsconfig.spec.json` that extends the base config and includes `.spec.ts` files
|
|
56
|
+
|
|
57
|
+
## Related
|
|
58
|
+
|
|
59
|
+
- See `setup-testing` for the full testing setup reference
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: unit-test-tool-resource-prompt
|
|
3
|
+
reference: setup-testing
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: 'Write unit tests for the three core MCP primitives, verifying that outputs match the expected MCP response shapes.'
|
|
6
|
+
tags: [testing, jest, unit-test, setup, unit, tool]
|
|
7
|
+
features:
|
|
8
|
+
- 'Testing tool `execute()` with a mock context object assigned via `Object.assign`'
|
|
9
|
+
- 'Verifying resource `read()` output matches the MCP `ReadResourceResult` shape'
|
|
10
|
+
- 'Verifying prompt `execute()` output matches the MCP `GetPromptResult` shape'
|
|
11
|
+
- 'Using Jest matchers like `expect.stringContaining` and `expect.objectContaining` for flexible assertions'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Unit Testing Tools, Resources, and Prompts
|
|
15
|
+
|
|
16
|
+
Write unit tests for the three core MCP primitives, verifying that outputs match the expected MCP response shapes.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/tools/__tests__/my-tool.spec.ts
|
|
22
|
+
import { MyTool } from '../my-tool';
|
|
23
|
+
|
|
24
|
+
describe('MyTool', () => {
|
|
25
|
+
let tool: MyTool;
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
tool = new MyTool();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should return formatted result for valid input', async () => {
|
|
32
|
+
const mockContext = {
|
|
33
|
+
scope: {
|
|
34
|
+
get: jest.fn(),
|
|
35
|
+
tryGet: jest.fn(),
|
|
36
|
+
},
|
|
37
|
+
fail: jest.fn(),
|
|
38
|
+
mark: jest.fn(),
|
|
39
|
+
fetch: jest.fn(),
|
|
40
|
+
};
|
|
41
|
+
Object.assign(tool, mockContext);
|
|
42
|
+
|
|
43
|
+
const result = await tool.execute({ query: 'test input' });
|
|
44
|
+
|
|
45
|
+
expect(result).toEqual({
|
|
46
|
+
content: [{ type: 'text', text: expect.stringContaining('test input') }],
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should throw for invalid input', async () => {
|
|
51
|
+
const mockContext = {
|
|
52
|
+
scope: { get: jest.fn(), tryGet: jest.fn() },
|
|
53
|
+
fail: jest.fn(),
|
|
54
|
+
};
|
|
55
|
+
Object.assign(tool, mockContext);
|
|
56
|
+
|
|
57
|
+
await expect(tool.execute({ query: '' })).rejects.toThrow();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// src/resources/__tests__/my-resource.spec.ts
|
|
64
|
+
import { MyResource } from '../my-resource';
|
|
65
|
+
|
|
66
|
+
describe('MyResource', () => {
|
|
67
|
+
it('should return resource contents matching ReadResourceResult', async () => {
|
|
68
|
+
const resource = new MyResource();
|
|
69
|
+
const result = await resource.read({ id: '123' });
|
|
70
|
+
|
|
71
|
+
expect(result).toEqual({
|
|
72
|
+
contents: [
|
|
73
|
+
{
|
|
74
|
+
uri: expect.stringMatching(/^resource:\/\//),
|
|
75
|
+
mimeType: 'application/json',
|
|
76
|
+
text: expect.any(String),
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// src/prompts/__tests__/my-prompt.spec.ts
|
|
86
|
+
import { MyPrompt } from '../my-prompt';
|
|
87
|
+
|
|
88
|
+
describe('MyPrompt', () => {
|
|
89
|
+
it('should return a valid GetPromptResult', async () => {
|
|
90
|
+
const prompt = new MyPrompt();
|
|
91
|
+
const result = await prompt.execute({ topic: 'testing' });
|
|
92
|
+
|
|
93
|
+
expect(result).toEqual({
|
|
94
|
+
messages: expect.arrayContaining([
|
|
95
|
+
expect.objectContaining({
|
|
96
|
+
role: 'user',
|
|
97
|
+
content: expect.objectContaining({ type: 'text' }),
|
|
98
|
+
}),
|
|
99
|
+
]),
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## What This Demonstrates
|
|
106
|
+
|
|
107
|
+
- Testing tool `execute()` with a mock context object assigned via `Object.assign`
|
|
108
|
+
- Verifying resource `read()` output matches the MCP `ReadResourceResult` shape
|
|
109
|
+
- Verifying prompt `execute()` output matches the MCP `GetPromptResult` shape
|
|
110
|
+
- Using Jest matchers like `expect.stringContaining` and `expect.objectContaining` for flexible assertions
|
|
111
|
+
|
|
112
|
+
## Related
|
|
113
|
+
|
|
114
|
+
- See `setup-testing` for the full testing setup reference
|
|
115
|
+
- See `test-tool-unit` for detailed tool unit testing patterns
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oauth-flow-test
|
|
3
|
+
reference: test-auth
|
|
4
|
+
level: advanced
|
|
5
|
+
description: 'Use `MockOAuthServer` to simulate an OAuth identity provider and test the authorization code flow.'
|
|
6
|
+
tags: [testing, oauth, auth, flow]
|
|
7
|
+
features:
|
|
8
|
+
- 'Setting up `MockOAuthServer` with a mock issuer URL and port'
|
|
9
|
+
- 'Starting an OAuth flow with `startFlow()` specifying client ID, redirect URI, and scopes'
|
|
10
|
+
- 'Verifying the authorization URL contains an authorization code'
|
|
11
|
+
- 'Testing concurrent OAuth flows with different client configurations'
|
|
12
|
+
- 'Proper cleanup with `mockOAuth.close()` in `afterAll`'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Testing OAuth Authorization Code Flow
|
|
16
|
+
|
|
17
|
+
Use `MockOAuthServer` to simulate an OAuth identity provider and test the authorization code flow.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// src/__tests__/oauth-flow.e2e.spec.ts
|
|
23
|
+
import { MockOAuthServer } from '@frontmcp/testing';
|
|
24
|
+
|
|
25
|
+
describe('OAuth Flow', () => {
|
|
26
|
+
let mockOAuth: MockOAuthServer;
|
|
27
|
+
|
|
28
|
+
beforeAll(async () => {
|
|
29
|
+
mockOAuth = await MockOAuthServer.create({
|
|
30
|
+
issuer: 'https://test-idp.example.com',
|
|
31
|
+
port: 9999,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterAll(async () => {
|
|
36
|
+
await mockOAuth.close();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should complete OAuth authorization code flow', async () => {
|
|
40
|
+
const { authorizationUrl } = await mockOAuth.startFlow({
|
|
41
|
+
clientId: 'test-client',
|
|
42
|
+
redirectUri: 'http://localhost:3001/callback',
|
|
43
|
+
scopes: ['openid', 'profile'],
|
|
44
|
+
});
|
|
45
|
+
expect(authorizationUrl).toContain('code=');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should support multiple concurrent flows', async () => {
|
|
49
|
+
const flow1 = await mockOAuth.startFlow({
|
|
50
|
+
clientId: 'client-a',
|
|
51
|
+
redirectUri: 'http://localhost:3001/callback',
|
|
52
|
+
scopes: ['openid'],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const flow2 = await mockOAuth.startFlow({
|
|
56
|
+
clientId: 'client-b',
|
|
57
|
+
redirectUri: 'http://localhost:3002/callback',
|
|
58
|
+
scopes: ['openid', 'email'],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(flow1.authorizationUrl).toContain('code=');
|
|
62
|
+
expect(flow2.authorizationUrl).toContain('code=');
|
|
63
|
+
expect(flow1.authorizationUrl).not.toBe(flow2.authorizationUrl);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## What This Demonstrates
|
|
69
|
+
|
|
70
|
+
- Setting up `MockOAuthServer` with a mock issuer URL and port
|
|
71
|
+
- Starting an OAuth flow with `startFlow()` specifying client ID, redirect URI, and scopes
|
|
72
|
+
- Verifying the authorization URL contains an authorization code
|
|
73
|
+
- Testing concurrent OAuth flows with different client configurations
|
|
74
|
+
- Proper cleanup with `mockOAuth.close()` in `afterAll`
|
|
75
|
+
|
|
76
|
+
## Related
|
|
77
|
+
|
|
78
|
+
- See `test-auth` for the full authentication testing reference
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: role-based-access-test
|
|
3
|
+
reference: test-auth
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: 'Verify that tools enforce role-based access by testing admin and user tokens against protected endpoints.'
|
|
6
|
+
tags: [testing, auth, role, based, access]
|
|
7
|
+
features:
|
|
8
|
+
- 'Creating tokens with different `roles` arrays to simulate admin and user access'
|
|
9
|
+
- 'Testing that admin-only tools accept admin tokens and reject user tokens'
|
|
10
|
+
- 'Verifying that user-level tools remain accessible to users with the correct role'
|
|
11
|
+
- 'Each test creates and closes its own client for proper isolation'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Testing Role-Based Access Control
|
|
15
|
+
|
|
16
|
+
Verify that tools enforce role-based access by testing admin and user tokens against protected endpoints.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/__tests__/rbac.e2e.spec.ts
|
|
22
|
+
import { McpTestClient, TestServer, TestTokenFactory } from '@frontmcp/testing';
|
|
23
|
+
import Server from '../src/main';
|
|
24
|
+
|
|
25
|
+
describe('Role-Based Access', () => {
|
|
26
|
+
let server: TestServer;
|
|
27
|
+
let tokenFactory: TestTokenFactory;
|
|
28
|
+
|
|
29
|
+
beforeAll(async () => {
|
|
30
|
+
server = await TestServer.create(Server);
|
|
31
|
+
tokenFactory = new TestTokenFactory({
|
|
32
|
+
issuer: 'https://test-idp.example.com',
|
|
33
|
+
audience: 'my-api',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(async () => {
|
|
38
|
+
await server.dispose();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should allow admin access to admin-only tool', async () => {
|
|
42
|
+
const adminToken = await tokenFactory.createToken({
|
|
43
|
+
sub: 'admin-1',
|
|
44
|
+
roles: ['admin'],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const client = await server.connect({ authToken: adminToken });
|
|
48
|
+
const result = await client.callTool('admin_only_tool', {});
|
|
49
|
+
expect(result).toBeSuccessful();
|
|
50
|
+
await client.close();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should deny user access to admin-only tool', async () => {
|
|
54
|
+
const userToken = await tokenFactory.createToken({
|
|
55
|
+
sub: 'user-1',
|
|
56
|
+
roles: ['user'],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const client = await server.connect({ authToken: userToken });
|
|
60
|
+
const result = await client.callTool('admin_only_tool', {});
|
|
61
|
+
expect(result.isError).toBe(true);
|
|
62
|
+
await client.close();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should allow user access to user-level tool', async () => {
|
|
66
|
+
const userToken = await tokenFactory.createToken({
|
|
67
|
+
sub: 'user-2',
|
|
68
|
+
roles: ['user'],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const client = await server.connect({ authToken: userToken });
|
|
72
|
+
const result = await client.callTool('user_tool', { data: 'hello' });
|
|
73
|
+
expect(result).toBeSuccessful();
|
|
74
|
+
await client.close();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## What This Demonstrates
|
|
80
|
+
|
|
81
|
+
- Creating tokens with different `roles` arrays to simulate admin and user access
|
|
82
|
+
- Testing that admin-only tools accept admin tokens and reject user tokens
|
|
83
|
+
- Verifying that user-level tools remain accessible to users with the correct role
|
|
84
|
+
- Each test creates and closes its own client for proper isolation
|
|
85
|
+
|
|
86
|
+
## Related
|
|
87
|
+
|
|
88
|
+
- See `test-auth` for the full authentication testing reference
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: token-factory-test
|
|
3
|
+
reference: test-auth
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Use `TestTokenFactory` to create tokens and verify authenticated and unauthenticated requests.'
|
|
6
|
+
tags: [testing, auth, token, factory]
|
|
7
|
+
features:
|
|
8
|
+
- 'Creating a `TestTokenFactory` with issuer and audience configuration'
|
|
9
|
+
- 'Generating test tokens with specific subjects and scopes via `createToken()`'
|
|
10
|
+
- 'Passing tokens to `server.connect({ authToken })` for authenticated client connections'
|
|
11
|
+
- 'Verifying that unauthenticated requests are rejected with `isError`'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Testing Authentication with TestTokenFactory
|
|
15
|
+
|
|
16
|
+
Use `TestTokenFactory` to create tokens and verify authenticated and unauthenticated requests.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/__tests__/auth.e2e.spec.ts
|
|
22
|
+
import { McpTestClient, TestServer, TestTokenFactory } from '@frontmcp/testing';
|
|
23
|
+
import Server from '../src/main';
|
|
24
|
+
|
|
25
|
+
describe('Authenticated Server', () => {
|
|
26
|
+
let server: TestServer;
|
|
27
|
+
let tokenFactory: TestTokenFactory;
|
|
28
|
+
|
|
29
|
+
beforeAll(async () => {
|
|
30
|
+
server = await TestServer.create(Server);
|
|
31
|
+
tokenFactory = new TestTokenFactory({
|
|
32
|
+
issuer: 'https://test-idp.example.com',
|
|
33
|
+
audience: 'my-api',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(async () => {
|
|
38
|
+
await server.dispose();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should reject unauthenticated requests', async () => {
|
|
42
|
+
const client = await server.connect();
|
|
43
|
+
const result = await client.callTool('protected_tool', {});
|
|
44
|
+
expect(result.isError).toBe(true);
|
|
45
|
+
await client.close();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should accept valid token', async () => {
|
|
49
|
+
const token = await tokenFactory.createToken({
|
|
50
|
+
sub: 'user-123',
|
|
51
|
+
scopes: ['read', 'write'],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const client = await server.connect({ authToken: token });
|
|
55
|
+
const result = await client.callTool('protected_tool', { data: 'test' });
|
|
56
|
+
expect(result).toBeSuccessful();
|
|
57
|
+
await client.close();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## What This Demonstrates
|
|
63
|
+
|
|
64
|
+
- Creating a `TestTokenFactory` with issuer and audience configuration
|
|
65
|
+
- Generating test tokens with specific subjects and scopes via `createToken()`
|
|
66
|
+
- Passing tokens to `server.connect({ authToken })` for authenticated client connections
|
|
67
|
+
- Verifying that unauthenticated requests are rejected with `isError`
|
|
68
|
+
|
|
69
|
+
## Related
|
|
70
|
+
|
|
71
|
+
- See `test-auth` for the full authentication testing reference
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser-bundle-validation
|
|
3
|
+
reference: test-browser-build
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Verify that the browser build produces a valid bundle without Node.js-only module references.'
|
|
6
|
+
tags: [testing, browser, node, bundle, validation]
|
|
7
|
+
features:
|
|
8
|
+
- 'Checking that the browser build output directory contains `.js` files'
|
|
9
|
+
- 'Scanning the bundle for Node.js-only `require()` calls that would break in browsers'
|
|
10
|
+
- 'Using dynamic `import()` to verify the bundle is loadable'
|
|
11
|
+
- 'Targeting the `dist/browser/` directory where `frontmcp build --target browser` places output'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Validating Browser Build Output
|
|
15
|
+
|
|
16
|
+
Verify that the browser build produces a valid bundle without Node.js-only module references.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/__tests__/browser-build.spec.ts
|
|
22
|
+
import * as fs from 'fs';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
|
|
25
|
+
const DIST_DIR = path.resolve(__dirname, '../dist/browser');
|
|
26
|
+
|
|
27
|
+
describe('Browser Build', () => {
|
|
28
|
+
it('should produce browser-compatible bundle', () => {
|
|
29
|
+
const files = fs.readdirSync(DIST_DIR);
|
|
30
|
+
expect(files.some((f) => f.endsWith('.js'))).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should not contain Node.js-only modules', () => {
|
|
34
|
+
const bundle = fs.readFileSync(path.join(DIST_DIR, 'index.js'), 'utf-8');
|
|
35
|
+
// These should be polyfilled or excluded
|
|
36
|
+
expect(bundle).not.toContain("require('fs')");
|
|
37
|
+
expect(bundle).not.toContain("require('child_process')");
|
|
38
|
+
expect(bundle).not.toContain("require('net')");
|
|
39
|
+
expect(bundle).not.toContain("require('cluster')");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should export expected functions', async () => {
|
|
43
|
+
const mod = await import(path.join(DIST_DIR, 'index.js'));
|
|
44
|
+
expect(mod).toBeDefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## What This Demonstrates
|
|
50
|
+
|
|
51
|
+
- Checking that the browser build output directory contains `.js` files
|
|
52
|
+
- Scanning the bundle for Node.js-only `require()` calls that would break in browsers
|
|
53
|
+
- Using dynamic `import()` to verify the bundle is loadable
|
|
54
|
+
- Targeting the `dist/browser/` directory where `frontmcp build --target browser` places output
|
|
55
|
+
|
|
56
|
+
## Related
|
|
57
|
+
|
|
58
|
+
- See `test-browser-build` for the full browser build testing reference
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-browser-test
|
|
3
|
+
reference: test-browser-build
|
|
4
|
+
level: advanced
|
|
5
|
+
description: 'Use Playwright to test a browser-based MCP client that loads and calls tools from an MCP server.'
|
|
6
|
+
tags: [testing, browser, playwright, e2e]
|
|
7
|
+
features:
|
|
8
|
+
- "Using Playwright's `test` and `expect` from `@playwright/test` for browser E2E testing"
|
|
9
|
+
- 'Waiting for DOM elements with `waitForSelector` before asserting tool list counts'
|
|
10
|
+
- 'Filling form inputs and clicking buttons to simulate tool calls in the browser'
|
|
11
|
+
- 'Asserting tool results via `textContent` on result elements'
|
|
12
|
+
- 'Using the `.pw.spec.ts` file suffix required by FrontMCP naming conventions'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Testing Browser MCP Client with Playwright
|
|
16
|
+
|
|
17
|
+
Use Playwright to test a browser-based MCP client that loads and calls tools from an MCP server.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// src/__tests__/browser-client.pw.spec.ts
|
|
23
|
+
import { test, expect } from '@playwright/test';
|
|
24
|
+
|
|
25
|
+
test('browser MCP client loads tools', async ({ page }) => {
|
|
26
|
+
await page.goto('http://localhost:3000');
|
|
27
|
+
|
|
28
|
+
// Wait for tools to load from MCP server
|
|
29
|
+
await page.waitForSelector('[data-testid="tool-list"]');
|
|
30
|
+
|
|
31
|
+
const tools = await page.locator('[data-testid="tool-item"]').count();
|
|
32
|
+
expect(tools).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('browser client can call a tool', async ({ page }) => {
|
|
36
|
+
await page.goto('http://localhost:3000');
|
|
37
|
+
|
|
38
|
+
await page.fill('[data-testid="input-a"]', '5');
|
|
39
|
+
await page.fill('[data-testid="input-b"]', '3');
|
|
40
|
+
await page.click('[data-testid="call-tool"]');
|
|
41
|
+
|
|
42
|
+
const result = await page.textContent('[data-testid="result"]');
|
|
43
|
+
expect(result).toContain('8');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('browser client shows error for invalid input', async ({ page }) => {
|
|
47
|
+
await page.goto('http://localhost:3000');
|
|
48
|
+
|
|
49
|
+
await page.fill('[data-testid="input-a"]', 'abc');
|
|
50
|
+
await page.fill('[data-testid="input-b"]', '3');
|
|
51
|
+
await page.click('[data-testid="call-tool"]');
|
|
52
|
+
|
|
53
|
+
const error = await page.textContent('[data-testid="error-message"]');
|
|
54
|
+
expect(error).toBeTruthy();
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## What This Demonstrates
|
|
59
|
+
|
|
60
|
+
- Using Playwright's `test` and `expect` from `@playwright/test` for browser E2E testing
|
|
61
|
+
- Waiting for DOM elements with `waitForSelector` before asserting tool list counts
|
|
62
|
+
- Filling form inputs and clicking buttons to simulate tool calls in the browser
|
|
63
|
+
- Asserting tool results via `textContent` on result elements
|
|
64
|
+
- Using the `.pw.spec.ts` file suffix required by FrontMCP naming conventions
|
|
65
|
+
|
|
66
|
+
## Related
|
|
67
|
+
|
|
68
|
+
- See `test-browser-build` for the full browser build testing reference
|
|
69
|
+
- See `test-e2e-handler` for server-side E2E testing patterns
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: binary-startup-test
|
|
3
|
+
reference: test-cli-binary
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Verify that a compiled CLI binary starts correctly and responds to health checks.'
|
|
6
|
+
tags: [testing, cli, binary, startup]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using `execSync` to test that `--help` flag exits with code 0 and prints usage info'
|
|
9
|
+
- 'Spawning the binary as a child process with `PORT=0` for dynamic port assignment'
|
|
10
|
+
- 'Waiting for the "listening" log message before sending requests'
|
|
11
|
+
- 'Testing the `/health` endpoint for server readiness'
|
|
12
|
+
- 'Cleaning up the child process with `child.kill()`'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Testing CLI Binary Startup and Health Check
|
|
16
|
+
|
|
17
|
+
Verify that a compiled CLI binary starts correctly and responds to health checks.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// src/__tests__/cli-binary.spec.ts
|
|
23
|
+
import { spawn, execSync } from 'child_process';
|
|
24
|
+
import * as path from 'path';
|
|
25
|
+
|
|
26
|
+
const BINARY = path.resolve(__dirname, '../dist/my-server');
|
|
27
|
+
|
|
28
|
+
describe('CLI Binary', () => {
|
|
29
|
+
it('should exit with code 0 on --help', () => {
|
|
30
|
+
const output = execSync(`${BINARY} --help`, { encoding: 'utf-8' });
|
|
31
|
+
expect(output).toContain('Usage');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should start and respond to health check', async () => {
|
|
35
|
+
const child = spawn(BINARY, [], {
|
|
36
|
+
env: { ...process.env, PORT: '0' },
|
|
37
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Wait for server to start and parse the actual port from stdout
|
|
41
|
+
const port = await new Promise<string>((resolve, reject) => {
|
|
42
|
+
const timeout = setTimeout(() => reject(new Error('Server did not start within 10s')), 10_000);
|
|
43
|
+
child.stdout.on('data', (data: Buffer) => {
|
|
44
|
+
const match = data.toString().match(/listening.*?:(\d+)/i);
|
|
45
|
+
if (match) {
|
|
46
|
+
clearTimeout(timeout);
|
|
47
|
+
resolve(match[1]);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
child.on('error', (err) => {
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
reject(err);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
// Test health endpoint on the dynamically assigned port
|
|
58
|
+
const res = await fetch(`http://localhost:${port}/health`);
|
|
59
|
+
expect(res.ok).toBe(true);
|
|
60
|
+
} finally {
|
|
61
|
+
child.kill();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## What This Demonstrates
|
|
68
|
+
|
|
69
|
+
- Using `execSync` to test that `--help` flag exits with code 0 and prints usage info
|
|
70
|
+
- Spawning the binary as a child process with `PORT=0` for dynamic port assignment
|
|
71
|
+
- Waiting for the "listening" log message before sending requests
|
|
72
|
+
- Testing the `/health` endpoint for server readiness
|
|
73
|
+
- Cleaning up the child process with `child.kill()`
|
|
74
|
+
|
|
75
|
+
## Related
|
|
76
|
+
|
|
77
|
+
- See `test-cli-binary` for the full CLI binary testing reference
|