mbxai 0.6.22__py3-none-any.whl → 0.6.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mbxai/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  MBX AI package.
3
3
  """
4
4
 
5
- __version__ = "0.6.22"
5
+ __version__ = "0.6.23"
mbxai/mcp/client.py CHANGED
@@ -24,8 +24,8 @@ class MCPTool(Tool):
24
24
 
25
25
  def to_openai_function(self) -> dict[str, Any]:
26
26
  """Convert the tool to an OpenAI function definition."""
27
- # Use the base Tool's schema conversion
28
- strict_schema = convert_to_strict_schema(self.input_schema, strict=self.strict)
27
+ # Use the unified schema conversion with keep_input_wrapper=True for MCP tools
28
+ strict_schema = convert_to_strict_schema(self.input_schema, strict=self.strict, keep_input_wrapper=True)
29
29
  logger.info(f"Converted schema for {self.name}: {json.dumps(strict_schema, indent=2)}")
30
30
 
31
31
  return {
@@ -56,11 +56,13 @@ class MCPTool(Tool):
56
56
  # Handle input wrapper
57
57
  if "properties" in mcp_schema and "input" in mcp_schema["properties"]:
58
58
  input_schema = mcp_schema["properties"]["input"]
59
+ logger.info(f"Found input wrapper. Input schema: {json.dumps(input_schema, indent=2)}")
59
60
 
60
61
  # If input has a $ref, resolve it
61
62
  if "$ref" in input_schema:
62
63
  ref = input_schema["$ref"].split("/")[-1]
63
64
  input_schema = mcp_schema.get("$defs", {}).get(ref, {})
65
+ logger.info(f"Resolved $ref to: {json.dumps(input_schema, indent=2)}")
64
66
 
65
67
  # Create the input property schema
66
68
  input_prop_schema = {
@@ -88,10 +90,12 @@ class MCPTool(Tool):
88
90
  new_prop[key] = value
89
91
 
90
92
  input_prop_schema["properties"][prop_name] = new_prop
93
+ logger.info(f"Added property {prop_name}: {json.dumps(new_prop, indent=2)}")
91
94
 
92
95
  # Copy over required fields for input schema
93
96
  if "required" in input_schema:
94
97
  input_prop_schema["required"] = input_schema["required"]
98
+ logger.info(f"Added required fields for input schema: {input_prop_schema['required']}")
95
99
 
96
100
  # Add the input property to the main schema
97
101
  strict_schema["properties"]["input"] = input_prop_schema
@@ -99,7 +103,9 @@ class MCPTool(Tool):
99
103
  # Copy over required fields for main schema
100
104
  if "required" in mcp_schema:
101
105
  strict_schema["required"] = mcp_schema["required"]
106
+ logger.info(f"Added required fields for main schema: {strict_schema['required']}")
102
107
 
108
+ logger.info(f"Final strict schema: {json.dumps(strict_schema, indent=2)}")
103
109
  return strict_schema
104
110
 
105
111
 
mbxai/mcp/server.py CHANGED
@@ -31,7 +31,7 @@ class MCPServer:
31
31
  self.app = FastAPI(
32
32
  title=self.name,
33
33
  description=self.description,
34
- version="0.6.22",
34
+ version="0.6.23",
35
35
  )
36
36
 
37
37
  # Initialize MCP server
mbxai/tools/types.py CHANGED
@@ -9,18 +9,19 @@ import json
9
9
 
10
10
  logger = logging.getLogger(__name__)
11
11
 
12
- def convert_to_strict_schema(schema: dict[str, Any], strict: bool = True) -> dict[str, Any]:
12
+ def convert_to_strict_schema(schema: dict[str, Any], strict: bool = True, keep_input_wrapper: bool = False) -> dict[str, Any]:
13
13
  """Convert a schema to strict format required by OpenAI.
14
14
 
15
15
  Args:
16
16
  schema: The input schema to validate and convert
17
17
  strict: Whether to enforce strict validation with additionalProperties: false
18
+ keep_input_wrapper: Whether to keep the input wrapper (for MCP tools)
18
19
 
19
20
  Returns:
20
21
  A schema in strict format
21
22
  """
22
23
  logger.info(f"Converting schema to strict format. Input schema: {json.dumps(schema, indent=2)}")
23
- logger.info(f"Strict mode: {strict}")
24
+ logger.info(f"Strict mode: {strict}, Keep input wrapper: {keep_input_wrapper}")
24
25
 
25
26
  if not schema:
26
27
  return {"type": "object", "properties": {}, "required": []}
@@ -47,41 +48,91 @@ def convert_to_strict_schema(schema: dict[str, Any], strict: bool = True) -> dic
47
48
  input_schema = schema.get("$defs", {}).get(ref, {})
48
49
  logger.info(f"Resolved $ref to: {json.dumps(input_schema, indent=2)}")
49
50
 
50
- # Create the input property schema
51
- input_prop_schema = {
52
- "type": "object",
53
- "properties": {},
54
- "required": []
55
- }
56
-
57
- # Add additionalProperties: false for input schema
58
- if strict:
59
- input_prop_schema["additionalProperties"] = False
60
-
61
- # Copy over input properties
62
- if "properties" in input_schema:
63
- for prop_name, prop in input_schema["properties"].items():
64
- # Create a new property object with only allowed fields
51
+ if keep_input_wrapper:
52
+ # Create the input property schema
53
+ input_prop_schema = {
54
+ "type": "object",
55
+ "properties": {},
56
+ "required": []
57
+ }
58
+
59
+ # Add additionalProperties: false for input schema
60
+ if strict:
61
+ input_prop_schema["additionalProperties"] = False
62
+
63
+ # Copy over input properties
64
+ if "properties" in input_schema:
65
+ for prop_name, prop in input_schema["properties"].items():
66
+ # Create a new property object with required fields
67
+ new_prop = {
68
+ "type": prop.get("type", "string"),
69
+ "description": prop.get("description", f"The {prop_name} parameter")
70
+ }
71
+
72
+ # Copy over any additional fields that might be useful
73
+ for key, value in prop.items():
74
+ if key not in new_prop:
75
+ new_prop[key] = value
76
+
77
+ input_prop_schema["properties"][prop_name] = new_prop
78
+ logger.info(f"Added property {prop_name}: {json.dumps(new_prop, indent=2)}")
79
+
80
+ # Copy over required fields for input schema
81
+ if "required" in input_schema:
82
+ input_prop_schema["required"] = input_schema["required"]
83
+ logger.info(f"Added required fields for input schema: {input_prop_schema['required']}")
84
+
85
+ # Add the input property to the main schema
86
+ strict_schema["properties"]["input"] = input_prop_schema
87
+
88
+ # Copy over required fields for main schema
89
+ if "required" in schema:
90
+ strict_schema["required"] = schema["required"]
91
+ logger.info(f"Added required fields for main schema: {strict_schema['required']}")
92
+ else:
93
+ # If not keeping input wrapper, use input schema directly
94
+ if "properties" in input_schema:
95
+ for prop_name, prop in input_schema["properties"].items():
96
+ # Create a new property object with required fields
97
+ new_prop = {
98
+ "type": prop.get("type", "string"),
99
+ "description": prop.get("description", f"The {prop_name} parameter")
100
+ }
101
+
102
+ # Copy over any additional fields that might be useful
103
+ for key, value in prop.items():
104
+ if key not in new_prop:
105
+ new_prop[key] = value
106
+
107
+ strict_schema["properties"][prop_name] = new_prop
108
+ logger.info(f"Added property {prop_name}: {json.dumps(new_prop, indent=2)}")
109
+
110
+ # Copy over required fields
111
+ if "required" in input_schema:
112
+ strict_schema["required"] = input_schema["required"]
113
+ logger.info(f"Added required fields: {strict_schema['required']}")
114
+ else:
115
+ # If no input wrapper, use the schema as is
116
+ if "properties" in schema:
117
+ for prop_name, prop in schema["properties"].items():
118
+ # Create a new property object with required fields
65
119
  new_prop = {
66
120
  "type": prop.get("type", "string"),
67
121
  "description": prop.get("description", f"The {prop_name} parameter")
68
122
  }
69
123
 
70
- input_prop_schema["properties"][prop_name] = new_prop
124
+ # Copy over any additional fields that might be useful
125
+ for key, value in prop.items():
126
+ if key not in new_prop:
127
+ new_prop[key] = value
128
+
129
+ strict_schema["properties"][prop_name] = new_prop
71
130
  logger.info(f"Added property {prop_name}: {json.dumps(new_prop, indent=2)}")
72
131
 
73
- # Copy over required fields for input schema
74
- if "required" in input_schema:
75
- input_prop_schema["required"] = input_schema["required"]
76
- logger.info(f"Added required fields for input schema: {input_prop_schema['required']}")
77
-
78
- # Add the input property to the main schema
79
- strict_schema["properties"]["input"] = input_prop_schema
80
-
81
- # Copy over required fields for main schema
132
+ # Copy over required fields
82
133
  if "required" in schema:
83
134
  strict_schema["required"] = schema["required"]
84
- logger.info(f"Added required fields for main schema: {strict_schema['required']}")
135
+ logger.info(f"Added required fields: {strict_schema['required']}")
85
136
 
86
137
  logger.info(f"Final strict schema: {json.dumps(strict_schema, indent=2)}")
87
138
  return strict_schema
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mbxai
3
- Version: 0.6.22
3
+ Version: 0.6.23
4
4
  Summary: MBX AI SDK
5
5
  Project-URL: Homepage, https://www.mibexx.de
6
6
  Project-URL: Documentation, https://www.mibexx.de
@@ -1,9 +1,9 @@
1
- mbxai/__init__.py,sha256=yg4sZUYaTu5lJqkUoW6bkIZhWpjbkcSLbNTkfDhD_5I,48
1
+ mbxai/__init__.py,sha256=sXELKJtZXTLn227-FJ-5b3CCiKmyNk74UWVjduIoeeE,48
2
2
  mbxai/core.py,sha256=WMvmU9TTa7M_m-qWsUew4xH8Ul6xseCZ2iBCXJTW-Bs,196
3
3
  mbxai/mcp/__init__.py,sha256=_ek9iYdYqW5saKetj4qDci11jxesQDiHPJRpHMKkxgU,175
4
- mbxai/mcp/client.py,sha256=EtgrKiTsHHeAzmnsYCOJMiu-i-k06kJZqR_L2bz91pw,7843
4
+ mbxai/mcp/client.py,sha256=2aX5zMe0vSxZSdvfxoHDA5p_aQSqV1bhX_-QopG2uX8,8477
5
5
  mbxai/mcp/example.py,sha256=oaol7AvvZnX86JWNz64KvPjab5gg1VjVN3G8eFSzuaE,2350
6
- mbxai/mcp/server.py,sha256=oFDL4CHXJxIpH1btcWTlxm4mLztfrY6X8cKI30HZxj0,3463
6
+ mbxai/mcp/server.py,sha256=2rQtXDie1hx9ofm5py779pjvdZXslY4bYcCXHfzFQ6E,3463
7
7
  mbxai/openrouter/__init__.py,sha256=Ito9Qp_B6q-RLGAQcYyTJVWwR2YAZvNqE-HIYXxhtD8,298
8
8
  mbxai/openrouter/client.py,sha256=nusxYObyLAMGQd6J9u2uLfkRXyE5kZmdIGdlU-76HPo,13529
9
9
  mbxai/openrouter/config.py,sha256=Ia93s-auim9Sq71eunVDbn9ET5xX2zusXpV4JBdHAzs,3251
@@ -11,8 +11,8 @@ mbxai/openrouter/models.py,sha256=b3IjjtZAjeGOf2rLsdnCD1HacjTnS8jmv_ZXorc-KJQ,26
11
11
  mbxai/tools/__init__.py,sha256=ogxrHvgJ7OR62Lmd5x9Eh5d2C0jqWyQis7Zy3yKpZ78,218
12
12
  mbxai/tools/client.py,sha256=qOf8MiQ8_flPUNiMioOyjeEaV8rN1EBWb98T8qTC3D4,17582
13
13
  mbxai/tools/example.py,sha256=1HgKK39zzUuwFbnp3f0ThyWVfA_8P28PZcTwaUw5K78,2232
14
- mbxai/tools/types.py,sha256=iyoSnRwr_Anf7qBybAQ_-dqFnDmABmrtPpgef3R7PV0,4193
15
- mbxai-0.6.22.dist-info/METADATA,sha256=sK-8ps0-u6T-8CaR8Rfgw1ZZ3wg7SI3On1ZwMQ7PQ2I,4148
16
- mbxai-0.6.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- mbxai-0.6.22.dist-info/licenses/LICENSE,sha256=hEyhc4FxwYo3NQ40yNgZ7STqwVk-1_XcTXOnAPbGJAw,1069
18
- mbxai-0.6.22.dist-info/RECORD,,
14
+ mbxai/tools/types.py,sha256=NA-9JvbKbNpg7LzUwuDlssBVfQoRI_5t8-UR4zGPqXM,6966
15
+ mbxai-0.6.23.dist-info/METADATA,sha256=MdcRJaBfxIslGOWZvrUXe1HgrLxRUwb0jK9xQtAJBzo,4148
16
+ mbxai-0.6.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ mbxai-0.6.23.dist-info/licenses/LICENSE,sha256=hEyhc4FxwYo3NQ40yNgZ7STqwVk-1_XcTXOnAPbGJAw,1069
18
+ mbxai-0.6.23.dist-info/RECORD,,
File without changes