cf-mcp 0.17.2 → 0.19.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 +4 -4
- data/CHANGELOG.md +15 -1
- data/Manifest.txt +1 -1
- data/Rakefile +1 -1
- data/config/puma.rb +17 -0
- data/exe/cf-mcp +0 -1
- data/lib/cf/mcp/cli.rb +2 -1
- data/lib/cf/mcp/downloader.rb +3 -0
- data/lib/cf/mcp/index_builder.rb +30 -3
- data/lib/cf/mcp/parser.rb +1 -0
- data/lib/cf/mcp/server.rb +13 -5
- data/lib/cf/mcp/templates/index.erb +6 -0
- data/lib/cf/mcp/version.rb +1 -1
- metadata +19 -6
- data/exe/cf-mcp-wrapper +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8503e2b733dd80a28ab4e44b5435ce8ca334ba25a0bd34a3751c2b986beea8dc
|
|
4
|
+
data.tar.gz: f4b986ddb96f77b7bc97c5b56384b6aaae88ee73f1f030a184409e64c78cd317
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e408e0273973b658e8eb883946d350b25a899d901e5f0940bbb4e9cec4e64e3d21287461fdf17141ba21b33e9b03016d4375635115b490b143476c0a5e142554
|
|
7
|
+
data.tar.gz: 7878980a0bb69c7038055106a803ee68032840ffb9fb37c684ddc99353797c133133c1485405f8342ae98052d974b7771d2e17258cf1474e27df1b90592a6dcf
|
data/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,20 @@ 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
|
-
## [
|
|
8
|
+
## [0.19.0] - 2026-09-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Show the Cute Framework revision (git commit SHA) being served at startup and on the dashboard, linked to the commit on GitHub
|
|
13
|
+
- Print progress while parsing header files, when running in a terminal
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Updated dependencies, including `mcp` from 0.22.0 to 0.25.0
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `--root` now accepts a Cute Framework project root (as documented) and auto-descends into its `include/` directory; previously this scanned unrelated files and skipped topic indexing entirely
|
|
9
22
|
|
|
10
23
|
## [0.17.2] - 2026-02-10
|
|
11
24
|
|
|
@@ -293,6 +306,7 @@ This version was prepared but never released. Changes rolled into 0.17.2.
|
|
|
293
306
|
- `cf_list_category` - List items by category
|
|
294
307
|
- `cf_get_details` - Get full documentation by name
|
|
295
308
|
|
|
309
|
+
[0.19.0]: https://github.com/pusewicz/cf-mcp/compare/v0.18.0...v0.19.0
|
|
296
310
|
[0.17.2]: https://github.com/pusewicz/cf-mcp/compare/v0.17.0...v0.17.2
|
|
297
311
|
[0.17.1]: https://github.com/pusewicz/cf-mcp/compare/v0.17.0...v0.17.1
|
|
298
312
|
[0.17.0]: https://github.com/pusewicz/cf-mcp/compare/v0.16.2...v0.17.0
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
|
@@ -9,7 +9,7 @@ require "standard/rake"
|
|
|
9
9
|
|
|
10
10
|
desc "Generate Manifest.txt from git ls-files"
|
|
11
11
|
task :manifest do
|
|
12
|
-
ignore_patterns = %w[bin/ Gemfile .gitignore test/ .github/ .standard.yml cf-mcp.gemspec .ruby-version CLAUDE.md AGENTS.md fly.toml Procfile Dockerfile .dockerignore .claude/ .mcp.json]
|
|
12
|
+
ignore_patterns = %w[bin/ Gemfile .gitignore test/ .github/ .standard.yml cf-mcp.gemspec .ruby-version CLAUDE.md AGENTS.md fly.toml Procfile Dockerfile .dockerignore .claude/ .mcp.json .serena/]
|
|
13
13
|
|
|
14
14
|
files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
|
|
15
15
|
ls.readlines("\x0", chomp: true)
|
data/config/puma.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Puma configuration for Fly.io deployment
|
|
2
|
+
# Optimized for low memory usage on shared-cpu-1x (256MB RAM)
|
|
3
|
+
|
|
4
|
+
# Single worker process (no forking) to save memory
|
|
5
|
+
workers 0
|
|
6
|
+
|
|
7
|
+
# Minimal threads for light MCP traffic
|
|
8
|
+
threads 2, 2
|
|
9
|
+
|
|
10
|
+
# Preload application for faster startup and lower memory footprint
|
|
11
|
+
preload_app!
|
|
12
|
+
|
|
13
|
+
# Bind to all interfaces
|
|
14
|
+
bind "tcp://0.0.0.0:#{ENV.fetch("PORT", 8080)}"
|
|
15
|
+
|
|
16
|
+
# Disable stats since we're running a single worker
|
|
17
|
+
activate_control_app false
|
data/exe/cf-mcp
CHANGED
data/lib/cf/mcp/cli.rb
CHANGED
|
@@ -97,8 +97,9 @@ module CF
|
|
|
97
97
|
warn "Indexed #{count} topics from: #{path}" if event == :topics_indexed
|
|
98
98
|
end
|
|
99
99
|
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
100
|
+
warn "Cute Framework revision: #{builder.revision}" if builder.revision
|
|
100
101
|
|
|
101
|
-
server = Server.new(index)
|
|
102
|
+
server = Server.new(index, revision: builder.revision)
|
|
102
103
|
server.run_stdio
|
|
103
104
|
end
|
|
104
105
|
|
data/lib/cf/mcp/downloader.rb
CHANGED
|
@@ -15,6 +15,8 @@ module CF
|
|
|
15
15
|
|
|
16
16
|
class DownloadError < StandardError; end
|
|
17
17
|
|
|
18
|
+
attr_reader :sha
|
|
19
|
+
|
|
18
20
|
def initialize(download_dir: DEFAULT_DOWNLOAD_DIR)
|
|
19
21
|
@download_dir = download_dir
|
|
20
22
|
end
|
|
@@ -30,6 +32,7 @@ module CF
|
|
|
30
32
|
# Check if cache is valid
|
|
31
33
|
stored_sha = read_sha_metadata(sha_file)
|
|
32
34
|
latest_sha = fetch_latest_sha
|
|
35
|
+
@sha = latest_sha
|
|
33
36
|
|
|
34
37
|
if stored_sha && latest_sha && stored_sha == latest_sha
|
|
35
38
|
if File.directory?(include_path) && !Dir.empty?(include_path)
|
data/lib/cf/mcp/index_builder.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
3
5
|
module CF
|
|
4
6
|
module MCP
|
|
5
7
|
class IndexBuilder
|
|
6
8
|
DEFAULT_HEADERS_PATH = File.expand_path("~/Work/GitHub/pusewicz/cute_framework/include")
|
|
7
9
|
|
|
8
|
-
attr_reader :headers_path
|
|
10
|
+
attr_reader :headers_path, :revision
|
|
9
11
|
|
|
10
12
|
def initialize(root: nil, download: false)
|
|
11
13
|
@headers_path = resolve_headers_path(root: root, download: download)
|
|
@@ -41,20 +43,45 @@ module CF
|
|
|
41
43
|
private
|
|
42
44
|
|
|
43
45
|
def resolve_headers_path(root:, download:)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
if root
|
|
47
|
+
@revision = detect_git_revision(root)
|
|
48
|
+
nested_include = File.join(root, "include")
|
|
49
|
+
return File.directory?(nested_include) ? nested_include : root
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if (env_path = ENV["CF_HEADERS_PATH"])
|
|
53
|
+
@revision = detect_git_revision(env_path)
|
|
54
|
+
return env_path
|
|
55
|
+
end
|
|
46
56
|
|
|
47
57
|
if download
|
|
48
58
|
warn "Downloading Cute Framework headers from GitHub..."
|
|
49
59
|
downloader = Downloader.new
|
|
50
60
|
path = downloader.download_and_extract
|
|
61
|
+
@revision = downloader.sha
|
|
51
62
|
warn "Downloaded headers to: #{path}"
|
|
52
63
|
return path
|
|
53
64
|
end
|
|
54
65
|
|
|
66
|
+
@revision = detect_git_revision(DEFAULT_HEADERS_PATH)
|
|
55
67
|
DEFAULT_HEADERS_PATH
|
|
56
68
|
end
|
|
57
69
|
|
|
70
|
+
# Detects the current git commit SHA for a local Cute Framework checkout.
|
|
71
|
+
# `path` may be the repo root or any subdirectory within it (e.g. include/) -
|
|
72
|
+
# git walks up to find the enclosing repository either way.
|
|
73
|
+
def detect_git_revision(path)
|
|
74
|
+
return nil unless File.directory?(path)
|
|
75
|
+
|
|
76
|
+
stdout, _stderr, status = Open3.capture3("git", "-C", path, "rev-parse", "--short", "HEAD")
|
|
77
|
+
return nil unless status.success?
|
|
78
|
+
|
|
79
|
+
sha = stdout.strip
|
|
80
|
+
sha.empty? ? nil : sha
|
|
81
|
+
rescue Errno::ENOENT
|
|
82
|
+
nil
|
|
83
|
+
end
|
|
84
|
+
|
|
58
85
|
def find_topics_path(headers_path)
|
|
59
86
|
# If headers_path is .../cute_framework/include, topics is at .../cute_framework/docs/topics
|
|
60
87
|
base = File.dirname(headers_path)
|
data/lib/cf/mcp/parser.rb
CHANGED
data/lib/cf/mcp/server.rb
CHANGED
|
@@ -5,7 +5,9 @@ require "mcp"
|
|
|
5
5
|
module CF
|
|
6
6
|
module MCP
|
|
7
7
|
class Server
|
|
8
|
-
attr_reader :server, :index
|
|
8
|
+
attr_reader :server, :index, :revision
|
|
9
|
+
|
|
10
|
+
CUTE_FRAMEWORK_COMMIT_URL_TEMPLATE = "https://github.com/RandyGaul/cute_framework/commit/%{revision}"
|
|
9
11
|
|
|
10
12
|
CORS_HEADERS = {
|
|
11
13
|
"access-control-allow-origin" => "*",
|
|
@@ -30,16 +32,18 @@ module CF
|
|
|
30
32
|
warn "Indexed #{count} topics from: #{path}" if event == :topics_indexed
|
|
31
33
|
end
|
|
32
34
|
warn "Indexed #{index.stats[:total]} items (#{index.stats[:functions]} functions, #{index.stats[:structs]} structs, #{index.stats[:enums]} enums)"
|
|
35
|
+
warn "Cute Framework revision: #{builder.revision}" if builder.revision
|
|
33
36
|
|
|
34
|
-
new(index).rack_app
|
|
37
|
+
new(index, revision: builder.revision).rack_app
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
PROTOCOL_VERSION = "2025-03-26"
|
|
38
41
|
WEBSITE_URL = ENV.fetch("FLY_APP_NAME", nil) ? "https://#{ENV["FLY_APP_NAME"]}.fly.dev" : "https://cf-mcp.fly.dev"
|
|
39
42
|
PUBLIC_DIR = File.join(__dir__, "public")
|
|
40
43
|
|
|
41
|
-
def initialize(index)
|
|
44
|
+
def initialize(index, revision: nil)
|
|
42
45
|
@index = index
|
|
46
|
+
@revision = revision
|
|
43
47
|
|
|
44
48
|
configuration = ::MCP::Configuration.new(protocol_version: PROTOCOL_VERSION)
|
|
45
49
|
@server = ::MCP::Server.new(
|
|
@@ -190,6 +194,8 @@ module CF
|
|
|
190
194
|
context = TemplateContext.new(
|
|
191
195
|
version: CF::MCP::VERSION,
|
|
192
196
|
protocol_version: PROTOCOL_VERSION,
|
|
197
|
+
revision: @revision,
|
|
198
|
+
revision_url: @revision && format(CUTE_FRAMEWORK_COMMIT_URL_TEMPLATE, revision: @revision),
|
|
193
199
|
stats: index.stats,
|
|
194
200
|
categories: index.categories.sort,
|
|
195
201
|
topics: index.topics_ordered.map { |t| {name: t.name, brief: t.brief} },
|
|
@@ -213,11 +219,13 @@ module CF
|
|
|
213
219
|
class TemplateContext
|
|
214
220
|
TEMPLATES_DIR = File.join(__dir__, "templates")
|
|
215
221
|
|
|
216
|
-
attr_reader :version, :protocol_version, :stats, :categories, :topics, :tools, :tool_schemas_json
|
|
222
|
+
attr_reader :version, :protocol_version, :revision, :revision_url, :stats, :categories, :topics, :tools, :tool_schemas_json
|
|
217
223
|
|
|
218
|
-
def initialize(version:, protocol_version:, stats:, categories:, topics:, tools:, tool_schemas_json:)
|
|
224
|
+
def initialize(version:, protocol_version:, revision:, revision_url:, stats:, categories:, topics:, tools:, tool_schemas_json:)
|
|
219
225
|
@version = version
|
|
220
226
|
@protocol_version = protocol_version
|
|
227
|
+
@revision = revision
|
|
228
|
+
@revision_url = revision_url
|
|
221
229
|
@stats = stats
|
|
222
230
|
@categories = categories
|
|
223
231
|
@topics = topics
|
|
@@ -55,6 +55,12 @@
|
|
|
55
55
|
<th>Protocol Version</th>
|
|
56
56
|
<td><%= protocol_version %></td>
|
|
57
57
|
</tr>
|
|
58
|
+
<% if revision %>
|
|
59
|
+
<tr>
|
|
60
|
+
<th>Cute Framework Revision</th>
|
|
61
|
+
<td><a href="<%= h(revision_url) %>"><%= h(revision) %></a></td>
|
|
62
|
+
</tr>
|
|
63
|
+
<% end %>
|
|
58
64
|
</table>
|
|
59
65
|
|
|
60
66
|
<h2>Endpoints</h2>
|
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.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Piotr Usewicz
|
|
@@ -9,20 +9,34 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: listen
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.10'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.10'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: mcp
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
15
29
|
requirements:
|
|
16
30
|
- - "~>"
|
|
17
31
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
32
|
+
version: '0.25'
|
|
19
33
|
type: :runtime
|
|
20
34
|
prerelease: false
|
|
21
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
36
|
requirements:
|
|
23
37
|
- - "~>"
|
|
24
38
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0.
|
|
39
|
+
version: '0.25'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: puma
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -85,7 +99,6 @@ email:
|
|
|
85
99
|
- piotr@layer22.com
|
|
86
100
|
executables:
|
|
87
101
|
- cf-mcp
|
|
88
|
-
- cf-mcp-wrapper
|
|
89
102
|
extensions: []
|
|
90
103
|
extra_rdoc_files: []
|
|
91
104
|
files:
|
|
@@ -95,8 +108,8 @@ files:
|
|
|
95
108
|
- README.md
|
|
96
109
|
- Rakefile
|
|
97
110
|
- config.ru
|
|
111
|
+
- config/puma.rb
|
|
98
112
|
- exe/cf-mcp
|
|
99
|
-
- exe/cf-mcp-wrapper
|
|
100
113
|
- lib/cf/mcp.rb
|
|
101
114
|
- lib/cf/mcp/cli.rb
|
|
102
115
|
- lib/cf/mcp/downloader.rb
|
|
@@ -155,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
155
168
|
- !ruby/object:Gem::Version
|
|
156
169
|
version: '0'
|
|
157
170
|
requirements: []
|
|
158
|
-
rubygems_version: 4.0.
|
|
171
|
+
rubygems_version: 4.0.12
|
|
159
172
|
specification_version: 4
|
|
160
173
|
summary: MCP server providing documentation tools for Cute Framework
|
|
161
174
|
test_files: []
|
data/exe/cf-mcp-wrapper
DELETED