@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
package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vector-search-and-resources
|
|
3
|
+
reference: example-knowledge-base
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: 'Shows a semantic search tool with embedding generation and a resource template for retrieving documents by ID using URI parameters.'
|
|
6
|
+
tags: [guides, openai, semantic-search, knowledge-base, knowledge, base]
|
|
7
|
+
features:
|
|
8
|
+
- 'Semantic search tool that generates query embeddings via `this.fetch()` to OpenAI'
|
|
9
|
+
- 'Using `this.mark()` for execution phase tracing'
|
|
10
|
+
- "Resource template with `uriTemplate: 'kb://documents/{documentId}'` for parameterized URIs"
|
|
11
|
+
- 'Typed params via `ResourceContext<{ documentId: string }>` for type-safe URI parameters'
|
|
12
|
+
- 'Returning `ReadResourceResult` with proper MCP protocol structure'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Knowledge Base: Semantic Search Tool and Resource Template
|
|
16
|
+
|
|
17
|
+
Shows a semantic search tool with embedding generation and a resource template for retrieving documents by ID using URI parameters.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// src/search/tools/search-docs.tool.ts
|
|
23
|
+
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
24
|
+
import { z } from 'zod';
|
|
25
|
+
import { VECTOR_STORE } from '../../ingestion/providers/vector-store.provider';
|
|
26
|
+
|
|
27
|
+
@Tool({
|
|
28
|
+
name: 'search_docs',
|
|
29
|
+
description: 'Semantic search across the knowledge base',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
query: z.string().min(1).describe('Natural language search query'),
|
|
32
|
+
topK: z.number().int().min(1).max(20).default(5).describe('Number of results'),
|
|
33
|
+
},
|
|
34
|
+
outputSchema: {
|
|
35
|
+
results: z.array(
|
|
36
|
+
z.object({
|
|
37
|
+
documentId: z.string(),
|
|
38
|
+
content: z.string(),
|
|
39
|
+
score: z.number(),
|
|
40
|
+
title: z.string(),
|
|
41
|
+
}),
|
|
42
|
+
),
|
|
43
|
+
total: z.number(),
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
export class SearchDocsTool extends ToolContext {
|
|
47
|
+
async execute(input: { query: string; topK: number }) {
|
|
48
|
+
const store = this.get(VECTOR_STORE);
|
|
49
|
+
|
|
50
|
+
// Mark execution phases for observability
|
|
51
|
+
this.mark('embedding-query');
|
|
52
|
+
const queryEmbedding = await this.generateQueryEmbedding(input.query);
|
|
53
|
+
|
|
54
|
+
this.mark('searching');
|
|
55
|
+
const chunks = await store.search(queryEmbedding, input.topK);
|
|
56
|
+
|
|
57
|
+
const results = chunks.map((chunk) => ({
|
|
58
|
+
documentId: chunk.documentId,
|
|
59
|
+
content: chunk.content,
|
|
60
|
+
score: chunk.metadata.score ? parseFloat(chunk.metadata.score) : 0,
|
|
61
|
+
title: chunk.metadata.title ?? 'Untitled',
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
return { results, total: results.length };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async generateQueryEmbedding(query: string): Promise<number[]> {
|
|
68
|
+
const response = await this.fetch('https://api.openai.com/v1/embeddings', {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: {
|
|
71
|
+
'Content-Type': 'application/json',
|
|
72
|
+
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
|
|
73
|
+
},
|
|
74
|
+
body: JSON.stringify({ input: query, model: 'text-embedding-3-small' }),
|
|
75
|
+
});
|
|
76
|
+
const data = await response.json();
|
|
77
|
+
return data.data[0].embedding;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// src/search/resources/doc.resource.ts
|
|
84
|
+
import { ResourceTemplate, ResourceContext } from '@frontmcp/sdk';
|
|
85
|
+
import type { ReadResourceResult } from '@frontmcp/protocol';
|
|
86
|
+
import { VECTOR_STORE } from '../../ingestion/providers/vector-store.provider';
|
|
87
|
+
|
|
88
|
+
@ResourceTemplate({
|
|
89
|
+
name: 'document',
|
|
90
|
+
uriTemplate: 'kb://documents/{documentId}',
|
|
91
|
+
description: 'Retrieve all chunks of a document by its ID',
|
|
92
|
+
mimeType: 'application/json',
|
|
93
|
+
})
|
|
94
|
+
export class DocResource extends ResourceContext<{ documentId: string }> {
|
|
95
|
+
async execute(uri: string, params: { documentId: string }): Promise<ReadResourceResult> {
|
|
96
|
+
const store = this.get(VECTOR_STORE);
|
|
97
|
+
const chunks = await store.getByDocumentId(params.documentId);
|
|
98
|
+
|
|
99
|
+
if (chunks.length === 0) {
|
|
100
|
+
this.fail(new Error(`Document not found: ${params.documentId}`));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const document = {
|
|
104
|
+
documentId: params.documentId,
|
|
105
|
+
title: chunks[0].metadata.title ?? 'Untitled',
|
|
106
|
+
chunks: chunks.map((c) => ({
|
|
107
|
+
chunkIndex: c.metadata.chunkIndex,
|
|
108
|
+
content: c.content,
|
|
109
|
+
})),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
contents: [
|
|
114
|
+
{
|
|
115
|
+
uri,
|
|
116
|
+
mimeType: 'application/json',
|
|
117
|
+
text: JSON.stringify(document, null, 2),
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## What This Demonstrates
|
|
126
|
+
|
|
127
|
+
- Semantic search tool that generates query embeddings via `this.fetch()` to OpenAI
|
|
128
|
+
- Using `this.mark()` for execution phase tracing
|
|
129
|
+
- Resource template with `uriTemplate: 'kb://documents/{documentId}'` for parameterized URIs
|
|
130
|
+
- Typed params via `ResourceContext<{ documentId: string }>` for type-safe URI parameters
|
|
131
|
+
- Returning `ReadResourceResult` with proper MCP protocol structure
|
|
132
|
+
|
|
133
|
+
## Related
|
|
134
|
+
|
|
135
|
+
- See `example-knowledge-base` for the full knowledge base example with ingestion, agent, and plugin code
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auth-and-crud-tools
|
|
3
|
+
reference: example-task-manager
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Shows how to create CRUD tools with authentication, using `this.context.session` for user isolation and `this.get()` for dependency injection.'
|
|
6
|
+
tags: [guides, auth, session, task-manager, task, manager]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using `this.context.session?.userId` for per-user data isolation'
|
|
9
|
+
- 'Using `this.get(TASK_STORE)` for dependency injection of providers'
|
|
10
|
+
- 'Enforcing authentication with `this.fail()` when no session exists'
|
|
11
|
+
- 'Optional input fields with `.optional()` for filtering'
|
|
12
|
+
- '`outputSchema` with nested `z.array(z.object(...))` for structured responses'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Task Manager: Authenticated CRUD Tools
|
|
16
|
+
|
|
17
|
+
Shows how to create CRUD tools with authentication, using `this.context.session` for user isolation and `this.get()` for dependency injection.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// src/tools/create-task.tool.ts
|
|
23
|
+
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
24
|
+
import { z } from 'zod';
|
|
25
|
+
import { TASK_STORE } from '../providers/task-store.provider';
|
|
26
|
+
|
|
27
|
+
@Tool({
|
|
28
|
+
name: 'create_task',
|
|
29
|
+
description: 'Create a new task for the authenticated user',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
title: z.string().min(1).max(200).describe('Task title'),
|
|
32
|
+
priority: z.enum(['low', 'medium', 'high']).default('medium').describe('Task priority'),
|
|
33
|
+
},
|
|
34
|
+
outputSchema: {
|
|
35
|
+
id: z.string(),
|
|
36
|
+
title: z.string(),
|
|
37
|
+
priority: z.string(),
|
|
38
|
+
status: z.string(),
|
|
39
|
+
createdAt: z.string(),
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
export class CreateTaskTool extends ToolContext {
|
|
43
|
+
async execute(input: { title: string; priority: 'low' | 'medium' | 'high' }) {
|
|
44
|
+
// Inject the task store via DI
|
|
45
|
+
const store = this.get(TASK_STORE);
|
|
46
|
+
|
|
47
|
+
// Get the authenticated user's ID from the session
|
|
48
|
+
const userId = this.context.session?.userId;
|
|
49
|
+
if (!userId) {
|
|
50
|
+
this.fail(new Error('Authentication required'));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const task = await store.create({
|
|
54
|
+
title: input.title,
|
|
55
|
+
priority: input.priority,
|
|
56
|
+
status: 'pending',
|
|
57
|
+
userId,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
id: task.id,
|
|
62
|
+
title: task.title,
|
|
63
|
+
priority: task.priority,
|
|
64
|
+
status: task.status,
|
|
65
|
+
createdAt: task.createdAt,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// src/tools/list-tasks.tool.ts
|
|
73
|
+
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
74
|
+
import { z } from 'zod';
|
|
75
|
+
import { TASK_STORE } from '../providers/task-store.provider';
|
|
76
|
+
|
|
77
|
+
@Tool({
|
|
78
|
+
name: 'list_tasks',
|
|
79
|
+
description: 'List all tasks for the authenticated user',
|
|
80
|
+
inputSchema: {
|
|
81
|
+
status: z.enum(['pending', 'in_progress', 'done']).optional().describe('Filter by status'),
|
|
82
|
+
},
|
|
83
|
+
outputSchema: {
|
|
84
|
+
tasks: z.array(
|
|
85
|
+
z.object({
|
|
86
|
+
id: z.string(),
|
|
87
|
+
title: z.string(),
|
|
88
|
+
priority: z.string(),
|
|
89
|
+
status: z.string(),
|
|
90
|
+
createdAt: z.string(),
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
93
|
+
total: z.number(),
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
export class ListTasksTool extends ToolContext {
|
|
97
|
+
async execute(input: { status?: 'pending' | 'in_progress' | 'done' }) {
|
|
98
|
+
const store = this.get(TASK_STORE);
|
|
99
|
+
const userId = this.context.session?.userId;
|
|
100
|
+
|
|
101
|
+
if (!userId) {
|
|
102
|
+
this.fail(new Error('Authentication required'));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let tasks = await store.list(userId);
|
|
106
|
+
|
|
107
|
+
if (input.status) {
|
|
108
|
+
tasks = tasks.filter((t) => t.status === input.status);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
tasks: tasks.map((t) => ({
|
|
113
|
+
id: t.id,
|
|
114
|
+
title: t.title,
|
|
115
|
+
priority: t.priority,
|
|
116
|
+
status: t.status,
|
|
117
|
+
createdAt: t.createdAt,
|
|
118
|
+
})),
|
|
119
|
+
total: tasks.length,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## What This Demonstrates
|
|
126
|
+
|
|
127
|
+
- Using `this.context.session?.userId` for per-user data isolation
|
|
128
|
+
- Using `this.get(TASK_STORE)` for dependency injection of providers
|
|
129
|
+
- Enforcing authentication with `this.fail()` when no session exists
|
|
130
|
+
- Optional input fields with `.optional()` for filtering
|
|
131
|
+
- `outputSchema` with nested `z.array(z.object(...))` for structured responses
|
|
132
|
+
|
|
133
|
+
## Related
|
|
134
|
+
|
|
135
|
+
- See `example-task-manager` for the full task manager example with provider, auth, and tests
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: authenticated-e2e-tests
|
|
3
|
+
reference: example-task-manager
|
|
4
|
+
level: advanced
|
|
5
|
+
description: 'Shows how to write E2E tests with authentication using `TestTokenFactory`, and unit tests for tools that require session context.'
|
|
6
|
+
tags: [guides, auth, session, e2e, unit-test, task-manager]
|
|
7
|
+
features:
|
|
8
|
+
- 'Using `TestTokenFactory` to create JWT tokens for authenticated E2E tests'
|
|
9
|
+
- 'Chaining `.withToken(token).buildAndConnect()` for authenticated clients'
|
|
10
|
+
- 'Unit testing with mocked DI tokens via `this.get()` mock'
|
|
11
|
+
- 'Mocking session context (`context: { session: { userId } }`) for auth-dependent tools'
|
|
12
|
+
- 'Testing the unauthenticated error path (no session)'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Task Manager: Authenticated E2E Tests
|
|
16
|
+
|
|
17
|
+
Shows how to write E2E tests with authentication using `TestTokenFactory`, and unit tests for tools that require session context.
|
|
18
|
+
|
|
19
|
+
## Code
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// test/tasks.e2e.spec.ts
|
|
23
|
+
import { McpTestClient, TestServer, TestTokenFactory } from '@frontmcp/testing';
|
|
24
|
+
|
|
25
|
+
describe('Task Manager E2E', () => {
|
|
26
|
+
let client: McpTestClient;
|
|
27
|
+
let server: TestServer;
|
|
28
|
+
|
|
29
|
+
beforeAll(async () => {
|
|
30
|
+
server = await TestServer.start({ command: 'npx tsx src/main.ts' });
|
|
31
|
+
|
|
32
|
+
// Create a test token for authenticated requests
|
|
33
|
+
const tokenFactory = new TestTokenFactory();
|
|
34
|
+
const token = await tokenFactory.createTestToken({ sub: 'user-e2e', scopes: ['tasks'] });
|
|
35
|
+
|
|
36
|
+
// Build client with the auth token
|
|
37
|
+
client = await McpTestClient.create({ baseUrl: server.info.baseUrl }).withToken(token).buildAndConnect();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterAll(async () => {
|
|
41
|
+
await client.disconnect();
|
|
42
|
+
await server.stop();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should list all CRUD tools', async () => {
|
|
46
|
+
const { tools } = await client.listTools();
|
|
47
|
+
const names = tools.map((t) => t.name);
|
|
48
|
+
|
|
49
|
+
expect(names).toContain('create_task');
|
|
50
|
+
expect(names).toContain('list_tasks');
|
|
51
|
+
expect(names).toContain('update_task');
|
|
52
|
+
expect(names).toContain('delete_task');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should create and list a task', async () => {
|
|
56
|
+
const createResult = await client.callTool('create_task', {
|
|
57
|
+
title: 'E2E test task',
|
|
58
|
+
priority: 'high',
|
|
59
|
+
});
|
|
60
|
+
expect(createResult).toBeSuccessful();
|
|
61
|
+
|
|
62
|
+
const listResult = await client.callTool('list_tasks', {});
|
|
63
|
+
expect(listResult).toBeSuccessful();
|
|
64
|
+
|
|
65
|
+
const parsed = JSON.parse(listResult.content[0].text);
|
|
66
|
+
expect(parsed.tasks.length).toBeGreaterThan(0);
|
|
67
|
+
expect(parsed.tasks.some((t: { title: string }) => t.title === 'E2E test task')).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// test/create-task.tool.spec.ts — Unit test with mocked session
|
|
74
|
+
import { ToolContext } from '@frontmcp/sdk';
|
|
75
|
+
import { CreateTaskTool } from '../src/tools/create-task.tool';
|
|
76
|
+
import { TASK_STORE, type TaskStore } from '../src/providers/task-store.provider';
|
|
77
|
+
import type { Task } from '../src/types/task';
|
|
78
|
+
|
|
79
|
+
describe('CreateTaskTool', () => {
|
|
80
|
+
let tool: CreateTaskTool;
|
|
81
|
+
let mockStore: jest.Mocked<TaskStore>;
|
|
82
|
+
|
|
83
|
+
beforeEach(() => {
|
|
84
|
+
tool = new CreateTaskTool();
|
|
85
|
+
mockStore = {
|
|
86
|
+
create: jest.fn(),
|
|
87
|
+
list: jest.fn(),
|
|
88
|
+
update: jest.fn(),
|
|
89
|
+
delete: jest.fn(),
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
function applyContext(userId: string | undefined): void {
|
|
94
|
+
const ctx = {
|
|
95
|
+
get: jest.fn((token: symbol) => {
|
|
96
|
+
if (token === TASK_STORE) return mockStore;
|
|
97
|
+
throw new Error(`Unknown token: ${String(token)}`);
|
|
98
|
+
}),
|
|
99
|
+
tryGet: jest.fn(),
|
|
100
|
+
fail: jest.fn((err: Error) => {
|
|
101
|
+
throw err;
|
|
102
|
+
}),
|
|
103
|
+
mark: jest.fn(),
|
|
104
|
+
notify: jest.fn(),
|
|
105
|
+
respondProgress: jest.fn(),
|
|
106
|
+
context: { session: userId ? { userId } : undefined },
|
|
107
|
+
} as unknown as ToolContext;
|
|
108
|
+
Object.assign(tool, ctx);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
it('should create a task for an authenticated user', async () => {
|
|
112
|
+
const mockTask: Task = {
|
|
113
|
+
id: 'task-001',
|
|
114
|
+
title: 'Write tests',
|
|
115
|
+
priority: 'high',
|
|
116
|
+
status: 'pending',
|
|
117
|
+
userId: 'user-123',
|
|
118
|
+
createdAt: '2026-03-27T10:00:00.000Z',
|
|
119
|
+
};
|
|
120
|
+
mockStore.create.mockResolvedValue(mockTask);
|
|
121
|
+
applyContext('user-123');
|
|
122
|
+
|
|
123
|
+
const result = await tool.execute({ title: 'Write tests', priority: 'high' });
|
|
124
|
+
|
|
125
|
+
expect(result.id).toBe('task-001');
|
|
126
|
+
expect(result.title).toBe('Write tests');
|
|
127
|
+
expect(mockStore.create).toHaveBeenCalledWith(expect.objectContaining({ userId: 'user-123', status: 'pending' }));
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should fail when user is not authenticated', async () => {
|
|
131
|
+
applyContext(undefined);
|
|
132
|
+
|
|
133
|
+
await expect(tool.execute({ title: 'Write tests', priority: 'medium' })).rejects.toThrow('Authentication required');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## What This Demonstrates
|
|
139
|
+
|
|
140
|
+
- Using `TestTokenFactory` to create JWT tokens for authenticated E2E tests
|
|
141
|
+
- Chaining `.withToken(token).buildAndConnect()` for authenticated clients
|
|
142
|
+
- Unit testing with mocked DI tokens via `this.get()` mock
|
|
143
|
+
- Mocking session context (`context: { session: { userId } }`) for auth-dependent tools
|
|
144
|
+
- Testing the unauthenticated error path (no session)
|
|
145
|
+
|
|
146
|
+
## Related
|
|
147
|
+
|
|
148
|
+
- See `example-task-manager` for the full task manager example with server setup and Vercel deployment
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: redis-provider-with-di
|
|
3
|
+
reference: example-task-manager
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: 'Shows how to create a Redis-backed provider with a DI token, lifecycle hooks (`onInit`/`onDestroy`), and how tools inject it.'
|
|
6
|
+
tags: [guides, redis, node, task-manager, task, manager]
|
|
7
|
+
features:
|
|
8
|
+
- "Defining an interface and DI token (`Symbol('TaskStore')`) for the provider"
|
|
9
|
+
- 'Using `@Provider({ token: TASK_STORE })` to register the provider for DI'
|
|
10
|
+
- 'Lifecycle hooks: `onInit()` for connection setup, `onDestroy()` for cleanup'
|
|
11
|
+
- 'Lazy-loading `ioredis` via dynamic `import()` in `onInit()`'
|
|
12
|
+
- 'Using `@frontmcp/utils` for `randomUUID()` instead of `node:crypto`'
|
|
13
|
+
- 'Per-user data isolation using Redis hash keys (`tasks:${userId}`)'
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Task Manager: Redis Provider with Dependency Injection
|
|
17
|
+
|
|
18
|
+
Shows how to create a Redis-backed provider with a DI token, lifecycle hooks (`onInit`/`onDestroy`), and how tools inject it.
|
|
19
|
+
|
|
20
|
+
## Code
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// src/types/task.ts
|
|
24
|
+
export interface Task {
|
|
25
|
+
id: string;
|
|
26
|
+
title: string;
|
|
27
|
+
priority: 'low' | 'medium' | 'high';
|
|
28
|
+
status: 'pending' | 'in_progress' | 'done';
|
|
29
|
+
userId: string;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// src/providers/task-store.provider.ts
|
|
36
|
+
import { Provider } from '@frontmcp/sdk';
|
|
37
|
+
import type { Token } from '@frontmcp/di';
|
|
38
|
+
import type { Task } from '../types/task';
|
|
39
|
+
|
|
40
|
+
export interface TaskStore {
|
|
41
|
+
create(task: Omit<Task, 'id' | 'createdAt'>): Promise<Task>;
|
|
42
|
+
list(userId: string): Promise<Task[]>;
|
|
43
|
+
update(id: string, userId: string, data: Partial<Pick<Task, 'title' | 'priority' | 'status'>>): Promise<Task>;
|
|
44
|
+
delete(id: string, userId: string): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// DI token — tools use this.get(TASK_STORE) to access the provider
|
|
48
|
+
export const TASK_STORE: Token<TaskStore> = Symbol('TaskStore');
|
|
49
|
+
|
|
50
|
+
@Provider({ token: TASK_STORE })
|
|
51
|
+
export class RedisTaskStoreProvider implements TaskStore {
|
|
52
|
+
private redis!: import('ioredis').default;
|
|
53
|
+
|
|
54
|
+
// Lifecycle: initialize Redis connection
|
|
55
|
+
async onInit(): Promise<void> {
|
|
56
|
+
const Redis = (await import('ioredis')).default;
|
|
57
|
+
this.redis = new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async create(input: Omit<Task, 'id' | 'createdAt'>): Promise<Task> {
|
|
61
|
+
const { randomUUID } = await import('@frontmcp/utils');
|
|
62
|
+
const task: Task = {
|
|
63
|
+
...input,
|
|
64
|
+
id: randomUUID(),
|
|
65
|
+
createdAt: new Date().toISOString(),
|
|
66
|
+
};
|
|
67
|
+
await this.redis.hset(`tasks:${task.userId}`, task.id, JSON.stringify(task));
|
|
68
|
+
return task;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async list(userId: string): Promise<Task[]> {
|
|
72
|
+
const entries = await this.redis.hgetall(`tasks:${userId}`);
|
|
73
|
+
return Object.values(entries).map((v) => JSON.parse(v) as Task);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async update(id: string, userId: string, data: Partial<Pick<Task, 'title' | 'priority' | 'status'>>): Promise<Task> {
|
|
77
|
+
const raw = await this.redis.hget(`tasks:${userId}`, id);
|
|
78
|
+
if (!raw) {
|
|
79
|
+
throw new Error(`Task not found: ${id}`);
|
|
80
|
+
}
|
|
81
|
+
const task: Task = { ...(JSON.parse(raw) as Task), ...data };
|
|
82
|
+
await this.redis.hset(`tasks:${userId}`, id, JSON.stringify(task));
|
|
83
|
+
return task;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async delete(id: string, userId: string): Promise<void> {
|
|
87
|
+
const removed = await this.redis.hdel(`tasks:${userId}`, id);
|
|
88
|
+
if (removed === 0) {
|
|
89
|
+
throw new Error(`Task not found: ${id}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Lifecycle: close Redis connection on shutdown
|
|
94
|
+
async onDestroy(): Promise<void> {
|
|
95
|
+
await this.redis.quit();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// src/tasks.app.ts
|
|
102
|
+
import { App } from '@frontmcp/sdk';
|
|
103
|
+
import { RedisTaskStoreProvider } from './providers/task-store.provider';
|
|
104
|
+
import { CreateTaskTool } from './tools/create-task.tool';
|
|
105
|
+
import { ListTasksTool } from './tools/list-tasks.tool';
|
|
106
|
+
import { UpdateTaskTool } from './tools/update-task.tool';
|
|
107
|
+
import { DeleteTaskTool } from './tools/delete-task.tool';
|
|
108
|
+
|
|
109
|
+
@App({
|
|
110
|
+
name: 'Tasks',
|
|
111
|
+
description: 'Task management with CRUD operations',
|
|
112
|
+
providers: [RedisTaskStoreProvider],
|
|
113
|
+
tools: [CreateTaskTool, ListTasksTool, UpdateTaskTool, DeleteTaskTool],
|
|
114
|
+
})
|
|
115
|
+
export class TasksApp {}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## What This Demonstrates
|
|
119
|
+
|
|
120
|
+
- Defining an interface and DI token (`Symbol('TaskStore')`) for the provider
|
|
121
|
+
- Using `@Provider({ token: TASK_STORE })` to register the provider for DI
|
|
122
|
+
- Lifecycle hooks: `onInit()` for connection setup, `onDestroy()` for cleanup
|
|
123
|
+
- Lazy-loading `ioredis` via dynamic `import()` in `onInit()`
|
|
124
|
+
- Using `@frontmcp/utils` for `randomUUID()` instead of `node:crypto`
|
|
125
|
+
- Per-user data isolation using Redis hash keys (`tasks:${userId}`)
|
|
126
|
+
|
|
127
|
+
## Related
|
|
128
|
+
|
|
129
|
+
- See `example-task-manager` for the full task manager example with auth and E2E tests
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: server-and-app-setup
|
|
3
|
+
reference: example-weather-api
|
|
4
|
+
level: basic
|
|
5
|
+
description: 'Shows the server entry point, app registration, and static resource for a beginner FrontMCP weather API server.'
|
|
6
|
+
tags: [guides, weather, api, app, setup]
|
|
7
|
+
features:
|
|
8
|
+
- 'Server entry point with `@FrontMcp` decorator and `info` configuration'
|
|
9
|
+
- 'App registration with `@App` grouping tools and resources together'
|
|
10
|
+
- 'Static resource that returns JSON data via `read()`'
|
|
11
|
+
- 'Clean separation between server, app, tools, and resources'
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Weather API: Server and App Setup
|
|
15
|
+
|
|
16
|
+
Shows the server entry point, app registration, and static resource for a beginner FrontMCP weather API server.
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// src/main.ts
|
|
22
|
+
import { FrontMcp } from '@frontmcp/sdk';
|
|
23
|
+
import { WeatherApp } from './weather.app';
|
|
24
|
+
|
|
25
|
+
@FrontMcp({
|
|
26
|
+
info: { name: 'weather-api', version: '1.0.0' },
|
|
27
|
+
apps: [WeatherApp],
|
|
28
|
+
})
|
|
29
|
+
export default class WeatherServer {}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// src/weather.app.ts
|
|
34
|
+
import { App } from '@frontmcp/sdk';
|
|
35
|
+
import { GetWeatherTool } from './tools/get-weather.tool';
|
|
36
|
+
import { CitiesResource } from './resources/cities.resource';
|
|
37
|
+
|
|
38
|
+
@App({
|
|
39
|
+
name: 'Weather',
|
|
40
|
+
description: 'Weather lookup tools and city data',
|
|
41
|
+
tools: [GetWeatherTool],
|
|
42
|
+
resources: [CitiesResource],
|
|
43
|
+
})
|
|
44
|
+
export class WeatherApp {}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// src/resources/cities.resource.ts
|
|
49
|
+
import { Resource, ResourceContext } from '@frontmcp/sdk';
|
|
50
|
+
|
|
51
|
+
const SUPPORTED_CITIES = ['London', 'Tokyo', 'New York', 'Paris', 'Sydney', 'Berlin', 'Toronto', 'Mumbai'];
|
|
52
|
+
|
|
53
|
+
@Resource({
|
|
54
|
+
uri: 'weather://cities',
|
|
55
|
+
name: 'Supported Cities',
|
|
56
|
+
description: 'List of cities with available weather data',
|
|
57
|
+
mimeType: 'application/json',
|
|
58
|
+
})
|
|
59
|
+
export class CitiesResource extends ResourceContext {
|
|
60
|
+
async read() {
|
|
61
|
+
return JSON.stringify(SUPPORTED_CITIES);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## What This Demonstrates
|
|
67
|
+
|
|
68
|
+
- Server entry point with `@FrontMcp` decorator and `info` configuration
|
|
69
|
+
- App registration with `@App` grouping tools and resources together
|
|
70
|
+
- Static resource that returns JSON data via `read()`
|
|
71
|
+
- Clean separation between server, app, tools, and resources
|
|
72
|
+
|
|
73
|
+
## Related
|
|
74
|
+
|
|
75
|
+
- See `example-weather-api` for the full end-to-end weather API example
|