@frontmcp/skills 1.0.3 → 1.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/catalog/frontmcp-authorities/SKILL.md +272 -0
- package/catalog/frontmcp-authorities/references/authority-profiles.md +262 -0
- package/catalog/frontmcp-authorities/references/claims-mapping.md +266 -0
- package/catalog/frontmcp-authorities/references/custom-evaluators.md +420 -0
- package/catalog/frontmcp-authorities/references/rbac-abac-rebac.md +391 -0
- package/catalog/frontmcp-channels/SKILL.md +122 -0
- package/catalog/frontmcp-channels/examples/channel-sources/agent-notify.md +70 -0
- package/catalog/frontmcp-channels/examples/channel-sources/app-errors.md +71 -0
- package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +102 -0
- package/catalog/frontmcp-channels/examples/channel-sources/job-completion.md +79 -0
- package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +106 -0
- package/catalog/frontmcp-channels/examples/channel-sources/service-connector.md +136 -0
- package/catalog/frontmcp-channels/examples/channel-sources/webhook-github.md +85 -0
- package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +133 -0
- package/catalog/frontmcp-channels/references/channel-sources.md +214 -0
- package/catalog/frontmcp-channels/references/channel-two-way.md +195 -0
- package/catalog/frontmcp-config/SKILL.md +20 -18
- package/catalog/frontmcp-config/examples/configure-auth/multi-app-auth.md +1 -2
- package/catalog/frontmcp-config/examples/configure-auth/public-mode-setup.md +1 -2
- package/catalog/frontmcp-config/examples/configure-auth/remote-oauth-with-vault.md +1 -2
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +1 -2
- package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +1 -2
- package/catalog/frontmcp-config/examples/configure-auth-modes/transparent-jwt-validation.md +1 -2
- package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +121 -0
- package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +64 -0
- package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +113 -0
- package/catalog/frontmcp-config/examples/configure-elicitation/basic-confirmation-gate.md +1 -2
- package/catalog/frontmcp-config/examples/configure-elicitation/distributed-elicitation-redis.md +1 -2
- package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -2
- package/catalog/frontmcp-config/examples/configure-http/unix-socket-local.md +1 -2
- package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +69 -0
- package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +91 -0
- package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +1 -2
- package/catalog/frontmcp-config/examples/configure-throttle/per-tool-rate-limit.md +1 -2
- package/catalog/frontmcp-config/examples/configure-throttle/server-level-rate-limit.md +1 -2
- package/catalog/frontmcp-config/examples/configure-transport/custom-protocol-flags.md +1 -2
- package/catalog/frontmcp-config/examples/configure-transport/distributed-sessions-redis.md +1 -2
- package/catalog/frontmcp-config/examples/configure-transport/stateless-serverless.md +1 -2
- package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/legacy-preset-nodejs.md +1 -2
- package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/stateless-api-serverless.md +1 -2
- package/catalog/frontmcp-config/references/configure-deployment-targets.md +214 -0
- package/catalog/frontmcp-config/references/configure-elicitation.md +1 -2
- package/catalog/frontmcp-config/references/configure-security-headers.md +198 -0
- package/catalog/frontmcp-deployment/SKILL.md +1 -0
- package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -2
- package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -2
- package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +117 -0
- package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -3
- package/catalog/frontmcp-deployment/examples/build-for-sdk/create-flat-config.md +1 -2
- package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +3 -3
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +1 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +1 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +1 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +1 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +1 -2
- package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +106 -0
- package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-binary-with-env.md +107 -0
- package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-npx.md +89 -0
- package/catalog/frontmcp-deployment/references/build-for-mcpb.md +209 -0
- package/catalog/frontmcp-deployment/references/build-for-sdk.md +1 -2
- package/catalog/frontmcp-deployment/references/mcp-client-integration.md +225 -0
- package/catalog/frontmcp-development/SKILL.md +4 -3
- package/catalog/frontmcp-development/examples/create-agent/basic-agent-with-tools.md +3 -6
- package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -2
- package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +2 -4
- package/catalog/frontmcp-development/examples/create-agent-llm-config/anthropic-config.md +1 -2
- package/catalog/frontmcp-development/examples/create-agent-llm-config/openai-config.md +1 -2
- package/catalog/frontmcp-development/examples/create-job/basic-report-job.md +1 -2
- package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +2 -3
- package/catalog/frontmcp-development/examples/create-job/job-with-retry.md +1 -2
- package/catalog/frontmcp-development/examples/create-plugin-hooks/tool-level-hooks-and-stage-replacement.md +2 -5
- package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +4 -3
- package/catalog/frontmcp-development/examples/create-skill-with-tools/directory-skill-with-tools.md +2 -3
- package/catalog/frontmcp-development/examples/create-tool/basic-class-tool.md +1 -2
- package/catalog/frontmcp-development/examples/create-tool/tool-with-di-and-errors.md +2 -2
- package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +1 -2
- package/catalog/frontmcp-development/examples/create-tool-annotations/destructive-delete-tool.md +2 -4
- package/catalog/frontmcp-development/examples/create-tool-annotations/readonly-query-tool.md +1 -2
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/primitive-and-media-outputs.md +3 -6
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-raw-shape-output.md +1 -2
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-schema-advanced-output.md +2 -4
- package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +3 -5
- package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +5 -5
- package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +4 -6
- package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +3 -5
- package/catalog/frontmcp-development/examples/official-plugins/production-multi-plugin-setup.md +4 -5
- package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +3 -5
- package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/authenticated-adapter-with-polling.md +2 -2
- package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/basic-openapi-adapter.md +2 -2
- package/catalog/frontmcp-development/examples/openapi-adapter/format-resolution-and-custom-resolvers.md +108 -0
- package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/multi-api-hub-with-inline-spec.md +2 -2
- package/catalog/frontmcp-development/examples/openapi-adapter/ref-security-and-filtering.md +111 -0
- package/catalog/frontmcp-development/references/create-agent.md +4 -7
- package/catalog/frontmcp-development/references/create-job.md +3 -6
- package/catalog/frontmcp-development/references/create-plugin-hooks.md +12 -16
- package/catalog/frontmcp-development/references/create-skill-with-tools.md +2 -3
- package/catalog/frontmcp-development/references/create-tool.md +93 -23
- package/catalog/frontmcp-development/references/create-workflow.md +2 -3
- package/catalog/frontmcp-development/references/decorators-guide.md +32 -36
- package/catalog/frontmcp-development/references/official-adapters.md +24 -153
- package/catalog/frontmcp-development/references/openapi-adapter.md +431 -0
- package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +4 -4
- package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -4
- package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +4 -3
- package/catalog/frontmcp-guides/SKILL.md +3 -3
- package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +4 -5
- package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +4 -3
- package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +4 -4
- package/catalog/frontmcp-guides/examples/example-weather-api/weather-tool-with-schemas.md +1 -2
- package/catalog/frontmcp-guides/references/example-knowledge-base.md +22 -17
- package/catalog/frontmcp-guides/references/example-task-manager.md +16 -11
- package/catalog/frontmcp-guides/references/example-weather-api.md +6 -3
- package/catalog/frontmcp-observability/examples/telemetry-api/tool-custom-spans.md +2 -3
- package/catalog/frontmcp-observability/examples/tracing-setup/basic-tracing.md +4 -3
- package/catalog/frontmcp-observability/references/telemetry-api.md +2 -3
- package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -2
- package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +3 -4
- package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md +229 -0
- package/catalog/frontmcp-production-readiness/examples/production-browser/cross-platform-crypto.md +2 -3
- package/catalog/frontmcp-production-readiness/examples/production-cli-binary/stdio-transport-error-handling.md +1 -2
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -4
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/workers-runtime-constraints.md +2 -3
- package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +3 -2
- package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +2 -2
- package/catalog/frontmcp-production-readiness/examples/production-vercel/stateless-serverless-design.md +3 -3
- package/catalog/frontmcp-production-readiness/references/distributed-ha.md +194 -0
- package/catalog/frontmcp-setup/SKILL.md +11 -11
- package/catalog/frontmcp-setup/examples/project-structure-standalone/feature-folder-organization.md +5 -3
- package/catalog/frontmcp-setup/examples/project-structure-standalone/minimal-standalone-layout.md +4 -2
- package/catalog/frontmcp-setup/examples/setup-project/basic-node-server.md +4 -2
- package/catalog/frontmcp-setup/examples/setup-project/vercel-serverless-server.md +4 -2
- package/catalog/frontmcp-setup/examples/setup-redis/hybrid-vercel-kv-with-pubsub.md +8 -7
- package/catalog/frontmcp-setup/references/setup-project.md +10 -9
- package/catalog/frontmcp-setup/references/setup-redis.md +19 -16
- package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +1 -3
- package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +1 -3
- package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +2 -2
- package/catalog/frontmcp-testing/references/test-direct-client.md +1 -3
- package/catalog/frontmcp-testing/references/test-tool-unit.md +2 -2
- package/catalog/skills-manifest.json +364 -12
- package/package.json +1 -1
package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md
CHANGED
|
@@ -45,8 +45,7 @@ export class LazyApiClientProvider {
|
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
47
|
// src/tools/cached-lookup.tool.ts
|
|
48
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
49
|
-
import { z } from 'zod';
|
|
48
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
50
49
|
|
|
51
50
|
// Cache OpenAPI spec in module scope — survives warm invocations
|
|
52
51
|
let cachedSpec: unknown | undefined;
|
|
@@ -78,6 +77,7 @@ export class CachedLookupTool extends ToolContext {
|
|
|
78
77
|
```typescript
|
|
79
78
|
// src/main.ts
|
|
80
79
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
80
|
+
|
|
81
81
|
// Only import lightweight modules at the top level
|
|
82
82
|
import { MyApp } from './my.app';
|
|
83
83
|
|
|
@@ -19,10 +19,9 @@ Shows a fully stateless server design that works on Vercel edge runtime with no
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/tools/edge-safe-tool.tool.ts
|
|
22
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
23
|
-
import { z } from 'zod';
|
|
22
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
24
23
|
// Use @frontmcp/utils for cross-platform crypto — not node:crypto
|
|
25
|
-
import {
|
|
24
|
+
import { randomUUID, sha256Hex } from '@frontmcp/utils';
|
|
26
25
|
|
|
27
26
|
@Tool({
|
|
28
27
|
name: 'process_request',
|
|
@@ -60,6 +59,7 @@ export class ProcessRequestTool extends ToolContext {
|
|
|
60
59
|
```typescript
|
|
61
60
|
// src/main.ts
|
|
62
61
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
62
|
+
|
|
63
63
|
import { EdgeApp } from './edge.app';
|
|
64
64
|
|
|
65
65
|
@FrontMcp({
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: distributed-ha
|
|
3
|
+
description: Deploy FrontMCP across multiple pods with heartbeat, session takeover, and notification relay for zero-downtime failover
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Distributed High Availability
|
|
7
|
+
|
|
8
|
+
FrontMCP's HA module provides automatic session failover across multiple pods using Redis. Three components work together: HeartbeatService (liveness detection), session takeover (atomic CAS), and NotificationRelay (cross-pod MCP notifications).
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
### Must Use
|
|
13
|
+
|
|
14
|
+
- Running 2+ FrontMCP pods behind a load balancer with Redis available
|
|
15
|
+
- Production deployments where pod restarts must not drop active MCP sessions
|
|
16
|
+
- Kubernetes deployments with rolling updates or horizontal pod autoscaling
|
|
17
|
+
|
|
18
|
+
### Recommended
|
|
19
|
+
|
|
20
|
+
- Any production deployment where zero-downtime upgrades are needed
|
|
21
|
+
- Multi-region setups with Redis replication
|
|
22
|
+
|
|
23
|
+
### Skip When
|
|
24
|
+
|
|
25
|
+
- Single-pod deployments (use `deploy-to-node` instead)
|
|
26
|
+
- Serverless platforms (Vercel, Lambda, Cloudflare) --- stateless by design
|
|
27
|
+
- Development and testing --- use `direct-client` or standalone mode
|
|
28
|
+
|
|
29
|
+
> **Decision:** Use this skill when you need session continuity across pod restarts. Skip for serverless or single-pod setups.
|
|
30
|
+
|
|
31
|
+
## Prerequisites
|
|
32
|
+
|
|
33
|
+
- Redis 6+ accessible from all pods
|
|
34
|
+
- `@frontmcp/sdk` and `@frontmcp/cli` installed
|
|
35
|
+
- `FRONTMCP_DEPLOYMENT_MODE=distributed` environment variable
|
|
36
|
+
|
|
37
|
+
## Step 1: Configure @FrontMcp Decorator
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { FrontMcp } from '@frontmcp/sdk';
|
|
41
|
+
|
|
42
|
+
@FrontMcp({
|
|
43
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
44
|
+
apps: [MyApp],
|
|
45
|
+
redis: { provider: 'redis', host: 'redis', port: 6379 },
|
|
46
|
+
transport: {
|
|
47
|
+
persistence: {
|
|
48
|
+
redis: { provider: 'redis', host: 'redis', port: 6379 },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
class Server {}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Step 2: Create Configuration File
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// frontmcp.config.ts
|
|
59
|
+
import { defineConfig } from '@frontmcp/cli';
|
|
60
|
+
|
|
61
|
+
export default defineConfig({
|
|
62
|
+
name: 'my-server',
|
|
63
|
+
version: '1.0.0',
|
|
64
|
+
deployments: [
|
|
65
|
+
{
|
|
66
|
+
target: 'distributed',
|
|
67
|
+
ha: {
|
|
68
|
+
heartbeatIntervalMs: 10000,
|
|
69
|
+
heartbeatTtlMs: 30000,
|
|
70
|
+
takeoverGracePeriodMs: 5000,
|
|
71
|
+
redisKeyPrefix: 'mcp:ha:',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Step 3: Build and Deploy
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export FRONTMCP_DEPLOYMENT_MODE=distributed
|
|
82
|
+
frontmcp build --target distributed
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Deploy with Docker or Kubernetes (see example below).
|
|
86
|
+
|
|
87
|
+
## Step 4: Verify Heartbeats
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Check heartbeat keys exist for each pod
|
|
91
|
+
redis-cli --scan --pattern "mcp:ha:heartbeat:*"
|
|
92
|
+
|
|
93
|
+
# Inspect a heartbeat value
|
|
94
|
+
redis-cli GET "mcp:ha:heartbeat:mcp-server-7b8f9-abc12"
|
|
95
|
+
# Returns: {"nodeId":"mcp-server-7b8f9-abc12","startedAt":1712620800000,"lastBeat":1712620810000,"sessionCount":5}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Configuration
|
|
99
|
+
|
|
100
|
+
| Field | Type | Default | Description |
|
|
101
|
+
| ----------------------- | ------ | --------- | ------------------------------------------------ |
|
|
102
|
+
| `heartbeatIntervalMs` | number | 10000 | How often each pod writes its heartbeat to Redis |
|
|
103
|
+
| `heartbeatTtlMs` | number | 30000 | TTL for heartbeat key (should be 2-3x interval) |
|
|
104
|
+
| `takeoverGracePeriodMs` | number | 5000 | Wait time before claiming orphaned sessions |
|
|
105
|
+
| `redisKeyPrefix` | string | `mcp:ha:` | Redis key prefix for all HA keys |
|
|
106
|
+
|
|
107
|
+
## Architecture
|
|
108
|
+
|
|
109
|
+
### Heartbeat Service
|
|
110
|
+
|
|
111
|
+
Each pod writes `mcp:ha:heartbeat:{nodeId}` to Redis every `heartbeatIntervalMs` with PX TTL of `heartbeatTtlMs`. The value contains `{ nodeId, startedAt, lastBeat, sessionCount }`. When a pod dies, the key expires.
|
|
112
|
+
|
|
113
|
+
### Session Takeover
|
|
114
|
+
|
|
115
|
+
When a request arrives for a session owned by a dead pod:
|
|
116
|
+
|
|
117
|
+
1. The live pod checks if the owner's heartbeat key exists
|
|
118
|
+
2. If missing, runs an atomic Lua CAS script: verifies `expectedOldNodeId`, updates `nodeId` + `reassignedAt`
|
|
119
|
+
3. Returns `{ claimed: true }` on success, `{ claimed: false }` if another pod won the race
|
|
120
|
+
|
|
121
|
+
### Notification Relay
|
|
122
|
+
|
|
123
|
+
Each pod subscribes to `mcp:ha:notify:{nodeId}` via Redis Pub/Sub. Cross-pod MCP notifications (progress updates, resource changes) are published to the target pod's channel for local delivery.
|
|
124
|
+
|
|
125
|
+
## Load Balancer Affinity
|
|
126
|
+
|
|
127
|
+
FrontMCP sets:
|
|
128
|
+
|
|
129
|
+
- **Cookie**: `__frontmcp_node` on Streamable HTTP initialize
|
|
130
|
+
- **Header**: `X-FrontMCP-Machine-Id` on every distributed response
|
|
131
|
+
|
|
132
|
+
NGINX sticky session example:
|
|
133
|
+
|
|
134
|
+
```nginx
|
|
135
|
+
upstream mcp_backend {
|
|
136
|
+
hash $cookie___frontmcp_node consistent;
|
|
137
|
+
server pod-1:3000;
|
|
138
|
+
server pod-2:3000;
|
|
139
|
+
server pod-3:3000;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Common Patterns
|
|
144
|
+
|
|
145
|
+
| Pattern | Correct | Incorrect | Why |
|
|
146
|
+
| ----------------- | ------------------------------------- | ----------------------------- | ------------------------------------------------- |
|
|
147
|
+
| Heartbeat TTL | `heartbeatTtlMs: 30000` (3x interval) | `heartbeatTtlMs: 10000` (1x) | Too low causes false-positive pod death detection |
|
|
148
|
+
| Redis connections | Dedicated pub/sub + data connections | Shared single connection | Pub/Sub blocks the connection |
|
|
149
|
+
| Machine ID | Let K8s set HOSTNAME | Override HOSTNAME in pod spec | Breaks session ownership mapping |
|
|
150
|
+
|
|
151
|
+
## Errors
|
|
152
|
+
|
|
153
|
+
| Error | When | Solution |
|
|
154
|
+
| --------------------------- | ------------------------------------------ | ------------------------------------------------------- |
|
|
155
|
+
| `SessionClaimConflictError` | Session claimed by another pod during race | Retry --- the load balancer will route to the new owner |
|
|
156
|
+
| `HaConfigurationError` | Redis not configured for distributed mode | Add `redis` to `@FrontMcp()` config |
|
|
157
|
+
|
|
158
|
+
## Verification Checklist
|
|
159
|
+
|
|
160
|
+
### Configuration
|
|
161
|
+
|
|
162
|
+
- [ ] `FRONTMCP_DEPLOYMENT_MODE=distributed` set in deployment
|
|
163
|
+
- [ ] Redis accessible from all pods
|
|
164
|
+
- [ ] `heartbeatTtlMs` >= 2x `heartbeatIntervalMs`
|
|
165
|
+
- [ ] Transport persistence configured with Redis
|
|
166
|
+
|
|
167
|
+
### Runtime
|
|
168
|
+
|
|
169
|
+
- [ ] `redis-cli --scan --pattern "mcp:ha:heartbeat:*"` shows entries for each pod
|
|
170
|
+
- [ ] Killing a pod results in its heartbeat expiring within TTL
|
|
171
|
+
- [ ] Surviving pods claim orphaned sessions after takeover grace period
|
|
172
|
+
- [ ] `/healthz` and `/readyz` return healthy on all pods
|
|
173
|
+
|
|
174
|
+
## Troubleshooting
|
|
175
|
+
|
|
176
|
+
| Problem | Cause | Solution |
|
|
177
|
+
| ---------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------ |
|
|
178
|
+
| Sessions not transferred after pod death | `heartbeatTtlMs` too high | Lower TTL while keeping >= 2x interval (e.g., 20-30s for a 10s interval) |
|
|
179
|
+
| `HaConfigurationError` on startup | Missing Redis config | Add `redis` to `@FrontMcp()` decorator |
|
|
180
|
+
| Duplicate notifications | Shared Redis subscriber connection | Use dedicated connections per relay |
|
|
181
|
+
| Session takeover race failures | High pod count + simultaneous restarts | Increase `takeoverGracePeriodMs` |
|
|
182
|
+
|
|
183
|
+
## Examples
|
|
184
|
+
|
|
185
|
+
| Example | Level | Description |
|
|
186
|
+
| ------------------------------------------------------------------------------------ | ------------ | ------------------------------------------------------------------------------------ |
|
|
187
|
+
| [`ha-kubernetes-3-replicas`](../examples/distributed-ha/ha-kubernetes-3-replicas.md) | Intermediate | Deploy FrontMCP with 3 replicas, Redis, and automatic session failover on Kubernetes |
|
|
188
|
+
|
|
189
|
+
> See all examples in [`examples/distributed-ha/`](../examples/distributed-ha/)
|
|
190
|
+
|
|
191
|
+
## Reference
|
|
192
|
+
|
|
193
|
+
- [Documentation](https://docs.agentfront.dev/frontmcp/deployment/high-availability)
|
|
194
|
+
- Related skills: `frontmcp-deployment`, `frontmcp-config`, `deploy-to-node`
|
|
@@ -52,17 +52,17 @@ Entry point for project setup and scaffolding. This skill helps you find the rig
|
|
|
52
52
|
|
|
53
53
|
## Scenario Routing Table
|
|
54
54
|
|
|
55
|
-
| Scenario | Reference | Description
|
|
56
|
-
| --------------------------------------------- | -------------------------------------------- |
|
|
57
|
-
| Scaffold a new project with `frontmcp create` | `references/setup-project.md` | CLI scaffolder (flags: `--target`, `--redis`, `--skills <bundle>`, `--cicd`, `--nx`, `--pm`)
|
|
58
|
-
| Organize a standalone (non-Nx) project | `references/project-structure-standalone.md` | File layout, naming conventions (`<name>.<type>.ts`), folder hierarchy
|
|
59
|
-
| Organize an Nx monorepo | `references/project-structure-nx.md` | apps/, libs/, servers/ layout, generators, dependency rules
|
|
60
|
-
| Set up Redis for production storage | `references/setup-redis.md` | Docker Redis, Vercel KV, pub/sub for subscriptions
|
|
61
|
-
| Set up SQLite for local development | `references/setup-sqlite.md` | WAL mode, migration helpers, encryption
|
|
62
|
-
| Compose multiple apps into one server | `references/multi-app-composition.md` | `@FrontMcp` with multiple `@App` classes, cross-app providers
|
|
63
|
-
| Use Nx build, test, and CI commands | `references/nx-workflow.md` | `nx build`, `nx test`, `nx run-many`, caching, affected commands
|
|
64
|
-
| Browse, install, and manage skills | `references/frontmcp-skills-usage.md` | CLI commands, bundles, categories, search
|
|
65
|
-
| Generate or update project README.md | `references/readme-guide.md` | Deployment-target-aware README for npm, CLI, Docker, serverless
|
|
55
|
+
| Scenario | Reference | Description |
|
|
56
|
+
| --------------------------------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
57
|
+
| Scaffold a new project with `frontmcp create` | `references/setup-project.md` | CLI scaffolder (flags: `--target`, `--redis`, `--skills <bundle>`, `--cicd`, `--nx`, `--pm`) |
|
|
58
|
+
| Organize a standalone (non-Nx) project | `references/project-structure-standalone.md` | File layout, naming conventions (`<name>.<type>.ts`), folder hierarchy |
|
|
59
|
+
| Organize an Nx monorepo | `references/project-structure-nx.md` | apps/, libs/, servers/ layout, generators, dependency rules |
|
|
60
|
+
| Set up Redis for production storage | `references/setup-redis.md` | Docker Redis, Vercel KV, pub/sub for distributed subscriptions (single-server uses in-memory) |
|
|
61
|
+
| Set up SQLite for local development | `references/setup-sqlite.md` | WAL mode, migration helpers, encryption |
|
|
62
|
+
| Compose multiple apps into one server | `references/multi-app-composition.md` | `@FrontMcp` with multiple `@App` classes, cross-app providers |
|
|
63
|
+
| Use Nx build, test, and CI commands | `references/nx-workflow.md` | `nx build`, `nx test`, `nx run-many`, caching, affected commands |
|
|
64
|
+
| Browse, install, and manage skills | `references/frontmcp-skills-usage.md` | CLI commands, bundles, categories, search |
|
|
65
|
+
| Generate or update project README.md | `references/readme-guide.md` | Deployment-target-aware README for npm, CLI, Docker, serverless |
|
|
66
66
|
|
|
67
67
|
## Recommended Reading Order
|
|
68
68
|
|
package/catalog/frontmcp-setup/examples/project-structure-standalone/feature-folder-organization.md
CHANGED
|
@@ -19,8 +19,7 @@ Organize a growing standalone project into domain-specific feature folders inste
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/billing/create-invoice.tool.ts
|
|
22
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
23
|
-
import { z } from 'zod';
|
|
22
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
24
23
|
|
|
25
24
|
@Tool({
|
|
26
25
|
name: 'create_invoice',
|
|
@@ -71,9 +70,10 @@ export class BillingProvider {
|
|
|
71
70
|
```typescript
|
|
72
71
|
// src/my-app.app.ts
|
|
73
72
|
import { App } from '@frontmcp/sdk';
|
|
73
|
+
|
|
74
|
+
import { BillingProvider } from './billing/billing.provider';
|
|
74
75
|
import CreateInvoiceTool from './billing/create-invoice.tool';
|
|
75
76
|
import InvoiceResource from './billing/invoice.resource';
|
|
76
|
-
import { BillingProvider } from './billing/billing.provider';
|
|
77
77
|
|
|
78
78
|
@App({
|
|
79
79
|
name: 'my-app',
|
|
@@ -87,7 +87,9 @@ export class MyApp {}
|
|
|
87
87
|
```typescript
|
|
88
88
|
// src/main.ts
|
|
89
89
|
import 'reflect-metadata';
|
|
90
|
+
|
|
90
91
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
92
|
+
|
|
91
93
|
import { MyApp } from './my-app.app';
|
|
92
94
|
|
|
93
95
|
@FrontMcp({
|
package/catalog/frontmcp-setup/examples/project-structure-standalone/minimal-standalone-layout.md
CHANGED
|
@@ -19,8 +19,7 @@ Set up the canonical file structure for a standalone FrontMCP project with one a
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/tools/fetch-weather.tool.ts
|
|
22
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
23
|
-
import { z } from 'zod';
|
|
22
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
24
23
|
|
|
25
24
|
@Tool({
|
|
26
25
|
name: 'fetch_weather',
|
|
@@ -37,6 +36,7 @@ export default class FetchWeatherTool extends ToolContext {
|
|
|
37
36
|
```typescript
|
|
38
37
|
// src/my-app.app.ts
|
|
39
38
|
import { App } from '@frontmcp/sdk';
|
|
39
|
+
|
|
40
40
|
import FetchWeatherTool from './tools/fetch-weather.tool';
|
|
41
41
|
|
|
42
42
|
@App({
|
|
@@ -49,7 +49,9 @@ export class MyApp {}
|
|
|
49
49
|
```typescript
|
|
50
50
|
// src/main.ts
|
|
51
51
|
import 'reflect-metadata';
|
|
52
|
+
|
|
52
53
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
54
|
+
|
|
53
55
|
import { MyApp } from './my-app.app';
|
|
54
56
|
|
|
55
57
|
@FrontMcp({
|
|
@@ -20,8 +20,7 @@ Scaffold a minimal FrontMCP server with one app and one tool, running on Node.js
|
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
22
|
// src/tools/add.tool.ts
|
|
23
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
24
|
-
import { z } from 'zod';
|
|
23
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
25
24
|
|
|
26
25
|
@Tool({
|
|
27
26
|
name: 'add',
|
|
@@ -41,6 +40,7 @@ export default class AddTool extends ToolContext {
|
|
|
41
40
|
```typescript
|
|
42
41
|
// src/apps/calc.app.ts
|
|
43
42
|
import { App } from '@frontmcp/sdk';
|
|
43
|
+
|
|
44
44
|
import AddTool from '../tools/add.tool';
|
|
45
45
|
|
|
46
46
|
@App({
|
|
@@ -53,7 +53,9 @@ export class CalcApp {}
|
|
|
53
53
|
```typescript
|
|
54
54
|
// src/main.ts
|
|
55
55
|
import 'reflect-metadata';
|
|
56
|
+
|
|
56
57
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
58
|
+
|
|
57
59
|
import { CalcApp } from './apps/calc.app';
|
|
58
60
|
|
|
59
61
|
@FrontMcp({
|
|
@@ -19,8 +19,7 @@ Configure a FrontMCP server for Vercel deployment with Vercel KV storage and mod
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/tools/lookup-user.tool.ts
|
|
22
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
23
|
-
import { z } from 'zod';
|
|
22
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
24
23
|
|
|
25
24
|
@Tool({
|
|
26
25
|
name: 'lookup_user',
|
|
@@ -37,6 +36,7 @@ export default class LookupUserTool extends ToolContext {
|
|
|
37
36
|
```typescript
|
|
38
37
|
// src/apps/users.app.ts
|
|
39
38
|
import { App } from '@frontmcp/sdk';
|
|
39
|
+
|
|
40
40
|
import LookupUserTool from '../tools/lookup-user.tool';
|
|
41
41
|
|
|
42
42
|
@App({
|
|
@@ -49,7 +49,9 @@ export class UsersApp {}
|
|
|
49
49
|
```typescript
|
|
50
50
|
// src/main.ts
|
|
51
51
|
import 'reflect-metadata';
|
|
52
|
+
|
|
52
53
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
54
|
+
|
|
53
55
|
import { UsersApp } from './apps/users.app';
|
|
54
56
|
|
|
55
57
|
@FrontMcp({
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
name: hybrid-vercel-kv-with-pubsub
|
|
3
3
|
reference: setup-redis
|
|
4
4
|
level: advanced
|
|
5
|
-
description: 'Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions.'
|
|
5
|
+
description: 'Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions in distributed multi-instance deployments.'
|
|
6
6
|
tags: [setup, vercel-kv, redis, vercel, session, hybrid]
|
|
7
7
|
features:
|
|
8
8
|
- 'Vercel KV handles sessions (`redis` config) while a real Redis handles pub/sub (`pubsub` config)'
|
|
9
|
-
- 'Vercel KV does not support pub/sub operations, so a separate Redis instance is required'
|
|
10
|
-
- '
|
|
9
|
+
- 'Vercel KV does not support pub/sub operations, so a separate Redis instance is required for distributed setups'
|
|
10
|
+
- 'Resource subscriptions across multiple server instances rely on the `pubsub` config for cross-instance notifications (single-instance servers use in-memory subscriptions automatically)'
|
|
11
11
|
- "The `pubsub` field accepts `provider: 'redis'` only (no Vercel KV support)"
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Hybrid Vercel KV with Redis Pub/Sub
|
|
15
15
|
|
|
16
|
-
Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions.
|
|
16
|
+
Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions in distributed multi-instance deployments.
|
|
17
|
+
|
|
18
|
+
> **Note:** Single-server deployments (stdio, binary, or single-instance HTTP) do not need pub/sub — resource subscriptions work in-memory out of the box.
|
|
17
19
|
|
|
18
20
|
## Code
|
|
19
21
|
|
|
@@ -50,7 +52,6 @@ import { Resource, ResourceContext } from '@frontmcp/sdk';
|
|
|
50
52
|
uri: 'metrics://live',
|
|
51
53
|
name: 'Live Metrics',
|
|
52
54
|
mimeType: 'application/json',
|
|
53
|
-
subscribe: true,
|
|
54
55
|
})
|
|
55
56
|
export default class LiveMetricsResource extends ResourceContext {
|
|
56
57
|
async read() {
|
|
@@ -69,8 +70,8 @@ REDIS_PUBSUB_PASSWORD=secret
|
|
|
69
70
|
## What This Demonstrates
|
|
70
71
|
|
|
71
72
|
- Vercel KV handles sessions (`redis` config) while a real Redis handles pub/sub (`pubsub` config)
|
|
72
|
-
- Vercel KV does not support pub/sub operations, so a separate Redis instance is required
|
|
73
|
-
-
|
|
73
|
+
- Vercel KV does not support pub/sub operations, so a separate Redis instance is required for distributed setups
|
|
74
|
+
- Resource subscriptions across multiple server instances rely on the `pubsub` config for cross-instance notifications (single-instance servers use in-memory subscriptions automatically)
|
|
74
75
|
- The `pubsub` field accepts `provider: 'redis'` only (no Vercel KV support)
|
|
75
76
|
|
|
76
77
|
## Related
|
|
@@ -141,6 +141,7 @@ The `@FrontMcp` decorator accepts a `FrontMcpMetadata` object with these fields:
|
|
|
141
141
|
|
|
142
142
|
```typescript
|
|
143
143
|
import 'reflect-metadata';
|
|
144
|
+
|
|
144
145
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
145
146
|
|
|
146
147
|
@FrontMcp({
|
|
@@ -180,6 +181,7 @@ export default class Server {}
|
|
|
180
181
|
|
|
181
182
|
```typescript
|
|
182
183
|
import 'reflect-metadata';
|
|
184
|
+
|
|
183
185
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
184
186
|
|
|
185
187
|
@FrontMcp({
|
|
@@ -225,8 +227,7 @@ export default class Server {}
|
|
|
225
227
|
Create `src/tools/add.tool.ts`:
|
|
226
228
|
|
|
227
229
|
```typescript
|
|
228
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
229
|
-
import { z } from 'zod';
|
|
230
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
230
231
|
|
|
231
232
|
@Tool({
|
|
232
233
|
name: 'add',
|
|
@@ -249,6 +250,7 @@ Create `src/apps/calc.app.ts`:
|
|
|
249
250
|
|
|
250
251
|
```typescript
|
|
251
252
|
import { App } from '@frontmcp/sdk';
|
|
253
|
+
|
|
252
254
|
import AddTool from '../tools/add.tool';
|
|
253
255
|
|
|
254
256
|
@App({
|
|
@@ -276,7 +278,9 @@ Update `src/main.ts`:
|
|
|
276
278
|
|
|
277
279
|
```typescript
|
|
278
280
|
import 'reflect-metadata';
|
|
281
|
+
|
|
279
282
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
283
|
+
|
|
280
284
|
import { CalcApp } from './apps/calc.app';
|
|
281
285
|
|
|
282
286
|
@FrontMcp({
|
|
@@ -292,24 +296,21 @@ Resources, Prompts, and Skills follow the same decorator pattern:
|
|
|
292
296
|
|
|
293
297
|
```typescript
|
|
294
298
|
// Resource - returns MCP ReadResourceResult
|
|
295
|
-
|
|
299
|
+
// Prompt - returns MCP GetPromptResult
|
|
300
|
+
|
|
301
|
+
// Skill - compound capability with tools + instructions
|
|
302
|
+
import { Prompt, PromptContext, Resource, ResourceContext, Skill, SkillContext } from '@frontmcp/sdk';
|
|
296
303
|
|
|
297
304
|
@Resource({ uri: 'config://app', name: 'App Config', mimeType: 'application/json' })
|
|
298
305
|
export default class AppConfigResource extends ResourceContext {
|
|
299
306
|
/* ... */
|
|
300
307
|
}
|
|
301
308
|
|
|
302
|
-
// Prompt - returns MCP GetPromptResult
|
|
303
|
-
import { Prompt, PromptContext } from '@frontmcp/sdk';
|
|
304
|
-
|
|
305
309
|
@Prompt({ name: 'summarize', description: 'Summarize a document' })
|
|
306
310
|
export default class SummarizePrompt extends PromptContext {
|
|
307
311
|
/* ... */
|
|
308
312
|
}
|
|
309
313
|
|
|
310
|
-
// Skill - compound capability with tools + instructions
|
|
311
|
-
import { Skill, SkillContext } from '@frontmcp/sdk';
|
|
312
|
-
|
|
313
314
|
@Skill({ name: 'data-analysis', description: 'Analyze datasets' })
|
|
314
315
|
export default class DataAnalysisSkill extends SkillContext {
|
|
315
316
|
/* ... */
|
|
@@ -15,15 +15,16 @@ description: Provision and configure Redis or Vercel KV for session storage and
|
|
|
15
15
|
|
|
16
16
|
### Recommended
|
|
17
17
|
|
|
18
|
-
- Resource subscriptions with `subscribe: true`
|
|
18
|
+
- Resource subscriptions with `subscribe: true` across **multiple server instances** (distributed pub/sub)
|
|
19
19
|
- Auth sessions or elicitation state must persist across server restarts
|
|
20
20
|
- Distributed rate limiting is configured in the throttle guard
|
|
21
21
|
|
|
22
22
|
### Skip When
|
|
23
23
|
|
|
24
|
-
- Running a single-instance stdio-only server for local development -- use `setup-sqlite` or in-memory stores
|
|
24
|
+
- Running a single-instance stdio-only server for local development -- use `setup-sqlite` or in-memory stores (resource subscriptions work in-memory without Redis)
|
|
25
25
|
- Only need to configure session TTL and key prefix on an already-provisioned Redis -- use `configure-session`
|
|
26
26
|
- Deploying a read-only MCP server with no sessions, subscriptions, or stateful tools
|
|
27
|
+
- Using resource subscriptions on a single server instance -- subscriptions work in-memory out of the box
|
|
27
28
|
|
|
28
29
|
> **Decision:** Use this skill to provision and connect Redis (Docker, existing instance, or Vercel KV); use `configure-session` to tune session-specific options after Redis is available.
|
|
29
30
|
|
|
@@ -217,9 +218,11 @@ const sessionStore = createSessionStoreSync({
|
|
|
217
218
|
});
|
|
218
219
|
```
|
|
219
220
|
|
|
220
|
-
## Step 4 -- Pub/Sub for Resource Subscriptions
|
|
221
|
+
## Step 4 -- Pub/Sub for Resource Subscriptions (Multi-Instance Only)
|
|
221
222
|
|
|
222
|
-
|
|
223
|
+
> **Single-server note:** If you run a single server instance (stdio, binary, or single-instance HTTP), resource subscriptions work in-memory without any Redis or pub/sub configuration. Skip this step for local development and single-server deployments.
|
|
224
|
+
|
|
225
|
+
For **distributed multi-instance** deployments where subscription state must be shared across server instances, you need pub/sub. Pub/sub requires a real Redis instance -- Vercel KV does not support pub/sub operations.
|
|
223
226
|
|
|
224
227
|
For a hybrid setup (Vercel KV for sessions, Redis for pub/sub):
|
|
225
228
|
|
|
@@ -318,13 +321,13 @@ You should see session keys like `mcp:session:<session-id>`.
|
|
|
318
321
|
|
|
319
322
|
## Common Patterns
|
|
320
323
|
|
|
321
|
-
| Pattern | Correct | Incorrect | Why
|
|
322
|
-
| ---------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
|
|
323
|
-
| Redis provider field | `redis: { provider: 'redis', host: '...', port: 6379 }` | `redis: { host: '...', port: 6379 }` without `provider` | Both forms are type-safe (the SDK's `RedisOptions` union accepts both shapes), but explicit `provider: 'redis'` improves clarity and intent
|
|
324
|
-
| Environment variables | `host: process.env['REDIS_HOST'] ?? 'localhost'` | Hardcoding `host: 'redis.internal'` in source | Hardcoded values break across environments (dev, staging, prod); always read from env with a sensible fallback
|
|
325
|
-
| Vercel KV credentials | Let Vercel auto-inject `KV_REST_API_URL` and `KV_REST_API_TOKEN` | Manually setting KV tokens in the `redis` config object | Auto-injection is safer and ensures tokens rotate correctly; manual values risk stale or committed secrets
|
|
326
|
-
| Docker persistence | `command: redis-server --appendonly yes` in docker-compose | Running Redis without `--appendonly` in development | Without AOF persistence, data is lost on container restart; `--appendonly yes` preserves data across restarts
|
|
327
|
-
| Pub/sub with Vercel KV | Separate `pubsub: { provider: 'redis', ... }` alongside `redis: { provider: 'vercel-kv' }` | Expecting Vercel KV to handle pub/sub | Vercel KV does not support pub/sub; a real Redis instance is required for resource subscriptions
|
|
324
|
+
| Pattern | Correct | Incorrect | Why |
|
|
325
|
+
| ---------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
326
|
+
| Redis provider field | `redis: { provider: 'redis', host: '...', port: 6379 }` | `redis: { host: '...', port: 6379 }` without `provider` | Both forms are type-safe (the SDK's `RedisOptions` union accepts both shapes), but explicit `provider: 'redis'` improves clarity and intent |
|
|
327
|
+
| Environment variables | `host: process.env['REDIS_HOST'] ?? 'localhost'` | Hardcoding `host: 'redis.internal'` in source | Hardcoded values break across environments (dev, staging, prod); always read from env with a sensible fallback |
|
|
328
|
+
| Vercel KV credentials | Let Vercel auto-inject `KV_REST_API_URL` and `KV_REST_API_TOKEN` | Manually setting KV tokens in the `redis` config object | Auto-injection is safer and ensures tokens rotate correctly; manual values risk stale or committed secrets |
|
|
329
|
+
| Docker persistence | `command: redis-server --appendonly yes` in docker-compose | Running Redis without `--appendonly` in development | Without AOF persistence, data is lost on container restart; `--appendonly yes` preserves data across restarts |
|
|
330
|
+
| Pub/sub with Vercel KV | Separate `pubsub: { provider: 'redis', ... }` alongside `redis: { provider: 'vercel-kv' }` | Expecting Vercel KV to handle pub/sub | Vercel KV does not support pub/sub; a real Redis instance is required for distributed resource subscriptions (single-instance servers use in-memory subscriptions and do not need pub/sub) |
|
|
328
331
|
|
|
329
332
|
## Verification Checklist
|
|
330
333
|
|
|
@@ -359,11 +362,11 @@ You should see session keys like `mcp:session:<session-id>`.
|
|
|
359
362
|
|
|
360
363
|
## Examples
|
|
361
364
|
|
|
362
|
-
| Example | Level | Description
|
|
363
|
-
| ----------------------------------------------------------------------------------------- | ------------ |
|
|
364
|
-
| [`docker-redis-local-dev`](../examples/setup-redis/docker-redis-local-dev.md) | Basic | Provision Redis with Docker Compose and connect a FrontMCP server for local session storage.
|
|
365
|
-
| [`hybrid-vercel-kv-with-pubsub`](../examples/setup-redis/hybrid-vercel-kv-with-pubsub.md) | Advanced | Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions. |
|
|
366
|
-
| [`vercel-kv-serverless`](../examples/setup-redis/vercel-kv-serverless.md) | Intermediate | Configure a FrontMCP server with Vercel KV as the session store for serverless deployment.
|
|
365
|
+
| Example | Level | Description |
|
|
366
|
+
| ----------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
367
|
+
| [`docker-redis-local-dev`](../examples/setup-redis/docker-redis-local-dev.md) | Basic | Provision Redis with Docker Compose and connect a FrontMCP server for local session storage. |
|
|
368
|
+
| [`hybrid-vercel-kv-with-pubsub`](../examples/setup-redis/hybrid-vercel-kv-with-pubsub.md) | Advanced | Use Vercel KV for session storage and a separate Redis instance for pub/sub resource subscriptions in distributed multi-instance deployments. |
|
|
369
|
+
| [`vercel-kv-serverless`](../examples/setup-redis/vercel-kv-serverless.md) | Intermediate | Configure a FrontMCP server with Vercel KV as the session store for serverless deployment. |
|
|
367
370
|
|
|
368
371
|
> See all examples in [`examples/setup-redis/`](../examples/setup-redis/)
|
|
369
372
|
|
|
@@ -19,9 +19,7 @@ Test tools in-memory without any HTTP overhead using the `create()` function fro
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/__tests__/direct-client.spec.ts
|
|
22
|
-
import { create } from '@frontmcp/sdk';
|
|
23
|
-
import { tool } from '@frontmcp/sdk';
|
|
24
|
-
import { z } from 'zod';
|
|
22
|
+
import { create, tool, z } from '@frontmcp/sdk';
|
|
25
23
|
|
|
26
24
|
const AddTool = tool({
|
|
27
25
|
name: 'add',
|
|
@@ -19,9 +19,7 @@ Verify that tools are returned in the correct format for OpenAI and Claude clien
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/__tests__/client-formats.spec.ts
|
|
22
|
-
import { connectOpenAI } from '@frontmcp/sdk';
|
|
23
|
-
import { tool } from '@frontmcp/sdk';
|
|
24
|
-
import { z } from 'zod';
|
|
22
|
+
import { connectOpenAI, tool, z } from '@frontmcp/sdk';
|
|
25
23
|
|
|
26
24
|
const AddTool = tool({
|
|
27
25
|
name: 'add',
|
|
@@ -19,8 +19,8 @@ Validate that a tool's Zod input schema rejects invalid data before `execute()`
|
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
// src/tools/__tests__/add.tool.schema.spec.ts
|
|
22
|
-
import { z } from '
|
|
23
|
-
|
|
22
|
+
import { ToolContext, z } from '@frontmcp/sdk';
|
|
23
|
+
|
|
24
24
|
import { AddTool } from '../add.tool';
|
|
25
25
|
|
|
26
26
|
describe('AddTool schema validation', () => {
|
|
@@ -8,9 +8,7 @@ description: In-memory testing with create() and connectOpenAI/connectClaude wit
|
|
|
8
8
|
Uses `connect()` or `create()` for in-memory testing without HTTP overhead.
|
|
9
9
|
|
|
10
10
|
```typescript
|
|
11
|
-
import { create,
|
|
12
|
-
import { tool } from '@frontmcp/sdk';
|
|
13
|
-
import { z } from 'zod';
|
|
11
|
+
import { connectOpenAI, create, tool, z } from '@frontmcp/sdk';
|
|
14
12
|
|
|
15
13
|
const AddTool = tool({
|
|
16
14
|
name: 'add',
|
|
@@ -6,8 +6,8 @@ description: Unit test a ToolContext execute method with mock context, inputs, a
|
|
|
6
6
|
# Unit Testing a Tool
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
|
-
import { z } from '
|
|
10
|
-
|
|
9
|
+
import { ToolContext, z } from '@frontmcp/sdk';
|
|
10
|
+
|
|
11
11
|
import { AddTool } from '../tools/add.tool';
|
|
12
12
|
|
|
13
13
|
describe('AddTool', () => {
|