@frontmcp/skills 1.0.0-beta.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/catalog/TEMPLATE.md +69 -0
- package/catalog/frontmcp-config/SKILL.md +38 -22
- 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 +15 -0
- package/catalog/frontmcp-config/references/configure-auth.md +15 -0
- package/catalog/frontmcp-config/references/configure-elicitation.md +14 -0
- package/catalog/frontmcp-config/references/configure-http.md +15 -0
- package/catalog/frontmcp-config/references/configure-session.md +15 -0
- package/catalog/frontmcp-config/references/configure-throttle-guard-config.md +14 -0
- package/catalog/frontmcp-config/references/configure-throttle.md +15 -0
- package/catalog/frontmcp-config/references/configure-transport-protocol-presets.md +14 -0
- package/catalog/frontmcp-config/references/configure-transport.md +15 -0
- package/catalog/frontmcp-config/references/setup-redis.md +10 -0
- package/catalog/frontmcp-config/references/setup-sqlite.md +10 -0
- package/catalog/frontmcp-deployment/SKILL.md +40 -12
- 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 +15 -0
- package/catalog/frontmcp-deployment/references/build-for-cli.md +65 -3
- package/catalog/frontmcp-deployment/references/build-for-sdk.md +15 -0
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +15 -0
- package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +18 -3
- package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +16 -2
- package/catalog/frontmcp-deployment/references/deploy-to-node.md +19 -4
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +14 -0
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +15 -0
- package/catalog/frontmcp-development/SKILL.md +25 -17
- 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 +14 -0
- package/catalog/frontmcp-development/references/create-agent-llm-config.md +14 -0
- package/catalog/frontmcp-development/references/create-agent.md +15 -0
- package/catalog/frontmcp-development/references/create-job.md +15 -0
- package/catalog/frontmcp-development/references/create-plugin-hooks.md +51 -0
- package/catalog/frontmcp-development/references/create-plugin.md +186 -11
- package/catalog/frontmcp-development/references/create-prompt.md +17 -0
- package/catalog/frontmcp-development/references/create-provider.md +14 -0
- package/catalog/frontmcp-development/references/create-resource.md +127 -0
- package/catalog/frontmcp-development/references/create-skill-with-tools.md +126 -7
- package/catalog/frontmcp-development/references/create-skill.md +57 -12
- package/catalog/frontmcp-development/references/create-tool-annotations.md +14 -0
- package/catalog/frontmcp-development/references/create-tool-output-schema-types.md +15 -0
- package/catalog/frontmcp-development/references/create-tool.md +205 -1
- package/catalog/frontmcp-development/references/create-workflow.md +15 -0
- package/catalog/frontmcp-development/references/decorators-guide.md +155 -78
- package/catalog/frontmcp-development/references/official-adapters.md +31 -16
- package/catalog/frontmcp-development/references/official-plugins.md +62 -28
- package/catalog/frontmcp-extensibility/SKILL.md +103 -0
- 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 +299 -0
- package/catalog/frontmcp-guides/SKILL.md +7 -4
- 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 +15 -0
- package/catalog/frontmcp-guides/references/example-task-manager.md +30 -21
- package/catalog/frontmcp-guides/references/example-weather-api.md +18 -6
- package/catalog/frontmcp-observability/SKILL.md +144 -0
- package/catalog/frontmcp-observability/examples/structured-logging/stdout-logging.md +71 -0
- package/catalog/frontmcp-observability/examples/structured-logging/winston-integration.md +70 -0
- package/catalog/frontmcp-observability/examples/telemetry-api/agent-nested-tracing.md +86 -0
- package/catalog/frontmcp-observability/examples/telemetry-api/plugin-telemetry.md +93 -0
- package/catalog/frontmcp-observability/examples/telemetry-api/tool-custom-spans.md +72 -0
- package/catalog/frontmcp-observability/examples/testing-observability/test-custom-spans.md +90 -0
- package/catalog/frontmcp-observability/examples/testing-observability/test-log-correlation.md +104 -0
- package/catalog/frontmcp-observability/examples/tracing-setup/basic-tracing.md +82 -0
- package/catalog/frontmcp-observability/examples/tracing-setup/production-tracing.md +73 -0
- package/catalog/frontmcp-observability/examples/vendor-integrations/coralogix-setup.md +74 -0
- package/catalog/frontmcp-observability/references/structured-logging.md +114 -0
- package/catalog/frontmcp-observability/references/telemetry-api.md +155 -0
- package/catalog/frontmcp-observability/references/testing-observability.md +169 -0
- package/catalog/frontmcp-observability/references/tracing-setup.md +146 -0
- package/catalog/frontmcp-observability/references/vendor-integrations.md +164 -0
- package/catalog/frontmcp-production-readiness/SKILL.md +99 -0
- 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/health-readiness-endpoints/basic-health-setup.md +81 -0
- package/catalog/frontmcp-production-readiness/examples/health-readiness-endpoints/custom-probes.md +136 -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 +175 -0
- package/catalog/frontmcp-production-readiness/references/health-readiness-endpoints.md +198 -0
- package/catalog/frontmcp-production-readiness/references/production-browser.md +56 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-binary.md +71 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +71 -0
- package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +62 -0
- package/catalog/frontmcp-production-readiness/references/production-lambda.md +63 -0
- package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +76 -0
- package/catalog/frontmcp-production-readiness/references/production-node-server.md +71 -0
- package/catalog/frontmcp-production-readiness/references/production-vercel.md +62 -0
- package/catalog/frontmcp-setup/SKILL.md +19 -14
- 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 +33 -9
- package/catalog/frontmcp-setup/references/multi-app-composition.md +15 -0
- package/catalog/frontmcp-setup/references/nx-workflow.md +15 -0
- package/catalog/frontmcp-setup/references/project-structure-nx.md +15 -0
- package/catalog/frontmcp-setup/references/project-structure-standalone.md +15 -0
- package/catalog/frontmcp-setup/references/readme-guide.md +235 -0
- package/catalog/frontmcp-setup/references/setup-project.md +16 -1
- package/catalog/frontmcp-setup/references/setup-redis.md +15 -0
- package/catalog/frontmcp-setup/references/setup-sqlite.md +15 -0
- package/catalog/frontmcp-testing/SKILL.md +41 -27
- 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 +17 -0
- package/catalog/frontmcp-testing/references/test-auth.md +15 -0
- package/catalog/frontmcp-testing/references/test-browser-build.md +14 -0
- package/catalog/frontmcp-testing/references/test-cli-binary.md +14 -0
- package/catalog/frontmcp-testing/references/test-direct-client.md +14 -0
- package/catalog/frontmcp-testing/references/test-e2e-handler.md +15 -0
- package/catalog/frontmcp-testing/references/test-tool-unit.md +15 -0
- package/catalog/skills-manifest.json +2849 -32
- package/package.json +2 -2
- package/src/index.d.ts +1 -1
- package/src/index.js.map +1 -1
- package/src/loader.js +0 -1
- package/src/loader.js.map +1 -1
- package/src/manifest.d.ts +36 -1
- package/src/manifest.js +6 -1
- package/src/manifest.js.map +1 -1
|
@@ -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
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: js-bundle-import-test
|
|
3
|
+
reference: test-cli-binary
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: 'Verify that the compiled JS bundle can be imported and exports the expected modules after a `frontmcp build` step.'
|
|
6
|
+
tags: [testing, cli, binary, js, bundle, import]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using dynamic `import()` to test that the built JS bundle is importable'
|
|
9
|
+
- 'Verifying the bundle has a default export (server class or factory)'
|
|
10
|
+
- 'Testing CommonJS `require()` compatibility to ensure the bundle works in CJS environments'
|
|
11
|
+
- 'Pointing to the `dist/` output directory where `frontmcp build` places artifacts'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Testing JS Bundle Importability
|
|
15
|
+
|
|
16
|
+
Verify that the compiled JS bundle can be imported and exports the expected modules after a `frontmcp build` step.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/__tests__/js-bundle.spec.ts
|
|
22
|
+
import * as path from 'path';
|
|
23
|
+
|
|
24
|
+
const DIST_DIR = path.resolve(__dirname, '../dist');
|
|
25
|
+
|
|
26
|
+
describe('JS Bundle', () => {
|
|
27
|
+
it('should be importable as a CJS module', async () => {
|
|
28
|
+
const mod = await import(path.join(DIST_DIR, 'my-server.cjs.js'));
|
|
29
|
+
expect(mod).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should export a default server module', async () => {
|
|
33
|
+
const mod = await import(path.join(DIST_DIR, 'my-server.cjs.js'));
|
|
34
|
+
// The default export should be the server class or factory
|
|
35
|
+
expect(mod.default || mod).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should not throw on require', () => {
|
|
39
|
+
expect(() => {
|
|
40
|
+
require(path.join(DIST_DIR, 'my-server.cjs.js'));
|
|
41
|
+
}).not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## What This Demonstrates
|
|
47
|
+
|
|
48
|
+
- Using dynamic `import()` to test that the built JS bundle is importable
|
|
49
|
+
- Verifying the bundle has a default export (server class or factory)
|
|
50
|
+
- Testing CommonJS `require()` compatibility to ensure the bundle works in CJS environments
|
|
51
|
+
- Pointing to the `dist/` output directory where `frontmcp build` places artifacts
|
|
52
|
+
|
|
53
|
+
## Related
|
|
54
|
+
|
|
55
|
+
- See `test-cli-binary` for the full CLI binary testing reference
|
|
56
|
+
- See `test-browser-build` for browser-specific build testing
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: basic-create-test
|
|
3
|
+
reference: test-direct-client
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Test tools in-memory without any HTTP overhead using the `create()` function from `@frontmcp/sdk`.'
|
|
6
|
+
tags: [testing, sdk, transport, direct-client, direct, client]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using `create()` to spin up an in-memory server with no HTTP transport'
|
|
9
|
+
- 'Defining tools inline with the functional `tool()` API and Zod schemas'
|
|
10
|
+
- 'Calling tools directly via `server.callTool()` and checking text content'
|
|
11
|
+
- 'Proper cleanup with `server.dispose()` in each test'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Basic In-Memory Testing with create()
|
|
15
|
+
|
|
16
|
+
Test tools in-memory without any HTTP overhead using the `create()` function from `@frontmcp/sdk`.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/__tests__/direct-client.spec.ts
|
|
22
|
+
import { create } from '@frontmcp/sdk';
|
|
23
|
+
import { tool } from '@frontmcp/sdk';
|
|
24
|
+
import { z } from 'zod';
|
|
25
|
+
|
|
26
|
+
const AddTool = tool({
|
|
27
|
+
name: 'add',
|
|
28
|
+
description: 'Add numbers',
|
|
29
|
+
inputSchema: { a: z.number(), b: z.number() },
|
|
30
|
+
outputSchema: { sum: z.number() },
|
|
31
|
+
})((input) => ({ sum: input.a + input.b }));
|
|
32
|
+
|
|
33
|
+
describe('Direct Client Testing', () => {
|
|
34
|
+
it('should call tools via create()', async () => {
|
|
35
|
+
const server = await create({
|
|
36
|
+
info: { name: 'test', version: '1.0.0' },
|
|
37
|
+
tools: [AddTool],
|
|
38
|
+
cacheKey: 'test-direct',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const result = await server.callTool('add', { a: 2, b: 3 });
|
|
42
|
+
expect(result.content[0].text).toContain('5');
|
|
43
|
+
|
|
44
|
+
await server.dispose();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should handle multiple tool calls', async () => {
|
|
48
|
+
const server = await create({
|
|
49
|
+
info: { name: 'test', version: '1.0.0' },
|
|
50
|
+
tools: [AddTool],
|
|
51
|
+
cacheKey: 'test-direct-multi',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const r1 = await server.callTool('add', { a: 10, b: 20 });
|
|
55
|
+
expect(r1.content[0].text).toContain('30');
|
|
56
|
+
|
|
57
|
+
const r2 = await server.callTool('add', { a: -5, b: 5 });
|
|
58
|
+
expect(r2.content[0].text).toContain('0');
|
|
59
|
+
|
|
60
|
+
await server.dispose();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## What This Demonstrates
|
|
66
|
+
|
|
67
|
+
- Using `create()` to spin up an in-memory server with no HTTP transport
|
|
68
|
+
- Defining tools inline with the functional `tool()` API and Zod schemas
|
|
69
|
+
- Calling tools directly via `server.callTool()` and checking text content
|
|
70
|
+
- Proper cleanup with `server.dispose()` in each test
|
|
71
|
+
|
|
72
|
+
## Related
|
|
73
|
+
|
|
74
|
+
- See `test-direct-client` for the full direct client testing reference
|