Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 0 additions & 35 deletions .changeset/mcp-toolkit-initial.md

This file was deleted.

8 changes: 8 additions & 0 deletions examples/mcp-toolkit-demo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# mcp-toolkit-demo

## 0.1.1

### Patch Changes

- Updated dependencies [5644daa]
- @upstash/mcp-toolkit@0.1.0
2 changes: 1 addition & 1 deletion examples/mcp-toolkit-demo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mcp-toolkit-demo",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
37 changes: 37 additions & 0 deletions packages/mcp-toolkit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# @upstash/mcp-toolkit

## 0.1.0

### Minor Changes

- 5644daa: Add `@upstash/mcp-toolkit`: durable building blocks for MCP servers on the official TypeScript SDK.

`@upstash/mcp-toolkit/tasks` — long-running tools. A task tool answers immediately with a task id;
the model polls the shared `task_status` tool for progress and the result, and can stop the task
with `task_cancel`. They are ordinary MCP tools, so they work in every client today. The record
lives in a `TaskStore` and the work runs behind a `TaskDispatcher`, and the dispatcher owns its
delivery endpoint (`export const POST = tasks.createExecuteHandler()`) and always verifies QStash's
signature against the URL it published to. Tasks are declared once at module scope with
`tasks.define(...)` and attached to each request's server with `tasks.register(server)`. A required
`principal` scopes tasks to their caller (and subscriptions to theirs); handlers get it as
`task.principal`, and an optional `authorize` on `tasks.define` checks the arguments before a task
is stored or queued.

`@upstash/mcp-toolkit/events` — MCP Events with webhook delivery, as ChatGPT ships it. Typed
`events.define(...)` handles with `emit(payload)`: the payload's values route the event and are what
the required `authorize` is checked against, at subscribe and again before every delivery.
`events/list`, `events/subscribe` and `events/unsubscribe` are registered on your server, with a
signed verification challenge, deterministic subscription ids, expiry and refresh, a configurable
limit of live subscriptions per subscriber (8 by default), SSRF checks on callback URLs, and signing
secrets encrypted at rest. `QStashDelivery` signs each attempt with
Standard Webhooks and lets QStash retry failures (`export const POST = events.createDeliveryHandler()`).

A handler that returns a tool error (`isError: true`) fails its task without a retry, and
`task_status` shows that error the way the synchronous tool would. The model only ever sees a
failure's `code` and `message`: transport details stay in the store, and dispatch errors are logged.

The package uses WebCrypto only, so it runs on Node and edge runtimes.

`@upstash/mcp-toolkit/upstash` holds the Upstash backends for both: `RedisTaskStore`,
`QStashDispatcher`, `WorkflowDispatcher`, `RedisSubscriptionStore` and `QStashDelivery`.
`@upstash/redis`, `@upstash/qstash` and `@upstash/workflow` are regular dependencies.
2 changes: 1 addition & 1 deletion packages/mcp-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@upstash/mcp-toolkit",
"version": "0.0.0",
"version": "0.1.0",
"description": "Durable building blocks for MCP servers on the official TypeScript SDK: long-running tools (tasks) and webhook events, with Upstash Redis, QStash and Workflow backends.",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-toolkit/src/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Generated by scripts/sync-version.mjs (run by `pnpm ci:version`) — do not edit by hand.
export const VERSION = "0.0.0";
export const VERSION = "0.1.0";