Skip to content

Conversation

@BuddhiLW
Copy link

Summary

Use p/future instead of p/promise for handler execution to enable true concurrent request processing.

Changes

;; Before
result-promise (p/promise
                 (receive-request method context params))

;; After  
result-promise (p/future
                 (discarding-stdout
                   (receive-request method context params)))

Benefits

1. Concurrent Request Handling

With p/promise, handlers run synchronously on the request processing thread, blocking subsequent requests. With p/future, handlers execute on a thread pool allowing multiple requests to be processed in parallel.

Use case: MCP servers with swarm/multi-agent orchestration where multiple Claude instances make concurrent tool calls.

2. Stdout Protection

The discarding-stdout wrapper prevents accidental println or logging statements from corrupting the JSON-RPC channel (which uses stdout for communication).

3. Non-blocking Event Loop

The main message processing loop stays responsive even when handlers are slow, preventing request queue buildup.

Testing

Tested with emacs-mcp swarm feature:

  • Spawned 2 concurrent agents
  • Both handlers executed in parallel ("working": 2)
  • Results collected successfully

Backward Compatibility

This change is backward compatible - existing single-request usage works identically, with the added benefit of non-blocking execution.

Run handlers asynchronously to prevent blocking the request processing thread.

Changes:
- Replace p/promise with p/future for concurrent handler execution
- Wrap in discarding-stdout to prevent logging from corrupting JSON-RPC output

This enables parallel request processing for MCP servers with concurrent
tool calls (e.g., swarm/multi-agent scenarios).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Pedro Branquinho <[email protected]>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
@BuddhiLW
Copy link
Author

BuddhiLW commented Jan 1, 2026

I've cleaned up this PR to include only the essential changes.

Before: 68 lines changed across multiple unrelated indentation adjustments

After: 10 lines changed in a single focused location (pending-received-request function)

The actual fix

;; Before
result-promise (p/promise
                 (receive-request method ...))

;; After
result-promise (p/future
                 (discarding-stdout
                   (receive-request method ...)))

Why this matters

  1. p/future vs p/promise: Enables handlers to run on a thread pool instead of blocking the request processing thread
  2. discarding-stdout: Prevents accidental println from corrupting the JSON-RPC channel (which uses stdout)

Use case

This fix is critical for MCP (Model Context Protocol) servers where:

  • Multiple concurrent tool calls need parallel processing
  • Stdout must remain clean for JSON-RPC communication

Tested with emacs-mcp swarm feature - concurrent agents now work correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant