Skip to content

Conversation

@ochafik
Copy link
Contributor

@ochafik ochafik commented Nov 11, 2025

Implement types from modelcontextprotocol/modelcontextprotocol#1577 (accepted)

Spec PR: modelcontextprotocol/modelcontextprotocol#1796 (merged)

cc/ @bhosmer-ant

Follow up PRs may include more code from #991:

  • Examples
  • ToolRegistry, runToolLoop helpers

Motivation and Context

Allows using tools in sampling.

How Has This Been Tested?

#991 has examples + backfill support

Breaking Changes

Yes: any code that uses the result of sampling will now need to check whether CreateMessageResult.content is an array or not (if the server is on a previous spec version, the content returned cannot be an array, but the static types now allow both)

const response = await options.server.server.createMessage({ messages, maxTokens: 4000 });

// BEFORE:
// const contentText = response.content.type === 'text' ? response.content.text : '';

// AFTER:
const contentArray = Array.isArray(response.content) ? response.content : [response.content];
const contentText = contentArray.filter(c => c.type === 'text').map(c => c.text).join('\n');

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@ochafik ochafik changed the title Implement SEP 1577 (Sampling w/ Tools) Implement SEP-1577: Sampling With Tools) Nov 11, 2025
@ochafik ochafik changed the title Implement SEP-1577: Sampling With Tools) Implement SEP-1577 - Sampling With Tools) Nov 11, 2025
@ochafik ochafik changed the title Implement SEP-1577 - Sampling With Tools) Implement SEP-1577 - Sampling With Tools Nov 17, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 17, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1101

commit: cd2b837

@ochafik ochafik marked this pull request as ready for review November 17, 2025 15:28
@ochafik ochafik requested a review from a team as a code owner November 17, 2025 15:28
ochafik and others added 8 commits November 18, 2025 17:10
- Use structuredContent instead of content for plain object results in ToolResultContent tests
- Use camelCase toolChoice instead of snake_case tool_choice in CreateMessageRequest test

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add type checks for ToolChoice, ToolUseContent, ToolResultContent, SamplingMessageContentBlock
- Update expected spec types count from 119 to 123

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

Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Remove `disable_parallel_tool_use` from ToolChoiceSchema (not in MCP spec)
- Remove unnecessary `.passthrough()` from ToolChoiceSchema
- Change CreateMessageResultSchema.role from z.literal("assistant") to
  z.enum(["user", "assistant"]) to match spec's SamplingMessage.role
- Update spec type count from 123 to 127 (4 new sampling tool types)
- Fix test accessing .type on content union (could be array)
- Add test for CreateMessageResult with array content
- Remove test expecting user role to fail (spec allows both roles)

Note: 7 type compatibility errors remain due to upstream spec issue
where ToolUseContent.input and ToolResultContent.structuredContent use
`object` type instead of `{ [key: string]: unknown }`.

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

Co-Authored-By: Claude <noreply@anthropic.com>
@bhosmer-ant bhosmer-ant force-pushed the ochafik/sep-1577-sampling-tools branch from 05f64f6 to a39bd78 Compare November 18, 2025 23:32
@bhosmer-ant
Copy link
Contributor

Hi @ochafik - I went ahead and rebased and reconciled a few schema updates ("user"|"assistant" type relaxation, etc.), hope that's ok 😬

Note: a handful of related errors remains due to a schema inconsistency that needs to be fixed in the spec before this will pass (due to spec.types.ts intake) - it's something I should've caught in my review, apologies. Below is Claude's (exhaustive) rundown of the situation, happy to talk through it if useful!


Upstream Spec Fix Required: SEP-1577 Type Inconsistency

Problem

The TypeScript SDK has 7 type compatibility errors between spec.types.ts (auto-generated from the upstream spec) and types.ts (SDK's Zod schemas). These errors block CI.

Root Cause

In schema/draft/schema.ts, the SEP-1577 implementation uses object type for two fields, but the existing CallToolResult uses { [key: string]: unknown } for the semantically equivalent field. This inconsistency causes type incompatibility.

Affected Fields

Interface Field Current Type Should Be
ToolUseContent input object { [key: string]: unknown }
ToolResultContent structuredContent object { [key: string]: unknown }

Why This Matters

In TypeScript:

  • object is any non-primitive value but has no index signature
  • { [key: string]: unknown } has an explicit index signature

These are not mutually assignable, causing cascade failures through all types that contain ToolUseContent or ToolResultContent:

  • SamplingMessageContentBlock
  • SamplingMessage
  • CreateMessageRequest
  • CreateMessageRequestParams
  • CreateMessageResult

Existing Precedent

CallToolResult.structuredContent already uses the correct type:

// In schema/draft/schema.ts (existing, correct)
export interface CallToolResult extends Result {
  structuredContent?: { [key: string]: unknown };  // ✓ correct
  // ...
}

Proposed Fix

In schema/draft/schema.ts, change:

// ToolUseContent - line ~1529
export interface ToolUseContent {
  // ...
  input: object;  // ← change this
  // ...
}

// ToolResultContent - line ~1568
export interface ToolResultContent {
  // ...
  structuredContent?: object;  // ← change this
  // ...
}

To:

// ToolUseContent
export interface ToolUseContent {
  // ...
  input: { [key: string]: unknown };
  // ...
}

// ToolResultContent
export interface ToolResultContent {
  // ...
  structuredContent?: { [key: string]: unknown };
  // ...
}

Commit Reference

This inconsistency was introduced in commit aa453ec ("SEP-1577: Add tool calling support to sampling").

After Fix

Once the upstream spec is fixed:

  1. Run npm run fetch:spec-types in the TypeScript SDK
  2. All type compatibility errors should resolve
  3. CI should pass

@ochafik
Copy link
Contributor Author

ochafik commented Nov 19, 2025

Thanks @bhosmer-ant, sent modelcontextprotocol/modelcontextprotocol#1842 for review to fix the spec types.

Copy link
Contributor

@bhosmer-ant bhosmer-ant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bhosmer-ant bhosmer-ant merged commit 9438478 into main Nov 19, 2025
10 checks passed
@bhosmer-ant bhosmer-ant deleted the ochafik/sep-1577-sampling-tools branch November 19, 2025 23:29
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.

Implement SEP-1577: Sampling With Tools

3 participants