') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); SEP-1319: Decouple Request Payloads, Remove passthrough iteration, Typecheck fixes by KKonstantinov · Pull Request #1086 · modelcontextprotocol/typescript-sdk · GitHub
Skip to content

SEP-1319: Decouple Request Payloads, Remove passthrough iteration, Typecheck fixes - #1086

Merged
pcarleton merged 11 commits into
modelcontextprotocol:mainfrom
KKonstantinov:feature/SEP-1319-ts-sdk
Nov 7, 2025
Merged

SEP-1319: Decouple Request Payloads, Remove passthrough iteration, Typecheck fixes#1086
pcarleton merged 11 commits into
modelcontextprotocol:mainfrom
KKonstantinov:feature/SEP-1319-ts-sdk

Conversation

@KKonstantinov

@KKonstantinovKKonstantinov commented Nov 6, 2025

Copy link
Copy Markdown
Contributor

Implemented modelcontextprotocol/modelcontextprotocol#1692, which lead to opportunities to remove .passthrough() on many places.

NOTE: Added all spec types, however spec tests will still fail until modelcontextprotocol/modelcontextprotocol#1770 gets merged, which fixes an accidental change of CallToolRequestParams, arguments to be { [key: string]: string }; instead of { [key: string]: unknown }; in modelcontextprotocol/modelcontextprotocol#1692

EDIT: #1770 in the spec repo has been merged, so no issues in spec type checks.

Motivation and Context

Implement SEP-1319, fix spec tests failures, remove passthrough where possibly (although the PR could possibly be achieved without removing .passthrough() as well).

How Has This Been Tested?

Unit tests, examples

Breaking Changes

Any client(s) and server(s) passing through any invalid properties will get typecheck errors. Our examples and tests contained such, which previously slipped through due to type checks not working. Examples of such can be seen in this PR's changes. Any client(s) / server(s) copying from such examples in our codebase would get a typecheck error.

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

Comment threadsrc/server/index.ts
protected assertRequestHandlerCapability(method: string): void {
switch (method) {
case 'sampling/createMessage':
if (!this._capabilities.sampling) {

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Servers do not have sampling capabilities, thus removed. Swapped with completions capabilities.

street: { type: 'string' },
city: { type: 'string' },
// @ts-expect-error - pattern is not a valid property by MCP spec, however it is making use of the Ajv validator
zipCode: { type: 'string', pattern: '^[0-9]{5}$' },

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Patterns not supported by the spec. Passing them will work, but the TS error needs ignoring.


// Create first client
const client1 = new Client({
id: clientId,

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

No such property.

type: 'string',
title: 'Start Time',
description: 'Event start time (HH:MM)',
pattern: '^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$'

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Pattern could be left here, but needs ts-ignore, as not supported by the spec. We could allow it on an optional basis and still match the spec if we wanted.

Comment threadsrc/server/mcp.ts
switch (request.params.ref.type) {
case 'ref/prompt':
assertCompleteRequestPrompt(request);
return this.handlePromptCompletion(request, request.params.ref);

@KKonstantinovKKonstantinovNov 7, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

When passthrough removed, assertions are needed to proceed with a narrowed type to alleviate type errors downstream.

{
name: 'new client',
version: '1.0',
protocolVersion: LATEST_PROTOCOL_VERSION

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Property doesn't exist.

@KKonstantinov

Copy link
Copy Markdown
ContributorAuthor

The npm run check step is failing because step.types.ts (the main protocol spec) is failing our linting. Have ignored the file from linting, as it's not within the SDK's control.

@KKonstantinov
KKonstantinov marked this pull request as ready for review November 7, 2025 11:58
@KKonstantinov
KKonstantinov requested a review from a team as a code ownerNovember 7, 2025 11:58

@pcarletonpcarleton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thank you!

Sign up for freeto 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-1319: Decouple Request Payload from RPC Methods

2 participants

@KKonstantinov@pcarleton