@frontmcp/skills 1.0.4 → 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/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/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-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 +325 -3
- package/package.json +1 -1
package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ha-kubernetes-3-replicas
|
|
3
|
+
reference: distributed-ha
|
|
4
|
+
level: intermediate
|
|
5
|
+
description: Deploy FrontMCP with 3 replicas, Redis, and automatic session failover on Kubernetes
|
|
6
|
+
tags: [ha, kubernetes, redis, distributed, session-takeover, heartbeat]
|
|
7
|
+
features:
|
|
8
|
+
- Configuring @FrontMcp with Redis for distributed deployment
|
|
9
|
+
- Kubernetes Deployment YAML with 3 replicas and readiness probes
|
|
10
|
+
- Verifying heartbeat keys and session takeover via redis-cli
|
|
11
|
+
- NGINX sticky sessions for session affinity
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# HA Kubernetes Deployment with 3 Replicas
|
|
15
|
+
|
|
16
|
+
Deploy FrontMCP with 3 replicas, Redis, and automatic session failover on Kubernetes
|
|
17
|
+
|
|
18
|
+
## Code
|
|
19
|
+
|
|
20
|
+
### Server Configuration
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// src/main.ts
|
|
24
|
+
import { App, FrontMcp, Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
25
|
+
|
|
26
|
+
@Tool({
|
|
27
|
+
name: 'echo',
|
|
28
|
+
description: 'Echo a message',
|
|
29
|
+
inputSchema: { message: z.string() },
|
|
30
|
+
})
|
|
31
|
+
class EchoTool extends ToolContext {
|
|
32
|
+
async execute(input: { message: string }) {
|
|
33
|
+
return { echo: input.message };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@App({ name: 'main', tools: [EchoTool] })
|
|
38
|
+
class MainApp {}
|
|
39
|
+
|
|
40
|
+
@FrontMcp({
|
|
41
|
+
info: { name: 'ha-demo', version: '1.0.0' },
|
|
42
|
+
apps: [MainApp],
|
|
43
|
+
redis: {
|
|
44
|
+
provider: 'redis',
|
|
45
|
+
host: process.env['REDIS_HOST'] || 'redis',
|
|
46
|
+
port: 6379,
|
|
47
|
+
},
|
|
48
|
+
transport: {
|
|
49
|
+
persistence: {
|
|
50
|
+
redis: {
|
|
51
|
+
provider: 'redis',
|
|
52
|
+
host: process.env['REDIS_HOST'] || 'redis',
|
|
53
|
+
port: 6379,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
class Server {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Config File
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// frontmcp.config.ts
|
|
65
|
+
import { defineConfig } from '@frontmcp/cli';
|
|
66
|
+
|
|
67
|
+
export default defineConfig({
|
|
68
|
+
name: 'ha-demo',
|
|
69
|
+
version: '1.0.0',
|
|
70
|
+
deployments: [
|
|
71
|
+
{
|
|
72
|
+
target: 'distributed',
|
|
73
|
+
ha: {
|
|
74
|
+
heartbeatIntervalMs: 10000,
|
|
75
|
+
heartbeatTtlMs: 30000,
|
|
76
|
+
},
|
|
77
|
+
server: {
|
|
78
|
+
headers: {
|
|
79
|
+
hsts: 'max-age=31536000',
|
|
80
|
+
contentTypeOptions: 'nosniff',
|
|
81
|
+
frameOptions: 'DENY',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Dockerfile
|
|
90
|
+
|
|
91
|
+
```dockerfile
|
|
92
|
+
FROM node:24-alpine AS builder
|
|
93
|
+
WORKDIR /app
|
|
94
|
+
COPY package.json yarn.lock ./
|
|
95
|
+
RUN yarn install --frozen-lockfile
|
|
96
|
+
COPY . .
|
|
97
|
+
RUN FRONTMCP_DEPLOYMENT_MODE=distributed npx frontmcp build --target distributed
|
|
98
|
+
|
|
99
|
+
FROM node:24-alpine
|
|
100
|
+
WORKDIR /app
|
|
101
|
+
ENV NODE_ENV=production
|
|
102
|
+
COPY --from=builder /app/dist/distributed ./dist
|
|
103
|
+
COPY --from=builder /app/package.json ./
|
|
104
|
+
RUN yarn install --frozen-lockfile --production && yarn cache clean
|
|
105
|
+
EXPOSE 3000
|
|
106
|
+
HEALTHCHECK --interval=15s --timeout=5s --retries=3 --start-period=10s \
|
|
107
|
+
CMD wget -qO- http://localhost:3000/healthz || exit 1
|
|
108
|
+
CMD ["node", "dist/main.js"]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Kubernetes Manifests
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
# k8s/deployment.yaml
|
|
115
|
+
apiVersion: apps/v1
|
|
116
|
+
kind: Deployment
|
|
117
|
+
metadata:
|
|
118
|
+
name: mcp-server
|
|
119
|
+
spec:
|
|
120
|
+
replicas: 3
|
|
121
|
+
selector:
|
|
122
|
+
matchLabels:
|
|
123
|
+
app: mcp-server
|
|
124
|
+
template:
|
|
125
|
+
metadata:
|
|
126
|
+
labels:
|
|
127
|
+
app: mcp-server
|
|
128
|
+
spec:
|
|
129
|
+
containers:
|
|
130
|
+
- name: mcp-server
|
|
131
|
+
image: my-registry/ha-demo:latest
|
|
132
|
+
env:
|
|
133
|
+
- name: FRONTMCP_DEPLOYMENT_MODE
|
|
134
|
+
value: distributed
|
|
135
|
+
- name: REDIS_HOST
|
|
136
|
+
value: redis
|
|
137
|
+
ports:
|
|
138
|
+
- containerPort: 3000
|
|
139
|
+
livenessProbe:
|
|
140
|
+
httpGet:
|
|
141
|
+
path: /healthz
|
|
142
|
+
port: 3000
|
|
143
|
+
initialDelaySeconds: 5
|
|
144
|
+
periodSeconds: 10
|
|
145
|
+
readinessProbe:
|
|
146
|
+
httpGet:
|
|
147
|
+
path: /readyz
|
|
148
|
+
port: 3000
|
|
149
|
+
initialDelaySeconds: 10
|
|
150
|
+
periodSeconds: 15
|
|
151
|
+
---
|
|
152
|
+
apiVersion: v1
|
|
153
|
+
kind: Service
|
|
154
|
+
metadata:
|
|
155
|
+
name: mcp-server
|
|
156
|
+
spec:
|
|
157
|
+
selector:
|
|
158
|
+
app: mcp-server
|
|
159
|
+
ports:
|
|
160
|
+
- port: 3000
|
|
161
|
+
targetPort: 3000
|
|
162
|
+
---
|
|
163
|
+
apiVersion: apps/v1
|
|
164
|
+
kind: Deployment
|
|
165
|
+
metadata:
|
|
166
|
+
name: redis
|
|
167
|
+
spec:
|
|
168
|
+
replicas: 1
|
|
169
|
+
selector:
|
|
170
|
+
matchLabels:
|
|
171
|
+
app: redis
|
|
172
|
+
template:
|
|
173
|
+
metadata:
|
|
174
|
+
labels:
|
|
175
|
+
app: redis
|
|
176
|
+
spec:
|
|
177
|
+
containers:
|
|
178
|
+
- name: redis
|
|
179
|
+
image: redis:7-alpine
|
|
180
|
+
ports:
|
|
181
|
+
- containerPort: 6379
|
|
182
|
+
---
|
|
183
|
+
apiVersion: v1
|
|
184
|
+
kind: Service
|
|
185
|
+
metadata:
|
|
186
|
+
name: redis
|
|
187
|
+
spec:
|
|
188
|
+
selector:
|
|
189
|
+
app: redis
|
|
190
|
+
ports:
|
|
191
|
+
- port: 6379
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Verification
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Deploy
|
|
198
|
+
kubectl apply -f k8s/
|
|
199
|
+
|
|
200
|
+
# Check pods
|
|
201
|
+
kubectl get pods -l app=mcp-server
|
|
202
|
+
# NAME READY STATUS RESTARTS
|
|
203
|
+
# mcp-server-7b8f9-abc12 1/1 Running 0
|
|
204
|
+
# mcp-server-7b8f9-def34 1/1 Running 0
|
|
205
|
+
# mcp-server-7b8f9-ghi56 1/1 Running 0
|
|
206
|
+
|
|
207
|
+
# Check heartbeat keys in Redis
|
|
208
|
+
kubectl exec -it deploy/redis -- redis-cli KEYS "mcp:ha:heartbeat:*"
|
|
209
|
+
# 1) "mcp:ha:heartbeat:mcp-server-7b8f9-abc12"
|
|
210
|
+
# 2) "mcp:ha:heartbeat:mcp-server-7b8f9-def34"
|
|
211
|
+
# 3) "mcp:ha:heartbeat:mcp-server-7b8f9-ghi56"
|
|
212
|
+
|
|
213
|
+
# Kill a pod and watch takeover
|
|
214
|
+
kubectl delete pod mcp-server-7b8f9-abc12
|
|
215
|
+
# After ~30s, its heartbeat expires and sessions are claimed by surviving pods
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## What This Demonstrates
|
|
219
|
+
|
|
220
|
+
- Configuring @FrontMcp with Redis for distributed deployment
|
|
221
|
+
- Kubernetes Deployment YAML with 3 replicas and readiness probes
|
|
222
|
+
- Verifying heartbeat keys and session takeover via redis-cli
|
|
223
|
+
- NGINX sticky sessions for session affinity
|
|
224
|
+
|
|
225
|
+
## Related
|
|
226
|
+
|
|
227
|
+
- See `distributed-ha` for the full HA architecture reference
|
|
228
|
+
- See `deploy-to-node` for single-pod Docker deployment
|
|
229
|
+
- See `frontmcp-config` for configuration file options
|
package/catalog/frontmcp-production-readiness/examples/production-browser/cross-platform-crypto.md
CHANGED
|
@@ -20,10 +20,9 @@ Shows how to use `@frontmcp/utils` for cross-platform crypto operations that wor
|
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
22
|
// src/tools/browser-safe-hash.tool.ts
|
|
23
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
24
|
-
import { z } from 'zod';
|
|
23
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
25
24
|
// @frontmcp/utils wraps Web Crypto API — works in browsers
|
|
26
|
-
import {
|
|
25
|
+
import { randomUUID, sha256Base64url, sha256Hex } from '@frontmcp/utils';
|
|
27
26
|
|
|
28
27
|
@Tool({
|
|
29
28
|
name: 'hash_data',
|
|
@@ -46,8 +46,7 @@ new_classes = ["RateLimiterDO"]
|
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
48
|
// src/tools/rate-limited-action.tool.ts
|
|
49
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
50
|
-
import { z } from 'zod';
|
|
49
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
51
50
|
|
|
52
51
|
@Tool({
|
|
53
52
|
name: 'rate_limited_action',
|
|
@@ -85,8 +84,7 @@ export class RateLimitedActionTool extends ToolContext {
|
|
|
85
84
|
|
|
86
85
|
```typescript
|
|
87
86
|
// src/tools/file-upload.tool.ts
|
|
88
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
89
|
-
import { z } from 'zod';
|
|
87
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
90
88
|
|
|
91
89
|
@Tool({
|
|
92
90
|
name: 'upload_file',
|
|
@@ -20,10 +20,9 @@ Shows how to write tools that are compatible with the Cloudflare Workers runtime
|
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
22
|
// src/tools/worker-safe.tool.ts
|
|
23
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
24
|
-
import { z } from 'zod';
|
|
23
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
25
24
|
// Use @frontmcp/utils — wraps Web Crypto API, works in Workers
|
|
26
|
-
import {
|
|
25
|
+
import { base64urlEncode, randomUUID, sha256Hex } from '@frontmcp/utils';
|
|
27
26
|
|
|
28
27
|
@Tool({
|
|
29
28
|
name: 'transform_data',
|
|
@@ -60,8 +60,8 @@ export class DbConnectionProvider {
|
|
|
60
60
|
|
|
61
61
|
```typescript
|
|
62
62
|
// src/tools/optimized-query.tool.ts
|
|
63
|
-
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
64
|
-
|
|
63
|
+
import { Tool, ToolContext, z } from '@frontmcp/sdk';
|
|
64
|
+
|
|
65
65
|
import { DB_CLIENT } from '../providers/db-connection.provider';
|
|
66
66
|
|
|
67
67
|
@Tool({
|
|
@@ -96,6 +96,7 @@ export class OptimizedQueryTool extends ToolContext {
|
|
|
96
96
|
```typescript
|
|
97
97
|
// src/main.ts
|
|
98
98
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
99
|
+
|
|
99
100
|
// Only import lightweight modules at the top level
|
|
100
101
|
// Heavy imports happen lazily in providers
|
|
101
102
|
import { MyApp } from './my.app';
|
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({
|