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.
23 lines
518 B
Python
23 lines
518 B
Python
"""A stdio MCP server used by test_correlation to check session linking end to end."""
|
|
|
|
from fastmcp import Context, FastMCP
|
|
|
|
from fastmcp_feedback.instrumentation import MemorySink, instrument
|
|
|
|
app = FastMCP("stdio-correlation")
|
|
mw = instrument(app, [MemorySink()])
|
|
|
|
|
|
@app.tool
|
|
def echo(text: str) -> str:
|
|
return text
|
|
|
|
|
|
@app.tool
|
|
async def report(ctx: Context) -> list:
|
|
return [[link.tool, link.rule] for link in await mw.capture_recent_calls(ctx)]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(show_banner=False)
|