talk_to_your_app 0.1.0.pre.3 → 0.1.0.pre.7
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 +205 -0
- data/LOCAL_DEVELOPMENT.md +9 -9
- data/README.md +157 -43
- data/SECURITY.md +69 -0
- data/docs/plugin_authoring.md +22 -11
- data/docs/read_only_connections.md +51 -25
- data/lib/generators/talk_to_your_app/custom_tool/custom_tool_generator.rb +4 -3
- data/lib/generators/talk_to_your_app/install/templates/initializer.rb.tt +73 -21
- data/lib/talk_to_your_app/audit_logger.rb +22 -0
- data/lib/talk_to_your_app/auth/middleware.rb +48 -26
- data/lib/talk_to_your_app/configuration.rb +66 -15
- data/lib/talk_to_your_app/connection_registry.rb +8 -4
- data/lib/talk_to_your_app/current.rb +6 -0
- data/lib/talk_to_your_app/plugin.rb +27 -10
- data/lib/talk_to_your_app/plugin_registry.rb +13 -0
- data/lib/talk_to_your_app/plugins/cache/plugin.rb +32 -0
- data/lib/talk_to_your_app/plugins/db/plugin.rb +42 -16
- data/lib/talk_to_your_app/plugins/db/tools/query.rb +17 -13
- data/lib/talk_to_your_app/plugins/db/tools/schema.rb +0 -3
- data/lib/talk_to_your_app/plugins/db/tools/tables.rb +4 -6
- data/lib/talk_to_your_app/plugins/flipper/plugin.rb +21 -3
- data/lib/talk_to_your_app/plugins/flipper/tools/disable_flag.rb +0 -1
- data/lib/talk_to_your_app/plugins/flipper/tools/enable_flag.rb +0 -1
- data/lib/talk_to_your_app/plugins/flipper/tools/enabled_flags.rb +0 -1
- data/lib/talk_to_your_app/plugins/flipper/tools/list_flags.rb +0 -1
- data/lib/talk_to_your_app/plugins/flipper/tools/read_flag.rb +0 -1
- data/lib/talk_to_your_app/plugins/jobs/plugin.rb +53 -28
- data/lib/talk_to_your_app/plugins/jobs/tools/base.rb +28 -0
- data/lib/talk_to_your_app/plugins/jobs/tools/failed_jobs.rb +3 -4
- data/lib/talk_to_your_app/plugins/jobs/tools/queue_sizes.rb +4 -4
- data/lib/talk_to_your_app/plugins/jobs/tools/rate_metrics.rb +3 -4
- data/lib/talk_to_your_app/plugins/jobs/tools/recent_jobs.rb +3 -4
- data/lib/talk_to_your_app/railtie.rb +24 -2
- data/lib/talk_to_your_app/tool.rb +68 -16
- data/lib/talk_to_your_app/transport/rails_mount.rb +26 -2
- data/lib/talk_to_your_app/version.rb +1 -1
- data/lib/talk_to_your_app.rb +27 -5
- metadata +22 -21
- data/docs/brainstorms/talk-to-your-app-gem-v1-requirements.md +0 -158
- data/docs/plans/2026-06-01-001-feat-talk-to-your-app-gem-v1-plan.md +0 -772
- data/docs/residual-review-findings/fd33390.md +0 -19
- data/docs/solutions/architecture-patterns/mcp-ruby-sdk-rails-integration-2026-06-01.md +0 -180
- data/docs/solutions/runtime-errors/sidekiq-adapter-requires-sidekiq-api-2026-06-16.md +0 -76
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d542357394a3ba10a68718a8dfb95eecfe61b51db60270afecbf5a5aa1853a48
|
|
4
|
+
data.tar.gz: 05e68c877cf7373494dffe68bf36948c502eba9eb89a412606edef85b446db5c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a02972f0943500d9c32261b9ec9b38a7c043212e8e5b880b7e3da2a8be4a0a038f4afa4975d348559d62cd9f9bb295d738ae22c09d15ffda135b44db3dff71f
|
|
7
|
+
data.tar.gz: fc4769d02c766c515f0b27761ad665a2c80be4e0344eb664460bbcf4560dc3704d379a711c4a244e5760c966cff56efb2b334401b9c1ed5a34facd29b73d8557
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org). Pre-1.0 minor releases may include
|
|
5
|
+
breaking changes.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Failed authentication is now logged. Every rejected request emits one `WARN`
|
|
11
|
+
line and a `talk_to_your_app.auth_failure` notification carrying `reason`
|
|
12
|
+
(`missing_credentials`, `unsupported_scheme`, `invalid_credentials`,
|
|
13
|
+
`validator_error`), `scheme`, `ip`, and `error_class` when a validator raised.
|
|
14
|
+
Previously a `401` left no trace at all, so credential guessing and endpoint
|
|
15
|
+
scanning were undetectable while every *successful* call was audit-logged. No
|
|
16
|
+
credential material is logged, and an unrecognized scheme is reported as
|
|
17
|
+
`other` so a crafted `Authorization` header cannot forge log fields. The level
|
|
18
|
+
is fixed at `:warn` rather than following `config.log_level`.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- A raising `basic_auth` callable is now reported through the configured audit
|
|
22
|
+
logger (as `reason=validator_error`) instead of `Kernel#warn`, so it reaches
|
|
23
|
+
the same sink as the rest of the audit trail. The request outcome is unchanged
|
|
24
|
+
(`401`, never a `500`).
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- `require "talk_to_your_app"` raised `NameError: uninitialized constant
|
|
28
|
+
ActiveSupport::CodeGenerator` anywhere ActiveSupport had not already been fully
|
|
29
|
+
loaded — a plain script, a non-Rails Rack process, or any Gemfile that reaches
|
|
30
|
+
this gem before `rails`. `current.rb` required
|
|
31
|
+
`active_support/current_attributes` without `active_support` itself, and every
|
|
32
|
+
Rails boot hid it. Now covered by a test that loads the gem in a fresh
|
|
33
|
+
subprocess, which is the only way to catch a load-order bug the suite's own
|
|
34
|
+
Rails boot papers over.
|
|
35
|
+
- Boot now rejects a **blank API key value**. `config.api_keys = { "x" =>
|
|
36
|
+
ENV["TTYA_KEY"] }` with the variable unset previously booted clean —
|
|
37
|
+
`auth_configured?` counted the entry, but a blank key can never authenticate,
|
|
38
|
+
so the endpoint returned `401` to every request with no signal that anything
|
|
39
|
+
was wrong. The error names the offending key(s) and never echoes a valid one.
|
|
40
|
+
|
|
41
|
+
### Fixed (docs)
|
|
42
|
+
- `SECURITY.md` now lists rate limiting, alerting on rejected requests,
|
|
43
|
+
and `X-Forwarded-For` IP trust in the operator checklist, and names rate
|
|
44
|
+
limiting plus query-driven resource exhaustion as operator-owned in the threat
|
|
45
|
+
model. The README documents the auth-failure line and notes that `max_rows`
|
|
46
|
+
bounds the response, not process memory — the full result set is fetched
|
|
47
|
+
before truncation.
|
|
48
|
+
|
|
49
|
+
## [0.1.0.pre.7] - 2026-07-24
|
|
50
|
+
|
|
51
|
+
### Removed
|
|
52
|
+
- The boot-time `no config.authorize configured` warning, and
|
|
53
|
+
`Configuration#authorize_configured?` along with it. It fired on every boot of
|
|
54
|
+
a deployment that deliberately grants every principal every tool, and could
|
|
55
|
+
not tell that choice apart from an oversight. The behavior it warned about is
|
|
56
|
+
unchanged and still documented in the README security model, the `SECURITY.md`
|
|
57
|
+
operator checklist, and the generated initializer. The writable-DB-connection
|
|
58
|
+
boot warning is unaffected.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
- Docs: `rails g talk_to_your_app:custom_tool`'s next-steps output and the
|
|
62
|
+
README "Writing your own plugin" example both told operators to enable a
|
|
63
|
+
plugin without `connection:`, which boot rejects. Both now show
|
|
64
|
+
`connection: false`.
|
|
65
|
+
- README's demo poster and video use absolute URLs, so they resolve wherever the
|
|
66
|
+
README is rendered (the files ship in the repo, not in the gem).
|
|
67
|
+
|
|
68
|
+
## [0.1.0.pre.6] - 2026-07-20
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
- Boot-time warnings (`no config.authorize configured`, writable DB connection)
|
|
72
|
+
now go to `$stderr` (`Kernel#warn`) instead of the configured logger. The
|
|
73
|
+
configured logger may write to `$stdout`, and boot output on `$stdout` can be
|
|
74
|
+
captured by scripts (e.g. building `DATABASE_URL` from `rails runner`), which
|
|
75
|
+
corrupted the captured value. Warnings never touch `$stdout` at boot now.
|
|
76
|
+
|
|
77
|
+
## [0.1.0.pre.5] - 2026-07-18
|
|
78
|
+
|
|
79
|
+
Requires Ruby >= 3.3 and Rails >= 7.2 (the tested CI matrix: Ruby 3.3/4.0 ×
|
|
80
|
+
Rails 7.2/8.0/8.1); the `mcp` SDK is pinned `~> 0.25.0`.
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
- Cache plugin: `config.plugin :cache, connection: false` exposes `cache.clear`
|
|
84
|
+
(`Rails.cache.clear`). Destructive (drops every cached entry) — scope it to
|
|
85
|
+
trusted principals with `config.authorize`.
|
|
86
|
+
- `config.authorize` now receives the tool's arguments as a third parameter:
|
|
87
|
+
`{ |principal, tool_name, args| ... }` (symbol keys, before defaults are
|
|
88
|
+
applied). Enables per-flag/per-task/per-table authorization. Two-parameter
|
|
89
|
+
blocks keep working (Ruby blocks ignore extra arguments); an explicit lambda
|
|
90
|
+
passed via `authorize(&my_lambda)` must accept all three.
|
|
91
|
+
- Boot warns (does not fail) when plugins are enabled without `config.authorize`
|
|
92
|
+
— every authenticated principal can otherwise call every enabled tool.
|
|
93
|
+
- `SECURITY.md` with private reporting instructions and an operator misconfiguration
|
|
94
|
+
checklist. Packaged in the gem; linked from the README security model.
|
|
95
|
+
- `config.allowed_hosts` (default `[]`). Extra `Host` header values accepted by
|
|
96
|
+
the transport's DNS-rebinding protection, beyond the loopback defaults
|
|
97
|
+
(`127.0.0.1`, `::1`, `localhost`). Required for any non-loopback deployment
|
|
98
|
+
(endpoint served from a real domain) — without it the transport rejects every
|
|
99
|
+
request with "Forbidden: Invalid Host header". Forwarded to the mcp SDK's
|
|
100
|
+
`StreamableHTTPTransport(allowed_hosts:)`. The generated initializer defaults
|
|
101
|
+
it to `TalkToYourApp.rails_hosts` — the host app's own `config.hosts` (literal
|
|
102
|
+
host strings only; regexp/IPAddr/dotted-wildcard entries are skipped).
|
|
103
|
+
- `config.enabled` (default true). A global on/off switch: when false the
|
|
104
|
+
mounted endpoint serves `503` and boot validation is skipped, so an operator
|
|
105
|
+
can ship the initializer and disable it per-environment without the gem
|
|
106
|
+
refusing to boot on otherwise-incomplete configuration.
|
|
107
|
+
- Opt-in DB writes: wiring a `role: :writing` connection into the DB plugin
|
|
108
|
+
(`config.plugin :db, connection: :writer`) lets `db.query` execute writes. It
|
|
109
|
+
is read-only on a `:reading` connection (the default) and logs a loud warning
|
|
110
|
+
at boot on a writable one. `config.authorize` cannot distinguish reads from
|
|
111
|
+
writes, and full SQL is written to the audit log — scope the DB user and log
|
|
112
|
+
sinks accordingly (see the README).
|
|
113
|
+
- `config.stateless` (default false). When true the Streamable HTTP transport
|
|
114
|
+
runs stateless — every request is self-contained with no per-session state in
|
|
115
|
+
the transport — so any worker or replica can serve any request. Set it when
|
|
116
|
+
the host app runs more than one Puma/Unicorn worker, where a follow-up request
|
|
117
|
+
can otherwise land on a process that never saw `initialize` and fail with
|
|
118
|
+
"Session not found". Stateless mode does not support SSE streaming or
|
|
119
|
+
server-initiated notifications.
|
|
120
|
+
- `app/talk_to_your_app/` convention directory: custom tools live in
|
|
121
|
+
`custom_tools/` (one `TalkToYourApp::Tool` subclass per file, loaded by
|
|
122
|
+
`:custom_tools`). The gem ignores the tree in Zeitwerk and requires the files
|
|
123
|
+
itself. The custom-tool generator writes here.
|
|
124
|
+
- `rails g talk_to_your_app:custom_tool NAME` generator — scaffolds a
|
|
125
|
+
`TalkToYourApp::Tool` subclass in `app/talk_to_your_app/custom_tools/`,
|
|
126
|
+
exposed as `custom.<name>`.
|
|
127
|
+
- Rake plugin per-task timeout: `config.plugin :rake, allowed: [...], timeout: 60`
|
|
128
|
+
(seconds, default 20). A task exceeding it is hard-killed (process group) and
|
|
129
|
+
returned as a tool error, so a hung task can't pin the web thread.
|
|
130
|
+
- `Tool::Context#ip` exposes the request IP (from `Current.ip`), completing
|
|
131
|
+
parity with `#principal` and `#session_id` for custom tools.
|
|
132
|
+
- Per-principal tool authorization: `config.authorize { |principal, tool_name| ... }`.
|
|
133
|
+
- DB plugin statement timeout on MySQL (`max_execution_time`) in addition to
|
|
134
|
+
PostgreSQL. SQLite and MariaDB have no per-statement timeout (the read-only
|
|
135
|
+
role still applies).
|
|
136
|
+
- Flipper plugin: enable/disable across actor, group, and percentage
|
|
137
|
+
(`percentage_of_actors` / `percentage_of_time`) gates, plus a
|
|
138
|
+
`flipper.enabled_flags` tool that lists active flags with their gates and
|
|
139
|
+
last-change timestamps.
|
|
140
|
+
|
|
141
|
+
### Changed
|
|
142
|
+
- **BREAKING — minimum `mcp` SDK raised to `~> 0.25.0`.** 0.23 added `Host`-header
|
|
143
|
+
DNS-rebinding protection (`allowed_hosts:`); 0.24/0.25 add transport fixes
|
|
144
|
+
(SSE write synchronization, header normalization) with no further breaking
|
|
145
|
+
changes to this gem's SDK touch points. Earlier SDK versions reject
|
|
146
|
+
`allowed_hosts:` at boot.
|
|
147
|
+
- `config.allowed_origins` now works: it is forwarded to the mcp SDK transport,
|
|
148
|
+
which owns Origin validation (same-origin allowed, case-insensitive matching,
|
|
149
|
+
no-Origin non-browser clients allowed). Previously the gem's own middleware
|
|
150
|
+
rejected every cross-origin request regardless of the setting — the gem-side
|
|
151
|
+
check is removed in favor of the SDK's.
|
|
152
|
+
- Connections use `with_connection` inside `connected_to` (with explicit
|
|
153
|
+
`prevent_writes:` from the connection spec) so checkouts return to the pool
|
|
154
|
+
when the tool block ends.
|
|
155
|
+
- `401` `WWW-Authenticate` lists only the configured schemes (`Bearer`, `Basic`,
|
|
156
|
+
or both) instead of always advertising Bearer.
|
|
157
|
+
- Install generator: sets `config.stateless = true` in production; stronger
|
|
158
|
+
production comments for `enabled`, `authorize`, and the security checklist.
|
|
159
|
+
- Gem package includes `CHANGELOG.md` and `SECURITY.md`; ships only operator
|
|
160
|
+
docs (`docs/read_only_connections.md`, `docs/plugin_authoring.md`) rather than
|
|
161
|
+
internal plans/brainstorms.
|
|
162
|
+
- README security model updated for opt-in writable DB and the authorize warning.
|
|
163
|
+
- **BREAKING — the `:jobs` plugin is split into `:sidekiq` and `:solid_queue`.**
|
|
164
|
+
Enable the backend you run (or both, e.g. mid-migration):
|
|
165
|
+
`config.plugin :sidekiq, connection: false`. The `adapter:` option is gone.
|
|
166
|
+
Tools are now adapter-namespaced — `sidekiq.queue_sizes` / `solid_queue.queue_sizes`
|
|
167
|
+
(etc.) instead of `jobs.queue_sizes` — so both backends can be exposed at once.
|
|
168
|
+
- **BREAKING — every plugin must declare `connection:`.** Pass a declared
|
|
169
|
+
connection name, or `connection: false` to opt out (`:sidekiq`, `:solid_queue`,
|
|
170
|
+
`:rake`, and connection-less `:custom_tools` use `false`). Enabling any plugin
|
|
171
|
+
without the option fails at boot. `:db` and `:flipper` require a real
|
|
172
|
+
connection (`connection: false` is rejected).
|
|
173
|
+
- **BREAKING — connections are wired into plugins by name.** Plugins no longer
|
|
174
|
+
hardcode a connection name; you declare connections and wire one into each
|
|
175
|
+
plugin that needs a database: `config.plugin :db, connection: :readonly` and
|
|
176
|
+
`config.plugin :flipper, connection: :writer`. Enabling `:db` or `:flipper`
|
|
177
|
+
without `connection:` now fails at boot with an actionable error. The per-tool
|
|
178
|
+
hardcoded connection names were removed. `config.connection`'s `role:` now
|
|
179
|
+
defaults to `:reading`. **Existing initializers must add `connection:` to
|
|
180
|
+
`config.plugin :db`/`:flipper`.** **Plugin authors:** the `requires_connection`
|
|
181
|
+
DSL and the `Plugin.required_connections` alias are removed entirely — the
|
|
182
|
+
framework now enforces `connection:` universally (see above), so plugins no
|
|
183
|
+
longer mark themselves. `Tool::Context#connection_name` is now a no-arg reader
|
|
184
|
+
(it reports the connection the call ran on); pass an explicit override to
|
|
185
|
+
`ctx.connection(:name)`, not to `connection_name`. Connection resolution is
|
|
186
|
+
most-specific-first: an explicit `ctx.connection(:name)` arg, then the tool's
|
|
187
|
+
own static `connection` DSL, then the plugin-wired `connection:` default. A
|
|
188
|
+
tool that declares its own connection is no longer overridden by the
|
|
189
|
+
plugin-wired one (custom tools), and a tool's declared connection is now
|
|
190
|
+
validated at boot, not at first call.
|
|
191
|
+
- **BREAKING — Flipper enforces `role: :writing` at boot.** A Flipper connection
|
|
192
|
+
declared `role: :reading` previously booted and failed only on the first write;
|
|
193
|
+
it now fails closed at boot.
|
|
194
|
+
- **Jobs adapter contract:** the `required_gem` hash key was renamed from
|
|
195
|
+
`name:` to `gem_name:` (e.g. `{ const: "Sidekiq", gem_name: "sidekiq" }`),
|
|
196
|
+
matching the Plugin DSL's `requires_gem` option. **Third-party jobs adapters
|
|
197
|
+
must update their `REQUIRED_GEM`/`required_gem` to use `gem_name:`** — with the
|
|
198
|
+
old `name:` key the boot-time gem check still runs but its error message shows
|
|
199
|
+
a blank gem name.
|
|
200
|
+
- **Jobs adapter response shape:** `enqueued_at` is now an ISO-8601 string
|
|
201
|
+
across all adapters, and every job hash carries the same keys (`jid`, `class`,
|
|
202
|
+
`queue`, `args`, `enqueued_at`, `error_message`), with `error_message` nil for
|
|
203
|
+
jobs that have not failed.
|
|
204
|
+
- **Flipper enable/disable response shape:** now `{ name, enabled, gate_type,
|
|
205
|
+
gates }` (previously `{ name, enabled, actor }`), consistent with `read_flag`.
|
data/LOCAL_DEVELOPMENT.md
CHANGED
|
@@ -4,11 +4,11 @@ How to work on the `talk_to_your_app` gem and run its test suite.
|
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
7
|
-
- **Ruby** >= 3.
|
|
7
|
+
- **Ruby** >= 3.3 (CI runs 3.3 and 4.0).
|
|
8
8
|
- **Bundler** (`gem install bundler`).
|
|
9
9
|
- **SQLite** — the default test database; the `sqlite3` gem is bundled, no server needed.
|
|
10
10
|
- **PostgreSQL** — _optional_ for the test suite (DB-plugin read-only-role and timeout tests skip without it) but **required to run the dummy app as a local MCP server** (see below). A running server on `localhost:5432` reachable as the `postgres` superuser (DBngin, Postgres.app, Homebrew, or Docker all work).
|
|
11
|
-
- **Redis** _(optional)_ — exercises the
|
|
11
|
+
- **Redis** _(optional)_ — exercises the Sidekiq plugin. A running server on `localhost:6379`.
|
|
12
12
|
|
|
13
13
|
Tests that need PostgreSQL or Redis **skip cleanly** when the service is not reachable, so `bundle exec rake test` always runs; you just get fewer assertions without the services.
|
|
14
14
|
|
|
@@ -52,7 +52,7 @@ bundle exec rake test TEST=test/talk_to_your_app/configuration_test.rb TESTOPTS=
|
|
|
52
52
|
|
|
53
53
|
## Testing against multiple Rails versions
|
|
54
54
|
|
|
55
|
-
The gem supports Rails 7.
|
|
55
|
+
The gem supports Rails 7.2, 8.0, and 8.1 via [Appraisal](https://github.com/thoughtbot/appraisal). The version matrix lives in `Appraisals`.
|
|
56
56
|
|
|
57
57
|
```sh
|
|
58
58
|
# Generate/install the per-version gemfiles under gemfiles/ (needs network)
|
|
@@ -117,11 +117,11 @@ The MCP endpoint is now at **`http://localhost:3000/mcp`**.
|
|
|
117
117
|
that user's name. (Restart the server after seeding new users so their
|
|
118
118
|
tokens are picked up.)
|
|
119
119
|
- **Root page:** `http://localhost:3000/` shows DB stats and the per-user tokens.
|
|
120
|
-
- **Plugins enabled:** DB, **
|
|
120
|
+
- **Plugins enabled:** DB, **Solid Queue**, **Flipper**, and **Rake** (allow-listed tasks `demo:stats`, `demo:echo`).
|
|
121
121
|
- **Tools available:** `db.query` (read-only SQL over `users` / `posts` /
|
|
122
122
|
`comments` / `widgets`), `db.tables`, `db.schema` (columns/indexes/FKs);
|
|
123
|
-
`
|
|
124
|
-
`
|
|
123
|
+
`solid_queue.queue_sizes` / `solid_queue.recent_jobs` /
|
|
124
|
+
`solid_queue.failed_jobs` / `solid_queue.rate_metrics`; `flipper.list_flags` /
|
|
125
125
|
`read_flag` / `enable_flag` / `disable_flag` / `enabled_flags`; `rake.run`
|
|
126
126
|
(allow-listed `demo:stats` and `demo:echo[message]`); and custom tools
|
|
127
127
|
`custom.make_admin` / `custom.toggle_active` (which write user state).
|
|
@@ -142,7 +142,7 @@ cd test/dummy
|
|
|
142
142
|
RAILS_ENV=development bundle exec ruby bin/jobs
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
Watch the queue with the `
|
|
145
|
+
Watch the queue with the `solid_queue.*` MCP tools (or `bin/rails console`).
|
|
146
146
|
|
|
147
147
|
### 3. Connect Claude Code
|
|
148
148
|
|
|
@@ -257,7 +257,7 @@ lib/talk_to_your_app/ # the gem
|
|
|
257
257
|
auth/ # Bearer/Basic middleware + validators
|
|
258
258
|
transport/rails_mount.rb # builds the MCP::Server + Rack app
|
|
259
259
|
audit_logger.rb # one log line per tool call
|
|
260
|
-
plugins/ # db, jobs, flipper, rake, custom_tools
|
|
260
|
+
plugins/ # db, jobs (sidekiq + solid_queue), flipper, rake, custom_tools
|
|
261
261
|
lib/generators/talk_to_your_app/ # install, custom_tool generators
|
|
262
262
|
test/
|
|
263
263
|
dummy/ # minimal Rails app for integration tests
|
|
@@ -281,4 +281,4 @@ Writing a plugin uses the same public DSL as the bundled ones — see
|
|
|
281
281
|
`test/support/mcp_driver.rb` (the `initialize` handshake → `tools/list` →
|
|
282
282
|
`tools/call`).
|
|
283
283
|
- Keep SDK touch points isolated to `transport/rails_mount.rb` and tool
|
|
284
|
-
compilation; the `mcp` gem is pinned `~> 0.
|
|
284
|
+
compilation; the `mcp` gem is pinned `~> 0.25.0` (see the README upgrade note).
|