cf-mcp 0.9.3 → 0.10.1
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 +23 -0
- data/Manifest.txt +0 -1
- data/lib/cf/mcp/cli.rb +8 -2
- data/lib/cf/mcp/models/doc_item.rb +33 -16
- data/lib/cf/mcp/version.rb +1 -1
- metadata +1 -2
- data/config.ru +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4766c9f8bb80d8be199403996163b2e21b7898ea2a8f14e0426d75bbf620364c
|
|
4
|
+
data.tar.gz: bd23236c47957a598c6b69c3f7d3d738d40701ceb2dba97b3afc84a94421ccb7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ea224066e2bb647782d8acc1c5c63855b11eafa4b31c6f649e77b74675443d8c4495b029ba6b0b21c4c85b34cf392f562d80c61d1a2d76d53429d6d94ff3732
|
|
7
|
+
data.tar.gz: 6158b7385eac465183b837e058042f2d648ab108d5a3b9deacadc7bdbe1e013d3bfec1eca58ecd2df1e2c8628b431a2c168d207035ba2bcd39657c6ae63c7992
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.10.1] - 2026-01-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `--host` CLI option for binding address (defaults to `0.0.0.0`)
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Unified boot process: Procfile now uses `cf-mcp combined --download` instead of rackup
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
|
|
20
|
+
- `config.ru` (no longer needed, CLI handles all server modes)
|
|
21
|
+
|
|
22
|
+
## [0.10.0] - 2026-01-14
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Multi-keyword search support: queries like "draw circle rectangle" now match items containing any keyword
|
|
27
|
+
- Items matching more keywords rank higher in search results
|
|
28
|
+
|
|
8
29
|
## [0.9.3] - 2026-01-14
|
|
9
30
|
|
|
10
31
|
### Added
|
|
@@ -105,6 +126,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
105
126
|
- `cf_list_category` - List items by category
|
|
106
127
|
- `cf_get_details` - Get full documentation by name
|
|
107
128
|
|
|
129
|
+
[0.10.1]: https://github.com/pusewicz/cf-mcp/compare/v0.10.0...v0.10.1
|
|
130
|
+
[0.10.0]: https://github.com/pusewicz/cf-mcp/compare/v0.9.3...v0.10.0
|
|
108
131
|
[0.9.3]: https://github.com/pusewicz/cf-mcp/compare/v0.9.2...v0.9.3
|
|
109
132
|
[0.9.2]: https://github.com/pusewicz/cf-mcp/compare/v0.9.1...v0.9.2
|
|
110
133
|
[0.9.1]: https://github.com/pusewicz/cf-mcp/compare/v0.9.0...v0.9.1
|
data/Manifest.txt
CHANGED
data/lib/cf/mcp/cli.rb
CHANGED
|
@@ -41,6 +41,7 @@ module CF
|
|
|
41
41
|
options = {
|
|
42
42
|
command: nil,
|
|
43
43
|
port: nil,
|
|
44
|
+
host: "0.0.0.0",
|
|
44
45
|
root: nil,
|
|
45
46
|
download: false
|
|
46
47
|
}
|
|
@@ -64,6 +65,10 @@ module CF
|
|
|
64
65
|
options[:port] = port
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
opts.on("-H", "--host HOST", "Host to bind to (default: 0.0.0.0)") do |host|
|
|
69
|
+
options[:host] = host
|
|
70
|
+
end
|
|
71
|
+
|
|
67
72
|
opts.on("-d", "--download", "Download Cute Framework headers from GitHub") do
|
|
68
73
|
options[:download] = true
|
|
69
74
|
end
|
|
@@ -136,12 +141,13 @@ module CF
|
|
|
136
141
|
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
137
142
|
|
|
138
143
|
port = @options[:port] || 9292
|
|
144
|
+
host = @options[:host]
|
|
139
145
|
server = CombinedServer.new(index)
|
|
140
146
|
app = server.rack_app
|
|
141
147
|
|
|
142
|
-
warn "Starting combined server on
|
|
148
|
+
warn "Starting combined server on #{host}:#{port}..."
|
|
143
149
|
warn "Web interface available at http://localhost:#{port}/"
|
|
144
|
-
Rackup::Server.start(app: app, Port: port, Logger: $stderr)
|
|
150
|
+
Rackup::Server.start(app: app, Host: host, Port: port, Logger: $stderr)
|
|
145
151
|
end
|
|
146
152
|
|
|
147
153
|
def resolve_headers_path
|
|
@@ -37,45 +37,62 @@ module CF
|
|
|
37
37
|
def matches?(query)
|
|
38
38
|
return true if query.nil? || query.empty?
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
keywords = query.split(/\s+/).reject(&:empty?)
|
|
41
|
+
return true if keywords.empty?
|
|
42
|
+
|
|
43
|
+
keywords.any? do |keyword|
|
|
44
|
+
pattern = Regexp.new(Regexp.escape(keyword), Regexp::IGNORECASE)
|
|
45
|
+
[name, brief, remarks, category].any? { |field| field&.match?(pattern) }
|
|
46
|
+
end
|
|
42
47
|
end
|
|
43
48
|
|
|
44
49
|
# Returns a relevance score for ranking search results.
|
|
45
50
|
# Higher scores indicate better matches.
|
|
51
|
+
# Supports multi-keyword queries - scores are summed across all keywords.
|
|
46
52
|
def relevance_score(query)
|
|
47
53
|
return 0 if query.nil? || query.empty?
|
|
48
54
|
|
|
55
|
+
keywords = query.split(/\s+/).reject(&:empty?)
|
|
56
|
+
return 0 if keywords.empty?
|
|
57
|
+
|
|
58
|
+
keywords.sum { |keyword| keyword_score(keyword) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def keyword_score(keyword)
|
|
49
64
|
score = 0
|
|
50
|
-
|
|
65
|
+
keyword_downcase = keyword.downcase
|
|
51
66
|
name_downcase = name&.downcase || ""
|
|
52
67
|
|
|
53
68
|
# Exact name match (highest priority)
|
|
54
|
-
if name_downcase ==
|
|
69
|
+
if name_downcase == keyword_downcase
|
|
55
70
|
score += 1000
|
|
56
|
-
# Name starts with
|
|
57
|
-
elsif name_downcase.start_with?(
|
|
71
|
+
# Name starts with keyword (prefix match)
|
|
72
|
+
elsif name_downcase.start_with?(keyword_downcase)
|
|
58
73
|
score += 500
|
|
59
|
-
# Name ends with
|
|
60
|
-
elsif name_downcase.end_with?(
|
|
74
|
+
# Name ends with keyword (suffix match)
|
|
75
|
+
elsif name_downcase.end_with?(keyword_downcase)
|
|
61
76
|
score += 400
|
|
62
|
-
# Name contains
|
|
63
|
-
elsif name_downcase.include?(
|
|
77
|
+
# Name contains keyword
|
|
78
|
+
elsif name_downcase.include?(keyword_downcase)
|
|
64
79
|
score += 100
|
|
65
80
|
end
|
|
66
81
|
|
|
67
|
-
# Brief contains
|
|
68
|
-
score += 50 if brief&.downcase&.include?(
|
|
82
|
+
# Brief contains keyword
|
|
83
|
+
score += 50 if brief&.downcase&.include?(keyword_downcase)
|
|
69
84
|
|
|
70
|
-
# Category contains
|
|
71
|
-
score += 30 if category&.downcase&.include?(
|
|
85
|
+
# Category contains keyword
|
|
86
|
+
score += 30 if category&.downcase&.include?(keyword_downcase)
|
|
72
87
|
|
|
73
|
-
# Remarks contains
|
|
74
|
-
score += 10 if remarks&.downcase&.include?(
|
|
88
|
+
# Remarks contains keyword
|
|
89
|
+
score += 10 if remarks&.downcase&.include?(keyword_downcase)
|
|
75
90
|
|
|
76
91
|
score
|
|
77
92
|
end
|
|
78
93
|
|
|
94
|
+
public
|
|
95
|
+
|
|
79
96
|
def source_urls
|
|
80
97
|
return nil unless source_file
|
|
81
98
|
# Header file URLs (include/cute_xxx.h)
|
data/lib/cf/mcp/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cf-mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Piotr Usewicz
|
|
@@ -93,7 +93,6 @@ files:
|
|
|
93
93
|
- Manifest.txt
|
|
94
94
|
- README.md
|
|
95
95
|
- Rakefile
|
|
96
|
-
- config.ru
|
|
97
96
|
- exe/cf-mcp
|
|
98
97
|
- lib/cf/mcp.rb
|
|
99
98
|
- lib/cf/mcp/cli.rb
|
data/config.ru
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "lib/cf/mcp"
|
|
4
|
-
|
|
5
|
-
# Download headers from GitHub if not already present
|
|
6
|
-
warn "Initializing CF::MCP server..."
|
|
7
|
-
downloader = CF::MCP::Downloader.new
|
|
8
|
-
headers_path = downloader.download_and_extract
|
|
9
|
-
warn "Using headers from: #{headers_path}"
|
|
10
|
-
|
|
11
|
-
# Build the index
|
|
12
|
-
warn "Parsing headers..."
|
|
13
|
-
parser = CF::MCP::Parser.new
|
|
14
|
-
index = CF::MCP::Index.new
|
|
15
|
-
|
|
16
|
-
parser.parse_directory(headers_path).each do |item|
|
|
17
|
-
index.add(item)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
21
|
-
|
|
22
|
-
# Create and run the combined server with both SSE and HTTP transports
|
|
23
|
-
# - / and /sse - SSE transport (stateful, for Claude Desktop)
|
|
24
|
-
# - /http - HTTP transport (stateless, for simple integrations)
|
|
25
|
-
server = CF::MCP::CombinedServer.new(index)
|
|
26
|
-
run server.rack_app
|