mathpix-mcp 1.0.0
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 +7 -0
- data/CHANGELOG.md +44 -0
- data/LICENSE +22 -0
- data/README.md +403 -0
- data/bin/mathpix-mcp +46 -0
- data/bin/mathpix-mcp-http +39 -0
- data/config.ru +24 -0
- data/lib/mathpix/client.rb +534 -0
- data/lib/mathpix/configuration.rb +182 -0
- data/lib/mathpix/document.rb +345 -0
- data/lib/mathpix/errors.rb +78 -0
- data/lib/mathpix/mcp/base_tool.rb +225 -0
- data/lib/mathpix/mcp/http_app.rb +60 -0
- data/lib/mathpix/mcp/server.rb +124 -0
- data/lib/mathpix/mcp/tools/batch_convert_tool.rb +147 -0
- data/lib/mathpix/mcp/tools/check_document_status_tool.rb +70 -0
- data/lib/mathpix/mcp/tools/convert_document_tool.rb +176 -0
- data/lib/mathpix/mcp/tools/convert_image_tool.rb +108 -0
- data/lib/mathpix/mcp/tools/convert_strokes_tool.rb +97 -0
- data/lib/mathpix/mcp/tools/get_account_info_tool.rb +47 -0
- data/lib/mathpix/mcp/tools/get_usage_tool.rb +61 -0
- data/lib/mathpix/mcp/tools/list_formats_tool.rb +79 -0
- data/lib/mathpix/mcp/tools/search_results_tool.rb +116 -0
- data/lib/mathpix/mcp.rb +31 -0
- data/lib/mathpix/result.rb +387 -0
- data/lib/mathpix/version.rb +5 -0
- data/lib/mathpix.rb +52 -0
- metadata +132 -0
data/lib/mathpix/mcp.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# MCP (Model Context Protocol) integration for Mathpix
|
|
4
|
+
#
|
|
5
|
+
# This module provides MCP server functionality using the official Ruby MCP SDK.
|
|
6
|
+
# All 9 tools are thin delegates to the core Mathpix::Client.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# require 'mathpix/mcp'
|
|
10
|
+
#
|
|
11
|
+
# Mathpix.configure do |config|
|
|
12
|
+
# config.app_id = ENV['MATHPIX_APP_ID']
|
|
13
|
+
# config.app_key = ENV['MATHPIX_APP_KEY']
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# Mathpix::MCP::Server.run
|
|
17
|
+
|
|
18
|
+
# Load MCP components (stdio server only)
|
|
19
|
+
require_relative 'mcp/server'
|
|
20
|
+
require_relative 'mcp/base_tool'
|
|
21
|
+
|
|
22
|
+
# Load all 9 tools
|
|
23
|
+
require_relative 'mcp/tools/convert_image_tool'
|
|
24
|
+
require_relative 'mcp/tools/convert_document_tool'
|
|
25
|
+
require_relative 'mcp/tools/convert_strokes_tool'
|
|
26
|
+
require_relative 'mcp/tools/batch_convert_tool'
|
|
27
|
+
require_relative 'mcp/tools/check_document_status_tool'
|
|
28
|
+
require_relative 'mcp/tools/search_results_tool'
|
|
29
|
+
require_relative 'mcp/tools/get_usage_tool'
|
|
30
|
+
require_relative 'mcp/tools/get_account_info_tool'
|
|
31
|
+
require_relative 'mcp/tools/list_formats_tool'
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mathpix
|
|
4
|
+
# OCR Result object
|
|
5
|
+
class Result
|
|
6
|
+
attr_reader :data, :source_path
|
|
7
|
+
|
|
8
|
+
def initialize(data, source_path = nil)
|
|
9
|
+
@data = data
|
|
10
|
+
@source_path = source_path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Get source URL if image was processed from URL
|
|
14
|
+
#
|
|
15
|
+
# @return [String, nil] URL if source was remote, nil otherwise
|
|
16
|
+
def source_url
|
|
17
|
+
return nil unless @source_path.is_a?(String)
|
|
18
|
+
|
|
19
|
+
@source_path.start_with?('http://', 'https://') ? @source_path : nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Text result
|
|
23
|
+
# @return [String, nil]
|
|
24
|
+
def text
|
|
25
|
+
data['text']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# LaTeX styled output
|
|
29
|
+
# @return [String, nil]
|
|
30
|
+
def latex
|
|
31
|
+
data['latex_styled'] || data['latex']
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
alias latex_styled latex
|
|
35
|
+
|
|
36
|
+
# Simplified LaTeX
|
|
37
|
+
# @return [String, nil]
|
|
38
|
+
def latex_simplified
|
|
39
|
+
data['latex_simplified']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# MathML output
|
|
43
|
+
# @return [String, nil]
|
|
44
|
+
def mathml
|
|
45
|
+
data['mathml']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# AsciiMath output
|
|
49
|
+
# @return [String, nil]
|
|
50
|
+
def asciimath
|
|
51
|
+
data['asciimath']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# HTML output (may contain SVG)
|
|
55
|
+
# @return [String, nil]
|
|
56
|
+
def html
|
|
57
|
+
data['html']
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Confidence score
|
|
61
|
+
# @return [Float] 0.0-1.0
|
|
62
|
+
def confidence
|
|
63
|
+
data['confidence'] || 0.0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Confidence rate (alternative)
|
|
67
|
+
# @return [Float] 0.0-1.0
|
|
68
|
+
def confidence_rate
|
|
69
|
+
data['confidence_rate'] || confidence
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Created timestamp
|
|
73
|
+
# @return [Time, nil]
|
|
74
|
+
def created_at
|
|
75
|
+
Time.parse(data['created']) if data['created']
|
|
76
|
+
rescue ArgumentError
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Request ID
|
|
81
|
+
# @return [String, nil]
|
|
82
|
+
def request_id
|
|
83
|
+
data['request_id']
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Processing time in milliseconds
|
|
87
|
+
# @return [Integer, nil]
|
|
88
|
+
def processing_time_ms
|
|
89
|
+
data['processing_time_ms']
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Bounding box / position of the detected region, if the API returned one.
|
|
93
|
+
# @return [Hash, nil]
|
|
94
|
+
def position
|
|
95
|
+
data['position']
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Raw capture timestamp (used by recent/search results).
|
|
99
|
+
# @return [String, nil]
|
|
100
|
+
def timestamp
|
|
101
|
+
data['timestamp'] || data['created']
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Line-level data array (alias for lines_json).
|
|
105
|
+
# @return [Array<Hash>]
|
|
106
|
+
def line_data
|
|
107
|
+
lines_json
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Word-level data array, if present.
|
|
111
|
+
# @return [Array<Hash>]
|
|
112
|
+
def word_data
|
|
113
|
+
data['word_data'] || []
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Is content printed (vs handwritten)?
|
|
117
|
+
# @return [Boolean]
|
|
118
|
+
def printed?
|
|
119
|
+
data['is_printed'] == true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Is content handwritten?
|
|
123
|
+
# @return [Boolean]
|
|
124
|
+
def handwritten?
|
|
125
|
+
data['is_handwritten'] == true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Contains chart?
|
|
129
|
+
# @return [Boolean]
|
|
130
|
+
def chart?
|
|
131
|
+
data['contains_chart'] == true
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Contains diagram?
|
|
135
|
+
# @return [Boolean]
|
|
136
|
+
def diagram?
|
|
137
|
+
data['contains_diagram'] == true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Contains table?
|
|
141
|
+
# @return [Boolean]
|
|
142
|
+
def table?
|
|
143
|
+
data['contains_table'] == true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Get metadata
|
|
147
|
+
# @return [Hash]
|
|
148
|
+
def metadata
|
|
149
|
+
data['metadata'] || {}
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get tags
|
|
153
|
+
# @return [Array<String>]
|
|
154
|
+
def tags
|
|
155
|
+
data['tags'] || []
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# --- Line-by-line data ---
|
|
159
|
+
|
|
160
|
+
# Get line-by-line data with bounding boxes
|
|
161
|
+
#
|
|
162
|
+
# Requires snap(..., include_line_data: true)
|
|
163
|
+
#
|
|
164
|
+
# @return [Array<Line>] array of line objects
|
|
165
|
+
def lines
|
|
166
|
+
return [] unless data['line_data']
|
|
167
|
+
|
|
168
|
+
@lines ||= data['line_data'].map { |line_data| Line.new(line_data) }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Get lines as JSON array (raw data)
|
|
172
|
+
# @return [Array<Hash>]
|
|
173
|
+
def lines_json
|
|
174
|
+
data['line_data'] || []
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Line data structure for bounding boxes and confidence
|
|
178
|
+
class Line
|
|
179
|
+
attr_reader :data
|
|
180
|
+
|
|
181
|
+
def initialize(data)
|
|
182
|
+
@data = data
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Line text content
|
|
186
|
+
# @return [String]
|
|
187
|
+
def text
|
|
188
|
+
data['text'] || ''
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Line confidence
|
|
192
|
+
# @return [Float]
|
|
193
|
+
def confidence
|
|
194
|
+
data['confidence'] || 0.0
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Bounding box coordinates [x, y, width, height]
|
|
198
|
+
# @return [Array<Integer>, nil]
|
|
199
|
+
def bbox
|
|
200
|
+
data['bbox']
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
alias bounding_box bbox
|
|
204
|
+
|
|
205
|
+
# Is this line handwritten?
|
|
206
|
+
# @return [Boolean]
|
|
207
|
+
def handwritten?
|
|
208
|
+
data['type'] == 'handwriting'
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Is this line printed?
|
|
212
|
+
# @return [Boolean]
|
|
213
|
+
def printed?
|
|
214
|
+
%w[printed print].include?(data['type'])
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# LaTeX for this line
|
|
218
|
+
# @return [String, nil]
|
|
219
|
+
def latex
|
|
220
|
+
data['latex']
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# MathML for this line
|
|
224
|
+
# @return [String, nil]
|
|
225
|
+
def mathml
|
|
226
|
+
data['mathml']
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Word-level data (if available)
|
|
230
|
+
# @return [Array<Word>]
|
|
231
|
+
def words
|
|
232
|
+
return [] unless data['words']
|
|
233
|
+
|
|
234
|
+
@words ||= data['words'].map { |word_data| Word.new(word_data) }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Convert to hash
|
|
238
|
+
# @return [Hash]
|
|
239
|
+
def to_h
|
|
240
|
+
data
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Inspect
|
|
244
|
+
# @return [String]
|
|
245
|
+
def inspect
|
|
246
|
+
"#<Mathpix::Result::Line text=\"#{text&.[](0..30)}\" confidence=#{confidence}>"
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Word data structure for fine-grained bounding boxes
|
|
251
|
+
class Word
|
|
252
|
+
attr_reader :data
|
|
253
|
+
|
|
254
|
+
def initialize(data)
|
|
255
|
+
@data = data
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Word text
|
|
259
|
+
# @return [String]
|
|
260
|
+
def text
|
|
261
|
+
data['text'] || ''
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Word confidence
|
|
265
|
+
# @return [Float]
|
|
266
|
+
def confidence
|
|
267
|
+
data['confidence'] || 0.0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Word bounding box
|
|
271
|
+
# @return [Array<Integer>, nil]
|
|
272
|
+
def bbox
|
|
273
|
+
data['bbox']
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Convert to hash
|
|
277
|
+
# @return [Hash]
|
|
278
|
+
def to_h
|
|
279
|
+
data
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Inspect
|
|
283
|
+
# @return [String]
|
|
284
|
+
def inspect
|
|
285
|
+
"#<Mathpix::Result::Word text=\"#{text}\" confidence=#{confidence}>"
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Convert to hash
|
|
290
|
+
# @return [Hash]
|
|
291
|
+
def to_h
|
|
292
|
+
data
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Convert to JSON
|
|
296
|
+
# @return [String]
|
|
297
|
+
def to_json(*)
|
|
298
|
+
data.to_json(*)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Inspect
|
|
302
|
+
# @return [String]
|
|
303
|
+
def inspect
|
|
304
|
+
"#<Mathpix::Result confidence=#{confidence} text=#{text&.[](0..50)}>"
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# --- Chemistry-specific methods ---
|
|
308
|
+
|
|
309
|
+
# SMILES notation (chemistry)
|
|
310
|
+
# @return [String, nil]
|
|
311
|
+
def smiles
|
|
312
|
+
text if chemistry?
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# InChI notation (chemistry)
|
|
316
|
+
# @return [String, nil]
|
|
317
|
+
def inchi
|
|
318
|
+
data['inchi']
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# InChI Key (chemistry)
|
|
322
|
+
# @return [String, nil]
|
|
323
|
+
def inchikey
|
|
324
|
+
data['inchikey']
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Molecular formula
|
|
328
|
+
# @return [String, nil]
|
|
329
|
+
def molecular_formula
|
|
330
|
+
data['molecular_formula']
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Molecular name
|
|
334
|
+
# @return [String, nil]
|
|
335
|
+
def molecular_name
|
|
336
|
+
data['molecular_name']
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# Molecular weight
|
|
340
|
+
# @return [Float, nil]
|
|
341
|
+
def molecular_weight
|
|
342
|
+
data['molecular_weight']
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Has stereochemistry?
|
|
346
|
+
# @return [Boolean]
|
|
347
|
+
def stereochemistry?
|
|
348
|
+
data['has_stereochemistry'] == true || smiles&.include?('@')
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Is this a chemistry result?
|
|
352
|
+
# @return [Boolean]
|
|
353
|
+
def chemistry?
|
|
354
|
+
molecular_formula || inchi || smiles&.match?(%r{^[A-Za-z0-9@\[\]()=#+\-\\/.]+$})
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# --- Success/Failure ---
|
|
358
|
+
|
|
359
|
+
# Was capture successful?
|
|
360
|
+
# @return [Boolean]
|
|
361
|
+
def success?
|
|
362
|
+
!text.nil? && confidence >= 0.5
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# Was capture a failure?
|
|
366
|
+
# @return [Boolean]
|
|
367
|
+
def failure?
|
|
368
|
+
!success?
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Execute block if successful
|
|
372
|
+
# @yield [self]
|
|
373
|
+
# @return [self]
|
|
374
|
+
def on_success
|
|
375
|
+
yield self if success?
|
|
376
|
+
self
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Execute block if failed
|
|
380
|
+
# @yield [self]
|
|
381
|
+
# @return [self]
|
|
382
|
+
def on_failure
|
|
383
|
+
yield self if failure?
|
|
384
|
+
self
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
data/lib/mathpix.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'base64'
|
|
7
|
+
|
|
8
|
+
require_relative 'mathpix/version'
|
|
9
|
+
require_relative 'mathpix/errors'
|
|
10
|
+
require_relative 'mathpix/configuration'
|
|
11
|
+
require_relative 'mathpix/result'
|
|
12
|
+
require_relative 'mathpix/client'
|
|
13
|
+
require_relative 'mathpix/document'
|
|
14
|
+
|
|
15
|
+
# Mathpix OCR engine for the MCP server.
|
|
16
|
+
#
|
|
17
|
+
# The classes under Mathpix:: are the engine the MCP tools delegate to
|
|
18
|
+
# (see lib/mathpix/mcp). Only configuration and the shared client instance are
|
|
19
|
+
# exposed at the top level — there is no general-purpose client API.
|
|
20
|
+
module Mathpix
|
|
21
|
+
class << self
|
|
22
|
+
# Configure the Mathpix client.
|
|
23
|
+
#
|
|
24
|
+
# @yield [Configuration] config object
|
|
25
|
+
# @example
|
|
26
|
+
# Mathpix.configure do |config|
|
|
27
|
+
# config.app_id = ENV['MATHPIX_APP_ID']
|
|
28
|
+
# config.app_key = ENV['MATHPIX_APP_KEY']
|
|
29
|
+
# end
|
|
30
|
+
def configure
|
|
31
|
+
yield configuration
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Current configuration.
|
|
35
|
+
# @return [Configuration]
|
|
36
|
+
def configuration
|
|
37
|
+
@configuration ||= Configuration.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Shared client instance used by the MCP tools.
|
|
41
|
+
# @return [Client]
|
|
42
|
+
def client
|
|
43
|
+
@client ||= Client.new(configuration)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Reset configuration and client (mainly for tests).
|
|
47
|
+
def reset!
|
|
48
|
+
@configuration = Configuration.new
|
|
49
|
+
@client = nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mathpix-mcp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Georgios Douzas
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: base64
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: mcp
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 0.9.2
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 0.9.2
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: puma
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 8.0.2
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 8.0.2
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rack
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.1'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.1'
|
|
68
|
+
description: |
|
|
69
|
+
A Model Context Protocol server for Mathpix OCR, over stdio or Streamable
|
|
70
|
+
HTTP (bearer-token auth). Exposes tools to convert images and PDF/DOCX/PPTX
|
|
71
|
+
documents to LaTeX and Markdown, with descriptive errors and optional file
|
|
72
|
+
output for large results.
|
|
73
|
+
email:
|
|
74
|
+
- georgios.douzas@gmail.com
|
|
75
|
+
executables:
|
|
76
|
+
- mathpix-mcp
|
|
77
|
+
- mathpix-mcp-http
|
|
78
|
+
extensions: []
|
|
79
|
+
extra_rdoc_files: []
|
|
80
|
+
files:
|
|
81
|
+
- CHANGELOG.md
|
|
82
|
+
- LICENSE
|
|
83
|
+
- README.md
|
|
84
|
+
- bin/mathpix-mcp
|
|
85
|
+
- bin/mathpix-mcp-http
|
|
86
|
+
- config.ru
|
|
87
|
+
- lib/mathpix.rb
|
|
88
|
+
- lib/mathpix/client.rb
|
|
89
|
+
- lib/mathpix/configuration.rb
|
|
90
|
+
- lib/mathpix/document.rb
|
|
91
|
+
- lib/mathpix/errors.rb
|
|
92
|
+
- lib/mathpix/mcp.rb
|
|
93
|
+
- lib/mathpix/mcp/base_tool.rb
|
|
94
|
+
- lib/mathpix/mcp/http_app.rb
|
|
95
|
+
- lib/mathpix/mcp/server.rb
|
|
96
|
+
- lib/mathpix/mcp/tools/batch_convert_tool.rb
|
|
97
|
+
- lib/mathpix/mcp/tools/check_document_status_tool.rb
|
|
98
|
+
- lib/mathpix/mcp/tools/convert_document_tool.rb
|
|
99
|
+
- lib/mathpix/mcp/tools/convert_image_tool.rb
|
|
100
|
+
- lib/mathpix/mcp/tools/convert_strokes_tool.rb
|
|
101
|
+
- lib/mathpix/mcp/tools/get_account_info_tool.rb
|
|
102
|
+
- lib/mathpix/mcp/tools/get_usage_tool.rb
|
|
103
|
+
- lib/mathpix/mcp/tools/list_formats_tool.rb
|
|
104
|
+
- lib/mathpix/mcp/tools/search_results_tool.rb
|
|
105
|
+
- lib/mathpix/result.rb
|
|
106
|
+
- lib/mathpix/version.rb
|
|
107
|
+
homepage: https://github.com/georgedouzas/mathpix-mcp
|
|
108
|
+
licenses:
|
|
109
|
+
- MIT
|
|
110
|
+
metadata:
|
|
111
|
+
rubygems_mfa_required: 'true'
|
|
112
|
+
source_code_uri: https://github.com/georgedouzas/mathpix-mcp
|
|
113
|
+
changelog_uri: https://github.com/georgedouzas/mathpix-mcp/blob/main/CHANGELOG.md
|
|
114
|
+
bug_tracker_uri: https://github.com/georgedouzas/mathpix-mcp/issues
|
|
115
|
+
rdoc_options: []
|
|
116
|
+
require_paths:
|
|
117
|
+
- lib
|
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - ">="
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: 3.2.0
|
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - ">="
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '0'
|
|
128
|
+
requirements: []
|
|
129
|
+
rubygems_version: 3.6.9
|
|
130
|
+
specification_version: 4
|
|
131
|
+
summary: Mathpix OCR MCP server (stdio + HTTP)
|
|
132
|
+
test_files: []
|