@frontmcp/skills 0.0.1 → 1.0.0-beta.11
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 +58 -13
- package/catalog/frontmcp-config/SKILL.md +156 -0
- package/catalog/{auth/configure-auth/references/auth-modes.md → frontmcp-config/references/configure-auth-modes.md} +5 -0
- package/catalog/frontmcp-config/references/configure-auth.md +243 -0
- package/catalog/frontmcp-config/references/configure-elicitation.md +183 -0
- package/catalog/frontmcp-config/references/configure-http.md +210 -0
- package/catalog/frontmcp-config/references/configure-session.md +210 -0
- package/catalog/{config/configure-throttle/references/guard-config.md → frontmcp-config/references/configure-throttle-guard-config.md} +5 -0
- package/catalog/frontmcp-config/references/configure-throttle.md +234 -0
- package/catalog/{config/configure-transport/references/protocol-presets.md → frontmcp-config/references/configure-transport-protocol-presets.md} +5 -0
- package/catalog/frontmcp-config/references/configure-transport.md +200 -0
- package/catalog/frontmcp-config/references/setup-redis.md +9 -0
- package/catalog/frontmcp-config/references/setup-sqlite.md +9 -0
- package/catalog/frontmcp-deployment/SKILL.md +152 -0
- package/catalog/frontmcp-deployment/references/build-for-browser.md +143 -0
- package/catalog/frontmcp-deployment/references/build-for-cli.md +191 -0
- package/catalog/{deployment/build-for-sdk/SKILL.md → frontmcp-deployment/references/build-for-sdk.md} +66 -20
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +218 -0
- package/catalog/{deployment/deploy-to-lambda/SKILL.md → frontmcp-deployment/references/deploy-to-lambda.md} +77 -59
- package/catalog/{deployment/deploy-to-node/references/Dockerfile.example → frontmcp-deployment/references/deploy-to-node-dockerfile.md} +18 -4
- package/catalog/{deployment/deploy-to-node/SKILL.md → frontmcp-deployment/references/deploy-to-node.md} +69 -36
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +65 -0
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +229 -0
- package/catalog/frontmcp-development/SKILL.md +126 -0
- package/catalog/frontmcp-development/references/create-adapter.md +170 -0
- package/catalog/{development/create-agent/references/llm-config.md → frontmcp-development/references/create-agent-llm-config.md} +10 -5
- package/catalog/{development/create-agent/SKILL.md → frontmcp-development/references/create-agent.md} +83 -40
- package/catalog/{development/create-job/SKILL.md → frontmcp-development/references/create-job.md} +62 -15
- package/catalog/{plugins/create-plugin-hooks/SKILL.md → frontmcp-development/references/create-plugin-hooks.md} +100 -7
- package/catalog/frontmcp-development/references/create-plugin.md +506 -0
- package/catalog/{development/create-prompt/SKILL.md → frontmcp-development/references/create-prompt.md} +65 -22
- package/catalog/{development/create-provider/SKILL.md → frontmcp-development/references/create-provider.md} +63 -23
- package/catalog/{development/create-resource/SKILL.md → frontmcp-development/references/create-resource.md} +148 -26
- package/catalog/{development/create-skill-with-tools/SKILL.md → frontmcp-development/references/create-skill-with-tools.md} +174 -20
- package/catalog/{development/create-skill/SKILL.md → frontmcp-development/references/create-skill.md} +114 -28
- package/catalog/{development/create-tool/references/tool-annotations.md → frontmcp-development/references/create-tool-annotations.md} +5 -0
- package/catalog/{development/create-tool/references/output-schema-types.md → frontmcp-development/references/create-tool-output-schema-types.md} +5 -0
- package/catalog/{development/create-tool/SKILL.md → frontmcp-development/references/create-tool.md} +172 -23
- package/catalog/{development/create-workflow/SKILL.md → frontmcp-development/references/create-workflow.md} +61 -14
- package/catalog/frontmcp-development/references/decorators-guide.md +754 -0
- package/catalog/frontmcp-development/references/official-adapters.md +199 -0
- package/catalog/{plugins/official-plugins/SKILL.md → frontmcp-development/references/official-plugins.md} +97 -27
- package/catalog/frontmcp-extensibility/SKILL.md +103 -0
- package/catalog/frontmcp-extensibility/references/vectoriadb.md +289 -0
- package/catalog/frontmcp-guides/SKILL.md +420 -0
- package/catalog/frontmcp-guides/references/example-knowledge-base.md +641 -0
- package/catalog/frontmcp-guides/references/example-task-manager.md +517 -0
- package/catalog/frontmcp-guides/references/example-weather-api.md +297 -0
- package/catalog/frontmcp-production-readiness/SKILL.md +98 -0
- package/catalog/frontmcp-production-readiness/references/common-checklist.md +156 -0
- package/catalog/frontmcp-production-readiness/references/production-browser.md +46 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-binary.md +62 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +61 -0
- package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +52 -0
- package/catalog/frontmcp-production-readiness/references/production-lambda.md +53 -0
- package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +66 -0
- package/catalog/frontmcp-production-readiness/references/production-node-server.md +61 -0
- package/catalog/frontmcp-production-readiness/references/production-vercel.md +52 -0
- package/catalog/frontmcp-setup/SKILL.md +132 -0
- package/catalog/frontmcp-setup/references/frontmcp-skills-usage.md +280 -0
- package/catalog/{setup/multi-app-composition/SKILL.md → frontmcp-setup/references/multi-app-composition.md} +66 -19
- package/catalog/{setup/nx-workflow/SKILL.md → frontmcp-setup/references/nx-workflow.md} +79 -17
- package/catalog/frontmcp-setup/references/project-structure-nx.md +251 -0
- package/catalog/frontmcp-setup/references/project-structure-standalone.md +217 -0
- package/catalog/frontmcp-setup/references/readme-guide.md +226 -0
- package/catalog/{setup/setup-project/SKILL.md → frontmcp-setup/references/setup-project.md} +63 -58
- package/catalog/{setup/setup-redis/SKILL.md → frontmcp-setup/references/setup-redis.md} +60 -82
- package/catalog/{setup/setup-sqlite/SKILL.md → frontmcp-setup/references/setup-sqlite.md} +65 -72
- package/catalog/frontmcp-testing/SKILL.md +135 -0
- package/catalog/{testing/setup-testing/SKILL.md → frontmcp-testing/references/setup-testing.md} +79 -63
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-auth.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-browser-build.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-cli-binary.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-direct-client.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-e2e-handler.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-tool-unit.md +6 -0
- package/catalog/skills-manifest.json +337 -382
- 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 +15 -3
- package/src/manifest.js +3 -3
- package/src/manifest.js.map +1 -1
- package/catalog/adapters/create-adapter/SKILL.md +0 -127
- package/catalog/adapters/official-adapters/SKILL.md +0 -136
- package/catalog/auth/configure-auth/SKILL.md +0 -250
- package/catalog/auth/configure-session/SKILL.md +0 -201
- package/catalog/config/configure-elicitation/SKILL.md +0 -136
- package/catalog/config/configure-http/SKILL.md +0 -167
- package/catalog/config/configure-throttle/SKILL.md +0 -189
- package/catalog/config/configure-transport/SKILL.md +0 -151
- package/catalog/deployment/build-for-browser/SKILL.md +0 -95
- package/catalog/deployment/build-for-cli/SKILL.md +0 -100
- package/catalog/deployment/deploy-to-cloudflare/SKILL.md +0 -192
- package/catalog/deployment/deploy-to-vercel/SKILL.md +0 -196
- package/catalog/deployment/deploy-to-vercel/references/vercel.json.example +0 -60
- package/catalog/development/decorators-guide/SKILL.md +0 -598
- package/catalog/plugins/create-plugin/SKILL.md +0 -336
- package/catalog/setup/frontmcp-skills-usage/SKILL.md +0 -200
- package/catalog/setup/project-structure-nx/SKILL.md +0 -186
- package/catalog/setup/project-structure-standalone/SKILL.md +0 -153
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configure-elicitation
|
|
3
|
+
description: Configure interactive user input during tool execution for confirmations, choices, and forms
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configuring Elicitation
|
|
7
|
+
|
|
8
|
+
Elicitation allows tools to request interactive input from users mid-execution — confirmations, choices, or structured form data.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
### Must Use
|
|
13
|
+
|
|
14
|
+
- Tools need user confirmation before destructive actions (delete, deploy, overwrite)
|
|
15
|
+
- Building interactive multi-step workflows that require user decisions mid-execution
|
|
16
|
+
- Tools need structured form input from the user during execution (e.g., parameter selection, file choice)
|
|
17
|
+
|
|
18
|
+
### Recommended
|
|
19
|
+
|
|
20
|
+
- Adding a safety gate to tools that modify external systems (databases, APIs, deployments)
|
|
21
|
+
- Implementing approval flows where a tool must get explicit consent before proceeding
|
|
22
|
+
- Multi-instance production deployments where elicitation state must be shared via Redis
|
|
23
|
+
|
|
24
|
+
### Skip When
|
|
25
|
+
|
|
26
|
+
- Tools are fully autonomous and never need user input -- elicitation adds overhead when unused
|
|
27
|
+
- The MCP client does not support elicitation -- check client capabilities first (see Notes section)
|
|
28
|
+
- Only need input validation, not mid-execution prompts -- use Zod input schemas on the `@Tool` decorator
|
|
29
|
+
|
|
30
|
+
> **Decision:** Use this skill when tools need to pause execution and request interactive input from the user; skip if all tools run autonomously without user interaction.
|
|
31
|
+
|
|
32
|
+
## Enable Elicitation
|
|
33
|
+
|
|
34
|
+
### Basic (In-Memory)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
@FrontMcp({
|
|
38
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
39
|
+
apps: [MyApp],
|
|
40
|
+
elicitation: {
|
|
41
|
+
enabled: true,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
class Server {}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With Redis (Distributed/Production)
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
@FrontMcp({
|
|
51
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
52
|
+
apps: [MyApp],
|
|
53
|
+
elicitation: {
|
|
54
|
+
enabled: true,
|
|
55
|
+
redis: { provider: 'redis', host: 'localhost', port: 6379 },
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
class Server {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## ElicitationOptionsInput
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
interface ElicitationOptionsInput {
|
|
65
|
+
enabled?: boolean; // default: false
|
|
66
|
+
redis?: RedisOptionsInput; // storage for elicitation state
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Using Elicitation in Tools
|
|
71
|
+
|
|
72
|
+
When elicitation is enabled, tools can request user input via the MCP elicitation protocol:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
76
|
+
import { z } from 'zod';
|
|
77
|
+
|
|
78
|
+
@Tool({
|
|
79
|
+
name: 'delete_records',
|
|
80
|
+
description: 'Delete records from the database',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
table: z.string(),
|
|
83
|
+
filter: z.string(),
|
|
84
|
+
},
|
|
85
|
+
outputSchema: { deleted: z.number() },
|
|
86
|
+
})
|
|
87
|
+
class DeleteRecordsTool extends ToolContext {
|
|
88
|
+
async execute(input: { table: string; filter: string }) {
|
|
89
|
+
// Count records that would be deleted
|
|
90
|
+
const db = this.get(DB_TOKEN);
|
|
91
|
+
const count = await db.count(input.table, input.filter);
|
|
92
|
+
|
|
93
|
+
// Request confirmation from user before proceeding
|
|
94
|
+
const confirmation = await this.elicit({
|
|
95
|
+
message: `This will delete ${count} records from ${input.table}. Are you sure?`,
|
|
96
|
+
requestedSchema: {
|
|
97
|
+
type: 'object',
|
|
98
|
+
properties: {
|
|
99
|
+
confirmed: { type: 'boolean', description: 'Confirm deletion' },
|
|
100
|
+
},
|
|
101
|
+
required: ['confirmed'],
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!confirmation || !confirmation.confirmed) {
|
|
106
|
+
return { deleted: 0 };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const deleted = await db.delete(input.table, input.filter);
|
|
110
|
+
return { deleted };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## How It Works
|
|
116
|
+
|
|
117
|
+
1. Tool calls `this.elicit()` with a message and requested schema
|
|
118
|
+
2. Server sends an `elicitation/request` to the client
|
|
119
|
+
3. Client displays the request to the user (UI varies by client)
|
|
120
|
+
4. User responds with structured data matching the schema
|
|
121
|
+
5. `this.elicit()` returns the user's response
|
|
122
|
+
6. Tool continues execution with the response
|
|
123
|
+
|
|
124
|
+
## Notes
|
|
125
|
+
|
|
126
|
+
- When `enabled: false` (default), `this.elicit()` is not available — keeps resource overhead low
|
|
127
|
+
- When enabled, tool output schemas are automatically extended with elicitation fallback type
|
|
128
|
+
- Use Redis storage for production/multi-instance deployments
|
|
129
|
+
- Not all MCP clients support elicitation — handle gracefully when `this.elicit()` returns `undefined`
|
|
130
|
+
|
|
131
|
+
## Verification
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Enable elicitation and start
|
|
135
|
+
frontmcp dev
|
|
136
|
+
|
|
137
|
+
# Test with an MCP client that supports elicitation
|
|
138
|
+
# The tool should pause and request user input
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Common Patterns
|
|
142
|
+
|
|
143
|
+
| Pattern | Correct | Incorrect | Why |
|
|
144
|
+
| ---------------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
145
|
+
| Handling unsupported clients | Check `if (!confirmation)` after `this.elicit()` and provide a fallback | Assuming `this.elicit()` always returns a value | Not all MCP clients support elicitation; `undefined` is returned when the client cannot handle the request |
|
|
146
|
+
| Schema for confirmation | Use `{ confirmed: { type: 'boolean' } }` in `requestedSchema` | Using a plain string prompt without a schema | Structured schemas let the client render proper UI controls (checkboxes, dropdowns) instead of free-text input |
|
|
147
|
+
| Redis for production | Set `elicitation: { enabled: true, redis: { provider: 'redis', ... } }` | Using in-memory elicitation state in a multi-instance deployment | In-memory state is per-process; if the response arrives at a different instance, the elicitation context is lost |
|
|
148
|
+
| Enabled flag | Explicitly set `elicitation: { enabled: true }` | Omitting the `enabled` field and expecting elicitation to work | Elicitation is disabled by default (`enabled: false`) to minimize resource overhead |
|
|
149
|
+
|
|
150
|
+
## Verification Checklist
|
|
151
|
+
|
|
152
|
+
### Configuration
|
|
153
|
+
|
|
154
|
+
- [ ] `elicitation.enabled` is set to `true` in the `@FrontMcp` decorator
|
|
155
|
+
- [ ] For production/multi-instance: `elicitation.redis` is configured with a valid Redis provider
|
|
156
|
+
- [ ] The `requestedSchema` in `this.elicit()` calls uses valid JSON Schema objects
|
|
157
|
+
|
|
158
|
+
### Runtime
|
|
159
|
+
|
|
160
|
+
- [ ] Tool execution pauses when `this.elicit()` is called and the client supports elicitation
|
|
161
|
+
- [ ] The user sees a prompt or form matching the requested schema
|
|
162
|
+
- [ ] After the user responds, `this.elicit()` returns the structured data and the tool resumes
|
|
163
|
+
- [ ] When the client does not support elicitation, `this.elicit()` returns `undefined` and the tool handles the fallback gracefully
|
|
164
|
+
|
|
165
|
+
### Integration
|
|
166
|
+
|
|
167
|
+
- [ ] MCP client under test advertises elicitation support in its capabilities
|
|
168
|
+
- [ ] Destructive tools have elicitation-based confirmation gates before proceeding
|
|
169
|
+
|
|
170
|
+
## Troubleshooting
|
|
171
|
+
|
|
172
|
+
| Problem | Cause | Solution |
|
|
173
|
+
| ------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
174
|
+
| `this.elicit is not a function` | Elicitation is not enabled in the server configuration | Set `elicitation: { enabled: true }` in the `@FrontMcp` decorator |
|
|
175
|
+
| `this.elicit()` returns `undefined` immediately | The connected MCP client does not support elicitation | Check client capabilities; provide a fallback code path for unsupported clients |
|
|
176
|
+
| Elicitation works locally but fails in production | In-memory store loses state across multiple server instances | Configure `elicitation.redis` to share elicitation state via Redis |
|
|
177
|
+
| User sees raw JSON instead of a form | The MCP client renders the `requestedSchema` as raw data rather than a form | Use standard JSON Schema types (`boolean`, `string`, `enum`) that clients can render as UI controls |
|
|
178
|
+
| Tool hangs indefinitely waiting for user response | No timeout configured and user never responds | Implement a timeout or cancellation mechanism in the tool logic to handle non-responsive users |
|
|
179
|
+
|
|
180
|
+
## Reference
|
|
181
|
+
|
|
182
|
+
- [Elicitation Docs](https://docs.agentfront.dev/frontmcp/servers/elicitation)
|
|
183
|
+
- Related skills: `configure-http`, `configure-transport`, `setup-redis`, `create-tool`
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configure-http
|
|
3
|
+
description: Configure HTTP server port, CORS policy, unix sockets, and entry path prefix
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configuring HTTP Options
|
|
7
|
+
|
|
8
|
+
Configure the HTTP server — port, CORS policy, unix sockets, and entry path prefix.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
### Must Use
|
|
13
|
+
|
|
14
|
+
- Changing the default HTTP port or binding to a specific network interface
|
|
15
|
+
- Enabling or restricting CORS for a frontend application that calls the MCP server
|
|
16
|
+
- Binding to a unix socket for local daemon or process-manager integrations
|
|
17
|
+
|
|
18
|
+
### Recommended
|
|
19
|
+
|
|
20
|
+
- Mounting the MCP server under a URL prefix behind a reverse proxy
|
|
21
|
+
- Setting a dynamic port from an environment variable for container deployments
|
|
22
|
+
- Fine-tuning CORS preflight caching for performance-sensitive frontends
|
|
23
|
+
|
|
24
|
+
### Skip When
|
|
25
|
+
|
|
26
|
+
- Using stdio transport only with no HTTP listener -- no HTTP options apply
|
|
27
|
+
- Only need rate limiting or IP filtering without changing HTTP binding -- use `configure-throttle`
|
|
28
|
+
- Need to configure TLS/HTTPS termination -- handle at the reverse proxy or load balancer level, not in FrontMCP
|
|
29
|
+
|
|
30
|
+
> **Decision:** Use this skill when you need to customize how the HTTP listener binds (port, socket, prefix) or how it handles CORS; skip if the default port 3001 with permissive CORS is sufficient.
|
|
31
|
+
|
|
32
|
+
## HttpOptionsInput
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
@FrontMcp({
|
|
36
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
37
|
+
apps: [MyApp],
|
|
38
|
+
http: {
|
|
39
|
+
port: 3001, // default: 3001
|
|
40
|
+
entryPath: '', // default: '' (root)
|
|
41
|
+
socketPath: undefined, // unix socket path (overrides port)
|
|
42
|
+
cors: {
|
|
43
|
+
// default: permissive (all origins)
|
|
44
|
+
origin: ['https://myapp.com'],
|
|
45
|
+
credentials: true,
|
|
46
|
+
maxAge: 86400,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
class Server {}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Port Configuration
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Default: port 3001
|
|
57
|
+
http: {
|
|
58
|
+
port: 3001;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Use environment variable
|
|
62
|
+
http: {
|
|
63
|
+
port: Number(process.env.PORT) || 3001;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Random port (useful for testing)
|
|
67
|
+
http: {
|
|
68
|
+
port: 0;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## CORS Configuration
|
|
73
|
+
|
|
74
|
+
### Permissive (Default)
|
|
75
|
+
|
|
76
|
+
When `cors` is not specified, the server allows all origins without credentials:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// All origins allowed (default behavior)
|
|
80
|
+
http: {
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Restrict to Specific Origins
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
http: {
|
|
88
|
+
cors: {
|
|
89
|
+
origin: ['https://myapp.com', 'https://staging.myapp.com'],
|
|
90
|
+
credentials: true,
|
|
91
|
+
maxAge: 86400, // Cache preflight for 24 hours
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Disable CORS Entirely
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
http: {
|
|
100
|
+
cors: false, // No CORS headers at all
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Dynamic Origin
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
http: {
|
|
108
|
+
cors: {
|
|
109
|
+
origin: (origin: string) => {
|
|
110
|
+
// Allow any *.myapp.com subdomain
|
|
111
|
+
return origin.endsWith('.myapp.com');
|
|
112
|
+
},
|
|
113
|
+
credentials: true,
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### CORS Fields
|
|
119
|
+
|
|
120
|
+
| Field | Type | Default | Description |
|
|
121
|
+
| ------------- | ------------------------------------------- | ------------ | ---------------------------------- |
|
|
122
|
+
| `origin` | `boolean \| string \| string[] \| function` | `true` (all) | Allowed origins |
|
|
123
|
+
| `credentials` | `boolean` | `false` | Allow cookies/auth headers |
|
|
124
|
+
| `maxAge` | `number` | — | Preflight cache duration (seconds) |
|
|
125
|
+
|
|
126
|
+
## Entry Path Prefix
|
|
127
|
+
|
|
128
|
+
Mount the MCP server under a URL prefix:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
http: {
|
|
132
|
+
entryPath: '/api/mcp',
|
|
133
|
+
}
|
|
134
|
+
// Server endpoints become: /api/mcp/sse, /api/mcp/, etc.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Useful when running behind a reverse proxy or alongside other services.
|
|
138
|
+
|
|
139
|
+
## Unix Socket Mode
|
|
140
|
+
|
|
141
|
+
Bind to a unix socket instead of a TCP port for local-only access:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
http: {
|
|
145
|
+
socketPath: '/tmp/my-mcp-server.sock',
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- Mutually exclusive with `port` — if `socketPath` is set, `port` is ignored
|
|
150
|
+
- Use for local daemons, CLI tools, and process manager integrations
|
|
151
|
+
- Combine with `sqlite` for fully local deployments
|
|
152
|
+
|
|
153
|
+
## Verification
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Start with custom port
|
|
157
|
+
PORT=8080 frontmcp dev
|
|
158
|
+
|
|
159
|
+
# Test CORS
|
|
160
|
+
curl -v -H "Origin: https://myapp.com" http://localhost:8080/
|
|
161
|
+
|
|
162
|
+
# Test unix socket
|
|
163
|
+
curl --unix-socket /tmp/my-mcp-server.sock http://localhost/
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Common Patterns
|
|
167
|
+
|
|
168
|
+
| Pattern | Correct | Incorrect | Why |
|
|
169
|
+
| --------------------- | ------------------------------------------------------------ | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| Port from environment | `port: Number(process.env.PORT) \|\| 3001` | `port: process.env.PORT` | The `port` field expects a number; passing a string causes a silent bind failure |
|
|
171
|
+
| CORS with credentials | `cors: { origin: ['https://myapp.com'], credentials: true }` | `cors: { origin: true, credentials: true }` | Browsers reject `Access-Control-Allow-Origin: *` when credentials are enabled; you must list explicit origins |
|
|
172
|
+
| Unix socket mode | `socketPath: '/tmp/my-mcp.sock'` with no `port` field | Setting both `socketPath` and `port` | When `socketPath` is set, `port` is silently ignored which can cause confusion during debugging |
|
|
173
|
+
| Entry path prefix | `entryPath: '/api/mcp'` (no trailing slash) | `entryPath: '/api/mcp/'` with trailing slash | Trailing slashes cause double-slash issues in route matching (e.g., `/api/mcp//sse`) |
|
|
174
|
+
| Disabling CORS | `cors: false` | Omitting the `cors` field entirely | Omitting `cors` applies permissive defaults (all origins allowed); set `false` explicitly to send no CORS headers |
|
|
175
|
+
|
|
176
|
+
## Verification Checklist
|
|
177
|
+
|
|
178
|
+
### Configuration
|
|
179
|
+
|
|
180
|
+
- [ ] `http` block is present in the `@FrontMcp` decorator metadata
|
|
181
|
+
- [ ] Port value is a number (not a string) and falls within a valid range (0-65535)
|
|
182
|
+
- [ ] If `socketPath` is set, `port` is removed or commented out to avoid confusion
|
|
183
|
+
- [ ] `entryPath` does not have a trailing slash
|
|
184
|
+
|
|
185
|
+
### CORS
|
|
186
|
+
|
|
187
|
+
- [ ] If `credentials: true`, `origin` lists explicit allowed origins (not `true` or `*`)
|
|
188
|
+
- [ ] `maxAge` is set to a reasonable value for production (e.g., `86400` for 24 hours)
|
|
189
|
+
- [ ] Dynamic origin function handles `undefined` origin (non-browser requests)
|
|
190
|
+
|
|
191
|
+
### Runtime
|
|
192
|
+
|
|
193
|
+
- [ ] Server starts and binds to the expected port or socket path
|
|
194
|
+
- [ ] `curl -v -H "Origin: <your-origin>" <url>` returns correct `Access-Control-Allow-Origin`
|
|
195
|
+
- [ ] Preflight `OPTIONS` requests return `204` with expected CORS headers
|
|
196
|
+
|
|
197
|
+
## Troubleshooting
|
|
198
|
+
|
|
199
|
+
| Problem | Cause | Solution |
|
|
200
|
+
| ------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
|
|
201
|
+
| `EADDRINUSE` on startup | Another process is already using the configured port | Change the port, stop the other process, or use `port: 0` for a random available port |
|
|
202
|
+
| CORS errors in the browser console | Origin not included in the `cors.origin` list or `credentials: true` with wildcard origin | Add the frontend origin to the `origin` array and ensure credentials and origin settings are compatible |
|
|
203
|
+
| Unix socket file not created | Missing write permissions on the target directory or stale socket file from a previous run | Check directory permissions and remove the stale `.sock` file before restarting |
|
|
204
|
+
| Routes return 404 after setting `entryPath` | Client is still requesting the root path without the prefix | Update client base URL to include the entry path (e.g., `http://localhost:3001/api/mcp`) |
|
|
205
|
+
| Server binds but external clients cannot connect | Server bound to `localhost` or `127.0.0.1` inside a container | Set `host: '0.0.0.0'` or use Docker port mapping to expose the container port |
|
|
206
|
+
|
|
207
|
+
## Reference
|
|
208
|
+
|
|
209
|
+
- [HTTP Server Docs](https://docs.agentfront.dev/frontmcp/deployment/local-dev-server)
|
|
210
|
+
- Related skills: `configure-throttle`, `configure-transport`, `setup-redis`, `setup-project`
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configure-session
|
|
3
|
+
description: Set up session storage with Redis or Vercel KV for persistent user state across requests
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configure Session Management
|
|
7
|
+
|
|
8
|
+
This skill covers setting up session storage in FrontMCP. Sessions track authenticated user state, token storage, and request context across MCP interactions.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
### Must Use
|
|
13
|
+
|
|
14
|
+
- Deploying to production where sessions must survive process restarts (Redis or Vercel KV required)
|
|
15
|
+
- Running multiple server instances behind a load balancer that need shared session state
|
|
16
|
+
- Using Streamable HTTP transport where sessions must persist across reconnects
|
|
17
|
+
|
|
18
|
+
### Recommended
|
|
19
|
+
|
|
20
|
+
- Configuring session TTL to match your workload pattern (interactive, agent, CI/CD)
|
|
21
|
+
- Namespacing session keys with a unique `keyPrefix` when sharing a Redis instance across multiple servers
|
|
22
|
+
- Setting up Vercel KV for serverless deployments on the Vercel platform
|
|
23
|
+
|
|
24
|
+
### Skip When
|
|
25
|
+
|
|
26
|
+
- Running a single-instance local development server -- the default in-memory store is sufficient
|
|
27
|
+
- Using stdio transport only where session persistence is not needed
|
|
28
|
+
- Need to provision Redis itself rather than configure sessions -- use `setup-redis` first, then return here
|
|
29
|
+
|
|
30
|
+
> **Decision:** Use this skill to choose and configure a session storage provider (memory, Redis, or Vercel KV) and tune TTL and key prefix settings; use `setup-redis` if Redis is not yet provisioned.
|
|
31
|
+
|
|
32
|
+
## Storage Providers
|
|
33
|
+
|
|
34
|
+
| Provider | Use Case | Persistence | Package Required |
|
|
35
|
+
| ----------- | ------------------- | ----------- | ---------------- |
|
|
36
|
+
| `memory` | Development/testing | None | None (default) |
|
|
37
|
+
| `redis` | Node.js production | Yes | `ioredis` |
|
|
38
|
+
| `vercel-kv` | Vercel deployments | Yes | `@vercel/kv` |
|
|
39
|
+
|
|
40
|
+
Never use the memory store in production. Sessions are lost on process restart, which breaks authentication for all connected clients.
|
|
41
|
+
|
|
42
|
+
## Redis (Production)
|
|
43
|
+
|
|
44
|
+
Configure Redis session storage via the `@FrontMcp` decorator:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { FrontMcp, App } from '@frontmcp/sdk';
|
|
48
|
+
|
|
49
|
+
@App({ name: 'MyApp' })
|
|
50
|
+
class MyApp {}
|
|
51
|
+
|
|
52
|
+
@FrontMcp({
|
|
53
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
54
|
+
apps: [MyApp],
|
|
55
|
+
redis: {
|
|
56
|
+
provider: 'redis',
|
|
57
|
+
host: process.env['REDIS_HOST'] ?? 'localhost',
|
|
58
|
+
port: Number(process.env['REDIS_PORT'] ?? 6379),
|
|
59
|
+
password: process.env['REDIS_PASSWORD'],
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
class MyServer {}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The SDK internally calls `createSessionStore()` to create a `RedisSessionStore`. The factory lazy-loads `ioredis` so it is not bundled when you use a different provider.
|
|
66
|
+
|
|
67
|
+
## Vercel KV
|
|
68
|
+
|
|
69
|
+
For Vercel deployments, use the `vercel-kv` provider. Credentials are read from environment variables set automatically by the Vercel platform:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
@FrontMcp({
|
|
73
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
74
|
+
apps: [MyApp],
|
|
75
|
+
redis: { provider: 'vercel-kv' },
|
|
76
|
+
})
|
|
77
|
+
class MyServer {}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Required environment variables (auto-injected when a KV store is linked to your Vercel project):
|
|
81
|
+
|
|
82
|
+
| Variable | Description |
|
|
83
|
+
| ------------------- | ------------------------------ |
|
|
84
|
+
| `KV_REST_API_URL` | Vercel KV REST endpoint |
|
|
85
|
+
| `KV_REST_API_TOKEN` | Vercel KV authentication token |
|
|
86
|
+
|
|
87
|
+
## Memory (Development Default)
|
|
88
|
+
|
|
89
|
+
When no Redis or KV configuration is provided, the SDK falls back to an in-memory store. This is suitable only for development:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
@FrontMcp({
|
|
93
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
94
|
+
apps: [MyApp],
|
|
95
|
+
// No redis config -- defaults to memory
|
|
96
|
+
})
|
|
97
|
+
class MyServer {}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Key Prefix
|
|
101
|
+
|
|
102
|
+
All persistent stores support a `keyPrefix` option that namespaces session keys. This is important when multiple FrontMCP servers share the same Redis instance:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
@FrontMcp({
|
|
106
|
+
info: { name: 'billing-server', version: '1.0.0' },
|
|
107
|
+
apps: [MyApp],
|
|
108
|
+
redis: {
|
|
109
|
+
provider: 'redis',
|
|
110
|
+
host: 'shared-redis.internal',
|
|
111
|
+
port: 6379,
|
|
112
|
+
keyPrefix: 'billing-mcp:session:',
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
class BillingServer {}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use a unique prefix per server to prevent session key collisions.
|
|
119
|
+
|
|
120
|
+
## TTL Configuration
|
|
121
|
+
|
|
122
|
+
The `defaultTtlMs` option controls how long sessions live before expiring:
|
|
123
|
+
|
|
124
|
+
| Scenario | Recommended TTL |
|
|
125
|
+
| ---------------------------- | ----------------------- |
|
|
126
|
+
| Interactive user sessions | `3_600_000` (1 hour) |
|
|
127
|
+
| Long-running agent workflows | `86_400_000` (24 hours) |
|
|
128
|
+
| Short-lived CI/CD operations | `600_000` (10 minutes) |
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
@FrontMcp({
|
|
132
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
133
|
+
apps: [MyApp],
|
|
134
|
+
redis: {
|
|
135
|
+
provider: 'redis',
|
|
136
|
+
host: 'localhost',
|
|
137
|
+
port: 6379,
|
|
138
|
+
defaultTtlMs: 86_400_000, // 24 hours for agent workflows
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
class MyServer {}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Pub/Sub for Resource Subscriptions
|
|
145
|
+
|
|
146
|
+
If your server uses resource subscriptions (clients subscribe to resource change notifications), you need a pub/sub channel. Vercel KV does not support pub/sub, so you must use Redis for the pub/sub channel even when using Vercel KV for sessions:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { createSessionStore, createPubsubStore } from '@frontmcp/sdk/auth/session';
|
|
150
|
+
|
|
151
|
+
// Sessions in Vercel KV
|
|
152
|
+
const sessionStore = await createSessionStore({
|
|
153
|
+
provider: 'vercel-kv',
|
|
154
|
+
url: process.env['KV_REST_API_URL'],
|
|
155
|
+
token: process.env['KV_REST_API_TOKEN'],
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Pub/sub requires Redis
|
|
159
|
+
const pubsubStore = createPubsubStore({
|
|
160
|
+
provider: 'redis',
|
|
161
|
+
host: process.env['REDIS_HOST'] ?? 'localhost',
|
|
162
|
+
port: 6379,
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Common Patterns
|
|
167
|
+
|
|
168
|
+
| Pattern | Correct | Incorrect | Why |
|
|
169
|
+
| ---------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| Store construction | Use `createSessionStore()` factory function | `new RedisSessionStore(client)` direct construction | The factory handles lazy-loading, key prefix normalization, and provider detection automatically |
|
|
171
|
+
| Vercel KV creation | `const store = await createSessionStore({ provider: 'vercel-kv' })` | `const store = createSessionStore({ provider: 'vercel-kv' })` without `await` | The factory is async for Vercel KV; forgetting `await` uses the store before its connection is ready |
|
|
172
|
+
| Key prefix per server | `keyPrefix: 'billing-mcp:session:'` unique per server | Same `keyPrefix` across multiple servers sharing one Redis instance | Shared prefixes cause session key collisions; one server may read or overwrite another's sessions |
|
|
173
|
+
| Production storage | `redis: { provider: 'redis', host: '...' }` or `redis: { provider: 'vercel-kv' }` | Omitting redis config in production (falls back to memory) | Memory sessions vanish on restart; all connected clients must re-authenticate and in-flight workflows are lost |
|
|
174
|
+
| Pub/sub with Vercel KV | Separate `pubsub` config pointing to real Redis alongside `redis: { provider: 'vercel-kv' }` | Expecting Vercel KV to handle pub/sub | Vercel KV does not support pub/sub operations; a real Redis instance is required for resource subscriptions |
|
|
175
|
+
|
|
176
|
+
## Verification Checklist
|
|
177
|
+
|
|
178
|
+
### Configuration
|
|
179
|
+
|
|
180
|
+
- [ ] `redis` block is present in the `@FrontMcp` decorator with a valid `provider` field (`'redis'` or `'vercel-kv'`)
|
|
181
|
+
- [ ] `keyPrefix` is unique per server when sharing a Redis instance
|
|
182
|
+
- [ ] `defaultTtlMs` matches the workload pattern (1 hour for interactive, 24 hours for agents, 10 minutes for CI/CD)
|
|
183
|
+
|
|
184
|
+
### Vercel KV
|
|
185
|
+
|
|
186
|
+
- [ ] `provider: 'vercel-kv'` is set in the `redis` config
|
|
187
|
+
- [ ] `KV_REST_API_URL` and `KV_REST_API_TOKEN` environment variables are present (auto-injected on Vercel)
|
|
188
|
+
- [ ] A separate `pubsub` config pointing to real Redis is provided if resource subscriptions are used
|
|
189
|
+
|
|
190
|
+
### Runtime
|
|
191
|
+
|
|
192
|
+
- [ ] Server starts without Redis connection errors in the logs
|
|
193
|
+
- [ ] `redis-cli keys "mcp:session:*"` shows session keys after an MCP request (for Redis provider)
|
|
194
|
+
- [ ] Sessions persist across server restarts (for Redis/Vercel KV providers)
|
|
195
|
+
- [ ] Sessions expire after the configured TTL
|
|
196
|
+
|
|
197
|
+
## Troubleshooting
|
|
198
|
+
|
|
199
|
+
| Problem | Cause | Solution |
|
|
200
|
+
| -------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
201
|
+
| Sessions lost after server restart | Using the default in-memory store in production | Configure `redis: { provider: 'redis' }` or `redis: { provider: 'vercel-kv' }` for persistence |
|
|
202
|
+
| `ECONNREFUSED` on startup | Redis is not running or host/port is incorrect | Start the Redis container (`docker compose up -d redis`) or verify connection details |
|
|
203
|
+
| Vercel KV `401 Unauthorized` | Missing or invalid KV tokens | Check `KV_REST_API_URL` and `KV_REST_API_TOKEN` in the Vercel dashboard and redeploy |
|
|
204
|
+
| Session key collisions between servers | Multiple servers share the same Redis instance and `keyPrefix` | Set a unique `keyPrefix` per server (e.g., `billing-mcp:session:`, `api-mcp:session:`) |
|
|
205
|
+
| Pub/sub not working with Vercel KV | Vercel KV does not support pub/sub operations | Add a separate `pubsub` config pointing to a real Redis instance |
|
|
206
|
+
|
|
207
|
+
## Reference
|
|
208
|
+
|
|
209
|
+
- [Session Storage Docs](https://docs.agentfront.dev/frontmcp/deployment/redis-setup)
|
|
210
|
+
- Related skills: `setup-redis`, `configure-auth`, `configure-transport`, `configure-elicitation`
|