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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98423800bb5ecaf4605f4ebf9dda9e8a23d0e769d2840d7ea02604ab46b2e82e
4
- data.tar.gz: 89d5e7b80786cec6e6304e1acf9f06e1eff0811f7091f77d776742ded9b515df
3
+ metadata.gz: 8503e2b733dd80a28ab4e44b5435ce8ca334ba25a0bd34a3751c2b986beea8dc
4
+ data.tar.gz: f4b986ddb96f77b7bc97c5b56384b6aaae88ee73f1f030a184409e64c78cd317
5
5
  SHA512:
6
- metadata.gz: c5af9f6e8e234fcf8dd3cd9cb074609bd600df1dd7dfb6884d10b993a22bc29dce1d0ad1b7b88b35ac0635089350004eb4a61718f9231a05d5f9f5755e0ff202
7
- data.tar.gz: 1aeb2b9475763f1d88a53d870f0513696b2855c3edbdab2652ad08a960b7a17fc6768b99c9ae233243ab509285b4726dcf17f562256b9d887a8759ca0e1dbe4a
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
- ## [Unreleased]
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
@@ -4,8 +4,8 @@ Manifest.txt
4
4
  README.md
5
5
  Rakefile
6
6
  config.ru
7
+ config/puma.rb
7
8
  exe/cf-mcp
8
- exe/cf-mcp-wrapper
9
9
  lib/cf/mcp.rb
10
10
  lib/cf/mcp/cli.rb
11
11
  lib/cf/mcp/downloader.rb
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
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
4
  require "cf/mcp"
6
5
 
7
6
  CF::MCP::CLI.new(ARGV).run
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
 
@@ -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)
@@ -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
- return root if root
45
- return ENV["CF_HEADERS_PATH"] if ENV["CF_HEADERS_PATH"]
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
@@ -32,6 +32,7 @@ module CF
32
32
  def parse_directory(path)
33
33
  items = []
34
34
  Dir.glob(File.join(path, "**/*.h")).each do |header_file|
35
+ warn "Parsing #{header_file}" if $stderr.isatty
35
36
  items.concat(parse_file(header_file))
36
37
  end
37
38
  items
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>
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CF
4
4
  module MCP
5
- VERSION = "0.17.2"
5
+ VERSION = "0.19.0"
6
6
  end
7
7
  end
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.17.2
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.6'
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.6'
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.6
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
@@ -1,8 +0,0 @@
1
- #!/bin/bash
2
- source /opt/homebrew/share/chruby/chruby.sh
3
-
4
- PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
5
- chruby "$(cat "$PROJECT_DIR/.ruby-version")"
6
-
7
- export BUNDLE_GEMFILE="$PROJECT_DIR/Gemfile"
8
- exec "$PROJECT_DIR/exe/cf-mcp" "$@"