|
9 | 9 | import java.util.List;
|
10 | 10 | import java.util.Map;
|
11 | 11 |
|
| 12 | +import com.fasterxml.jackson.core.type.TypeReference; |
12 | 13 | import com.fasterxml.jackson.databind.ObjectMapper;
|
13 | 14 | import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
|
14 | 15 | import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
|
@@ -449,6 +450,92 @@ void testGetPromptResult() throws Exception {
|
449 | 450 |
|
450 | 451 | // Tool Tests
|
451 | 452 |
|
| 453 | + @Test |
| 454 | + void testJsonSchema() throws Exception { |
| 455 | + String schemaJson = """ |
| 456 | + { |
| 457 | + "type": "object", |
| 458 | + "properties": { |
| 459 | + "name": { |
| 460 | + "type": "string" |
| 461 | + }, |
| 462 | + "address": { |
| 463 | + "$ref": "#/$defs/Address" |
| 464 | + } |
| 465 | + }, |
| 466 | + "required": ["name"], |
| 467 | + "$defs": { |
| 468 | + "Address": { |
| 469 | + "type": "object", |
| 470 | + "properties": { |
| 471 | + "street": {"type": "string"}, |
| 472 | + "city": {"type": "string"} |
| 473 | + }, |
| 474 | + "required": ["street", "city"] |
| 475 | + } |
| 476 | + } |
| 477 | + } |
| 478 | + """; |
| 479 | + |
| 480 | + // Deserialize the original string to a JsonSchema object |
| 481 | + McpSchema.JsonSchema schema = mapper.readValue(schemaJson, McpSchema.JsonSchema.class); |
| 482 | + |
| 483 | + // Serialize the object back to a string |
| 484 | + String serialized = mapper.writeValueAsString(schema); |
| 485 | + |
| 486 | + // Deserialize again |
| 487 | + McpSchema.JsonSchema deserialized = mapper.readValue(serialized, McpSchema.JsonSchema.class); |
| 488 | + |
| 489 | + // Serialize one more time and compare with the first serialization |
| 490 | + String serializedAgain = mapper.writeValueAsString(deserialized); |
| 491 | + |
| 492 | + // The two serialized strings should be the same |
| 493 | + assertThatJson(serializedAgain).when(Option.IGNORING_ARRAY_ORDER).isEqualTo(json(serialized)); |
| 494 | + } |
| 495 | + |
| 496 | + @Test |
| 497 | + void testJsonSchemaWithDefinitions() throws Exception { |
| 498 | + String schemaJson = """ |
| 499 | + { |
| 500 | + "type": "object", |
| 501 | + "properties": { |
| 502 | + "name": { |
| 503 | + "type": "string" |
| 504 | + }, |
| 505 | + "address": { |
| 506 | + "$ref": "#/definitions/Address" |
| 507 | + } |
| 508 | + }, |
| 509 | + "required": ["name"], |
| 510 | + "definitions": { |
| 511 | + "Address": { |
| 512 | + "type": "object", |
| 513 | + "properties": { |
| 514 | + "street": {"type": "string"}, |
| 515 | + "city": {"type": "string"} |
| 516 | + }, |
| 517 | + "required": ["street", "city"] |
| 518 | + } |
| 519 | + } |
| 520 | + } |
| 521 | + """; |
| 522 | + |
| 523 | + // Deserialize the original string to a JsonSchema object |
| 524 | + McpSchema.JsonSchema schema = mapper.readValue(schemaJson, McpSchema.JsonSchema.class); |
| 525 | + |
| 526 | + // Serialize the object back to a string |
| 527 | + String serialized = mapper.writeValueAsString(schema); |
| 528 | + |
| 529 | + // Deserialize again |
| 530 | + McpSchema.JsonSchema deserialized = mapper.readValue(serialized, McpSchema.JsonSchema.class); |
| 531 | + |
| 532 | + // Serialize one more time and compare with the first serialization |
| 533 | + String serializedAgain = mapper.writeValueAsString(deserialized); |
| 534 | + |
| 535 | + // The two serialized strings should be the same |
| 536 | + assertThatJson(serializedAgain).when(Option.IGNORING_ARRAY_ORDER).isEqualTo(json(serialized)); |
| 537 | + } |
| 538 | + |
452 | 539 | @Test
|
453 | 540 | void testTool() throws Exception {
|
454 | 541 | String schemaJson = """
|
@@ -477,6 +564,48 @@ void testTool() throws Exception {
|
477 | 564 | {"name":"test-tool","description":"A test tool","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"number"}},"required":["name"]}}"""));
|
478 | 565 | }
|
479 | 566 |
|
| 567 | + @Test |
| 568 | + void testToolWithComplexSchema() throws Exception { |
| 569 | + String complexSchemaJson = """ |
| 570 | + { |
| 571 | + "type": "object", |
| 572 | + "$defs": { |
| 573 | + "Address": { |
| 574 | + "type": "object", |
| 575 | + "properties": { |
| 576 | + "street": {"type": "string"}, |
| 577 | + "city": {"type": "string"} |
| 578 | + }, |
| 579 | + "required": ["street", "city"] |
| 580 | + } |
| 581 | + }, |
| 582 | + "properties": { |
| 583 | + "name": {"type": "string"}, |
| 584 | + "shippingAddress": {"$ref": "#/$defs/Address"} |
| 585 | + }, |
| 586 | + "required": ["name", "shippingAddress"] |
| 587 | + } |
| 588 | + """; |
| 589 | + |
| 590 | + McpSchema.Tool tool = new McpSchema.Tool("addressTool", "Handles addresses", complexSchemaJson); |
| 591 | + |
| 592 | + // Serialize the tool to a string |
| 593 | + String serialized = mapper.writeValueAsString(tool); |
| 594 | + |
| 595 | + // Deserialize back to a Tool object |
| 596 | + McpSchema.Tool deserializedTool = mapper.readValue(serialized, McpSchema.Tool.class); |
| 597 | + |
| 598 | + // Serialize again and compare with first serialization |
| 599 | + String serializedAgain = mapper.writeValueAsString(deserializedTool); |
| 600 | + |
| 601 | + // The two serialized strings should be the same |
| 602 | + assertThatJson(serializedAgain).when(Option.IGNORING_ARRAY_ORDER).isEqualTo(json(serialized)); |
| 603 | + |
| 604 | + // Just verify the basic structure was preserved |
| 605 | + assertThat(deserializedTool.inputSchema().defs()).isNotNull(); |
| 606 | + assertThat(deserializedTool.inputSchema().defs()).containsKey("Address"); |
| 607 | + } |
| 608 | + |
480 | 609 | @Test
|
481 | 610 | void testCallToolRequest() throws Exception {
|
482 | 611 | Map<String, Object> arguments = new HashMap<>();
|
|
0 commit comments