mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
docs(mcp): document MCP Tasks support (#21)
- README: add tasksMode YAML example and MCP Tasks subsection with SDK opt-in snippet - pkg/kit/README: add MCP Tasks subsection covering MCPTaskMode, progress callbacks, and List/Get/Cancel methods - www/configuration: document the tasksMode server field plus a per-mode behaviour table - www/sdk/options: extend the Compaction & MCP table with the six new Options fields and add a top-level MCP Tasks section - www/sdk/overview: add a brief MCP Tasks section between MCP prompts/resources and Context & compaction All examples verified against the public symbols in pkg/kit/mcp_tasks.go; docs site builds cleanly via npx tome build.
This commit is contained in:
@@ -162,6 +162,11 @@ mcpServers:
|
||||
type: remote
|
||||
url: "https://pubmed.mcp.example.com"
|
||||
noOAuth: true # skip OAuth for public servers that don't require auth
|
||||
|
||||
builds:
|
||||
type: remote
|
||||
url: "https://builds.mcp.example.com"
|
||||
tasksMode: always # async task execution — see MCP Tasks below
|
||||
```
|
||||
|
||||
## CLI Reference
|
||||
@@ -626,6 +631,36 @@ in a custom `MCPTokenStoreFactory` for encrypted, DB-backed, or in-memory
|
||||
storage. See the [SDK options docs](/sdk/options#mcp-oauth-authorization) for
|
||||
the full matrix.
|
||||
|
||||
### MCP Tasks (long-running tools)
|
||||
|
||||
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
during `initialize`, so cooperating MCP servers can respond to `tools/call`
|
||||
with a `taskId` instead of blocking the connection. Kit then polls
|
||||
`tasks/get` / `tasks/result` until the task reaches a terminal state, and
|
||||
best-effort `tasks/cancel`s on context cancellation.
|
||||
|
||||
Defaults are safe — a server that doesn't advertise task capability runs
|
||||
synchronously, exactly as before. Opt in per server via `tasksMode` in
|
||||
`.kit.yml` (`auto` | `never` | `always`) or programmatically through the SDK:
|
||||
|
||||
```go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
MCPTaskMode: map[string]kit.MCPTaskMode{
|
||||
"build-server": kit.MCPTaskModeAlways,
|
||||
},
|
||||
MCPTaskTimeout: 15 * time.Minute,
|
||||
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
||||
log.Printf("%s: %s", p.TaskID, p.Status)
|
||||
},
|
||||
})
|
||||
|
||||
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
||||
_, _ = host.CancelMCPTask(ctx, "build-server", tasks[0].TaskID)
|
||||
```
|
||||
|
||||
See the [configuration docs](/configuration#mcp-tasks-long-running-tools) and
|
||||
[SDK options → MCP Tasks](/sdk/options#mcp-tasks) for the full surface.
|
||||
|
||||
### Custom Tools
|
||||
|
||||
Create custom tools with automatic schema generation — no external dependencies needed:
|
||||
|
||||
@@ -190,6 +190,41 @@ msg, err := host.GetMCPPrompt(ctx, "server-name", "prompt-name", map[string]stri
|
||||
})
|
||||
```
|
||||
|
||||
### MCP Tasks (long-running tools)
|
||||
|
||||
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
during `initialize`. Cooperating servers can respond to `tools/call` with a
|
||||
`taskId` immediately; Kit then polls `tasks/get` / `tasks/result` until the
|
||||
task reaches a terminal state, and best-effort `tasks/cancel`s on context
|
||||
cancellation. Servers that don't advertise the capability keep their previous
|
||||
synchronous behaviour.
|
||||
|
||||
```go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
// Per-server mode: auto (default), never, or always.
|
||||
MCPTaskMode: map[string]kit.MCPTaskMode{
|
||||
"build-server": kit.MCPTaskModeAlways,
|
||||
},
|
||||
MCPTaskTimeout: 15 * time.Minute, // total wall-clock cap
|
||||
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
||||
log.Printf("%s/%s: %s", p.Server, p.TaskID, p.Status)
|
||||
},
|
||||
})
|
||||
|
||||
// Inspect / cancel in-flight tasks
|
||||
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
||||
t, _ := host.GetMCPTask(ctx, "build-server", tasks[0].TaskID)
|
||||
if !t.Status.IsTerminal() {
|
||||
_, _ = host.CancelMCPTask(ctx, "build-server", t.TaskID)
|
||||
}
|
||||
```
|
||||
|
||||
The progress handler fires once when a task is accepted and again on every
|
||||
observed status transition; the final invocation always carries a terminal
|
||||
status (`MCPTaskStatusCompleted`, `MCPTaskStatusFailed`, or
|
||||
`MCPTaskStatusCancelled`). Don't block in the handler — dispatch long work on
|
||||
a goroutine.
|
||||
|
||||
### Session Management
|
||||
|
||||
Maintain conversation context:
|
||||
|
||||
@@ -88,6 +88,11 @@ mcpServers:
|
||||
type: remote
|
||||
url: "https://pubmed.mcp.example.com"
|
||||
noOAuth: true # skip OAuth for public servers
|
||||
|
||||
builds:
|
||||
type: remote
|
||||
url: "https://builds.mcp.example.com"
|
||||
tasksMode: always # always run tools/call as async tasks (Phase 1 MVP)
|
||||
```
|
||||
|
||||
### MCP server fields
|
||||
@@ -101,9 +106,34 @@ mcpServers:
|
||||
| `allowedTools` | list | Whitelist of tool names to expose |
|
||||
| `excludedTools` | list | Blacklist of tool names to hide |
|
||||
| `noOAuth` | bool | Skip OAuth for this server (for public servers that don't require auth) |
|
||||
| `tasksMode` | string | When to augment `tools/call` with MCP task metadata: `auto` (default — only when the server advertises task support), `never`, or `always`. See [MCP tasks](#mcp-tasks-long-running-tools). |
|
||||
|
||||
A legacy format with `transport`, `args`, `env`, and `headers` fields is also supported.
|
||||
|
||||
### MCP tasks (long-running tools)
|
||||
|
||||
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
during `initialize` so servers can respond to `tools/call` with a
|
||||
`CreateTaskResult` (a task ID + `working` status) instead of blocking until
|
||||
the operation finishes. Kit then polls `tasks/get` / `tasks/result` until the
|
||||
task reaches a terminal state, and best-effort `tasks/cancel`s on context
|
||||
cancellation.
|
||||
|
||||
This avoids HTTP/SSE proxy timeouts on long builds, deploys, and batch jobs,
|
||||
and lets the user/agent abort cleanly with Ctrl-C.
|
||||
|
||||
**Per-server `tasksMode`:**
|
||||
|
||||
| Value | Behaviour |
|
||||
|-------|-----------|
|
||||
| `auto` (default) | Augment `tools/call` with task metadata only when the server advertised `tasks/toolCalls` capability. Servers that don't advertise it run synchronously, exactly as before. |
|
||||
| `never` | Always issue `tools/call` synchronously, regardless of server capability. |
|
||||
| `always` | Always opt into task augmentation, even when the server didn't advertise the capability. The server may still respond synchronously — this just expresses client intent unconditionally. |
|
||||
|
||||
Defaults are safe: any existing MCP server keeps its previous behaviour
|
||||
bit-for-bit. SDK consumers can also override the mode programmatically and
|
||||
plug in a progress callback — see [SDK options](/sdk/options#mcp-tasks).
|
||||
|
||||
## Custom models
|
||||
|
||||
Define custom models in your `.kit.yml` for use with the `custom` provider. This is useful for self-hosted models or API endpoints not in the built-in database:
|
||||
|
||||
@@ -169,6 +169,12 @@ when embedding Kit as a library.
|
||||
| `MCPAuthHandler` | `MCPAuthHandler` | — | OAuth handler for remote MCP servers. `nil` disables OAuth (servers returning 401 fail with the authorization-required error). See [MCP OAuth](#mcp-oauth-authorization) below. |
|
||||
| `MCPTokenStoreFactory` | `func` | — | Custom OAuth token storage for MCP servers (default: JSON file in `$XDG_CONFIG_HOME/.kit/mcp_tokens.json`). |
|
||||
| `InProcessMCPServers` | `map[string]*MCPServer` | — | In-process mcp-go servers (no subprocess) |
|
||||
| `MCPTaskMode` | `map[string]MCPTaskMode` | — | Per-server override for task-augmented `tools/call`. Keys are server names; missing entries fall back to the `tasksMode` field of the matching `MCPServerConfig`. See [MCP Tasks](#mcp-tasks). |
|
||||
| `MCPTaskTimeout` | `time.Duration` | `15m` | Maximum wall-clock to wait for a task to reach a terminal state. Independent of any per-call context deadline. |
|
||||
| `MCPTaskTTL` | `time.Duration` | — | TTL hint sent in `TaskParams` for every task-augmented call. Zero omits the field and lets the server pick. |
|
||||
| `MCPTaskPollInterval` | `time.Duration` | `1s` | Fallback interval between `tasks/get` requests when the server does not suggest one. |
|
||||
| `MCPTaskMaxPollInterval` | `time.Duration` | `5s` | Cap on the polling interval (a server-supplied `pollInterval` can otherwise grow without bound). |
|
||||
| `MCPTaskProgress` | `MCPTaskProgressHandler` | — | Optional callback invoked once when a task is accepted and on every observed status transition. The final invocation always carries a terminal status. |
|
||||
|
||||
## MCP OAuth Authorization
|
||||
|
||||
@@ -248,6 +254,79 @@ authorization URL and hang until the 2-minute callback timeout fires. Always
|
||||
set `OnAuthURL`, or use a higher-level wrapper like `CLIMCPAuthHandler`.
|
||||
:::
|
||||
|
||||
## MCP Tasks
|
||||
|
||||
The [MCP Tasks utility](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
turns a synchronous `tools/call` into a pollable async job: the server
|
||||
returns a `taskId` with status `working` immediately, and the client polls
|
||||
`tasks/get` / `tasks/result` until the task reaches a terminal state.
|
||||
|
||||
Kit advertises task support during `initialize` and, by default, augments
|
||||
`tools/call` with task metadata only when the server advertises
|
||||
`tasks/toolCalls` capability — so any existing MCP server keeps its previous
|
||||
synchronous behaviour bit-for-bit. Long-running tools (builds, deployments,
|
||||
batch jobs, sub-agent runs) get HTTP/SSE timeout-resistance and clean
|
||||
cancellation "for free" once both sides opt in.
|
||||
|
||||
### Per-server mode
|
||||
|
||||
```go
|
||||
import "time"
|
||||
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
MCPTaskMode: map[string]kit.MCPTaskMode{
|
||||
"build-server": kit.MCPTaskModeAlways, // force task-augmented calls
|
||||
"chat-server": kit.MCPTaskModeNever, // force synchronous calls
|
||||
// any server not in the map honours its `tasksMode` config field
|
||||
// (default "auto")
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
| Mode | Behaviour |
|
||||
|---|---|
|
||||
| `MCPTaskModeAuto` (default) | Augment `tools/call` with `TaskParams` only when the server advertised `tasks/toolCalls`. |
|
||||
| `MCPTaskModeNever` | Always issue `tools/call` synchronously, ignoring server capability. |
|
||||
| `MCPTaskModeAlways` | Always opt in, even when the server didn't advertise the capability. The server may still respond synchronously. |
|
||||
|
||||
### Progress callbacks
|
||||
|
||||
```go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
MCPTaskTimeout: 15 * time.Minute, // total wall-clock cap
|
||||
MCPTaskTTL: 30 * time.Minute, // server retention hint
|
||||
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
||||
log.Printf("%s/%s: %s %s", p.Server, p.TaskID, p.Status, p.Message)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The handler fires once when a task is accepted and again on every observed
|
||||
status transition. The final call always carries a terminal status
|
||||
(`MCPTaskStatusCompleted`, `MCPTaskStatusFailed`, or `MCPTaskStatusCancelled`).
|
||||
Do not block in the handler — dispatch long work on a goroutine.
|
||||
|
||||
### Inspecting and cancelling tasks
|
||||
|
||||
```go
|
||||
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
||||
for _, t := range tasks {
|
||||
fmt.Printf("%s: %s (%s)\n", t.TaskID, t.Status, t.StatusMessage)
|
||||
}
|
||||
|
||||
t, _ := host.GetMCPTask(ctx, "build-server", taskID)
|
||||
if !t.Status.IsTerminal() {
|
||||
_, _ = host.CancelMCPTask(ctx, "build-server", taskID)
|
||||
}
|
||||
```
|
||||
|
||||
`Kit.ListMCPTasks`, `Kit.GetMCPTask`, and `Kit.CancelMCPTask` work against any
|
||||
loaded MCP server that advertises the corresponding capability.
|
||||
`MCPTaskStatus.IsTerminal()` is the canonical check for completion.
|
||||
|
||||
Context cancellation also works end-to-end: cancelling the `ctx` passed to a
|
||||
tool execution triggers a best-effort `tasks/cancel` before the call returns.
|
||||
|
||||
## Precedence
|
||||
|
||||
For any given generation or provider field, the effective value is resolved
|
||||
|
||||
@@ -215,6 +215,33 @@ resources := host.ListMCPResources()
|
||||
content, _ := host.ReadMCPResource(ctx, "server", "file:///path")
|
||||
```
|
||||
|
||||
## MCP tasks (long-running tools)
|
||||
|
||||
Kit advertises [MCP task support](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks)
|
||||
during `initialize`, so cooperating servers can return a `taskId` immediately
|
||||
and let Kit poll `tasks/get` / `tasks/result` until the operation completes.
|
||||
This avoids HTTP/SSE proxy timeouts on long tools and gives you clean
|
||||
cancellation via context.
|
||||
|
||||
```go
|
||||
host, _ := kit.New(ctx, &kit.Options{
|
||||
MCPTaskMode: map[string]kit.MCPTaskMode{
|
||||
"build-server": kit.MCPTaskModeAlways,
|
||||
},
|
||||
MCPTaskProgress: func(p kit.MCPTaskProgress) {
|
||||
log.Printf("%s: %s", p.TaskID, p.Status)
|
||||
},
|
||||
})
|
||||
|
||||
// Inspect / cancel in-flight tasks
|
||||
tasks, _ := host.ListMCPTasks(ctx, "build-server")
|
||||
_, _ = host.CancelMCPTask(ctx, "build-server", tasks[0].TaskID)
|
||||
```
|
||||
|
||||
Defaults to `MCPTaskModeAuto` per server, so any existing MCP server keeps
|
||||
its previous synchronous behaviour. See [SDK options → MCP Tasks](/sdk/options#mcp-tasks)
|
||||
for the full surface.
|
||||
|
||||
## Context and compaction
|
||||
|
||||
Monitor and manage context usage:
|
||||
|
||||
Reference in New Issue
Block a user