Skip to content

Commit 9438478

Browse files
authored
Implement SEP-1577 - Sampling With Tools (#1101)
1 parent 8acd838 commit 9438478

File tree

5 files changed

+784
-25
lines changed

5 files changed

+784
-25
lines changed

src/examples/server/toolWithSampleServer.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ mcpServer.registerTool(
3333
maxTokens: 500
3434
});
3535

36+
const contents = Array.isArray(response.content) ? response.content : [response.content];
3637
return {
37-
content: [
38-
{
39-
type: 'text',
40-
text: response.content.type === 'text' ? response.content.text : 'Unable to generate summary'
41-
}
42-
]
38+
content: contents.map(content => ({
39+
type: 'text',
40+
text: content.type === 'text' ? content.text : 'Unable to generate summary'
41+
}))
4342
};
4443
}
4544
);

src/spec.types.test.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,11 @@ const sdkTypeChecks = {
360360
sdk = spec;
361361
spec = sdk;
362362
},
363-
SamplingMessage: (sdk: SDKTypes.SamplingMessage, spec: SpecTypes.SamplingMessage) => {
363+
SamplingMessage: (sdk: RemovePassthrough<SDKTypes.SamplingMessage>, spec: SpecTypes.SamplingMessage) => {
364364
sdk = spec;
365365
spec = sdk;
366366
},
367-
CreateMessageResult: (sdk: SDKTypes.CreateMessageResult, spec: SpecTypes.CreateMessageResult) => {
367+
CreateMessageResult: (sdk: RemovePassthrough<SDKTypes.CreateMessageResult>, spec: SpecTypes.CreateMessageResult) => {
368368
sdk = spec;
369369
spec = sdk;
370370
},
@@ -614,6 +614,25 @@ const sdkTypeChecks = {
614614
ModelPreferences: (sdk: SDKTypes.ModelPreferences, spec: SpecTypes.ModelPreferences) => {
615615
sdk = spec;
616616
spec = sdk;
617+
},
618+
ToolChoice: (sdk: SDKTypes.ToolChoice, spec: SpecTypes.ToolChoice) => {
619+
sdk = spec;
620+
spec = sdk;
621+
},
622+
ToolUseContent: (sdk: RemovePassthrough<SDKTypes.ToolUseContent>, spec: SpecTypes.ToolUseContent) => {
623+
sdk = spec;
624+
spec = sdk;
625+
},
626+
ToolResultContent: (sdk: RemovePassthrough<SDKTypes.ToolResultContent>, spec: SpecTypes.ToolResultContent) => {
627+
sdk = spec;
628+
spec = sdk;
629+
},
630+
SamplingMessageContentBlock: (
631+
sdk: RemovePassthrough<SDKTypes.SamplingMessageContentBlock>,
632+
spec: SpecTypes.SamplingMessageContentBlock
633+
) => {
634+
sdk = spec;
635+
spec = sdk;
617636
}
618637
};
619638

@@ -643,7 +662,7 @@ describe('Spec Types', () => {
643662
it('should define some expected types', () => {
644663
expect(specTypes).toContain('JSONRPCNotification');
645664
expect(specTypes).toContain('ElicitResult');
646-
expect(specTypes).toHaveLength(123);
665+
expect(specTypes).toHaveLength(127);
647666
});
648667

649668
it('should have up to date list of missing sdk types', () => {

src/spec.types.ts

Lines changed: 144 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,17 @@ export interface ClientCapabilities {
307307
/**
308308
* Present if the client supports sampling from an LLM.
309309
*/
310-
sampling?: object;
310+
sampling?: {
311+
/**
312+
* Whether the client supports context inclusion via includeContext parameter.
313+
* If not declared, servers SHOULD only use `includeContext: "none"` (or omit it).
314+
*/
315+
context?: object;
316+
/**
317+
* Whether the client supports tool use via tools and toolChoice parameters.
318+
*/
319+
tools?: object;
320+
};
311321
/**
312322
* Present if the client supports elicitation from the server.
313323
*/
@@ -1255,7 +1265,11 @@ export interface CreateMessageRequestParams extends RequestParams {
12551265
*/
12561266
systemPrompt?: string;
12571267
/**
1258-
* A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.
1268+
* A request to include context from one or more MCP servers (including the caller), to be attached to the prompt.
1269+
* The client MAY ignore this request.
1270+
*
1271+
* Default is "none". Values "thisServer" and "allServers" are soft-deprecated. Servers SHOULD only use these values if the client
1272+
* declares ClientCapabilities.sampling.context. These values may be removed in future spec releases.
12591273
*/
12601274
includeContext?: "none" | "thisServer" | "allServers";
12611275
/**
@@ -1273,6 +1287,32 @@ export interface CreateMessageRequestParams extends RequestParams {
12731287
* Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.
12741288
*/
12751289
metadata?: object;
1290+
/**
1291+
* Tools that the model may use during generation.
1292+
* The client MUST return an error if this field is provided but ClientCapabilities.sampling.tools is not declared.
1293+
*/
1294+
tools?: Tool[];
1295+
/**
1296+
* Controls how the model uses tools.
1297+
* The client MUST return an error if this field is provided but ClientCapabilities.sampling.tools is not declared.
1298+
* Default is `{ mode: "auto" }`.
1299+
*/
1300+
toolChoice?: ToolChoice;
1301+
}
1302+
1303+
/**
1304+
* Controls tool selection behavior for sampling requests.
1305+
*
1306+
* @category `sampling/createMessage`
1307+
*/
1308+
export interface ToolChoice {
1309+
/**
1310+
* Controls the tool use ability of the model:
1311+
* - "auto": Model decides whether to use tools (default)
1312+
* - "required": Model MUST use at least one tool before completing
1313+
* - "none": Model MUST NOT use any tools
1314+
*/
1315+
mode?: "auto" | "required" | "none";
12761316
}
12771317

12781318
/**
@@ -1295,10 +1335,19 @@ export interface CreateMessageResult extends Result, SamplingMessage {
12951335
* The name of the model that generated the message.
12961336
*/
12971337
model: string;
1338+
12981339
/**
12991340
* The reason why sampling stopped, if known.
1341+
*
1342+
* Standard values:
1343+
* - "endTurn": Natural end of the assistant's turn
1344+
* - "stopSequence": A stop sequence was encountered
1345+
* - "maxTokens": Maximum token limit was reached
1346+
* - "toolUse": The model wants to use one or more tools
1347+
*
1348+
* This field is an open string to allow for provider-specific stop reasons.
13001349
*/
1301-
stopReason?: "endTurn" | "stopSequence" | "maxTokens" | string;
1350+
stopReason?: "endTurn" | "stopSequence" | "maxTokens" | "toolUse" | string;
13021351
}
13031352

13041353
/**
@@ -1308,8 +1357,18 @@ export interface CreateMessageResult extends Result, SamplingMessage {
13081357
*/
13091358
export interface SamplingMessage {
13101359
role: Role;
1311-
content: TextContent | ImageContent | AudioContent;
1360+
content: SamplingMessageContentBlock | SamplingMessageContentBlock[];
1361+
/**
1362+
* See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
1363+
*/
1364+
_meta?: { [key: string]: unknown };
13121365
}
1366+
export type SamplingMessageContentBlock =
1367+
| TextContent
1368+
| ImageContent
1369+
| AudioContent
1370+
| ToolUseContent
1371+
| ToolResultContent;
13131372

13141373
/**
13151374
* Optional annotations for the client. The client can use annotations to inform how objects are used or displayed
@@ -1444,6 +1503,87 @@ export interface AudioContent {
14441503
_meta?: { [key: string]: unknown };
14451504
}
14461505

1506+
/**
1507+
* A request from the assistant to call a tool.
1508+
*
1509+
* @category `sampling/createMessage`
1510+
*/
1511+
export interface ToolUseContent {
1512+
type: "tool_use";
1513+
1514+
/**
1515+
* A unique identifier for this tool use.
1516+
*
1517+
* This ID is used to match tool results to their corresponding tool uses.
1518+
*/
1519+
id: string;
1520+
1521+
/**
1522+
* The name of the tool to call.
1523+
*/
1524+
name: string;
1525+
1526+
/**
1527+
* The arguments to pass to the tool, conforming to the tool's input schema.
1528+
*/
1529+
input: { [key: string]: unknown };
1530+
1531+
/**
1532+
* Optional metadata about the tool use. Clients SHOULD preserve this field when
1533+
* including tool uses in subsequent sampling requests to enable caching optimizations.
1534+
*
1535+
* See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
1536+
*/
1537+
_meta?: { [key: string]: unknown };
1538+
}
1539+
1540+
/**
1541+
* The result of a tool use, provided by the user back to the assistant.
1542+
*
1543+
* @category `sampling/createMessage`
1544+
*/
1545+
export interface ToolResultContent {
1546+
type: "tool_result";
1547+
1548+
/**
1549+
* The ID of the tool use this result corresponds to.
1550+
*
1551+
* This MUST match the ID from a previous ToolUseContent.
1552+
*/
1553+
toolUseId: string;
1554+
1555+
/**
1556+
* The unstructured result content of the tool use.
1557+
*
1558+
* This has the same format as CallToolResult.content and can include text, images,
1559+
* audio, resource links, and embedded resources.
1560+
*/
1561+
content: ContentBlock[];
1562+
1563+
/**
1564+
* An optional structured result object.
1565+
*
1566+
* If the tool defined an outputSchema, this SHOULD conform to that schema.
1567+
*/
1568+
structuredContent?: { [key: string]: unknown };
1569+
1570+
/**
1571+
* Whether the tool use resulted in an error.
1572+
*
1573+
* If true, the content typically describes the error that occurred.
1574+
* Default: false
1575+
*/
1576+
isError?: boolean;
1577+
1578+
/**
1579+
* Optional metadata about the tool result. Clients SHOULD preserve this field when
1580+
* including tool results in subsequent sampling requests to enable caching optimizations.
1581+
*
1582+
* See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
1583+
*/
1584+
_meta?: { [key: string]: unknown };
1585+
}
1586+
14471587
/**
14481588
* The server's preferences for model selection, requested of the client during sampling.
14491589
*
@@ -1762,7 +1902,6 @@ export interface ElicitRequest extends JSONRPCRequest {
17621902
params: ElicitRequestParams;
17631903
}
17641904

1765-
/**
17661905
/**
17671906
* Restricted schema definitions that only allow primitive types
17681907
* without nested objects or arrays.

0 commit comments

Comments
 (0)