Commit Graph
15 Commits
Author SHA1 Message Date
rsp2k 5e9a9ca037 Release 2026.10.01.2: instrumentation imports without the database extras
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / test-postgres (==2.12.2) (push) Canceled after 0s
Tests / test-postgres (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
2026-10-01 20:56:02 -06:00
rsp2k 4922eaecbd Let an explicit success flag win over error keys
A result with ok or success exactly True skips the error-key check, so
{"ok": True, "error": "deprecated arg"} is ok and the string reads as a
warning. A failing status, a False flag and isError still flag it, and
truthy non-bools are not an explicit success.
2026-10-01 18:04:15 -06:00
rsp2k f4aef293a5 Document error_keys, unique event keys, and the call/event join
README: the error-string check, its default and the behavior change on
upgrade; event keys used for joining must be unique across restarts; the
SQLite and Postgres join from calls to events; ids are UUIDs, so order
by occurred_at.
2026-10-01 16:41:54 -06:00
rsp2k ac1d751045 Document backfilling embeddings and list/dict flattening 2026-09-30 11:17:21 -06:00
rsp2k c655949bbb Embed feedback, tool errors, event text and opt-in LLM text for similarity search
EmbeddingSink queues text from each batch on its own bounded queue and
upserts vectors into a new {prefix}embeddings table (pgvector on Postgres,
JSON elsewhere). mw.similar() and mw.similar_feedback() search it.
submit_feedback records a feedback.submitted event; record_llm_call keeps
prompt and completion only with capture_llm_text=True.
2026-09-30 00:22:14 -06:00
rsp2k bf62650e05 Add events: record_event, record_llm_call and an events table
Events are things worth recording that are not tool calls, such as a
background job changing state or an LLM request made by a tool. They go
through the same queue as call records, are redacted the same way, link
to the running tool call when there is one, and can be recorded from any
thread. DatabaseSink writes them to {prefix}events and prunes them with
the same retention; events_for(key) reads them back.
2026-09-29 10:22:05 -06:00
rsp2k 25a1ca5ecd Add per-tool exclusion and sampling, and retention pruning 2026-09-28 22:11:20 -06:00
rsp2k 472071730e Release 2026.09.27.4: soft-error classification
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
2026-09-27 19:34:30 -06:00
rsp2k 052862f4fc Point README examples at the in-repo examples/ directory
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
The showcase repo is private and fastmcp-feedback-showcase was never
published, so both the link and the uvx command failed for everyone else.
Tested the new clone-and-run instructions against the now-public repo.
2026-09-27 12:31:18 -06:00
rsp2k a530634eb9 Release 2026.09.27.3: feedback-to-call correlation
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
Changelog entry and version bump for linking feedback items to the tool
calls that preceded them. README documents the instrumentation parameter
of add_feedback_tools and the new feedback_call_links table that Alembic
hosts need to migrate.
2026-09-27 12:26:00 -06:00
rsp2k 4b16764faa Attribute per-call session ids to the stateless MCP protocol
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
Tested against real clients: a FastMCP 4.0.10 server keeps ctx.session_id
stable for clients that open sessions (curl on 2025-06-18, the FastMCP 3.3
Client, Claude Code over stdio). Claude Code and FastMCP 4's Client speak
MCP 2026-07-28, which has no HTTP sessions, so FastMCP generates an id per
request. Not a FastMCP bug; correct the comments and README note.
2026-09-27 10:01:44 -06:00
rsp2k 58e531019d Add feedback-to-call correlation (unreleased)
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
capture_recent_calls() picks the calls that led up to a feedback item:
same client session first, then the same user within a window, each link
recording which rule matched. It reads an in-memory buffer (so calls still
queued count) and falls back to DatabaseSink for other workers and
restarts. link_feedback() stores links against any feedback id in a
prefixed feedback_call_links table; feedback_context() reads them back.
add_feedback_tools(instrumentation=mw) makes submit_feedback link
automatically and report linked_calls.

session_key() works around FastMCP 4.0 returning a new ctx.session_id on
every call: it prefers the HTTP mcp-session-id header, then one key per
process for stdio, then ctx.session_id.

Also fixes a race where the writer and link_feedback both ran create_all
with create_tables=True.

468 tests pass on FastMCP 2.12.2, 2.14.3, 3.3.1, 3.4.7; 467 + 1 skip on
4.0.10. Still to do before release: execute the new README examples,
CHANGELOG, version bump.
2026-09-27 09:12:10 -06:00
rsp2k 2e1278d81f Add per-call instrumentation middleware
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=3.3,<4) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
InstrumentationMiddleware (and instrument(app)) records every tool call on
a FastMCP server: tool, timing, outcome and original error type, session
and request ids, argument and result sizes, plus identity and enrichment
hook output. Modes off/meta/full; full adds redacted args and results.

Recording can't slow or break a call. Records reach sinks through a
bounded queue drained by a background task and are dropped, counted, when
it fills. Sink and hook failures are logged, never raised, and async hooks
are cut off after hook_timeout.

Redactor strips secrets by key at any depth and by value pattern from
args, results, error text and hook output. DatabaseSink runs on async
SQLAlchemy, takes a host AsyncEngine, writes to a prefixed table and never
creates it unless asked; build_metadata() plugs into Alembic env.py.

Verified on FastMCP 2.12.2, 2.14.3, 3.3.1, 3.4.7 and 4.0.10. CI matrix
gains 3.x. Version 2026.09.27.1.
2026-09-27 08:37:09 -06:00
rsp2k ddf23d10e4 Support FastMCP 4 and fix silent composition failure
Tests / test (==2.12.2) (push) Canceled after 0s
Tests / test (==2.14.3) (push) Canceled after 0s
Tests / test (>=4,<5) (push) Canceled after 0s
Tests / canary (push) Canceled after 0s
compose_feedback_services() called import_server() without awaiting it.
That method became async in FastMCP 2.14, so on the version this package
was built against it composed nothing while logging success. FastMCP 4
removed it outright. Use mount(), which is sync on 2.12 through 4.x.

The test suite could not start (pytest-html hook, plugin not installed),
so nothing caught this. Add pytest-html, bring examples/ over from the docs
repo since the integration tests import them, and fix the tests that had
drifted from the code. 407 tests pass on FastMCP 2.12.2, 2.14.3 and 4.0.10.

- Declare fastmcp>=2.12.2,<5; CI matrix covers each family plus a
  non-blocking canary on the newest FastMCP
- Add a composition test with real servers; the mocked ones could not
  see a missing await
- Rewrite the README against the actual API and execute its examples
- Ignore ruff UP042: StrEnum would change stored enum formatting
- Version 2026.09.27
2026-09-27 06:09:30 -06:00
rsp2k d81fcecb92 feat: Initial release of fastmcp-feedback v2026.01.12
Production-ready feedback collection system for FastMCP servers.

Features:
- One-line integration with add_feedback_tools()
- Modular mixin architecture (SubmissionMixin, RetrievalMixin, ManagementMixin)
- Multi-database support (SQLite, PostgreSQL, MySQL)
- Privacy-compliant analytics with FeedbackInsights
- Server composition with create_feedback_server()
- Full type hints and Pydantic validation
- 97%+ test coverage

Installation:
  uv add fastmcp-feedback

Documentation: https://fastmcp-feedback.l.supported.systems
2026-01-12 11:54:26 -07:00