Commit e2c1762
authored
feat(server): implement task-augmented tools capability (#707)
* feat(mcp): add ToolExecution types and TaskSupport constants
Add foundational types for task-augmented tool support per MCP spec 2025-11-25:
- Add TaskSupport type (string enum) with three constants:
- TaskSupportForbidden: tool cannot be invoked as a task (default)
- TaskSupportOptional: tool can be invoked either way
- TaskSupportRequired: tool must be invoked as a task
- Add ToolExecution struct with TaskSupport field
- Update Tool struct to include optional Execution field
- Update Tool.MarshalJSON to serialize execution field when present
- Add comprehensive tests for marshaling behavior and constants
Related to #656
* feat(tasks): implement pagination for tasks/list endpoint
- Add Task.GetName() method to implement Named interface for pagination
- Update handleListTasks to sort tasks by TaskId and use listByPagination
- Add comprehensive pagination tests covering multiple pages and edge cases
- Add TestTask_GetName unit test
All tests pass with race detector, linter clean.
* feat(tasks): add RelatedTaskMeta helper functions
Add helper functions for associating messages with tasks per MCP spec:
- RelatedTaskMetaKey constant for standard metadata key
- RelatedTaskMeta() to create task metadata maps
- WithRelatedTask() to create Meta objects with task IDs
Includes comprehensive test coverage in mcp/tasks_test.go.
Part of #656 (TAS-14)
* feat(tasks): add WithTaskSupport option for tool configuration
Add WithTaskSupport() function to configure task support modes for tools.
The function accepts TaskSupportForbidden, TaskSupportOptional, or
TaskSupportRequired values and properly initializes or updates the tool's
Execution field.
- Implement WithTaskSupport() in mcp/tools.go
- Add comprehensive test coverage in mcp/tools_test.go
- Test all three task support modes with JSON marshaling
- Test Execution initialization when nil
- Test preservation of existing Execution instance
Related to #656
* feat(tasks): add TaskParams field to CallToolParams for task-augmented tool calls
- Add Task *TaskParams field to CallToolParams struct to support task augmentation
- Add ToInt64Ptr() helper function in utils.go for creating int64 pointers
- Add comprehensive tests for CallToolRequest with task params:
- Test unmarshaling with task params, without task params, and null task params
- Test round-trip marshaling/unmarshaling to verify data preservation
- All tests pass with race detector, linter clean
This enables detection of task-augmented tool calls and unblocks:
- TAS-15: Support for optional task tools (hybrid mode)
- TAS-16: Validation of task support on required tools
Related to #656
* feat(tasks): add lastUpdatedAt field to Task type
Add LastUpdatedAt field to Task struct per MCP spec 2025-11-25 requirement.
The field is automatically set on task creation and updated whenever the
task status changes (completed, failed, or cancelled).
Changes:
- Add LastUpdatedAt string field to Task struct in mcp/types.go
- Initialize both CreatedAt and LastUpdatedAt in NewTask() (mcp/tasks.go)
- Update lastUpdatedAt in completeTask() when task completes or fails
- Update lastUpdatedAt in cancelTask() when task is cancelled
- Add comprehensive test coverage for timestamp behavior
- Enhance JSON marshaling tests to verify field presence
All tests pass, linter clean. Complies with MCP spec requirement that
tasks MUST include lastUpdatedAt ISO 8601 timestamp.
* feat(tasks): add validation for TaskSupportRequired tools
Implement validation in handleToolCall() to enforce that tools with
TaskSupportRequired cannot be called without task augmentation. Returns
METHOD_NOT_FOUND error with message 'tool X requires task augmentation'.
Add comprehensive test suite TestMCPServer_TaskSupportValidation with 7
test cases covering all task support modes (required, optional, forbidden).
Implements MCP spec 2025-11-25 requirement for task support validation.
Related to #656
* feat(tasks): add task status notifications
Implement notifications/tasks/status to notify clients when task status
changes. Notifications are sent automatically when tasks complete, fail,
or are cancelled.
Changes:
- Add sendTaskStatusNotification() helper method that converts task data
to notification params format
- Include required fields: taskId, status, createdAt, lastUpdatedAt
- Conditionally include optional fields: statusMessage, ttl, pollInterval
- Integrate notifications into completeTask() and cancelTask()
- Add comprehensive test suite with 7 test cases covering all scenarios
Complies with MCP spec 2025-11-25 task notification requirements.
Issue: #656
* feat(tasks): implement hybrid mode detection for optional task tools
Add routing logic to detect when tools with TaskSupportOptional or
TaskSupportRequired are called with task parameters. Tools called with
task params now route to task-augmented execution path (placeholder
error until TAS-9 implements handleTaskAugmentedToolCall). Tools
called without task params continue to execute synchronously.
- Add shouldExecuteAsTask detection in handleToolCall()
- Add comprehensive test suite TestMCPServer_HybridModeDetection
- Update existing tests to expect task execution routing behavior
This provides the routing foundation for TAS-9 to implement actual
task-augmented tool execution.
* feat(server): add task-augmented tool call detection and routing
- Add detection logic in handleToolCall() to identify task-augmented requests
- Route requests with task params to handleTaskAugmentedToolCall() when tool has TaskSupportOptional or TaskSupportRequired
- Add handleTaskAugmentedToolCall() stub method with TODO for TAS-9 implementation
- Completes TAS-8: routing infrastructure for task-augmented tool execution
Related to #656
* feat(examples): add task tool example demonstrating async execution
Add comprehensive example showing task-augmented tools with three types:
- process_batch: TaskSupportRequired tool for batch processing
- analyze_data: TaskSupportOptional tool with sync/async modes
- quick_check: Regular synchronous tool for comparison
Includes detailed README with usage examples, HTTP testing instructions,
and task workflow explanation. Build constraint prevents compilation until
core implementation (TAS-4 through TAS-10) is complete.
Related to #656 (TAS-19)
* feat(server): add TaskToolHandlerFunc type and ServerTaskTool struct for async task execution
- Add TaskToolHandlerFunc type for asynchronous tool call handlers that return CreateTaskResult
- Add ServerTaskTool struct combining Tool with TaskToolHandlerFunc
- Add taskTools map to MCPServer for storing task-augmented tools
- Initialize taskTools map in NewMCPServer constructor
- Add comprehensive test suite validating type definitions and initialization
These type definitions provide the foundation for task-augmented tool execution (TAS-4, TAS-5).
Related to #656
* feat(tasks): implement executeTaskTool method for async task execution
Implement executeTaskTool method that executes task tool handlers
asynchronously. The method creates a cancellable context, stores the
cancel function for potential cancellation via tasks/cancel, executes
the handler in the background, and completes the task with result or error.
Implementation details:
- Creates cancellable context using context.WithCancel()
- Stores cancel func in task entry under lock before execution
- Executes TaskToolHandlerFunc and handles results/errors
- Calls completeTask() to update status and send notifications
Test coverage includes 6 comprehensive test cases:
- Successful task execution stores result
- Failed task execution stores error with proper status
- Task cancellation via context
- Cancel function storage timing (race condition test)
- Task status notification on completion
- Multiple concurrent task execution
All tests pass with race detector, linter clean.
This provides the core async execution mechanism for TAS-9
(handleTaskAugmentedToolCall).
Related to #656
* feat(server): implement task-augmented tool call handling (TAS-9)
Implement handleTaskAugmentedToolCall method that enables async execution
of tools with TaskSupport. The implementation:
- Checks both taskTools and regular tools maps for tool lookup
- Validates task support mode (optional/required)
- Generates UUID v4 task IDs and creates task entries
- Starts async execution via executeTaskTool or executeRegularToolAsTask
- Returns CreateTaskResult immediately wrapped in CallToolResult _meta field
- Fixes race condition by copying task before returning
Add executeRegularToolAsTask method to handle hybrid mode where regular
tools with TaskSupport are executed asynchronously.
Update test expectations in TestMCPServer_HybridModeDetection and
TestMCPServer_TaskSupportValidation to expect successful task creation
instead of 'not yet implemented' error.
Tools with TaskSupportOptional/Required can now be called with task
params and execute asynchronously with proper task tracking.
* docs: add comprehensive task-augmented tools documentation to README
- Add Task-Augmented Tools section explaining async execution
- Document three TaskSupport modes (Forbidden, Optional, Required)
- Include code examples for TaskSupportRequired and TaskSupportOptional
- Explain task execution flow (call → task ID → async → polling → notifications)
- Add context cancellation and WithTaskCapabilities examples
- Update Examples section to highlight task_tool example
- Reorganize synchronous tools section for clarity
* feat(server): include task tools in handleListTools response
Update handleListTools to return both regular and task-augmented tools in tools/list response. Implementation iterates over both s.tools and s.taskTools maps, sorts all tool names alphabetically, and includes both types in the result.
- Extend capacity of tools slice to accommodate both tool types
- Collect tool names from both s.tools and s.taskTools maps
- Maintain alphabetical sorting across all tools
- Protected by existing toolsMu mutex for thread safety
- Add comprehensive test suite with 4 test cases:
* Mixed regular and task tools with proper sorting
* Only task tools scenario
* Empty list when no tools exist
* Alphabetical ordering verification
Task tools identified by Execution.TaskSupport field in metadata.
* feat(server): add AddTaskTool and AddTaskTools methods
Implement proper API for registering task-augmented tools following the
same pattern as regular tool registration (AddTool/AddTools).
- Add AddTaskTool() method for single task tool registration
- Add AddTaskTools() method for batch task tool registration
- Both methods implicitly register tool capabilities (listChanged=true)
- Send tools/list_changed notifications to initialized sessions
- Add comprehensive test suite TestMCPServer_AddTaskTool with 4 test cases
- Update existing tests to use new methods instead of direct map access
All tests pass with race detector, linter clean (0 issues).
* test: add comprehensive task tool integration test (TAS-12)
Add TestTaskToolTracerBullet in server/task_tool_test.go with 6 end-to-end
test scenarios covering:
- Complete task tool flow with TaskSupportRequired
- TaskSupportOptional sync/async execution modes
- Task cancellation via context
- Error handling with proper task failure states
- Multiple concurrent task tools
Fix bug in handleToolCall where taskTools map was not checked during tool
lookup. Now checks both s.tools and s.taskTools, allowing tools registered
with AddTaskTool to be properly found and validated.
All tests pass with race detector, linter reports 0 issues.
* feat(server): improve context cancellation handling for task tools
- Add explicit checking for context.Canceled and context.DeadlineExceeded errors in executeTaskTool and executeRegularToolAsTask
- Mark tasks as 'cancelled' instead of 'failed' when handlers return context cancellation errors
- Handle race condition where handler detects cancellation before tasks/cancel is called
- Add comprehensive test for handler-detected context cancellation edge case
- Update existing test expectations to correctly expect TaskStatusCancelled
This ensures proper status differentiation between cancellation and failure, respecting Go's context patterns.
* feat(server): add task metrics and observability hooks
Implement comprehensive observability system for task-augmented tools:
- Add TaskMetrics struct with execution metadata (ID, tool name, status,
timestamps, duration, session, error)
- Add TaskHooks with 5 lifecycle hook types: OnTaskCreated, OnTaskCompleted,
OnTaskFailed, OnTaskCancelled, OnTaskStatusChanged
- Add WithTaskHooks() ServerOption for hook configuration
- Integrate hooks into task lifecycle (createTask, completeTask, cancelTask,
executeTaskTool, executeRegularToolAsTask)
- Update taskEntry to track toolName and createdAt for metrics
- Add comprehensive test suite with 8 test cases covering all hook scenarios
- Update task_tool example to demonstrate hook usage with logging
This enables developers to monitor task execution, collect metrics, and
integrate with monitoring systems for async tool operations.
Resolves TAS-24
* feat(server): add max concurrent tasks limit for task-augmented tools
Add optional resource management for task-augmented tools through
WithMaxConcurrentTasks() ServerOption. This prevents resource exhaustion
by limiting the number of concurrent running tasks.
Changes:
- Add maxConcurrentTasks and activeTasks fields to MCPServer
- Add WithMaxConcurrentTasks(limit int) ServerOption
- Modify createTask() to check limit and return error when exceeded
- Update task completion/cancellation to decrement active task counter
- Add comprehensive test suite (8 test cases) with race detector
- Update examples and documentation
The limit only applies to non-terminal (working) tasks. Completed,
failed, or cancelled tasks don't count toward the limit. When not
configured or set to 0, no limit is enforced.
All tests pass with race detector. Linter clean.
* types
* remove
* fix(tasks): eliminate race condition in createTask and add tool name collision validation
- Fix race window in createTask() between checking concurrent task limit and inserting task
- Restructure to build task entry first without lock
- Use single critical section with defer for check + increment + insert
- Prevents multiple goroutines from exceeding maxConcurrentTasks under high concurrency
- Add tool name collision validation
- Prevent same tool name from being registered in both s.tools and s.taskTools
- AddTools() now checks for collisions with s.taskTools before registration
- AddTaskTools() now checks for collisions with s.tools before registration
- Panic with clear error message on collision to fail fast during setup
- Prevents silent shadowing where task tools become invisible in handleListTools
- Add comprehensive test coverage
- Test concurrent task creation respects limit (existing test now passes reliably)
- Add TestMCPServer_ToolNameCollisionValidation with 5 collision scenarios
- All tests pass with race detector enabled
* fix(tasks): add mutex synchronization to eliminate data races in tests
Shared variables handlerCalled and receivedData were accessed without
synchronization from both the async task handler goroutine and the main
test thread, causing data races detected by 'go test -race'. Added
sync.Mutex protection around all reads and writes to these variables.
All tests now pass with race detector enabled.
* fix: return CreateTaskResult with task as direct field for spec compliance
Task-augmented tool calls now return CreateTaskResult with task as a direct
field of result (result.task) instead of nested in _meta (result._meta.task),
matching the MCP Tasks Specification (2025-11-25).
Changes:
- Modified handleToolCall() to return 'any' to support both CallToolResult
and CreateTaskResult
- Modified handleTaskAugmentedToolCall() to return *CreateTaskResult directly
- Updated code generation templates to support ResultIsAny flag for flexible
return types
- Regenerated hooks.go and request_handler.go with updated templates
- Fixed all tests to use pointer type assertions and expect correct format
- Added comprehensive spec compliance tests
All tests pass with race detector enabled.
Resolves: #707 (TAS-1)
* docs: update task spec URLs from draft to 2025-11-25
Updated doc comment spec version references for all task-related methods
from specification/draft to specification/2025-11-25 for spec compliance.
Changes:
- MethodTasksGet
- MethodTasksList
- MethodTasksResult
- MethodTasksCancel
- MethodNotificationTasksStatus
All 5 URLs now reference the published 2025-11-25 spec version.
* docs: document input_required status and remove unused wrapper code
- Add documentation to TaskStatusInputRequired explaining it's not yet implemented
- Remove unused wrapper code in handleTaskAugmentedToolCall that was never executed
- The wrapper was created but never used when hasTaskHandler=false
Related to #707
* test: replace time.Sleep with proper synchronization in task tests
Replace all time.Sleep calls in task_hooks_test.go with channels and
sync.WaitGroup for reliable test synchronization. Update 7 test functions
to use select/timeout pattern for single-event tests and WaitGroup for
multi-event tests, eliminating race conditions and timing-dependent
flakiness.
Additionally:
- Add model-immediate-response support with helper functions and tests
- Improve task error differentiation (expired vs not found)
- Remove unused wrapper code in handleTaskAugmentedToolCall
- Add comprehensive test coverage for new functionality
All tests pass with race detector enabled.
* fix: improve task status notification test reliability and fix typo
- Update task tool test to drain notifyChan until completed status is
received, preventing flaky failures when working status arrives first
- Fix grammar in README: 'timeout' -> 'time out' (verb form)1 parent 45740a0 commit e2c1762
File tree
25 files changed
+5365
-59
lines changed- client
- examples
- everything
- task_tool
- mcp
- server
- internal/gen
25 files changed
+5365
-59
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
310 | 310 | | |
311 | 311 | | |
312 | 312 | | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
313 | 420 | | |
314 | 421 | | |
315 | 422 | | |
| |||
535 | 642 | | |
536 | 643 | | |
537 | 644 | | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
538 | 649 | | |
539 | 650 | | |
540 | 651 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
| 57 | + | |
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| |||
0 commit comments