mathpix 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +53 -0
- data/README.md +114 -1
- data/lib/mathpix/batch.rb +7 -8
- data/lib/mathpix/batched_document_conversion.rb +238 -0
- data/lib/mathpix/client.rb +33 -27
- data/lib/mathpix/configuration.rb +5 -9
- data/lib/mathpix/conversion.rb +2 -6
- data/lib/mathpix/document.rb +47 -12
- data/lib/mathpix/document_batcher.rb +191 -0
- data/lib/mathpix/mcp/auth/oauth_provider.rb +8 -9
- data/lib/mathpix/mcp/base_tool.rb +8 -5
- data/lib/mathpix/mcp/elicitations/ambiguity_elicitation.rb +8 -11
- data/lib/mathpix/mcp/elicitations/base_elicitation.rb +2 -0
- data/lib/mathpix/mcp/elicitations/confidence_elicitation.rb +2 -1
- data/lib/mathpix/mcp/elicitations.rb +1 -1
- data/lib/mathpix/mcp/middleware/cors_middleware.rb +2 -6
- data/lib/mathpix/mcp/middleware/oauth_middleware.rb +2 -6
- data/lib/mathpix/mcp/middleware/rate_limiting_middleware.rb +19 -18
- data/lib/mathpix/mcp/resources/formats_list_resource.rb +54 -54
- data/lib/mathpix/mcp/resources/hierarchical_router.rb +9 -18
- data/lib/mathpix/mcp/resources/latest_snip_resource.rb +22 -22
- data/lib/mathpix/mcp/resources/recent_snips_resource.rb +11 -10
- data/lib/mathpix/mcp/resources/snip_stats_resource.rb +14 -12
- data/lib/mathpix/mcp/server.rb +18 -18
- data/lib/mathpix/mcp/tools/batch_convert_tool.rb +31 -37
- data/lib/mathpix/mcp/tools/check_document_status_tool.rb +5 -5
- data/lib/mathpix/mcp/tools/convert_document_tool.rb +15 -14
- data/lib/mathpix/mcp/tools/convert_image_tool.rb +15 -14
- data/lib/mathpix/mcp/tools/convert_strokes_tool.rb +13 -13
- data/lib/mathpix/mcp/tools/get_account_info_tool.rb +1 -1
- data/lib/mathpix/mcp/tools/get_usage_tool.rb +5 -7
- data/lib/mathpix/mcp/tools/list_formats_tool.rb +30 -30
- data/lib/mathpix/mcp/tools/search_results_tool.rb +13 -14
- data/lib/mathpix/mcp/transports/http_streaming_transport.rb +129 -118
- data/lib/mathpix/mcp/transports/sse_stream_handler.rb +37 -35
- data/lib/mathpix/result.rb +3 -2
- data/lib/mathpix/version.rb +1 -1
- data/lib/mathpix.rb +3 -1
- metadata +60 -2
@@ -14,97 +14,97 @@ module Mathpix
|
|
14
14
|
#
|
15
15
|
# @param client [Mathpix::Client] optional client (not used, kept for consistency)
|
16
16
|
# @return [Hash] resource content
|
17
|
-
def self.fetch(
|
17
|
+
def self.fetch(_client = nil)
|
18
18
|
formats = {
|
19
19
|
image_formats: [
|
20
20
|
{
|
21
|
-
name:
|
22
|
-
description:
|
23
|
-
use_case:
|
21
|
+
name: 'latex_styled',
|
22
|
+
description: 'LaTeX with styling commands',
|
23
|
+
use_case: 'Typesetting, display'
|
24
24
|
},
|
25
25
|
{
|
26
|
-
name:
|
27
|
-
description:
|
28
|
-
use_case:
|
26
|
+
name: 'text',
|
27
|
+
description: 'Plain text representation',
|
28
|
+
use_case: 'Simple text extraction'
|
29
29
|
},
|
30
30
|
{
|
31
|
-
name:
|
32
|
-
description:
|
33
|
-
use_case:
|
31
|
+
name: 'latex_list',
|
32
|
+
description: 'Array of LaTeX expressions',
|
33
|
+
use_case: 'Multiple equations'
|
34
34
|
},
|
35
35
|
{
|
36
|
-
name:
|
37
|
-
description:
|
38
|
-
use_case:
|
36
|
+
name: 'mathml',
|
37
|
+
description: 'MathML markup language',
|
38
|
+
use_case: 'Web display, accessibility'
|
39
39
|
},
|
40
40
|
{
|
41
|
-
name:
|
42
|
-
description:
|
43
|
-
use_case:
|
41
|
+
name: 'asciimath',
|
42
|
+
description: 'AsciiMath notation',
|
43
|
+
use_case: 'Simple math notation'
|
44
44
|
},
|
45
45
|
{
|
46
|
-
name:
|
47
|
-
description:
|
48
|
-
use_case:
|
46
|
+
name: 'text_display',
|
47
|
+
description: 'Display-style text',
|
48
|
+
use_case: 'Large equation display'
|
49
49
|
},
|
50
50
|
{
|
51
|
-
name:
|
52
|
-
description:
|
53
|
-
use_case:
|
51
|
+
name: 'latex_simplified',
|
52
|
+
description: 'Simplified LaTeX',
|
53
|
+
use_case: 'Basic LaTeX output'
|
54
54
|
},
|
55
55
|
{
|
56
|
-
name:
|
57
|
-
description:
|
58
|
-
use_case:
|
56
|
+
name: 'data',
|
57
|
+
description: 'Full response with metadata',
|
58
|
+
use_case: 'Complete API response'
|
59
59
|
},
|
60
60
|
{
|
61
|
-
name:
|
62
|
-
description:
|
63
|
-
use_case:
|
61
|
+
name: 'html',
|
62
|
+
description: 'HTML markup',
|
63
|
+
use_case: 'Web integration'
|
64
64
|
}
|
65
65
|
],
|
66
66
|
document_formats: [
|
67
67
|
{
|
68
|
-
name:
|
69
|
-
description:
|
70
|
-
use_case:
|
68
|
+
name: 'markdown',
|
69
|
+
description: 'Markdown document format',
|
70
|
+
use_case: 'Note-taking, documentation'
|
71
71
|
},
|
72
72
|
{
|
73
|
-
name:
|
74
|
-
description:
|
75
|
-
use_case:
|
73
|
+
name: 'latex',
|
74
|
+
description: 'LaTeX document format',
|
75
|
+
use_case: 'Academic papers, typesetting'
|
76
76
|
},
|
77
77
|
{
|
78
|
-
name:
|
79
|
-
description:
|
80
|
-
use_case:
|
78
|
+
name: 'html',
|
79
|
+
description: 'HTML document format',
|
80
|
+
use_case: 'Web publishing'
|
81
81
|
},
|
82
82
|
{
|
83
|
-
name:
|
84
|
-
description:
|
85
|
-
use_case:
|
83
|
+
name: 'docx',
|
84
|
+
description: 'Microsoft Word document',
|
85
|
+
use_case: 'Word processing'
|
86
86
|
},
|
87
87
|
{
|
88
|
-
name:
|
89
|
-
description:
|
90
|
-
use_case:
|
88
|
+
name: 'tex.zip',
|
89
|
+
description: 'LaTeX with figures (zipped)',
|
90
|
+
use_case: 'Complete LaTeX projects'
|
91
91
|
}
|
92
92
|
]
|
93
93
|
}
|
94
94
|
|
95
95
|
{
|
96
|
-
uri:
|
97
|
-
mime_type:
|
96
|
+
uri: 'mathpix://formats/list',
|
97
|
+
mime_type: 'application/json',
|
98
98
|
content: JSON.pretty_generate({
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
99
|
+
success: true,
|
100
|
+
image_formats_count: formats[:image_formats].length,
|
101
|
+
document_formats_count: formats[:document_formats].length,
|
102
|
+
formats: formats,
|
103
|
+
usage: {
|
104
|
+
image_capture: 'Use with Mathpix.snap() or ConvertImageTool',
|
105
|
+
document_conversion: 'Use with Mathpix.document() or ConvertDocumentTool'
|
106
|
+
}
|
107
|
+
})
|
108
108
|
}
|
109
109
|
end
|
110
110
|
end
|
@@ -84,7 +84,7 @@ module Mathpix
|
|
84
84
|
links[:first] = build_link(path, limit, 0, query_params)
|
85
85
|
|
86
86
|
# Previous link (if not on first page)
|
87
|
-
if offset
|
87
|
+
if offset.positive?
|
88
88
|
prev_offset = [offset - limit, 0].max
|
89
89
|
links[:prev] = build_link(path, limit, prev_offset, query_params)
|
90
90
|
end
|
@@ -168,9 +168,7 @@ module Mathpix
|
|
168
168
|
return false if value == 'false'
|
169
169
|
|
170
170
|
# Array (comma-separated)
|
171
|
-
if value.include?(',')
|
172
|
-
return value.split(',').map(&:strip)
|
173
|
-
end
|
171
|
+
return value.split(',').map(&:strip) if value.include?(',')
|
174
172
|
|
175
173
|
# String
|
176
174
|
value
|
@@ -179,9 +177,7 @@ module Mathpix
|
|
179
177
|
def validate_params(params)
|
180
178
|
# Validate limit
|
181
179
|
if params[:limit]
|
182
|
-
unless params[:limit].is_a?(Integer)
|
183
|
-
raise InvalidParameterError, 'limit must be a number'
|
184
|
-
end
|
180
|
+
raise InvalidParameterError, 'limit must be a number' unless params[:limit].is_a?(Integer)
|
185
181
|
|
186
182
|
unless params[:limit].between?(MIN_LIMIT, MAX_LIMIT)
|
187
183
|
raise InvalidParameterError, "limit must be between #{MIN_LIMIT} and #{MAX_LIMIT}"
|
@@ -189,18 +185,13 @@ module Mathpix
|
|
189
185
|
end
|
190
186
|
|
191
187
|
# Validate offset
|
192
|
-
if params[:offset]
|
193
|
-
unless params[:offset].is_a?(Integer)
|
194
|
-
raise InvalidParameterError, 'offset must be a number'
|
195
|
-
end
|
196
|
-
end
|
188
|
+
raise InvalidParameterError, 'offset must be a number' if params[:offset] && !params[:offset].is_a?(Integer)
|
197
189
|
|
198
190
|
# Validate ID format (if present)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
end
|
191
|
+
return unless params[:id]
|
192
|
+
return if params[:id] =~ /^[a-zA-Z0-9_-]+$/
|
193
|
+
|
194
|
+
raise InvalidParameterError, 'id must be alphanumeric'
|
204
195
|
end
|
205
196
|
|
206
197
|
def build_link(path, limit, offset, query_params)
|
@@ -228,7 +219,7 @@ module Mathpix
|
|
228
219
|
{ id: params[:id], line_number: params[:line_number] }
|
229
220
|
end
|
230
221
|
|
231
|
-
def list_snips(
|
222
|
+
def list_snips(_params)
|
232
223
|
[]
|
233
224
|
end
|
234
225
|
end
|
@@ -19,39 +19,39 @@ module Mathpix
|
|
19
19
|
|
20
20
|
if recent.empty?
|
21
21
|
{
|
22
|
-
uri:
|
23
|
-
mime_type:
|
22
|
+
uri: 'mathpix://snip/recent/latest',
|
23
|
+
mime_type: 'application/json',
|
24
24
|
content: JSON.pretty_generate({
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
success: false,
|
26
|
+
message: 'No recent captures found'
|
27
|
+
})
|
28
28
|
}
|
29
29
|
else
|
30
30
|
result = recent.first
|
31
31
|
{
|
32
|
-
uri:
|
33
|
-
mime_type:
|
32
|
+
uri: 'mathpix://snip/recent/latest',
|
33
|
+
mime_type: 'application/json',
|
34
34
|
content: JSON.pretty_generate({
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
35
|
+
success: true,
|
36
|
+
id: result.request_id,
|
37
|
+
created_at: result.timestamp,
|
38
|
+
latex: result.latex,
|
39
|
+
text: result.text,
|
40
|
+
confidence: result.confidence,
|
41
|
+
is_printed: result.printed?,
|
42
|
+
is_handwritten: result.handwritten?,
|
43
|
+
position: result.position
|
44
|
+
})
|
45
45
|
}
|
46
46
|
end
|
47
47
|
rescue Mathpix::Error => e
|
48
48
|
{
|
49
|
-
uri:
|
50
|
-
mime_type:
|
49
|
+
uri: 'mathpix://snip/recent/latest',
|
50
|
+
mime_type: 'application/json',
|
51
51
|
content: JSON.pretty_generate({
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
success: false,
|
53
|
+
error: e.message
|
54
|
+
})
|
55
55
|
}
|
56
56
|
end
|
57
57
|
end
|
@@ -40,22 +40,22 @@ module Mathpix
|
|
40
40
|
|
41
41
|
{
|
42
42
|
uri: "mathpix://snip/recent?limit=#{limit}",
|
43
|
-
mime_type:
|
43
|
+
mime_type: 'application/json',
|
44
44
|
content: JSON.pretty_generate({
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
success: true,
|
46
|
+
limit: limit,
|
47
|
+
count: results.length,
|
48
|
+
results: results
|
49
|
+
})
|
50
50
|
}
|
51
51
|
rescue Mathpix::Error => e
|
52
52
|
{
|
53
53
|
uri: "mathpix://snip/recent?limit=#{limit}",
|
54
|
-
mime_type:
|
54
|
+
mime_type: 'application/json',
|
55
55
|
content: JSON.pretty_generate({
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
success: false,
|
57
|
+
error: e.message
|
58
|
+
})
|
59
59
|
}
|
60
60
|
end
|
61
61
|
|
@@ -67,6 +67,7 @@ module Mathpix
|
|
67
67
|
def self.truncate(text, max_length)
|
68
68
|
return nil unless text
|
69
69
|
return text if text.length <= max_length
|
70
|
+
|
70
71
|
"#{text[0...max_length]}..."
|
71
72
|
end
|
72
73
|
end
|
@@ -27,22 +27,22 @@ module Mathpix
|
|
27
27
|
stats = compute_stats(recent)
|
28
28
|
|
29
29
|
{
|
30
|
-
uri:
|
31
|
-
mime_type:
|
30
|
+
uri: 'mathpix://snip/stats',
|
31
|
+
mime_type: 'application/json',
|
32
32
|
content: JSON.pretty_generate({
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
success: true,
|
34
|
+
period: 'last_100_captures',
|
35
|
+
stats: stats
|
36
|
+
})
|
37
37
|
}
|
38
38
|
rescue Mathpix::Error => e
|
39
39
|
{
|
40
|
-
uri:
|
41
|
-
mime_type:
|
40
|
+
uri: 'mathpix://snip/stats',
|
41
|
+
mime_type: 'application/json',
|
42
42
|
content: JSON.pretty_generate({
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
success: false,
|
44
|
+
error: e.message
|
45
|
+
})
|
46
46
|
}
|
47
47
|
end
|
48
48
|
|
@@ -67,7 +67,9 @@ module Mathpix
|
|
67
67
|
average_confidence: avg_confidence.round(3),
|
68
68
|
confidence_distribution: {
|
69
69
|
high: confidences.count { |c| c >= Mathpix::Configuration::CONFIDENCE_HIGH },
|
70
|
-
medium: confidences.count
|
70
|
+
medium: confidences.count do |c|
|
71
|
+
c >= Mathpix::Configuration::CONFIDENCE_MEDIUM && c < Mathpix::Configuration::CONFIDENCE_HIGH
|
72
|
+
end,
|
71
73
|
low: confidences.count { |c| c < Mathpix::Configuration::CONFIDENCE_MEDIUM }
|
72
74
|
}
|
73
75
|
}
|
data/lib/mathpix/mcp/server.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'mcp'
|
5
|
-
require 'mcp/transports/stdio'
|
5
|
+
require 'mcp/transports/stdio' # Transport classes not auto-loaded
|
6
6
|
rescue LoadError
|
7
7
|
raise LoadError, <<~ERROR
|
8
8
|
The 'mcp' gem is required for MCP server functionality.
|
@@ -52,7 +52,7 @@ module Mathpix
|
|
52
52
|
# @param name [String] server name
|
53
53
|
# @param version [String] server version
|
54
54
|
# @param mathpix_client [Mathpix::Client] optional client instance
|
55
|
-
def initialize(name:
|
55
|
+
def initialize(name: 'mathpix', version: Mathpix::VERSION, mathpix_client: nil)
|
56
56
|
@name = name
|
57
57
|
@version = version
|
58
58
|
@mathpix_client = mathpix_client || Mathpix.client
|
@@ -144,28 +144,28 @@ module Mathpix
|
|
144
144
|
def resource_specs
|
145
145
|
[
|
146
146
|
{
|
147
|
-
uri:
|
148
|
-
name:
|
149
|
-
description:
|
150
|
-
mime_type:
|
147
|
+
uri: 'mathpix://snip/recent/latest',
|
148
|
+
name: 'latest-snip',
|
149
|
+
description: 'Most recent capture result',
|
150
|
+
mime_type: 'application/json'
|
151
151
|
},
|
152
152
|
{
|
153
|
-
uri:
|
154
|
-
name:
|
155
|
-
description:
|
156
|
-
mime_type:
|
153
|
+
uri: 'mathpix://snip/stats',
|
154
|
+
name: 'snip-stats',
|
155
|
+
description: 'Overall capture statistics',
|
156
|
+
mime_type: 'application/json'
|
157
157
|
},
|
158
158
|
{
|
159
|
-
uri:
|
160
|
-
name:
|
161
|
-
description:
|
162
|
-
mime_type:
|
159
|
+
uri: 'mathpix://snip/recent?limit=10',
|
160
|
+
name: 'recent-snips',
|
161
|
+
description: 'Recent capture results (default limit 10)',
|
162
|
+
mime_type: 'application/json'
|
163
163
|
},
|
164
164
|
{
|
165
|
-
uri:
|
166
|
-
name:
|
167
|
-
description:
|
168
|
-
mime_type:
|
165
|
+
uri: 'mathpix://formats/list',
|
166
|
+
name: 'formats-list',
|
167
|
+
description: 'Available output formats',
|
168
|
+
mime_type: 'application/json'
|
169
169
|
}
|
170
170
|
]
|
171
171
|
end
|
@@ -12,33 +12,33 @@ module Mathpix
|
|
12
12
|
#
|
13
13
|
# The geodesic path: official SDK + batch iteration
|
14
14
|
class BatchConvertTool < BaseTool
|
15
|
-
description
|
15
|
+
description 'Convert multiple images in batch using Mathpix OCR'
|
16
16
|
|
17
17
|
input_schema(
|
18
18
|
properties: {
|
19
19
|
image_paths: {
|
20
|
-
type:
|
21
|
-
items: { type:
|
22
|
-
description:
|
20
|
+
type: 'array',
|
21
|
+
items: { type: 'string' },
|
22
|
+
description: 'Array of image paths or URLs to process'
|
23
23
|
},
|
24
24
|
formats: {
|
25
|
-
type:
|
26
|
-
items: { type:
|
27
|
-
description:
|
25
|
+
type: 'array',
|
26
|
+
items: { type: 'string' },
|
27
|
+
description: 'Output formats for all images: latex, text, mathml, asciimath (default: latex_styled, text)'
|
28
28
|
},
|
29
29
|
parallel: {
|
30
|
-
type:
|
31
|
-
description:
|
30
|
+
type: 'boolean',
|
31
|
+
description: 'Process images in parallel (default: false)'
|
32
32
|
},
|
33
33
|
max_parallel: {
|
34
|
-
type:
|
35
|
-
description:
|
34
|
+
type: 'number',
|
35
|
+
description: 'Maximum number of parallel requests (default: 3)'
|
36
36
|
}
|
37
37
|
},
|
38
|
-
required: [
|
38
|
+
required: ['image_paths']
|
39
39
|
)
|
40
40
|
|
41
|
-
def self.call(image_paths:, formats: nil, parallel: false, max_parallel: 3
|
41
|
+
def self.call(image_paths:, server_context:, formats: nil, parallel: false, max_parallel: 3)
|
42
42
|
safe_execute do
|
43
43
|
client = mathpix_client(server_context)
|
44
44
|
|
@@ -51,13 +51,11 @@ module Mathpix
|
|
51
51
|
end
|
52
52
|
|
53
53
|
# Process images
|
54
|
-
|
54
|
+
if parallel
|
55
55
|
# TODO: Implement parallel processing (requires threading)
|
56
56
|
# For now, process sequentially
|
57
|
-
process_batch_sequential(client, normalized_paths, output_formats)
|
58
|
-
else
|
59
|
-
process_batch_sequential(client, normalized_paths, output_formats)
|
60
57
|
end
|
58
|
+
results = process_batch_sequential(client, normalized_paths, output_formats)
|
61
59
|
|
62
60
|
# Format response
|
63
61
|
response_data = {
|
@@ -76,28 +74,24 @@ module Mathpix
|
|
76
74
|
end
|
77
75
|
end
|
78
76
|
|
79
|
-
private
|
80
|
-
|
81
77
|
def self.process_batch_sequential(client, paths, formats)
|
82
78
|
paths.map.with_index do |path, index|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
}
|
100
|
-
end
|
79
|
+
result = client.snap(path, formats: formats)
|
80
|
+
{
|
81
|
+
index: index,
|
82
|
+
image_path: path,
|
83
|
+
success: true,
|
84
|
+
latex: result.latex,
|
85
|
+
text: result.text,
|
86
|
+
confidence: result.confidence
|
87
|
+
}
|
88
|
+
rescue Mathpix::Error => e
|
89
|
+
{
|
90
|
+
index: index,
|
91
|
+
image_path: path,
|
92
|
+
success: false,
|
93
|
+
error: e.message
|
94
|
+
}
|
101
95
|
end
|
102
96
|
end
|
103
97
|
end
|
@@ -12,16 +12,16 @@ module Mathpix
|
|
12
12
|
#
|
13
13
|
# The geodesic path: official SDK + status polling
|
14
14
|
class CheckDocumentStatusTool < BaseTool
|
15
|
-
description
|
15
|
+
description 'Check the status of a document conversion (PDF, DOCX, PPTX)'
|
16
16
|
|
17
17
|
input_schema(
|
18
18
|
properties: {
|
19
19
|
conversion_id: {
|
20
|
-
type:
|
21
|
-
description:
|
20
|
+
type: 'string',
|
21
|
+
description: 'Document conversion ID returned from convert_document'
|
22
22
|
}
|
23
23
|
},
|
24
|
-
required: [
|
24
|
+
required: ['conversion_id']
|
25
25
|
)
|
26
26
|
|
27
27
|
def self.call(conversion_id:, server_context:)
|
@@ -52,7 +52,7 @@ module Mathpix
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Add error info if failed
|
55
|
-
if
|
55
|
+
if %w[error failed].include?(status_data['status'])
|
56
56
|
response_data[:error] = status_data['error']
|
57
57
|
response_data[:error_info] = status_data['error_info']
|
58
58
|
end
|
@@ -12,36 +12,37 @@ module Mathpix
|
|
12
12
|
#
|
13
13
|
# The geodesic path: official SDK + Document class delegation
|
14
14
|
class ConvertDocumentTool < BaseTool
|
15
|
-
description
|
15
|
+
description 'Convert document (PDF, DOCX, PPTX) to Markdown, LaTeX, HTML, or other formats using Mathpix OCR'
|
16
16
|
|
17
17
|
input_schema(
|
18
18
|
properties: {
|
19
19
|
document_path: {
|
20
|
-
type:
|
21
|
-
description:
|
20
|
+
type: 'string',
|
21
|
+
description: 'Path to document file or URL (PDF, DOCX, or PPTX)'
|
22
22
|
},
|
23
23
|
formats: {
|
24
|
-
type:
|
25
|
-
items: { type:
|
26
|
-
description:
|
24
|
+
type: 'array',
|
25
|
+
items: { type: 'string' },
|
26
|
+
description: 'Output formats: markdown, latex, html, docx (default: markdown)'
|
27
27
|
},
|
28
28
|
include_tables: {
|
29
|
-
type:
|
30
|
-
description:
|
29
|
+
type: 'boolean',
|
30
|
+
description: 'Include table extraction as HTML'
|
31
31
|
},
|
32
32
|
max_wait: {
|
33
|
-
type:
|
34
|
-
description:
|
33
|
+
type: 'number',
|
34
|
+
description: 'Maximum wait time in seconds for conversion (default: 600)'
|
35
35
|
},
|
36
36
|
poll_interval: {
|
37
|
-
type:
|
38
|
-
description:
|
37
|
+
type: 'number',
|
38
|
+
description: 'Polling interval in seconds (default: 3.0)'
|
39
39
|
}
|
40
40
|
},
|
41
|
-
required: [
|
41
|
+
required: ['document_path']
|
42
42
|
)
|
43
43
|
|
44
|
-
def self.call(document_path:, formats: nil, include_tables: false, max_wait: 600,
|
44
|
+
def self.call(document_path:, server_context:, formats: nil, include_tables: false, max_wait: 600,
|
45
|
+
poll_interval: 3.0)
|
45
46
|
safe_execute do
|
46
47
|
client = mathpix_client(server_context)
|
47
48
|
|